From c8ce4517e3bde526106b48e0446f5758ff768fde Mon Sep 17 00:00:00 2001 From: Ben Darnell Date: Sun, 16 Mar 2014 22:17:38 -0400 Subject: [PATCH] Stop overriding _execute in WebSocketHandler; use get() instead. Revise HTTP1Connection detach protocol. As a side effect, this now decodes the arguments to open() in the same way as the arguments to get(). --- maint/test/websocket/client.py | 8 ++++---- tornado/http1connection.py | 16 ++++++++++++---- tornado/websocket.py | 14 ++++---------- 3 files changed, 20 insertions(+), 18 deletions(-) diff --git a/maint/test/websocket/client.py b/maint/test/websocket/client.py index 71624552..91bcd284 100644 --- a/maint/test/websocket/client.py +++ b/maint/test/websocket/client.py @@ -5,7 +5,7 @@ import logging from tornado import gen from tornado.ioloop import IOLoop from tornado.options import define, options, parse_command_line -from tornado.websocket import WebSocketConnect +from tornado.websocket import websocket_connect define('url', default='ws://localhost:9001') define('name', default='Tornado') @@ -13,7 +13,7 @@ define('name', default='Tornado') @gen.engine def run_tests(): url = options.url + '/getCaseCount' - control_ws = yield WebSocketConnect(url, None) + control_ws = yield websocket_connect(url, None) num_tests = int((yield control_ws.read_message())) logging.info('running %d cases', num_tests) msg = yield control_ws.read_message() @@ -22,7 +22,7 @@ def run_tests(): for i in range(1, num_tests + 1): logging.info('running test case %d', i) url = options.url + '/runCase?case=%d&agent=%s' % (i, options.name) - test_ws = yield WebSocketConnect(url, None) + test_ws = yield websocket_connect(url, None) while True: message = yield test_ws.read_message() if message is None: @@ -30,7 +30,7 @@ def run_tests(): test_ws.write_message(message, binary=isinstance(message, bytes)) url = options.url + '/updateReports?agent=%s' % options.name - update_ws = yield WebSocketConnect(url, None) + update_ws = yield websocket_connect(url, None) msg = yield update_ws.read_message() assert msg is None IOLoop.instance().stop() diff --git a/tornado/http1connection.py b/tornado/http1connection.py index ac759a4b..a8c9498e 100644 --- a/tornado/http1connection.py +++ b/tornado/http1connection.py @@ -105,10 +105,11 @@ class HTTP1Connection(object): self._disconnect_on_finish = not self._can_keep_alive( start_line, headers) - ret = delegate.headers_received(start_line, headers) - # TODO: finalize the 'detach' interface. - if ret == 'detach': - return + delegate.headers_received(start_line, headers) + if self.stream is None: + # We've been detached. + # TODO: where else do we need to check for detach? + raise gen.Return(False) skip_body = False if is_client: if method == 'HEAD': @@ -127,6 +128,8 @@ class HTTP1Connection(object): yield body_future delegate.finish() yield self._finish_future + if self.stream is None: + raise gen.Return(False) except httputil.HTTPMessageException as e: gen_log.info("Malformed HTTP message from %r: %s", self.address, e) @@ -173,6 +176,11 @@ class HTTP1Connection(object): # cycle and delay garbage collection of this connection. self._clear_request_state() + def detach(self): + stream = self.stream + self.stream = None + return stream + def write_headers(self, start_line, headers, chunk=None, callback=None): self._chunking = ( # TODO: should this use self._version or start_line.version? diff --git a/tornado/websocket.py b/tornado/websocket.py index 7fdd2f81..40d04e65 100644 --- a/tornado/websocket.py +++ b/tornado/websocket.py @@ -108,22 +108,16 @@ class WebSocketHandler(tornado.web.RequestHandler): def __init__(self, application, request, **kwargs): tornado.web.RequestHandler.__init__(self, application, request, **kwargs) - self.stream = request.connection.stream self.ws_connection = None self.close_code = None self.close_reason = None - def _execute(self, transforms, *args, **kwargs): + @tornado.web.asynchronous + def get(self, *args, **kwargs): self.open_args = args self.open_kwargs = kwargs - # Websocket only supports GET method - if self.request.method != 'GET': - self.stream.write(tornado.escape.utf8( - "HTTP/1.1 405 Method Not Allowed\r\n\r\n" - )) - self.stream.close() - return + self.stream = self.request.connection.detach() # Upgrade header should be present and should be equal to WebSocket if self.request.headers.get("Upgrade", "").lower() != 'websocket': @@ -878,10 +872,10 @@ class WebSocketClientConnection(simple_httpclient._HTTPConnection): self.io_loop.remove_timeout(self._timeout) self._timeout = None + self.stream = self.connection.detach() self.stream.set_close_callback(self._on_close) self.connect_future.set_result(self) - return 'detach' def write_message(self, message, binary=False): """Sends a message to the WebSocket server."""