Source code for arrested.endpoint

import json
from werkzeug.wrappers import Response

from itertools import chain

from flask import Response, abort, request, current_app
from flask.views import MethodView

from .handlers import ResponseHandler, RequestHandler


[docs]class Endpoint(MethodView): """The Endpoint class represents the HTTP methods that can be called against an Endpoint inside of a particular resource. """ #: list containing the permitted HTTP methods this endpoint accepts methods = ["GET", "POST", "PUT", "PATCH", "DELETE"] #: The name used to register this endpoint with Flask's url_map name = None #: A :class:`.ResponseHandler` class response_handler = ResponseHandler #: A :class:`.RequestHandler` class request_handler = RequestHandler #: The URL this endpoint is mapped against. This will build on top of any url_prefix #: defined at the API and Resource level url = '' #: A list of functions called before any specific request handler methods are called before_all_hooks = [] #: A list of functions called before GET requests are dispatched before_get_hooks = [] #: A list of functions called after GET requests are dispatched after_get_hooks = [] #: A list of functions called before POST requests are dispatched before_post_hooks = [] #: A list of functions called after POST requests are dispatched after_post_hooks = [] #: A list of functions called before PUT requests are dispatched before_put_hooks = [] #: A list of functions called after PUT requests are dispatched after_put_hooks = [] #: A list of functions called before PATCH requests are dispatched before_patch_hooks = [] #: A list of functions called after PATCH requests are dispatched after_patch_hooks = [] #: A list of functions called before DELETE requests are dispatched before_delete_hooks = [] #: A list of functions called after DELETE requests are dispatched after_delete_hooks = [] #: A list of functions called after all requests are dispatched after_all_hooks = []
[docs] def dispatch_request(self, *args, **kwargs): """Dispatch the incoming HTTP request to the appropriate handler. """ self.args = args self.kwargs = kwargs meth = request.method.lower() if request.method not in self.methods: self.return_error(405) resource = current_app.blueprints.get(request.blueprint, None) if resource: for hook in chain(resource.api.before_all_hooks, resource.before_all_hooks): hook(self) before_hooks = getattr(self, 'before_{method}_hooks'.format(method=meth)) for hook in before_hooks: hook(self) resp = super(Endpoint, self).dispatch_request(*args, **kwargs) resp = self.make_response(resp) after_hooks = getattr(self, 'after_{method}_hooks'.format(method=meth)) for hook in after_hooks: resp = hook(self, resp) if resource: for hook in chain(resource.after_all_hooks, resource.api.after_all_hooks): resp = hook(self, resp) return resp
[docs] @classmethod def get_name(cls): """Returns the user provided name or the lower() class name for use when registering the Endpoint with a :class:`Resource`. :returns: registration name for this Endpoint. :rtype: string """ return cls.name or cls.__name__.lower()
[docs] def make_response(self, rv, status=200, headers=None, mime='application/json'): """Create a response object using the :class:`flask.Response` class. :param rv: Response value. If the value is not an instance of :class:`werkzeug.wrappers.Response` it will be converted into a Response object. :param status: specify the HTTP status code for this response. :param mime: Specify the mimetype for this request. :param headers: Specify dict of headers for the response. """ if not isinstance(rv, Response): resp = Response( response=rv, headers=headers, mimetype=mime, status=status ) else: resp = rv return resp
[docs] def get_response_handler_params(self, **params): """Return a dictionary of options that are passed to the specified :class:`ResponseHandler`. :returns: Dictionary of :class:`ResponseHandler` config options. :rtype: dict """ return params
[docs] def get_response_handler(self): """Return the Endpoints defined :attr:`Endpoint.response_handler`. :returns: A instance of the Endpoint specified :class:`ResonseHandler`. :rtype: :class:`ResponseHandler` """ assert self.response_handler is not None, \ 'Please define a response_handler ' \ ' for Endpoint: %s' % self.__class__.__name__ return self.response_handler(self, **self.get_response_handler_params())
[docs] def get_request_handler_params(self, **params): """Return a dictionary of options that are passed to the specified :class:`RequestHandler`. :returns: Dictionary of :class:`RequestHandler` config options. :rtype: dict """ return params
[docs] def get_request_handler(self): """Return the Endpoints defined :attr:`Endpoint.request_handler`. :returns: A instance of the Endpoint specified :class:`RequestHandler`. :rtype: :class:`RequestHandler` """ assert self.request_handler is not None, \ 'Please define a request_handler ' \ ' for Endpoint: %s' % self.__class__.__name__ return self.request_handler(self, **self.get_request_handler_params())
[docs] def return_error(self, status, payload=None): """Error handler called by request handlers when an error occurs and the request should be aborted. Usage:: def handle_post_request(self, *args, **kwargs): self.request_handler = self.get_request_handler() try: self.request_handler.process(self.get_data()) except SomeException as e: self.return_error(400, payload=self.request_handler.errors) return self.return_create_response() """ resp = None if payload is not None: payload = json.dumps(payload) resp = self.make_response(payload, status=status) if status in [405]: abort(status) else: abort(status, response=resp)
[docs] def get(self, *args, **kwargs): """Handle Incoming GET requests and dispatch to handle_get_request method. """ return self.handle_get_request()
[docs] def post(self, *args, **kwargs): """Handle Incoming POST requests and dispatch to handle_post_request method. """ return self.handle_post_request()
[docs] def put(self, *args, **kwargs): """Handle Incoming PUT requests and dispatch to handle_put_request method. """ return self.handle_put_request()
[docs] def patch(self, *args, **kwargs): """Handle Incoming PATCH requests and dispatch to handle_patch_request method. """ return self.handle_patch_request()
[docs] def delete(self, *args, **kwargs): """Handle Incoming DELETE requests and dispatch to handle_delete_request method. """ return self.handle_delete_request()