]> git.ipfire.org Git - thirdparty/tornado.git/commitdiff
Move outgoing HTTP header generation to HTTP1Connection.
authorBen Darnell <ben@bendarnell.com>
Sun, 16 Mar 2014 00:11:02 +0000 (20:11 -0400)
committerBen Darnell <ben@bendarnell.com>
Sun, 16 Mar 2014 00:11:02 +0000 (20:11 -0400)
tornado/http1connection.py
tornado/httputil.py
tornado/simple_httpclient.py
tornado/web.py

index e9d6c9a954308ba87b54f280632b14a0a4766829..3fb58279070755d73e7c90d9a34ab20090e85c21 100644 (file)
@@ -17,7 +17,7 @@
 from __future__ import absolute_import, division, print_function, with_statement
 
 from tornado.concurrent import Future
-from tornado.escape import native_str
+from tornado.escape import native_str, utf8
 from tornado import gen
 from tornado import httputil
 from tornado import iostream
@@ -154,6 +154,14 @@ class HTTP1Connection(object):
         # cycle and delay garbage collection of this connection.
         self._clear_request_state()
 
+    def write_headers(self, start_line, headers):
+        lines = [utf8("%s %s %s" % start_line)]
+        lines.extend([utf8(n) + b": " + utf8(v) for n, v in headers.get_all()])
+        for line in lines:
+            if b'\n' in line:
+                raise ValueError('Newline in header: ' + repr(line))
+        self.write(b"\r\n".join(lines) + b"\r\n\r\n")
+
     def write(self, chunk, callback=None):
         """Writes a chunk of output to the stream."""
         if not self.stream.closed():
index 80cd08ebe794919de93a01b281a5cc240e20b6f4..f36284674ed23a615cacb560b714d07382d41a91 100644 (file)
@@ -631,9 +631,14 @@ def format_timestamp(ts):
     return email.utils.formatdate(ts, usegmt=True)
 
 
+RequestStartLine = collections.namedtuple(
+    'RequestStartLine', ['method', 'path', 'version'])
+
+
 ResponseStartLine = collections.namedtuple(
     'ResponseStartLine', ['version', 'code', 'reason'])
 
+
 def parse_response_start_line(line):
     """Returns a (version, code, reason) tuple for an HTTP 1.x response line.
 
index acc8984398235054a307ac49c1a7979fed6d48a8..4564c3700f1980261023ef863de698dc2888d495 100644 (file)
@@ -322,21 +322,15 @@ class _HTTPConnection(httputil.HTTPMessageDelegate):
             self.request.headers["Accept-Encoding"] = "gzip"
         req_path = ((self.parsed.path or '/') +
                    (('?' + self.parsed.query) if self.parsed.query else ''))
-        request_lines = [utf8("%s %s HTTP/1.1" % (self.request.method,
-                                                  req_path))]
-        for k, v in self.request.headers.get_all():
-            line = utf8(k) + b": " + utf8(v)
-            if b'\n' in line:
-                raise ValueError('Newline in header: ' + repr(line))
-            request_lines.append(line)
-        request_str = b"\r\n".join(request_lines) + b"\r\n\r\n"
-        if self.request.body is not None:
-            request_str += self.request.body
         self.stream.set_nodelay(True)
-        self.stream.write(request_str)
         self.connection = HTTP1Connection(
             self.stream, self._sockaddr,
             no_keep_alive=True, protocol=self.parsed.scheme)
+        start_line = httputil.RequestStartLine(self.request.method,
+                                               req_path, 'HTTP/1.1')
+        self.connection.write_headers(start_line, self.request.headers)
+        if self.request.body is not None:
+            self.connection.write(self.request.body)
         # Ensure that any exception raised in read_response ends up in our
         # stack context.
         self.io_loop.add_future(
index 2c11f2bc177bf6935281ffb0cfd4651d2918e13d..8ff22ca9bcac72800172551f9c6d8d3d6a3f81d6 100644 (file)
@@ -787,19 +787,26 @@ class RequestHandler(object):
                 self._status_code, self._headers, chunk = \
                     transform.transform_first_chunk(
                         self._status_code, self._headers, chunk, include_footers)
-            headers = self._generate_headers()
+            # Finalize the cookie headers (which have been stored in a side
+            # object so an outgoing cookie could be overwritten before it
+            # is sent).
+            if hasattr(self, "_new_cookie"):
+                for cookie in self._new_cookie.values():
+                    self.add_header("Set-Cookie", cookie.OutputString(None))
+
+            start_line = httputil.ResponseStartLine(self.request.version,
+                                                    self._status_code,
+                                                    self._reason)
+            self.request.connection.write_headers(start_line, self._headers)
         else:
             for transform in self._transforms:
                 chunk = transform.transform_chunk(chunk, include_footers)
-            headers = b""
 
         # Ignore the chunk and only write the headers for HEAD requests
         if self.request.method == "HEAD":
-            if headers:
-                self.request.write(headers, callback=callback)
             return
 
-        self.request.write(headers + chunk, callback=callback)
+        self.request.write(chunk, callback=callback)
 
     def finish(self, chunk=None):
         """Finishes this response, ending the HTTP request."""
@@ -1245,18 +1252,6 @@ class RequestHandler(object):
         if self._auto_finish and not self._finished:
             self.finish()
 
-    def _generate_headers(self):
-        reason = self._reason
-        lines = [utf8(self.request.version + " " +
-                      str(self._status_code) +
-                      " " + reason)]
-        lines.extend([utf8(n) + b": " + utf8(v) for n, v in self._headers.get_all()])
-
-        if hasattr(self, "_new_cookie"):
-            for cookie in self._new_cookie.values():
-                lines.append(utf8("Set-Cookie: " + cookie.OutputString(None)))
-        return b"\r\n".join(lines) + b"\r\n\r\n"
-
     def _log(self):
         """Logs the current request.