]> git.ipfire.org Git - thirdparty/tornado.git/commitdiff
Handle non-ascii headers correctly in curl_httpclient.
authorBen Darnell <ben@bendarnell.com>
Sun, 14 Feb 2016 19:00:00 +0000 (14:00 -0500)
committerBen Darnell <ben@bendarnell.com>
Sun, 14 Feb 2016 19:00:00 +0000 (14:00 -0500)
Fixes #1608

tornado/curl_httpclient.py
tornado/test/httpclient_test.py

index 6dadedd9fefb6eb38cce7f77d32e958938201210..664cb492c0f4fab04956df37b91c09648faa0327 100644 (file)
@@ -462,7 +462,7 @@ class CurlAsyncHTTPClient(AsyncHTTPClient):
             request.prepare_curl_callback(curl)
 
     def _curl_header_callback(self, headers, header_callback, header_line):
-        header_line = native_str(header_line)
+        header_line = native_str(header_line.decode('latin1'))
         if header_callback is not None:
             self.io_loop.add_callback(header_callback, header_line)
         # header_line as returned by curl includes the end-of-line characters.
index 9e8e62c6f90a4e390e8c5eae742d6e238f3a943a..8c9a99d9f5a3ea852ee8dafd27c45b153c291028 100644 (file)
@@ -12,7 +12,7 @@ import threading
 import datetime
 from io import BytesIO
 
-from tornado.escape import utf8
+from tornado.escape import utf8, native_str
 from tornado import gen
 from tornado.httpclient import HTTPRequest, HTTPResponse, _RequestProxy, HTTPError, HTTPClient
 from tornado.httpserver import HTTPServer
@@ -113,6 +113,15 @@ class AllMethodsHandler(RequestHandler):
 
     get = post = put = delete = options = patch = other = method
 
+
+class SetHeaderHandler(RequestHandler):
+    def get(self):
+        # Use get_arguments for keys to get strings, but
+        # request.arguments for values to get bytes.
+        for k, v in zip(self.get_arguments('k'),
+                        self.request.arguments['v']):
+            self.set_header(k, v)
+
 # These tests end up getting run redundantly: once here with the default
 # HTTPClient implementation, and then again in each implementation's own
 # test suite.
@@ -133,6 +142,7 @@ class HTTPClientCommonTestCase(AsyncHTTPTestCase):
             url("/304_with_content_length", ContentLength304Handler),
             url("/all_methods", AllMethodsHandler),
             url('/patch', PatchHandler),
+            url('/set_header', SetHeaderHandler),
         ], gzip=True)
 
     def test_patch_receives_payload(self):
@@ -520,6 +530,12 @@ X-XSS-Protection: 1;
         response.rethrow()
         self.assertEqual(response.body, b"Put body: hello")
 
+    def test_non_ascii_header(self):
+        # Non-ascii headers are sent as latin1.
+        response = self.fetch("/set_header?k=foo&v=%E9")
+        response.rethrow()
+        self.assertEqual(response.headers["Foo"], native_str(u"\u00e9"))
+
 
 class RequestProxyTest(unittest.TestCase):
     def test_request_set(self):