refactor JsonResource
rephrase the OPTIONS and unrecognised request handling so that they look similar to the common flow.pull/2965/head
parent
89b7232ff8
commit
dbe80a286b
|
@ -1,5 +1,6 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright 2014-2016 OpenMarket Ltd
|
# Copyright 2014-2016 OpenMarket Ltd
|
||||||
|
# Copyright 2018 New Vector Ltd
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
|
@ -276,49 +277,54 @@ class JsonResource(HttpServer, resource.Resource):
|
||||||
This checks if anyone has registered a callback for that method and
|
This checks if anyone has registered a callback for that method and
|
||||||
path.
|
path.
|
||||||
"""
|
"""
|
||||||
|
callback, group_dict = self._get_handler_for_request(request)
|
||||||
|
|
||||||
|
servlet_instance = getattr(callback, "__self__", None)
|
||||||
|
if servlet_instance is not None:
|
||||||
|
servlet_classname = servlet_instance.__class__.__name__
|
||||||
|
else:
|
||||||
|
servlet_classname = "%r" % callback
|
||||||
|
|
||||||
|
request_metrics.name = servlet_classname
|
||||||
|
|
||||||
|
# Now trigger the callback. If it returns a response, we send it
|
||||||
|
# here. If it throws an exception, that is handled by the wrapper
|
||||||
|
# installed by @request_handler.
|
||||||
|
|
||||||
|
kwargs = intern_dict({
|
||||||
|
name: urllib.unquote(value).decode("UTF-8") if value else value
|
||||||
|
for name, value in group_dict.items()
|
||||||
|
})
|
||||||
|
|
||||||
|
callback_return = yield callback(request, **kwargs)
|
||||||
|
if callback_return is not None:
|
||||||
|
code, response = callback_return
|
||||||
|
self._send_response(request, code, response)
|
||||||
|
|
||||||
|
def _get_handler_for_request(self, request):
|
||||||
|
"""Finds a callback method to handle the given request
|
||||||
|
|
||||||
|
Args:
|
||||||
|
request (twisted.web.http.Request):
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Tuple[Callable, dict[str, str]]: callback method, and the dict
|
||||||
|
mapping keys to path components as specified in the handler's
|
||||||
|
path match regexp
|
||||||
|
"""
|
||||||
if request.method == "OPTIONS":
|
if request.method == "OPTIONS":
|
||||||
self._send_response(request, 200, {})
|
return _options_handler, {}
|
||||||
return
|
|
||||||
|
|
||||||
# Loop through all the registered callbacks to check if the method
|
# Loop through all the registered callbacks to check if the method
|
||||||
# and path regex match
|
# and path regex match
|
||||||
for path_entry in self.path_regexs.get(request.method, []):
|
for path_entry in self.path_regexs.get(request.method, []):
|
||||||
m = path_entry.pattern.match(request.path)
|
m = path_entry.pattern.match(request.path)
|
||||||
if not m:
|
if m:
|
||||||
continue
|
# We found a match!
|
||||||
|
return path_entry.callback, m.groupdict()
|
||||||
# We found a match! First update the metrics object to indicate
|
|
||||||
# which servlet is handling the request.
|
|
||||||
|
|
||||||
callback = path_entry.callback
|
|
||||||
|
|
||||||
servlet_instance = getattr(callback, "__self__", None)
|
|
||||||
if servlet_instance is not None:
|
|
||||||
servlet_classname = servlet_instance.__class__.__name__
|
|
||||||
else:
|
|
||||||
servlet_classname = "%r" % callback
|
|
||||||
|
|
||||||
request_metrics.name = servlet_classname
|
|
||||||
|
|
||||||
# Now trigger the callback. If it returns a response, we send it
|
|
||||||
# here. If it throws an exception, that is handled by the wrapper
|
|
||||||
# installed by @request_handler.
|
|
||||||
|
|
||||||
kwargs = intern_dict({
|
|
||||||
name: urllib.unquote(value).decode("UTF-8") if value else value
|
|
||||||
for name, value in m.groupdict().items()
|
|
||||||
})
|
|
||||||
|
|
||||||
callback_return = yield callback(request, **kwargs)
|
|
||||||
if callback_return is not None:
|
|
||||||
code, response = callback_return
|
|
||||||
self._send_response(request, code, response)
|
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
# Huh. No one wanted to handle that? Fiiiiiine. Send 400.
|
# Huh. No one wanted to handle that? Fiiiiiine. Send 400.
|
||||||
request_metrics.name = self.__class__.__name__ + ".UnrecognizedRequest"
|
return _unrecognised_request_handler, {}
|
||||||
raise UnrecognizedRequestError()
|
|
||||||
|
|
||||||
def _send_response(self, request, code, response_json_object,
|
def _send_response(self, request, code, response_json_object,
|
||||||
response_code_message=None):
|
response_code_message=None):
|
||||||
|
@ -335,6 +341,14 @@ class JsonResource(HttpServer, resource.Resource):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _options_handler(request):
|
||||||
|
return {}
|
||||||
|
|
||||||
|
|
||||||
|
def _unrecognised_request_handler(request):
|
||||||
|
raise UnrecognizedRequestError()
|
||||||
|
|
||||||
|
|
||||||
class RequestMetrics(object):
|
class RequestMetrics(object):
|
||||||
def start(self, clock, name):
|
def start(self, clock, name):
|
||||||
self.start = clock.time_msec()
|
self.start = clock.time_msec()
|
||||||
|
|
Loading…
Reference in New Issue