tornado-openapi3/tornado_openapi3/requests.py

76 lines
2.6 KiB
Python
Raw Normal View History

2020-09-17 03:04:11 +00:00
import itertools
from urllib.parse import parse_qsl
from typing import Union
2020-09-17 03:04:11 +00:00
from openapi_core.validation.request.datatypes import ( # type: ignore
OpenAPIRequest,
2020-12-05 02:01:22 +00:00
RequestParameters,
RequestValidationResult,
2020-09-17 03:04:11 +00:00
)
from openapi_core.validation.request import validators # type: ignore
from tornado.httpclient import HTTPRequest
from tornado.httputil import HTTPServerRequest, parse_cookie
2020-09-17 03:04:11 +00:00
from werkzeug.datastructures import ImmutableMultiDict, Headers
from .util import parse_mimetype
2020-09-17 03:04:11 +00:00
class TornadoRequestFactory:
2021-02-26 17:03:04 +00:00
"""Factory for converting Tornado requests to OpenAPI request objects."""
2021-02-26 20:34:54 +00:00
2020-09-17 03:04:11 +00:00
@classmethod
def create(cls, request: Union[HTTPRequest, HTTPServerRequest]) -> OpenAPIRequest:
2021-02-26 17:03:04 +00:00
"""Creates an OpenAPI request from Tornado request objects.
Supports both :class:`tornado.httpclient.HTTPRequest` and
:class:`tornado.httputil.HTTPServerRequest` objects.
"""
if isinstance(request, HTTPRequest):
if request.url:
path, _, querystring = request.url.partition("?")
query_arguments: ImmutableMultiDict[str, str] = ImmutableMultiDict(
parse_qsl(querystring)
)
else:
path = ""
query_arguments = ImmutableMultiDict()
2020-09-17 03:04:11 +00:00
else:
path, _, _ = request.full_url().partition("?")
2020-12-04 18:37:25 +00:00
if path == "://":
path = ""
query_arguments = ImmutableMultiDict(
itertools.chain(
*[
[(k, v.decode("utf-8")) for v in vs]
for k, vs in request.query_arguments.items()
]
)
2020-09-17 03:04:11 +00:00
)
return OpenAPIRequest(
full_url_pattern=path,
method=request.method.lower() if request.method else "get",
parameters=RequestParameters(
query=query_arguments,
header=Headers(request.headers.get_all()),
cookie=parse_cookie(request.headers.get("Cookie", "")),
2020-09-17 03:04:11 +00:00
),
body=request.body if request.body else None,
mimetype=parse_mimetype(
request.headers.get("Content-Type", "application/x-www-form-urlencoded")
2020-11-20 00:37:58 +00:00
),
2020-09-17 03:04:11 +00:00
)
class RequestValidator(validators.RequestValidator):
2021-02-26 17:03:04 +00:00
"""Validator for Tornado HTTP Requests."""
2021-02-26 20:34:54 +00:00
2020-12-05 02:01:22 +00:00
def validate(
self, request: Union[HTTPRequest, HTTPServerRequest]
) -> RequestValidationResult:
2021-02-26 17:03:04 +00:00
"""Validate a Tornado HTTP request object."""
return super().validate(TornadoRequestFactory.create(request))
__all__ = ["RequestValidator", "TornadoRequestFactory"]