Source code for zsl.interface.web.performers.resource

"""
:mod:`zsl.interface.webservice.performers.resource`
---------------------------------------------------
"""
import json
import logging

from flask import Response, request

from zsl import Zsl, inject
from zsl.application.error_handler import error_handler
from zsl.constants import MimeType
from zsl.db.model import AppModelJSONEncoder
from zsl.interface.resource import ResourceResult
from zsl.interface.web.utils.execution import convert_to_web_response, notify_responders
from zsl.interface.web.utils.response_headers import append_headers
from zsl.task.job_context import WebJobContext
from zsl.utils.request_helper import args_to_dict
from zsl.utils.resource_helper import get_resource_task, parse_resource_path


[docs] @inject(app=Zsl) def create_resource_mapping(app): @app.route("/resource/<path:path>", methods=['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS']) @append_headers @notify_responders @convert_to_web_response @error_handler def perform_resource(path): logging.debug("Getting resource %s.", path) WebJobContext(path, None, None, None, request) if request.method == 'OPTIONS': response = app.make_default_options_response() else: (resource, params) = parse_resource_path(path) resource_task = get_resource_task(resource) if resource_task is None: raise ImportError("No resource named '{0}'.".format(resource)) msg_format = "Fetched resource named '{0}' with data\n{1}." logging.debug(msg_format.format(resource, request.data)) data = request.get_json() if request.data else None resource_result = resource_task(params=params, args=args_to_dict(request.args), data=data) if not isinstance(resource_result, ResourceResult): resource_result = ResourceResult(body=resource_result) response = Response( json.dumps(resource_result.body, cls=AppModelJSONEncoder), mimetype=MimeType.APPLICATION_JSON.value) if resource_result.status: response.status = str(resource_result.status) if resource_result.location: response.location = resource_result.location if resource_result.count is not None: response.headers['X-Total-Count'] = resource_result.count if resource_result.links: response.headers['Links'] = ', '.join( ['<{url}>; rel="{name}"'.format(url=url, name=name) for name, url in resource_result.links.items()] ) return response