From: Andrey Sumin Date: Tue, 29 Nov 2016 08:41:02 +0000 (+0300) Subject: allow HTTPServerConnectionDelegate as routing targets X-Git-Tag: v4.5.0~48^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7bb6bb4d30076f825a52b799f641289a6bbe8ab0;p=thirdparty%2Ftornado.git allow HTTPServerConnectionDelegate as routing targets --- diff --git a/tornado/httputil.py b/tornado/httputil.py index 8e9361c5c..8ea8a01e2 100644 --- a/tornado/httputil.py +++ b/tornado/httputil.py @@ -337,7 +337,7 @@ class HTTPServerRequest(object): """ def __init__(self, method=None, uri=None, version="HTTP/1.0", headers=None, body=None, host=None, files=None, connection=None, - start_line=None): + start_line=None, server_connection=None): if start_line is not None: method, uri, version = start_line self.method = method @@ -355,6 +355,7 @@ class HTTPServerRequest(object): self.host_name = split_host_and_port(self.host.lower())[0] self.files = files or {} self.connection = connection + self.server_connection = server_connection self._start_time = time.time() self._finish_time = None diff --git a/tornado/routing.py b/tornado/routing.py index cb584cf3d..15baeb489 100644 --- a/tornado/routing.py +++ b/tornado/routing.py @@ -60,14 +60,14 @@ routing configurations. For example, `RuleRouter` can be used to route between a server = HTTPServer(router) -Subclasses of `~.httputil.HTTPMessageDelegate` and old-style callables can also be used as +Implementations of `~.httputil.HTTPServerConnectionDelegate` and old-style callables can also be used as rule targets: .. code-block:: python router = RuleRouter([ Rule(PathMatches("/callable"), request_callable), # def request_callable(request): ... - Rule(PathMatches("/delegate"), HTTPMessageDelegateSubclass) + Rule(PathMatches("/delegate"), HTTPServerConnectionDelegateImpl()) ]) server = HTTPServer(router) @@ -95,8 +95,8 @@ And of course a nested `RuleRouter` would be a valid thing: server = HTTPServer(router) Rules are instances of `Rule` class. They contain some target (`~.web.Application` instance, -`~.httputil.HTTPMessageDelegate` subclass, a callable or a nested `Router`) and provide the -basic routing logic defining whether this rule is a match for a particular request. +`~.httputil.HTTPServerConnectionDelegate` implementation, a callable or a nested `Router`) and +provide the basic routing logic defining whether this rule is a match for a particular request. This routing logic is implemented in `Matcher` subclasses (see `HostMatches`, `PathMatches` and others). @@ -108,7 +108,6 @@ from __future__ import absolute_import, division, print_function, with_statement import re from functools import partial -from inspect import isclass from tornado import httputil from tornado.httpserver import _CallableAdapter @@ -139,7 +138,7 @@ class Router(httputil.HTTPServerConnectionDelegate): raise NotImplementedError() def start_request(self, server_conn, request_conn): - return _RoutingDelegate(self, request_conn) + return _RoutingDelegate(self, server_conn, request_conn) class ReversibleRouter(Router): @@ -159,15 +158,17 @@ class ReversibleRouter(Router): class _RoutingDelegate(httputil.HTTPMessageDelegate): - def __init__(self, router, request_conn): - self.connection = request_conn + def __init__(self, router, server_conn, request_conn): + self.server_conn = server_conn + self.request_conn = request_conn self.delegate = None self.router = router # type: Router def headers_received(self, start_line, headers): request = httputil.HTTPServerRequest( - connection=self.connection, start_line=start_line, - headers=headers) + connection=self.request_conn, + server_connection=self.server_conn, + start_line=start_line, headers=headers) self.delegate = self.router.find_handler(request) return self.delegate.headers_received(start_line, headers) @@ -264,8 +265,8 @@ class RuleRouter(Router): if isinstance(target, Router): return target.find_handler(request, **target_params) - elif isclass(target) and issubclass(target, httputil.HTTPMessageDelegate): - return target(request.connection) + elif isinstance(target, httputil.HTTPServerConnectionDelegate): + return target.start_request(request.server_connection, request.connection) elif callable(target): return _CallableAdapter( @@ -322,7 +323,7 @@ class Rule(object): whether the rule should be considered a match for a specific request. :arg target: a Rule's target (typically a ``RequestHandler`` or - `~.httputil.HTTPMessageDelegate` subclass or even a nested `Router`). + `~.httputil.HTTPServerConnectionDelegate` subclass or even a nested `Router`). :arg dict target_kwargs: a dict of parameters that can be useful at the moment of target instantiation (for example, ``status_code`` for a ``RequestHandler`` subclass). They end up in diff --git a/tornado/test/routing_test.py b/tornado/test/routing_test.py index 1d1a858b0..37f7cfd3a 100644 --- a/tornado/test/routing_test.py +++ b/tornado/test/routing_test.py @@ -13,7 +13,7 @@ from __future__ import absolute_import, division, print_function, with_statement -from tornado.httputil import HTTPHeaders, HTTPMessageDelegate, ResponseStartLine +from tornado.httputil import HTTPHeaders, HTTPMessageDelegate, HTTPServerConnectionDelegate, ResponseStartLine from tornado.routing import HostMatches, PathMatches, ReversibleRouter, Rule, RuleRouter from tornado.testing import AsyncHTTPTestCase from tornado.web import Application, RequestHandler @@ -80,17 +80,22 @@ class CustomRouterTestCase(AsyncHTTPTestCase): self.assertEqual(response.body, b"app2: first_handler: /first_handler") -class MessageDelegate(HTTPMessageDelegate): - def __init__(self, connection): - self.connection = connection +class ConnectionDelegate(HTTPServerConnectionDelegate): + def start_request(self, server_conn, request_conn): - def finish(self): - response_body = b"OK" - self.connection.write_headers( - ResponseStartLine("HTTP/1.1", 200, "OK"), - HTTPHeaders({"Content-Length": str(len(response_body))})) - self.connection.write(response_body) - self.connection.finish() + class MessageDelegate(HTTPMessageDelegate): + def __init__(self, connection): + self.connection = connection + + def finish(self): + response_body = b"OK" + self.connection.write_headers( + ResponseStartLine("HTTP/1.1", 200, "OK"), + HTTPHeaders({"Content-Length": str(len(response_body))})) + self.connection.write(response_body) + self.connection.finish() + + return MessageDelegate(request_conn) class RuleRouterTest(AsyncHTTPTestCase): @@ -107,7 +112,7 @@ class RuleRouterTest(AsyncHTTPTestCase): ]), Rule(PathMatches("/first_handler"), FirstHandler, name="first_handler"), Rule(PathMatches("/request_callable"), request_callable), - ("/message_delegate", MessageDelegate) + ("/connection_delegate", ConnectionDelegate()) ]) return app @@ -118,7 +123,7 @@ class RuleRouterTest(AsyncHTTPTestCase): response = self.fetch("/first_handler", headers={'Host': 'www.example.com'}) self.assertEqual(response.body, b"second_handler: /first_handler") - response = self.fetch("/message_delegate") + response = self.fetch("/connection_delegate") self.assertEqual(response.body, b"OK") response = self.fetch("/request_callable")