Source code for kuha_oai_pmh_repo_handler.http_api

"""Declare HTTP API

This module is responsible for interpreting the HTTP request
parameters and headers. All OAI-PMH specific parameters are
interpreted in controller logic. The controller must be linked to HTTP
API via Tornado WebApplication initialization (see get_app()) and is
used in OAIRouteHandler via self.application.settings['controller'].
"""
import logging
import os.path
from urllib.parse import unquote
from kuha_common.server import (
    RequestHandler,
    WebApplication,
    str_api_endpoint
)


_logger = logging.getLogger(__name__)


[docs]class OAIRouteHandler(RequestHandler): """Declares the OAI-PMH HTTP API. Takes in HTTP verbs GET and POST. Gathers their parameters and dispatches the parameters, correlation_id HTTP headers and a tornado request object to the controller. Dispatching requests to controller ---------------------------------- The dispatch is done by calling the controller's oai_request async method with parameters: args, correlation_id_header, tornado_request * args is a list of two-tuples containing request parameters that were submitted via GET or POST. * correlation_id_header is a dictionary that can be used as is for further requests using Tornado's HTTP clients: {'X-REQUEST-ID': <corr_id>}. * tornado_request is a tornado request object that wraps the current request. It should be used as a read-only object. """ @property def _ctrl(self): return self.application.settings['controller']
[docs] async def prepare(self): """Prepare response by settings the correct output content type. """ await super().prepare() self.oai_protocol = None self.set_output_content_type(self.CONTENT_TYPE_XML)
[docs] async def write_output(self, iterable): """Write output by iterating the parameter. :param iterable: output to be written as HTTP response. """ for data in iterable: self.write(data)
async def _dispatch(self, args): iterable, self.oai_protocol = await self._ctrl.oai_request( args, self._correlation_id.as_header(), self.request) await self.write_output(iterable)
[docs] async def get(self): """HTTP-GET handler Gathers request arguments. Calls dispatch. Finishes the response. "URLs for GET requests have keyword arguments appended to the base URL" -- http://www.openarchives.org/OAI/openarchivesprotocol.html#ProtocolFeatures """ args = [] for key, values in self.request.arguments.items(): for value in values: arg_value = value.decode('utf-8') args.append((key, unquote(arg_value))) await self._dispatch(args) self.finish()
[docs] async def post(self): """HTTP-POST handler Validates request content type. Gathers request arguments. Calls dispatch. Finishes the response. "Keyword arguments are carried in the message body of the HTTP POST. The Content-Type of the request must be application/x-www-form-urlencoded." -- http://www.openarchives.org/OAI/openarchivesprotocol.html#ProtocolFeatures """ self.assert_request_content_type('application/x-www-form-urlencoded') args = [] _body = self.request.body.decode('utf-8') for submitted_arg in _body.split('&'): if not submitted_arg: continue key = submitted_arg.split('=')[0] value = self.get_body_argument(key) args.append((key, unquote(value))) await self._dispatch(args) self.finish()
[docs]def get_app(api_version, controller, app_class=None): """Setup routes and return initialized Tornado web application. :param str api_version: HTTP Api version gets prepended to routes. :param controller: Controller logic for HTTP API. :param app_class: Use custom WebApplication class. Defaults to kuha_common.server.WebApplication. :returns: Tornado web application. :rtype: :obj:`tornado.web.Application` """ handlers = [ (str_api_endpoint(api_version, r"oai"), OAIRouteHandler), ] settings = {'controller': controller} if controller.stylesheet_url.startswith('/'): static_url_prefix = '/'.join(controller.stylesheet_url.split('/')[:-1]) + '/' settings.update({'static_path': os.path.join(os.path.dirname(__file__), 'static'), 'static_url_prefix': static_url_prefix}) app_class = app_class or WebApplication web_app = app_class(handlers=handlers, **settings) return web_app