openapi-core/openapi_core/wrappers.py

135 lines
3.7 KiB
Python
Raw Normal View History

2017-09-21 11:51:37 +00:00
"""OpenAPI core wrappers module"""
from six import iteritems
2017-09-25 11:22:55 +00:00
from six.moves.urllib.parse import urljoin
2017-09-21 11:51:37 +00:00
from openapi_core.exceptions import (
OpenAPIMappingError, MissingParameterError, InvalidContentTypeError,
2017-09-25 11:22:55 +00:00
InvalidServerError,
2017-09-21 11:51:37 +00:00
)
SPEC_LOCATION_TO_REQUEST_LOCATION_MAPPING = {
'path': 'view_args',
'query': 'args',
'headers': 'headers',
'cookies': 'cookies',
}
class RequestParameters(dict):
valid_locations = ['path', 'query', 'headers', 'cookies']
def __getitem__(self, location):
self.validate_location(location)
return self.setdefault(location, {})
def __setitem__(self, location, value):
raise NotImplementedError
@classmethod
def validate_location(cls, location):
if location not in cls.valid_locations:
raise OpenAPIMappingError(
"Unknown parameter location: {0}".format(str(location)))
2017-09-25 11:22:55 +00:00
class BaseRequestFactory(object):
def get_operation(self, request, spec):
server = self._get_server(request, spec)
operation_pattern = request.full_url_pattern.replace(
server.default_url, '')
2017-10-19 09:34:20 +00:00
method = request.method.lower()
2017-09-25 11:22:55 +00:00
2017-10-19 09:34:20 +00:00
return spec.get_operation(operation_pattern, method)
2017-09-25 11:22:55 +00:00
def _get_server(self, request, spec):
for server in spec.servers:
if server.default_url in request.full_url_pattern:
return server
raise InvalidServerError(
"Invalid request server {0}".format(request.full_url_pattern))
class RequestParametersFactory(BaseRequestFactory):
2017-09-21 11:51:37 +00:00
def __init__(self, attr_mapping=SPEC_LOCATION_TO_REQUEST_LOCATION_MAPPING):
self.attr_mapping = attr_mapping
def create(self, request, spec):
2017-09-25 11:22:55 +00:00
operation = self.get_operation(request, spec)
2017-09-21 11:51:37 +00:00
params = RequestParameters()
for param_name, param in iteritems(operation.parameters):
try:
raw_value = self._get_raw_value(request, param)
2017-09-21 11:51:37 +00:00
except MissingParameterError:
if param.required:
raise
if not param.schema or not param.schema.default:
continue
raw_value = param.schema.default
value = param.unmarshal(raw_value)
2017-09-21 11:51:37 +00:00
params[param.location][param_name] = value
return params
def _get_raw_value(self, request, param):
2017-09-21 11:51:37 +00:00
request_location = self.attr_mapping[param.location]
request_attr = getattr(request, request_location)
try:
return request_attr[param.name]
2017-09-21 11:51:37 +00:00
except KeyError:
raise MissingParameterError(
"Missing required `{0}` parameter".format(param.name))
2017-09-25 11:22:55 +00:00
class RequestBodyFactory(BaseRequestFactory):
2017-09-21 11:51:37 +00:00
def create(self, request, spec):
2017-09-25 11:22:55 +00:00
operation = self.get_operation(request, spec)
2017-09-21 11:51:37 +00:00
2017-09-25 13:20:23 +00:00
if operation.request_body is None:
return None
2017-09-21 11:51:37 +00:00
try:
2017-10-09 14:57:07 +00:00
media_type = operation.request_body[request.mimetype]
2017-09-21 11:51:37 +00:00
except KeyError:
raise InvalidContentTypeError(
2017-10-09 14:57:07 +00:00
"Invalid media type `{0}`".format(request.mimetype))
2017-09-21 11:51:37 +00:00
return media_type.unmarshal(request.data)
class BaseOpenAPIRequest(object):
2017-09-25 11:22:55 +00:00
host_url = NotImplemented
2017-09-21 11:51:37 +00:00
path = NotImplemented
path_pattern = NotImplemented
method = NotImplemented
args = NotImplemented
view_args = NotImplemented
headers = NotImplemented
cookies = NotImplemented
data = NotImplemented
2017-10-09 14:57:07 +00:00
mimetype = NotImplemented
2017-09-21 11:51:37 +00:00
2017-09-25 11:22:55 +00:00
@property
def full_url_pattern(self):
return urljoin(self.host_url, self.path_pattern)
2017-09-21 11:51:37 +00:00
def get_parameters(self, spec):
return RequestParametersFactory().create(self, spec)
def get_body(self, spec):
return RequestBodyFactory().create(self, spec)