diff --git a/tornado/escape.py b/tornado/escape.py
index e6636f20..7a3b0e03 100644
--- a/tornado/escape.py
+++ b/tornado/escape.py
@@ -37,6 +37,11 @@ else:
     import htmlentitydefs
     import urllib as urllib_parse
 
+try:
+    import typing  # noqa
+except ImportError:
+    pass
+
 
 _XHTML_ESCAPE_RE = re.compile('[&<>"\']')
 _XHTML_ESCAPE_DICT = {'&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;',
@@ -180,6 +185,7 @@ _UTF8_TYPES = (bytes, type(None))
 
 
 def utf8(value):
+    # type: (typing.Union[bytes,unicode_type,None])->typing.Union[bytes,None]
     """Converts a string argument to a byte string.
 
     If the argument is already a byte string or None, it is returned unchanged.
diff --git a/tornado/http1connection.py b/tornado/http1connection.py
index b04cff13..8194f914 100644
--- a/tornado/http1connection.py
+++ b/tornado/http1connection.py
@@ -30,7 +30,7 @@ from tornado import httputil
 from tornado import iostream
 from tornado.log import gen_log, app_log
 from tornado import stack_context
-from tornado.util import GzipDecompressor
+from tornado.util import GzipDecompressor, PY3
 
 
 class _QuietException(Exception):
@@ -372,7 +372,14 @@ class HTTP1Connection(httputil.HTTPConnection):
             self._expected_content_remaining = int(headers['Content-Length'])
         else:
             self._expected_content_remaining = None
-        lines.extend([utf8(n) + b": " + utf8(v) for n, v in headers.get_all()])
+        # TODO: headers are supposed to be of type str, but we still have some
+        # cases that let bytes slip through. Remove these native_str calls when those
+        # are fixed.
+        header_lines = (native_str(n) + ": " + native_str(v) for n, v in headers.get_all())
+        if PY3:
+            lines.extend(l.encode('latin1') for l in header_lines)
+        else:
+            lines.extend(header_lines)
         for line in lines:
             if b'\n' in line:
                 raise ValueError('Newline in header: ' + repr(line))
diff --git a/tornado/httputil.py b/tornado/httputil.py
index d0901565..866681ad 100644
--- a/tornado/httputil.py
+++ b/tornado/httputil.py
@@ -59,6 +59,12 @@ except ImportError:
     # on the class definition itself; must go through an assignment.
     SSLError = _SSLError  # type: ignore
 
+try:
+    import typing
+except ImportError:
+    pass
+
+
 # RFC 7230 section 3.5: a recipient MAY recognize a single LF as a line
 # terminator and ignore any preceding CR.
 _CRLF_RE = re.compile(r'\r?\n')
@@ -124,8 +130,8 @@ class HTTPHeaders(collections.MutableMapping):
     Set-Cookie: C=D
     """
     def __init__(self, *args, **kwargs):
-        self._dict = {}
-        self._as_list = {}
+        self._dict = {}  # type: typing.Dict[str, str]
+        self._as_list = {}  # type: typing.Dict[str, typing.List[str]]
         self._last_key = None
         if (len(args) == 1 and len(kwargs) == 0 and
                 isinstance(args[0], HTTPHeaders)):
@@ -139,6 +145,7 @@ class HTTPHeaders(collections.MutableMapping):
     # new public methods
 
     def add(self, name, value):
+        # type: (str, str) -> None
         """Adds a new value for the given key."""
         norm_name = _normalized_headers[name]
         self._last_key = norm_name
@@ -155,6 +162,7 @@ class HTTPHeaders(collections.MutableMapping):
         return self._as_list.get(norm_name, [])
 
     def get_all(self):
+        # type: () -> typing.Iterable[typing.Tuple[str, str]]
         """Returns an iterable of all (name, value) pairs.
 
         If a header has multiple values, multiple pairs will be
@@ -203,6 +211,7 @@ class HTTPHeaders(collections.MutableMapping):
         self._as_list[norm_name] = [value]
 
     def __getitem__(self, name):
+        # type: (str) -> str
         return self._dict[_normalized_headers[name]]
 
     def __delitem__(self, name):
diff --git a/tornado/log.py b/tornado/log.py
index ac1bb95e..1d10d379 100644
--- a/tornado/log.py
+++ b/tornado/log.py
@@ -77,8 +77,8 @@ class LogFormatter(logging.Formatter):
     * Robust against str/bytes encoding problems.
 
     This formatter is enabled automatically by
-    `tornado.options.parse_command_line` or `tornado.options.parse_config_file`
-    (unless ``--logging=none`` is used).
+    `tornado.options.parse_command_line` (unless ``--logging=none`` is
+    used).
     """
     DEFAULT_FORMAT = '%(color)s[%(levelname)1.1s %(asctime)s %(module)s:%(lineno)d]%(end_color)s %(message)s'
     DEFAULT_DATE_FORMAT = '%y%m%d %H:%M:%S'
diff --git a/tornado/util.py b/tornado/util.py
index 4283d4e8..d49a84f4 100644
--- a/tornado/util.py
+++ b/tornado/util.py
@@ -33,12 +33,13 @@ else:
 # Aliases for types that are spelled differently in different Python
 # versions. bytes_type is deprecated and no longer used in Tornado
 # itself but is left in case anyone outside Tornado is using it.
-unicode_type = type(u'')
 bytes_type = bytes
 if PY3:
+    unicode_type = str
     basestring_type = str
 else:
-    # The name basestring doesn't exist in py3 so silence flake8.
+    # The names unicode and basestring don't exist in py3 so silence flake8.
+    unicode_type = unicode  # noqa
     basestring_type = basestring  # noqa
 
 
diff --git a/tornado/web.py b/tornado/web.py
index 8f2acfcc..c9ff2b2d 100644
--- a/tornado/web.py
+++ b/tornado/web.py
@@ -104,6 +104,11 @@ else:
 
 try:
     import typing  # noqa
+
+    # The following types are accepted by RequestHandler.set_header
+    # and related methods.
+    _HeaderTypes = typing.Union[bytes, unicode_type,
+                                numbers.Integral, datetime.datetime]
 except ImportError:
     pass
 
@@ -164,6 +169,7 @@ class RequestHandler(object):
         self._auto_finish = True
         self._transforms = None  # will be set in _execute
         self._prepared_future = None
+        self._headers = None  # type: httputil.HTTPHeaders
         self.path_args = None
         self.path_kwargs = None
         self.ui = ObjectDict((n, self._ui_method(m)) for n, m in
@@ -318,6 +324,7 @@ class RequestHandler(object):
         return self._status_code
 
     def set_header(self, name, value):
+        # type: (str, _HeaderTypes) -> None
         """Sets the given response header name and value.
 
         If a datetime is given, we automatically format it according to the
@@ -327,6 +334,7 @@ class RequestHandler(object):
         self._headers[name] = self._convert_header_value(value)
 
     def add_header(self, name, value):
+        # type: (str, _HeaderTypes) -> None
         """Adds the given response header and value.
 
         Unlike `set_header`, `add_header` may be called multiple times
@@ -343,13 +351,25 @@ class RequestHandler(object):
         if name in self._headers:
             del self._headers[name]
 
-    _INVALID_HEADER_CHAR_RE = re.compile(br"[\x00-\x1f]")
+    _INVALID_HEADER_CHAR_RE = re.compile(r"[\x00-\x1f]")
 
     def _convert_header_value(self, value):
-        if isinstance(value, bytes):
-            pass
-        elif isinstance(value, unicode_type):
-            value = value.encode('utf-8')
+        # type: (_HeaderTypes) -> str
+
+        # Convert the input value to a str. This type check is a bit
+        # subtle: The bytes case only executes on python 3, and the
+        # unicode case only executes on python 2, because the other
+        # cases are covered by the first match for str.
+        if isinstance(value, str):
+            retval = value
+        elif isinstance(value, bytes):  # py3
+            # Non-ascii characters in headers are not well supported,
+            # but if you pass bytes, use latin1 so they pass through as-is.
+            retval = value.decode('latin1')
+        elif isinstance(value, unicode_type):  # py2
+            # TODO: This is inconsistent with the use of latin1 above,
+            # but it's been that way for a long time. Should it change?
+            retval = escape.utf8(value)
         elif isinstance(value, numbers.Integral):
             # return immediately since we know the converted value will be safe
             return str(value)
@@ -359,9 +379,9 @@ class RequestHandler(object):
             raise TypeError("Unsupported header value %r" % value)
         # If \n is allowed into the header, it is possible to inject
         # additional headers or split the request.
-        if RequestHandler._INVALID_HEADER_CHAR_RE.search(value):
-            raise ValueError("Unsafe header value %r", value)
-        return value
+        if RequestHandler._INVALID_HEADER_CHAR_RE.search(retval):
+            raise ValueError("Unsafe header value %r", retval)
+        return retval
 
     _ARG_DEFAULT = object()
 
@@ -2696,6 +2716,7 @@ class OutputTransform(object):
         pass
 
     def transform_first_chunk(self, status_code, headers, chunk, finishing):
+        # type: (int, httputil.HTTPHeaders, bytes, bool) -> typing.Tuple[int, httputil.HTTPHeaders, bytes]
         return status_code, headers, chunk
 
     def transform_chunk(self, chunk, finishing):
@@ -2736,10 +2757,12 @@ class GZipContentEncoding(OutputTransform):
         return ctype.startswith('text/') or ctype in self.CONTENT_TYPES
 
     def transform_first_chunk(self, status_code, headers, chunk, finishing):
+        # type: (int, httputil.HTTPHeaders, bytes, bool) -> typing.Tuple[int, httputil.HTTPHeaders, bytes]
+        # TODO: can/should this type be inherited from the superclass?
         if 'Vary' in headers:
-            headers['Vary'] += b', Accept-Encoding'
+            headers['Vary'] += ', Accept-Encoding'
         else:
-            headers['Vary'] = b'Accept-Encoding'
+            headers['Vary'] = 'Accept-Encoding'
         if self._gzipping:
             ctype = _unicode(headers.get("Content-Type", "")).split(";")[0]
             self._gzipping = self._compressible_type(ctype) and \

When Use AsyncHttpClien.AttributeError: 'GZipContentEncoding' object has no attribute '_gzip_file'
 File "D:\Python3.4.3\lib\site-packages\tornado-4.3-py3.4-win32.egg\tornado\web.py", line 781, in render
        self.finish(html)
      File "D:\Python3.4.3\lib\site-packages\tornado-4.3-py3.4-win32.egg\tornado\web.py", line 932, in finish
        self.flush(include_footers=True)
      File "D:\Python3.4.3\lib\site-packages\tornado-4.3-py3.4-win32.egg\tornado\web.py", line 891, in flush
        chunk = transform.transform_chunk(chunk, include_footers)
      File "D:\Python3.4.3\lib\site-packages\tornado-4.3-py3.4-win32.egg\tornado\web.py", line 2763, in transform_chunk
        self._gzip_file.write(chunk)
    AttributeError: 'GZipContentEncoding' object has no attribute '_gzip_file'
diff --git a/tornado/test/web_test.py b/tornado/test/web_test.py
index fac23a21..7e417854 100644
--- a/tornado/test/web_test.py
+++ b/tornado/test/web_test.py
@@ -1506,8 +1506,8 @@ class ErrorHandlerXSRFTest(WebTestCase):
 class GzipTestCase(SimpleHandlerTestCase):
     class Handler(RequestHandler):
         def get(self):
-            if self.get_argument('vary', None):
-                self.set_header('Vary', self.get_argument('vary'))
+            for v in self.get_arguments('vary'):
+                self.add_header('Vary', v)
             # Must write at least MIN_LENGTH bytes to activate compression.
             self.write('hello world' + ('!' * GZipContentEncoding.MIN_LENGTH))
 
@@ -1516,8 +1516,7 @@ class GzipTestCase(SimpleHandlerTestCase):
             gzip=True,
             static_path=os.path.join(os.path.dirname(__file__), 'static'))
 
-    def test_gzip(self):
-        response = self.fetch('/')
+    def assert_compressed(self, response):
         # simple_httpclient renames the content-encoding header;
         # curl_httpclient doesn't.
         self.assertEqual(
@@ -1525,17 +1524,18 @@ class GzipTestCase(SimpleHandlerTestCase):
                 'Content-Encoding',
                 response.headers.get('X-Consumed-Content-Encoding')),
             'gzip')
+
+
+    def test_gzip(self):
+        response = self.fetch('/')
+        self.assert_compressed(response)
         self.assertEqual(response.headers['Vary'], 'Accept-Encoding')
 
     def test_gzip_static(self):
         # The streaming responses in StaticFileHandler have subtle
         # interactions with the gzip output so test this case separately.
         response = self.fetch('/robots.txt')
-        self.assertEqual(
-            response.headers.get(
-                'Content-Encoding',
-                response.headers.get('X-Consumed-Content-Encoding')),
-            'gzip')
+        self.assert_compressed(response)
         self.assertEqual(response.headers['Vary'], 'Accept-Encoding')
 
     def test_gzip_not_requested(self):
@@ -1545,9 +1545,16 @@ class GzipTestCase(SimpleHandlerTestCase):
 
     def test_vary_already_present(self):
         response = self.fetch('/?vary=Accept-Language')
-        self.assertEqual(response.headers['Vary'],
-                         'Accept-Language, Accept-Encoding')
-
+        self.assert_compressed(response)
+        self.assertEqual([s.strip() for s in response.headers['Vary'].split(',')],
+                         ['Accept-Language', 'Accept-Encoding'])
+
+    def test_vary_already_present_multiple(self):
+        # Regression test for https://github.com/tornadoweb/tornado/issues/1670
+        response = self.fetch('/?vary=Accept-Language&vary=Cookie')
+        self.assert_compressed(response)
+        self.assertEqual([s.strip() for s in response.headers['Vary'].split(',')],
+                         ['Accept-Language', 'Cookie', 'Accept-Encoding'])
 
 @wsgi_safe
 class PathArgsInPrepareTest(WebTestCase):

pip install -e .
parse_log_pytest
pytest
futures mock monotonic trollius pytest
apt-get update apt-get install -y gcc
3.5
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
attrs @ file:///opt/conda/conda-bld/attrs_1642510447205/work
certifi==2021.5.30
futures==2.2.0
importlib-metadata @ file:///tmp/build/80754af9/importlib-metadata_1631916693255/work
iniconfig @ file:///home/linux1/recipes/ci/iniconfig_1610983019677/work
mock==5.2.0
monotonic==1.6
more-itertools @ file:///tmp/build/80754af9/more-itertools_1637733554872/work
packaging @ file:///tmp/build/80754af9/packaging_1637314298585/work
pluggy @ file:///tmp/build/80754af9/pluggy_1615976315926/work
py @ file:///opt/conda/conda-bld/py_1644396412707/work
pyparsing @ file:///tmp/build/80754af9/pyparsing_1635766073266/work
pytest==6.2.4
six==1.17.0
toml @ file:///tmp/build/80754af9/toml_1616166611790/work
-e git+https://github.com/tornadoweb/tornado.git@d71026ab2e1febfedb9d5e0589107349c5019fde#egg=tornado
trollius==2.1.post2
typing_extensions @ file:///opt/conda/conda-bld/typing_extensions_1647553014482/work
zipp @ file:///tmp/build/80754af9/zipp_1633618647012/work

name: tornado
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - attrs=21.4.0=pyhd3eb1b0_0
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2021.5.30=py36h06a4308_0
  - importlib-metadata=4.8.1=py36h06a4308_0
  - importlib_metadata=4.8.1=hd3eb1b0_0
  - iniconfig=1.1.1=pyhd3eb1b0_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.3=he6710b0_2
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - more-itertools=8.12.0=pyhd3eb1b0_0
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - packaging=21.3=pyhd3eb1b0_0
  - pip=21.2.2=py36h06a4308_0
  - pluggy=0.13.1=py36h06a4308_0
  - py=1.11.0=pyhd3eb1b0_0
  - pyparsing=3.0.4=pyhd3eb1b0_0
  - pytest=6.2.4=py36h06a4308_2
  - python=3.6.13=h12debd9_1
  - readline=8.2=h5eee18b_0
  - setuptools=58.0.4=py36h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - toml=0.10.2=pyhd3eb1b0_0
  - typing_extensions=4.1.1=pyh06a4308_0
  - wheel=0.37.1=pyhd3eb1b0_0
  - xz=5.6.4=h5eee18b_1
  - zipp=3.6.0=pyhd3eb1b0_0
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - futures==2.2.0
      - mock==5.2.0
      - monotonic==1.6
      - six==1.17.0
      - trollius==2.1.post2
prefix: /opt/conda/envs/tornado

tornado/test/web_test.py::GzipTestCase::test_vary_already_present_multiple
tornado/test/web_test.py::SecureCookieV1Test::test_arbitrary_bytes tornado/test/web_test.py::SecureCookieV1Test::test_cookie_tampering_future_timestamp tornado/test/web_test.py::SecureCookieV1Test::test_round_trip tornado/test/web_test.py::SecureCookieV2Test::test_key_version_increment_version tornado/test/web_test.py::SecureCookieV2Test::test_key_version_invalidate_version tornado/test/web_test.py::SecureCookieV2Test::test_key_version_roundtrip tornado/test/web_test.py::SecureCookieV2Test::test_key_version_roundtrip_differing_version tornado/test/web_test.py::SecureCookieV2Test::test_round_trip tornado/test/web_test.py::CookieTest::test_cookie_special_char tornado/test/web_test.py::CookieTest::test_get_cookie tornado/test/web_test.py::CookieTest::test_set_cookie tornado/test/web_test.py::CookieTest::test_set_cookie_domain tornado/test/web_test.py::CookieTest::test_set_cookie_expires_days tornado/test/web_test.py::CookieTest::test_set_cookie_false_flags tornado/test/web_test.py::CookieTest::test_set_cookie_max_age tornado/test/web_test.py::CookieTest::test_set_cookie_overwrite tornado/test/web_test.py::AuthRedirectTest::test_absolute_auth_redirect tornado/test/web_test.py::AuthRedirectTest::test_relative_auth_redirect tornado/test/web_test.py::ConnectionCloseTest::test_connection_close tornado/test/web_test.py::RequestEncodingTest::test_error tornado/test/web_test.py::RequestEncodingTest::test_group_encoding tornado/test/web_test.py::RequestEncodingTest::test_group_question_mark tornado/test/web_test.py::RequestEncodingTest::test_slashes tornado/test/web_test.py::WSGISafeWebTest::test_decode_argument tornado/test/web_test.py::WSGISafeWebTest::test_decode_argument_invalid_unicode tornado/test/web_test.py::WSGISafeWebTest::test_decode_argument_plus tornado/test/web_test.py::WSGISafeWebTest::test_get_argument tornado/test/web_test.py::WSGISafeWebTest::test_get_body_arguments tornado/test/web_test.py::WSGISafeWebTest::test_get_query_arguments tornado/test/web_test.py::WSGISafeWebTest::test_header_injection tornado/test/web_test.py::WSGISafeWebTest::test_multi_header tornado/test/web_test.py::WSGISafeWebTest::test_no_gzip tornado/test/web_test.py::WSGISafeWebTest::test_optional_path tornado/test/web_test.py::WSGISafeWebTest::test_redirect tornado/test/web_test.py::WSGISafeWebTest::test_reverse_url tornado/test/web_test.py::WSGISafeWebTest::test_types tornado/test/web_test.py::WSGISafeWebTest::test_uimodule_resources tornado/test/web_test.py::WSGISafeWebTest::test_uimodule_unescaped tornado/test/web_test.py::WSGISafeWebTest::test_web_redirect tornado/test/web_test.py::WSGISafeWebTest::test_web_redirect_double_slash tornado/test/web_test.py::NonWSGIWebTests::test_empty_flush tornado/test/web_test.py::NonWSGIWebTests::test_flow_control tornado/test/web_test.py::ErrorResponseTest::test_default tornado/test/web_test.py::ErrorResponseTest::test_failed_write_error tornado/test/web_test.py::ErrorResponseTest::test_write_error tornado/test/web_test.py::StaticFileTest::test_absolute_static_url tornado/test/web_test.py::StaticFileTest::test_absolute_version_exclusion tornado/test/web_test.py::StaticFileTest::test_include_host_override tornado/test/web_test.py::StaticFileTest::test_path_traversal_protection tornado/test/web_test.py::StaticFileTest::test_relative_version_exclusion tornado/test/web_test.py::StaticFileTest::test_root_static_path tornado/test/web_test.py::StaticFileTest::test_static_304_if_modified_since tornado/test/web_test.py::StaticFileTest::test_static_304_if_none_match tornado/test/web_test.py::StaticFileTest::test_static_404 tornado/test/web_test.py::StaticFileTest::test_static_compressed_files tornado/test/web_test.py::StaticFileTest::test_static_etag tornado/test/web_test.py::StaticFileTest::test_static_files tornado/test/web_test.py::StaticFileTest::test_static_head tornado/test/web_test.py::StaticFileTest::test_static_head_range tornado/test/web_test.py::StaticFileTest::test_static_if_modified_since_pre_epoch tornado/test/web_test.py::StaticFileTest::test_static_if_modified_since_time_zone tornado/test/web_test.py::StaticFileTest::test_static_invalid_range tornado/test/web_test.py::StaticFileTest::test_static_range_if_none_match tornado/test/web_test.py::StaticFileTest::test_static_unsatisfiable_range_invalid_start tornado/test/web_test.py::StaticFileTest::test_static_unsatisfiable_range_zero_suffix tornado/test/web_test.py::StaticFileTest::test_static_url tornado/test/web_test.py::StaticFileTest::test_static_with_range tornado/test/web_test.py::StaticFileTest::test_static_with_range_end_edge tornado/test/web_test.py::StaticFileTest::test_static_with_range_full_file tornado/test/web_test.py::StaticFileTest::test_static_with_range_full_past_end tornado/test/web_test.py::StaticFileTest::test_static_with_range_neg_end tornado/test/web_test.py::StaticFileTest::test_static_with_range_partial_past_end tornado/test/web_test.py::StaticDefaultFilenameTest::test_static_default_filename tornado/test/web_test.py::StaticDefaultFilenameTest::test_static_default_redirect tornado/test/web_test.py::StaticFileWithPathTest::test_serve tornado/test/web_test.py::CustomStaticFileTest::test_serve tornado/test/web_test.py::CustomStaticFileTest::test_static_url tornado/test/web_test.py::HostMatchingTest::test_host_matching tornado/test/web_test.py::NamedURLSpecGroupsTest::test_named_urlspec_groups tornado/test/web_test.py::ClearHeaderTest::test_clear_header tornado/test/web_test.py::Header304Test::test_304_headers tornado/test/web_test.py::StatusReasonTest::test_status tornado/test/web_test.py::DateHeaderTest::test_date_header tornado/test/web_test.py::RaiseWithReasonTest::test_httperror_str tornado/test/web_test.py::RaiseWithReasonTest::test_httperror_str_from_httputil tornado/test/web_test.py::RaiseWithReasonTest::test_raise_with_reason tornado/test/web_test.py::ErrorHandlerXSRFTest::test_404_xsrf tornado/test/web_test.py::ErrorHandlerXSRFTest::test_error_xsrf tornado/test/web_test.py::GzipTestCase::test_gzip tornado/test/web_test.py::GzipTestCase::test_gzip_not_requested tornado/test/web_test.py::GzipTestCase::test_gzip_static tornado/test/web_test.py::GzipTestCase::test_vary_already_present tornado/test/web_test.py::PathArgsInPrepareTest::test_kw tornado/test/web_test.py::PathArgsInPrepareTest::test_pos tornado/test/web_test.py::ClearAllCookiesTest::test_clear_all_cookies tornado/test/web_test.py::ExceptionHandlerTest::test_http_error tornado/test/web_test.py::ExceptionHandlerTest::test_known_error tornado/test/web_test.py::ExceptionHandlerTest::test_unknown_error tornado/test/web_test.py::BuggyLoggingTest::test_buggy_log_exception tornado/test/web_test.py::UIMethodUIModuleTest::test_ui_method tornado/test/web_test.py::GetArgumentErrorTest::test_catch_error tornado/test/web_test.py::MultipleExceptionTest::test_multi_exception tornado/test/web_test.py::SetLazyPropertiesTest::test_set_properties tornado/test/web_test.py::GetCurrentUserTest::test_get_current_user_from_ui_module_is_lazy tornado/test/web_test.py::GetCurrentUserTest::test_get_current_user_from_ui_module_works tornado/test/web_test.py::GetCurrentUserTest::test_get_current_user_works tornado/test/web_test.py::UnimplementedHTTPMethodsTest::test_unimplemented_standard_methods tornado/test/web_test.py::UnimplementedNonStandardMethodsTest::test_unimplemented_other tornado/test/web_test.py::UnimplementedNonStandardMethodsTest::test_unimplemented_patch tornado/test/web_test.py::AllHTTPMethodsTest::test_standard_methods tornado/test/web_test.py::PatchMethodTest::test_other tornado/test/web_test.py::PatchMethodTest::test_patch tornado/test/web_test.py::FinishInPrepareTest::test_finish_in_prepare tornado/test/web_test.py::Default404Test::test_404 tornado/test/web_test.py::Custom404Test::test_404 tornado/test/web_test.py::DefaultHandlerArgumentsTest::test_403 tornado/test/web_test.py::HandlerByNameTest::test_handler_by_name tornado/test/web_test.py::StreamingRequestBodyTest::test_close_during_upload tornado/test/web_test.py::StreamingRequestBodyTest::test_early_return tornado/test/web_test.py::StreamingRequestBodyTest::test_early_return_with_data tornado/test/web_test.py::StreamingRequestBodyTest::test_streaming_body tornado/test/web_test.py::DecoratedStreamingRequestFlowControlTest::test_flow_control_chunked_body tornado/test/web_test.py::DecoratedStreamingRequestFlowControlTest::test_flow_control_compressed_body tornado/test/web_test.py::DecoratedStreamingRequestFlowControlTest::test_flow_control_fixed_body tornado/test/web_test.py::NativeStreamingRequestFlowControlTest::test_flow_control_chunked_body tornado/test/web_test.py::NativeStreamingRequestFlowControlTest::test_flow_control_compressed_body tornado/test/web_test.py::NativeStreamingRequestFlowControlTest::test_flow_control_fixed_body tornado/test/web_test.py::IncorrectContentLengthTest::test_content_length_too_high tornado/test/web_test.py::IncorrectContentLengthTest::test_content_length_too_low tornado/test/web_test.py::ClientCloseTest::test_client_close tornado/test/web_test.py::SignedValueTest::test_expired tornado/test/web_test.py::SignedValueTest::test_key_version_retrieval tornado/test/web_test.py::SignedValueTest::test_key_versioning_invalid_key tornado/test/web_test.py::SignedValueTest::test_key_versioning_read_write_default_key tornado/test/web_test.py::SignedValueTest::test_key_versioning_read_write_non_default_key tornado/test/web_test.py::SignedValueTest::test_known_values tornado/test/web_test.py::SignedValueTest::test_name_swap tornado/test/web_test.py::SignedValueTest::test_non_ascii tornado/test/web_test.py::SignedValueTest::test_payload_tampering tornado/test/web_test.py::SignedValueTest::test_signature_tampering tornado/test/web_test.py::XSRFTest::test_cross_user tornado/test/web_test.py::XSRFTest::test_distinct_tokens tornado/test/web_test.py::XSRFTest::test_refresh_token tornado/test/web_test.py::XSRFTest::test_versioning tornado/test/web_test.py::XSRFTest::test_xsrf_fail_body_no_cookie tornado/test/web_test.py::XSRFTest::test_xsrf_fail_cookie_no_body tornado/test/web_test.py::XSRFTest::test_xsrf_fail_no_token tornado/test/web_test.py::XSRFTest::test_xsrf_success_header tornado/test/web_test.py::XSRFTest::test_xsrf_success_non_hex_token tornado/test/web_test.py::XSRFTest::test_xsrf_success_post_body tornado/test/web_test.py::XSRFTest::test_xsrf_success_query_string tornado/test/web_test.py::XSRFTest::test_xsrf_success_short_token tornado/test/web_test.py::XSRFCookieKwargsTest::test_xsrf_httponly tornado/test/web_test.py::FinishExceptionTest::test_finish_exception tornado/test/web_test.py::DecoratorTest::test_addslash tornado/test/web_test.py::DecoratorTest::test_removeslash tornado/test/web_test.py::CacheTest::test_multiple_strong_etag_match tornado/test/web_test.py::CacheTest::test_multiple_strong_etag_not_match tornado/test/web_test.py::CacheTest::test_multiple_weak_etag_match tornado/test/web_test.py::CacheTest::test_multiple_weak_etag_not_match tornado/test/web_test.py::CacheTest::test_strong_etag_match tornado/test/web_test.py::CacheTest::test_strong_etag_not_match tornado/test/web_test.py::CacheTest::test_weak_etag_match tornado/test/web_test.py::CacheTest::test_weak_etag_not_match tornado/test/web_test.py::CacheTest::test_wildcard_etag tornado/test/web_test.py::RequestSummaryTest::test_missing_remote_ip tornado/test/web_test.py::HTTPErrorTest::test_copy tornado/test/web_test.py::ApplicationTest::test_listen tornado/test/web_test.py::URLSpecReverseTest::test_reverse
tornado/web.py tornado/log.py tornado/http1connection.py tornado/httputil.py tornado/escape.py tornado/util.py
tornado/web.py tornado/log.py tornado/http1connection.py tornado/httputil.py tornado/escape.py tornado/util.py