{
    "file_diffs": [
        {
            "old_file_content": ".. currentmodule:: tornado.web\n\nOverview\n========\n\n`FriendFeed's <http://friendfeed.com/>`_ web server is a relatively\nsimple, non-blocking web server written in Python. The FriendFeed\napplication is written using a web framework that looks a bit like\n`web.py <http://webpy.org/>`_ or Google's\n`webapp <http://code.google.com/appengine/docs/python/tools/webapp/>`_,\nbut with additional tools and optimizations to take advantage of the\nnon-blocking web server and tools.\n\n`Tornado <https://github.com/tornadoweb/tornado>`_ is an open source\nversion of this web server and some of the tools we use most often at\nFriendFeed. The framework is distinct from most mainstream web server\nframeworks (and certainly most Python frameworks) because it is\nnon-blocking and reasonably fast. Because it is non-blocking and uses\n`epoll\n<http://www.kernel.org/doc/man-pages/online/pages/man4/epoll.4.html>`_\nor kqueue, it can handle thousands of simultaneous standing\nconnections, which means the framework is ideal for real-time web\nservices. We built the web server specifically to handle FriendFeed's\nreal-time features — every active user of FriendFeed maintains an open\nconnection to the FriendFeed servers. (For more information on scaling\nservers to support thousands of clients, see `The C10K problem\n<http://www.kegel.com/c10k.html>`_.)\n\nHere is the canonical \"Hello, world\" example app:\n\n::\n\n    import tornado.ioloop\n    import tornado.web\n\n    class MainHandler(tornado.web.RequestHandler):\n        def get(self):\n            self.write(\"Hello, world\")\n\n    application = tornado.web.Application([\n        (r\"/\", MainHandler),\n    ])\n\n    if __name__ == \"__main__\":\n        application.listen(8888)\n        tornado.ioloop.IOLoop.instance().start()\n\nWe attempted to clean up the code base to reduce interdependencies\nbetween modules, so you should (theoretically) be able to use any of the\nmodules independently in your project without using the whole package.\n\nRequest handlers and request arguments\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nA Tornado web application maps URLs or URL patterns to subclasses of\n`tornado.web.RequestHandler`. Those classes define ``get()`` or\n``post()`` methods to handle HTTP ``GET`` or ``POST`` requests to that\nURL.\n\nThis code maps the root URL ``/`` to ``MainHandler`` and the URL pattern\n``/story/([0-9]+)`` to ``StoryHandler``. Regular expression groups are\npassed as arguments to the ``RequestHandler`` methods:\n\n::\n\n    class MainHandler(tornado.web.RequestHandler):\n        def get(self):\n            self.write(\"You requested the main page\")\n\n    class StoryHandler(tornado.web.RequestHandler):\n        def get(self, story_id):\n            self.write(\"You requested the story \" + story_id)\n\n    application = tornado.web.Application([\n        (r\"/\", MainHandler),\n        (r\"/story/([0-9]+)\", StoryHandler),\n    ])\n\nYou can get query string arguments and parse ``POST`` bodies with the\n``get_argument()`` method:\n\n::\n\n    class MyFormHandler(tornado.web.RequestHandler):\n        def get(self):\n            self.write('<html><body><form action=\"/myform\" method=\"post\">'\n                       '<input type=\"text\" name=\"message\">'\n                       '<input type=\"submit\" value=\"Submit\">'\n                       '</form></body></html>')\n\n        def post(self):\n            self.set_header(\"Content-Type\", \"text/plain\")\n            self.write(\"You wrote \" + self.get_argument(\"message\"))\n\nUploaded files are available in ``self.request.files``, which maps names\n(the name of the HTML ``<input type=\"file\">`` element) to a list of\nfiles. Each file is a dictionary of the form\n``{\"filename\":..., \"content_type\":..., \"body\":...}``.\n\nIf you want to send an error response to the client, e.g., 403\nUnauthorized, you can just raise a ``tornado.web.HTTPError`` exception:\n\n::\n\n    if not self.user_is_logged_in():\n        raise tornado.web.HTTPError(403)\n\nThe request handler can access the object representing the current\nrequest with ``self.request``. The ``HTTPRequest`` object includes a\nnumber of useful attributes, including:\n\n-  ``arguments`` - all of the ``GET`` and ``POST`` arguments\n-  ``files`` - all of the uploaded files (via ``multipart/form-data``\n   POST requests)\n-  ``path`` - the request path (everything before the ``?``)\n-  ``headers`` - the request headers\n\nSee the class definition for `tornado.httputil.HTTPServerRequest` for a\ncomplete list of attributes.\n\nOverriding RequestHandler methods\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nIn addition to ``get()``/``post()``/etc, certain other methods in\n``RequestHandler`` are designed to be overridden by subclasses when\nnecessary. On every request, the following sequence of calls takes\nplace:\n\n1. A new RequestHandler object is created on each request\n2. ``initialize()`` is called with keyword arguments from the\n   ``Application`` configuration. (the ``initialize`` method is new in\n   Tornado 1.1; in older versions subclasses would override ``__init__``\n   instead). ``initialize`` should typically just save the arguments\n   passed into member variables; it may not produce any output or call\n   methods like ``send_error``.\n3. ``prepare()`` is called. This is most useful in a base class shared\n   by all of your handler subclasses, as ``prepare`` is called no matter\n   which HTTP method is used. ``prepare`` may produce output; if it\n   calls ``finish`` (or ``send_error``, etc), processing stops here.\n4. One of the HTTP methods is called: ``get()``, ``post()``, ``put()``,\n   etc. If the URL regular expression contains capturing groups, they\n   are passed as arguments to this method.\n5. When the request is finished, ``on_finish()`` is called.  For synchronous\n   handlers this is immediately after ``get()`` (etc) return; for\n   asynchronous handlers it is after the call to ``finish()``.\n\nHere is an example demonstrating the ``initialize()`` method:\n\n::\n\n    class ProfileHandler(RequestHandler):\n        def initialize(self, database):\n            self.database = database\n\n        def get(self, username):\n            ...\n\n    app = Application([\n        (r'/user/(.*)', ProfileHandler, dict(database=database)),\n        ])\n\nOther methods designed for overriding include:\n\n-  ``write_error(self, status_code, exc_info=None, **kwargs)`` -\n   outputs HTML for use on error pages.\n-  ``get_current_user(self)`` - see `User\n   Authentication <#user-authentication>`_ below\n-  ``get_user_locale(self)`` - returns ``locale`` object to use for the\n   current user\n-  ``get_login_url(self)`` - returns login url to be used by the\n   ``@authenticated`` decorator (default is in ``Application`` settings)\n-  ``get_template_path(self)`` - returns location of template files\n   (default is in ``Application`` settings)\n-  ``set_default_headers(self)`` - may be used to set additional headers\n   on the response (such as a custom ``Server`` header)\n\nError Handling\n~~~~~~~~~~~~~~\n\nThere are three ways to return an error from a `RequestHandler`:\n\n1. Manually call `~tornado.web.RequestHandler.set_status` and output the\n   response body normally.\n2. Call `~RequestHandler.send_error`.  This discards\n   any pending unflushed output and calls `~RequestHandler.write_error` to\n   generate an error page.\n3. Raise an exception.  `tornado.web.HTTPError` can be used to generate\n   a specified status code; all other exceptions return a 500 status.\n   The exception handler uses `~RequestHandler.send_error` and\n   `~RequestHandler.write_error` to generate the error page.\n\nThe default error page includes a stack trace in debug mode and a one-line\ndescription of the error (e.g. \"500: Internal Server Error\") otherwise.\nTo produce a custom error page, override `RequestHandler.write_error`.\nThis method may produce output normally via methods such as\n`~RequestHandler.write` and `~RequestHandler.render`.  If the error was\ncaused by an exception, an ``exc_info`` triple will be passed as a keyword\nargument (note that this exception is not guaranteed to be the current\nexception in ``sys.exc_info``, so ``write_error`` must use e.g.\n`traceback.format_exception` instead of `traceback.format_exc`).\n\nIn Tornado 2.0 and earlier, custom error pages were implemented by overriding\n``RequestHandler.get_error_html``, which returned the error page as a string\ninstead of calling the normal output methods (and had slightly different\nsemantics for exceptions).  This method is still supported, but it is\ndeprecated and applications are encouraged to switch to\n`RequestHandler.write_error`.\n\nRedirection\n~~~~~~~~~~~\n\nThere are two main ways you can redirect requests in Tornado:\n``self.redirect`` and with the ``RedirectHandler``.\n\nYou can use ``self.redirect`` within a ``RequestHandler`` method (like\n``get``) to redirect users elsewhere. There is also an optional\nparameter ``permanent`` which you can use to indicate that the\nredirection is considered permanent.\n\nThis triggers a ``301 Moved Permanently`` HTTP status, which is useful\nfor e.g. redirecting to a canonical URL for a page in an SEO-friendly\nmanner.\n\nThe default value of ``permanent`` is ``False``, which is apt for things\nlike redirecting users on successful POST requests.\n\n::\n\n    self.redirect('/some-canonical-page', permanent=True)\n\n``RedirectHandler`` is available for your use when you initialize\n``Application``.\n\nFor example, notice how we redirect to a longer download URL on this\nwebsite:\n\n::\n\n    application = tornado.wsgi.WSGIApplication([\n        (r\"/([a-z]*)\", ContentHandler),\n        (r\"/static/tornado-0.2.tar.gz\", tornado.web.RedirectHandler,\n         dict(url=\"https://github.com/downloads/facebook/tornado/tornado-0.2.tar.gz\")),\n    ], **settings)\n\nThe default ``RedirectHandler`` status code is\n``301 Moved Permanently``, but to use ``302 Found`` instead, set\n``permanent`` to ``False``.\n\n::\n\n    application = tornado.wsgi.WSGIApplication([\n        (r\"/foo\", tornado.web.RedirectHandler, {\"url\":\"/bar\", \"permanent\":False}),\n    ], **settings)\n\nNote that the default value of ``permanent`` is different in\n``self.redirect`` than in ``RedirectHandler``. This should make some\nsense if you consider that ``self.redirect`` is used in your methods and\nis probably invoked by logic involving environment, authentication, or\nform submission, but ``RedirectHandler`` patterns are going to fire 100%\nof the time they match the request URL.\n\nTemplates\n~~~~~~~~~\n\nYou can use any template language supported by Python, but Tornado ships\nwith its own templating language that is a lot faster and more flexible\nthan many of the most popular templating systems out there. See the\n`tornado.template` module documentation for complete documentation.\n\nA Tornado template is just HTML (or any other text-based format) with\nPython control sequences and expressions embedded within the markup:\n\n::\n\n    <html>\n       <head>\n          <title>{{ title }}</title>\n       </head>\n       <body>\n         <ul>\n           {% for item in items %}\n             <li>{{ escape(item) }}</li>\n           {% end %}\n         </ul>\n       </body>\n     </html>\n\nIf you saved this template as \"template.html\" and put it in the same\ndirectory as your Python file, you could render this template with:\n\n::\n\n    class MainHandler(tornado.web.RequestHandler):\n        def get(self):\n            items = [\"Item 1\", \"Item 2\", \"Item 3\"]\n            self.render(\"template.html\", title=\"My title\", items=items)\n\nTornado templates support *control statements* and *expressions*.\nControl statements are surronded by ``{%`` and ``%}``, e.g.,\n``{% if len(items) > 2 %}``. Expressions are surrounded by ``{{`` and\n``}}``, e.g., ``{{ items[0] }}``.\n\nControl statements more or less map exactly to Python statements. We\nsupport ``if``, ``for``, ``while``, and ``try``, all of which are\nterminated with ``{% end %}``. We also support *template inheritance*\nusing the ``extends`` and ``block`` statements, which are described in\ndetail in the documentation for the `tornado.template`.\n\nExpressions can be any Python expression, including function calls.\nTemplate code is executed in a namespace that includes the following\nobjects and functions (Note that this list applies to templates rendered\nusing ``RequestHandler.render`` and ``render_string``. If you're using\nthe ``template`` module directly outside of a ``RequestHandler`` many of\nthese entries are not present).\n\n-  ``escape``: alias for ``tornado.escape.xhtml_escape``\n-  ``xhtml_escape``: alias for ``tornado.escape.xhtml_escape``\n-  ``url_escape``: alias for ``tornado.escape.url_escape``\n-  ``json_encode``: alias for ``tornado.escape.json_encode``\n-  ``squeeze``: alias for ``tornado.escape.squeeze``\n-  ``linkify``: alias for ``tornado.escape.linkify``\n-  ``datetime``: the Python ``datetime`` module\n-  ``handler``: the current ``RequestHandler`` object\n-  ``request``: alias for ``handler.request``\n-  ``current_user``: alias for ``handler.current_user``\n-  ``locale``: alias for ``handler.locale``\n-  ``_``: alias for ``handler.locale.translate``\n-  ``static_url``: alias for ``handler.static_url``\n-  ``xsrf_form_html``: alias for ``handler.xsrf_form_html``\n-  ``reverse_url``: alias for ``Application.reverse_url``\n-  All entries from the ``ui_methods`` and ``ui_modules``\n   ``Application`` settings\n-  Any keyword arguments passed to ``render`` or ``render_string``\n\nWhen you are building a real application, you are going to want to use\nall of the features of Tornado templates, especially template\ninheritance. Read all about those features in the `tornado.template`\nsection (some features, including ``UIModules`` are implemented in the\n``web`` module)\n\nUnder the hood, Tornado templates are translated directly to Python. The\nexpressions you include in your template are copied verbatim into a\nPython function representing your template. We don't try to prevent\nanything in the template language; we created it explicitly to provide\nthe flexibility that other, stricter templating systems prevent.\nConsequently, if you write random stuff inside of your template\nexpressions, you will get random Python errors when you execute the\ntemplate.\n\nAll template output is escaped by default, using the\n``tornado.escape.xhtml_escape`` function. This behavior can be changed\nglobally by passing ``autoescape=None`` to the ``Application`` or\n``TemplateLoader`` constructors, for a template file with the\n``{% autoescape None %}`` directive, or for a single expression by\nreplacing ``{{ ... }}`` with ``{% raw ...%}``. Additionally, in each of\nthese places the name of an alternative escaping function may be used\ninstead of ``None``.\n\nNote that while Tornado's automatic escaping is helpful in avoiding\nXSS vulnerabilities, it is not sufficient in all cases.  Expressions\nthat appear in certain locations, such as in Javascript or CSS, may need\nadditional escaping.  Additionally, either care must be taken to always\nuse double quotes and ``xhtml_escape`` in HTML attributes that may contain\nuntrusted content, or a separate escaping function must be used for\nattributes (see e.g. http://wonko.com/post/html-escaping)\n\nCookies and secure cookies\n~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nYou can set cookies in the user's browser with the ``set_cookie``\nmethod:\n\n::\n\n    class MainHandler(tornado.web.RequestHandler):\n        def get(self):\n            if not self.get_cookie(\"mycookie\"):\n                self.set_cookie(\"mycookie\", \"myvalue\")\n                self.write(\"Your cookie was not set yet!\")\n            else:\n                self.write(\"Your cookie was set!\")\n\nCookies are easily forged by malicious clients. If you need to set\ncookies to, e.g., save the user ID of the currently logged in user, you\nneed to sign your cookies to prevent forgery. Tornado supports this out\nof the box with the ``set_secure_cookie`` and ``get_secure_cookie``\nmethods. To use these methods, you need to specify a secret key named\n``cookie_secret`` when you create your application. You can pass in\napplication settings as keyword arguments to your application:\n\n::\n\n    application = tornado.web.Application([\n        (r\"/\", MainHandler),\n    ], cookie_secret=\"__TODO:_GENERATE_YOUR_OWN_RANDOM_VALUE_HERE__\")\n\nSigned cookies contain the encoded value of the cookie in addition to a\ntimestamp and an `HMAC <http://en.wikipedia.org/wiki/HMAC>`_ signature.\nIf the cookie is old or if the signature doesn't match,\n``get_secure_cookie`` will return ``None`` just as if the cookie isn't\nset. The secure version of the example above:\n\n::\n\n    class MainHandler(tornado.web.RequestHandler):\n        def get(self):\n            if not self.get_secure_cookie(\"mycookie\"):\n                self.set_secure_cookie(\"mycookie\", \"myvalue\")\n                self.write(\"Your cookie was not set yet!\")\n            else:\n                self.write(\"Your cookie was set!\")\n\nUser authentication\n~~~~~~~~~~~~~~~~~~~\n\nThe currently authenticated user is available in every request handler\nas ``self.current_user``, and in every template as ``current_user``. By\ndefault, ``current_user`` is ``None``.\n\nTo implement user authentication in your application, you need to\noverride the ``get_current_user()`` method in your request handlers to\ndetermine the current user based on, e.g., the value of a cookie. Here\nis an example that lets users log into the application simply by\nspecifying a nickname, which is then saved in a cookie:\n\n::\n\n    class BaseHandler(tornado.web.RequestHandler):\n        def get_current_user(self):\n            return self.get_secure_cookie(\"user\")\n\n    class MainHandler(BaseHandler):\n        def get(self):\n            if not self.current_user:\n                self.redirect(\"/login\")\n                return\n            name = tornado.escape.xhtml_escape(self.current_user)\n            self.write(\"Hello, \" + name)\n\n    class LoginHandler(BaseHandler):\n        def get(self):\n            self.write('<html><body><form action=\"/login\" method=\"post\">'\n                       'Name: <input type=\"text\" name=\"name\">'\n                       '<input type=\"submit\" value=\"Sign in\">'\n                       '</form></body></html>')\n\n        def post(self):\n            self.set_secure_cookie(\"user\", self.get_argument(\"name\"))\n            self.redirect(\"/\")\n\n    application = tornado.web.Application([\n        (r\"/\", MainHandler),\n        (r\"/login\", LoginHandler),\n    ], cookie_secret=\"__TODO:_GENERATE_YOUR_OWN_RANDOM_VALUE_HERE__\")\n\nYou can require that the user be logged in using the `Python\ndecorator <http://www.python.org/dev/peps/pep-0318/>`_\n``tornado.web.authenticated``. If a request goes to a method with this\ndecorator, and the user is not logged in, they will be redirected to\n``login_url`` (another application setting). The example above could be\nrewritten:\n\n::\n\n    class MainHandler(BaseHandler):\n        @tornado.web.authenticated\n        def get(self):\n            name = tornado.escape.xhtml_escape(self.current_user)\n            self.write(\"Hello, \" + name)\n\n    settings = {\n        \"cookie_secret\": \"__TODO:_GENERATE_YOUR_OWN_RANDOM_VALUE_HERE__\",\n        \"login_url\": \"/login\",\n    }\n    application = tornado.web.Application([\n        (r\"/\", MainHandler),\n        (r\"/login\", LoginHandler),\n    ], **settings)\n\nIf you decorate ``post()`` methods with the ``authenticated`` decorator,\nand the user is not logged in, the server will send a ``403`` response.\n\nTornado comes with built-in support for third-party authentication\nschemes like Google OAuth. See the `tornado.auth`\nfor more details. Check out the `Tornado Blog example application <https://github.com/tornadoweb/tornado/tree/stable/demos/blog>`_ for a\ncomplete example that uses authentication (and stores user data in a\nMySQL database).\n\n.. _xsrf:\n\nCross-site request forgery protection\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n`Cross-site request\nforgery <http://en.wikipedia.org/wiki/Cross-site_request_forgery>`_, or\nXSRF, is a common problem for personalized web applications. See the\n`Wikipedia\narticle <http://en.wikipedia.org/wiki/Cross-site_request_forgery>`_ for\nmore information on how XSRF works.\n\nThe generally accepted solution to prevent XSRF is to cookie every user\nwith an unpredictable value and include that value as an additional\nargument with every form submission on your site. If the cookie and the\nvalue in the form submission do not match, then the request is likely\nforged.\n\nTornado comes with built-in XSRF protection. To include it in your site,\ninclude the application setting ``xsrf_cookies``:\n\n::\n\n    settings = {\n        \"cookie_secret\": \"__TODO:_GENERATE_YOUR_OWN_RANDOM_VALUE_HERE__\",\n        \"login_url\": \"/login\",\n        \"xsrf_cookies\": True,\n    }\n    application = tornado.web.Application([\n        (r\"/\", MainHandler),\n        (r\"/login\", LoginHandler),\n    ], **settings)\n\nIf ``xsrf_cookies`` is set, the Tornado web application will set the\n``_xsrf`` cookie for all users and reject all ``POST``, ``PUT``, and\n``DELETE`` requests that do not contain a correct ``_xsrf`` value. If\nyou turn this setting on, you need to instrument all forms that submit\nvia ``POST`` to contain this field. You can do this with the special\nfunction ``xsrf_form_html()``, available in all templates:\n\n::\n\n    <form action=\"/new_message\" method=\"post\">\n      {% module xsrf_form_html() %}\n      <input type=\"text\" name=\"message\"/>\n      <input type=\"submit\" value=\"Post\"/>\n    </form>\n\nIf you submit AJAX ``POST`` requests, you will also need to instrument\nyour JavaScript to include the ``_xsrf`` value with each request. This\nis the `jQuery <http://jquery.com/>`_ function we use at FriendFeed for\nAJAX ``POST`` requests that automatically adds the ``_xsrf`` value to\nall requests:\n\n::\n\n    function getCookie(name) {\n        var r = document.cookie.match(\"\\\\b\" + name + \"=([^;]*)\\\\b\");\n        return r ? r[1] : undefined;\n    }\n\n    jQuery.postJSON = function(url, args, callback) {\n        args._xsrf = getCookie(\"_xsrf\");\n        $.ajax({url: url, data: $.param(args), dataType: \"text\", type: \"POST\",\n            success: function(response) {\n            callback(eval(\"(\" + response + \")\"));\n        }});\n    };\n\nFor ``PUT`` and ``DELETE`` requests (as well as ``POST`` requests that\ndo not use form-encoded arguments), the XSRF token may also be passed\nvia an HTTP header named ``X-XSRFToken``.  The XSRF cookie is normally\nset when ``xsrf_form_html`` is used, but in a pure-Javascript application\nthat does not use any regular forms you may need to access\n``self.xsrf_token`` manually (just reading the property is enough to\nset the cookie as a side effect).\n\nIf you need to customize XSRF behavior on a per-handler basis, you can\noverride ``RequestHandler.check_xsrf_cookie()``. For example, if you\nhave an API whose authentication does not use cookies, you may want to\ndisable XSRF protection by making ``check_xsrf_cookie()`` do nothing.\nHowever, if you support both cookie and non-cookie-based authentication,\nit is important that XSRF protection be used whenever the current\nrequest is authenticated with a cookie.\n\nStatic files and aggressive file caching\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nYou can serve static files from Tornado by specifying the\n``static_path`` setting in your application:\n\n::\n\n    settings = {\n        \"static_path\": os.path.join(os.path.dirname(__file__), \"static\"),\n        \"cookie_secret\": \"__TODO:_GENERATE_YOUR_OWN_RANDOM_VALUE_HERE__\",\n        \"login_url\": \"/login\",\n        \"xsrf_cookies\": True,\n    }\n    application = tornado.web.Application([\n        (r\"/\", MainHandler),\n        (r\"/login\", LoginHandler),\n        (r\"/(apple-touch-icon\\.png)\", tornado.web.StaticFileHandler,\n         dict(path=settings['static_path'])),\n    ], **settings)\n\nThis setting will automatically make all requests that start with\n``/static/`` serve from that static directory, e.g.,\n`http://localhost:8888/static/foo.png <http://localhost:8888/static/foo.png>`_\nwill serve the file ``foo.png`` from the specified static directory. We\nalso automatically serve ``/robots.txt`` and ``/favicon.ico`` from the\nstatic directory (even though they don't start with the ``/static/``\nprefix).\n\nIn the above settings, we have explicitly configured Tornado to serve\n``apple-touch-icon.png`` “from” the root with the ``StaticFileHandler``,\nthough it is physically in the static file directory. (The capturing\ngroup in that regular expression is necessary to tell\n``StaticFileHandler`` the requested filename; capturing groups are\npassed to handlers as method arguments.) You could do the same thing to\nserve e.g. ``sitemap.xml`` from the site root. Of course, you can also\navoid faking a root ``apple-touch-icon.png`` by using the appropriate\n``<link />`` tag in your HTML.\n\nTo improve performance, it is generally a good idea for browsers to\ncache static resources aggressively so browsers won't send unnecessary\n``If-Modified-Since`` or ``Etag`` requests that might block the\nrendering of the page. Tornado supports this out of the box with *static\ncontent versioning*.\n\nTo use this feature, use the ``static_url()`` method in your templates\nrather than typing the URL of the static file directly in your HTML:\n\n::\n\n    <html>\n       <head>\n          <title>FriendFeed - {{ _(\"Home\") }}</title>\n       </head>\n       <body>\n         <div><img src=\"{{ static_url(\"images/logo.png\") }}\"/></div>\n       </body>\n     </html>\n\nThe ``static_url()`` function will translate that relative path to a URI\nthat looks like ``/static/images/logo.png?v=aae54``. The ``v`` argument\nis a hash of the content in ``logo.png``, and its presence makes the\nTornado server send cache headers to the user's browser that will make\nthe browser cache the content indefinitely.\n\nSince the ``v`` argument is based on the content of the file, if you\nupdate a file and restart your server, it will start sending a new ``v``\nvalue, so the user's browser will automatically fetch the new file. If\nthe file's contents don't change, the browser will continue to use a\nlocally cached copy without ever checking for updates on the server,\nsignificantly improving rendering performance.\n\nIn production, you probably want to serve static files from a more\noptimized static file server like `nginx <http://nginx.net/>`_. You can\nconfigure most any web server to support these caching semantics. Here\nis the nginx configuration we use at FriendFeed:\n\n::\n\n    location /static/ {\n        root /var/friendfeed/static;\n        if ($query_string) {\n            expires max;\n        }\n     }\n\nLocalization\n~~~~~~~~~~~~\n\nThe locale of the current user (whether they are logged in or not) is\nalways available as ``self.locale`` in the request handler and as\n``locale`` in templates. The name of the locale (e.g., ``en_US``) is\navailable as ``locale.name``, and you can translate strings with the\n``locale.translate`` method. Templates also have the global function\ncall ``_()`` available for string translation. The translate function\nhas two forms:\n\n::\n\n    _(\"Translate this string\")\n\nwhich translates the string directly based on the current locale, and\n\n::\n\n    _(\"A person liked this\", \"%(num)d people liked this\",\n      len(people)) % {\"num\": len(people)}\n\nwhich translates a string that can be singular or plural based on the\nvalue of the third argument. In the example above, a translation of the\nfirst string will be returned if ``len(people)`` is ``1``, or a\ntranslation of the second string will be returned otherwise.\n\nThe most common pattern for translations is to use Python named\nplaceholders for variables (the ``%(num)d`` in the example above) since\nplaceholders can move around on translation.\n\nHere is a properly localized template:\n\n::\n\n    <html>\n       <head>\n          <title>FriendFeed - {{ _(\"Sign in\") }}</title>\n       </head>\n       <body>\n         <form action=\"{{ request.path }}\" method=\"post\">\n           <div>{{ _(\"Username\") }} <input type=\"text\" name=\"username\"/></div>\n           <div>{{ _(\"Password\") }} <input type=\"password\" name=\"password\"/></div>\n           <div><input type=\"submit\" value=\"{{ _(\"Sign in\") }}\"/></div>\n           {% module xsrf_form_html() %}\n         </form>\n       </body>\n     </html>\n\nBy default, we detect the user's locale using the ``Accept-Language``\nheader sent by the user's browser. We choose ``en_US`` if we can't find\nan appropriate ``Accept-Language`` value. If you let user's set their\nlocale as a preference, you can override this default locale selection\nby overriding ``get_user_locale`` in your request handler:\n\n::\n\n    class BaseHandler(tornado.web.RequestHandler):\n        def get_current_user(self):\n            user_id = self.get_secure_cookie(\"user\")\n            if not user_id: return None\n            return self.backend.get_user_by_id(user_id)\n\n        def get_user_locale(self):\n            if \"locale\" not in self.current_user.prefs:\n                # Use the Accept-Language header\n                return None\n            return self.current_user.prefs[\"locale\"]\n\nIf ``get_user_locale`` returns ``None``, we fall back on the\n``Accept-Language`` header.\n\nYou can load all the translations for your application using the\n``tornado.locale.load_translations`` method. It takes in the name of the\ndirectory which should contain CSV files named after the locales whose\ntranslations they contain, e.g., ``es_GT.csv`` or ``fr_CA.csv``. The\nmethod loads all the translations from those CSV files and infers the\nlist of supported locales based on the presence of each CSV file. You\ntypically call this method once in the ``main()`` method of your server:\n\n::\n\n    def main():\n        tornado.locale.load_translations(\n            os.path.join(os.path.dirname(__file__), \"translations\"))\n        start_server()\n\nYou can get the list of supported locales in your application with\n``tornado.locale.get_supported_locales()``. The user's locale is chosen\nto be the closest match based on the supported locales. For example, if\nthe user's locale is ``es_GT``, and the ``es`` locale is supported,\n``self.locale`` will be ``es`` for that request. We fall back on\n``en_US`` if no close match can be found.\n\nSee the `tornado.locale`\ndocumentation for detailed information on the CSV format and other\nlocalization methods.\n\n.. _ui-modules:\n\nUI modules\n~~~~~~~~~~\n\nTornado supports *UI modules* to make it easy to support standard,\nreusable UI widgets across your application. UI modules are like special\nfunctional calls to render components of your page, and they can come\npackaged with their own CSS and JavaScript.\n\nFor example, if you are implementing a blog, and you want to have blog\nentries appear on both the blog home page and on each blog entry page,\nyou can make an ``Entry`` module to render them on both pages. First,\ncreate a Python module for your UI modules, e.g., ``uimodules.py``:\n\n::\n\n    class Entry(tornado.web.UIModule):\n        def render(self, entry, show_comments=False):\n            return self.render_string(\n                \"module-entry.html\", entry=entry, show_comments=show_comments)\n\nTell Tornado to use ``uimodules.py`` using the ``ui_modules`` setting in\nyour application:\n\n::\n\n    class HomeHandler(tornado.web.RequestHandler):\n        def get(self):\n            entries = self.db.query(\"SELECT * FROM entries ORDER BY date DESC\")\n            self.render(\"home.html\", entries=entries)\n\n    class EntryHandler(tornado.web.RequestHandler):\n        def get(self, entry_id):\n            entry = self.db.get(\"SELECT * FROM entries WHERE id = %s\", entry_id)\n            if not entry: raise tornado.web.HTTPError(404)\n            self.render(\"entry.html\", entry=entry)\n\n    settings = {\n        \"ui_modules\": uimodules,\n    }\n    application = tornado.web.Application([\n        (r\"/\", HomeHandler),\n        (r\"/entry/([0-9]+)\", EntryHandler),\n    ], **settings)\n\nWithin ``home.html``, you reference the ``Entry`` module rather than\nprinting the HTML directly:\n\n::\n\n    {% for entry in entries %}\n      {% module Entry(entry) %}\n    {% end %}\n\nWithin ``entry.html``, you reference the ``Entry`` module with the\n``show_comments`` argument to show the expanded form of the entry:\n\n::\n\n    {% module Entry(entry, show_comments=True) %}\n\nModules can include custom CSS and JavaScript functions by overriding\nthe ``embedded_css``, ``embedded_javascript``, ``javascript_files``, or\n``css_files`` methods:\n\n::\n\n    class Entry(tornado.web.UIModule):\n        def embedded_css(self):\n            return \".entry { margin-bottom: 1em; }\"\n\n        def render(self, entry, show_comments=False):\n            return self.render_string(\n                \"module-entry.html\", show_comments=show_comments)\n\nModule CSS and JavaScript will be included once no matter how many times\na module is used on a page. CSS is always included in the ``<head>`` of\nthe page, and JavaScript is always included just before the ``</body>``\ntag at the end of the page.\n\nWhen additional Python code is not required, a template file itself may\nbe used as a module. For example, the preceding example could be\nrewritten to put the following in ``module-entry.html``:\n\n::\n\n    {{ set_resources(embedded_css=\".entry { margin-bottom: 1em; }\") }}\n    <!-- more template html... -->\n\nThis revised template module would be invoked with\n\n::\n\n    {% module Template(\"module-entry.html\", show_comments=True) %}\n\nThe ``set_resources`` function is only available in templates invoked\nvia ``{% module Template(...) %}``. Unlike the ``{% include ... %}``\ndirective, template modules have a distinct namespace from their\ncontaining template - they can only see the global template namespace\nand their own keyword arguments.\n\nNon-blocking, asynchronous requests\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nWhen a request handler is executed, the request is automatically\nfinished. Since Tornado uses a non-blocking I/O style, you can override\nthis default behavior if you want a request to remain open after the\nmain request handler method returns using the\n``tornado.web.asynchronous`` decorator.\n\nWhen you use this decorator, it is your responsibility to call\n``self.finish()`` to finish the HTTP request, or the user's browser will\nsimply hang:\n\n::\n\n    class MainHandler(tornado.web.RequestHandler):\n        @tornado.web.asynchronous\n        def get(self):\n            self.write(\"Hello, world\")\n            self.finish()\n\nHere is a real example that makes a call to the FriendFeed API using\nTornado's built-in asynchronous HTTP client:\n\n::\n\n    class MainHandler(tornado.web.RequestHandler):\n        @tornado.web.asynchronous\n        def get(self):\n            http = tornado.httpclient.AsyncHTTPClient()\n            http.fetch(\"http://friendfeed-api.com/v2/feed/bret\",\n                       callback=self.on_response)\n\n        def on_response(self, response):\n            if response.error: raise tornado.web.HTTPError(500)\n            json = tornado.escape.json_decode(response.body)\n            self.write(\"Fetched \" + str(len(json[\"entries\"])) + \" entries \"\n                       \"from the FriendFeed API\")\n            self.finish()\n\nWhen ``get()`` returns, the request has not finished. When the HTTP\nclient eventually calls ``on_response()``, the request is still open,\nand the response is finally flushed to the client with the call to\n``self.finish()``.\n\nFor a more advanced asynchronous example, take a look at the `chat\nexample application\n<https://github.com/tornadoweb/tornado/tree/stable/demos/chat>`_, which\nimplements an AJAX chat room using `long polling\n<http://en.wikipedia.org/wiki/Push_technology#Long_polling>`_.  Users\nof long polling may want to override ``on_connection_close()`` to\nclean up after the client closes the connection (but see that method's\ndocstring for caveats).\n\nAsynchronous HTTP clients\n~~~~~~~~~~~~~~~~~~~~~~~~~\n\nTornado includes two non-blocking HTTP client implementations:\n``SimpleAsyncHTTPClient`` and ``CurlAsyncHTTPClient``. The simple client\nhas no external dependencies because it is implemented directly on top\nof Tornado's ``IOLoop``. The Curl client requires that ``libcurl`` and\n``pycurl`` be installed (and a recent version of each is highly\nrecommended to avoid bugs in older version's asynchronous interfaces),\nbut is more likely to be compatible with sites that exercise little-used\nparts of the HTTP specification.\n\nEach of these clients is available in its own module\n(``tornado.simple_httpclient`` and ``tornado.curl_httpclient``), as well\nas via a configurable alias in ``tornado.httpclient``.\n``SimpleAsyncHTTPClient`` is the default, but to use a different\nimplementation call the ``AsyncHTTPClient.configure`` method at startup:\n\n::\n\n    AsyncHTTPClient.configure('tornado.curl_httpclient.CurlAsyncHTTPClient')\n\nThird party authentication\n~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nTornado's ``auth`` module implements the authentication and\nauthorization protocols for a number of the most popular sites on the\nweb, including Google/Gmail, Facebook, Twitter, and FriendFeed.\nThe module includes methods to log users in via these sites and, where\napplicable, methods to authorize access to the service so you can, e.g.,\ndownload a user's address book or publish a Twitter message on their\nbehalf.\n\nHere is an example handler that uses Google for authentication, saving\nthe Google credentials in a cookie for later access:\n\n::\n\n    class GoogleHandler(tornado.web.RequestHandler, tornado.auth.GoogleMixin):\n        @tornado.web.asynchronous\n        def get(self):\n            if self.get_argument(\"openid.mode\", None):\n                self.get_authenticated_user(self._on_auth)\n                return\n            self.authenticate_redirect()\n\n        def _on_auth(self, user):\n            if not user:\n                self.authenticate_redirect()\n                return\n            # Save the user with, e.g., set_secure_cookie()\n\nSee the `tornado.auth` module documentation for more details.\n\n.. _debug-mode:\n\nDebug mode and automatic reloading\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nIf you pass ``debug=True`` to the ``Application`` constructor, the app\nwill be run in debug/development mode. In this mode, several features\nintended for convenience while developing will be enabled (each of which\nis also available as an individual flag; if both are specified the\nindividual flag takes precedence):\n\n* ``autoreload=True``: The app will watch for changes to its source\n  files and reload itself when anything changes. This reduces the need\n  to manually restart the server during development. However, certain\n  failures (such as syntax errors at import time) can still take the\n  server down in a way that debug mode cannot currently recover from.\n* ``compiled_template_cache=False``: Templates will not be cached.\n* ``static_hash_cache=False``: Static file hashes (used by the\n  ``static_url`` function) will not be cached\n* ``serve_traceback=True``: When an exception in a ``RequestHandler``\n  is not caught, an error page including a stack trace will be\n  generated.\n\nAutoreload mode is not compatible with the multi-process mode of ``HTTPServer``.\nYou must not give ``HTTPServer.start`` an argument other than 1 (or\ncall `tornado.process.fork_processes`) if you are using autoreload mode.\n\nThe automatic reloading feature of debug mode is available as a\nstandalone module in ``tornado.autoreload``.  The two can be used in\ncombination to provide extra robustness against syntax errors: set\n``autoreload=True`` within the app to detect changes while it is running,\nand start it with ``python -m tornado.autoreload myserver.py`` to catch\nany syntax errors or other errors at startup.\n\nReloading loses any Python interpreter command-line arguments (e.g. ``-u``)\nbecause it re-executes Python using ``sys.executable`` and ``sys.argv``.\nAdditionally, modifying these variables will cause reloading to behave\nincorrectly.\n\nOn some platforms (including Windows and Mac OSX prior to 10.6), the\nprocess cannot be updated \"in-place\", so when a code change is\ndetected the old server exits and a new one starts.  This has been\nknown to confuse some IDEs.\n\n\nRunning Tornado in production\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nAt FriendFeed, we use `nginx <http://nginx.net/>`_ as a load balancer\nand static file server. We run multiple instances of the Tornado web\nserver on multiple frontend machines. We typically run one Tornado\nfrontend per core on the machine (sometimes more depending on\nutilization).\n\nWhen running behind a load balancer like nginx, it is recommended to\npass ``xheaders=True`` to the ``HTTPServer`` constructor. This will tell\nTornado to use headers like ``X-Real-IP`` to get the user's IP address\ninstead of attributing all traffic to the balancer's IP address.\n\nThis is a barebones nginx config file that is structurally similar to\nthe one we use at FriendFeed. It assumes nginx and the Tornado servers\nare running on the same machine, and the four Tornado servers are\nrunning on ports 8000 - 8003:\n\n::\n\n    user nginx;\n    worker_processes 1;\n\n    error_log /var/log/nginx/error.log;\n    pid /var/run/nginx.pid;\n\n    events {\n        worker_connections 1024;\n        use epoll;\n    }\n\n    http {\n        # Enumerate all the Tornado servers here\n        upstream frontends {\n            server 127.0.0.1:8000;\n            server 127.0.0.1:8001;\n            server 127.0.0.1:8002;\n            server 127.0.0.1:8003;\n        }\n\n        include /etc/nginx/mime.types;\n        default_type application/octet-stream;\n\n        access_log /var/log/nginx/access.log;\n\n        keepalive_timeout 65;\n        proxy_read_timeout 200;\n        sendfile on;\n        tcp_nopush on;\n        tcp_nodelay on;\n        gzip on;\n        gzip_min_length 1000;\n        gzip_proxied any;\n        gzip_types text/plain text/html text/css text/xml\n                   application/x-javascript application/xml\n                   application/atom+xml text/javascript;\n\n        # Only retry if there was a communication error, not a timeout\n        # on the Tornado server (to avoid propagating \"queries of death\"\n        # to all frontends)\n        proxy_next_upstream error;\n\n        server {\n            listen 80;\n\n            # Allow file uploads\n            client_max_body_size 50M;\n\n            location ^~ /static/ {\n                root /var/www;\n                if ($query_string) {\n                    expires max;\n                }\n            }\n            location = /favicon.ico {\n                rewrite (.*) /static/favicon.ico;\n            }\n            location = /robots.txt {\n                rewrite (.*) /static/robots.txt;\n            }\n\n            location / {\n                proxy_pass_header Server;\n                proxy_set_header Host $http_host;\n                proxy_redirect off;\n                proxy_set_header X-Real-IP $remote_addr;\n                proxy_set_header X-Scheme $scheme;\n                proxy_pass http://frontends;\n            }\n        }\n    }\n\nWSGI and Google AppEngine\n~~~~~~~~~~~~~~~~~~~~~~~~~\n\nTornado comes with limited support for `WSGI <http://wsgi.org/>`_.\nHowever, since WSGI does not support non-blocking requests, you cannot\nuse any of the asynchronous/non-blocking features of Tornado in your\napplication if you choose to use WSGI instead of Tornado's HTTP server.\nSome of the features that are not available in WSGI applications:\n``@tornado.web.asynchronous``, the ``httpclient`` module, and the\n``auth`` module.\n\nYou can create a valid WSGI application from your Tornado request\nhandlers by using ``WSGIApplication`` in the ``wsgi`` module instead of\nusing ``tornado.web.Application``. Here is an example that uses the\nbuilt-in WSGI ``CGIHandler`` to make a valid `Google\nAppEngine <http://code.google.com/appengine/>`_ application:\n\n::\n\n    import tornado.web\n    import tornado.wsgi\n    import wsgiref.handlers\n\n    class MainHandler(tornado.web.RequestHandler):\n        def get(self):\n            self.write(\"Hello, world\")\n\n    if __name__ == \"__main__\":\n        application = tornado.wsgi.WSGIApplication([\n            (r\"/\", MainHandler),\n        ])\n        wsgiref.handlers.CGIHandler().run(application)\n\nSee the `appengine example application\n<https://github.com/tornadoweb/tornado/tree/stable/demos/appengine>`_ for a\nfull-featured AppEngine app built on Tornado.\n",
            "new_file_content": ".. currentmodule:: tornado.web\n\nOverview\n========\n\n`FriendFeed's <http://friendfeed.com/>`_ web server is a relatively\nsimple, non-blocking web server written in Python. The FriendFeed\napplication is written using a web framework that looks a bit like\n`web.py <http://webpy.org/>`_ or Google's\n`webapp <http://code.google.com/appengine/docs/python/tools/webapp/>`_,\nbut with additional tools and optimizations to take advantage of the\nnon-blocking web server and tools.\n\n`Tornado <https://github.com/tornadoweb/tornado>`_ is an open source\nversion of this web server and some of the tools we use most often at\nFriendFeed. The framework is distinct from most mainstream web server\nframeworks (and certainly most Python frameworks) because it is\nnon-blocking and reasonably fast. Because it is non-blocking and uses\n`epoll\n<http://www.kernel.org/doc/man-pages/online/pages/man4/epoll.4.html>`_\nor kqueue, it can handle thousands of simultaneous standing\nconnections, which means the framework is ideal for real-time web\nservices. We built the web server specifically to handle FriendFeed's\nreal-time features — every active user of FriendFeed maintains an open\nconnection to the FriendFeed servers. (For more information on scaling\nservers to support thousands of clients, see `The C10K problem\n<http://www.kegel.com/c10k.html>`_.)\n\nHere is the canonical \"Hello, world\" example app:\n\n::\n\n    import tornado.ioloop\n    import tornado.web\n\n    class MainHandler(tornado.web.RequestHandler):\n        def get(self):\n            self.write(\"Hello, world\")\n\n    application = tornado.web.Application([\n        (r\"/\", MainHandler),\n    ])\n\n    if __name__ == \"__main__\":\n        application.listen(8888)\n        tornado.ioloop.IOLoop.instance().start()\n\nWe attempted to clean up the code base to reduce interdependencies\nbetween modules, so you should (theoretically) be able to use any of the\nmodules independently in your project without using the whole package.\n\nRequest handlers and request arguments\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nA Tornado web application maps URLs or URL patterns to subclasses of\n`tornado.web.RequestHandler`. Those classes define ``get()`` or\n``post()`` methods to handle HTTP ``GET`` or ``POST`` requests to that\nURL.\n\nThis code maps the root URL ``/`` to ``MainHandler`` and the URL pattern\n``/story/([0-9]+)`` to ``StoryHandler``. Regular expression groups are\npassed as arguments to the ``RequestHandler`` methods:\n\n::\n\n    class MainHandler(tornado.web.RequestHandler):\n        def get(self):\n            self.write(\"You requested the main page\")\n\n    class StoryHandler(tornado.web.RequestHandler):\n        def get(self, story_id):\n            self.write(\"You requested the story \" + story_id)\n\n    application = tornado.web.Application([\n        (r\"/\", MainHandler),\n        (r\"/story/([0-9]+)\", StoryHandler),\n    ])\n\nYou can get query string arguments and parse ``POST`` bodies with the\n``get_argument()`` method:\n\n::\n\n    class MyFormHandler(tornado.web.RequestHandler):\n        def get(self):\n            self.write('<html><body><form action=\"/myform\" method=\"post\">'\n                       '<input type=\"text\" name=\"message\">'\n                       '<input type=\"submit\" value=\"Submit\">'\n                       '</form></body></html>')\n\n        def post(self):\n            self.set_header(\"Content-Type\", \"text/plain\")\n            self.write(\"You wrote \" + self.get_argument(\"message\"))\n\nUploaded files are available in ``self.request.files``, which maps names\n(the name of the HTML ``<input type=\"file\">`` element) to a list of\nfiles. Each file is a dictionary of the form\n``{\"filename\":..., \"content_type\":..., \"body\":...}``.\n\nIf you want to send an error response to the client, e.g., 403\nUnauthorized, you can just raise a ``tornado.web.HTTPError`` exception:\n\n::\n\n    if not self.user_is_logged_in():\n        raise tornado.web.HTTPError(403)\n\nThe request handler can access the object representing the current\nrequest with ``self.request``. The ``HTTPRequest`` object includes a\nnumber of useful attributes, including:\n\n-  ``arguments`` - all of the ``GET`` and ``POST`` arguments\n-  ``files`` - all of the uploaded files (via ``multipart/form-data``\n   POST requests)\n-  ``path`` - the request path (everything before the ``?``)\n-  ``headers`` - the request headers\n\nSee the class definition for `tornado.httputil.HTTPServerRequest` for a\ncomplete list of attributes.\n\nOverriding RequestHandler methods\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nIn addition to ``get()``/``post()``/etc, certain other methods in\n``RequestHandler`` are designed to be overridden by subclasses when\nnecessary. On every request, the following sequence of calls takes\nplace:\n\n1. A new RequestHandler object is created on each request\n2. ``initialize()`` is called with keyword arguments from the\n   ``Application`` configuration. (the ``initialize`` method is new in\n   Tornado 1.1; in older versions subclasses would override ``__init__``\n   instead). ``initialize`` should typically just save the arguments\n   passed into member variables; it may not produce any output or call\n   methods like ``send_error``.\n3. ``prepare()`` is called. This is most useful in a base class shared\n   by all of your handler subclasses, as ``prepare`` is called no matter\n   which HTTP method is used. ``prepare`` may produce output; if it\n   calls ``finish`` (or ``send_error``, etc), processing stops here.\n4. One of the HTTP methods is called: ``get()``, ``post()``, ``put()``,\n   etc. If the URL regular expression contains capturing groups, they\n   are passed as arguments to this method.\n5. When the request is finished, ``on_finish()`` is called.  For synchronous\n   handlers this is immediately after ``get()`` (etc) return; for\n   asynchronous handlers it is after the call to ``finish()``.\n\nHere is an example demonstrating the ``initialize()`` method:\n\n::\n\n    class ProfileHandler(RequestHandler):\n        def initialize(self, database):\n            self.database = database\n\n        def get(self, username):\n            ...\n\n    app = Application([\n        (r'/user/(.*)', ProfileHandler, dict(database=database)),\n        ])\n\nOther methods designed for overriding include:\n\n-  ``write_error(self, status_code, exc_info=None, **kwargs)`` -\n   outputs HTML for use on error pages.\n-  ``get_current_user(self)`` - see `User\n   Authentication <#user-authentication>`_ below\n-  ``get_user_locale(self)`` - returns ``locale`` object to use for the\n   current user\n-  ``get_login_url(self)`` - returns login url to be used by the\n   ``@authenticated`` decorator (default is in ``Application`` settings)\n-  ``get_template_path(self)`` - returns location of template files\n   (default is in ``Application`` settings)\n-  ``set_default_headers(self)`` - may be used to set additional headers\n   on the response (such as a custom ``Server`` header)\n\nError Handling\n~~~~~~~~~~~~~~\n\nThere are three ways to return an error from a `RequestHandler`:\n\n1. Manually call `~tornado.web.RequestHandler.set_status` and output the\n   response body normally.\n2. Call `~RequestHandler.send_error`.  This discards\n   any pending unflushed output and calls `~RequestHandler.write_error` to\n   generate an error page.\n3. Raise an exception.  `tornado.web.HTTPError` can be used to generate\n   a specified status code; all other exceptions return a 500 status.\n   The exception handler uses `~RequestHandler.send_error` and\n   `~RequestHandler.write_error` to generate the error page.\n\nThe default error page includes a stack trace in debug mode and a one-line\ndescription of the error (e.g. \"500: Internal Server Error\") otherwise.\nTo produce a custom error page, override `RequestHandler.write_error`.\nThis method may produce output normally via methods such as\n`~RequestHandler.write` and `~RequestHandler.render`.  If the error was\ncaused by an exception, an ``exc_info`` triple will be passed as a keyword\nargument (note that this exception is not guaranteed to be the current\nexception in ``sys.exc_info``, so ``write_error`` must use e.g.\n`traceback.format_exception` instead of `traceback.format_exc`).\n\nIn Tornado 2.0 and earlier, custom error pages were implemented by overriding\n``RequestHandler.get_error_html``, which returned the error page as a string\ninstead of calling the normal output methods (and had slightly different\nsemantics for exceptions).  This method is still supported, but it is\ndeprecated and applications are encouraged to switch to\n`RequestHandler.write_error`.\n\nRedirection\n~~~~~~~~~~~\n\nThere are two main ways you can redirect requests in Tornado:\n``self.redirect`` and with the ``RedirectHandler``.\n\nYou can use ``self.redirect`` within a ``RequestHandler`` method (like\n``get``) to redirect users elsewhere. There is also an optional\nparameter ``permanent`` which you can use to indicate that the\nredirection is considered permanent.\n\nThis triggers a ``301 Moved Permanently`` HTTP status, which is useful\nfor e.g. redirecting to a canonical URL for a page in an SEO-friendly\nmanner.\n\nThe default value of ``permanent`` is ``False``, which is apt for things\nlike redirecting users on successful POST requests.\n\n::\n\n    self.redirect('/some-canonical-page', permanent=True)\n\n``RedirectHandler`` is available for your use when you initialize\n``Application``.\n\nFor example, notice how we redirect to a longer download URL on this\nwebsite:\n\n::\n\n    application = tornado.wsgi.WSGIApplication([\n        (r\"/([a-z]*)\", ContentHandler),\n        (r\"/static/tornado-0.2.tar.gz\", tornado.web.RedirectHandler,\n         dict(url=\"https://github.com/downloads/facebook/tornado/tornado-0.2.tar.gz\")),\n    ], **settings)\n\nThe default ``RedirectHandler`` status code is\n``301 Moved Permanently``, but to use ``302 Found`` instead, set\n``permanent`` to ``False``.\n\n::\n\n    application = tornado.wsgi.WSGIApplication([\n        (r\"/foo\", tornado.web.RedirectHandler, {\"url\":\"/bar\", \"permanent\":False}),\n    ], **settings)\n\nNote that the default value of ``permanent`` is different in\n``self.redirect`` than in ``RedirectHandler``. This should make some\nsense if you consider that ``self.redirect`` is used in your methods and\nis probably invoked by logic involving environment, authentication, or\nform submission, but ``RedirectHandler`` patterns are going to fire 100%\nof the time they match the request URL.\n\nTemplates\n~~~~~~~~~\n\nYou can use any template language supported by Python, but Tornado ships\nwith its own templating language that is a lot faster and more flexible\nthan many of the most popular templating systems out there. See the\n`tornado.template` module documentation for complete documentation.\n\nA Tornado template is just HTML (or any other text-based format) with\nPython control sequences and expressions embedded within the markup:\n\n::\n\n    <html>\n       <head>\n          <title>{{ title }}</title>\n       </head>\n       <body>\n         <ul>\n           {% for item in items %}\n             <li>{{ escape(item) }}</li>\n           {% end %}\n         </ul>\n       </body>\n     </html>\n\nIf you saved this template as \"template.html\" and put it in the same\ndirectory as your Python file, you could render this template with:\n\n::\n\n    class MainHandler(tornado.web.RequestHandler):\n        def get(self):\n            items = [\"Item 1\", \"Item 2\", \"Item 3\"]\n            self.render(\"template.html\", title=\"My title\", items=items)\n\nTornado templates support *control statements* and *expressions*.\nControl statements are surrounded by ``{%`` and ``%}``, e.g.,\n``{% if len(items) > 2 %}``. Expressions are surrounded by ``{{`` and\n``}}``, e.g., ``{{ items[0] }}``.\n\nControl statements more or less map exactly to Python statements. We\nsupport ``if``, ``for``, ``while``, and ``try``, all of which are\nterminated with ``{% end %}``. We also support *template inheritance*\nusing the ``extends`` and ``block`` statements, which are described in\ndetail in the documentation for the `tornado.template`.\n\nExpressions can be any Python expression, including function calls.\nTemplate code is executed in a namespace that includes the following\nobjects and functions (Note that this list applies to templates rendered\nusing ``RequestHandler.render`` and ``render_string``. If you're using\nthe ``template`` module directly outside of a ``RequestHandler`` many of\nthese entries are not present).\n\n-  ``escape``: alias for ``tornado.escape.xhtml_escape``\n-  ``xhtml_escape``: alias for ``tornado.escape.xhtml_escape``\n-  ``url_escape``: alias for ``tornado.escape.url_escape``\n-  ``json_encode``: alias for ``tornado.escape.json_encode``\n-  ``squeeze``: alias for ``tornado.escape.squeeze``\n-  ``linkify``: alias for ``tornado.escape.linkify``\n-  ``datetime``: the Python ``datetime`` module\n-  ``handler``: the current ``RequestHandler`` object\n-  ``request``: alias for ``handler.request``\n-  ``current_user``: alias for ``handler.current_user``\n-  ``locale``: alias for ``handler.locale``\n-  ``_``: alias for ``handler.locale.translate``\n-  ``static_url``: alias for ``handler.static_url``\n-  ``xsrf_form_html``: alias for ``handler.xsrf_form_html``\n-  ``reverse_url``: alias for ``Application.reverse_url``\n-  All entries from the ``ui_methods`` and ``ui_modules``\n   ``Application`` settings\n-  Any keyword arguments passed to ``render`` or ``render_string``\n\nWhen you are building a real application, you are going to want to use\nall of the features of Tornado templates, especially template\ninheritance. Read all about those features in the `tornado.template`\nsection (some features, including ``UIModules`` are implemented in the\n``web`` module)\n\nUnder the hood, Tornado templates are translated directly to Python. The\nexpressions you include in your template are copied verbatim into a\nPython function representing your template. We don't try to prevent\nanything in the template language; we created it explicitly to provide\nthe flexibility that other, stricter templating systems prevent.\nConsequently, if you write random stuff inside of your template\nexpressions, you will get random Python errors when you execute the\ntemplate.\n\nAll template output is escaped by default, using the\n``tornado.escape.xhtml_escape`` function. This behavior can be changed\nglobally by passing ``autoescape=None`` to the ``Application`` or\n``TemplateLoader`` constructors, for a template file with the\n``{% autoescape None %}`` directive, or for a single expression by\nreplacing ``{{ ... }}`` with ``{% raw ...%}``. Additionally, in each of\nthese places the name of an alternative escaping function may be used\ninstead of ``None``.\n\nNote that while Tornado's automatic escaping is helpful in avoiding\nXSS vulnerabilities, it is not sufficient in all cases.  Expressions\nthat appear in certain locations, such as in Javascript or CSS, may need\nadditional escaping.  Additionally, either care must be taken to always\nuse double quotes and ``xhtml_escape`` in HTML attributes that may contain\nuntrusted content, or a separate escaping function must be used for\nattributes (see e.g. http://wonko.com/post/html-escaping)\n\nCookies and secure cookies\n~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nYou can set cookies in the user's browser with the ``set_cookie``\nmethod:\n\n::\n\n    class MainHandler(tornado.web.RequestHandler):\n        def get(self):\n            if not self.get_cookie(\"mycookie\"):\n                self.set_cookie(\"mycookie\", \"myvalue\")\n                self.write(\"Your cookie was not set yet!\")\n            else:\n                self.write(\"Your cookie was set!\")\n\nCookies are easily forged by malicious clients. If you need to set\ncookies to, e.g., save the user ID of the currently logged in user, you\nneed to sign your cookies to prevent forgery. Tornado supports this out\nof the box with the ``set_secure_cookie`` and ``get_secure_cookie``\nmethods. To use these methods, you need to specify a secret key named\n``cookie_secret`` when you create your application. You can pass in\napplication settings as keyword arguments to your application:\n\n::\n\n    application = tornado.web.Application([\n        (r\"/\", MainHandler),\n    ], cookie_secret=\"__TODO:_GENERATE_YOUR_OWN_RANDOM_VALUE_HERE__\")\n\nSigned cookies contain the encoded value of the cookie in addition to a\ntimestamp and an `HMAC <http://en.wikipedia.org/wiki/HMAC>`_ signature.\nIf the cookie is old or if the signature doesn't match,\n``get_secure_cookie`` will return ``None`` just as if the cookie isn't\nset. The secure version of the example above:\n\n::\n\n    class MainHandler(tornado.web.RequestHandler):\n        def get(self):\n            if not self.get_secure_cookie(\"mycookie\"):\n                self.set_secure_cookie(\"mycookie\", \"myvalue\")\n                self.write(\"Your cookie was not set yet!\")\n            else:\n                self.write(\"Your cookie was set!\")\n\nUser authentication\n~~~~~~~~~~~~~~~~~~~\n\nThe currently authenticated user is available in every request handler\nas ``self.current_user``, and in every template as ``current_user``. By\ndefault, ``current_user`` is ``None``.\n\nTo implement user authentication in your application, you need to\noverride the ``get_current_user()`` method in your request handlers to\ndetermine the current user based on, e.g., the value of a cookie. Here\nis an example that lets users log into the application simply by\nspecifying a nickname, which is then saved in a cookie:\n\n::\n\n    class BaseHandler(tornado.web.RequestHandler):\n        def get_current_user(self):\n            return self.get_secure_cookie(\"user\")\n\n    class MainHandler(BaseHandler):\n        def get(self):\n            if not self.current_user:\n                self.redirect(\"/login\")\n                return\n            name = tornado.escape.xhtml_escape(self.current_user)\n            self.write(\"Hello, \" + name)\n\n    class LoginHandler(BaseHandler):\n        def get(self):\n            self.write('<html><body><form action=\"/login\" method=\"post\">'\n                       'Name: <input type=\"text\" name=\"name\">'\n                       '<input type=\"submit\" value=\"Sign in\">'\n                       '</form></body></html>')\n\n        def post(self):\n            self.set_secure_cookie(\"user\", self.get_argument(\"name\"))\n            self.redirect(\"/\")\n\n    application = tornado.web.Application([\n        (r\"/\", MainHandler),\n        (r\"/login\", LoginHandler),\n    ], cookie_secret=\"__TODO:_GENERATE_YOUR_OWN_RANDOM_VALUE_HERE__\")\n\nYou can require that the user be logged in using the `Python\ndecorator <http://www.python.org/dev/peps/pep-0318/>`_\n``tornado.web.authenticated``. If a request goes to a method with this\ndecorator, and the user is not logged in, they will be redirected to\n``login_url`` (another application setting). The example above could be\nrewritten:\n\n::\n\n    class MainHandler(BaseHandler):\n        @tornado.web.authenticated\n        def get(self):\n            name = tornado.escape.xhtml_escape(self.current_user)\n            self.write(\"Hello, \" + name)\n\n    settings = {\n        \"cookie_secret\": \"__TODO:_GENERATE_YOUR_OWN_RANDOM_VALUE_HERE__\",\n        \"login_url\": \"/login\",\n    }\n    application = tornado.web.Application([\n        (r\"/\", MainHandler),\n        (r\"/login\", LoginHandler),\n    ], **settings)\n\nIf you decorate ``post()`` methods with the ``authenticated`` decorator,\nand the user is not logged in, the server will send a ``403`` response.\n\nTornado comes with built-in support for third-party authentication\nschemes like Google OAuth. See the `tornado.auth`\nfor more details. Check out the `Tornado Blog example application <https://github.com/tornadoweb/tornado/tree/stable/demos/blog>`_ for a\ncomplete example that uses authentication (and stores user data in a\nMySQL database).\n\n.. _xsrf:\n\nCross-site request forgery protection\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n`Cross-site request\nforgery <http://en.wikipedia.org/wiki/Cross-site_request_forgery>`_, or\nXSRF, is a common problem for personalized web applications. See the\n`Wikipedia\narticle <http://en.wikipedia.org/wiki/Cross-site_request_forgery>`_ for\nmore information on how XSRF works.\n\nThe generally accepted solution to prevent XSRF is to cookie every user\nwith an unpredictable value and include that value as an additional\nargument with every form submission on your site. If the cookie and the\nvalue in the form submission do not match, then the request is likely\nforged.\n\nTornado comes with built-in XSRF protection. To include it in your site,\ninclude the application setting ``xsrf_cookies``:\n\n::\n\n    settings = {\n        \"cookie_secret\": \"__TODO:_GENERATE_YOUR_OWN_RANDOM_VALUE_HERE__\",\n        \"login_url\": \"/login\",\n        \"xsrf_cookies\": True,\n    }\n    application = tornado.web.Application([\n        (r\"/\", MainHandler),\n        (r\"/login\", LoginHandler),\n    ], **settings)\n\nIf ``xsrf_cookies`` is set, the Tornado web application will set the\n``_xsrf`` cookie for all users and reject all ``POST``, ``PUT``, and\n``DELETE`` requests that do not contain a correct ``_xsrf`` value. If\nyou turn this setting on, you need to instrument all forms that submit\nvia ``POST`` to contain this field. You can do this with the special\nfunction ``xsrf_form_html()``, available in all templates:\n\n::\n\n    <form action=\"/new_message\" method=\"post\">\n      {% module xsrf_form_html() %}\n      <input type=\"text\" name=\"message\"/>\n      <input type=\"submit\" value=\"Post\"/>\n    </form>\n\nIf you submit AJAX ``POST`` requests, you will also need to instrument\nyour JavaScript to include the ``_xsrf`` value with each request. This\nis the `jQuery <http://jquery.com/>`_ function we use at FriendFeed for\nAJAX ``POST`` requests that automatically adds the ``_xsrf`` value to\nall requests:\n\n::\n\n    function getCookie(name) {\n        var r = document.cookie.match(\"\\\\b\" + name + \"=([^;]*)\\\\b\");\n        return r ? r[1] : undefined;\n    }\n\n    jQuery.postJSON = function(url, args, callback) {\n        args._xsrf = getCookie(\"_xsrf\");\n        $.ajax({url: url, data: $.param(args), dataType: \"text\", type: \"POST\",\n            success: function(response) {\n            callback(eval(\"(\" + response + \")\"));\n        }});\n    };\n\nFor ``PUT`` and ``DELETE`` requests (as well as ``POST`` requests that\ndo not use form-encoded arguments), the XSRF token may also be passed\nvia an HTTP header named ``X-XSRFToken``.  The XSRF cookie is normally\nset when ``xsrf_form_html`` is used, but in a pure-Javascript application\nthat does not use any regular forms you may need to access\n``self.xsrf_token`` manually (just reading the property is enough to\nset the cookie as a side effect).\n\nIf you need to customize XSRF behavior on a per-handler basis, you can\noverride ``RequestHandler.check_xsrf_cookie()``. For example, if you\nhave an API whose authentication does not use cookies, you may want to\ndisable XSRF protection by making ``check_xsrf_cookie()`` do nothing.\nHowever, if you support both cookie and non-cookie-based authentication,\nit is important that XSRF protection be used whenever the current\nrequest is authenticated with a cookie.\n\nStatic files and aggressive file caching\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nYou can serve static files from Tornado by specifying the\n``static_path`` setting in your application:\n\n::\n\n    settings = {\n        \"static_path\": os.path.join(os.path.dirname(__file__), \"static\"),\n        \"cookie_secret\": \"__TODO:_GENERATE_YOUR_OWN_RANDOM_VALUE_HERE__\",\n        \"login_url\": \"/login\",\n        \"xsrf_cookies\": True,\n    }\n    application = tornado.web.Application([\n        (r\"/\", MainHandler),\n        (r\"/login\", LoginHandler),\n        (r\"/(apple-touch-icon\\.png)\", tornado.web.StaticFileHandler,\n         dict(path=settings['static_path'])),\n    ], **settings)\n\nThis setting will automatically make all requests that start with\n``/static/`` serve from that static directory, e.g.,\n`http://localhost:8888/static/foo.png <http://localhost:8888/static/foo.png>`_\nwill serve the file ``foo.png`` from the specified static directory. We\nalso automatically serve ``/robots.txt`` and ``/favicon.ico`` from the\nstatic directory (even though they don't start with the ``/static/``\nprefix).\n\nIn the above settings, we have explicitly configured Tornado to serve\n``apple-touch-icon.png`` “from” the root with the ``StaticFileHandler``,\nthough it is physically in the static file directory. (The capturing\ngroup in that regular expression is necessary to tell\n``StaticFileHandler`` the requested filename; capturing groups are\npassed to handlers as method arguments.) You could do the same thing to\nserve e.g. ``sitemap.xml`` from the site root. Of course, you can also\navoid faking a root ``apple-touch-icon.png`` by using the appropriate\n``<link />`` tag in your HTML.\n\nTo improve performance, it is generally a good idea for browsers to\ncache static resources aggressively so browsers won't send unnecessary\n``If-Modified-Since`` or ``Etag`` requests that might block the\nrendering of the page. Tornado supports this out of the box with *static\ncontent versioning*.\n\nTo use this feature, use the ``static_url()`` method in your templates\nrather than typing the URL of the static file directly in your HTML:\n\n::\n\n    <html>\n       <head>\n          <title>FriendFeed - {{ _(\"Home\") }}</title>\n       </head>\n       <body>\n         <div><img src=\"{{ static_url(\"images/logo.png\") }}\"/></div>\n       </body>\n     </html>\n\nThe ``static_url()`` function will translate that relative path to a URI\nthat looks like ``/static/images/logo.png?v=aae54``. The ``v`` argument\nis a hash of the content in ``logo.png``, and its presence makes the\nTornado server send cache headers to the user's browser that will make\nthe browser cache the content indefinitely.\n\nSince the ``v`` argument is based on the content of the file, if you\nupdate a file and restart your server, it will start sending a new ``v``\nvalue, so the user's browser will automatically fetch the new file. If\nthe file's contents don't change, the browser will continue to use a\nlocally cached copy without ever checking for updates on the server,\nsignificantly improving rendering performance.\n\nIn production, you probably want to serve static files from a more\noptimized static file server like `nginx <http://nginx.net/>`_. You can\nconfigure most any web server to support these caching semantics. Here\nis the nginx configuration we use at FriendFeed:\n\n::\n\n    location /static/ {\n        root /var/friendfeed/static;\n        if ($query_string) {\n            expires max;\n        }\n     }\n\nLocalization\n~~~~~~~~~~~~\n\nThe locale of the current user (whether they are logged in or not) is\nalways available as ``self.locale`` in the request handler and as\n``locale`` in templates. The name of the locale (e.g., ``en_US``) is\navailable as ``locale.name``, and you can translate strings with the\n``locale.translate`` method. Templates also have the global function\ncall ``_()`` available for string translation. The translate function\nhas two forms:\n\n::\n\n    _(\"Translate this string\")\n\nwhich translates the string directly based on the current locale, and\n\n::\n\n    _(\"A person liked this\", \"%(num)d people liked this\",\n      len(people)) % {\"num\": len(people)}\n\nwhich translates a string that can be singular or plural based on the\nvalue of the third argument. In the example above, a translation of the\nfirst string will be returned if ``len(people)`` is ``1``, or a\ntranslation of the second string will be returned otherwise.\n\nThe most common pattern for translations is to use Python named\nplaceholders for variables (the ``%(num)d`` in the example above) since\nplaceholders can move around on translation.\n\nHere is a properly localized template:\n\n::\n\n    <html>\n       <head>\n          <title>FriendFeed - {{ _(\"Sign in\") }}</title>\n       </head>\n       <body>\n         <form action=\"{{ request.path }}\" method=\"post\">\n           <div>{{ _(\"Username\") }} <input type=\"text\" name=\"username\"/></div>\n           <div>{{ _(\"Password\") }} <input type=\"password\" name=\"password\"/></div>\n           <div><input type=\"submit\" value=\"{{ _(\"Sign in\") }}\"/></div>\n           {% module xsrf_form_html() %}\n         </form>\n       </body>\n     </html>\n\nBy default, we detect the user's locale using the ``Accept-Language``\nheader sent by the user's browser. We choose ``en_US`` if we can't find\nan appropriate ``Accept-Language`` value. If you let user's set their\nlocale as a preference, you can override this default locale selection\nby overriding ``get_user_locale`` in your request handler:\n\n::\n\n    class BaseHandler(tornado.web.RequestHandler):\n        def get_current_user(self):\n            user_id = self.get_secure_cookie(\"user\")\n            if not user_id: return None\n            return self.backend.get_user_by_id(user_id)\n\n        def get_user_locale(self):\n            if \"locale\" not in self.current_user.prefs:\n                # Use the Accept-Language header\n                return None\n            return self.current_user.prefs[\"locale\"]\n\nIf ``get_user_locale`` returns ``None``, we fall back on the\n``Accept-Language`` header.\n\nYou can load all the translations for your application using the\n``tornado.locale.load_translations`` method. It takes in the name of the\ndirectory which should contain CSV files named after the locales whose\ntranslations they contain, e.g., ``es_GT.csv`` or ``fr_CA.csv``. The\nmethod loads all the translations from those CSV files and infers the\nlist of supported locales based on the presence of each CSV file. You\ntypically call this method once in the ``main()`` method of your server:\n\n::\n\n    def main():\n        tornado.locale.load_translations(\n            os.path.join(os.path.dirname(__file__), \"translations\"))\n        start_server()\n\nYou can get the list of supported locales in your application with\n``tornado.locale.get_supported_locales()``. The user's locale is chosen\nto be the closest match based on the supported locales. For example, if\nthe user's locale is ``es_GT``, and the ``es`` locale is supported,\n``self.locale`` will be ``es`` for that request. We fall back on\n``en_US`` if no close match can be found.\n\nSee the `tornado.locale`\ndocumentation for detailed information on the CSV format and other\nlocalization methods.\n\n.. _ui-modules:\n\nUI modules\n~~~~~~~~~~\n\nTornado supports *UI modules* to make it easy to support standard,\nreusable UI widgets across your application. UI modules are like special\nfunctional calls to render components of your page, and they can come\npackaged with their own CSS and JavaScript.\n\nFor example, if you are implementing a blog, and you want to have blog\nentries appear on both the blog home page and on each blog entry page,\nyou can make an ``Entry`` module to render them on both pages. First,\ncreate a Python module for your UI modules, e.g., ``uimodules.py``:\n\n::\n\n    class Entry(tornado.web.UIModule):\n        def render(self, entry, show_comments=False):\n            return self.render_string(\n                \"module-entry.html\", entry=entry, show_comments=show_comments)\n\nTell Tornado to use ``uimodules.py`` using the ``ui_modules`` setting in\nyour application:\n\n::\n\n    class HomeHandler(tornado.web.RequestHandler):\n        def get(self):\n            entries = self.db.query(\"SELECT * FROM entries ORDER BY date DESC\")\n            self.render(\"home.html\", entries=entries)\n\n    class EntryHandler(tornado.web.RequestHandler):\n        def get(self, entry_id):\n            entry = self.db.get(\"SELECT * FROM entries WHERE id = %s\", entry_id)\n            if not entry: raise tornado.web.HTTPError(404)\n            self.render(\"entry.html\", entry=entry)\n\n    settings = {\n        \"ui_modules\": uimodules,\n    }\n    application = tornado.web.Application([\n        (r\"/\", HomeHandler),\n        (r\"/entry/([0-9]+)\", EntryHandler),\n    ], **settings)\n\nWithin ``home.html``, you reference the ``Entry`` module rather than\nprinting the HTML directly:\n\n::\n\n    {% for entry in entries %}\n      {% module Entry(entry) %}\n    {% end %}\n\nWithin ``entry.html``, you reference the ``Entry`` module with the\n``show_comments`` argument to show the expanded form of the entry:\n\n::\n\n    {% module Entry(entry, show_comments=True) %}\n\nModules can include custom CSS and JavaScript functions by overriding\nthe ``embedded_css``, ``embedded_javascript``, ``javascript_files``, or\n``css_files`` methods:\n\n::\n\n    class Entry(tornado.web.UIModule):\n        def embedded_css(self):\n            return \".entry { margin-bottom: 1em; }\"\n\n        def render(self, entry, show_comments=False):\n            return self.render_string(\n                \"module-entry.html\", show_comments=show_comments)\n\nModule CSS and JavaScript will be included once no matter how many times\na module is used on a page. CSS is always included in the ``<head>`` of\nthe page, and JavaScript is always included just before the ``</body>``\ntag at the end of the page.\n\nWhen additional Python code is not required, a template file itself may\nbe used as a module. For example, the preceding example could be\nrewritten to put the following in ``module-entry.html``:\n\n::\n\n    {{ set_resources(embedded_css=\".entry { margin-bottom: 1em; }\") }}\n    <!-- more template html... -->\n\nThis revised template module would be invoked with\n\n::\n\n    {% module Template(\"module-entry.html\", show_comments=True) %}\n\nThe ``set_resources`` function is only available in templates invoked\nvia ``{% module Template(...) %}``. Unlike the ``{% include ... %}``\ndirective, template modules have a distinct namespace from their\ncontaining template - they can only see the global template namespace\nand their own keyword arguments.\n\nNon-blocking, asynchronous requests\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nWhen a request handler is executed, the request is automatically\nfinished. Since Tornado uses a non-blocking I/O style, you can override\nthis default behavior if you want a request to remain open after the\nmain request handler method returns using the\n``tornado.web.asynchronous`` decorator.\n\nWhen you use this decorator, it is your responsibility to call\n``self.finish()`` to finish the HTTP request, or the user's browser will\nsimply hang:\n\n::\n\n    class MainHandler(tornado.web.RequestHandler):\n        @tornado.web.asynchronous\n        def get(self):\n            self.write(\"Hello, world\")\n            self.finish()\n\nHere is a real example that makes a call to the FriendFeed API using\nTornado's built-in asynchronous HTTP client:\n\n::\n\n    class MainHandler(tornado.web.RequestHandler):\n        @tornado.web.asynchronous\n        def get(self):\n            http = tornado.httpclient.AsyncHTTPClient()\n            http.fetch(\"http://friendfeed-api.com/v2/feed/bret\",\n                       callback=self.on_response)\n\n        def on_response(self, response):\n            if response.error: raise tornado.web.HTTPError(500)\n            json = tornado.escape.json_decode(response.body)\n            self.write(\"Fetched \" + str(len(json[\"entries\"])) + \" entries \"\n                       \"from the FriendFeed API\")\n            self.finish()\n\nWhen ``get()`` returns, the request has not finished. When the HTTP\nclient eventually calls ``on_response()``, the request is still open,\nand the response is finally flushed to the client with the call to\n``self.finish()``.\n\nFor a more advanced asynchronous example, take a look at the `chat\nexample application\n<https://github.com/tornadoweb/tornado/tree/stable/demos/chat>`_, which\nimplements an AJAX chat room using `long polling\n<http://en.wikipedia.org/wiki/Push_technology#Long_polling>`_.  Users\nof long polling may want to override ``on_connection_close()`` to\nclean up after the client closes the connection (but see that method's\ndocstring for caveats).\n\nAsynchronous HTTP clients\n~~~~~~~~~~~~~~~~~~~~~~~~~\n\nTornado includes two non-blocking HTTP client implementations:\n``SimpleAsyncHTTPClient`` and ``CurlAsyncHTTPClient``. The simple client\nhas no external dependencies because it is implemented directly on top\nof Tornado's ``IOLoop``. The Curl client requires that ``libcurl`` and\n``pycurl`` be installed (and a recent version of each is highly\nrecommended to avoid bugs in older version's asynchronous interfaces),\nbut is more likely to be compatible with sites that exercise little-used\nparts of the HTTP specification.\n\nEach of these clients is available in its own module\n(``tornado.simple_httpclient`` and ``tornado.curl_httpclient``), as well\nas via a configurable alias in ``tornado.httpclient``.\n``SimpleAsyncHTTPClient`` is the default, but to use a different\nimplementation call the ``AsyncHTTPClient.configure`` method at startup:\n\n::\n\n    AsyncHTTPClient.configure('tornado.curl_httpclient.CurlAsyncHTTPClient')\n\nThird party authentication\n~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nTornado's ``auth`` module implements the authentication and\nauthorization protocols for a number of the most popular sites on the\nweb, including Google/Gmail, Facebook, Twitter, and FriendFeed.\nThe module includes methods to log users in via these sites and, where\napplicable, methods to authorize access to the service so you can, e.g.,\ndownload a user's address book or publish a Twitter message on their\nbehalf.\n\nHere is an example handler that uses Google for authentication, saving\nthe Google credentials in a cookie for later access:\n\n::\n\n    class GoogleHandler(tornado.web.RequestHandler, tornado.auth.GoogleMixin):\n        @tornado.web.asynchronous\n        def get(self):\n            if self.get_argument(\"openid.mode\", None):\n                self.get_authenticated_user(self._on_auth)\n                return\n            self.authenticate_redirect()\n\n        def _on_auth(self, user):\n            if not user:\n                self.authenticate_redirect()\n                return\n            # Save the user with, e.g., set_secure_cookie()\n\nSee the `tornado.auth` module documentation for more details.\n\n.. _debug-mode:\n\nDebug mode and automatic reloading\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nIf you pass ``debug=True`` to the ``Application`` constructor, the app\nwill be run in debug/development mode. In this mode, several features\nintended for convenience while developing will be enabled (each of which\nis also available as an individual flag; if both are specified the\nindividual flag takes precedence):\n\n* ``autoreload=True``: The app will watch for changes to its source\n  files and reload itself when anything changes. This reduces the need\n  to manually restart the server during development. However, certain\n  failures (such as syntax errors at import time) can still take the\n  server down in a way that debug mode cannot currently recover from.\n* ``compiled_template_cache=False``: Templates will not be cached.\n* ``static_hash_cache=False``: Static file hashes (used by the\n  ``static_url`` function) will not be cached\n* ``serve_traceback=True``: When an exception in a ``RequestHandler``\n  is not caught, an error page including a stack trace will be\n  generated.\n\nAutoreload mode is not compatible with the multi-process mode of ``HTTPServer``.\nYou must not give ``HTTPServer.start`` an argument other than 1 (or\ncall `tornado.process.fork_processes`) if you are using autoreload mode.\n\nThe automatic reloading feature of debug mode is available as a\nstandalone module in ``tornado.autoreload``.  The two can be used in\ncombination to provide extra robustness against syntax errors: set\n``autoreload=True`` within the app to detect changes while it is running,\nand start it with ``python -m tornado.autoreload myserver.py`` to catch\nany syntax errors or other errors at startup.\n\nReloading loses any Python interpreter command-line arguments (e.g. ``-u``)\nbecause it re-executes Python using ``sys.executable`` and ``sys.argv``.\nAdditionally, modifying these variables will cause reloading to behave\nincorrectly.\n\nOn some platforms (including Windows and Mac OSX prior to 10.6), the\nprocess cannot be updated \"in-place\", so when a code change is\ndetected the old server exits and a new one starts.  This has been\nknown to confuse some IDEs.\n\n\nRunning Tornado in production\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nAt FriendFeed, we use `nginx <http://nginx.net/>`_ as a load balancer\nand static file server. We run multiple instances of the Tornado web\nserver on multiple frontend machines. We typically run one Tornado\nfrontend per core on the machine (sometimes more depending on\nutilization).\n\nWhen running behind a load balancer like nginx, it is recommended to\npass ``xheaders=True`` to the ``HTTPServer`` constructor. This will tell\nTornado to use headers like ``X-Real-IP`` to get the user's IP address\ninstead of attributing all traffic to the balancer's IP address.\n\nThis is a barebones nginx config file that is structurally similar to\nthe one we use at FriendFeed. It assumes nginx and the Tornado servers\nare running on the same machine, and the four Tornado servers are\nrunning on ports 8000 - 8003:\n\n::\n\n    user nginx;\n    worker_processes 1;\n\n    error_log /var/log/nginx/error.log;\n    pid /var/run/nginx.pid;\n\n    events {\n        worker_connections 1024;\n        use epoll;\n    }\n\n    http {\n        # Enumerate all the Tornado servers here\n        upstream frontends {\n            server 127.0.0.1:8000;\n            server 127.0.0.1:8001;\n            server 127.0.0.1:8002;\n            server 127.0.0.1:8003;\n        }\n\n        include /etc/nginx/mime.types;\n        default_type application/octet-stream;\n\n        access_log /var/log/nginx/access.log;\n\n        keepalive_timeout 65;\n        proxy_read_timeout 200;\n        sendfile on;\n        tcp_nopush on;\n        tcp_nodelay on;\n        gzip on;\n        gzip_min_length 1000;\n        gzip_proxied any;\n        gzip_types text/plain text/html text/css text/xml\n                   application/x-javascript application/xml\n                   application/atom+xml text/javascript;\n\n        # Only retry if there was a communication error, not a timeout\n        # on the Tornado server (to avoid propagating \"queries of death\"\n        # to all frontends)\n        proxy_next_upstream error;\n\n        server {\n            listen 80;\n\n            # Allow file uploads\n            client_max_body_size 50M;\n\n            location ^~ /static/ {\n                root /var/www;\n                if ($query_string) {\n                    expires max;\n                }\n            }\n            location = /favicon.ico {\n                rewrite (.*) /static/favicon.ico;\n            }\n            location = /robots.txt {\n                rewrite (.*) /static/robots.txt;\n            }\n\n            location / {\n                proxy_pass_header Server;\n                proxy_set_header Host $http_host;\n                proxy_redirect off;\n                proxy_set_header X-Real-IP $remote_addr;\n                proxy_set_header X-Scheme $scheme;\n                proxy_pass http://frontends;\n            }\n        }\n    }\n\nWSGI and Google AppEngine\n~~~~~~~~~~~~~~~~~~~~~~~~~\n\nTornado comes with limited support for `WSGI <http://wsgi.org/>`_.\nHowever, since WSGI does not support non-blocking requests, you cannot\nuse any of the asynchronous/non-blocking features of Tornado in your\napplication if you choose to use WSGI instead of Tornado's HTTP server.\nSome of the features that are not available in WSGI applications:\n``@tornado.web.asynchronous``, the ``httpclient`` module, and the\n``auth`` module.\n\nYou can create a valid WSGI application from your Tornado request\nhandlers by using ``WSGIApplication`` in the ``wsgi`` module instead of\nusing ``tornado.web.Application``. Here is an example that uses the\nbuilt-in WSGI ``CGIHandler`` to make a valid `Google\nAppEngine <http://code.google.com/appengine/>`_ application:\n\n::\n\n    import tornado.web\n    import tornado.wsgi\n    import wsgiref.handlers\n\n    class MainHandler(tornado.web.RequestHandler):\n        def get(self):\n            self.write(\"Hello, world\")\n\n    if __name__ == \"__main__\":\n        application = tornado.wsgi.WSGIApplication([\n            (r\"/\", MainHandler),\n        ])\n        wsgiref.handlers.CGIHandler().run(application)\n\nSee the `appengine example application\n<https://github.com/tornadoweb/tornado/tree/stable/demos/appengine>`_ for a\nfull-featured AppEngine app built on Tornado.\n",
            "header": {
                "file": {
                    "path": "docs/overview.rst"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "413c4189",
                "new_commit_hash": "21ccb79d",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/docs/overview.rst"
            },
            "plus_file": {
                "path": "b/docs/overview.rst"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 296,
                            "length": 7
                        },
                        "new_range": {
                            "start": 296,
                            "length": 7
                        },
                        "section": "directory as your Python file, you could render this template with:"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "            self.render(\"template.html\", title=\"My title\", items=items)",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "Tornado templates support *control statements* and *expressions*.",
                                "type": "context"
                            },
                            {
                                "content": "Control statements are surronded by ``{%`` and ``%}``, e.g.,",
                                "type": "deleted"
                            },
                            {
                                "content": "Control statements are surrounded by ``{%`` and ``%}``, e.g.,",
                                "type": "added"
                            },
                            {
                                "content": "``{% if len(items) > 2 %}``. Expressions are surrounded by ``{{`` and",
                                "type": "context"
                            },
                            {
                                "content": "``}}``, e.g., ``{{ items[0] }}``.",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [],
                    "added_entities": [],
                    "deleted_entities": []
                }
            ]
        },
        {
            "old_file_content": "from __future__ import absolute_import, division, print_function, with_statement\n\nimport traceback\n\nfrom tornado.concurrent import Future\nfrom tornado.httpclient import HTTPError, HTTPRequest\nfrom tornado.log import gen_log\nfrom tornado.testing import AsyncHTTPTestCase, gen_test, bind_unused_port, ExpectLog\nfrom tornado.test.util import unittest\nfrom tornado.web import Application, RequestHandler\n\ntry:\n    import tornado.websocket\nexcept ImportError:\n    # The unittest module presents misleading errors on ImportError\n    # (it acts as if websocket_test could not be found, hiding the underlying\n    # error).  If we get an ImportError here (which could happen due to\n    # TORNADO_EXTENSION=1), print some extra information before failing.\n    traceback.print_exc()\n    raise\n\nfrom tornado.websocket import WebSocketHandler, websocket_connect, WebSocketError, _websocket_mask_python\n\ntry:\n    from tornado import speedups\nexcept ImportError:\n    speedups = None\n\n\nclass TestWebSocketHandler(WebSocketHandler):\n    \"\"\"Base class for testing handlers that exposes the on_close event.\n\n    This allows for deterministic cleanup of the associated socket.\n    \"\"\"\n    def initialize(self, close_future):\n        self.close_future = close_future\n\n    def on_close(self):\n        self.close_future.set_result((self.close_code, self.close_reason))\n\n\nclass EchoHandler(TestWebSocketHandler):\n    def on_message(self, message):\n        self.write_message(message, isinstance(message, bytes))\n\n\nclass HeaderHandler(TestWebSocketHandler):\n    def open(self):\n        self.write_message(self.request.headers.get('X-Test', ''))\n\n\nclass NonWebSocketHandler(RequestHandler):\n    def get(self):\n        self.write('ok')\n\n\nclass CloseReasonHandler(TestWebSocketHandler):\n    def open(self):\n        self.close(1001, \"goodbye\")\n\n\nclass WebSocketTest(AsyncHTTPTestCase):\n    def get_app(self):\n        self.close_future = Future()\n        return Application([\n            ('/echo', EchoHandler, dict(close_future=self.close_future)),\n            ('/non_ws', NonWebSocketHandler),\n            ('/header', HeaderHandler, dict(close_future=self.close_future)),\n            ('/close_reason', CloseReasonHandler,\n             dict(close_future=self.close_future)),\n        ])\n\n    @gen_test\n    def test_websocket_gen(self):\n        ws = yield websocket_connect(\n            'ws://localhost:%d/echo' % self.get_http_port(),\n            io_loop=self.io_loop)\n        ws.write_message('hello')\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    def test_websocket_callbacks(self):\n        websocket_connect(\n            'ws://localhost:%d/echo' % self.get_http_port(),\n            io_loop=self.io_loop, callback=self.stop)\n        ws = self.wait().result()\n        ws.write_message('hello')\n        ws.read_message(self.stop)\n        response = self.wait().result()\n        self.assertEqual(response, 'hello')\n        self.close_future.add_done_callback(lambda f: self.stop())\n        ws.close()\n        self.wait()\n\n    @gen_test\n    def test_websocket_http_fail(self):\n        with self.assertRaises(HTTPError) as cm:\n            yield websocket_connect(\n                'ws://localhost:%d/notfound' % self.get_http_port(),\n                io_loop=self.io_loop)\n        self.assertEqual(cm.exception.code, 404)\n\n    @gen_test\n    def test_websocket_http_success(self):\n        with self.assertRaises(WebSocketError):\n            yield websocket_connect(\n                'ws://localhost:%d/non_ws' % self.get_http_port(),\n                io_loop=self.io_loop)\n\n    @gen_test\n    def test_websocket_network_fail(self):\n        sock, port = bind_unused_port()\n        sock.close()\n        with self.assertRaises(IOError):\n            with ExpectLog(gen_log, \".*\"):\n                yield websocket_connect(\n                    'ws://localhost:%d/' % port,\n                    io_loop=self.io_loop,\n                    connect_timeout=3600)\n\n    @gen_test\n    def test_websocket_close_buffered_data(self):\n        ws = yield websocket_connect(\n            'ws://localhost:%d/echo' % self.get_http_port())\n        ws.write_message('hello')\n        ws.write_message('world')\n        ws.stream.close()\n        yield self.close_future\n\n    @gen_test\n    def test_websocket_headers(self):\n        # Ensure that arbitrary headers can be passed through websocket_connect.\n        ws = yield websocket_connect(\n            HTTPRequest('ws://localhost:%d/header' % self.get_http_port(),\n                        headers={'X-Test': 'hello'}))\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    @gen_test\n    def test_server_close_reason(self):\n        ws = yield websocket_connect(\n            'ws://localhost:%d/close_reason' % self.get_http_port())\n        msg = yield ws.read_message()\n        # A message of None means the other side closed the connection.\n        self.assertIs(msg, None)\n        self.assertEqual(ws.close_code, 1001)\n        self.assertEqual(ws.close_reason, \"goodbye\")\n\n    @gen_test\n    def test_client_close_reason(self):\n        ws = yield websocket_connect(\n            'ws://localhost:%d/echo' % self.get_http_port())\n        ws.close(1001, 'goodbye')\n        code, reason = yield self.close_future\n        self.assertEqual(code, 1001)\n        self.assertEqual(reason, 'goodbye')\n\n\nclass MaskFunctionMixin(object):\n    # Subclasses should define self.mask(mask, data)\n    def test_mask(self):\n        self.assertEqual(self.mask(b'abcd', b''), b'')\n        self.assertEqual(self.mask(b'abcd', b'b'), b'\\x03')\n        self.assertEqual(self.mask(b'abcd', b'54321'), b'TVPVP')\n        self.assertEqual(self.mask(b'ZXCV', b'98765432'), b'c`t`olpd')\n        # Include test cases with \\x00 bytes (to ensure that the C\n        # extension isn't depending on null-terminated strings) and\n        # bytes with the high bit set (to smoke out signedness issues).\n        self.assertEqual(self.mask(b'\\x00\\x01\\x02\\x03',\n                                   b'\\xff\\xfb\\xfd\\xfc\\xfe\\xfa'),\n                         b'\\xff\\xfa\\xff\\xff\\xfe\\xfb')\n        self.assertEqual(self.mask(b'\\xff\\xfb\\xfd\\xfc',\n                                   b'\\x00\\x01\\x02\\x03\\x04\\x05'),\n                         b'\\xff\\xfa\\xff\\xff\\xfb\\xfe')\n\n\nclass PythonMaskFunctionTest(MaskFunctionMixin, unittest.TestCase):\n    def mask(self, mask, data):\n        return _websocket_mask_python(mask, data)\n\n\n@unittest.skipIf(speedups is None, \"tornado.speedups module not present\")\nclass CythonMaskFunctionTest(MaskFunctionMixin, unittest.TestCase):\n    def mask(self, mask, data):\n        return speedups.websocket_mask(mask, data)\n",
            "new_file_content": "from __future__ import absolute_import, division, print_function, with_statement\n\nimport traceback\n\nfrom tornado.concurrent import Future\nfrom tornado.httpclient import HTTPError, HTTPRequest\nfrom tornado.log import gen_log\nfrom tornado.testing import AsyncHTTPTestCase, gen_test, bind_unused_port, ExpectLog\nfrom tornado.test.util import unittest\nfrom tornado.web import Application, RequestHandler\n\ntry:\n    import tornado.websocket\nexcept ImportError:\n    # The unittest module presents misleading errors on ImportError\n    # (it acts as if websocket_test could not be found, hiding the underlying\n    # error).  If we get an ImportError here (which could happen due to\n    # TORNADO_EXTENSION=1), print some extra information before failing.\n    traceback.print_exc()\n    raise\n\nfrom tornado.websocket import WebSocketHandler, websocket_connect, WebSocketError, _websocket_mask_python\n\ntry:\n    from tornado import speedups\nexcept ImportError:\n    speedups = None\n\n\nclass TestWebSocketHandler(WebSocketHandler):\n    \"\"\"Base class for testing handlers that exposes the on_close event.\n\n    This allows for deterministic cleanup of the associated socket.\n    \"\"\"\n    def initialize(self, close_future):\n        self.close_future = close_future\n\n    def on_close(self):\n        self.close_future.set_result((self.close_code, self.close_reason))\n\n\nclass EchoHandler(TestWebSocketHandler):\n    def on_message(self, message):\n        self.write_message(message, isinstance(message, bytes))\n\n\nclass HeaderHandler(TestWebSocketHandler):\n    def open(self):\n        self.write_message(self.request.headers.get('X-Test', ''))\n\n\nclass NonWebSocketHandler(RequestHandler):\n    def get(self):\n        self.write('ok')\n\n\nclass CloseReasonHandler(TestWebSocketHandler):\n    def open(self):\n        self.close(1001, \"goodbye\")\n\n\nclass WebSocketTest(AsyncHTTPTestCase):\n    def get_app(self):\n        self.close_future = Future()\n        return Application([\n            ('/echo', EchoHandler, dict(close_future=self.close_future)),\n            ('/non_ws', NonWebSocketHandler),\n            ('/header', HeaderHandler, dict(close_future=self.close_future)),\n            ('/close_reason', CloseReasonHandler,\n             dict(close_future=self.close_future)),\n        ])\n\n    @gen_test\n    def test_websocket_gen(self):\n        ws = yield websocket_connect(\n            'ws://localhost:%d/echo' % self.get_http_port(),\n            io_loop=self.io_loop)\n        ws.write_message('hello')\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    def test_websocket_callbacks(self):\n        websocket_connect(\n            'ws://localhost:%d/echo' % self.get_http_port(),\n            io_loop=self.io_loop, callback=self.stop)\n        ws = self.wait().result()\n        ws.write_message('hello')\n        ws.read_message(self.stop)\n        response = self.wait().result()\n        self.assertEqual(response, 'hello')\n        self.close_future.add_done_callback(lambda f: self.stop())\n        ws.close()\n        self.wait()\n\n    @gen_test\n    def test_websocket_http_fail(self):\n        with self.assertRaises(HTTPError) as cm:\n            yield websocket_connect(\n                'ws://localhost:%d/notfound' % self.get_http_port(),\n                io_loop=self.io_loop)\n        self.assertEqual(cm.exception.code, 404)\n\n    @gen_test\n    def test_websocket_http_success(self):\n        with self.assertRaises(WebSocketError):\n            yield websocket_connect(\n                'ws://localhost:%d/non_ws' % self.get_http_port(),\n                io_loop=self.io_loop)\n\n    @gen_test\n    def test_websocket_network_fail(self):\n        sock, port = bind_unused_port()\n        sock.close()\n        with self.assertRaises(IOError):\n            with ExpectLog(gen_log, \".*\"):\n                yield websocket_connect(\n                    'ws://localhost:%d/' % port,\n                    io_loop=self.io_loop,\n                    connect_timeout=3600)\n\n    @gen_test\n    def test_websocket_close_buffered_data(self):\n        ws = yield websocket_connect(\n            'ws://localhost:%d/echo' % self.get_http_port())\n        ws.write_message('hello')\n        ws.write_message('world')\n        ws.stream.close()\n        yield self.close_future\n\n    @gen_test\n    def test_websocket_headers(self):\n        # Ensure that arbitrary headers can be passed through websocket_connect.\n        ws = yield websocket_connect(\n            HTTPRequest('ws://localhost:%d/header' % self.get_http_port(),\n                        headers={'X-Test': 'hello'}))\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    @gen_test\n    def test_server_close_reason(self):\n        ws = yield websocket_connect(\n            'ws://localhost:%d/close_reason' % self.get_http_port())\n        msg = yield ws.read_message()\n        # A message of None means the other side closed the connection.\n        self.assertIs(msg, None)\n        self.assertEqual(ws.close_code, 1001)\n        self.assertEqual(ws.close_reason, \"goodbye\")\n\n    @gen_test\n    def test_client_close_reason(self):\n        ws = yield websocket_connect(\n            'ws://localhost:%d/echo' % self.get_http_port())\n        ws.close(1001, 'goodbye')\n        code, reason = yield self.close_future\n        self.assertEqual(code, 1001)\n        self.assertEqual(reason, 'goodbye')\n\n    @gen_test\n    def test_check_origin_valid(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        headers = {'Origin': 'http://localhost:%d' % port}\n\n        ws = yield websocket_connect(HTTPRequest(url, headers=headers),\n            io_loop=self.io_loop)\n        ws.write_message('hello')\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    @gen_test\n    def test_check_origin_with_path(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        headers = {'Origin': 'http://localhost:%d/something' % port}\n\n        ws = yield websocket_connect(HTTPRequest(url, headers=headers),\n            io_loop=self.io_loop)\n        ws.write_message('hello')\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    @gen_test\n    def test_check_origin_valid2(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        headers = {'Origin': 'localhost:%d' % port}\n\n        ws = yield websocket_connect(HTTPRequest(url, headers=headers),\n            io_loop=self.io_loop)\n        ws.write_message('hello')\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    @gen_test\n    def test_check_origin_invalid(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        # Host is localhost, which should not be accessible from some other\n        # domain\n        headers = {'Origin': 'http://somewhereelse.com'}\n\n        with self.assertRaises(HTTPError) as cm:\n            yield websocket_connect(HTTPRequest(url, headers=headers),\n                                    io_loop=self.io_loop)\n\n        self.assertEqual(cm.exception.code, 403)\n\n    @gen_test\n    def test_check_origin_invalid2(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        # subdomains should be invalid by default\n        headers = {'Origin': 'http://subtenant.somewhereelse.com',\n                   'Host': 'subtenant2.somewhereelse.com'}\n\n        with self.assertRaises(HTTPError) as cm:\n            yield websocket_connect(HTTPRequest(url, headers=headers),\n                                    io_loop=self.io_loop)\n\n        self.assertEqual(cm.exception.code, 403)\n\n\nclass MaskFunctionMixin(object):\n    # Subclasses should define self.mask(mask, data)\n    def test_mask(self):\n        self.assertEqual(self.mask(b'abcd', b''), b'')\n        self.assertEqual(self.mask(b'abcd', b'b'), b'\\x03')\n        self.assertEqual(self.mask(b'abcd', b'54321'), b'TVPVP')\n        self.assertEqual(self.mask(b'ZXCV', b'98765432'), b'c`t`olpd')\n        # Include test cases with \\x00 bytes (to ensure that the C\n        # extension isn't depending on null-terminated strings) and\n        # bytes with the high bit set (to smoke out signedness issues).\n        self.assertEqual(self.mask(b'\\x00\\x01\\x02\\x03',\n                                   b'\\xff\\xfb\\xfd\\xfc\\xfe\\xfa'),\n                         b'\\xff\\xfa\\xff\\xff\\xfe\\xfb')\n        self.assertEqual(self.mask(b'\\xff\\xfb\\xfd\\xfc',\n                                   b'\\x00\\x01\\x02\\x03\\x04\\x05'),\n                         b'\\xff\\xfa\\xff\\xff\\xfb\\xfe')\n\n\nclass PythonMaskFunctionTest(MaskFunctionMixin, unittest.TestCase):\n    def mask(self, mask, data):\n        return _websocket_mask_python(mask, data)\n\n\n@unittest.skipIf(speedups is None, \"tornado.speedups module not present\")\nclass CythonMaskFunctionTest(MaskFunctionMixin, unittest.TestCase):\n    def mask(self, mask, data):\n        return speedups.websocket_mask(mask, data)\n",
            "header": {
                "file": {
                    "path": "tornado/test/websocket_test.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "99ded1b8",
                "new_commit_hash": "736da141",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/tornado/test/websocket_test.py"
            },
            "plus_file": {
                "path": "b/tornado/test/websocket_test.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 159,
                            "length": 6
                        },
                        "new_range": {
                            "start": 159,
                            "length": 81
                        },
                        "section": "class WebSocketTest(AsyncHTTPTestCase):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "        self.assertEqual(code, 1001)",
                                "type": "context"
                            },
                            {
                                "content": "        self.assertEqual(reason, 'goodbye')",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "    @gen_test",
                                "type": "added"
                            },
                            {
                                "content": "    def test_check_origin_valid(self):",
                                "type": "added"
                            },
                            {
                                "content": "        port = self.get_http_port()",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "        url = 'ws://localhost:%d/echo' % port",
                                "type": "added"
                            },
                            {
                                "content": "        headers = {'Origin': 'http://localhost:%d' % port}",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "        ws = yield websocket_connect(HTTPRequest(url, headers=headers),",
                                "type": "added"
                            },
                            {
                                "content": "            io_loop=self.io_loop)",
                                "type": "added"
                            },
                            {
                                "content": "        ws.write_message('hello')",
                                "type": "added"
                            },
                            {
                                "content": "        response = yield ws.read_message()",
                                "type": "added"
                            },
                            {
                                "content": "        self.assertEqual(response, 'hello')",
                                "type": "added"
                            },
                            {
                                "content": "        ws.close()",
                                "type": "added"
                            },
                            {
                                "content": "        yield self.close_future",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "    @gen_test",
                                "type": "added"
                            },
                            {
                                "content": "    def test_check_origin_with_path(self):",
                                "type": "added"
                            },
                            {
                                "content": "        port = self.get_http_port()",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "        url = 'ws://localhost:%d/echo' % port",
                                "type": "added"
                            },
                            {
                                "content": "        headers = {'Origin': 'http://localhost:%d/something' % port}",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "        ws = yield websocket_connect(HTTPRequest(url, headers=headers),",
                                "type": "added"
                            },
                            {
                                "content": "            io_loop=self.io_loop)",
                                "type": "added"
                            },
                            {
                                "content": "        ws.write_message('hello')",
                                "type": "added"
                            },
                            {
                                "content": "        response = yield ws.read_message()",
                                "type": "added"
                            },
                            {
                                "content": "        self.assertEqual(response, 'hello')",
                                "type": "added"
                            },
                            {
                                "content": "        ws.close()",
                                "type": "added"
                            },
                            {
                                "content": "        yield self.close_future",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "    @gen_test",
                                "type": "added"
                            },
                            {
                                "content": "    def test_check_origin_valid2(self):",
                                "type": "added"
                            },
                            {
                                "content": "        port = self.get_http_port()",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "        url = 'ws://localhost:%d/echo' % port",
                                "type": "added"
                            },
                            {
                                "content": "        headers = {'Origin': 'localhost:%d' % port}",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "        ws = yield websocket_connect(HTTPRequest(url, headers=headers),",
                                "type": "added"
                            },
                            {
                                "content": "            io_loop=self.io_loop)",
                                "type": "added"
                            },
                            {
                                "content": "        ws.write_message('hello')",
                                "type": "added"
                            },
                            {
                                "content": "        response = yield ws.read_message()",
                                "type": "added"
                            },
                            {
                                "content": "        self.assertEqual(response, 'hello')",
                                "type": "added"
                            },
                            {
                                "content": "        ws.close()",
                                "type": "added"
                            },
                            {
                                "content": "        yield self.close_future",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "    @gen_test",
                                "type": "added"
                            },
                            {
                                "content": "    def test_check_origin_invalid(self):",
                                "type": "added"
                            },
                            {
                                "content": "        port = self.get_http_port()",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "        url = 'ws://localhost:%d/echo' % port",
                                "type": "added"
                            },
                            {
                                "content": "        # Host is localhost, which should not be accessible from some other",
                                "type": "added"
                            },
                            {
                                "content": "        # domain",
                                "type": "added"
                            },
                            {
                                "content": "        headers = {'Origin': 'http://somewhereelse.com'}",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "        with self.assertRaises(HTTPError) as cm:",
                                "type": "added"
                            },
                            {
                                "content": "            yield websocket_connect(HTTPRequest(url, headers=headers),",
                                "type": "added"
                            },
                            {
                                "content": "                                    io_loop=self.io_loop)",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "        self.assertEqual(cm.exception.code, 403)",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "    @gen_test",
                                "type": "added"
                            },
                            {
                                "content": "    def test_check_origin_invalid2(self):",
                                "type": "added"
                            },
                            {
                                "content": "        port = self.get_http_port()",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "        url = 'ws://localhost:%d/echo' % port",
                                "type": "added"
                            },
                            {
                                "content": "        # subdomains should be invalid by default",
                                "type": "added"
                            },
                            {
                                "content": "        headers = {'Origin': 'http://subtenant.somewhereelse.com',",
                                "type": "added"
                            },
                            {
                                "content": "                   'Host': 'subtenant2.somewhereelse.com'}",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "        with self.assertRaises(HTTPError) as cm:",
                                "type": "added"
                            },
                            {
                                "content": "            yield websocket_connect(HTTPRequest(url, headers=headers),",
                                "type": "added"
                            },
                            {
                                "content": "                                    io_loop=self.io_loop)",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "        self.assertEqual(cm.exception.code, 403)",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "class MaskFunctionMixin(object):",
                                "type": "context"
                            },
                            {
                                "content": "    # Subclasses should define self.mask(mask, data)",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "tornado/test/websocket_test.py",
                            "type": "class",
                            "name": "WebSocketTest",
                            "content": "class WebSocketTest(AsyncHTTPTestCase):\n    def get_app(self):\n        self.close_future = Future()\n        return Application([\n            ('/echo', EchoHandler, dict(close_future=self.close_future)),\n            ('/non_ws', NonWebSocketHandler),\n            ('/header', HeaderHandler, dict(close_future=self.close_future)),\n            ('/close_reason', CloseReasonHandler,\n             dict(close_future=self.close_future)),\n        ])\n\n    @gen_test\n    def test_websocket_gen(self):\n        ws = yield websocket_connect(\n            'ws://localhost:%d/echo' % self.get_http_port(),\n            io_loop=self.io_loop)\n        ws.write_message('hello')\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    def test_websocket_callbacks(self):\n        websocket_connect(\n            'ws://localhost:%d/echo' % self.get_http_port(),\n            io_loop=self.io_loop, callback=self.stop)\n        ws = self.wait().result()\n        ws.write_message('hello')\n        ws.read_message(self.stop)\n        response = self.wait().result()\n        self.assertEqual(response, 'hello')\n        self.close_future.add_done_callback(lambda f: self.stop())\n        ws.close()\n        self.wait()\n\n    @gen_test\n    def test_websocket_http_fail(self):\n        with self.assertRaises(HTTPError) as cm:\n            yield websocket_connect(\n                'ws://localhost:%d/notfound' % self.get_http_port(),\n                io_loop=self.io_loop)\n        self.assertEqual(cm.exception.code, 404)\n\n    @gen_test\n    def test_websocket_http_success(self):\n        with self.assertRaises(WebSocketError):\n            yield websocket_connect(\n                'ws://localhost:%d/non_ws' % self.get_http_port(),\n                io_loop=self.io_loop)\n\n    @gen_test\n    def test_websocket_network_fail(self):\n        sock, port = bind_unused_port()\n        sock.close()\n        with self.assertRaises(IOError):\n            with ExpectLog(gen_log, \".*\"):\n                yield websocket_connect(\n                    'ws://localhost:%d/' % port,\n                    io_loop=self.io_loop,\n                    connect_timeout=3600)\n\n    @gen_test\n    def test_websocket_close_buffered_data(self):\n        ws = yield websocket_connect(\n            'ws://localhost:%d/echo' % self.get_http_port())\n        ws.write_message('hello')\n        ws.write_message('world')\n        ws.stream.close()\n        yield self.close_future\n\n    @gen_test\n    def test_websocket_headers(self):\n        # Ensure that arbitrary headers can be passed through websocket_connect.\n        ws = yield websocket_connect(\n            HTTPRequest('ws://localhost:%d/header' % self.get_http_port(),\n                        headers={'X-Test': 'hello'}))\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    @gen_test\n    def test_server_close_reason(self):\n        ws = yield websocket_connect(\n            'ws://localhost:%d/close_reason' % self.get_http_port())\n        msg = yield ws.read_message()\n        # A message of None means the other side closed the connection.\n        self.assertIs(msg, None)\n        self.assertEqual(ws.close_code, 1001)\n        self.assertEqual(ws.close_reason, \"goodbye\")\n\n    @gen_test\n    def test_client_close_reason(self):\n        ws = yield websocket_connect(\n            'ws://localhost:%d/echo' % self.get_http_port())\n        ws.close(1001, 'goodbye')\n        code, reason = yield self.close_future\n        self.assertEqual(code, 1001)\n        self.assertEqual(reason, 'goodbye')\n\n    @gen_test\n    def test_check_origin_valid(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        headers = {'Origin': 'http://localhost:%d' % port}\n\n        ws = yield websocket_connect(HTTPRequest(url, headers=headers),\n            io_loop=self.io_loop)\n        ws.write_message('hello')\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    @gen_test\n    def test_check_origin_with_path(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        headers = {'Origin': 'http://localhost:%d/something' % port}\n\n        ws = yield websocket_connect(HTTPRequest(url, headers=headers),\n            io_loop=self.io_loop)\n        ws.write_message('hello')\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    @gen_test\n    def test_check_origin_valid2(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        headers = {'Origin': 'localhost:%d' % port}\n\n        ws = yield websocket_connect(HTTPRequest(url, headers=headers),\n            io_loop=self.io_loop)\n        ws.write_message('hello')\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    @gen_test\n    def test_check_origin_invalid(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        # Host is localhost, which should not be accessible from some other\n        # domain\n        headers = {'Origin': 'http://somewhereelse.com'}\n\n        with self.assertRaises(HTTPError) as cm:\n            yield websocket_connect(HTTPRequest(url, headers=headers),\n                                    io_loop=self.io_loop)\n\n        self.assertEqual(cm.exception.code, 403)\n\n    @gen_test\n    def test_check_origin_invalid2(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        # subdomains should be invalid by default\n        headers = {'Origin': 'http://subtenant.somewhereelse.com',\n                   'Host': 'subtenant2.somewhereelse.com'}\n\n        with self.assertRaises(HTTPError) as cm:\n            yield websocket_connect(HTTPRequest(url, headers=headers),\n                                    io_loop=self.io_loop)\n\n        self.assertEqual(cm.exception.code, 403)",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 62,
                            "end_lineno": 235,
                            "parent": null
                        }
                    ],
                    "added_entities": [
                        {
                            "file_name": "tornado/test/websocket_test.py",
                            "type": "method",
                            "name": "WebSocketTest.test_check_origin_invalid",
                            "content": "class WebSocketTest(AsyncHTTPTestCase):\n    def get_app(self):\n        self.close_future = Future()\n        return Application([\n            ('/echo', EchoHandler, dict(close_future=self.close_future)),\n            ('/non_ws', NonWebSocketHandler),\n            ('/header', HeaderHandler, dict(close_future=self.close_future)),\n            ('/close_reason', CloseReasonHandler,\n             dict(close_future=self.close_future)),\n        ])\n\n    @gen_test\n    def test_websocket_gen(self):\n        ws = yield websocket_connect(\n            'ws://localhost:%d/echo' % self.get_http_port(),\n            io_loop=self.io_loop)\n        ws.write_message('hello')\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    def test_websocket_callbacks(self):\n        websocket_connect(\n            'ws://localhost:%d/echo' % self.get_http_port(),\n            io_loop=self.io_loop, callback=self.stop)\n        ws = self.wait().result()\n        ws.write_message('hello')\n        ws.read_message(self.stop)\n        response = self.wait().result()\n        self.assertEqual(response, 'hello')\n        self.close_future.add_done_callback(lambda f: self.stop())\n        ws.close()\n        self.wait()\n\n    @gen_test\n    def test_websocket_http_fail(self):\n        with self.assertRaises(HTTPError) as cm:\n            yield websocket_connect(\n                'ws://localhost:%d/notfound' % self.get_http_port(),\n                io_loop=self.io_loop)\n        self.assertEqual(cm.exception.code, 404)\n\n    @gen_test\n    def test_websocket_http_success(self):\n        with self.assertRaises(WebSocketError):\n            yield websocket_connect(\n                'ws://localhost:%d/non_ws' % self.get_http_port(),\n                io_loop=self.io_loop)\n\n    @gen_test\n    def test_websocket_network_fail(self):\n        sock, port = bind_unused_port()\n        sock.close()\n        with self.assertRaises(IOError):\n            with ExpectLog(gen_log, \".*\"):\n                yield websocket_connect(\n                    'ws://localhost:%d/' % port,\n                    io_loop=self.io_loop,\n                    connect_timeout=3600)\n\n    @gen_test\n    def test_websocket_close_buffered_data(self):\n        ws = yield websocket_connect(\n            'ws://localhost:%d/echo' % self.get_http_port())\n        ws.write_message('hello')\n        ws.write_message('world')\n        ws.stream.close()\n        yield self.close_future\n\n    @gen_test\n    def test_websocket_headers(self):\n        # Ensure that arbitrary headers can be passed through websocket_connect.\n        ws = yield websocket_connect(\n            HTTPRequest('ws://localhost:%d/header' % self.get_http_port(),\n                        headers={'X-Test': 'hello'}))\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    @gen_test\n    def test_server_close_reason(self):\n        ws = yield websocket_connect(\n            'ws://localhost:%d/close_reason' % self.get_http_port())\n        msg = yield ws.read_message()\n        # A message of None means the other side closed the connection.\n        self.assertIs(msg, None)\n        self.assertEqual(ws.close_code, 1001)\n        self.assertEqual(ws.close_reason, \"goodbye\")\n\n    @gen_test\n    def test_client_close_reason(self):\n        ws = yield websocket_connect(\n            'ws://localhost:%d/echo' % self.get_http_port())\n        ws.close(1001, 'goodbye')\n        code, reason = yield self.close_future\n        self.assertEqual(code, 1001)\n        self.assertEqual(reason, 'goodbye')\n\n    @gen_test\n    def test_check_origin_valid(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        headers = {'Origin': 'http://localhost:%d' % port}\n\n        ws = yield websocket_connect(HTTPRequest(url, headers=headers),\n            io_loop=self.io_loop)\n        ws.write_message('hello')\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    @gen_test\n    def test_check_origin_with_path(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        headers = {'Origin': 'http://localhost:%d/something' % port}\n\n        ws = yield websocket_connect(HTTPRequest(url, headers=headers),\n            io_loop=self.io_loop)\n        ws.write_message('hello')\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    @gen_test\n    def test_check_origin_valid2(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        headers = {'Origin': 'localhost:%d' % port}\n\n        ws = yield websocket_connect(HTTPRequest(url, headers=headers),\n            io_loop=self.io_loop)\n        ws.write_message('hello')\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    @gen_test\n    def test_check_origin_invalid(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        # Host is localhost, which should not be accessible from some other\n        # domain\n        headers = {'Origin': 'http://somewhereelse.com'}\n\n        with self.assertRaises(HTTPError) as cm:\n            yield websocket_connect(HTTPRequest(url, headers=headers),\n                                    io_loop=self.io_loop)\n\n        self.assertEqual(cm.exception.code, 403)\n\n    @gen_test\n    def test_check_origin_invalid2(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        # subdomains should be invalid by default\n        headers = {'Origin': 'http://subtenant.somewhereelse.com',\n                   'Host': 'subtenant2.somewhereelse.com'}\n\n        with self.assertRaises(HTTPError) as cm:\n            yield websocket_connect(HTTPRequest(url, headers=headers),\n                                    io_loop=self.io_loop)\n\n        self.assertEqual(cm.exception.code, 403)",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 208,
                            "end_lineno": 220,
                            "parent": {
                                "file_name": "tornado/test/websocket_test.py",
                                "type": "class",
                                "name": "WebSocketTest",
                                "content": "class WebSocketTest(AsyncHTTPTestCase):\n    def get_app(self):\n        self.close_future = Future()\n        return Application([\n            ('/echo', EchoHandler, dict(close_future=self.close_future)),\n            ('/non_ws', NonWebSocketHandler),\n            ('/header', HeaderHandler, dict(close_future=self.close_future)),\n            ('/close_reason', CloseReasonHandler,\n             dict(close_future=self.close_future)),\n        ])\n\n    @gen_test\n    def test_websocket_gen(self):\n        ws = yield websocket_connect(\n            'ws://localhost:%d/echo' % self.get_http_port(),\n            io_loop=self.io_loop)\n        ws.write_message('hello')\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    def test_websocket_callbacks(self):\n        websocket_connect(\n            'ws://localhost:%d/echo' % self.get_http_port(),\n            io_loop=self.io_loop, callback=self.stop)\n        ws = self.wait().result()\n        ws.write_message('hello')\n        ws.read_message(self.stop)\n        response = self.wait().result()\n        self.assertEqual(response, 'hello')\n        self.close_future.add_done_callback(lambda f: self.stop())\n        ws.close()\n        self.wait()\n\n    @gen_test\n    def test_websocket_http_fail(self):\n        with self.assertRaises(HTTPError) as cm:\n            yield websocket_connect(\n                'ws://localhost:%d/notfound' % self.get_http_port(),\n                io_loop=self.io_loop)\n        self.assertEqual(cm.exception.code, 404)\n\n    @gen_test\n    def test_websocket_http_success(self):\n        with self.assertRaises(WebSocketError):\n            yield websocket_connect(\n                'ws://localhost:%d/non_ws' % self.get_http_port(),\n                io_loop=self.io_loop)\n\n    @gen_test\n    def test_websocket_network_fail(self):\n        sock, port = bind_unused_port()\n        sock.close()\n        with self.assertRaises(IOError):\n            with ExpectLog(gen_log, \".*\"):\n                yield websocket_connect(\n                    'ws://localhost:%d/' % port,\n                    io_loop=self.io_loop,\n                    connect_timeout=3600)\n\n    @gen_test\n    def test_websocket_close_buffered_data(self):\n        ws = yield websocket_connect(\n            'ws://localhost:%d/echo' % self.get_http_port())\n        ws.write_message('hello')\n        ws.write_message('world')\n        ws.stream.close()\n        yield self.close_future\n\n    @gen_test\n    def test_websocket_headers(self):\n        # Ensure that arbitrary headers can be passed through websocket_connect.\n        ws = yield websocket_connect(\n            HTTPRequest('ws://localhost:%d/header' % self.get_http_port(),\n                        headers={'X-Test': 'hello'}))\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    @gen_test\n    def test_server_close_reason(self):\n        ws = yield websocket_connect(\n            'ws://localhost:%d/close_reason' % self.get_http_port())\n        msg = yield ws.read_message()\n        # A message of None means the other side closed the connection.\n        self.assertIs(msg, None)\n        self.assertEqual(ws.close_code, 1001)\n        self.assertEqual(ws.close_reason, \"goodbye\")\n\n    @gen_test\n    def test_client_close_reason(self):\n        ws = yield websocket_connect(\n            'ws://localhost:%d/echo' % self.get_http_port())\n        ws.close(1001, 'goodbye')\n        code, reason = yield self.close_future\n        self.assertEqual(code, 1001)\n        self.assertEqual(reason, 'goodbye')\n\n    @gen_test\n    def test_check_origin_valid(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        headers = {'Origin': 'http://localhost:%d' % port}\n\n        ws = yield websocket_connect(HTTPRequest(url, headers=headers),\n            io_loop=self.io_loop)\n        ws.write_message('hello')\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    @gen_test\n    def test_check_origin_with_path(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        headers = {'Origin': 'http://localhost:%d/something' % port}\n\n        ws = yield websocket_connect(HTTPRequest(url, headers=headers),\n            io_loop=self.io_loop)\n        ws.write_message('hello')\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    @gen_test\n    def test_check_origin_valid2(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        headers = {'Origin': 'localhost:%d' % port}\n\n        ws = yield websocket_connect(HTTPRequest(url, headers=headers),\n            io_loop=self.io_loop)\n        ws.write_message('hello')\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    @gen_test\n    def test_check_origin_invalid(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        # Host is localhost, which should not be accessible from some other\n        # domain\n        headers = {'Origin': 'http://somewhereelse.com'}\n\n        with self.assertRaises(HTTPError) as cm:\n            yield websocket_connect(HTTPRequest(url, headers=headers),\n                                    io_loop=self.io_loop)\n\n        self.assertEqual(cm.exception.code, 403)\n\n    @gen_test\n    def test_check_origin_invalid2(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        # subdomains should be invalid by default\n        headers = {'Origin': 'http://subtenant.somewhereelse.com',\n                   'Host': 'subtenant2.somewhereelse.com'}\n\n        with self.assertRaises(HTTPError) as cm:\n            yield websocket_connect(HTTPRequest(url, headers=headers),\n                                    io_loop=self.io_loop)\n\n        self.assertEqual(cm.exception.code, 403)",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 62,
                                "end_lineno": 235,
                                "parent": null
                            }
                        },
                        {
                            "file_name": "tornado/test/websocket_test.py",
                            "type": "method",
                            "name": "WebSocketTest.test_check_origin_valid",
                            "content": "class WebSocketTest(AsyncHTTPTestCase):\n    def get_app(self):\n        self.close_future = Future()\n        return Application([\n            ('/echo', EchoHandler, dict(close_future=self.close_future)),\n            ('/non_ws', NonWebSocketHandler),\n            ('/header', HeaderHandler, dict(close_future=self.close_future)),\n            ('/close_reason', CloseReasonHandler,\n             dict(close_future=self.close_future)),\n        ])\n\n    @gen_test\n    def test_websocket_gen(self):\n        ws = yield websocket_connect(\n            'ws://localhost:%d/echo' % self.get_http_port(),\n            io_loop=self.io_loop)\n        ws.write_message('hello')\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    def test_websocket_callbacks(self):\n        websocket_connect(\n            'ws://localhost:%d/echo' % self.get_http_port(),\n            io_loop=self.io_loop, callback=self.stop)\n        ws = self.wait().result()\n        ws.write_message('hello')\n        ws.read_message(self.stop)\n        response = self.wait().result()\n        self.assertEqual(response, 'hello')\n        self.close_future.add_done_callback(lambda f: self.stop())\n        ws.close()\n        self.wait()\n\n    @gen_test\n    def test_websocket_http_fail(self):\n        with self.assertRaises(HTTPError) as cm:\n            yield websocket_connect(\n                'ws://localhost:%d/notfound' % self.get_http_port(),\n                io_loop=self.io_loop)\n        self.assertEqual(cm.exception.code, 404)\n\n    @gen_test\n    def test_websocket_http_success(self):\n        with self.assertRaises(WebSocketError):\n            yield websocket_connect(\n                'ws://localhost:%d/non_ws' % self.get_http_port(),\n                io_loop=self.io_loop)\n\n    @gen_test\n    def test_websocket_network_fail(self):\n        sock, port = bind_unused_port()\n        sock.close()\n        with self.assertRaises(IOError):\n            with ExpectLog(gen_log, \".*\"):\n                yield websocket_connect(\n                    'ws://localhost:%d/' % port,\n                    io_loop=self.io_loop,\n                    connect_timeout=3600)\n\n    @gen_test\n    def test_websocket_close_buffered_data(self):\n        ws = yield websocket_connect(\n            'ws://localhost:%d/echo' % self.get_http_port())\n        ws.write_message('hello')\n        ws.write_message('world')\n        ws.stream.close()\n        yield self.close_future\n\n    @gen_test\n    def test_websocket_headers(self):\n        # Ensure that arbitrary headers can be passed through websocket_connect.\n        ws = yield websocket_connect(\n            HTTPRequest('ws://localhost:%d/header' % self.get_http_port(),\n                        headers={'X-Test': 'hello'}))\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    @gen_test\n    def test_server_close_reason(self):\n        ws = yield websocket_connect(\n            'ws://localhost:%d/close_reason' % self.get_http_port())\n        msg = yield ws.read_message()\n        # A message of None means the other side closed the connection.\n        self.assertIs(msg, None)\n        self.assertEqual(ws.close_code, 1001)\n        self.assertEqual(ws.close_reason, \"goodbye\")\n\n    @gen_test\n    def test_client_close_reason(self):\n        ws = yield websocket_connect(\n            'ws://localhost:%d/echo' % self.get_http_port())\n        ws.close(1001, 'goodbye')\n        code, reason = yield self.close_future\n        self.assertEqual(code, 1001)\n        self.assertEqual(reason, 'goodbye')\n\n    @gen_test\n    def test_check_origin_valid(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        headers = {'Origin': 'http://localhost:%d' % port}\n\n        ws = yield websocket_connect(HTTPRequest(url, headers=headers),\n            io_loop=self.io_loop)\n        ws.write_message('hello')\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    @gen_test\n    def test_check_origin_with_path(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        headers = {'Origin': 'http://localhost:%d/something' % port}\n\n        ws = yield websocket_connect(HTTPRequest(url, headers=headers),\n            io_loop=self.io_loop)\n        ws.write_message('hello')\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    @gen_test\n    def test_check_origin_valid2(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        headers = {'Origin': 'localhost:%d' % port}\n\n        ws = yield websocket_connect(HTTPRequest(url, headers=headers),\n            io_loop=self.io_loop)\n        ws.write_message('hello')\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    @gen_test\n    def test_check_origin_invalid(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        # Host is localhost, which should not be accessible from some other\n        # domain\n        headers = {'Origin': 'http://somewhereelse.com'}\n\n        with self.assertRaises(HTTPError) as cm:\n            yield websocket_connect(HTTPRequest(url, headers=headers),\n                                    io_loop=self.io_loop)\n\n        self.assertEqual(cm.exception.code, 403)\n\n    @gen_test\n    def test_check_origin_invalid2(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        # subdomains should be invalid by default\n        headers = {'Origin': 'http://subtenant.somewhereelse.com',\n                   'Host': 'subtenant2.somewhereelse.com'}\n\n        with self.assertRaises(HTTPError) as cm:\n            yield websocket_connect(HTTPRequest(url, headers=headers),\n                                    io_loop=self.io_loop)\n\n        self.assertEqual(cm.exception.code, 403)",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 163,
                            "end_lineno": 175,
                            "parent": {
                                "file_name": "tornado/test/websocket_test.py",
                                "type": "class",
                                "name": "WebSocketTest",
                                "content": "class WebSocketTest(AsyncHTTPTestCase):\n    def get_app(self):\n        self.close_future = Future()\n        return Application([\n            ('/echo', EchoHandler, dict(close_future=self.close_future)),\n            ('/non_ws', NonWebSocketHandler),\n            ('/header', HeaderHandler, dict(close_future=self.close_future)),\n            ('/close_reason', CloseReasonHandler,\n             dict(close_future=self.close_future)),\n        ])\n\n    @gen_test\n    def test_websocket_gen(self):\n        ws = yield websocket_connect(\n            'ws://localhost:%d/echo' % self.get_http_port(),\n            io_loop=self.io_loop)\n        ws.write_message('hello')\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    def test_websocket_callbacks(self):\n        websocket_connect(\n            'ws://localhost:%d/echo' % self.get_http_port(),\n            io_loop=self.io_loop, callback=self.stop)\n        ws = self.wait().result()\n        ws.write_message('hello')\n        ws.read_message(self.stop)\n        response = self.wait().result()\n        self.assertEqual(response, 'hello')\n        self.close_future.add_done_callback(lambda f: self.stop())\n        ws.close()\n        self.wait()\n\n    @gen_test\n    def test_websocket_http_fail(self):\n        with self.assertRaises(HTTPError) as cm:\n            yield websocket_connect(\n                'ws://localhost:%d/notfound' % self.get_http_port(),\n                io_loop=self.io_loop)\n        self.assertEqual(cm.exception.code, 404)\n\n    @gen_test\n    def test_websocket_http_success(self):\n        with self.assertRaises(WebSocketError):\n            yield websocket_connect(\n                'ws://localhost:%d/non_ws' % self.get_http_port(),\n                io_loop=self.io_loop)\n\n    @gen_test\n    def test_websocket_network_fail(self):\n        sock, port = bind_unused_port()\n        sock.close()\n        with self.assertRaises(IOError):\n            with ExpectLog(gen_log, \".*\"):\n                yield websocket_connect(\n                    'ws://localhost:%d/' % port,\n                    io_loop=self.io_loop,\n                    connect_timeout=3600)\n\n    @gen_test\n    def test_websocket_close_buffered_data(self):\n        ws = yield websocket_connect(\n            'ws://localhost:%d/echo' % self.get_http_port())\n        ws.write_message('hello')\n        ws.write_message('world')\n        ws.stream.close()\n        yield self.close_future\n\n    @gen_test\n    def test_websocket_headers(self):\n        # Ensure that arbitrary headers can be passed through websocket_connect.\n        ws = yield websocket_connect(\n            HTTPRequest('ws://localhost:%d/header' % self.get_http_port(),\n                        headers={'X-Test': 'hello'}))\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    @gen_test\n    def test_server_close_reason(self):\n        ws = yield websocket_connect(\n            'ws://localhost:%d/close_reason' % self.get_http_port())\n        msg = yield ws.read_message()\n        # A message of None means the other side closed the connection.\n        self.assertIs(msg, None)\n        self.assertEqual(ws.close_code, 1001)\n        self.assertEqual(ws.close_reason, \"goodbye\")\n\n    @gen_test\n    def test_client_close_reason(self):\n        ws = yield websocket_connect(\n            'ws://localhost:%d/echo' % self.get_http_port())\n        ws.close(1001, 'goodbye')\n        code, reason = yield self.close_future\n        self.assertEqual(code, 1001)\n        self.assertEqual(reason, 'goodbye')\n\n    @gen_test\n    def test_check_origin_valid(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        headers = {'Origin': 'http://localhost:%d' % port}\n\n        ws = yield websocket_connect(HTTPRequest(url, headers=headers),\n            io_loop=self.io_loop)\n        ws.write_message('hello')\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    @gen_test\n    def test_check_origin_with_path(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        headers = {'Origin': 'http://localhost:%d/something' % port}\n\n        ws = yield websocket_connect(HTTPRequest(url, headers=headers),\n            io_loop=self.io_loop)\n        ws.write_message('hello')\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    @gen_test\n    def test_check_origin_valid2(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        headers = {'Origin': 'localhost:%d' % port}\n\n        ws = yield websocket_connect(HTTPRequest(url, headers=headers),\n            io_loop=self.io_loop)\n        ws.write_message('hello')\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    @gen_test\n    def test_check_origin_invalid(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        # Host is localhost, which should not be accessible from some other\n        # domain\n        headers = {'Origin': 'http://somewhereelse.com'}\n\n        with self.assertRaises(HTTPError) as cm:\n            yield websocket_connect(HTTPRequest(url, headers=headers),\n                                    io_loop=self.io_loop)\n\n        self.assertEqual(cm.exception.code, 403)\n\n    @gen_test\n    def test_check_origin_invalid2(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        # subdomains should be invalid by default\n        headers = {'Origin': 'http://subtenant.somewhereelse.com',\n                   'Host': 'subtenant2.somewhereelse.com'}\n\n        with self.assertRaises(HTTPError) as cm:\n            yield websocket_connect(HTTPRequest(url, headers=headers),\n                                    io_loop=self.io_loop)\n\n        self.assertEqual(cm.exception.code, 403)",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 62,
                                "end_lineno": 235,
                                "parent": null
                            }
                        },
                        {
                            "file_name": "tornado/test/websocket_test.py",
                            "type": "method",
                            "name": "WebSocketTest.test_check_origin_valid2",
                            "content": "class WebSocketTest(AsyncHTTPTestCase):\n    def get_app(self):\n        self.close_future = Future()\n        return Application([\n            ('/echo', EchoHandler, dict(close_future=self.close_future)),\n            ('/non_ws', NonWebSocketHandler),\n            ('/header', HeaderHandler, dict(close_future=self.close_future)),\n            ('/close_reason', CloseReasonHandler,\n             dict(close_future=self.close_future)),\n        ])\n\n    @gen_test\n    def test_websocket_gen(self):\n        ws = yield websocket_connect(\n            'ws://localhost:%d/echo' % self.get_http_port(),\n            io_loop=self.io_loop)\n        ws.write_message('hello')\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    def test_websocket_callbacks(self):\n        websocket_connect(\n            'ws://localhost:%d/echo' % self.get_http_port(),\n            io_loop=self.io_loop, callback=self.stop)\n        ws = self.wait().result()\n        ws.write_message('hello')\n        ws.read_message(self.stop)\n        response = self.wait().result()\n        self.assertEqual(response, 'hello')\n        self.close_future.add_done_callback(lambda f: self.stop())\n        ws.close()\n        self.wait()\n\n    @gen_test\n    def test_websocket_http_fail(self):\n        with self.assertRaises(HTTPError) as cm:\n            yield websocket_connect(\n                'ws://localhost:%d/notfound' % self.get_http_port(),\n                io_loop=self.io_loop)\n        self.assertEqual(cm.exception.code, 404)\n\n    @gen_test\n    def test_websocket_http_success(self):\n        with self.assertRaises(WebSocketError):\n            yield websocket_connect(\n                'ws://localhost:%d/non_ws' % self.get_http_port(),\n                io_loop=self.io_loop)\n\n    @gen_test\n    def test_websocket_network_fail(self):\n        sock, port = bind_unused_port()\n        sock.close()\n        with self.assertRaises(IOError):\n            with ExpectLog(gen_log, \".*\"):\n                yield websocket_connect(\n                    'ws://localhost:%d/' % port,\n                    io_loop=self.io_loop,\n                    connect_timeout=3600)\n\n    @gen_test\n    def test_websocket_close_buffered_data(self):\n        ws = yield websocket_connect(\n            'ws://localhost:%d/echo' % self.get_http_port())\n        ws.write_message('hello')\n        ws.write_message('world')\n        ws.stream.close()\n        yield self.close_future\n\n    @gen_test\n    def test_websocket_headers(self):\n        # Ensure that arbitrary headers can be passed through websocket_connect.\n        ws = yield websocket_connect(\n            HTTPRequest('ws://localhost:%d/header' % self.get_http_port(),\n                        headers={'X-Test': 'hello'}))\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    @gen_test\n    def test_server_close_reason(self):\n        ws = yield websocket_connect(\n            'ws://localhost:%d/close_reason' % self.get_http_port())\n        msg = yield ws.read_message()\n        # A message of None means the other side closed the connection.\n        self.assertIs(msg, None)\n        self.assertEqual(ws.close_code, 1001)\n        self.assertEqual(ws.close_reason, \"goodbye\")\n\n    @gen_test\n    def test_client_close_reason(self):\n        ws = yield websocket_connect(\n            'ws://localhost:%d/echo' % self.get_http_port())\n        ws.close(1001, 'goodbye')\n        code, reason = yield self.close_future\n        self.assertEqual(code, 1001)\n        self.assertEqual(reason, 'goodbye')\n\n    @gen_test\n    def test_check_origin_valid(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        headers = {'Origin': 'http://localhost:%d' % port}\n\n        ws = yield websocket_connect(HTTPRequest(url, headers=headers),\n            io_loop=self.io_loop)\n        ws.write_message('hello')\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    @gen_test\n    def test_check_origin_with_path(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        headers = {'Origin': 'http://localhost:%d/something' % port}\n\n        ws = yield websocket_connect(HTTPRequest(url, headers=headers),\n            io_loop=self.io_loop)\n        ws.write_message('hello')\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    @gen_test\n    def test_check_origin_valid2(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        headers = {'Origin': 'localhost:%d' % port}\n\n        ws = yield websocket_connect(HTTPRequest(url, headers=headers),\n            io_loop=self.io_loop)\n        ws.write_message('hello')\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    @gen_test\n    def test_check_origin_invalid(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        # Host is localhost, which should not be accessible from some other\n        # domain\n        headers = {'Origin': 'http://somewhereelse.com'}\n\n        with self.assertRaises(HTTPError) as cm:\n            yield websocket_connect(HTTPRequest(url, headers=headers),\n                                    io_loop=self.io_loop)\n\n        self.assertEqual(cm.exception.code, 403)\n\n    @gen_test\n    def test_check_origin_invalid2(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        # subdomains should be invalid by default\n        headers = {'Origin': 'http://subtenant.somewhereelse.com',\n                   'Host': 'subtenant2.somewhereelse.com'}\n\n        with self.assertRaises(HTTPError) as cm:\n            yield websocket_connect(HTTPRequest(url, headers=headers),\n                                    io_loop=self.io_loop)\n\n        self.assertEqual(cm.exception.code, 403)",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 193,
                            "end_lineno": 205,
                            "parent": {
                                "file_name": "tornado/test/websocket_test.py",
                                "type": "class",
                                "name": "WebSocketTest",
                                "content": "class WebSocketTest(AsyncHTTPTestCase):\n    def get_app(self):\n        self.close_future = Future()\n        return Application([\n            ('/echo', EchoHandler, dict(close_future=self.close_future)),\n            ('/non_ws', NonWebSocketHandler),\n            ('/header', HeaderHandler, dict(close_future=self.close_future)),\n            ('/close_reason', CloseReasonHandler,\n             dict(close_future=self.close_future)),\n        ])\n\n    @gen_test\n    def test_websocket_gen(self):\n        ws = yield websocket_connect(\n            'ws://localhost:%d/echo' % self.get_http_port(),\n            io_loop=self.io_loop)\n        ws.write_message('hello')\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    def test_websocket_callbacks(self):\n        websocket_connect(\n            'ws://localhost:%d/echo' % self.get_http_port(),\n            io_loop=self.io_loop, callback=self.stop)\n        ws = self.wait().result()\n        ws.write_message('hello')\n        ws.read_message(self.stop)\n        response = self.wait().result()\n        self.assertEqual(response, 'hello')\n        self.close_future.add_done_callback(lambda f: self.stop())\n        ws.close()\n        self.wait()\n\n    @gen_test\n    def test_websocket_http_fail(self):\n        with self.assertRaises(HTTPError) as cm:\n            yield websocket_connect(\n                'ws://localhost:%d/notfound' % self.get_http_port(),\n                io_loop=self.io_loop)\n        self.assertEqual(cm.exception.code, 404)\n\n    @gen_test\n    def test_websocket_http_success(self):\n        with self.assertRaises(WebSocketError):\n            yield websocket_connect(\n                'ws://localhost:%d/non_ws' % self.get_http_port(),\n                io_loop=self.io_loop)\n\n    @gen_test\n    def test_websocket_network_fail(self):\n        sock, port = bind_unused_port()\n        sock.close()\n        with self.assertRaises(IOError):\n            with ExpectLog(gen_log, \".*\"):\n                yield websocket_connect(\n                    'ws://localhost:%d/' % port,\n                    io_loop=self.io_loop,\n                    connect_timeout=3600)\n\n    @gen_test\n    def test_websocket_close_buffered_data(self):\n        ws = yield websocket_connect(\n            'ws://localhost:%d/echo' % self.get_http_port())\n        ws.write_message('hello')\n        ws.write_message('world')\n        ws.stream.close()\n        yield self.close_future\n\n    @gen_test\n    def test_websocket_headers(self):\n        # Ensure that arbitrary headers can be passed through websocket_connect.\n        ws = yield websocket_connect(\n            HTTPRequest('ws://localhost:%d/header' % self.get_http_port(),\n                        headers={'X-Test': 'hello'}))\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    @gen_test\n    def test_server_close_reason(self):\n        ws = yield websocket_connect(\n            'ws://localhost:%d/close_reason' % self.get_http_port())\n        msg = yield ws.read_message()\n        # A message of None means the other side closed the connection.\n        self.assertIs(msg, None)\n        self.assertEqual(ws.close_code, 1001)\n        self.assertEqual(ws.close_reason, \"goodbye\")\n\n    @gen_test\n    def test_client_close_reason(self):\n        ws = yield websocket_connect(\n            'ws://localhost:%d/echo' % self.get_http_port())\n        ws.close(1001, 'goodbye')\n        code, reason = yield self.close_future\n        self.assertEqual(code, 1001)\n        self.assertEqual(reason, 'goodbye')\n\n    @gen_test\n    def test_check_origin_valid(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        headers = {'Origin': 'http://localhost:%d' % port}\n\n        ws = yield websocket_connect(HTTPRequest(url, headers=headers),\n            io_loop=self.io_loop)\n        ws.write_message('hello')\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    @gen_test\n    def test_check_origin_with_path(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        headers = {'Origin': 'http://localhost:%d/something' % port}\n\n        ws = yield websocket_connect(HTTPRequest(url, headers=headers),\n            io_loop=self.io_loop)\n        ws.write_message('hello')\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    @gen_test\n    def test_check_origin_valid2(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        headers = {'Origin': 'localhost:%d' % port}\n\n        ws = yield websocket_connect(HTTPRequest(url, headers=headers),\n            io_loop=self.io_loop)\n        ws.write_message('hello')\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    @gen_test\n    def test_check_origin_invalid(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        # Host is localhost, which should not be accessible from some other\n        # domain\n        headers = {'Origin': 'http://somewhereelse.com'}\n\n        with self.assertRaises(HTTPError) as cm:\n            yield websocket_connect(HTTPRequest(url, headers=headers),\n                                    io_loop=self.io_loop)\n\n        self.assertEqual(cm.exception.code, 403)\n\n    @gen_test\n    def test_check_origin_invalid2(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        # subdomains should be invalid by default\n        headers = {'Origin': 'http://subtenant.somewhereelse.com',\n                   'Host': 'subtenant2.somewhereelse.com'}\n\n        with self.assertRaises(HTTPError) as cm:\n            yield websocket_connect(HTTPRequest(url, headers=headers),\n                                    io_loop=self.io_loop)\n\n        self.assertEqual(cm.exception.code, 403)",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 62,
                                "end_lineno": 235,
                                "parent": null
                            }
                        },
                        {
                            "file_name": "tornado/test/websocket_test.py",
                            "type": "method",
                            "name": "WebSocketTest.test_check_origin_invalid2",
                            "content": "class WebSocketTest(AsyncHTTPTestCase):\n    def get_app(self):\n        self.close_future = Future()\n        return Application([\n            ('/echo', EchoHandler, dict(close_future=self.close_future)),\n            ('/non_ws', NonWebSocketHandler),\n            ('/header', HeaderHandler, dict(close_future=self.close_future)),\n            ('/close_reason', CloseReasonHandler,\n             dict(close_future=self.close_future)),\n        ])\n\n    @gen_test\n    def test_websocket_gen(self):\n        ws = yield websocket_connect(\n            'ws://localhost:%d/echo' % self.get_http_port(),\n            io_loop=self.io_loop)\n        ws.write_message('hello')\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    def test_websocket_callbacks(self):\n        websocket_connect(\n            'ws://localhost:%d/echo' % self.get_http_port(),\n            io_loop=self.io_loop, callback=self.stop)\n        ws = self.wait().result()\n        ws.write_message('hello')\n        ws.read_message(self.stop)\n        response = self.wait().result()\n        self.assertEqual(response, 'hello')\n        self.close_future.add_done_callback(lambda f: self.stop())\n        ws.close()\n        self.wait()\n\n    @gen_test\n    def test_websocket_http_fail(self):\n        with self.assertRaises(HTTPError) as cm:\n            yield websocket_connect(\n                'ws://localhost:%d/notfound' % self.get_http_port(),\n                io_loop=self.io_loop)\n        self.assertEqual(cm.exception.code, 404)\n\n    @gen_test\n    def test_websocket_http_success(self):\n        with self.assertRaises(WebSocketError):\n            yield websocket_connect(\n                'ws://localhost:%d/non_ws' % self.get_http_port(),\n                io_loop=self.io_loop)\n\n    @gen_test\n    def test_websocket_network_fail(self):\n        sock, port = bind_unused_port()\n        sock.close()\n        with self.assertRaises(IOError):\n            with ExpectLog(gen_log, \".*\"):\n                yield websocket_connect(\n                    'ws://localhost:%d/' % port,\n                    io_loop=self.io_loop,\n                    connect_timeout=3600)\n\n    @gen_test\n    def test_websocket_close_buffered_data(self):\n        ws = yield websocket_connect(\n            'ws://localhost:%d/echo' % self.get_http_port())\n        ws.write_message('hello')\n        ws.write_message('world')\n        ws.stream.close()\n        yield self.close_future\n\n    @gen_test\n    def test_websocket_headers(self):\n        # Ensure that arbitrary headers can be passed through websocket_connect.\n        ws = yield websocket_connect(\n            HTTPRequest('ws://localhost:%d/header' % self.get_http_port(),\n                        headers={'X-Test': 'hello'}))\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    @gen_test\n    def test_server_close_reason(self):\n        ws = yield websocket_connect(\n            'ws://localhost:%d/close_reason' % self.get_http_port())\n        msg = yield ws.read_message()\n        # A message of None means the other side closed the connection.\n        self.assertIs(msg, None)\n        self.assertEqual(ws.close_code, 1001)\n        self.assertEqual(ws.close_reason, \"goodbye\")\n\n    @gen_test\n    def test_client_close_reason(self):\n        ws = yield websocket_connect(\n            'ws://localhost:%d/echo' % self.get_http_port())\n        ws.close(1001, 'goodbye')\n        code, reason = yield self.close_future\n        self.assertEqual(code, 1001)\n        self.assertEqual(reason, 'goodbye')\n\n    @gen_test\n    def test_check_origin_valid(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        headers = {'Origin': 'http://localhost:%d' % port}\n\n        ws = yield websocket_connect(HTTPRequest(url, headers=headers),\n            io_loop=self.io_loop)\n        ws.write_message('hello')\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    @gen_test\n    def test_check_origin_with_path(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        headers = {'Origin': 'http://localhost:%d/something' % port}\n\n        ws = yield websocket_connect(HTTPRequest(url, headers=headers),\n            io_loop=self.io_loop)\n        ws.write_message('hello')\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    @gen_test\n    def test_check_origin_valid2(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        headers = {'Origin': 'localhost:%d' % port}\n\n        ws = yield websocket_connect(HTTPRequest(url, headers=headers),\n            io_loop=self.io_loop)\n        ws.write_message('hello')\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    @gen_test\n    def test_check_origin_invalid(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        # Host is localhost, which should not be accessible from some other\n        # domain\n        headers = {'Origin': 'http://somewhereelse.com'}\n\n        with self.assertRaises(HTTPError) as cm:\n            yield websocket_connect(HTTPRequest(url, headers=headers),\n                                    io_loop=self.io_loop)\n\n        self.assertEqual(cm.exception.code, 403)\n\n    @gen_test\n    def test_check_origin_invalid2(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        # subdomains should be invalid by default\n        headers = {'Origin': 'http://subtenant.somewhereelse.com',\n                   'Host': 'subtenant2.somewhereelse.com'}\n\n        with self.assertRaises(HTTPError) as cm:\n            yield websocket_connect(HTTPRequest(url, headers=headers),\n                                    io_loop=self.io_loop)\n\n        self.assertEqual(cm.exception.code, 403)",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 223,
                            "end_lineno": 235,
                            "parent": {
                                "file_name": "tornado/test/websocket_test.py",
                                "type": "class",
                                "name": "WebSocketTest",
                                "content": "class WebSocketTest(AsyncHTTPTestCase):\n    def get_app(self):\n        self.close_future = Future()\n        return Application([\n            ('/echo', EchoHandler, dict(close_future=self.close_future)),\n            ('/non_ws', NonWebSocketHandler),\n            ('/header', HeaderHandler, dict(close_future=self.close_future)),\n            ('/close_reason', CloseReasonHandler,\n             dict(close_future=self.close_future)),\n        ])\n\n    @gen_test\n    def test_websocket_gen(self):\n        ws = yield websocket_connect(\n            'ws://localhost:%d/echo' % self.get_http_port(),\n            io_loop=self.io_loop)\n        ws.write_message('hello')\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    def test_websocket_callbacks(self):\n        websocket_connect(\n            'ws://localhost:%d/echo' % self.get_http_port(),\n            io_loop=self.io_loop, callback=self.stop)\n        ws = self.wait().result()\n        ws.write_message('hello')\n        ws.read_message(self.stop)\n        response = self.wait().result()\n        self.assertEqual(response, 'hello')\n        self.close_future.add_done_callback(lambda f: self.stop())\n        ws.close()\n        self.wait()\n\n    @gen_test\n    def test_websocket_http_fail(self):\n        with self.assertRaises(HTTPError) as cm:\n            yield websocket_connect(\n                'ws://localhost:%d/notfound' % self.get_http_port(),\n                io_loop=self.io_loop)\n        self.assertEqual(cm.exception.code, 404)\n\n    @gen_test\n    def test_websocket_http_success(self):\n        with self.assertRaises(WebSocketError):\n            yield websocket_connect(\n                'ws://localhost:%d/non_ws' % self.get_http_port(),\n                io_loop=self.io_loop)\n\n    @gen_test\n    def test_websocket_network_fail(self):\n        sock, port = bind_unused_port()\n        sock.close()\n        with self.assertRaises(IOError):\n            with ExpectLog(gen_log, \".*\"):\n                yield websocket_connect(\n                    'ws://localhost:%d/' % port,\n                    io_loop=self.io_loop,\n                    connect_timeout=3600)\n\n    @gen_test\n    def test_websocket_close_buffered_data(self):\n        ws = yield websocket_connect(\n            'ws://localhost:%d/echo' % self.get_http_port())\n        ws.write_message('hello')\n        ws.write_message('world')\n        ws.stream.close()\n        yield self.close_future\n\n    @gen_test\n    def test_websocket_headers(self):\n        # Ensure that arbitrary headers can be passed through websocket_connect.\n        ws = yield websocket_connect(\n            HTTPRequest('ws://localhost:%d/header' % self.get_http_port(),\n                        headers={'X-Test': 'hello'}))\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    @gen_test\n    def test_server_close_reason(self):\n        ws = yield websocket_connect(\n            'ws://localhost:%d/close_reason' % self.get_http_port())\n        msg = yield ws.read_message()\n        # A message of None means the other side closed the connection.\n        self.assertIs(msg, None)\n        self.assertEqual(ws.close_code, 1001)\n        self.assertEqual(ws.close_reason, \"goodbye\")\n\n    @gen_test\n    def test_client_close_reason(self):\n        ws = yield websocket_connect(\n            'ws://localhost:%d/echo' % self.get_http_port())\n        ws.close(1001, 'goodbye')\n        code, reason = yield self.close_future\n        self.assertEqual(code, 1001)\n        self.assertEqual(reason, 'goodbye')\n\n    @gen_test\n    def test_check_origin_valid(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        headers = {'Origin': 'http://localhost:%d' % port}\n\n        ws = yield websocket_connect(HTTPRequest(url, headers=headers),\n            io_loop=self.io_loop)\n        ws.write_message('hello')\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    @gen_test\n    def test_check_origin_with_path(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        headers = {'Origin': 'http://localhost:%d/something' % port}\n\n        ws = yield websocket_connect(HTTPRequest(url, headers=headers),\n            io_loop=self.io_loop)\n        ws.write_message('hello')\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    @gen_test\n    def test_check_origin_valid2(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        headers = {'Origin': 'localhost:%d' % port}\n\n        ws = yield websocket_connect(HTTPRequest(url, headers=headers),\n            io_loop=self.io_loop)\n        ws.write_message('hello')\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    @gen_test\n    def test_check_origin_invalid(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        # Host is localhost, which should not be accessible from some other\n        # domain\n        headers = {'Origin': 'http://somewhereelse.com'}\n\n        with self.assertRaises(HTTPError) as cm:\n            yield websocket_connect(HTTPRequest(url, headers=headers),\n                                    io_loop=self.io_loop)\n\n        self.assertEqual(cm.exception.code, 403)\n\n    @gen_test\n    def test_check_origin_invalid2(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        # subdomains should be invalid by default\n        headers = {'Origin': 'http://subtenant.somewhereelse.com',\n                   'Host': 'subtenant2.somewhereelse.com'}\n\n        with self.assertRaises(HTTPError) as cm:\n            yield websocket_connect(HTTPRequest(url, headers=headers),\n                                    io_loop=self.io_loop)\n\n        self.assertEqual(cm.exception.code, 403)",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 62,
                                "end_lineno": 235,
                                "parent": null
                            }
                        },
                        {
                            "file_name": "tornado/test/websocket_test.py",
                            "type": "method",
                            "name": "WebSocketTest.test_check_origin_with_path",
                            "content": "class WebSocketTest(AsyncHTTPTestCase):\n    def get_app(self):\n        self.close_future = Future()\n        return Application([\n            ('/echo', EchoHandler, dict(close_future=self.close_future)),\n            ('/non_ws', NonWebSocketHandler),\n            ('/header', HeaderHandler, dict(close_future=self.close_future)),\n            ('/close_reason', CloseReasonHandler,\n             dict(close_future=self.close_future)),\n        ])\n\n    @gen_test\n    def test_websocket_gen(self):\n        ws = yield websocket_connect(\n            'ws://localhost:%d/echo' % self.get_http_port(),\n            io_loop=self.io_loop)\n        ws.write_message('hello')\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    def test_websocket_callbacks(self):\n        websocket_connect(\n            'ws://localhost:%d/echo' % self.get_http_port(),\n            io_loop=self.io_loop, callback=self.stop)\n        ws = self.wait().result()\n        ws.write_message('hello')\n        ws.read_message(self.stop)\n        response = self.wait().result()\n        self.assertEqual(response, 'hello')\n        self.close_future.add_done_callback(lambda f: self.stop())\n        ws.close()\n        self.wait()\n\n    @gen_test\n    def test_websocket_http_fail(self):\n        with self.assertRaises(HTTPError) as cm:\n            yield websocket_connect(\n                'ws://localhost:%d/notfound' % self.get_http_port(),\n                io_loop=self.io_loop)\n        self.assertEqual(cm.exception.code, 404)\n\n    @gen_test\n    def test_websocket_http_success(self):\n        with self.assertRaises(WebSocketError):\n            yield websocket_connect(\n                'ws://localhost:%d/non_ws' % self.get_http_port(),\n                io_loop=self.io_loop)\n\n    @gen_test\n    def test_websocket_network_fail(self):\n        sock, port = bind_unused_port()\n        sock.close()\n        with self.assertRaises(IOError):\n            with ExpectLog(gen_log, \".*\"):\n                yield websocket_connect(\n                    'ws://localhost:%d/' % port,\n                    io_loop=self.io_loop,\n                    connect_timeout=3600)\n\n    @gen_test\n    def test_websocket_close_buffered_data(self):\n        ws = yield websocket_connect(\n            'ws://localhost:%d/echo' % self.get_http_port())\n        ws.write_message('hello')\n        ws.write_message('world')\n        ws.stream.close()\n        yield self.close_future\n\n    @gen_test\n    def test_websocket_headers(self):\n        # Ensure that arbitrary headers can be passed through websocket_connect.\n        ws = yield websocket_connect(\n            HTTPRequest('ws://localhost:%d/header' % self.get_http_port(),\n                        headers={'X-Test': 'hello'}))\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    @gen_test\n    def test_server_close_reason(self):\n        ws = yield websocket_connect(\n            'ws://localhost:%d/close_reason' % self.get_http_port())\n        msg = yield ws.read_message()\n        # A message of None means the other side closed the connection.\n        self.assertIs(msg, None)\n        self.assertEqual(ws.close_code, 1001)\n        self.assertEqual(ws.close_reason, \"goodbye\")\n\n    @gen_test\n    def test_client_close_reason(self):\n        ws = yield websocket_connect(\n            'ws://localhost:%d/echo' % self.get_http_port())\n        ws.close(1001, 'goodbye')\n        code, reason = yield self.close_future\n        self.assertEqual(code, 1001)\n        self.assertEqual(reason, 'goodbye')\n\n    @gen_test\n    def test_check_origin_valid(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        headers = {'Origin': 'http://localhost:%d' % port}\n\n        ws = yield websocket_connect(HTTPRequest(url, headers=headers),\n            io_loop=self.io_loop)\n        ws.write_message('hello')\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    @gen_test\n    def test_check_origin_with_path(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        headers = {'Origin': 'http://localhost:%d/something' % port}\n\n        ws = yield websocket_connect(HTTPRequest(url, headers=headers),\n            io_loop=self.io_loop)\n        ws.write_message('hello')\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    @gen_test\n    def test_check_origin_valid2(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        headers = {'Origin': 'localhost:%d' % port}\n\n        ws = yield websocket_connect(HTTPRequest(url, headers=headers),\n            io_loop=self.io_loop)\n        ws.write_message('hello')\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    @gen_test\n    def test_check_origin_invalid(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        # Host is localhost, which should not be accessible from some other\n        # domain\n        headers = {'Origin': 'http://somewhereelse.com'}\n\n        with self.assertRaises(HTTPError) as cm:\n            yield websocket_connect(HTTPRequest(url, headers=headers),\n                                    io_loop=self.io_loop)\n\n        self.assertEqual(cm.exception.code, 403)\n\n    @gen_test\n    def test_check_origin_invalid2(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        # subdomains should be invalid by default\n        headers = {'Origin': 'http://subtenant.somewhereelse.com',\n                   'Host': 'subtenant2.somewhereelse.com'}\n\n        with self.assertRaises(HTTPError) as cm:\n            yield websocket_connect(HTTPRequest(url, headers=headers),\n                                    io_loop=self.io_loop)\n\n        self.assertEqual(cm.exception.code, 403)",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 178,
                            "end_lineno": 190,
                            "parent": {
                                "file_name": "tornado/test/websocket_test.py",
                                "type": "class",
                                "name": "WebSocketTest",
                                "content": "class WebSocketTest(AsyncHTTPTestCase):\n    def get_app(self):\n        self.close_future = Future()\n        return Application([\n            ('/echo', EchoHandler, dict(close_future=self.close_future)),\n            ('/non_ws', NonWebSocketHandler),\n            ('/header', HeaderHandler, dict(close_future=self.close_future)),\n            ('/close_reason', CloseReasonHandler,\n             dict(close_future=self.close_future)),\n        ])\n\n    @gen_test\n    def test_websocket_gen(self):\n        ws = yield websocket_connect(\n            'ws://localhost:%d/echo' % self.get_http_port(),\n            io_loop=self.io_loop)\n        ws.write_message('hello')\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    def test_websocket_callbacks(self):\n        websocket_connect(\n            'ws://localhost:%d/echo' % self.get_http_port(),\n            io_loop=self.io_loop, callback=self.stop)\n        ws = self.wait().result()\n        ws.write_message('hello')\n        ws.read_message(self.stop)\n        response = self.wait().result()\n        self.assertEqual(response, 'hello')\n        self.close_future.add_done_callback(lambda f: self.stop())\n        ws.close()\n        self.wait()\n\n    @gen_test\n    def test_websocket_http_fail(self):\n        with self.assertRaises(HTTPError) as cm:\n            yield websocket_connect(\n                'ws://localhost:%d/notfound' % self.get_http_port(),\n                io_loop=self.io_loop)\n        self.assertEqual(cm.exception.code, 404)\n\n    @gen_test\n    def test_websocket_http_success(self):\n        with self.assertRaises(WebSocketError):\n            yield websocket_connect(\n                'ws://localhost:%d/non_ws' % self.get_http_port(),\n                io_loop=self.io_loop)\n\n    @gen_test\n    def test_websocket_network_fail(self):\n        sock, port = bind_unused_port()\n        sock.close()\n        with self.assertRaises(IOError):\n            with ExpectLog(gen_log, \".*\"):\n                yield websocket_connect(\n                    'ws://localhost:%d/' % port,\n                    io_loop=self.io_loop,\n                    connect_timeout=3600)\n\n    @gen_test\n    def test_websocket_close_buffered_data(self):\n        ws = yield websocket_connect(\n            'ws://localhost:%d/echo' % self.get_http_port())\n        ws.write_message('hello')\n        ws.write_message('world')\n        ws.stream.close()\n        yield self.close_future\n\n    @gen_test\n    def test_websocket_headers(self):\n        # Ensure that arbitrary headers can be passed through websocket_connect.\n        ws = yield websocket_connect(\n            HTTPRequest('ws://localhost:%d/header' % self.get_http_port(),\n                        headers={'X-Test': 'hello'}))\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    @gen_test\n    def test_server_close_reason(self):\n        ws = yield websocket_connect(\n            'ws://localhost:%d/close_reason' % self.get_http_port())\n        msg = yield ws.read_message()\n        # A message of None means the other side closed the connection.\n        self.assertIs(msg, None)\n        self.assertEqual(ws.close_code, 1001)\n        self.assertEqual(ws.close_reason, \"goodbye\")\n\n    @gen_test\n    def test_client_close_reason(self):\n        ws = yield websocket_connect(\n            'ws://localhost:%d/echo' % self.get_http_port())\n        ws.close(1001, 'goodbye')\n        code, reason = yield self.close_future\n        self.assertEqual(code, 1001)\n        self.assertEqual(reason, 'goodbye')\n\n    @gen_test\n    def test_check_origin_valid(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        headers = {'Origin': 'http://localhost:%d' % port}\n\n        ws = yield websocket_connect(HTTPRequest(url, headers=headers),\n            io_loop=self.io_loop)\n        ws.write_message('hello')\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    @gen_test\n    def test_check_origin_with_path(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        headers = {'Origin': 'http://localhost:%d/something' % port}\n\n        ws = yield websocket_connect(HTTPRequest(url, headers=headers),\n            io_loop=self.io_loop)\n        ws.write_message('hello')\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    @gen_test\n    def test_check_origin_valid2(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        headers = {'Origin': 'localhost:%d' % port}\n\n        ws = yield websocket_connect(HTTPRequest(url, headers=headers),\n            io_loop=self.io_loop)\n        ws.write_message('hello')\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    @gen_test\n    def test_check_origin_invalid(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        # Host is localhost, which should not be accessible from some other\n        # domain\n        headers = {'Origin': 'http://somewhereelse.com'}\n\n        with self.assertRaises(HTTPError) as cm:\n            yield websocket_connect(HTTPRequest(url, headers=headers),\n                                    io_loop=self.io_loop)\n\n        self.assertEqual(cm.exception.code, 403)\n\n    @gen_test\n    def test_check_origin_invalid2(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        # subdomains should be invalid by default\n        headers = {'Origin': 'http://subtenant.somewhereelse.com',\n                   'Host': 'subtenant2.somewhereelse.com'}\n\n        with self.assertRaises(HTTPError) as cm:\n            yield websocket_connect(HTTPRequest(url, headers=headers),\n                                    io_loop=self.io_loop)\n\n        self.assertEqual(cm.exception.code, 403)",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 62,
                                "end_lineno": 235,
                                "parent": null
                            }
                        }
                    ],
                    "deleted_entities": []
                }
            ]
        },
        {
            "old_file_content": "\"\"\"Implementation of the WebSocket protocol.\n\n`WebSockets <http://dev.w3.org/html5/websockets/>`_ allow for bidirectional\ncommunication between the browser and server.\n\n.. warning::\n\n   The WebSocket protocol was recently finalized as `RFC 6455\n   <http://tools.ietf.org/html/rfc6455>`_ and is not yet supported in\n   all browsers.  Refer to http://caniuse.com/websockets for details\n   on compatibility.  In addition, during development the protocol\n   went through several incompatible versions, and some browsers only\n   support older versions.  By default this module only supports the\n   latest version of the protocol, but optional support for an older\n   version (known as \"draft 76\" or \"hixie-76\") can be enabled by\n   overriding `WebSocketHandler.allow_draft76` (see that method's\n   documentation for caveats).\n\"\"\"\n\nfrom __future__ import absolute_import, division, print_function, with_statement\n# Author: Jacob Kristhammar, 2010\n\nimport array\nimport base64\nimport collections\nimport functools\nimport hashlib\nimport os\nimport struct\nimport time\nimport tornado.escape\nimport tornado.web\n\nfrom tornado.concurrent import TracebackFuture\nfrom tornado.escape import utf8, native_str, to_unicode\nfrom tornado import httpclient, httputil\nfrom tornado.ioloop import IOLoop\nfrom tornado.iostream import StreamClosedError\nfrom tornado.log import gen_log, app_log\nfrom tornado import simple_httpclient\nfrom tornado.tcpclient import TCPClient\nfrom tornado.util import bytes_type, unicode_type\n\ntry:\n    xrange  # py2\nexcept NameError:\n    xrange = range  # py3\n\n\nclass WebSocketError(Exception):\n    pass\n\n\nclass WebSocketClosedError(WebSocketError):\n    \"\"\"Raised by operations on a closed connection.\n\n    .. versionadded:: 3.2\n    \"\"\"\n    pass\n\n\nclass WebSocketHandler(tornado.web.RequestHandler):\n    \"\"\"Subclass this class to create a basic WebSocket handler.\n\n    Override `on_message` to handle incoming messages, and use\n    `write_message` to send messages to the client. You can also\n    override `open` and `on_close` to handle opened and closed\n    connections.\n\n    See http://dev.w3.org/html5/websockets/ for details on the\n    JavaScript interface.  The protocol is specified at\n    http://tools.ietf.org/html/rfc6455.\n\n    Here is an example WebSocket handler that echos back all received messages\n    back to the client::\n\n      class EchoWebSocket(websocket.WebSocketHandler):\n          def open(self):\n              print \"WebSocket opened\"\n\n          def on_message(self, message):\n              self.write_message(u\"You said: \" + message)\n\n          def on_close(self):\n              print \"WebSocket closed\"\n\n    WebSockets are not standard HTTP connections. The \"handshake\" is\n    HTTP, but after the handshake, the protocol is\n    message-based. Consequently, most of the Tornado HTTP facilities\n    are not available in handlers of this type. The only communication\n    methods available to you are `write_message()`, `ping()`, and\n    `close()`. Likewise, your request handler class should implement\n    `open()` method rather than ``get()`` or ``post()``.\n\n    If you map the handler above to ``/websocket`` in your application, you can\n    invoke it in JavaScript with::\n\n      var ws = new WebSocket(\"ws://localhost:8888/websocket\");\n      ws.onopen = function() {\n         ws.send(\"Hello, world\");\n      };\n      ws.onmessage = function (evt) {\n         alert(evt.data);\n      };\n\n    This script pops up an alert box that says \"You said: Hello, world\".\n    \"\"\"\n    def __init__(self, application, request, **kwargs):\n        tornado.web.RequestHandler.__init__(self, application, request,\n                                            **kwargs)\n        self.ws_connection = None\n        self.close_code = None\n        self.close_reason = None\n\n    @tornado.web.asynchronous\n    def get(self, *args, **kwargs):\n        self.open_args = args\n        self.open_kwargs = kwargs\n\n        self.stream = self.request.connection.detach()\n        self.stream.set_close_callback(self.on_connection_close)\n\n        # Upgrade header should be present and should be equal to WebSocket\n        if self.request.headers.get(\"Upgrade\", \"\").lower() != 'websocket':\n            self.stream.write(tornado.escape.utf8(\n                \"HTTP/1.1 400 Bad Request\\r\\n\\r\\n\"\n                \"Can \\\"Upgrade\\\" only to \\\"WebSocket\\\".\"\n            ))\n            self.stream.close()\n            return\n\n        # Connection header should be upgrade. Some proxy servers/load balancers\n        # might mess with it.\n        headers = self.request.headers\n        connection = map(lambda s: s.strip().lower(), headers.get(\"Connection\", \"\").split(\",\"))\n        if 'upgrade' not in connection:\n            self.stream.write(tornado.escape.utf8(\n                \"HTTP/1.1 400 Bad Request\\r\\n\\r\\n\"\n                \"\\\"Connection\\\" must be \\\"Upgrade\\\".\"\n            ))\n            self.stream.close()\n            return\n\n        # The difference between version 8 and 13 is that in 8 the\n        # client sends a \"Sec-Websocket-Origin\" header and in 13 it's\n        # simply \"Origin\".\n        if self.request.headers.get(\"Sec-WebSocket-Version\") in (\"7\", \"8\", \"13\"):\n            self.ws_connection = WebSocketProtocol13(self)\n            self.ws_connection.accept_connection()\n        elif (self.allow_draft76() and\n              \"Sec-WebSocket-Version\" not in self.request.headers):\n            self.ws_connection = WebSocketProtocol76(self)\n            self.ws_connection.accept_connection()\n        else:\n            self.stream.write(tornado.escape.utf8(\n                \"HTTP/1.1 426 Upgrade Required\\r\\n\"\n                \"Sec-WebSocket-Version: 8\\r\\n\\r\\n\"))\n            self.stream.close()\n\n    def write_message(self, message, binary=False):\n        \"\"\"Sends the given message to the client of this Web Socket.\n\n        The message may be either a string or a dict (which will be\n        encoded as json).  If the ``binary`` argument is false, the\n        message will be sent as utf8; in binary mode any byte string\n        is allowed.\n\n        If the connection is already closed, raises `WebSocketClosedError`.\n\n        .. versionchanged:: 3.2\n           `WebSocketClosedError` was added (previously a closed connection\n           would raise an `AttributeError`)\n        \"\"\"\n        if self.ws_connection is None:\n            raise WebSocketClosedError()\n        if isinstance(message, dict):\n            message = tornado.escape.json_encode(message)\n        self.ws_connection.write_message(message, binary=binary)\n\n    def select_subprotocol(self, subprotocols):\n        \"\"\"Invoked when a new WebSocket requests specific subprotocols.\n\n        ``subprotocols`` is a list of strings identifying the\n        subprotocols proposed by the client.  This method may be\n        overridden to return one of those strings to select it, or\n        ``None`` to not select a subprotocol.  Failure to select a\n        subprotocol does not automatically abort the connection,\n        although clients may close the connection if none of their\n        proposed subprotocols was selected.\n        \"\"\"\n        return None\n\n    def open(self):\n        \"\"\"Invoked when a new WebSocket is opened.\n\n        The arguments to `open` are extracted from the `tornado.web.URLSpec`\n        regular expression, just like the arguments to\n        `tornado.web.RequestHandler.get`.\n        \"\"\"\n        pass\n\n    def on_message(self, message):\n        \"\"\"Handle incoming messages on the WebSocket\n\n        This method must be overridden.\n        \"\"\"\n        raise NotImplementedError\n\n    def ping(self, data):\n        \"\"\"Send ping frame to the remote end.\"\"\"\n        if self.ws_connection is None:\n            raise WebSocketClosedError()\n        self.ws_connection.write_ping(data)\n\n    def on_pong(self, data):\n        \"\"\"Invoked when the response to a ping frame is received.\"\"\"\n        pass\n\n    def on_close(self):\n        \"\"\"Invoked when the WebSocket is closed.\n\n        If the connection was closed cleanly and a status code or reason\n        phrase was supplied, these values will be available as the attributes\n        ``self.close_code`` and ``self.close_reason``.\n\n        .. versionchanged:: 3.3\n\n           Added ``close_code`` and ``close_reason`` attributes.\n        \"\"\"\n        pass\n\n    def close(self, code=None, reason=None):\n        \"\"\"Closes this Web Socket.\n\n        Once the close handshake is successful the socket will be closed.\n\n        ``code`` may be a numeric status code, taken from the values\n        defined in `RFC 6455 section 7.4.1\n        <https://tools.ietf.org/html/rfc6455#section-7.4.1>`_.\n        ``reason`` may be a textual message about why the connection is\n        closing.  These values are made available to the client, but are\n        not otherwise interpreted by the websocket protocol.\n\n        The ``code`` and ``reason`` arguments are ignored in the \"draft76\"\n        protocol version.\n\n        .. versionchanged:: 3.3\n\n           Added the ``code`` and ``reason`` arguments.\n        \"\"\"\n        if self.ws_connection:\n            self.ws_connection.close(code, reason)\n            self.ws_connection = None\n\n    def allow_draft76(self):\n        \"\"\"Override to enable support for the older \"draft76\" protocol.\n\n        The draft76 version of the websocket protocol is disabled by\n        default due to security concerns, but it can be enabled by\n        overriding this method to return True.\n\n        Connections using the draft76 protocol do not support the\n        ``binary=True`` flag to `write_message`.\n\n        Support for the draft76 protocol is deprecated and will be\n        removed in a future version of Tornado.\n        \"\"\"\n        return False\n\n    def set_nodelay(self, value):\n        \"\"\"Set the no-delay flag for this stream.\n\n        By default, small messages may be delayed and/or combined to minimize\n        the number of packets sent.  This can sometimes cause 200-500ms delays\n        due to the interaction between Nagle's algorithm and TCP delayed\n        ACKs.  To reduce this delay (at the expense of possibly increasing\n        bandwidth usage), call ``self.set_nodelay(True)`` once the websocket\n        connection is established.\n\n        See `.BaseIOStream.set_nodelay` for additional details.\n\n        .. versionadded:: 3.1\n        \"\"\"\n        self.stream.set_nodelay(value)\n\n    def get_websocket_scheme(self):\n        \"\"\"Return the url scheme used for this request, either \"ws\" or \"wss\".\n\n        This is normally decided by HTTPServer, but applications\n        may wish to override this if they are using an SSL proxy\n        that does not provide the X-Scheme header as understood\n        by HTTPServer.\n\n        Note that this is only used by the draft76 protocol.\n        \"\"\"\n        return \"wss\" if self.request.protocol == \"https\" else \"ws\"\n\n    def async_callback(self, callback, *args, **kwargs):\n        \"\"\"Obsolete - catches exceptions from the wrapped function.\n\n        This function is normally unncecessary thanks to\n        `tornado.stack_context`.\n        \"\"\"\n        return self.ws_connection.async_callback(callback, *args, **kwargs)\n\n    def _not_supported(self, *args, **kwargs):\n        raise Exception(\"Method not supported for Web Sockets\")\n\n    def on_connection_close(self):\n        if self.ws_connection:\n            self.ws_connection.on_connection_close()\n            self.ws_connection = None\n            self.on_close()\n\n\nfor method in [\"write\", \"redirect\", \"set_header\", \"send_error\", \"set_cookie\",\n               \"set_status\", \"flush\", \"finish\"]:\n    setattr(WebSocketHandler, method, WebSocketHandler._not_supported)\n\n\nclass WebSocketProtocol(object):\n    \"\"\"Base class for WebSocket protocol versions.\n    \"\"\"\n    def __init__(self, handler):\n        self.handler = handler\n        self.request = handler.request\n        self.stream = handler.stream\n        self.client_terminated = False\n        self.server_terminated = False\n\n    def async_callback(self, callback, *args, **kwargs):\n        \"\"\"Wrap callbacks with this if they are used on asynchronous requests.\n\n        Catches exceptions properly and closes this WebSocket if an exception\n        is uncaught.\n        \"\"\"\n        if args or kwargs:\n            callback = functools.partial(callback, *args, **kwargs)\n\n        def wrapper(*args, **kwargs):\n            try:\n                return callback(*args, **kwargs)\n            except Exception:\n                app_log.error(\"Uncaught exception in %s\",\n                              self.request.path, exc_info=True)\n                self._abort()\n        return wrapper\n\n    def on_connection_close(self):\n        self._abort()\n\n    def _abort(self):\n        \"\"\"Instantly aborts the WebSocket connection by closing the socket\"\"\"\n        self.client_terminated = True\n        self.server_terminated = True\n        self.stream.close()  # forcibly tear down the connection\n        self.close()  # let the subclass cleanup\n\n\nclass WebSocketProtocol76(WebSocketProtocol):\n    \"\"\"Implementation of the WebSockets protocol, version hixie-76.\n\n    This class provides basic functionality to process WebSockets requests as\n    specified in\n    http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-76\n    \"\"\"\n    def __init__(self, handler):\n        WebSocketProtocol.__init__(self, handler)\n        self.challenge = None\n        self._waiting = None\n\n    def accept_connection(self):\n        try:\n            self._handle_websocket_headers()\n        except ValueError:\n            gen_log.debug(\"Malformed WebSocket request received\")\n            self._abort()\n            return\n\n        scheme = self.handler.get_websocket_scheme()\n\n        # draft76 only allows a single subprotocol\n        subprotocol_header = ''\n        subprotocol = self.request.headers.get(\"Sec-WebSocket-Protocol\", None)\n        if subprotocol:\n            selected = self.handler.select_subprotocol([subprotocol])\n            if selected:\n                assert selected == subprotocol\n                subprotocol_header = \"Sec-WebSocket-Protocol: %s\\r\\n\" % selected\n\n        # Write the initial headers before attempting to read the challenge.\n        # This is necessary when using proxies (such as HAProxy), which\n        # need to see the Upgrade headers before passing through the\n        # non-HTTP traffic that follows.\n        self.stream.write(tornado.escape.utf8(\n            \"HTTP/1.1 101 WebSocket Protocol Handshake\\r\\n\"\n            \"Upgrade: WebSocket\\r\\n\"\n            \"Connection: Upgrade\\r\\n\"\n            \"Server: TornadoServer/%(version)s\\r\\n\"\n            \"Sec-WebSocket-Origin: %(origin)s\\r\\n\"\n            \"Sec-WebSocket-Location: %(scheme)s://%(host)s%(uri)s\\r\\n\"\n            \"%(subprotocol)s\"\n            \"\\r\\n\" % (dict(\n                version=tornado.version,\n                origin=self.request.headers[\"Origin\"],\n                scheme=scheme,\n                host=self.request.host,\n                uri=self.request.uri,\n                subprotocol=subprotocol_header))))\n        self.stream.read_bytes(8, self._handle_challenge)\n\n    def challenge_response(self, challenge):\n        \"\"\"Generates the challenge response that's needed in the handshake\n\n        The challenge parameter should be the raw bytes as sent from the\n        client.\n        \"\"\"\n        key_1 = self.request.headers.get(\"Sec-Websocket-Key1\")\n        key_2 = self.request.headers.get(\"Sec-Websocket-Key2\")\n        try:\n            part_1 = self._calculate_part(key_1)\n            part_2 = self._calculate_part(key_2)\n        except ValueError:\n            raise ValueError(\"Invalid Keys/Challenge\")\n        return self._generate_challenge_response(part_1, part_2, challenge)\n\n    def _handle_challenge(self, challenge):\n        try:\n            challenge_response = self.challenge_response(challenge)\n        except ValueError:\n            gen_log.debug(\"Malformed key data in WebSocket request\")\n            self._abort()\n            return\n        self._write_response(challenge_response)\n\n    def _write_response(self, challenge):\n        self.stream.write(challenge)\n        self.async_callback(self.handler.open)(*self.handler.open_args, **self.handler.open_kwargs)\n        self._receive_message()\n\n    def _handle_websocket_headers(self):\n        \"\"\"Verifies all invariant- and required headers\n\n        If a header is missing or have an incorrect value ValueError will be\n        raised\n        \"\"\"\n        fields = (\"Origin\", \"Host\", \"Sec-Websocket-Key1\",\n                  \"Sec-Websocket-Key2\")\n        if not all(map(lambda f: self.request.headers.get(f), fields)):\n            raise ValueError(\"Missing/Invalid WebSocket headers\")\n\n    def _calculate_part(self, key):\n        \"\"\"Processes the key headers and calculates their key value.\n\n        Raises ValueError when feed invalid key.\"\"\"\n        # pyflakes complains about variable reuse if both of these lines use 'c'\n        number = int(''.join(c for c in key if c.isdigit()))\n        spaces = len([c2 for c2 in key if c2.isspace()])\n        try:\n            key_number = number // spaces\n        except (ValueError, ZeroDivisionError):\n            raise ValueError\n        return struct.pack(\">I\", key_number)\n\n    def _generate_challenge_response(self, part_1, part_2, part_3):\n        m = hashlib.md5()\n        m.update(part_1)\n        m.update(part_2)\n        m.update(part_3)\n        return m.digest()\n\n    def _receive_message(self):\n        self.stream.read_bytes(1, self._on_frame_type)\n\n    def _on_frame_type(self, byte):\n        frame_type = ord(byte)\n        if frame_type == 0x00:\n            self.stream.read_until(b\"\\xff\", self._on_end_delimiter)\n        elif frame_type == 0xff:\n            self.stream.read_bytes(1, self._on_length_indicator)\n        else:\n            self._abort()\n\n    def _on_end_delimiter(self, frame):\n        if not self.client_terminated:\n            self.async_callback(self.handler.on_message)(\n                frame[:-1].decode(\"utf-8\", \"replace\"))\n        if not self.client_terminated:\n            self._receive_message()\n\n    def _on_length_indicator(self, byte):\n        if ord(byte) != 0x00:\n            self._abort()\n            return\n        self.client_terminated = True\n        self.close()\n\n    def write_message(self, message, binary=False):\n        \"\"\"Sends the given message to the client of this Web Socket.\"\"\"\n        if binary:\n            raise ValueError(\n                \"Binary messages not supported by this version of websockets\")\n        if isinstance(message, unicode_type):\n            message = message.encode(\"utf-8\")\n        assert isinstance(message, bytes_type)\n        self.stream.write(b\"\\x00\" + message + b\"\\xff\")\n\n    def write_ping(self, data):\n        \"\"\"Send ping frame.\"\"\"\n        raise ValueError(\"Ping messages not supported by this version of websockets\")\n\n    def close(self, code=None, reason=None):\n        \"\"\"Closes the WebSocket connection.\"\"\"\n        if not self.server_terminated:\n            if not self.stream.closed():\n                self.stream.write(\"\\xff\\x00\")\n            self.server_terminated = True\n        if self.client_terminated:\n            if self._waiting is not None:\n                self.stream.io_loop.remove_timeout(self._waiting)\n            self._waiting = None\n            self.stream.close()\n        elif self._waiting is None:\n            self._waiting = self.stream.io_loop.add_timeout(\n                time.time() + 5, self._abort)\n\n\nclass WebSocketProtocol13(WebSocketProtocol):\n    \"\"\"Implementation of the WebSocket protocol from RFC 6455.\n\n    This class supports versions 7 and 8 of the protocol in addition to the\n    final version 13.\n    \"\"\"\n    def __init__(self, handler, mask_outgoing=False):\n        WebSocketProtocol.__init__(self, handler)\n        self.mask_outgoing = mask_outgoing\n        self._final_frame = False\n        self._frame_opcode = None\n        self._masked_frame = None\n        self._frame_mask = None\n        self._frame_length = None\n        self._fragmented_message_buffer = None\n        self._fragmented_message_opcode = None\n        self._waiting = None\n\n    def accept_connection(self):\n        try:\n            self._handle_websocket_headers()\n            self._accept_connection()\n        except ValueError:\n            gen_log.debug(\"Malformed WebSocket request received\", exc_info=True)\n            self._abort()\n            return\n\n    def _handle_websocket_headers(self):\n        \"\"\"Verifies all invariant- and required headers\n\n        If a header is missing or have an incorrect value ValueError will be\n        raised\n        \"\"\"\n        fields = (\"Host\", \"Sec-Websocket-Key\", \"Sec-Websocket-Version\")\n        if not all(map(lambda f: self.request.headers.get(f), fields)):\n            raise ValueError(\"Missing/Invalid WebSocket headers\")\n\n    @staticmethod\n    def compute_accept_value(key):\n        \"\"\"Computes the value for the Sec-WebSocket-Accept header,\n        given the value for Sec-WebSocket-Key.\n        \"\"\"\n        sha1 = hashlib.sha1()\n        sha1.update(utf8(key))\n        sha1.update(b\"258EAFA5-E914-47DA-95CA-C5AB0DC85B11\")  # Magic value\n        return native_str(base64.b64encode(sha1.digest()))\n\n    def _challenge_response(self):\n        return WebSocketProtocol13.compute_accept_value(\n            self.request.headers.get(\"Sec-Websocket-Key\"))\n\n    def _accept_connection(self):\n        subprotocol_header = ''\n        subprotocols = self.request.headers.get(\"Sec-WebSocket-Protocol\", '')\n        subprotocols = [s.strip() for s in subprotocols.split(',')]\n        if subprotocols:\n            selected = self.handler.select_subprotocol(subprotocols)\n            if selected:\n                assert selected in subprotocols\n                subprotocol_header = \"Sec-WebSocket-Protocol: %s\\r\\n\" % selected\n\n        self.stream.write(tornado.escape.utf8(\n            \"HTTP/1.1 101 Switching Protocols\\r\\n\"\n            \"Upgrade: websocket\\r\\n\"\n            \"Connection: Upgrade\\r\\n\"\n            \"Sec-WebSocket-Accept: %s\\r\\n\"\n            \"%s\"\n            \"\\r\\n\" % (self._challenge_response(), subprotocol_header)))\n\n        self.async_callback(self.handler.open)(*self.handler.open_args, **self.handler.open_kwargs)\n        self._receive_frame()\n\n    def _write_frame(self, fin, opcode, data):\n        if fin:\n            finbit = 0x80\n        else:\n            finbit = 0\n        frame = struct.pack(\"B\", finbit | opcode)\n        l = len(data)\n        if self.mask_outgoing:\n            mask_bit = 0x80\n        else:\n            mask_bit = 0\n        if l < 126:\n            frame += struct.pack(\"B\", l | mask_bit)\n        elif l <= 0xFFFF:\n            frame += struct.pack(\"!BH\", 126 | mask_bit, l)\n        else:\n            frame += struct.pack(\"!BQ\", 127 | mask_bit, l)\n        if self.mask_outgoing:\n            mask = os.urandom(4)\n            data = mask + _websocket_mask(mask, data)\n        frame += data\n        self.stream.write(frame)\n\n    def write_message(self, message, binary=False):\n        \"\"\"Sends the given message to the client of this Web Socket.\"\"\"\n        if binary:\n            opcode = 0x2\n        else:\n            opcode = 0x1\n        message = tornado.escape.utf8(message)\n        assert isinstance(message, bytes_type)\n        try:\n            self._write_frame(True, opcode, message)\n        except StreamClosedError:\n            self._abort()\n\n    def write_ping(self, data):\n        \"\"\"Send ping frame.\"\"\"\n        assert isinstance(data, bytes_type)\n        self._write_frame(True, 0x9, data)\n\n    def _receive_frame(self):\n        try:\n            self.stream.read_bytes(2, self._on_frame_start)\n        except StreamClosedError:\n            self._abort()\n\n    def _on_frame_start(self, data):\n        header, payloadlen = struct.unpack(\"BB\", data)\n        self._final_frame = header & 0x80\n        reserved_bits = header & 0x70\n        self._frame_opcode = header & 0xf\n        self._frame_opcode_is_control = self._frame_opcode & 0x8\n        if reserved_bits:\n            # client is using as-yet-undefined extensions; abort\n            self._abort()\n            return\n        self._masked_frame = bool(payloadlen & 0x80)\n        payloadlen = payloadlen & 0x7f\n        if self._frame_opcode_is_control and payloadlen >= 126:\n            # control frames must have payload < 126\n            self._abort()\n            return\n        try:\n            if payloadlen < 126:\n                self._frame_length = payloadlen\n                if self._masked_frame:\n                    self.stream.read_bytes(4, self._on_masking_key)\n                else:\n                    self.stream.read_bytes(self._frame_length, self._on_frame_data)\n            elif payloadlen == 126:\n                self.stream.read_bytes(2, self._on_frame_length_16)\n            elif payloadlen == 127:\n                self.stream.read_bytes(8, self._on_frame_length_64)\n        except StreamClosedError:\n            self._abort()\n\n    def _on_frame_length_16(self, data):\n        self._frame_length = struct.unpack(\"!H\", data)[0]\n        try:\n            if self._masked_frame:\n                self.stream.read_bytes(4, self._on_masking_key)\n            else:\n                self.stream.read_bytes(self._frame_length, self._on_frame_data)\n        except StreamClosedError:\n            self._abort()\n\n    def _on_frame_length_64(self, data):\n        self._frame_length = struct.unpack(\"!Q\", data)[0]\n        try:\n            if self._masked_frame:\n                self.stream.read_bytes(4, self._on_masking_key)\n            else:\n                self.stream.read_bytes(self._frame_length, self._on_frame_data)\n        except StreamClosedError:\n            self._abort()\n\n    def _on_masking_key(self, data):\n        self._frame_mask = data\n        try:\n            self.stream.read_bytes(self._frame_length, self._on_masked_frame_data)\n        except StreamClosedError:\n            self._abort()\n\n    def _on_masked_frame_data(self, data):\n        self._on_frame_data(_websocket_mask(self._frame_mask, data))\n\n    def _on_frame_data(self, data):\n        if self._frame_opcode_is_control:\n            # control frames may be interleaved with a series of fragmented\n            # data frames, so control frames must not interact with\n            # self._fragmented_*\n            if not self._final_frame:\n                # control frames must not be fragmented\n                self._abort()\n                return\n            opcode = self._frame_opcode\n        elif self._frame_opcode == 0:  # continuation frame\n            if self._fragmented_message_buffer is None:\n                # nothing to continue\n                self._abort()\n                return\n            self._fragmented_message_buffer += data\n            if self._final_frame:\n                opcode = self._fragmented_message_opcode\n                data = self._fragmented_message_buffer\n                self._fragmented_message_buffer = None\n        else:  # start of new data message\n            if self._fragmented_message_buffer is not None:\n                # can't start new message until the old one is finished\n                self._abort()\n                return\n            if self._final_frame:\n                opcode = self._frame_opcode\n            else:\n                self._fragmented_message_opcode = self._frame_opcode\n                self._fragmented_message_buffer = data\n\n        if self._final_frame:\n            self._handle_message(opcode, data)\n\n        if not self.client_terminated:\n            self._receive_frame()\n\n    def _handle_message(self, opcode, data):\n        if self.client_terminated:\n            return\n\n        if opcode == 0x1:\n            # UTF-8 data\n            try:\n                decoded = data.decode(\"utf-8\")\n            except UnicodeDecodeError:\n                self._abort()\n                return\n            self.async_callback(self.handler.on_message)(decoded)\n        elif opcode == 0x2:\n            # Binary data\n            self.async_callback(self.handler.on_message)(data)\n        elif opcode == 0x8:\n            # Close\n            self.client_terminated = True\n            if len(data) >= 2:\n                self.handler.close_code = struct.unpack('>H', data[:2])[0]\n            if len(data) > 2:\n                self.handler.close_reason = to_unicode(data[2:])\n            self.close()\n        elif opcode == 0x9:\n            # Ping\n            self._write_frame(True, 0xA, data)\n        elif opcode == 0xA:\n            # Pong\n            self.async_callback(self.handler.on_pong)(data)\n        else:\n            self._abort()\n\n    def close(self, code=None, reason=None):\n        \"\"\"Closes the WebSocket connection.\"\"\"\n        if not self.server_terminated:\n            if not self.stream.closed():\n                if code is None and reason is not None:\n                    code = 1000  # \"normal closure\" status code\n                if code is None:\n                    close_data = b''\n                else:\n                    close_data = struct.pack('>H', code)\n                if reason is not None:\n                    close_data += utf8(reason)\n                self._write_frame(True, 0x8, close_data)\n            self.server_terminated = True\n        if self.client_terminated:\n            if self._waiting is not None:\n                self.stream.io_loop.remove_timeout(self._waiting)\n                self._waiting = None\n            self.stream.close()\n        elif self._waiting is None:\n            # Give the client a few seconds to complete a clean shutdown,\n            # otherwise just close the connection.\n            self._waiting = self.stream.io_loop.add_timeout(\n                self.stream.io_loop.time() + 5, self._abort)\n\n\nclass WebSocketClientConnection(simple_httpclient._HTTPConnection):\n    \"\"\"WebSocket client connection.\n\n    This class should not be instantiated directly; use the\n    `websocket_connect` function instead.\n    \"\"\"\n    def __init__(self, io_loop, request):\n        self.connect_future = TracebackFuture()\n        self.read_future = None\n        self.read_queue = collections.deque()\n        self.key = base64.b64encode(os.urandom(16))\n\n        scheme, sep, rest = request.url.partition(':')\n        scheme = {'ws': 'http', 'wss': 'https'}[scheme]\n        request.url = scheme + sep + rest\n        request.headers.update({\n            'Upgrade': 'websocket',\n            'Connection': 'Upgrade',\n            'Sec-WebSocket-Key': self.key,\n            'Sec-WebSocket-Version': '13',\n        })\n\n        self.tcp_client = TCPClient(io_loop=io_loop)\n        super(WebSocketClientConnection, self).__init__(\n            io_loop, None, request, lambda: None, self._on_http_response,\n            104857600, self.tcp_client, 65536)\n\n    def close(self, code=None, reason=None):\n        \"\"\"Closes the websocket connection.\n\n        ``code`` and ``reason`` are documented under\n        `WebSocketHandler.close`.\n\n        .. versionadded:: 3.2\n\n        .. versionchanged:: 3.3\n\n           Added the ``code`` and ``reason`` arguments.\n        \"\"\"\n        if self.protocol is not None:\n            self.protocol.close(code, reason)\n            self.protocol = None\n\n    def _on_close(self):\n        self.on_message(None)\n        self.resolver.close()\n        super(WebSocketClientConnection, self)._on_close()\n\n    def _on_http_response(self, response):\n        if not self.connect_future.done():\n            if response.error:\n                self.connect_future.set_exception(response.error)\n            else:\n                self.connect_future.set_exception(WebSocketError(\n                    \"Non-websocket response\"))\n\n    def headers_received(self, start_line, headers):\n        if start_line.code != 101:\n            return super(WebSocketClientConnection, self).headers_received(\n                start_line, headers)\n\n        self.headers = headers\n        assert self.headers['Upgrade'].lower() == 'websocket'\n        assert self.headers['Connection'].lower() == 'upgrade'\n        accept = WebSocketProtocol13.compute_accept_value(self.key)\n        assert self.headers['Sec-Websocket-Accept'] == accept\n\n        self.protocol = WebSocketProtocol13(self, mask_outgoing=True)\n        self.protocol._receive_frame()\n\n        if self._timeout is not None:\n            self.io_loop.remove_timeout(self._timeout)\n            self._timeout = None\n\n        self.stream = self.connection.detach()\n        self.stream.set_close_callback(self._on_close)\n\n        self.connect_future.set_result(self)\n\n    def write_message(self, message, binary=False):\n        \"\"\"Sends a message to the WebSocket server.\"\"\"\n        self.protocol.write_message(message, binary)\n\n    def read_message(self, callback=None):\n        \"\"\"Reads a message from the WebSocket server.\n\n        Returns a future whose result is the message, or None\n        if the connection is closed.  If a callback argument\n        is given it will be called with the future when it is\n        ready.\n        \"\"\"\n        assert self.read_future is None\n        future = TracebackFuture()\n        if self.read_queue:\n            future.set_result(self.read_queue.popleft())\n        else:\n            self.read_future = future\n        if callback is not None:\n            self.io_loop.add_future(future, callback)\n        return future\n\n    def on_message(self, message):\n        if self.read_future is not None:\n            self.read_future.set_result(message)\n            self.read_future = None\n        else:\n            self.read_queue.append(message)\n\n    def on_pong(self, data):\n        pass\n\n\ndef websocket_connect(url, io_loop=None, callback=None, connect_timeout=None):\n    \"\"\"Client-side websocket support.\n\n    Takes a url and returns a Future whose result is a\n    `WebSocketClientConnection`.\n\n    .. versionchanged:: 3.2\n       Also accepts ``HTTPRequest`` objects in place of urls.\n    \"\"\"\n    if io_loop is None:\n        io_loop = IOLoop.current()\n    if isinstance(url, httpclient.HTTPRequest):\n        assert connect_timeout is None\n        request = url\n        # Copy and convert the headers dict/object (see comments in\n        # AsyncHTTPClient.fetch)\n        request.headers = httputil.HTTPHeaders(request.headers)\n    else:\n        request = httpclient.HTTPRequest(url, connect_timeout=connect_timeout)\n    request = httpclient._RequestProxy(\n        request, httpclient.HTTPRequest._DEFAULTS)\n    conn = WebSocketClientConnection(io_loop, request)\n    if callback is not None:\n        io_loop.add_future(conn.connect_future, callback)\n    return conn.connect_future\n\n\ndef _websocket_mask_python(mask, data):\n    \"\"\"Websocket masking function.\n\n    `mask` is a `bytes` object of length 4; `data` is a `bytes` object of any length.\n    Returns a `bytes` object of the same length as `data` with the mask applied\n    as specified in section 5.3 of RFC 6455.\n\n    This pure-python implementation may be replaced by an optimized version when available.\n    \"\"\"\n    mask = array.array(\"B\", mask)\n    unmasked = array.array(\"B\", data)\n    for i in xrange(len(data)):\n        unmasked[i] = unmasked[i] ^ mask[i % 4]\n    if hasattr(unmasked, 'tobytes'):\n        # tostring was deprecated in py32.  It hasn't been removed,\n        # but since we turn on deprecation warnings in our tests\n        # we need to use the right one.\n        return unmasked.tobytes()\n    else:\n        return unmasked.tostring()\n\nif (os.environ.get('TORNADO_NO_EXTENSION') or\n        os.environ.get('TORNADO_EXTENSION') == '0'):\n    # These environment variables exist to make it easier to do performance\n    # comparisons; they are not guaranteed to remain supported in the future.\n    _websocket_mask = _websocket_mask_python\nelse:\n    try:\n        from tornado.speedups import websocket_mask as _websocket_mask\n    except ImportError:\n        if os.environ.get('TORNADO_EXTENSION') == '1':\n            raise\n        _websocket_mask = _websocket_mask_python\n",
            "new_file_content": "\"\"\"Implementation of the WebSocket protocol.\n\n`WebSockets <http://dev.w3.org/html5/websockets/>`_ allow for bidirectional\ncommunication between the browser and server.\n\n.. warning::\n\n   The WebSocket protocol was recently finalized as `RFC 6455\n   <http://tools.ietf.org/html/rfc6455>`_ and is not yet supported in\n   all browsers.  Refer to http://caniuse.com/websockets for details\n   on compatibility.  In addition, during development the protocol\n   went through several incompatible versions, and some browsers only\n   support older versions.  By default this module only supports the\n   latest version of the protocol, but optional support for an older\n   version (known as \"draft 76\" or \"hixie-76\") can be enabled by\n   overriding `WebSocketHandler.allow_draft76` (see that method's\n   documentation for caveats).\n\"\"\"\n\nfrom __future__ import absolute_import, division, print_function, with_statement\n# Author: Jacob Kristhammar, 2010\n\nimport array\nimport base64\nimport collections\nimport functools\nimport hashlib\nimport os\nimport struct\nimport time\nimport tornado.escape\nimport tornado.web\n\nfrom tornado.concurrent import TracebackFuture\nfrom tornado.escape import utf8, native_str, to_unicode\nfrom tornado import httpclient, httputil\nfrom tornado.ioloop import IOLoop\nfrom tornado.iostream import StreamClosedError\nfrom tornado.log import gen_log, app_log\nfrom tornado import simple_httpclient\nfrom tornado.tcpclient import TCPClient\nfrom tornado.util import bytes_type, unicode_type\n\ntry:\n    from urllib.parse import urlparse # py2\nexcept ImportError:\n    from urlparse import urlparse # py3\n\ntry:\n    xrange  # py2\nexcept NameError:\n    xrange = range  # py3\n\n\nclass WebSocketError(Exception):\n    pass\n\n\nclass WebSocketClosedError(WebSocketError):\n    \"\"\"Raised by operations on a closed connection.\n\n    .. versionadded:: 3.2\n    \"\"\"\n    pass\n\n\nclass WebSocketHandler(tornado.web.RequestHandler):\n    \"\"\"Subclass this class to create a basic WebSocket handler.\n\n    Override `on_message` to handle incoming messages, and use\n    `write_message` to send messages to the client. You can also\n    override `open` and `on_close` to handle opened and closed\n    connections.\n\n    See http://dev.w3.org/html5/websockets/ for details on the\n    JavaScript interface.  The protocol is specified at\n    http://tools.ietf.org/html/rfc6455.\n\n    Here is an example WebSocket handler that echos back all received messages\n    back to the client::\n\n      class EchoWebSocket(websocket.WebSocketHandler):\n          def open(self):\n              print \"WebSocket opened\"\n\n          def on_message(self, message):\n              self.write_message(u\"You said: \" + message)\n\n          def on_close(self):\n              print \"WebSocket closed\"\n\n    WebSockets are not standard HTTP connections. The \"handshake\" is\n    HTTP, but after the handshake, the protocol is\n    message-based. Consequently, most of the Tornado HTTP facilities\n    are not available in handlers of this type. The only communication\n    methods available to you are `write_message()`, `ping()`, and\n    `close()`. Likewise, your request handler class should implement\n    `open()` method rather than ``get()`` or ``post()``.\n\n    If you map the handler above to ``/websocket`` in your application, you can\n    invoke it in JavaScript with::\n\n      var ws = new WebSocket(\"ws://localhost:8888/websocket\");\n      ws.onopen = function() {\n         ws.send(\"Hello, world\");\n      };\n      ws.onmessage = function (evt) {\n         alert(evt.data);\n      };\n\n    This script pops up an alert box that says \"You said: Hello, world\".\n    \"\"\"\n    def __init__(self, application, request, **kwargs):\n        tornado.web.RequestHandler.__init__(self, application, request,\n                                            **kwargs)\n        self.ws_connection = None\n        self.close_code = None\n        self.close_reason = None\n\n    @tornado.web.asynchronous\n    def get(self, *args, **kwargs):\n        self.open_args = args\n        self.open_kwargs = kwargs\n\n        self.stream = self.request.connection.detach()\n        self.stream.set_close_callback(self.on_connection_close)\n\n        # Upgrade header should be present and should be equal to WebSocket\n        if self.request.headers.get(\"Upgrade\", \"\").lower() != 'websocket':\n            self.stream.write(tornado.escape.utf8(\n                \"HTTP/1.1 400 Bad Request\\r\\n\\r\\n\"\n                \"Can \\\"Upgrade\\\" only to \\\"WebSocket\\\".\"\n            ))\n            self.stream.close()\n            return\n\n        # Connection header should be upgrade. Some proxy servers/load balancers\n        # might mess with it.\n        headers = self.request.headers\n        connection = map(lambda s: s.strip().lower(), headers.get(\"Connection\", \"\").split(\",\"))\n        if 'upgrade' not in connection:\n            self.stream.write(tornado.escape.utf8(\n                \"HTTP/1.1 400 Bad Request\\r\\n\\r\\n\"\n                \"\\\"Connection\\\" must be \\\"Upgrade\\\".\"\n            ))\n            self.stream.close()\n            return\n\n        # Handle WebSocket Origin naming convention differences\n        # The difference between version 8 and 13 is that in 8 the\n        # client sends a \"Sec-Websocket-Origin\" header and in 13 it's\n        # simply \"Origin\".\n        if \"Origin\" in self.request.headers:\n            origin = self.request.headers.get(\"Origin\")\n        else:\n            origin = self.request.headers.get(\"Sec-Websocket-Origin\", None)\n\n\n        # If there was an origin header, check to make sure it matches\n        # according to check_origin. When the origin is None, we assume it\n        # came from a browser and that it can be passed on.\n        if origin is not None and not self.check_origin(origin):\n            self.stream.write(tornado.escape.utf8(\n                \"HTTP/1.1 403 Cross Origin Websockets Disabled\\r\\n\\r\\n\"\n            ))\n            self.stream.close()\n            return\n\n        if self.request.headers.get(\"Sec-WebSocket-Version\") in (\"7\", \"8\", \"13\"):\n            self.ws_connection = WebSocketProtocol13(self)\n            self.ws_connection.accept_connection()\n        elif (self.allow_draft76() and\n              \"Sec-WebSocket-Version\" not in self.request.headers):\n            self.ws_connection = WebSocketProtocol76(self)\n            self.ws_connection.accept_connection()\n        else:\n            self.stream.write(tornado.escape.utf8(\n                \"HTTP/1.1 426 Upgrade Required\\r\\n\"\n                \"Sec-WebSocket-Version: 8\\r\\n\\r\\n\"))\n            self.stream.close()\n\n\n    def write_message(self, message, binary=False):\n        \"\"\"Sends the given message to the client of this Web Socket.\n\n        The message may be either a string or a dict (which will be\n        encoded as json).  If the ``binary`` argument is false, the\n        message will be sent as utf8; in binary mode any byte string\n        is allowed.\n\n        If the connection is already closed, raises `WebSocketClosedError`.\n\n        .. versionchanged:: 3.2\n           `WebSocketClosedError` was added (previously a closed connection\n           would raise an `AttributeError`)\n        \"\"\"\n        if self.ws_connection is None:\n            raise WebSocketClosedError()\n        if isinstance(message, dict):\n            message = tornado.escape.json_encode(message)\n        self.ws_connection.write_message(message, binary=binary)\n\n    def select_subprotocol(self, subprotocols):\n        \"\"\"Invoked when a new WebSocket requests specific subprotocols.\n\n        ``subprotocols`` is a list of strings identifying the\n        subprotocols proposed by the client.  This method may be\n        overridden to return one of those strings to select it, or\n        ``None`` to not select a subprotocol.  Failure to select a\n        subprotocol does not automatically abort the connection,\n        although clients may close the connection if none of their\n        proposed subprotocols was selected.\n        \"\"\"\n        return None\n\n    def open(self):\n        \"\"\"Invoked when a new WebSocket is opened.\n\n        The arguments to `open` are extracted from the `tornado.web.URLSpec`\n        regular expression, just like the arguments to\n        `tornado.web.RequestHandler.get`.\n        \"\"\"\n        pass\n\n    def on_message(self, message):\n        \"\"\"Handle incoming messages on the WebSocket\n\n        This method must be overridden.\n        \"\"\"\n        raise NotImplementedError\n\n    def ping(self, data):\n        \"\"\"Send ping frame to the remote end.\"\"\"\n        if self.ws_connection is None:\n            raise WebSocketClosedError()\n        self.ws_connection.write_ping(data)\n\n    def on_pong(self, data):\n        \"\"\"Invoked when the response to a ping frame is received.\"\"\"\n        pass\n\n    def on_close(self):\n        \"\"\"Invoked when the WebSocket is closed.\n\n        If the connection was closed cleanly and a status code or reason\n        phrase was supplied, these values will be available as the attributes\n        ``self.close_code`` and ``self.close_reason``.\n\n        .. versionchanged:: 3.3\n\n           Added ``close_code`` and ``close_reason`` attributes.\n        \"\"\"\n        pass\n\n    def close(self, code=None, reason=None):\n        \"\"\"Closes this Web Socket.\n\n        Once the close handshake is successful the socket will be closed.\n\n        ``code`` may be a numeric status code, taken from the values\n        defined in `RFC 6455 section 7.4.1\n        <https://tools.ietf.org/html/rfc6455#section-7.4.1>`_.\n        ``reason`` may be a textual message about why the connection is\n        closing.  These values are made available to the client, but are\n        not otherwise interpreted by the websocket protocol.\n\n        The ``code`` and ``reason`` arguments are ignored in the \"draft76\"\n        protocol version.\n\n        .. versionchanged:: 3.3\n\n           Added the ``code`` and ``reason`` arguments.\n        \"\"\"\n        if self.ws_connection:\n            self.ws_connection.close(code, reason)\n            self.ws_connection = None\n\n    def check_origin(self, origin):\n        \"\"\"Override to enable support for allowing alternate origins.\n        \n        By default, this checks to see that the host matches the origin\n        provided.\n\n        This is a security protection against cross site scripting attacks on\n        browsers, since WebSockets don't have CORS headers.\n        \"\"\"\n\n        # Due to how stdlib's urlparse is implemented, urls without a //\n        # are interpreted to be paths (resulting in netloc being None)\n        if(\"//\" not in origin):\n            origin = \"//\" + origin\n        parsed_origin = urlparse(origin)\n        origin = parsed_origin.netloc\n        origin = origin.lower()\n\n        host = self.request.headers.get(\"Host\")\n\n        # Check to see that origin matches host directly, including ports\n        return origin == host\n\n    def allow_draft76(self):\n        \"\"\"Override to enable support for the older \"draft76\" protocol.\n\n        The draft76 version of the websocket protocol is disabled by\n        default due to security concerns, but it can be enabled by\n        overriding this method to return True.\n\n        Connections using the draft76 protocol do not support the\n        ``binary=True`` flag to `write_message`.\n\n        Support for the draft76 protocol is deprecated and will be\n        removed in a future version of Tornado.\n        \"\"\"\n        return False\n\n    def set_nodelay(self, value):\n        \"\"\"Set the no-delay flag for this stream.\n\n        By default, small messages may be delayed and/or combined to minimize\n        the number of packets sent.  This can sometimes cause 200-500ms delays\n        due to the interaction between Nagle's algorithm and TCP delayed\n        ACKs.  To reduce this delay (at the expense of possibly increasing\n        bandwidth usage), call ``self.set_nodelay(True)`` once the websocket\n        connection is established.\n\n        See `.BaseIOStream.set_nodelay` for additional details.\n\n        .. versionadded:: 3.1\n        \"\"\"\n        self.stream.set_nodelay(value)\n\n    def get_websocket_scheme(self):\n        \"\"\"Return the url scheme used for this request, either \"ws\" or \"wss\".\n\n        This is normally decided by HTTPServer, but applications\n        may wish to override this if they are using an SSL proxy\n        that does not provide the X-Scheme header as understood\n        by HTTPServer.\n\n        Note that this is only used by the draft76 protocol.\n        \"\"\"\n        return \"wss\" if self.request.protocol == \"https\" else \"ws\"\n\n    def async_callback(self, callback, *args, **kwargs):\n        \"\"\"Obsolete - catches exceptions from the wrapped function.\n\n        This function is normally unncecessary thanks to\n        `tornado.stack_context`.\n        \"\"\"\n        return self.ws_connection.async_callback(callback, *args, **kwargs)\n\n    def _not_supported(self, *args, **kwargs):\n        raise Exception(\"Method not supported for Web Sockets\")\n\n    def on_connection_close(self):\n        if self.ws_connection:\n            self.ws_connection.on_connection_close()\n            self.ws_connection = None\n            self.on_close()\n\n\nfor method in [\"write\", \"redirect\", \"set_header\", \"send_error\", \"set_cookie\",\n               \"set_status\", \"flush\", \"finish\"]:\n    setattr(WebSocketHandler, method, WebSocketHandler._not_supported)\n\n\nclass WebSocketProtocol(object):\n    \"\"\"Base class for WebSocket protocol versions.\n    \"\"\"\n    def __init__(self, handler):\n        self.handler = handler\n        self.request = handler.request\n        self.stream = handler.stream\n        self.client_terminated = False\n        self.server_terminated = False\n\n    def async_callback(self, callback, *args, **kwargs):\n        \"\"\"Wrap callbacks with this if they are used on asynchronous requests.\n\n        Catches exceptions properly and closes this WebSocket if an exception\n        is uncaught.\n        \"\"\"\n        if args or kwargs:\n            callback = functools.partial(callback, *args, **kwargs)\n\n        def wrapper(*args, **kwargs):\n            try:\n                return callback(*args, **kwargs)\n            except Exception:\n                app_log.error(\"Uncaught exception in %s\",\n                              self.request.path, exc_info=True)\n                self._abort()\n        return wrapper\n\n    def on_connection_close(self):\n        self._abort()\n\n    def _abort(self):\n        \"\"\"Instantly aborts the WebSocket connection by closing the socket\"\"\"\n        self.client_terminated = True\n        self.server_terminated = True\n        self.stream.close()  # forcibly tear down the connection\n        self.close()  # let the subclass cleanup\n\n\nclass WebSocketProtocol76(WebSocketProtocol):\n    \"\"\"Implementation of the WebSockets protocol, version hixie-76.\n\n    This class provides basic functionality to process WebSockets requests as\n    specified in\n    http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-76\n    \"\"\"\n    def __init__(self, handler):\n        WebSocketProtocol.__init__(self, handler)\n        self.challenge = None\n        self._waiting = None\n\n    def accept_connection(self):\n        try:\n            self._handle_websocket_headers()\n        except ValueError:\n            gen_log.debug(\"Malformed WebSocket request received\")\n            self._abort()\n            return\n\n        scheme = self.handler.get_websocket_scheme()\n\n        # draft76 only allows a single subprotocol\n        subprotocol_header = ''\n        subprotocol = self.request.headers.get(\"Sec-WebSocket-Protocol\", None)\n        if subprotocol:\n            selected = self.handler.select_subprotocol([subprotocol])\n            if selected:\n                assert selected == subprotocol\n                subprotocol_header = \"Sec-WebSocket-Protocol: %s\\r\\n\" % selected\n\n        # Write the initial headers before attempting to read the challenge.\n        # This is necessary when using proxies (such as HAProxy), which\n        # need to see the Upgrade headers before passing through the\n        # non-HTTP traffic that follows.\n        self.stream.write(tornado.escape.utf8(\n            \"HTTP/1.1 101 WebSocket Protocol Handshake\\r\\n\"\n            \"Upgrade: WebSocket\\r\\n\"\n            \"Connection: Upgrade\\r\\n\"\n            \"Server: TornadoServer/%(version)s\\r\\n\"\n            \"Sec-WebSocket-Origin: %(origin)s\\r\\n\"\n            \"Sec-WebSocket-Location: %(scheme)s://%(host)s%(uri)s\\r\\n\"\n            \"%(subprotocol)s\"\n            \"\\r\\n\" % (dict(\n                version=tornado.version,\n                origin=self.request.headers[\"Origin\"],\n                scheme=scheme,\n                host=self.request.host,\n                uri=self.request.uri,\n                subprotocol=subprotocol_header))))\n        self.stream.read_bytes(8, self._handle_challenge)\n\n    def challenge_response(self, challenge):\n        \"\"\"Generates the challenge response that's needed in the handshake\n\n        The challenge parameter should be the raw bytes as sent from the\n        client.\n        \"\"\"\n        key_1 = self.request.headers.get(\"Sec-Websocket-Key1\")\n        key_2 = self.request.headers.get(\"Sec-Websocket-Key2\")\n        try:\n            part_1 = self._calculate_part(key_1)\n            part_2 = self._calculate_part(key_2)\n        except ValueError:\n            raise ValueError(\"Invalid Keys/Challenge\")\n        return self._generate_challenge_response(part_1, part_2, challenge)\n\n    def _handle_challenge(self, challenge):\n        try:\n            challenge_response = self.challenge_response(challenge)\n        except ValueError:\n            gen_log.debug(\"Malformed key data in WebSocket request\")\n            self._abort()\n            return\n        self._write_response(challenge_response)\n\n    def _write_response(self, challenge):\n        self.stream.write(challenge)\n        self.async_callback(self.handler.open)(*self.handler.open_args, **self.handler.open_kwargs)\n        self._receive_message()\n\n    def _handle_websocket_headers(self):\n        \"\"\"Verifies all invariant- and required headers\n\n        If a header is missing or have an incorrect value ValueError will be\n        raised\n        \"\"\"\n        fields = (\"Origin\", \"Host\", \"Sec-Websocket-Key1\",\n                  \"Sec-Websocket-Key2\")\n        if not all(map(lambda f: self.request.headers.get(f), fields)):\n            raise ValueError(\"Missing/Invalid WebSocket headers\")\n\n    def _calculate_part(self, key):\n        \"\"\"Processes the key headers and calculates their key value.\n\n        Raises ValueError when feed invalid key.\"\"\"\n        # pyflakes complains about variable reuse if both of these lines use 'c'\n        number = int(''.join(c for c in key if c.isdigit()))\n        spaces = len([c2 for c2 in key if c2.isspace()])\n        try:\n            key_number = number // spaces\n        except (ValueError, ZeroDivisionError):\n            raise ValueError\n        return struct.pack(\">I\", key_number)\n\n    def _generate_challenge_response(self, part_1, part_2, part_3):\n        m = hashlib.md5()\n        m.update(part_1)\n        m.update(part_2)\n        m.update(part_3)\n        return m.digest()\n\n    def _receive_message(self):\n        self.stream.read_bytes(1, self._on_frame_type)\n\n    def _on_frame_type(self, byte):\n        frame_type = ord(byte)\n        if frame_type == 0x00:\n            self.stream.read_until(b\"\\xff\", self._on_end_delimiter)\n        elif frame_type == 0xff:\n            self.stream.read_bytes(1, self._on_length_indicator)\n        else:\n            self._abort()\n\n    def _on_end_delimiter(self, frame):\n        if not self.client_terminated:\n            self.async_callback(self.handler.on_message)(\n                frame[:-1].decode(\"utf-8\", \"replace\"))\n        if not self.client_terminated:\n            self._receive_message()\n\n    def _on_length_indicator(self, byte):\n        if ord(byte) != 0x00:\n            self._abort()\n            return\n        self.client_terminated = True\n        self.close()\n\n    def write_message(self, message, binary=False):\n        \"\"\"Sends the given message to the client of this Web Socket.\"\"\"\n        if binary:\n            raise ValueError(\n                \"Binary messages not supported by this version of websockets\")\n        if isinstance(message, unicode_type):\n            message = message.encode(\"utf-8\")\n        assert isinstance(message, bytes_type)\n        self.stream.write(b\"\\x00\" + message + b\"\\xff\")\n\n    def write_ping(self, data):\n        \"\"\"Send ping frame.\"\"\"\n        raise ValueError(\"Ping messages not supported by this version of websockets\")\n\n    def close(self, code=None, reason=None):\n        \"\"\"Closes the WebSocket connection.\"\"\"\n        if not self.server_terminated:\n            if not self.stream.closed():\n                self.stream.write(\"\\xff\\x00\")\n            self.server_terminated = True\n        if self.client_terminated:\n            if self._waiting is not None:\n                self.stream.io_loop.remove_timeout(self._waiting)\n            self._waiting = None\n            self.stream.close()\n        elif self._waiting is None:\n            self._waiting = self.stream.io_loop.add_timeout(\n                time.time() + 5, self._abort)\n\n\nclass WebSocketProtocol13(WebSocketProtocol):\n    \"\"\"Implementation of the WebSocket protocol from RFC 6455.\n\n    This class supports versions 7 and 8 of the protocol in addition to the\n    final version 13.\n    \"\"\"\n    def __init__(self, handler, mask_outgoing=False):\n        WebSocketProtocol.__init__(self, handler)\n        self.mask_outgoing = mask_outgoing\n        self._final_frame = False\n        self._frame_opcode = None\n        self._masked_frame = None\n        self._frame_mask = None\n        self._frame_length = None\n        self._fragmented_message_buffer = None\n        self._fragmented_message_opcode = None\n        self._waiting = None\n\n    def accept_connection(self):\n        try:\n            self._handle_websocket_headers()\n            self._accept_connection()\n        except ValueError:\n            gen_log.debug(\"Malformed WebSocket request received\", exc_info=True)\n            self._abort()\n            return\n\n    def _handle_websocket_headers(self):\n        \"\"\"Verifies all invariant- and required headers\n\n        If a header is missing or have an incorrect value ValueError will be\n        raised\n        \"\"\"\n        fields = (\"Host\", \"Sec-Websocket-Key\", \"Sec-Websocket-Version\")\n        if not all(map(lambda f: self.request.headers.get(f), fields)):\n            raise ValueError(\"Missing/Invalid WebSocket headers\")\n\n    @staticmethod\n    def compute_accept_value(key):\n        \"\"\"Computes the value for the Sec-WebSocket-Accept header,\n        given the value for Sec-WebSocket-Key.\n        \"\"\"\n        sha1 = hashlib.sha1()\n        sha1.update(utf8(key))\n        sha1.update(b\"258EAFA5-E914-47DA-95CA-C5AB0DC85B11\")  # Magic value\n        return native_str(base64.b64encode(sha1.digest()))\n\n    def _challenge_response(self):\n        return WebSocketProtocol13.compute_accept_value(\n            self.request.headers.get(\"Sec-Websocket-Key\"))\n\n    def _accept_connection(self):\n        subprotocol_header = ''\n        subprotocols = self.request.headers.get(\"Sec-WebSocket-Protocol\", '')\n        subprotocols = [s.strip() for s in subprotocols.split(',')]\n        if subprotocols:\n            selected = self.handler.select_subprotocol(subprotocols)\n            if selected:\n                assert selected in subprotocols\n                subprotocol_header = \"Sec-WebSocket-Protocol: %s\\r\\n\" % selected\n\n        self.stream.write(tornado.escape.utf8(\n            \"HTTP/1.1 101 Switching Protocols\\r\\n\"\n            \"Upgrade: websocket\\r\\n\"\n            \"Connection: Upgrade\\r\\n\"\n            \"Sec-WebSocket-Accept: %s\\r\\n\"\n            \"%s\"\n            \"\\r\\n\" % (self._challenge_response(), subprotocol_header)))\n\n        self.async_callback(self.handler.open)(*self.handler.open_args, **self.handler.open_kwargs)\n        self._receive_frame()\n\n    def _write_frame(self, fin, opcode, data):\n        if fin:\n            finbit = 0x80\n        else:\n            finbit = 0\n        frame = struct.pack(\"B\", finbit | opcode)\n        l = len(data)\n        if self.mask_outgoing:\n            mask_bit = 0x80\n        else:\n            mask_bit = 0\n        if l < 126:\n            frame += struct.pack(\"B\", l | mask_bit)\n        elif l <= 0xFFFF:\n            frame += struct.pack(\"!BH\", 126 | mask_bit, l)\n        else:\n            frame += struct.pack(\"!BQ\", 127 | mask_bit, l)\n        if self.mask_outgoing:\n            mask = os.urandom(4)\n            data = mask + _websocket_mask(mask, data)\n        frame += data\n        self.stream.write(frame)\n\n    def write_message(self, message, binary=False):\n        \"\"\"Sends the given message to the client of this Web Socket.\"\"\"\n        if binary:\n            opcode = 0x2\n        else:\n            opcode = 0x1\n        message = tornado.escape.utf8(message)\n        assert isinstance(message, bytes_type)\n        try:\n            self._write_frame(True, opcode, message)\n        except StreamClosedError:\n            self._abort()\n\n    def write_ping(self, data):\n        \"\"\"Send ping frame.\"\"\"\n        assert isinstance(data, bytes_type)\n        self._write_frame(True, 0x9, data)\n\n    def _receive_frame(self):\n        try:\n            self.stream.read_bytes(2, self._on_frame_start)\n        except StreamClosedError:\n            self._abort()\n\n    def _on_frame_start(self, data):\n        header, payloadlen = struct.unpack(\"BB\", data)\n        self._final_frame = header & 0x80\n        reserved_bits = header & 0x70\n        self._frame_opcode = header & 0xf\n        self._frame_opcode_is_control = self._frame_opcode & 0x8\n        if reserved_bits:\n            # client is using as-yet-undefined extensions; abort\n            self._abort()\n            return\n        self._masked_frame = bool(payloadlen & 0x80)\n        payloadlen = payloadlen & 0x7f\n        if self._frame_opcode_is_control and payloadlen >= 126:\n            # control frames must have payload < 126\n            self._abort()\n            return\n        try:\n            if payloadlen < 126:\n                self._frame_length = payloadlen\n                if self._masked_frame:\n                    self.stream.read_bytes(4, self._on_masking_key)\n                else:\n                    self.stream.read_bytes(self._frame_length, self._on_frame_data)\n            elif payloadlen == 126:\n                self.stream.read_bytes(2, self._on_frame_length_16)\n            elif payloadlen == 127:\n                self.stream.read_bytes(8, self._on_frame_length_64)\n        except StreamClosedError:\n            self._abort()\n\n    def _on_frame_length_16(self, data):\n        self._frame_length = struct.unpack(\"!H\", data)[0]\n        try:\n            if self._masked_frame:\n                self.stream.read_bytes(4, self._on_masking_key)\n            else:\n                self.stream.read_bytes(self._frame_length, self._on_frame_data)\n        except StreamClosedError:\n            self._abort()\n\n    def _on_frame_length_64(self, data):\n        self._frame_length = struct.unpack(\"!Q\", data)[0]\n        try:\n            if self._masked_frame:\n                self.stream.read_bytes(4, self._on_masking_key)\n            else:\n                self.stream.read_bytes(self._frame_length, self._on_frame_data)\n        except StreamClosedError:\n            self._abort()\n\n    def _on_masking_key(self, data):\n        self._frame_mask = data\n        try:\n            self.stream.read_bytes(self._frame_length, self._on_masked_frame_data)\n        except StreamClosedError:\n            self._abort()\n\n    def _on_masked_frame_data(self, data):\n        self._on_frame_data(_websocket_mask(self._frame_mask, data))\n\n    def _on_frame_data(self, data):\n        if self._frame_opcode_is_control:\n            # control frames may be interleaved with a series of fragmented\n            # data frames, so control frames must not interact with\n            # self._fragmented_*\n            if not self._final_frame:\n                # control frames must not be fragmented\n                self._abort()\n                return\n            opcode = self._frame_opcode\n        elif self._frame_opcode == 0:  # continuation frame\n            if self._fragmented_message_buffer is None:\n                # nothing to continue\n                self._abort()\n                return\n            self._fragmented_message_buffer += data\n            if self._final_frame:\n                opcode = self._fragmented_message_opcode\n                data = self._fragmented_message_buffer\n                self._fragmented_message_buffer = None\n        else:  # start of new data message\n            if self._fragmented_message_buffer is not None:\n                # can't start new message until the old one is finished\n                self._abort()\n                return\n            if self._final_frame:\n                opcode = self._frame_opcode\n            else:\n                self._fragmented_message_opcode = self._frame_opcode\n                self._fragmented_message_buffer = data\n\n        if self._final_frame:\n            self._handle_message(opcode, data)\n\n        if not self.client_terminated:\n            self._receive_frame()\n\n    def _handle_message(self, opcode, data):\n        if self.client_terminated:\n            return\n\n        if opcode == 0x1:\n            # UTF-8 data\n            try:\n                decoded = data.decode(\"utf-8\")\n            except UnicodeDecodeError:\n                self._abort()\n                return\n            self.async_callback(self.handler.on_message)(decoded)\n        elif opcode == 0x2:\n            # Binary data\n            self.async_callback(self.handler.on_message)(data)\n        elif opcode == 0x8:\n            # Close\n            self.client_terminated = True\n            if len(data) >= 2:\n                self.handler.close_code = struct.unpack('>H', data[:2])[0]\n            if len(data) > 2:\n                self.handler.close_reason = to_unicode(data[2:])\n            self.close()\n        elif opcode == 0x9:\n            # Ping\n            self._write_frame(True, 0xA, data)\n        elif opcode == 0xA:\n            # Pong\n            self.async_callback(self.handler.on_pong)(data)\n        else:\n            self._abort()\n\n    def close(self, code=None, reason=None):\n        \"\"\"Closes the WebSocket connection.\"\"\"\n        if not self.server_terminated:\n            if not self.stream.closed():\n                if code is None and reason is not None:\n                    code = 1000  # \"normal closure\" status code\n                if code is None:\n                    close_data = b''\n                else:\n                    close_data = struct.pack('>H', code)\n                if reason is not None:\n                    close_data += utf8(reason)\n                self._write_frame(True, 0x8, close_data)\n            self.server_terminated = True\n        if self.client_terminated:\n            if self._waiting is not None:\n                self.stream.io_loop.remove_timeout(self._waiting)\n                self._waiting = None\n            self.stream.close()\n        elif self._waiting is None:\n            # Give the client a few seconds to complete a clean shutdown,\n            # otherwise just close the connection.\n            self._waiting = self.stream.io_loop.add_timeout(\n                self.stream.io_loop.time() + 5, self._abort)\n\n\nclass WebSocketClientConnection(simple_httpclient._HTTPConnection):\n    \"\"\"WebSocket client connection.\n\n    This class should not be instantiated directly; use the\n    `websocket_connect` function instead.\n    \"\"\"\n    def __init__(self, io_loop, request):\n        self.connect_future = TracebackFuture()\n        self.read_future = None\n        self.read_queue = collections.deque()\n        self.key = base64.b64encode(os.urandom(16))\n\n        scheme, sep, rest = request.url.partition(':')\n        scheme = {'ws': 'http', 'wss': 'https'}[scheme]\n        request.url = scheme + sep + rest\n        request.headers.update({\n            'Upgrade': 'websocket',\n            'Connection': 'Upgrade',\n            'Sec-WebSocket-Key': self.key,\n            'Sec-WebSocket-Version': '13',\n        })\n\n        self.tcp_client = TCPClient(io_loop=io_loop)\n        super(WebSocketClientConnection, self).__init__(\n            io_loop, None, request, lambda: None, self._on_http_response,\n            104857600, self.tcp_client, 65536)\n\n    def close(self, code=None, reason=None):\n        \"\"\"Closes the websocket connection.\n\n        ``code`` and ``reason`` are documented under\n        `WebSocketHandler.close`.\n\n        .. versionadded:: 3.2\n\n        .. versionchanged:: 3.3\n\n           Added the ``code`` and ``reason`` arguments.\n        \"\"\"\n        if self.protocol is not None:\n            self.protocol.close(code, reason)\n            self.protocol = None\n\n    def _on_close(self):\n        self.on_message(None)\n        self.resolver.close()\n        super(WebSocketClientConnection, self)._on_close()\n\n    def _on_http_response(self, response):\n        if not self.connect_future.done():\n            if response.error:\n                self.connect_future.set_exception(response.error)\n            else:\n                self.connect_future.set_exception(WebSocketError(\n                    \"Non-websocket response\"))\n\n    def headers_received(self, start_line, headers):\n        if start_line.code != 101:\n            return super(WebSocketClientConnection, self).headers_received(\n                start_line, headers)\n\n        self.headers = headers\n        assert self.headers['Upgrade'].lower() == 'websocket'\n        assert self.headers['Connection'].lower() == 'upgrade'\n        accept = WebSocketProtocol13.compute_accept_value(self.key)\n        assert self.headers['Sec-Websocket-Accept'] == accept\n\n        self.protocol = WebSocketProtocol13(self, mask_outgoing=True)\n        self.protocol._receive_frame()\n\n        if self._timeout is not None:\n            self.io_loop.remove_timeout(self._timeout)\n            self._timeout = None\n\n        self.stream = self.connection.detach()\n        self.stream.set_close_callback(self._on_close)\n\n        self.connect_future.set_result(self)\n\n    def write_message(self, message, binary=False):\n        \"\"\"Sends a message to the WebSocket server.\"\"\"\n        self.protocol.write_message(message, binary)\n\n    def read_message(self, callback=None):\n        \"\"\"Reads a message from the WebSocket server.\n\n        Returns a future whose result is the message, or None\n        if the connection is closed.  If a callback argument\n        is given it will be called with the future when it is\n        ready.\n        \"\"\"\n        assert self.read_future is None\n        future = TracebackFuture()\n        if self.read_queue:\n            future.set_result(self.read_queue.popleft())\n        else:\n            self.read_future = future\n        if callback is not None:\n            self.io_loop.add_future(future, callback)\n        return future\n\n    def on_message(self, message):\n        if self.read_future is not None:\n            self.read_future.set_result(message)\n            self.read_future = None\n        else:\n            self.read_queue.append(message)\n\n    def on_pong(self, data):\n        pass\n\n\ndef websocket_connect(url, io_loop=None, callback=None, connect_timeout=None):\n    \"\"\"Client-side websocket support.\n\n    Takes a url and returns a Future whose result is a\n    `WebSocketClientConnection`.\n\n    .. versionchanged:: 3.2\n       Also accepts ``HTTPRequest`` objects in place of urls.\n    \"\"\"\n    if io_loop is None:\n        io_loop = IOLoop.current()\n    if isinstance(url, httpclient.HTTPRequest):\n        assert connect_timeout is None\n        request = url\n        # Copy and convert the headers dict/object (see comments in\n        # AsyncHTTPClient.fetch)\n        request.headers = httputil.HTTPHeaders(request.headers)\n    else:\n        request = httpclient.HTTPRequest(url, connect_timeout=connect_timeout)\n    request = httpclient._RequestProxy(\n        request, httpclient.HTTPRequest._DEFAULTS)\n    conn = WebSocketClientConnection(io_loop, request)\n    if callback is not None:\n        io_loop.add_future(conn.connect_future, callback)\n    return conn.connect_future\n\n\ndef _websocket_mask_python(mask, data):\n    \"\"\"Websocket masking function.\n\n    `mask` is a `bytes` object of length 4; `data` is a `bytes` object of any length.\n    Returns a `bytes` object of the same length as `data` with the mask applied\n    as specified in section 5.3 of RFC 6455.\n\n    This pure-python implementation may be replaced by an optimized version when available.\n    \"\"\"\n    mask = array.array(\"B\", mask)\n    unmasked = array.array(\"B\", data)\n    for i in xrange(len(data)):\n        unmasked[i] = unmasked[i] ^ mask[i % 4]\n    if hasattr(unmasked, 'tobytes'):\n        # tostring was deprecated in py32.  It hasn't been removed,\n        # but since we turn on deprecation warnings in our tests\n        # we need to use the right one.\n        return unmasked.tobytes()\n    else:\n        return unmasked.tostring()\n\nif (os.environ.get('TORNADO_NO_EXTENSION') or\n        os.environ.get('TORNADO_EXTENSION') == '0'):\n    # These environment variables exist to make it easier to do performance\n    # comparisons; they are not guaranteed to remain supported in the future.\n    _websocket_mask = _websocket_mask_python\nelse:\n    try:\n        from tornado.speedups import websocket_mask as _websocket_mask\n    except ImportError:\n        if os.environ.get('TORNADO_EXTENSION') == '1':\n            raise\n        _websocket_mask = _websocket_mask_python\n",
            "header": {
                "file": {
                    "path": "tornado/websocket.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "bfb90d18",
                "new_commit_hash": "d797a0cd",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/tornado/websocket.py"
            },
            "plus_file": {
                "path": "b/tornado/websocket.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 41,
                            "length": 6
                        },
                        "new_range": {
                            "start": 41,
                            "length": 11
                        },
                        "section": "from tornado import simple_httpclient"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "from tornado.tcpclient import TCPClient",
                                "type": "context"
                            },
                            {
                                "content": "from tornado.util import bytes_type, unicode_type",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "try:",
                                "type": "added"
                            },
                            {
                                "content": "    from urllib.parse import urlparse # py2",
                                "type": "added"
                            },
                            {
                                "content": "except ImportError:",
                                "type": "added"
                            },
                            {
                                "content": "    from urlparse import urlparse # py3",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "try:",
                                "type": "context"
                            },
                            {
                                "content": "    xrange  # py2",
                                "type": "context"
                            },
                            {
                                "content": "except NameError:",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [],
                    "added_entities": [
                        {
                            "file_name": "tornado/websocket.py",
                            "type": "statement",
                            "name": "",
                            "content": "try:\n    from urllib.parse import urlparse # py2\nexcept ImportError:\n    from urlparse import urlparse",
                            "ast_type_str": "Try",
                            "start_lineno": 44,
                            "end_lineno": 47,
                            "parent": null
                        }
                    ],
                    "deleted_entities": []
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 141,
                            "length": 9
                        },
                        "new_range": {
                            "start": 146,
                            "length": 26
                        },
                        "section": "class WebSocketHandler(tornado.web.RequestHandler):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "            self.stream.close()",
                                "type": "context"
                            },
                            {
                                "content": "            return",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "        # Handle WebSocket Origin naming convention differences",
                                "type": "added"
                            },
                            {
                                "content": "        # The difference between version 8 and 13 is that in 8 the",
                                "type": "context"
                            },
                            {
                                "content": "        # client sends a \"Sec-Websocket-Origin\" header and in 13 it's",
                                "type": "context"
                            },
                            {
                                "content": "        # simply \"Origin\".",
                                "type": "context"
                            },
                            {
                                "content": "        if \"Origin\" in self.request.headers:",
                                "type": "added"
                            },
                            {
                                "content": "            origin = self.request.headers.get(\"Origin\")",
                                "type": "added"
                            },
                            {
                                "content": "        else:",
                                "type": "added"
                            },
                            {
                                "content": "            origin = self.request.headers.get(\"Sec-Websocket-Origin\", None)",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "        # If there was an origin header, check to make sure it matches",
                                "type": "added"
                            },
                            {
                                "content": "        # according to check_origin. When the origin is None, we assume it",
                                "type": "added"
                            },
                            {
                                "content": "        # came from a browser and that it can be passed on.",
                                "type": "added"
                            },
                            {
                                "content": "        if origin is not None and not self.check_origin(origin):",
                                "type": "added"
                            },
                            {
                                "content": "            self.stream.write(tornado.escape.utf8(",
                                "type": "added"
                            },
                            {
                                "content": "                \"HTTP/1.1 403 Cross Origin Websockets Disabled\\r\\n\\r\\n\"",
                                "type": "added"
                            },
                            {
                                "content": "            ))",
                                "type": "added"
                            },
                            {
                                "content": "            self.stream.close()",
                                "type": "added"
                            },
                            {
                                "content": "            return",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "        if self.request.headers.get(\"Sec-WebSocket-Version\") in (\"7\", \"8\", \"13\"):",
                                "type": "context"
                            },
                            {
                                "content": "            self.ws_connection = WebSocketProtocol13(self)",
                                "type": "context"
                            },
                            {
                                "content": "            self.ws_connection.accept_connection()",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "tornado/websocket.py",
                            "type": "class",
                            "name": "WebSocketHandler",
                            "content": "class WebSocketHandler(tornado.web.RequestHandler):\n    \"\"\"Subclass this class to create a basic WebSocket handler.\n\n    Override `on_message` to handle incoming messages, and use\n    `write_message` to send messages to the client. You can also\n    override `open` and `on_close` to handle opened and closed\n    connections.\n\n    See http://dev.w3.org/html5/websockets/ for details on the\n    JavaScript interface.  The protocol is specified at\n    http://tools.ietf.org/html/rfc6455.\n\n    Here is an example WebSocket handler that echos back all received messages\n    back to the client::\n\n      class EchoWebSocket(websocket.WebSocketHandler):\n          def open(self):\n              print \"WebSocket opened\"\n\n          def on_message(self, message):\n              self.write_message(u\"You said: \" + message)\n\n          def on_close(self):\n              print \"WebSocket closed\"\n\n    WebSockets are not standard HTTP connections. The \"handshake\" is\n    HTTP, but after the handshake, the protocol is\n    message-based. Consequently, most of the Tornado HTTP facilities\n    are not available in handlers of this type. The only communication\n    methods available to you are `write_message()`, `ping()`, and\n    `close()`. Likewise, your request handler class should implement\n    `open()` method rather than ``get()`` or ``post()``.\n\n    If you map the handler above to ``/websocket`` in your application, you can\n    invoke it in JavaScript with::\n\n      var ws = new WebSocket(\"ws://localhost:8888/websocket\");\n      ws.onopen = function() {\n         ws.send(\"Hello, world\");\n      };\n      ws.onmessage = function (evt) {\n         alert(evt.data);\n      };\n\n    This script pops up an alert box that says \"You said: Hello, world\".\n    \"\"\"\n    def __init__(self, application, request, **kwargs):\n        tornado.web.RequestHandler.__init__(self, application, request,\n                                            **kwargs)\n        self.ws_connection = None\n        self.close_code = None\n        self.close_reason = None\n\n    @tornado.web.asynchronous\n    def get(self, *args, **kwargs):\n        self.open_args = args\n        self.open_kwargs = kwargs\n\n        self.stream = self.request.connection.detach()\n        self.stream.set_close_callback(self.on_connection_close)\n\n        # Upgrade header should be present and should be equal to WebSocket\n        if self.request.headers.get(\"Upgrade\", \"\").lower() != 'websocket':\n            self.stream.write(tornado.escape.utf8(\n                \"HTTP/1.1 400 Bad Request\\r\\n\\r\\n\"\n                \"Can \\\"Upgrade\\\" only to \\\"WebSocket\\\".\"\n            ))\n            self.stream.close()\n            return\n\n        # Connection header should be upgrade. Some proxy servers/load balancers\n        # might mess with it.\n        headers = self.request.headers\n        connection = map(lambda s: s.strip().lower(), headers.get(\"Connection\", \"\").split(\",\"))\n        if 'upgrade' not in connection:\n            self.stream.write(tornado.escape.utf8(\n                \"HTTP/1.1 400 Bad Request\\r\\n\\r\\n\"\n                \"\\\"Connection\\\" must be \\\"Upgrade\\\".\"\n            ))\n            self.stream.close()\n            return\n\n        # Handle WebSocket Origin naming convention differences\n        # The difference between version 8 and 13 is that in 8 the\n        # client sends a \"Sec-Websocket-Origin\" header and in 13 it's\n        # simply \"Origin\".\n        if \"Origin\" in self.request.headers:\n            origin = self.request.headers.get(\"Origin\")\n        else:\n            origin = self.request.headers.get(\"Sec-Websocket-Origin\", None)\n\n\n        # If there was an origin header, check to make sure it matches\n        # according to check_origin. When the origin is None, we assume it\n        # came from a browser and that it can be passed on.\n        if origin is not None and not self.check_origin(origin):\n            self.stream.write(tornado.escape.utf8(\n                \"HTTP/1.1 403 Cross Origin Websockets Disabled\\r\\n\\r\\n\"\n            ))\n            self.stream.close()\n            return\n\n        if self.request.headers.get(\"Sec-WebSocket-Version\") in (\"7\", \"8\", \"13\"):\n            self.ws_connection = WebSocketProtocol13(self)\n            self.ws_connection.accept_connection()\n        elif (self.allow_draft76() and\n              \"Sec-WebSocket-Version\" not in self.request.headers):\n            self.ws_connection = WebSocketProtocol76(self)\n            self.ws_connection.accept_connection()\n        else:\n            self.stream.write(tornado.escape.utf8(\n                \"HTTP/1.1 426 Upgrade Required\\r\\n\"\n                \"Sec-WebSocket-Version: 8\\r\\n\\r\\n\"))\n            self.stream.close()\n\n\n    def write_message(self, message, binary=False):\n        \"\"\"Sends the given message to the client of this Web Socket.\n\n        The message may be either a string or a dict (which will be\n        encoded as json).  If the ``binary`` argument is false, the\n        message will be sent as utf8; in binary mode any byte string\n        is allowed.\n\n        If the connection is already closed, raises `WebSocketClosedError`.\n\n        .. versionchanged:: 3.2\n           `WebSocketClosedError` was added (previously a closed connection\n           would raise an `AttributeError`)\n        \"\"\"\n        if self.ws_connection is None:\n            raise WebSocketClosedError()\n        if isinstance(message, dict):\n            message = tornado.escape.json_encode(message)\n        self.ws_connection.write_message(message, binary=binary)\n\n    def select_subprotocol(self, subprotocols):\n        \"\"\"Invoked when a new WebSocket requests specific subprotocols.\n\n        ``subprotocols`` is a list of strings identifying the\n        subprotocols proposed by the client.  This method may be\n        overridden to return one of those strings to select it, or\n        ``None`` to not select a subprotocol.  Failure to select a\n        subprotocol does not automatically abort the connection,\n        although clients may close the connection if none of their\n        proposed subprotocols was selected.\n        \"\"\"\n        return None\n\n    def open(self):\n        \"\"\"Invoked when a new WebSocket is opened.\n\n        The arguments to `open` are extracted from the `tornado.web.URLSpec`\n        regular expression, just like the arguments to\n        `tornado.web.RequestHandler.get`.\n        \"\"\"\n        pass\n\n    def on_message(self, message):\n        \"\"\"Handle incoming messages on the WebSocket\n\n        This method must be overridden.\n        \"\"\"\n        raise NotImplementedError\n\n    def ping(self, data):\n        \"\"\"Send ping frame to the remote end.\"\"\"\n        if self.ws_connection is None:\n            raise WebSocketClosedError()\n        self.ws_connection.write_ping(data)\n\n    def on_pong(self, data):\n        \"\"\"Invoked when the response to a ping frame is received.\"\"\"\n        pass\n\n    def on_close(self):\n        \"\"\"Invoked when the WebSocket is closed.\n\n        If the connection was closed cleanly and a status code or reason\n        phrase was supplied, these values will be available as the attributes\n        ``self.close_code`` and ``self.close_reason``.\n\n        .. versionchanged:: 3.3\n\n           Added ``close_code`` and ``close_reason`` attributes.\n        \"\"\"\n        pass\n\n    def close(self, code=None, reason=None):\n        \"\"\"Closes this Web Socket.\n\n        Once the close handshake is successful the socket will be closed.\n\n        ``code`` may be a numeric status code, taken from the values\n        defined in `RFC 6455 section 7.4.1\n        <https://tools.ietf.org/html/rfc6455#section-7.4.1>`_.\n        ``reason`` may be a textual message about why the connection is\n        closing.  These values are made available to the client, but are\n        not otherwise interpreted by the websocket protocol.\n\n        The ``code`` and ``reason`` arguments are ignored in the \"draft76\"\n        protocol version.\n\n        .. versionchanged:: 3.3\n\n           Added the ``code`` and ``reason`` arguments.\n        \"\"\"\n        if self.ws_connection:\n            self.ws_connection.close(code, reason)\n            self.ws_connection = None\n\n    def check_origin(self, origin):\n        \"\"\"Override to enable support for allowing alternate origins.\n        \n        By default, this checks to see that the host matches the origin\n        provided.\n\n        This is a security protection against cross site scripting attacks on\n        browsers, since WebSockets don't have CORS headers.\n        \"\"\"\n\n        # Due to how stdlib's urlparse is implemented, urls without a //\n        # are interpreted to be paths (resulting in netloc being None)\n        if(\"//\" not in origin):\n            origin = \"//\" + origin\n        parsed_origin = urlparse(origin)\n        origin = parsed_origin.netloc\n        origin = origin.lower()\n\n        host = self.request.headers.get(\"Host\")\n\n        # Check to see that origin matches host directly, including ports\n        return origin == host\n\n    def allow_draft76(self):\n        \"\"\"Override to enable support for the older \"draft76\" protocol.\n\n        The draft76 version of the websocket protocol is disabled by\n        default due to security concerns, but it can be enabled by\n        overriding this method to return True.\n\n        Connections using the draft76 protocol do not support the\n        ``binary=True`` flag to `write_message`.\n\n        Support for the draft76 protocol is deprecated and will be\n        removed in a future version of Tornado.\n        \"\"\"\n        return False\n\n    def set_nodelay(self, value):\n        \"\"\"Set the no-delay flag for this stream.\n\n        By default, small messages may be delayed and/or combined to minimize\n        the number of packets sent.  This can sometimes cause 200-500ms delays\n        due to the interaction between Nagle's algorithm and TCP delayed\n        ACKs.  To reduce this delay (at the expense of possibly increasing\n        bandwidth usage), call ``self.set_nodelay(True)`` once the websocket\n        connection is established.\n\n        See `.BaseIOStream.set_nodelay` for additional details.\n\n        .. versionadded:: 3.1\n        \"\"\"\n        self.stream.set_nodelay(value)\n\n    def get_websocket_scheme(self):\n        \"\"\"Return the url scheme used for this request, either \"ws\" or \"wss\".\n\n        This is normally decided by HTTPServer, but applications\n        may wish to override this if they are using an SSL proxy\n        that does not provide the X-Scheme header as understood\n        by HTTPServer.\n\n        Note that this is only used by the draft76 protocol.\n        \"\"\"\n        return \"wss\" if self.request.protocol == \"https\" else \"ws\"\n\n    def async_callback(self, callback, *args, **kwargs):\n        \"\"\"Obsolete - catches exceptions from the wrapped function.\n\n        This function is normally unncecessary thanks to\n        `tornado.stack_context`.\n        \"\"\"\n        return self.ws_connection.async_callback(callback, *args, **kwargs)\n\n    def _not_supported(self, *args, **kwargs):\n        raise Exception(\"Method not supported for Web Sockets\")\n\n    def on_connection_close(self):\n        if self.ws_connection:\n            self.ws_connection.on_connection_close()\n            self.ws_connection = None\n            self.on_close()",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 67,
                            "end_lineno": 359,
                            "parent": null
                        },
                        {
                            "file_name": "tornado/websocket.py",
                            "type": "method",
                            "name": "WebSocketHandler.get",
                            "content": "class WebSocketHandler(tornado.web.RequestHandler):\n    \"\"\"Subclass this class to create a basic WebSocket handler.\n\n    Override `on_message` to handle incoming messages, and use\n    `write_message` to send messages to the client. You can also\n    override `open` and `on_close` to handle opened and closed\n    connections.\n\n    See http://dev.w3.org/html5/websockets/ for details on the\n    JavaScript interface.  The protocol is specified at\n    http://tools.ietf.org/html/rfc6455.\n\n    Here is an example WebSocket handler that echos back all received messages\n    back to the client::\n\n      class EchoWebSocket(websocket.WebSocketHandler):\n          def open(self):\n              print \"WebSocket opened\"\n\n          def on_message(self, message):\n              self.write_message(u\"You said: \" + message)\n\n          def on_close(self):\n              print \"WebSocket closed\"\n\n    WebSockets are not standard HTTP connections. The \"handshake\" is\n    HTTP, but after the handshake, the protocol is\n    message-based. Consequently, most of the Tornado HTTP facilities\n    are not available in handlers of this type. The only communication\n    methods available to you are `write_message()`, `ping()`, and\n    `close()`. Likewise, your request handler class should implement\n    `open()` method rather than ``get()`` or ``post()``.\n\n    If you map the handler above to ``/websocket`` in your application, you can\n    invoke it in JavaScript with::\n\n      var ws = new WebSocket(\"ws://localhost:8888/websocket\");\n      ws.onopen = function() {\n         ws.send(\"Hello, world\");\n      };\n      ws.onmessage = function (evt) {\n         alert(evt.data);\n      };\n\n    This script pops up an alert box that says \"You said: Hello, world\".\n    \"\"\"\n    def __init__(self, application, request, **kwargs):\n        tornado.web.RequestHandler.__init__(self, application, request,\n                                            **kwargs)\n        self.ws_connection = None\n        self.close_code = None\n        self.close_reason = None\n\n    @tornado.web.asynchronous\n    def get(self, *args, **kwargs):\n        self.open_args = args\n        self.open_kwargs = kwargs\n\n        self.stream = self.request.connection.detach()\n        self.stream.set_close_callback(self.on_connection_close)\n\n        # Upgrade header should be present and should be equal to WebSocket\n        if self.request.headers.get(\"Upgrade\", \"\").lower() != 'websocket':\n            self.stream.write(tornado.escape.utf8(\n                \"HTTP/1.1 400 Bad Request\\r\\n\\r\\n\"\n                \"Can \\\"Upgrade\\\" only to \\\"WebSocket\\\".\"\n            ))\n            self.stream.close()\n            return\n\n        # Connection header should be upgrade. Some proxy servers/load balancers\n        # might mess with it.\n        headers = self.request.headers\n        connection = map(lambda s: s.strip().lower(), headers.get(\"Connection\", \"\").split(\",\"))\n        if 'upgrade' not in connection:\n            self.stream.write(tornado.escape.utf8(\n                \"HTTP/1.1 400 Bad Request\\r\\n\\r\\n\"\n                \"\\\"Connection\\\" must be \\\"Upgrade\\\".\"\n            ))\n            self.stream.close()\n            return\n\n        # Handle WebSocket Origin naming convention differences\n        # The difference between version 8 and 13 is that in 8 the\n        # client sends a \"Sec-Websocket-Origin\" header and in 13 it's\n        # simply \"Origin\".\n        if \"Origin\" in self.request.headers:\n            origin = self.request.headers.get(\"Origin\")\n        else:\n            origin = self.request.headers.get(\"Sec-Websocket-Origin\", None)\n\n\n        # If there was an origin header, check to make sure it matches\n        # according to check_origin. When the origin is None, we assume it\n        # came from a browser and that it can be passed on.\n        if origin is not None and not self.check_origin(origin):\n            self.stream.write(tornado.escape.utf8(\n                \"HTTP/1.1 403 Cross Origin Websockets Disabled\\r\\n\\r\\n\"\n            ))\n            self.stream.close()\n            return\n\n        if self.request.headers.get(\"Sec-WebSocket-Version\") in (\"7\", \"8\", \"13\"):\n            self.ws_connection = WebSocketProtocol13(self)\n            self.ws_connection.accept_connection()\n        elif (self.allow_draft76() and\n              \"Sec-WebSocket-Version\" not in self.request.headers):\n            self.ws_connection = WebSocketProtocol76(self)\n            self.ws_connection.accept_connection()\n        else:\n            self.stream.write(tornado.escape.utf8(\n                \"HTTP/1.1 426 Upgrade Required\\r\\n\"\n                \"Sec-WebSocket-Version: 8\\r\\n\\r\\n\"))\n            self.stream.close()\n\n\n    def write_message(self, message, binary=False):\n        \"\"\"Sends the given message to the client of this Web Socket.\n\n        The message may be either a string or a dict (which will be\n        encoded as json).  If the ``binary`` argument is false, the\n        message will be sent as utf8; in binary mode any byte string\n        is allowed.\n\n        If the connection is already closed, raises `WebSocketClosedError`.\n\n        .. versionchanged:: 3.2\n           `WebSocketClosedError` was added (previously a closed connection\n           would raise an `AttributeError`)\n        \"\"\"\n        if self.ws_connection is None:\n            raise WebSocketClosedError()\n        if isinstance(message, dict):\n            message = tornado.escape.json_encode(message)\n        self.ws_connection.write_message(message, binary=binary)\n\n    def select_subprotocol(self, subprotocols):\n        \"\"\"Invoked when a new WebSocket requests specific subprotocols.\n\n        ``subprotocols`` is a list of strings identifying the\n        subprotocols proposed by the client.  This method may be\n        overridden to return one of those strings to select it, or\n        ``None`` to not select a subprotocol.  Failure to select a\n        subprotocol does not automatically abort the connection,\n        although clients may close the connection if none of their\n        proposed subprotocols was selected.\n        \"\"\"\n        return None\n\n    def open(self):\n        \"\"\"Invoked when a new WebSocket is opened.\n\n        The arguments to `open` are extracted from the `tornado.web.URLSpec`\n        regular expression, just like the arguments to\n        `tornado.web.RequestHandler.get`.\n        \"\"\"\n        pass\n\n    def on_message(self, message):\n        \"\"\"Handle incoming messages on the WebSocket\n\n        This method must be overridden.\n        \"\"\"\n        raise NotImplementedError\n\n    def ping(self, data):\n        \"\"\"Send ping frame to the remote end.\"\"\"\n        if self.ws_connection is None:\n            raise WebSocketClosedError()\n        self.ws_connection.write_ping(data)\n\n    def on_pong(self, data):\n        \"\"\"Invoked when the response to a ping frame is received.\"\"\"\n        pass\n\n    def on_close(self):\n        \"\"\"Invoked when the WebSocket is closed.\n\n        If the connection was closed cleanly and a status code or reason\n        phrase was supplied, these values will be available as the attributes\n        ``self.close_code`` and ``self.close_reason``.\n\n        .. versionchanged:: 3.3\n\n           Added ``close_code`` and ``close_reason`` attributes.\n        \"\"\"\n        pass\n\n    def close(self, code=None, reason=None):\n        \"\"\"Closes this Web Socket.\n\n        Once the close handshake is successful the socket will be closed.\n\n        ``code`` may be a numeric status code, taken from the values\n        defined in `RFC 6455 section 7.4.1\n        <https://tools.ietf.org/html/rfc6455#section-7.4.1>`_.\n        ``reason`` may be a textual message about why the connection is\n        closing.  These values are made available to the client, but are\n        not otherwise interpreted by the websocket protocol.\n\n        The ``code`` and ``reason`` arguments are ignored in the \"draft76\"\n        protocol version.\n\n        .. versionchanged:: 3.3\n\n           Added the ``code`` and ``reason`` arguments.\n        \"\"\"\n        if self.ws_connection:\n            self.ws_connection.close(code, reason)\n            self.ws_connection = None\n\n    def check_origin(self, origin):\n        \"\"\"Override to enable support for allowing alternate origins.\n        \n        By default, this checks to see that the host matches the origin\n        provided.\n\n        This is a security protection against cross site scripting attacks on\n        browsers, since WebSockets don't have CORS headers.\n        \"\"\"\n\n        # Due to how stdlib's urlparse is implemented, urls without a //\n        # are interpreted to be paths (resulting in netloc being None)\n        if(\"//\" not in origin):\n            origin = \"//\" + origin\n        parsed_origin = urlparse(origin)\n        origin = parsed_origin.netloc\n        origin = origin.lower()\n\n        host = self.request.headers.get(\"Host\")\n\n        # Check to see that origin matches host directly, including ports\n        return origin == host\n\n    def allow_draft76(self):\n        \"\"\"Override to enable support for the older \"draft76\" protocol.\n\n        The draft76 version of the websocket protocol is disabled by\n        default due to security concerns, but it can be enabled by\n        overriding this method to return True.\n\n        Connections using the draft76 protocol do not support the\n        ``binary=True`` flag to `write_message`.\n\n        Support for the draft76 protocol is deprecated and will be\n        removed in a future version of Tornado.\n        \"\"\"\n        return False\n\n    def set_nodelay(self, value):\n        \"\"\"Set the no-delay flag for this stream.\n\n        By default, small messages may be delayed and/or combined to minimize\n        the number of packets sent.  This can sometimes cause 200-500ms delays\n        due to the interaction between Nagle's algorithm and TCP delayed\n        ACKs.  To reduce this delay (at the expense of possibly increasing\n        bandwidth usage), call ``self.set_nodelay(True)`` once the websocket\n        connection is established.\n\n        See `.BaseIOStream.set_nodelay` for additional details.\n\n        .. versionadded:: 3.1\n        \"\"\"\n        self.stream.set_nodelay(value)\n\n    def get_websocket_scheme(self):\n        \"\"\"Return the url scheme used for this request, either \"ws\" or \"wss\".\n\n        This is normally decided by HTTPServer, but applications\n        may wish to override this if they are using an SSL proxy\n        that does not provide the X-Scheme header as understood\n        by HTTPServer.\n\n        Note that this is only used by the draft76 protocol.\n        \"\"\"\n        return \"wss\" if self.request.protocol == \"https\" else \"ws\"\n\n    def async_callback(self, callback, *args, **kwargs):\n        \"\"\"Obsolete - catches exceptions from the wrapped function.\n\n        This function is normally unncecessary thanks to\n        `tornado.stack_context`.\n        \"\"\"\n        return self.ws_connection.async_callback(callback, *args, **kwargs)\n\n    def _not_supported(self, *args, **kwargs):\n        raise Exception(\"Method not supported for Web Sockets\")\n\n    def on_connection_close(self):\n        if self.ws_connection:\n            self.ws_connection.on_connection_close()\n            self.ws_connection = None\n            self.on_close()",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 121,
                            "end_lineno": 180,
                            "parent": {
                                "file_name": "tornado/websocket.py",
                                "type": "class",
                                "name": "WebSocketHandler",
                                "content": "class WebSocketHandler(tornado.web.RequestHandler):\n    \"\"\"Subclass this class to create a basic WebSocket handler.\n\n    Override `on_message` to handle incoming messages, and use\n    `write_message` to send messages to the client. You can also\n    override `open` and `on_close` to handle opened and closed\n    connections.\n\n    See http://dev.w3.org/html5/websockets/ for details on the\n    JavaScript interface.  The protocol is specified at\n    http://tools.ietf.org/html/rfc6455.\n\n    Here is an example WebSocket handler that echos back all received messages\n    back to the client::\n\n      class EchoWebSocket(websocket.WebSocketHandler):\n          def open(self):\n              print \"WebSocket opened\"\n\n          def on_message(self, message):\n              self.write_message(u\"You said: \" + message)\n\n          def on_close(self):\n              print \"WebSocket closed\"\n\n    WebSockets are not standard HTTP connections. The \"handshake\" is\n    HTTP, but after the handshake, the protocol is\n    message-based. Consequently, most of the Tornado HTTP facilities\n    are not available in handlers of this type. The only communication\n    methods available to you are `write_message()`, `ping()`, and\n    `close()`. Likewise, your request handler class should implement\n    `open()` method rather than ``get()`` or ``post()``.\n\n    If you map the handler above to ``/websocket`` in your application, you can\n    invoke it in JavaScript with::\n\n      var ws = new WebSocket(\"ws://localhost:8888/websocket\");\n      ws.onopen = function() {\n         ws.send(\"Hello, world\");\n      };\n      ws.onmessage = function (evt) {\n         alert(evt.data);\n      };\n\n    This script pops up an alert box that says \"You said: Hello, world\".\n    \"\"\"\n    def __init__(self, application, request, **kwargs):\n        tornado.web.RequestHandler.__init__(self, application, request,\n                                            **kwargs)\n        self.ws_connection = None\n        self.close_code = None\n        self.close_reason = None\n\n    @tornado.web.asynchronous\n    def get(self, *args, **kwargs):\n        self.open_args = args\n        self.open_kwargs = kwargs\n\n        self.stream = self.request.connection.detach()\n        self.stream.set_close_callback(self.on_connection_close)\n\n        # Upgrade header should be present and should be equal to WebSocket\n        if self.request.headers.get(\"Upgrade\", \"\").lower() != 'websocket':\n            self.stream.write(tornado.escape.utf8(\n                \"HTTP/1.1 400 Bad Request\\r\\n\\r\\n\"\n                \"Can \\\"Upgrade\\\" only to \\\"WebSocket\\\".\"\n            ))\n            self.stream.close()\n            return\n\n        # Connection header should be upgrade. Some proxy servers/load balancers\n        # might mess with it.\n        headers = self.request.headers\n        connection = map(lambda s: s.strip().lower(), headers.get(\"Connection\", \"\").split(\",\"))\n        if 'upgrade' not in connection:\n            self.stream.write(tornado.escape.utf8(\n                \"HTTP/1.1 400 Bad Request\\r\\n\\r\\n\"\n                \"\\\"Connection\\\" must be \\\"Upgrade\\\".\"\n            ))\n            self.stream.close()\n            return\n\n        # Handle WebSocket Origin naming convention differences\n        # The difference between version 8 and 13 is that in 8 the\n        # client sends a \"Sec-Websocket-Origin\" header and in 13 it's\n        # simply \"Origin\".\n        if \"Origin\" in self.request.headers:\n            origin = self.request.headers.get(\"Origin\")\n        else:\n            origin = self.request.headers.get(\"Sec-Websocket-Origin\", None)\n\n\n        # If there was an origin header, check to make sure it matches\n        # according to check_origin. When the origin is None, we assume it\n        # came from a browser and that it can be passed on.\n        if origin is not None and not self.check_origin(origin):\n            self.stream.write(tornado.escape.utf8(\n                \"HTTP/1.1 403 Cross Origin Websockets Disabled\\r\\n\\r\\n\"\n            ))\n            self.stream.close()\n            return\n\n        if self.request.headers.get(\"Sec-WebSocket-Version\") in (\"7\", \"8\", \"13\"):\n            self.ws_connection = WebSocketProtocol13(self)\n            self.ws_connection.accept_connection()\n        elif (self.allow_draft76() and\n              \"Sec-WebSocket-Version\" not in self.request.headers):\n            self.ws_connection = WebSocketProtocol76(self)\n            self.ws_connection.accept_connection()\n        else:\n            self.stream.write(tornado.escape.utf8(\n                \"HTTP/1.1 426 Upgrade Required\\r\\n\"\n                \"Sec-WebSocket-Version: 8\\r\\n\\r\\n\"))\n            self.stream.close()\n\n\n    def write_message(self, message, binary=False):\n        \"\"\"Sends the given message to the client of this Web Socket.\n\n        The message may be either a string or a dict (which will be\n        encoded as json).  If the ``binary`` argument is false, the\n        message will be sent as utf8; in binary mode any byte string\n        is allowed.\n\n        If the connection is already closed, raises `WebSocketClosedError`.\n\n        .. versionchanged:: 3.2\n           `WebSocketClosedError` was added (previously a closed connection\n           would raise an `AttributeError`)\n        \"\"\"\n        if self.ws_connection is None:\n            raise WebSocketClosedError()\n        if isinstance(message, dict):\n            message = tornado.escape.json_encode(message)\n        self.ws_connection.write_message(message, binary=binary)\n\n    def select_subprotocol(self, subprotocols):\n        \"\"\"Invoked when a new WebSocket requests specific subprotocols.\n\n        ``subprotocols`` is a list of strings identifying the\n        subprotocols proposed by the client.  This method may be\n        overridden to return one of those strings to select it, or\n        ``None`` to not select a subprotocol.  Failure to select a\n        subprotocol does not automatically abort the connection,\n        although clients may close the connection if none of their\n        proposed subprotocols was selected.\n        \"\"\"\n        return None\n\n    def open(self):\n        \"\"\"Invoked when a new WebSocket is opened.\n\n        The arguments to `open` are extracted from the `tornado.web.URLSpec`\n        regular expression, just like the arguments to\n        `tornado.web.RequestHandler.get`.\n        \"\"\"\n        pass\n\n    def on_message(self, message):\n        \"\"\"Handle incoming messages on the WebSocket\n\n        This method must be overridden.\n        \"\"\"\n        raise NotImplementedError\n\n    def ping(self, data):\n        \"\"\"Send ping frame to the remote end.\"\"\"\n        if self.ws_connection is None:\n            raise WebSocketClosedError()\n        self.ws_connection.write_ping(data)\n\n    def on_pong(self, data):\n        \"\"\"Invoked when the response to a ping frame is received.\"\"\"\n        pass\n\n    def on_close(self):\n        \"\"\"Invoked when the WebSocket is closed.\n\n        If the connection was closed cleanly and a status code or reason\n        phrase was supplied, these values will be available as the attributes\n        ``self.close_code`` and ``self.close_reason``.\n\n        .. versionchanged:: 3.3\n\n           Added ``close_code`` and ``close_reason`` attributes.\n        \"\"\"\n        pass\n\n    def close(self, code=None, reason=None):\n        \"\"\"Closes this Web Socket.\n\n        Once the close handshake is successful the socket will be closed.\n\n        ``code`` may be a numeric status code, taken from the values\n        defined in `RFC 6455 section 7.4.1\n        <https://tools.ietf.org/html/rfc6455#section-7.4.1>`_.\n        ``reason`` may be a textual message about why the connection is\n        closing.  These values are made available to the client, but are\n        not otherwise interpreted by the websocket protocol.\n\n        The ``code`` and ``reason`` arguments are ignored in the \"draft76\"\n        protocol version.\n\n        .. versionchanged:: 3.3\n\n           Added the ``code`` and ``reason`` arguments.\n        \"\"\"\n        if self.ws_connection:\n            self.ws_connection.close(code, reason)\n            self.ws_connection = None\n\n    def check_origin(self, origin):\n        \"\"\"Override to enable support for allowing alternate origins.\n        \n        By default, this checks to see that the host matches the origin\n        provided.\n\n        This is a security protection against cross site scripting attacks on\n        browsers, since WebSockets don't have CORS headers.\n        \"\"\"\n\n        # Due to how stdlib's urlparse is implemented, urls without a //\n        # are interpreted to be paths (resulting in netloc being None)\n        if(\"//\" not in origin):\n            origin = \"//\" + origin\n        parsed_origin = urlparse(origin)\n        origin = parsed_origin.netloc\n        origin = origin.lower()\n\n        host = self.request.headers.get(\"Host\")\n\n        # Check to see that origin matches host directly, including ports\n        return origin == host\n\n    def allow_draft76(self):\n        \"\"\"Override to enable support for the older \"draft76\" protocol.\n\n        The draft76 version of the websocket protocol is disabled by\n        default due to security concerns, but it can be enabled by\n        overriding this method to return True.\n\n        Connections using the draft76 protocol do not support the\n        ``binary=True`` flag to `write_message`.\n\n        Support for the draft76 protocol is deprecated and will be\n        removed in a future version of Tornado.\n        \"\"\"\n        return False\n\n    def set_nodelay(self, value):\n        \"\"\"Set the no-delay flag for this stream.\n\n        By default, small messages may be delayed and/or combined to minimize\n        the number of packets sent.  This can sometimes cause 200-500ms delays\n        due to the interaction between Nagle's algorithm and TCP delayed\n        ACKs.  To reduce this delay (at the expense of possibly increasing\n        bandwidth usage), call ``self.set_nodelay(True)`` once the websocket\n        connection is established.\n\n        See `.BaseIOStream.set_nodelay` for additional details.\n\n        .. versionadded:: 3.1\n        \"\"\"\n        self.stream.set_nodelay(value)\n\n    def get_websocket_scheme(self):\n        \"\"\"Return the url scheme used for this request, either \"ws\" or \"wss\".\n\n        This is normally decided by HTTPServer, but applications\n        may wish to override this if they are using an SSL proxy\n        that does not provide the X-Scheme header as understood\n        by HTTPServer.\n\n        Note that this is only used by the draft76 protocol.\n        \"\"\"\n        return \"wss\" if self.request.protocol == \"https\" else \"ws\"\n\n    def async_callback(self, callback, *args, **kwargs):\n        \"\"\"Obsolete - catches exceptions from the wrapped function.\n\n        This function is normally unncecessary thanks to\n        `tornado.stack_context`.\n        \"\"\"\n        return self.ws_connection.async_callback(callback, *args, **kwargs)\n\n    def _not_supported(self, *args, **kwargs):\n        raise Exception(\"Method not supported for Web Sockets\")\n\n    def on_connection_close(self):\n        if self.ws_connection:\n            self.ws_connection.on_connection_close()\n            self.ws_connection = None\n            self.on_close()",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 67,
                                "end_lineno": 359,
                                "parent": null
                            }
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 157,
                            "length": 6
                        },
                        "new_range": {
                            "start": 179,
                            "length": 7
                        },
                        "section": "class WebSocketHandler(tornado.web.RequestHandler):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "                \"Sec-WebSocket-Version: 8\\r\\n\\r\\n\"))",
                                "type": "context"
                            },
                            {
                                "content": "            self.stream.close()",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "    def write_message(self, message, binary=False):",
                                "type": "context"
                            },
                            {
                                "content": "        \"\"\"Sends the given message to the client of this Web Socket.",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "tornado/websocket.py",
                            "type": "class",
                            "name": "WebSocketHandler",
                            "content": "class WebSocketHandler(tornado.web.RequestHandler):\n    \"\"\"Subclass this class to create a basic WebSocket handler.\n\n    Override `on_message` to handle incoming messages, and use\n    `write_message` to send messages to the client. You can also\n    override `open` and `on_close` to handle opened and closed\n    connections.\n\n    See http://dev.w3.org/html5/websockets/ for details on the\n    JavaScript interface.  The protocol is specified at\n    http://tools.ietf.org/html/rfc6455.\n\n    Here is an example WebSocket handler that echos back all received messages\n    back to the client::\n\n      class EchoWebSocket(websocket.WebSocketHandler):\n          def open(self):\n              print \"WebSocket opened\"\n\n          def on_message(self, message):\n              self.write_message(u\"You said: \" + message)\n\n          def on_close(self):\n              print \"WebSocket closed\"\n\n    WebSockets are not standard HTTP connections. The \"handshake\" is\n    HTTP, but after the handshake, the protocol is\n    message-based. Consequently, most of the Tornado HTTP facilities\n    are not available in handlers of this type. The only communication\n    methods available to you are `write_message()`, `ping()`, and\n    `close()`. Likewise, your request handler class should implement\n    `open()` method rather than ``get()`` or ``post()``.\n\n    If you map the handler above to ``/websocket`` in your application, you can\n    invoke it in JavaScript with::\n\n      var ws = new WebSocket(\"ws://localhost:8888/websocket\");\n      ws.onopen = function() {\n         ws.send(\"Hello, world\");\n      };\n      ws.onmessage = function (evt) {\n         alert(evt.data);\n      };\n\n    This script pops up an alert box that says \"You said: Hello, world\".\n    \"\"\"\n    def __init__(self, application, request, **kwargs):\n        tornado.web.RequestHandler.__init__(self, application, request,\n                                            **kwargs)\n        self.ws_connection = None\n        self.close_code = None\n        self.close_reason = None\n\n    @tornado.web.asynchronous\n    def get(self, *args, **kwargs):\n        self.open_args = args\n        self.open_kwargs = kwargs\n\n        self.stream = self.request.connection.detach()\n        self.stream.set_close_callback(self.on_connection_close)\n\n        # Upgrade header should be present and should be equal to WebSocket\n        if self.request.headers.get(\"Upgrade\", \"\").lower() != 'websocket':\n            self.stream.write(tornado.escape.utf8(\n                \"HTTP/1.1 400 Bad Request\\r\\n\\r\\n\"\n                \"Can \\\"Upgrade\\\" only to \\\"WebSocket\\\".\"\n            ))\n            self.stream.close()\n            return\n\n        # Connection header should be upgrade. Some proxy servers/load balancers\n        # might mess with it.\n        headers = self.request.headers\n        connection = map(lambda s: s.strip().lower(), headers.get(\"Connection\", \"\").split(\",\"))\n        if 'upgrade' not in connection:\n            self.stream.write(tornado.escape.utf8(\n                \"HTTP/1.1 400 Bad Request\\r\\n\\r\\n\"\n                \"\\\"Connection\\\" must be \\\"Upgrade\\\".\"\n            ))\n            self.stream.close()\n            return\n\n        # Handle WebSocket Origin naming convention differences\n        # The difference between version 8 and 13 is that in 8 the\n        # client sends a \"Sec-Websocket-Origin\" header and in 13 it's\n        # simply \"Origin\".\n        if \"Origin\" in self.request.headers:\n            origin = self.request.headers.get(\"Origin\")\n        else:\n            origin = self.request.headers.get(\"Sec-Websocket-Origin\", None)\n\n\n        # If there was an origin header, check to make sure it matches\n        # according to check_origin. When the origin is None, we assume it\n        # came from a browser and that it can be passed on.\n        if origin is not None and not self.check_origin(origin):\n            self.stream.write(tornado.escape.utf8(\n                \"HTTP/1.1 403 Cross Origin Websockets Disabled\\r\\n\\r\\n\"\n            ))\n            self.stream.close()\n            return\n\n        if self.request.headers.get(\"Sec-WebSocket-Version\") in (\"7\", \"8\", \"13\"):\n            self.ws_connection = WebSocketProtocol13(self)\n            self.ws_connection.accept_connection()\n        elif (self.allow_draft76() and\n              \"Sec-WebSocket-Version\" not in self.request.headers):\n            self.ws_connection = WebSocketProtocol76(self)\n            self.ws_connection.accept_connection()\n        else:\n            self.stream.write(tornado.escape.utf8(\n                \"HTTP/1.1 426 Upgrade Required\\r\\n\"\n                \"Sec-WebSocket-Version: 8\\r\\n\\r\\n\"))\n            self.stream.close()\n\n\n    def write_message(self, message, binary=False):\n        \"\"\"Sends the given message to the client of this Web Socket.\n\n        The message may be either a string or a dict (which will be\n        encoded as json).  If the ``binary`` argument is false, the\n        message will be sent as utf8; in binary mode any byte string\n        is allowed.\n\n        If the connection is already closed, raises `WebSocketClosedError`.\n\n        .. versionchanged:: 3.2\n           `WebSocketClosedError` was added (previously a closed connection\n           would raise an `AttributeError`)\n        \"\"\"\n        if self.ws_connection is None:\n            raise WebSocketClosedError()\n        if isinstance(message, dict):\n            message = tornado.escape.json_encode(message)\n        self.ws_connection.write_message(message, binary=binary)\n\n    def select_subprotocol(self, subprotocols):\n        \"\"\"Invoked when a new WebSocket requests specific subprotocols.\n\n        ``subprotocols`` is a list of strings identifying the\n        subprotocols proposed by the client.  This method may be\n        overridden to return one of those strings to select it, or\n        ``None`` to not select a subprotocol.  Failure to select a\n        subprotocol does not automatically abort the connection,\n        although clients may close the connection if none of their\n        proposed subprotocols was selected.\n        \"\"\"\n        return None\n\n    def open(self):\n        \"\"\"Invoked when a new WebSocket is opened.\n\n        The arguments to `open` are extracted from the `tornado.web.URLSpec`\n        regular expression, just like the arguments to\n        `tornado.web.RequestHandler.get`.\n        \"\"\"\n        pass\n\n    def on_message(self, message):\n        \"\"\"Handle incoming messages on the WebSocket\n\n        This method must be overridden.\n        \"\"\"\n        raise NotImplementedError\n\n    def ping(self, data):\n        \"\"\"Send ping frame to the remote end.\"\"\"\n        if self.ws_connection is None:\n            raise WebSocketClosedError()\n        self.ws_connection.write_ping(data)\n\n    def on_pong(self, data):\n        \"\"\"Invoked when the response to a ping frame is received.\"\"\"\n        pass\n\n    def on_close(self):\n        \"\"\"Invoked when the WebSocket is closed.\n\n        If the connection was closed cleanly and a status code or reason\n        phrase was supplied, these values will be available as the attributes\n        ``self.close_code`` and ``self.close_reason``.\n\n        .. versionchanged:: 3.3\n\n           Added ``close_code`` and ``close_reason`` attributes.\n        \"\"\"\n        pass\n\n    def close(self, code=None, reason=None):\n        \"\"\"Closes this Web Socket.\n\n        Once the close handshake is successful the socket will be closed.\n\n        ``code`` may be a numeric status code, taken from the values\n        defined in `RFC 6455 section 7.4.1\n        <https://tools.ietf.org/html/rfc6455#section-7.4.1>`_.\n        ``reason`` may be a textual message about why the connection is\n        closing.  These values are made available to the client, but are\n        not otherwise interpreted by the websocket protocol.\n\n        The ``code`` and ``reason`` arguments are ignored in the \"draft76\"\n        protocol version.\n\n        .. versionchanged:: 3.3\n\n           Added the ``code`` and ``reason`` arguments.\n        \"\"\"\n        if self.ws_connection:\n            self.ws_connection.close(code, reason)\n            self.ws_connection = None\n\n    def check_origin(self, origin):\n        \"\"\"Override to enable support for allowing alternate origins.\n        \n        By default, this checks to see that the host matches the origin\n        provided.\n\n        This is a security protection against cross site scripting attacks on\n        browsers, since WebSockets don't have CORS headers.\n        \"\"\"\n\n        # Due to how stdlib's urlparse is implemented, urls without a //\n        # are interpreted to be paths (resulting in netloc being None)\n        if(\"//\" not in origin):\n            origin = \"//\" + origin\n        parsed_origin = urlparse(origin)\n        origin = parsed_origin.netloc\n        origin = origin.lower()\n\n        host = self.request.headers.get(\"Host\")\n\n        # Check to see that origin matches host directly, including ports\n        return origin == host\n\n    def allow_draft76(self):\n        \"\"\"Override to enable support for the older \"draft76\" protocol.\n\n        The draft76 version of the websocket protocol is disabled by\n        default due to security concerns, but it can be enabled by\n        overriding this method to return True.\n\n        Connections using the draft76 protocol do not support the\n        ``binary=True`` flag to `write_message`.\n\n        Support for the draft76 protocol is deprecated and will be\n        removed in a future version of Tornado.\n        \"\"\"\n        return False\n\n    def set_nodelay(self, value):\n        \"\"\"Set the no-delay flag for this stream.\n\n        By default, small messages may be delayed and/or combined to minimize\n        the number of packets sent.  This can sometimes cause 200-500ms delays\n        due to the interaction between Nagle's algorithm and TCP delayed\n        ACKs.  To reduce this delay (at the expense of possibly increasing\n        bandwidth usage), call ``self.set_nodelay(True)`` once the websocket\n        connection is established.\n\n        See `.BaseIOStream.set_nodelay` for additional details.\n\n        .. versionadded:: 3.1\n        \"\"\"\n        self.stream.set_nodelay(value)\n\n    def get_websocket_scheme(self):\n        \"\"\"Return the url scheme used for this request, either \"ws\" or \"wss\".\n\n        This is normally decided by HTTPServer, but applications\n        may wish to override this if they are using an SSL proxy\n        that does not provide the X-Scheme header as understood\n        by HTTPServer.\n\n        Note that this is only used by the draft76 protocol.\n        \"\"\"\n        return \"wss\" if self.request.protocol == \"https\" else \"ws\"\n\n    def async_callback(self, callback, *args, **kwargs):\n        \"\"\"Obsolete - catches exceptions from the wrapped function.\n\n        This function is normally unncecessary thanks to\n        `tornado.stack_context`.\n        \"\"\"\n        return self.ws_connection.async_callback(callback, *args, **kwargs)\n\n    def _not_supported(self, *args, **kwargs):\n        raise Exception(\"Method not supported for Web Sockets\")\n\n    def on_connection_close(self):\n        if self.ws_connection:\n            self.ws_connection.on_connection_close()\n            self.ws_connection = None\n            self.on_close()",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 67,
                            "end_lineno": 359,
                            "parent": null
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 252,
                            "length": 6
                        },
                        "new_range": {
                            "start": 275,
                            "length": 29
                        },
                        "section": "class WebSocketHandler(tornado.web.RequestHandler):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "            self.ws_connection.close(code, reason)",
                                "type": "context"
                            },
                            {
                                "content": "            self.ws_connection = None",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "    def check_origin(self, origin):",
                                "type": "added"
                            },
                            {
                                "content": "        \"\"\"Override to enable support for allowing alternate origins.",
                                "type": "added"
                            },
                            {
                                "content": "        ",
                                "type": "added"
                            },
                            {
                                "content": "        By default, this checks to see that the host matches the origin",
                                "type": "added"
                            },
                            {
                                "content": "        provided.",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "        This is a security protection against cross site scripting attacks on",
                                "type": "added"
                            },
                            {
                                "content": "        browsers, since WebSockets don't have CORS headers.",
                                "type": "added"
                            },
                            {
                                "content": "        \"\"\"",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "        # Due to how stdlib's urlparse is implemented, urls without a //",
                                "type": "added"
                            },
                            {
                                "content": "        # are interpreted to be paths (resulting in netloc being None)",
                                "type": "added"
                            },
                            {
                                "content": "        if(\"//\" not in origin):",
                                "type": "added"
                            },
                            {
                                "content": "            origin = \"//\" + origin",
                                "type": "added"
                            },
                            {
                                "content": "        parsed_origin = urlparse(origin)",
                                "type": "added"
                            },
                            {
                                "content": "        origin = parsed_origin.netloc",
                                "type": "added"
                            },
                            {
                                "content": "        origin = origin.lower()",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "        host = self.request.headers.get(\"Host\")",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "        # Check to see that origin matches host directly, including ports",
                                "type": "added"
                            },
                            {
                                "content": "        return origin == host",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "    def allow_draft76(self):",
                                "type": "context"
                            },
                            {
                                "content": "        \"\"\"Override to enable support for the older \"draft76\" protocol.",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "tornado/websocket.py",
                            "type": "class",
                            "name": "WebSocketHandler",
                            "content": "class WebSocketHandler(tornado.web.RequestHandler):\n    \"\"\"Subclass this class to create a basic WebSocket handler.\n\n    Override `on_message` to handle incoming messages, and use\n    `write_message` to send messages to the client. You can also\n    override `open` and `on_close` to handle opened and closed\n    connections.\n\n    See http://dev.w3.org/html5/websockets/ for details on the\n    JavaScript interface.  The protocol is specified at\n    http://tools.ietf.org/html/rfc6455.\n\n    Here is an example WebSocket handler that echos back all received messages\n    back to the client::\n\n      class EchoWebSocket(websocket.WebSocketHandler):\n          def open(self):\n              print \"WebSocket opened\"\n\n          def on_message(self, message):\n              self.write_message(u\"You said: \" + message)\n\n          def on_close(self):\n              print \"WebSocket closed\"\n\n    WebSockets are not standard HTTP connections. The \"handshake\" is\n    HTTP, but after the handshake, the protocol is\n    message-based. Consequently, most of the Tornado HTTP facilities\n    are not available in handlers of this type. The only communication\n    methods available to you are `write_message()`, `ping()`, and\n    `close()`. Likewise, your request handler class should implement\n    `open()` method rather than ``get()`` or ``post()``.\n\n    If you map the handler above to ``/websocket`` in your application, you can\n    invoke it in JavaScript with::\n\n      var ws = new WebSocket(\"ws://localhost:8888/websocket\");\n      ws.onopen = function() {\n         ws.send(\"Hello, world\");\n      };\n      ws.onmessage = function (evt) {\n         alert(evt.data);\n      };\n\n    This script pops up an alert box that says \"You said: Hello, world\".\n    \"\"\"\n    def __init__(self, application, request, **kwargs):\n        tornado.web.RequestHandler.__init__(self, application, request,\n                                            **kwargs)\n        self.ws_connection = None\n        self.close_code = None\n        self.close_reason = None\n\n    @tornado.web.asynchronous\n    def get(self, *args, **kwargs):\n        self.open_args = args\n        self.open_kwargs = kwargs\n\n        self.stream = self.request.connection.detach()\n        self.stream.set_close_callback(self.on_connection_close)\n\n        # Upgrade header should be present and should be equal to WebSocket\n        if self.request.headers.get(\"Upgrade\", \"\").lower() != 'websocket':\n            self.stream.write(tornado.escape.utf8(\n                \"HTTP/1.1 400 Bad Request\\r\\n\\r\\n\"\n                \"Can \\\"Upgrade\\\" only to \\\"WebSocket\\\".\"\n            ))\n            self.stream.close()\n            return\n\n        # Connection header should be upgrade. Some proxy servers/load balancers\n        # might mess with it.\n        headers = self.request.headers\n        connection = map(lambda s: s.strip().lower(), headers.get(\"Connection\", \"\").split(\",\"))\n        if 'upgrade' not in connection:\n            self.stream.write(tornado.escape.utf8(\n                \"HTTP/1.1 400 Bad Request\\r\\n\\r\\n\"\n                \"\\\"Connection\\\" must be \\\"Upgrade\\\".\"\n            ))\n            self.stream.close()\n            return\n\n        # Handle WebSocket Origin naming convention differences\n        # The difference between version 8 and 13 is that in 8 the\n        # client sends a \"Sec-Websocket-Origin\" header and in 13 it's\n        # simply \"Origin\".\n        if \"Origin\" in self.request.headers:\n            origin = self.request.headers.get(\"Origin\")\n        else:\n            origin = self.request.headers.get(\"Sec-Websocket-Origin\", None)\n\n\n        # If there was an origin header, check to make sure it matches\n        # according to check_origin. When the origin is None, we assume it\n        # came from a browser and that it can be passed on.\n        if origin is not None and not self.check_origin(origin):\n            self.stream.write(tornado.escape.utf8(\n                \"HTTP/1.1 403 Cross Origin Websockets Disabled\\r\\n\\r\\n\"\n            ))\n            self.stream.close()\n            return\n\n        if self.request.headers.get(\"Sec-WebSocket-Version\") in (\"7\", \"8\", \"13\"):\n            self.ws_connection = WebSocketProtocol13(self)\n            self.ws_connection.accept_connection()\n        elif (self.allow_draft76() and\n              \"Sec-WebSocket-Version\" not in self.request.headers):\n            self.ws_connection = WebSocketProtocol76(self)\n            self.ws_connection.accept_connection()\n        else:\n            self.stream.write(tornado.escape.utf8(\n                \"HTTP/1.1 426 Upgrade Required\\r\\n\"\n                \"Sec-WebSocket-Version: 8\\r\\n\\r\\n\"))\n            self.stream.close()\n\n\n    def write_message(self, message, binary=False):\n        \"\"\"Sends the given message to the client of this Web Socket.\n\n        The message may be either a string or a dict (which will be\n        encoded as json).  If the ``binary`` argument is false, the\n        message will be sent as utf8; in binary mode any byte string\n        is allowed.\n\n        If the connection is already closed, raises `WebSocketClosedError`.\n\n        .. versionchanged:: 3.2\n           `WebSocketClosedError` was added (previously a closed connection\n           would raise an `AttributeError`)\n        \"\"\"\n        if self.ws_connection is None:\n            raise WebSocketClosedError()\n        if isinstance(message, dict):\n            message = tornado.escape.json_encode(message)\n        self.ws_connection.write_message(message, binary=binary)\n\n    def select_subprotocol(self, subprotocols):\n        \"\"\"Invoked when a new WebSocket requests specific subprotocols.\n\n        ``subprotocols`` is a list of strings identifying the\n        subprotocols proposed by the client.  This method may be\n        overridden to return one of those strings to select it, or\n        ``None`` to not select a subprotocol.  Failure to select a\n        subprotocol does not automatically abort the connection,\n        although clients may close the connection if none of their\n        proposed subprotocols was selected.\n        \"\"\"\n        return None\n\n    def open(self):\n        \"\"\"Invoked when a new WebSocket is opened.\n\n        The arguments to `open` are extracted from the `tornado.web.URLSpec`\n        regular expression, just like the arguments to\n        `tornado.web.RequestHandler.get`.\n        \"\"\"\n        pass\n\n    def on_message(self, message):\n        \"\"\"Handle incoming messages on the WebSocket\n\n        This method must be overridden.\n        \"\"\"\n        raise NotImplementedError\n\n    def ping(self, data):\n        \"\"\"Send ping frame to the remote end.\"\"\"\n        if self.ws_connection is None:\n            raise WebSocketClosedError()\n        self.ws_connection.write_ping(data)\n\n    def on_pong(self, data):\n        \"\"\"Invoked when the response to a ping frame is received.\"\"\"\n        pass\n\n    def on_close(self):\n        \"\"\"Invoked when the WebSocket is closed.\n\n        If the connection was closed cleanly and a status code or reason\n        phrase was supplied, these values will be available as the attributes\n        ``self.close_code`` and ``self.close_reason``.\n\n        .. versionchanged:: 3.3\n\n           Added ``close_code`` and ``close_reason`` attributes.\n        \"\"\"\n        pass\n\n    def close(self, code=None, reason=None):\n        \"\"\"Closes this Web Socket.\n\n        Once the close handshake is successful the socket will be closed.\n\n        ``code`` may be a numeric status code, taken from the values\n        defined in `RFC 6455 section 7.4.1\n        <https://tools.ietf.org/html/rfc6455#section-7.4.1>`_.\n        ``reason`` may be a textual message about why the connection is\n        closing.  These values are made available to the client, but are\n        not otherwise interpreted by the websocket protocol.\n\n        The ``code`` and ``reason`` arguments are ignored in the \"draft76\"\n        protocol version.\n\n        .. versionchanged:: 3.3\n\n           Added the ``code`` and ``reason`` arguments.\n        \"\"\"\n        if self.ws_connection:\n            self.ws_connection.close(code, reason)\n            self.ws_connection = None\n\n    def check_origin(self, origin):\n        \"\"\"Override to enable support for allowing alternate origins.\n        \n        By default, this checks to see that the host matches the origin\n        provided.\n\n        This is a security protection against cross site scripting attacks on\n        browsers, since WebSockets don't have CORS headers.\n        \"\"\"\n\n        # Due to how stdlib's urlparse is implemented, urls without a //\n        # are interpreted to be paths (resulting in netloc being None)\n        if(\"//\" not in origin):\n            origin = \"//\" + origin\n        parsed_origin = urlparse(origin)\n        origin = parsed_origin.netloc\n        origin = origin.lower()\n\n        host = self.request.headers.get(\"Host\")\n\n        # Check to see that origin matches host directly, including ports\n        return origin == host\n\n    def allow_draft76(self):\n        \"\"\"Override to enable support for the older \"draft76\" protocol.\n\n        The draft76 version of the websocket protocol is disabled by\n        default due to security concerns, but it can be enabled by\n        overriding this method to return True.\n\n        Connections using the draft76 protocol do not support the\n        ``binary=True`` flag to `write_message`.\n\n        Support for the draft76 protocol is deprecated and will be\n        removed in a future version of Tornado.\n        \"\"\"\n        return False\n\n    def set_nodelay(self, value):\n        \"\"\"Set the no-delay flag for this stream.\n\n        By default, small messages may be delayed and/or combined to minimize\n        the number of packets sent.  This can sometimes cause 200-500ms delays\n        due to the interaction between Nagle's algorithm and TCP delayed\n        ACKs.  To reduce this delay (at the expense of possibly increasing\n        bandwidth usage), call ``self.set_nodelay(True)`` once the websocket\n        connection is established.\n\n        See `.BaseIOStream.set_nodelay` for additional details.\n\n        .. versionadded:: 3.1\n        \"\"\"\n        self.stream.set_nodelay(value)\n\n    def get_websocket_scheme(self):\n        \"\"\"Return the url scheme used for this request, either \"ws\" or \"wss\".\n\n        This is normally decided by HTTPServer, but applications\n        may wish to override this if they are using an SSL proxy\n        that does not provide the X-Scheme header as understood\n        by HTTPServer.\n\n        Note that this is only used by the draft76 protocol.\n        \"\"\"\n        return \"wss\" if self.request.protocol == \"https\" else \"ws\"\n\n    def async_callback(self, callback, *args, **kwargs):\n        \"\"\"Obsolete - catches exceptions from the wrapped function.\n\n        This function is normally unncecessary thanks to\n        `tornado.stack_context`.\n        \"\"\"\n        return self.ws_connection.async_callback(callback, *args, **kwargs)\n\n    def _not_supported(self, *args, **kwargs):\n        raise Exception(\"Method not supported for Web Sockets\")\n\n    def on_connection_close(self):\n        if self.ws_connection:\n            self.ws_connection.on_connection_close()\n            self.ws_connection = None\n            self.on_close()",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 67,
                            "end_lineno": 359,
                            "parent": null
                        }
                    ],
                    "added_entities": [
                        {
                            "file_name": "tornado/websocket.py",
                            "type": "method",
                            "name": "WebSocketHandler.check_origin",
                            "content": "class WebSocketHandler(tornado.web.RequestHandler):\n    \"\"\"Subclass this class to create a basic WebSocket handler.\n\n    Override `on_message` to handle incoming messages, and use\n    `write_message` to send messages to the client. You can also\n    override `open` and `on_close` to handle opened and closed\n    connections.\n\n    See http://dev.w3.org/html5/websockets/ for details on the\n    JavaScript interface.  The protocol is specified at\n    http://tools.ietf.org/html/rfc6455.\n\n    Here is an example WebSocket handler that echos back all received messages\n    back to the client::\n\n      class EchoWebSocket(websocket.WebSocketHandler):\n          def open(self):\n              print \"WebSocket opened\"\n\n          def on_message(self, message):\n              self.write_message(u\"You said: \" + message)\n\n          def on_close(self):\n              print \"WebSocket closed\"\n\n    WebSockets are not standard HTTP connections. The \"handshake\" is\n    HTTP, but after the handshake, the protocol is\n    message-based. Consequently, most of the Tornado HTTP facilities\n    are not available in handlers of this type. The only communication\n    methods available to you are `write_message()`, `ping()`, and\n    `close()`. Likewise, your request handler class should implement\n    `open()` method rather than ``get()`` or ``post()``.\n\n    If you map the handler above to ``/websocket`` in your application, you can\n    invoke it in JavaScript with::\n\n      var ws = new WebSocket(\"ws://localhost:8888/websocket\");\n      ws.onopen = function() {\n         ws.send(\"Hello, world\");\n      };\n      ws.onmessage = function (evt) {\n         alert(evt.data);\n      };\n\n    This script pops up an alert box that says \"You said: Hello, world\".\n    \"\"\"\n    def __init__(self, application, request, **kwargs):\n        tornado.web.RequestHandler.__init__(self, application, request,\n                                            **kwargs)\n        self.ws_connection = None\n        self.close_code = None\n        self.close_reason = None\n\n    @tornado.web.asynchronous\n    def get(self, *args, **kwargs):\n        self.open_args = args\n        self.open_kwargs = kwargs\n\n        self.stream = self.request.connection.detach()\n        self.stream.set_close_callback(self.on_connection_close)\n\n        # Upgrade header should be present and should be equal to WebSocket\n        if self.request.headers.get(\"Upgrade\", \"\").lower() != 'websocket':\n            self.stream.write(tornado.escape.utf8(\n                \"HTTP/1.1 400 Bad Request\\r\\n\\r\\n\"\n                \"Can \\\"Upgrade\\\" only to \\\"WebSocket\\\".\"\n            ))\n            self.stream.close()\n            return\n\n        # Connection header should be upgrade. Some proxy servers/load balancers\n        # might mess with it.\n        headers = self.request.headers\n        connection = map(lambda s: s.strip().lower(), headers.get(\"Connection\", \"\").split(\",\"))\n        if 'upgrade' not in connection:\n            self.stream.write(tornado.escape.utf8(\n                \"HTTP/1.1 400 Bad Request\\r\\n\\r\\n\"\n                \"\\\"Connection\\\" must be \\\"Upgrade\\\".\"\n            ))\n            self.stream.close()\n            return\n\n        # Handle WebSocket Origin naming convention differences\n        # The difference between version 8 and 13 is that in 8 the\n        # client sends a \"Sec-Websocket-Origin\" header and in 13 it's\n        # simply \"Origin\".\n        if \"Origin\" in self.request.headers:\n            origin = self.request.headers.get(\"Origin\")\n        else:\n            origin = self.request.headers.get(\"Sec-Websocket-Origin\", None)\n\n\n        # If there was an origin header, check to make sure it matches\n        # according to check_origin. When the origin is None, we assume it\n        # came from a browser and that it can be passed on.\n        if origin is not None and not self.check_origin(origin):\n            self.stream.write(tornado.escape.utf8(\n                \"HTTP/1.1 403 Cross Origin Websockets Disabled\\r\\n\\r\\n\"\n            ))\n            self.stream.close()\n            return\n\n        if self.request.headers.get(\"Sec-WebSocket-Version\") in (\"7\", \"8\", \"13\"):\n            self.ws_connection = WebSocketProtocol13(self)\n            self.ws_connection.accept_connection()\n        elif (self.allow_draft76() and\n              \"Sec-WebSocket-Version\" not in self.request.headers):\n            self.ws_connection = WebSocketProtocol76(self)\n            self.ws_connection.accept_connection()\n        else:\n            self.stream.write(tornado.escape.utf8(\n                \"HTTP/1.1 426 Upgrade Required\\r\\n\"\n                \"Sec-WebSocket-Version: 8\\r\\n\\r\\n\"))\n            self.stream.close()\n\n\n    def write_message(self, message, binary=False):\n        \"\"\"Sends the given message to the client of this Web Socket.\n\n        The message may be either a string or a dict (which will be\n        encoded as json).  If the ``binary`` argument is false, the\n        message will be sent as utf8; in binary mode any byte string\n        is allowed.\n\n        If the connection is already closed, raises `WebSocketClosedError`.\n\n        .. versionchanged:: 3.2\n           `WebSocketClosedError` was added (previously a closed connection\n           would raise an `AttributeError`)\n        \"\"\"\n        if self.ws_connection is None:\n            raise WebSocketClosedError()\n        if isinstance(message, dict):\n            message = tornado.escape.json_encode(message)\n        self.ws_connection.write_message(message, binary=binary)\n\n    def select_subprotocol(self, subprotocols):\n        \"\"\"Invoked when a new WebSocket requests specific subprotocols.\n\n        ``subprotocols`` is a list of strings identifying the\n        subprotocols proposed by the client.  This method may be\n        overridden to return one of those strings to select it, or\n        ``None`` to not select a subprotocol.  Failure to select a\n        subprotocol does not automatically abort the connection,\n        although clients may close the connection if none of their\n        proposed subprotocols was selected.\n        \"\"\"\n        return None\n\n    def open(self):\n        \"\"\"Invoked when a new WebSocket is opened.\n\n        The arguments to `open` are extracted from the `tornado.web.URLSpec`\n        regular expression, just like the arguments to\n        `tornado.web.RequestHandler.get`.\n        \"\"\"\n        pass\n\n    def on_message(self, message):\n        \"\"\"Handle incoming messages on the WebSocket\n\n        This method must be overridden.\n        \"\"\"\n        raise NotImplementedError\n\n    def ping(self, data):\n        \"\"\"Send ping frame to the remote end.\"\"\"\n        if self.ws_connection is None:\n            raise WebSocketClosedError()\n        self.ws_connection.write_ping(data)\n\n    def on_pong(self, data):\n        \"\"\"Invoked when the response to a ping frame is received.\"\"\"\n        pass\n\n    def on_close(self):\n        \"\"\"Invoked when the WebSocket is closed.\n\n        If the connection was closed cleanly and a status code or reason\n        phrase was supplied, these values will be available as the attributes\n        ``self.close_code`` and ``self.close_reason``.\n\n        .. versionchanged:: 3.3\n\n           Added ``close_code`` and ``close_reason`` attributes.\n        \"\"\"\n        pass\n\n    def close(self, code=None, reason=None):\n        \"\"\"Closes this Web Socket.\n\n        Once the close handshake is successful the socket will be closed.\n\n        ``code`` may be a numeric status code, taken from the values\n        defined in `RFC 6455 section 7.4.1\n        <https://tools.ietf.org/html/rfc6455#section-7.4.1>`_.\n        ``reason`` may be a textual message about why the connection is\n        closing.  These values are made available to the client, but are\n        not otherwise interpreted by the websocket protocol.\n\n        The ``code`` and ``reason`` arguments are ignored in the \"draft76\"\n        protocol version.\n\n        .. versionchanged:: 3.3\n\n           Added the ``code`` and ``reason`` arguments.\n        \"\"\"\n        if self.ws_connection:\n            self.ws_connection.close(code, reason)\n            self.ws_connection = None\n\n    def check_origin(self, origin):\n        \"\"\"Override to enable support for allowing alternate origins.\n        \n        By default, this checks to see that the host matches the origin\n        provided.\n\n        This is a security protection against cross site scripting attacks on\n        browsers, since WebSockets don't have CORS headers.\n        \"\"\"\n\n        # Due to how stdlib's urlparse is implemented, urls without a //\n        # are interpreted to be paths (resulting in netloc being None)\n        if(\"//\" not in origin):\n            origin = \"//\" + origin\n        parsed_origin = urlparse(origin)\n        origin = parsed_origin.netloc\n        origin = origin.lower()\n\n        host = self.request.headers.get(\"Host\")\n\n        # Check to see that origin matches host directly, including ports\n        return origin == host\n\n    def allow_draft76(self):\n        \"\"\"Override to enable support for the older \"draft76\" protocol.\n\n        The draft76 version of the websocket protocol is disabled by\n        default due to security concerns, but it can be enabled by\n        overriding this method to return True.\n\n        Connections using the draft76 protocol do not support the\n        ``binary=True`` flag to `write_message`.\n\n        Support for the draft76 protocol is deprecated and will be\n        removed in a future version of Tornado.\n        \"\"\"\n        return False\n\n    def set_nodelay(self, value):\n        \"\"\"Set the no-delay flag for this stream.\n\n        By default, small messages may be delayed and/or combined to minimize\n        the number of packets sent.  This can sometimes cause 200-500ms delays\n        due to the interaction between Nagle's algorithm and TCP delayed\n        ACKs.  To reduce this delay (at the expense of possibly increasing\n        bandwidth usage), call ``self.set_nodelay(True)`` once the websocket\n        connection is established.\n\n        See `.BaseIOStream.set_nodelay` for additional details.\n\n        .. versionadded:: 3.1\n        \"\"\"\n        self.stream.set_nodelay(value)\n\n    def get_websocket_scheme(self):\n        \"\"\"Return the url scheme used for this request, either \"ws\" or \"wss\".\n\n        This is normally decided by HTTPServer, but applications\n        may wish to override this if they are using an SSL proxy\n        that does not provide the X-Scheme header as understood\n        by HTTPServer.\n\n        Note that this is only used by the draft76 protocol.\n        \"\"\"\n        return \"wss\" if self.request.protocol == \"https\" else \"ws\"\n\n    def async_callback(self, callback, *args, **kwargs):\n        \"\"\"Obsolete - catches exceptions from the wrapped function.\n\n        This function is normally unncecessary thanks to\n        `tornado.stack_context`.\n        \"\"\"\n        return self.ws_connection.async_callback(callback, *args, **kwargs)\n\n    def _not_supported(self, *args, **kwargs):\n        raise Exception(\"Method not supported for Web Sockets\")\n\n    def on_connection_close(self):\n        if self.ws_connection:\n            self.ws_connection.on_connection_close()\n            self.ws_connection = None\n            self.on_close()",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 278,
                            "end_lineno": 299,
                            "parent": {
                                "file_name": "tornado/websocket.py",
                                "type": "class",
                                "name": "WebSocketHandler",
                                "content": "class WebSocketHandler(tornado.web.RequestHandler):\n    \"\"\"Subclass this class to create a basic WebSocket handler.\n\n    Override `on_message` to handle incoming messages, and use\n    `write_message` to send messages to the client. You can also\n    override `open` and `on_close` to handle opened and closed\n    connections.\n\n    See http://dev.w3.org/html5/websockets/ for details on the\n    JavaScript interface.  The protocol is specified at\n    http://tools.ietf.org/html/rfc6455.\n\n    Here is an example WebSocket handler that echos back all received messages\n    back to the client::\n\n      class EchoWebSocket(websocket.WebSocketHandler):\n          def open(self):\n              print \"WebSocket opened\"\n\n          def on_message(self, message):\n              self.write_message(u\"You said: \" + message)\n\n          def on_close(self):\n              print \"WebSocket closed\"\n\n    WebSockets are not standard HTTP connections. The \"handshake\" is\n    HTTP, but after the handshake, the protocol is\n    message-based. Consequently, most of the Tornado HTTP facilities\n    are not available in handlers of this type. The only communication\n    methods available to you are `write_message()`, `ping()`, and\n    `close()`. Likewise, your request handler class should implement\n    `open()` method rather than ``get()`` or ``post()``.\n\n    If you map the handler above to ``/websocket`` in your application, you can\n    invoke it in JavaScript with::\n\n      var ws = new WebSocket(\"ws://localhost:8888/websocket\");\n      ws.onopen = function() {\n         ws.send(\"Hello, world\");\n      };\n      ws.onmessage = function (evt) {\n         alert(evt.data);\n      };\n\n    This script pops up an alert box that says \"You said: Hello, world\".\n    \"\"\"\n    def __init__(self, application, request, **kwargs):\n        tornado.web.RequestHandler.__init__(self, application, request,\n                                            **kwargs)\n        self.ws_connection = None\n        self.close_code = None\n        self.close_reason = None\n\n    @tornado.web.asynchronous\n    def get(self, *args, **kwargs):\n        self.open_args = args\n        self.open_kwargs = kwargs\n\n        self.stream = self.request.connection.detach()\n        self.stream.set_close_callback(self.on_connection_close)\n\n        # Upgrade header should be present and should be equal to WebSocket\n        if self.request.headers.get(\"Upgrade\", \"\").lower() != 'websocket':\n            self.stream.write(tornado.escape.utf8(\n                \"HTTP/1.1 400 Bad Request\\r\\n\\r\\n\"\n                \"Can \\\"Upgrade\\\" only to \\\"WebSocket\\\".\"\n            ))\n            self.stream.close()\n            return\n\n        # Connection header should be upgrade. Some proxy servers/load balancers\n        # might mess with it.\n        headers = self.request.headers\n        connection = map(lambda s: s.strip().lower(), headers.get(\"Connection\", \"\").split(\",\"))\n        if 'upgrade' not in connection:\n            self.stream.write(tornado.escape.utf8(\n                \"HTTP/1.1 400 Bad Request\\r\\n\\r\\n\"\n                \"\\\"Connection\\\" must be \\\"Upgrade\\\".\"\n            ))\n            self.stream.close()\n            return\n\n        # Handle WebSocket Origin naming convention differences\n        # The difference between version 8 and 13 is that in 8 the\n        # client sends a \"Sec-Websocket-Origin\" header and in 13 it's\n        # simply \"Origin\".\n        if \"Origin\" in self.request.headers:\n            origin = self.request.headers.get(\"Origin\")\n        else:\n            origin = self.request.headers.get(\"Sec-Websocket-Origin\", None)\n\n\n        # If there was an origin header, check to make sure it matches\n        # according to check_origin. When the origin is None, we assume it\n        # came from a browser and that it can be passed on.\n        if origin is not None and not self.check_origin(origin):\n            self.stream.write(tornado.escape.utf8(\n                \"HTTP/1.1 403 Cross Origin Websockets Disabled\\r\\n\\r\\n\"\n            ))\n            self.stream.close()\n            return\n\n        if self.request.headers.get(\"Sec-WebSocket-Version\") in (\"7\", \"8\", \"13\"):\n            self.ws_connection = WebSocketProtocol13(self)\n            self.ws_connection.accept_connection()\n        elif (self.allow_draft76() and\n              \"Sec-WebSocket-Version\" not in self.request.headers):\n            self.ws_connection = WebSocketProtocol76(self)\n            self.ws_connection.accept_connection()\n        else:\n            self.stream.write(tornado.escape.utf8(\n                \"HTTP/1.1 426 Upgrade Required\\r\\n\"\n                \"Sec-WebSocket-Version: 8\\r\\n\\r\\n\"))\n            self.stream.close()\n\n\n    def write_message(self, message, binary=False):\n        \"\"\"Sends the given message to the client of this Web Socket.\n\n        The message may be either a string or a dict (which will be\n        encoded as json).  If the ``binary`` argument is false, the\n        message will be sent as utf8; in binary mode any byte string\n        is allowed.\n\n        If the connection is already closed, raises `WebSocketClosedError`.\n\n        .. versionchanged:: 3.2\n           `WebSocketClosedError` was added (previously a closed connection\n           would raise an `AttributeError`)\n        \"\"\"\n        if self.ws_connection is None:\n            raise WebSocketClosedError()\n        if isinstance(message, dict):\n            message = tornado.escape.json_encode(message)\n        self.ws_connection.write_message(message, binary=binary)\n\n    def select_subprotocol(self, subprotocols):\n        \"\"\"Invoked when a new WebSocket requests specific subprotocols.\n\n        ``subprotocols`` is a list of strings identifying the\n        subprotocols proposed by the client.  This method may be\n        overridden to return one of those strings to select it, or\n        ``None`` to not select a subprotocol.  Failure to select a\n        subprotocol does not automatically abort the connection,\n        although clients may close the connection if none of their\n        proposed subprotocols was selected.\n        \"\"\"\n        return None\n\n    def open(self):\n        \"\"\"Invoked when a new WebSocket is opened.\n\n        The arguments to `open` are extracted from the `tornado.web.URLSpec`\n        regular expression, just like the arguments to\n        `tornado.web.RequestHandler.get`.\n        \"\"\"\n        pass\n\n    def on_message(self, message):\n        \"\"\"Handle incoming messages on the WebSocket\n\n        This method must be overridden.\n        \"\"\"\n        raise NotImplementedError\n\n    def ping(self, data):\n        \"\"\"Send ping frame to the remote end.\"\"\"\n        if self.ws_connection is None:\n            raise WebSocketClosedError()\n        self.ws_connection.write_ping(data)\n\n    def on_pong(self, data):\n        \"\"\"Invoked when the response to a ping frame is received.\"\"\"\n        pass\n\n    def on_close(self):\n        \"\"\"Invoked when the WebSocket is closed.\n\n        If the connection was closed cleanly and a status code or reason\n        phrase was supplied, these values will be available as the attributes\n        ``self.close_code`` and ``self.close_reason``.\n\n        .. versionchanged:: 3.3\n\n           Added ``close_code`` and ``close_reason`` attributes.\n        \"\"\"\n        pass\n\n    def close(self, code=None, reason=None):\n        \"\"\"Closes this Web Socket.\n\n        Once the close handshake is successful the socket will be closed.\n\n        ``code`` may be a numeric status code, taken from the values\n        defined in `RFC 6455 section 7.4.1\n        <https://tools.ietf.org/html/rfc6455#section-7.4.1>`_.\n        ``reason`` may be a textual message about why the connection is\n        closing.  These values are made available to the client, but are\n        not otherwise interpreted by the websocket protocol.\n\n        The ``code`` and ``reason`` arguments are ignored in the \"draft76\"\n        protocol version.\n\n        .. versionchanged:: 3.3\n\n           Added the ``code`` and ``reason`` arguments.\n        \"\"\"\n        if self.ws_connection:\n            self.ws_connection.close(code, reason)\n            self.ws_connection = None\n\n    def check_origin(self, origin):\n        \"\"\"Override to enable support for allowing alternate origins.\n        \n        By default, this checks to see that the host matches the origin\n        provided.\n\n        This is a security protection against cross site scripting attacks on\n        browsers, since WebSockets don't have CORS headers.\n        \"\"\"\n\n        # Due to how stdlib's urlparse is implemented, urls without a //\n        # are interpreted to be paths (resulting in netloc being None)\n        if(\"//\" not in origin):\n            origin = \"//\" + origin\n        parsed_origin = urlparse(origin)\n        origin = parsed_origin.netloc\n        origin = origin.lower()\n\n        host = self.request.headers.get(\"Host\")\n\n        # Check to see that origin matches host directly, including ports\n        return origin == host\n\n    def allow_draft76(self):\n        \"\"\"Override to enable support for the older \"draft76\" protocol.\n\n        The draft76 version of the websocket protocol is disabled by\n        default due to security concerns, but it can be enabled by\n        overriding this method to return True.\n\n        Connections using the draft76 protocol do not support the\n        ``binary=True`` flag to `write_message`.\n\n        Support for the draft76 protocol is deprecated and will be\n        removed in a future version of Tornado.\n        \"\"\"\n        return False\n\n    def set_nodelay(self, value):\n        \"\"\"Set the no-delay flag for this stream.\n\n        By default, small messages may be delayed and/or combined to minimize\n        the number of packets sent.  This can sometimes cause 200-500ms delays\n        due to the interaction between Nagle's algorithm and TCP delayed\n        ACKs.  To reduce this delay (at the expense of possibly increasing\n        bandwidth usage), call ``self.set_nodelay(True)`` once the websocket\n        connection is established.\n\n        See `.BaseIOStream.set_nodelay` for additional details.\n\n        .. versionadded:: 3.1\n        \"\"\"\n        self.stream.set_nodelay(value)\n\n    def get_websocket_scheme(self):\n        \"\"\"Return the url scheme used for this request, either \"ws\" or \"wss\".\n\n        This is normally decided by HTTPServer, but applications\n        may wish to override this if they are using an SSL proxy\n        that does not provide the X-Scheme header as understood\n        by HTTPServer.\n\n        Note that this is only used by the draft76 protocol.\n        \"\"\"\n        return \"wss\" if self.request.protocol == \"https\" else \"ws\"\n\n    def async_callback(self, callback, *args, **kwargs):\n        \"\"\"Obsolete - catches exceptions from the wrapped function.\n\n        This function is normally unncecessary thanks to\n        `tornado.stack_context`.\n        \"\"\"\n        return self.ws_connection.async_callback(callback, *args, **kwargs)\n\n    def _not_supported(self, *args, **kwargs):\n        raise Exception(\"Method not supported for Web Sockets\")\n\n    def on_connection_close(self):\n        if self.ws_connection:\n            self.ws_connection.on_connection_close()\n            self.ws_connection = None\n            self.on_close()",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 67,
                                "end_lineno": 359,
                                "parent": null
                            }
                        }
                    ],
                    "deleted_entities": []
                }
            ]
        }
    ],
    "old_commit_hash": "cc8dcecef263e2f531a89806262a368ca4a38f90^",
    "new_commit_hash": "cc8dcecef263e2f531a89806262a368ca4a38f90",
    "commit_message": "Merge remote-tracking branch 'rgbkrk/cross_origin' into merge",
    "commit_date": "2014-05-25T20:49:00-04:00",
    "metadata": {}
}
{
    "repo_name": "tornado",
    "new_commit_hash": "cc8dcecef263e2f531a89806262a368ca4a38f90",
    "test_file_codes": [
        "from __future__ import absolute_import, division, print_function, with_statement\n\nimport traceback\n\nfrom tornado.concurrent import Future\nfrom tornado.httpclient import HTTPError, HTTPRequest\nfrom tornado.log import gen_log\nfrom tornado.testing import AsyncHTTPTestCase, gen_test, bind_unused_port, ExpectLog\nfrom tornado.test.util import unittest\nfrom tornado.web import Application, RequestHandler\n\ntry:\n    import tornado.websocket\nexcept ImportError:\n    # The unittest module presents misleading errors on ImportError\n    # (it acts as if websocket_test could not be found, hiding the underlying\n    # error).  If we get an ImportError here (which could happen due to\n    # TORNADO_EXTENSION=1), print some extra information before failing.\n    traceback.print_exc()\n    raise\n\nfrom tornado.websocket import WebSocketHandler, websocket_connect, WebSocketError, _websocket_mask_python\n\ntry:\n    from tornado import speedups\nexcept ImportError:\n    speedups = None\n\n\nclass TestWebSocketHandler(WebSocketHandler):\n    \"\"\"Base class for testing handlers that exposes the on_close event.\n\n    This allows for deterministic cleanup of the associated socket.\n    \"\"\"\n    def initialize(self, close_future):\n        self.close_future = close_future\n\n    def on_close(self):\n        self.close_future.set_result((self.close_code, self.close_reason))\n\n\nclass EchoHandler(TestWebSocketHandler):\n    def on_message(self, message):\n        self.write_message(message, isinstance(message, bytes))\n\n\nclass HeaderHandler(TestWebSocketHandler):\n    def open(self):\n        self.write_message(self.request.headers.get('X-Test', ''))\n\n\nclass NonWebSocketHandler(RequestHandler):\n    def get(self):\n        self.write('ok')\n\n\nclass CloseReasonHandler(TestWebSocketHandler):\n    def open(self):\n        self.close(1001, \"goodbye\")\n\n\nclass WebSocketTest(AsyncHTTPTestCase):\n    def get_app(self):\n        self.close_future = Future()\n        return Application([\n            ('/echo', EchoHandler, dict(close_future=self.close_future)),\n            ('/non_ws', NonWebSocketHandler),\n            ('/header', HeaderHandler, dict(close_future=self.close_future)),\n            ('/close_reason', CloseReasonHandler,\n             dict(close_future=self.close_future)),\n        ])\n\n    @gen_test\n    def test_websocket_gen(self):\n        ws = yield websocket_connect(\n            'ws://localhost:%d/echo' % self.get_http_port(),\n            io_loop=self.io_loop)\n        ws.write_message('hello')\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    def test_websocket_callbacks(self):\n        websocket_connect(\n            'ws://localhost:%d/echo' % self.get_http_port(),\n            io_loop=self.io_loop, callback=self.stop)\n        ws = self.wait().result()\n        ws.write_message('hello')\n        ws.read_message(self.stop)\n        response = self.wait().result()\n        self.assertEqual(response, 'hello')\n        self.close_future.add_done_callback(lambda f: self.stop())\n        ws.close()\n        self.wait()\n\n    @gen_test\n    def test_websocket_http_fail(self):\n        with self.assertRaises(HTTPError) as cm:\n            yield websocket_connect(\n                'ws://localhost:%d/notfound' % self.get_http_port(),\n                io_loop=self.io_loop)\n        self.assertEqual(cm.exception.code, 404)\n\n    @gen_test\n    def test_websocket_http_success(self):\n        with self.assertRaises(WebSocketError):\n            yield websocket_connect(\n                'ws://localhost:%d/non_ws' % self.get_http_port(),\n                io_loop=self.io_loop)\n\n    @gen_test\n    def test_websocket_network_fail(self):\n        sock, port = bind_unused_port()\n        sock.close()\n        with self.assertRaises(IOError):\n            with ExpectLog(gen_log, \".*\"):\n                yield websocket_connect(\n                    'ws://localhost:%d/' % port,\n                    io_loop=self.io_loop,\n                    connect_timeout=3600)\n\n    @gen_test\n    def test_websocket_close_buffered_data(self):\n        ws = yield websocket_connect(\n            'ws://localhost:%d/echo' % self.get_http_port())\n        ws.write_message('hello')\n        ws.write_message('world')\n        ws.stream.close()\n        yield self.close_future\n\n    @gen_test\n    def test_websocket_headers(self):\n        # Ensure that arbitrary headers can be passed through websocket_connect.\n        ws = yield websocket_connect(\n            HTTPRequest('ws://localhost:%d/header' % self.get_http_port(),\n                        headers={'X-Test': 'hello'}))\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    @gen_test\n    def test_server_close_reason(self):\n        ws = yield websocket_connect(\n            'ws://localhost:%d/close_reason' % self.get_http_port())\n        msg = yield ws.read_message()\n        # A message of None means the other side closed the connection.\n        self.assertIs(msg, None)\n        self.assertEqual(ws.close_code, 1001)\n        self.assertEqual(ws.close_reason, \"goodbye\")\n\n    @gen_test\n    def test_client_close_reason(self):\n        ws = yield websocket_connect(\n            'ws://localhost:%d/echo' % self.get_http_port())\n        ws.close(1001, 'goodbye')\n        code, reason = yield self.close_future\n        self.assertEqual(code, 1001)\n        self.assertEqual(reason, 'goodbye')\n\n    @gen_test\n    def test_check_origin_valid(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        headers = {'Origin': 'http://localhost:%d' % port}\n\n        ws = yield websocket_connect(HTTPRequest(url, headers=headers),\n            io_loop=self.io_loop)\n        ws.write_message('hello')\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    @gen_test\n    def test_check_origin_with_path(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        headers = {'Origin': 'http://localhost:%d/something' % port}\n\n        ws = yield websocket_connect(HTTPRequest(url, headers=headers),\n            io_loop=self.io_loop)\n        ws.write_message('hello')\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    @gen_test\n    def test_check_origin_valid2(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        headers = {'Origin': 'localhost:%d' % port}\n\n        ws = yield websocket_connect(HTTPRequest(url, headers=headers),\n            io_loop=self.io_loop)\n        ws.write_message('hello')\n        response = yield ws.read_message()\n        self.assertEqual(response, 'hello')\n        ws.close()\n        yield self.close_future\n\n    @gen_test\n    def test_check_origin_invalid(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        # Host is localhost, which should not be accessible from some other\n        # domain\n        headers = {'Origin': 'http://somewhereelse.com'}\n\n        with self.assertRaises(HTTPError) as cm:\n            yield websocket_connect(HTTPRequest(url, headers=headers),\n                                    io_loop=self.io_loop)\n\n        self.assertEqual(cm.exception.code, 403)\n\n    @gen_test\n    def test_check_origin_invalid2(self):\n        port = self.get_http_port()\n\n        url = 'ws://localhost:%d/echo' % port\n        # subdomains should be invalid by default\n        headers = {'Origin': 'http://subtenant.somewhereelse.com',\n                   'Host': 'subtenant2.somewhereelse.com'}\n\n        with self.assertRaises(HTTPError) as cm:\n            yield websocket_connect(HTTPRequest(url, headers=headers),\n                                    io_loop=self.io_loop)\n\n        self.assertEqual(cm.exception.code, 403)\n\n\nclass MaskFunctionMixin(object):\n    # Subclasses should define self.mask(mask, data)\n    def test_mask(self):\n        self.assertEqual(self.mask(b'abcd', b''), b'')\n        self.assertEqual(self.mask(b'abcd', b'b'), b'\\x03')\n        self.assertEqual(self.mask(b'abcd', b'54321'), b'TVPVP')\n        self.assertEqual(self.mask(b'ZXCV', b'98765432'), b'c`t`olpd')\n        # Include test cases with \\x00 bytes (to ensure that the C\n        # extension isn't depending on null-terminated strings) and\n        # bytes with the high bit set (to smoke out signedness issues).\n        self.assertEqual(self.mask(b'\\x00\\x01\\x02\\x03',\n                                   b'\\xff\\xfb\\xfd\\xfc\\xfe\\xfa'),\n                         b'\\xff\\xfa\\xff\\xff\\xfe\\xfb')\n        self.assertEqual(self.mask(b'\\xff\\xfb\\xfd\\xfc',\n                                   b'\\x00\\x01\\x02\\x03\\x04\\x05'),\n                         b'\\xff\\xfa\\xff\\xff\\xfb\\xfe')\n\n\nclass PythonMaskFunctionTest(MaskFunctionMixin, unittest.TestCase):\n    def mask(self, mask, data):\n        return _websocket_mask_python(mask, data)\n\n\n@unittest.skipIf(speedups is None, \"tornado.speedups module not present\")\nclass CythonMaskFunctionTest(MaskFunctionMixin, unittest.TestCase):\n    def mask(self, mask, data):\n        return speedups.websocket_mask(mask, data)\n",
        "#!/usr/bin/env python\nimport unittest\nimport sys\nimport time\nimport traceback\nimport platform\nimport os\n\n\nclass PytestLikeResult(unittest.TestResult):\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        self.start_time = None\n        # Store (test, outcome, info) for each test:\n        #   outcome ∈ { \"passed\", \"failed\", \"error\", \"skipped\" }\n        #   info can hold the exception or skip reason, etc.\n        self.results = []\n\n    def startTestRun(self):\n        \"\"\"Called once before all tests.\"\"\"\n        self.start_time = time.time()\n        # Print a header similar to pytest\n        print(\"=\" * 29 + \" test session starts \" + \"=\" * 29)\n        # You can customize the platform/versions/paths as you like:\n        print(\n            f\"platform {platform.system().lower()} -- Python {platform.python_version()}\"\n        )\n        print(f\"rootdir: {os.path.abspath(os.curdir)}\")\n\n    def stopTestRun(self):\n        \"\"\"Called once after all tests are done.\"\"\"\n        elapsed = time.time() - self.start_time\n        print()  # blank line after final dot\n\n        # Summarize\n        ntests = len(self.results)\n        print(f\"collected {ntests} items\")\n\n        # Show details of failures/errors\n        failures = [r for r in self.results if r[1] == \"failed\"]\n        errors = [r for r in self.results if r[1] == \"error\"]\n\n        if failures:\n            print(\"\\n\" + \"=\" * 35 + \" FAILURES \" + \"=\" * 35)\n            for test, outcome, err_info in failures:\n                test = test.split(\"::\")\n                if len(test) == 3:\n                    test = f\"{test[1]}.{test[2]}\"\n                else:\n                    test = f\"{test[1]}\"\n                print(f\"__________ {test} __________\")\n                self._print_traceback(err_info)\n        if errors:\n            print(\"\\n\" + \"=\" * 35 + \" ERRORS \" + \"=\" * 37)\n            for test, outcome, err_info in errors:\n                test = test.split(\"::\")\n                if len(test) == 3:\n                    test = f\"{test[1]}.{test[2]}\"\n                else:\n                    test = f\"{test[1]}\"\n                print(f\"__________ {test} __________\")\n                self._print_traceback(err_info)\n\n        # Optional short summary lines for passes/fails/skips\n        print(\"\\n==================== short test summary info ====================\")\n        for test, outcome, info in self.results:\n            if outcome in (\"passed\", \"failed\", \"error\", \"skipped\"):\n                print(f\"{outcome.upper()} {test}\")\n\n        # Final one-line summary: “1 failed, 1 errors, 10 passed in 2.04s”\n        passed_count = sum(1 for r in self.results if r[1] == \"passed\")\n        failed_count = len(failures)\n        error_count = len(errors)\n        skipped_count = sum(1 for r in self.results if r[1] == \"skipped\")\n\n        summary_bits = []\n        if failed_count:\n            summary_bits.append(f\"{failed_count} failed\")\n        if error_count:\n            summary_bits.append(f\"{error_count} error{'s' if error_count != 1 else ''}\")\n        if passed_count:\n            summary_bits.append(f\"{passed_count} passed\")\n        if skipped_count:\n            summary_bits.append(f\"{skipped_count} skipped\")\n\n        summary_str = \", \".join(summary_bits) if summary_bits else \"no tests run\"\n        print(\n            f\"=================== {summary_str} in {elapsed:.2f}s ===================\"\n        )\n\n    def startTest(self, test):\n        \"\"\"Called right before each test method.\"\"\"\n        super().startTest(test)\n        # Print a dot or some indicator\n        print(\".\", end=\"\", flush=True)\n\n    def addSuccess(self, test):\n        super().addSuccess(test)\n        self.results.append((self._test_id(test), \"passed\", None))\n\n    def addFailure(self, test, err):\n        super().addFailure(test, err)\n        self.results.append((self._test_id(test), \"failed\", err))\n\n    def addError(self, test, err):\n        super().addError(test, err)\n        self.results.append((self._test_id(test), \"error\", err))\n\n    def addSkip(self, test, reason):\n        super().addSkip(test, reason)\n        self.results.append((self._test_id(test), \"skipped\", reason))\n\n    def _print_traceback(self, err_info):\n        \"\"\"Helper to print the traceback like pytest does.\"\"\"\n        if isinstance(err_info, tuple) and len(err_info) == 3:\n            exc_type, exc_value, tb = err_info\n            traceback.print_exception(exc_type, exc_value, tb, file=sys.stdout)\n        else:\n            print(str(err_info))\n\n    def _test_id(self, test):\n        try:\n            return f\"{test.__class__.__module__}::{test.__class__.__name__}::{test._testMethodName}\"\n        except AttributeError:\n            # Fallback for _ErrorHolder objects\n            return f\"{test.__class__.__module__}::{test.__class__.__name__}\"\n\n\nclass PytestLikeRunner(unittest.TextTestRunner):\n    \"\"\"A custom TextTestRunner that uses the PytestLikeResult.\"\"\"\n\n    resultclass = PytestLikeResult\n\n    def run(self, test):\n        result = self._makeResult()\n        # Overriding run to ensure we call startTestRun/stopTestRun\n        result.startTestRun()\n        test(result)\n        result.stopTestRun()\n        return result\n\n    def tearDown(self):\n        # Reset signal handlers\n        from twisted.internet import reactor\n\n        reactor.removeAll()\n        reactor.stop()\n        super().tearDown()\n\n\ndef main():\n    loader = unittest.TestLoader()\n    suite = loader.discover(\".\", pattern=\"test_*.py\")  # discover tests in r2e_tests/\n    runner = PytestLikeRunner(verbosity=0)\n    result = runner.run(suite)\n    # Exit with code 0 if all tests passed/skipped, 1 if there were fails/errors\n    sys.exit(not result.wasSuccessful())\n\n\nif __name__ == \"__main__\":\n    main()\n"
    ],
    "test_file_names": [
        "test_1.py",
        "tornado_unittest_runner.py"
    ],
    "setup_res_code": 0,
    "setup_res_stdout": "",
    "setup_res_stderr": "Using CPython 3.9.21\nCreating virtual environment at: .venv\nActivate with: source .venv/bin/activate\nResolved 2 packages in 813ms\nPrepared 1 package in 1.04s\nInstalled 2 packages in 1ms\n + certifi==2024.12.14\n + tornado==3.3.dev1 (from file:///home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_cc8dcecef263e2f531a89806262a368ca4a38f90)\nResolved 29 packages in 13ms\nInstalled 29 packages in 133ms\n + attrs==24.3.0\n + automat==24.8.1\n + cachetools==5.5.0\n + cffi==1.17.1\n + chardet==5.2.0\n + colorama==0.4.6\n + constantly==23.10.4\n + distlib==0.3.9\n + exceptiongroup==1.2.2\n + filelock==3.16.1\n + hyperlink==21.0.0\n + idna==3.10\n + incremental==24.7.2\n + iniconfig==2.0.0\n + packaging==24.2\n + platformdirs==4.3.6\n + pluggy==1.5.0\n + pycares==4.5.0\n + pycparser==2.22\n + pycurl==7.45.4\n + pyproject-api==1.8.0\n + pytest==8.3.4\n + setuptools==75.6.0\n + tomli==2.2.1\n + tox==4.23.2\n + twisted==24.11.0\n + typing-extensions==4.12.2\n + virtualenv==20.28.0\n + zope-interface==7.2\n",
    "new_commit_res_code": 0,
    "new_commit_res_stdout": "============================= test session starts =============================\nplatform linux -- Python 3.9.21\nrootdir: /home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_cc8dcecef263e2f531a89806262a368ca4a38f90\n................\ncollected 16 items\n\n==================== short test summary info ====================\nPASSED r2e_tests.test_1::CythonMaskFunctionTest::test_mask\nPASSED r2e_tests.test_1::PythonMaskFunctionTest::test_mask\nPASSED r2e_tests.test_1::WebSocketTest::test_check_origin_invalid\nPASSED r2e_tests.test_1::WebSocketTest::test_check_origin_invalid2\nPASSED r2e_tests.test_1::WebSocketTest::test_check_origin_valid\nPASSED r2e_tests.test_1::WebSocketTest::test_check_origin_valid2\nPASSED r2e_tests.test_1::WebSocketTest::test_check_origin_with_path\nPASSED r2e_tests.test_1::WebSocketTest::test_client_close_reason\nPASSED r2e_tests.test_1::WebSocketTest::test_server_close_reason\nPASSED r2e_tests.test_1::WebSocketTest::test_websocket_callbacks\nPASSED r2e_tests.test_1::WebSocketTest::test_websocket_close_buffered_data\nPASSED r2e_tests.test_1::WebSocketTest::test_websocket_gen\nPASSED r2e_tests.test_1::WebSocketTest::test_websocket_headers\nPASSED r2e_tests.test_1::WebSocketTest::test_websocket_http_fail\nPASSED r2e_tests.test_1::WebSocketTest::test_websocket_http_success\nPASSED r2e_tests.test_1::WebSocketTest::test_websocket_network_fail\n=================== 16 passed in 0.02s ===================\n",
    "new_commit_res_stderr": "WARNING:tornado.access:404 GET /notfound (127.0.0.1) 0.16ms\n",
    "old_commit_res_code": 1,
    "old_commit_res_stdout": "============================= test session starts =============================\nplatform linux -- Python 3.9.21\nrootdir: /home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_cc8dcecef263e2f531a89806262a368ca4a38f90\n................\ncollected 16 items\n\n=================================== FAILURES ===================================\n__________ WebSocketTest.test_check_origin_invalid __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_cc8dcecef263e2f531a89806262a368ca4a38f90/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_cc8dcecef263e2f531a89806262a368ca4a38f90/tornado/testing.py\", line 492, in post_coroutine\n    return self.io_loop.run_sync(\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_cc8dcecef263e2f531a89806262a368ca4a38f90/tornado/ioloop.py\", line 418, in run_sync\n    return future_cell[0].result()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_cc8dcecef263e2f531a89806262a368ca4a38f90/tornado/concurrent.py\", line 109, in result\n    raise_exc_info(self._exc_info)\n  File \"<string>\", line 3, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_cc8dcecef263e2f531a89806262a368ca4a38f90/tornado/gen.py\", line 653, in run\n    yielded = self.gen.send(value)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_cc8dcecef263e2f531a89806262a368ca4a38f90/r2e_tests/test_1.py\", line 217, in test_check_origin_invalid\n    yield websocket_connect(HTTPRequest(url, headers=headers),\nAssertionError: HTTPError not raised\n__________ WebSocketTest.test_check_origin_invalid2 __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_cc8dcecef263e2f531a89806262a368ca4a38f90/tornado/testing.py\", line 118, in __call__\n    result = self.orig_method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_cc8dcecef263e2f531a89806262a368ca4a38f90/tornado/testing.py\", line 492, in post_coroutine\n    return self.io_loop.run_sync(\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_cc8dcecef263e2f531a89806262a368ca4a38f90/tornado/ioloop.py\", line 418, in run_sync\n    return future_cell[0].result()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_cc8dcecef263e2f531a89806262a368ca4a38f90/tornado/concurrent.py\", line 109, in result\n    raise_exc_info(self._exc_info)\n  File \"<string>\", line 3, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_cc8dcecef263e2f531a89806262a368ca4a38f90/tornado/gen.py\", line 653, in run\n    yielded = self.gen.send(value)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_cc8dcecef263e2f531a89806262a368ca4a38f90/r2e_tests/test_1.py\", line 232, in test_check_origin_invalid2\n    yield websocket_connect(HTTPRequest(url, headers=headers),\nAssertionError: HTTPError not raised\n\n==================== short test summary info ====================\nPASSED r2e_tests.test_1::CythonMaskFunctionTest::test_mask\nPASSED r2e_tests.test_1::PythonMaskFunctionTest::test_mask\nFAILED r2e_tests.test_1::WebSocketTest::test_check_origin_invalid\nFAILED r2e_tests.test_1::WebSocketTest::test_check_origin_invalid2\nPASSED r2e_tests.test_1::WebSocketTest::test_check_origin_valid\nPASSED r2e_tests.test_1::WebSocketTest::test_check_origin_valid2\nPASSED r2e_tests.test_1::WebSocketTest::test_check_origin_with_path\nPASSED r2e_tests.test_1::WebSocketTest::test_client_close_reason\nPASSED r2e_tests.test_1::WebSocketTest::test_server_close_reason\nPASSED r2e_tests.test_1::WebSocketTest::test_websocket_callbacks\nPASSED r2e_tests.test_1::WebSocketTest::test_websocket_close_buffered_data\nPASSED r2e_tests.test_1::WebSocketTest::test_websocket_gen\nPASSED r2e_tests.test_1::WebSocketTest::test_websocket_headers\nPASSED r2e_tests.test_1::WebSocketTest::test_websocket_http_fail\nPASSED r2e_tests.test_1::WebSocketTest::test_websocket_http_success\nPASSED r2e_tests.test_1::WebSocketTest::test_websocket_network_fail\n=================== 2 failed, 14 passed in 0.02s ===================\n",
    "old_commit_res_stderr": "WARNING:tornado.access:404 GET /notfound (127.0.0.1) 0.17ms\n"
}
docs/overview.rst tornado/test/websocket_test.py tornado/websocket.py
We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[ISSUE]

**WebSocket Server Accepts Connections with Invalid Origin Headers**

**Description**

When a client attempts to establish a WebSocket connection with an invalid `Origin` header, the server does not reject the connection as expected. This behavior allows unauthorized cross-origin WebSocket connections, potentially leading to security vulnerabilities.

**Example Code**

```python
headers = {'Origin': 'http://somewhereelse.com'}
ws = websocket_connect(HTTPRequest('ws://localhost:PORT/echo', headers=headers))
# Expected to receive an HTTP 403 error, but the connection is accepted instead.
```

**Expected Behavior**

The server should reject WebSocket connections that include invalid `Origin` headers by responding with an HTTP 403 status code. This ensures that only authorized origins can establish WebSocket connections, enforcing proper cross-origin restrictions.

**Actual Behavior**

Connections with invalid `Origin` headers are accepted without raising an error, bypassing the intended security checks and allowing unauthorized cross-origin access.

[/ISSUE]
--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.

--- BEGIN FILE ---
```
### tornado/websocket.py
"""Implementation of the WebSocket protocol.

`WebSockets <http://dev.w3.org/html5/websockets/>`_ allow for bidirectional
communication between the browser and server.

.. warning::

   The WebSocket protocol was recently finalized as `RFC 6455
   <http://tools.ietf.org/html/rfc6455>`_ and is not yet supported in
   all browsers.  Refer to http://caniuse.com/websockets for details
   on compatibility.  In addition, during development the protocol
   went through several incompatible versions, and some browsers only
   support older versions.  By default this module only supports the
   latest version of the protocol, but optional support for an older
   version (known as "draft 76" or "hixie-76") can be enabled by
   overriding `WebSocketHandler.allow_draft76` (see that method's
   documentation for caveats).
"""

from __future__ import absolute_import, division, print_function, with_statement
# Author: Jacob Kristhammar, 2010

import array
import base64
import collections
import functools
import hashlib
import os
import struct
import time
import tornado.escape
import tornado.web

from tornado.concurrent import TracebackFuture
from tornado.escape import utf8, native_str, to_unicode
from tornado import httpclient, httputil
from tornado.ioloop import IOLoop
from tornado.iostream import StreamClosedError
from tornado.log import gen_log, app_log
from tornado import simple_httpclient
from tornado.tcpclient import TCPClient
from tornado.util import bytes_type, unicode_type

try:
    xrange  # py2
except NameError:
    xrange = range  # py3


class WebSocketError(Exception):
    pass


class WebSocketClosedError(WebSocketError):
    """Raised by operations on a closed connection.

    .. versionadded:: 3.2
    """
    pass


class WebSocketHandler(tornado.web.RequestHandler):
    """Subclass this class to create a basic WebSocket handler.

    Override `on_message` to handle incoming messages, and use
    `write_message` to send messages to the client. You can also
    override `open` and `on_close` to handle opened and closed
    connections.

    See http://dev.w3.org/html5/websockets/ for details on the
    JavaScript interface.  The protocol is specified at
    http://tools.ietf.org/html/rfc6455.

    Here is an example WebSocket handler that echos back all received messages
    back to the client::

      class EchoWebSocket(websocket.WebSocketHandler):
          def open(self):
              print "WebSocket opened"

          def on_message(self, message):
              self.write_message(u"You said: " + message)

          def on_close(self):
              print "WebSocket closed"

    WebSockets are not standard HTTP connections. The "handshake" is
    HTTP, but after the handshake, the protocol is
    message-based. Consequently, most of the Tornado HTTP facilities
    are not available in handlers of this type. The only communication
    methods available to you are `write_message()`, `ping()`, and
    `close()`. Likewise, your request handler class should implement
    `open()` method rather than ``get()`` or ``post()``.

    If you map the handler above to ``/websocket`` in your application, you can
    invoke it in JavaScript with::

      var ws = new WebSocket("ws://localhost:8888/websocket");
      ws.onopen = function() {
         ws.send("Hello, world");
      };
      ws.onmessage = function (evt) {
         alert(evt.data);
      };

    This script pops up an alert box that says "You said: Hello, world".
    """
    def __init__(self, application, request, **kwargs):
        tornado.web.RequestHandler.__init__(self, application, request,
                                            **kwargs)
        self.ws_connection = None
        self.close_code = None
        self.close_reason = None

    @tornado.web.asynchronous
    def get(self, *args, **kwargs):
        self.open_args = args
        self.open_kwargs = kwargs

        self.stream = self.request.connection.detach()
        self.stream.set_close_callback(self.on_connection_close)

        # Upgrade header should be present and should be equal to WebSocket
        if self.request.headers.get("Upgrade", "").lower() != 'websocket':
            self.stream.write(tornado.escape.utf8(
                "HTTP/1.1 400 Bad Request\r\n\r\n"
                "Can \"Upgrade\" only to \"WebSocket\"."
            ))
            self.stream.close()
            return

        # Connection header should be upgrade. Some proxy servers/load balancers
        # might mess with it.
        headers = self.request.headers
        connection = map(lambda s: s.strip().lower(), headers.get("Connection", "").split(","))
        if 'upgrade' not in connection:
            self.stream.write(tornado.escape.utf8(
                "HTTP/1.1 400 Bad Request\r\n\r\n"
                "\"Connection\" must be \"Upgrade\"."
            ))
            self.stream.close()
            return

        # The difference between version 8 and 13 is that in 8 the
        # client sends a "Sec-Websocket-Origin" header and in 13 it's
        # simply "Origin".
        if self.request.headers.get("Sec-WebSocket-Version") in ("7", "8", "13"):
            self.ws_connection = WebSocketProtocol13(self)
            self.ws_connection.accept_connection()
        elif (self.allow_draft76() and
              "Sec-WebSocket-Version" not in self.request.headers):
            self.ws_connection = WebSocketProtocol76(self)
            self.ws_connection.accept_connection()
        else:
            self.stream.write(tornado.escape.utf8(
                "HTTP/1.1 426 Upgrade Required\r\n"
                "Sec-WebSocket-Version: 8\r\n\r\n"))
            self.stream.close()

    def write_message(self, message, binary=False):
        """Sends the given message to the client of this Web Socket.

        The message may be either a string or a dict (which will be
        encoded as json).  If the ``binary`` argument is false, the
        message will be sent as utf8; in binary mode any byte string
        is allowed.

        If the connection is already closed, raises `WebSocketClosedError`.

        .. versionchanged:: 3.2
           `WebSocketClosedError` was added (previously a closed connection
           would raise an `AttributeError`)
        """
        if self.ws_connection is None:
            raise WebSocketClosedError()
        if isinstance(message, dict):
            message = tornado.escape.json_encode(message)
        self.ws_connection.write_message(message, binary=binary)

    def select_subprotocol(self, subprotocols):
        """Invoked when a new WebSocket requests specific subprotocols.

        ``subprotocols`` is a list of strings identifying the
        subprotocols proposed by the client.  This method may be
        overridden to return one of those strings to select it, or
        ``None`` to not select a subprotocol.  Failure to select a
        subprotocol does not automatically abort the connection,
        although clients may close the connection if none of their
        proposed subprotocols was selected.
        """
        return None

    def open(self):
        """Invoked when a new WebSocket is opened.

        The arguments to `open` are extracted from the `tornado.web.URLSpec`
        regular expression, just like the arguments to
        `tornado.web.RequestHandler.get`.
        """
        pass

    def on_message(self, message):
        """Handle incoming messages on the WebSocket

        This method must be overridden.
        """
        raise NotImplementedError

    def ping(self, data):
        """Send ping frame to the remote end."""
        if self.ws_connection is None:
            raise WebSocketClosedError()
        self.ws_connection.write_ping(data)

    def on_pong(self, data):
        """Invoked when the response to a ping frame is received."""
        pass

    def on_close(self):
        """Invoked when the WebSocket is closed.

        If the connection was closed cleanly and a status code or reason
        phrase was supplied, these values will be available as the attributes
        ``self.close_code`` and ``self.close_reason``.

        .. versionchanged:: 3.3

           Added ``close_code`` and ``close_reason`` attributes.
        """
        pass

    def close(self, code=None, reason=None):
        """Closes this Web Socket.

        Once the close handshake is successful the socket will be closed.

        ``code`` may be a numeric status code, taken from the values
        defined in `RFC 6455 section 7.4.1
        <https://tools.ietf.org/html/rfc6455#section-7.4.1>`_.
        ``reason`` may be a textual message about why the connection is
        closing.  These values are made available to the client, but are
        not otherwise interpreted by the websocket protocol.

        The ``code`` and ``reason`` arguments are ignored in the "draft76"
        protocol version.

        .. versionchanged:: 3.3

           Added the ``code`` and ``reason`` arguments.
        """
        if self.ws_connection:
            self.ws_connection.close(code, reason)
            self.ws_connection = None

    def allow_draft76(self):
        """Override to enable support for the older "draft76" protocol.

        The draft76 version of the websocket protocol is disabled by
        default due to security concerns, but it can be enabled by
        overriding this method to return True.

        Connections using the draft76 protocol do not support the
        ``binary=True`` flag to `write_message`.

        Support for the draft76 protocol is deprecated and will be
        removed in a future version of Tornado.
        """
        return False

    def set_nodelay(self, value):
        """Set the no-delay flag for this stream.

        By default, small messages may be delayed and/or combined to minimize
        the number of packets sent.  This can sometimes cause 200-500ms delays
        due to the interaction between Nagle's algorithm and TCP delayed
        ACKs.  To reduce this delay (at the expense of possibly increasing
        bandwidth usage), call ``self.set_nodelay(True)`` once the websocket
        connection is established.

        See `.BaseIOStream.set_nodelay` for additional details.

        .. versionadded:: 3.1
        """
        self.stream.set_nodelay(value)

    def get_websocket_scheme(self):
        """Return the url scheme used for this request, either "ws" or "wss".

        This is normally decided by HTTPServer, but applications
        may wish to override this if they are using an SSL proxy
        that does not provide the X-Scheme header as understood
        by HTTPServer.

        Note that this is only used by the draft76 protocol.
        """
        return "wss" if self.request.protocol == "https" else "ws"

    def async_callback(self, callback, *args, **kwargs):
        """Obsolete - catches exceptions from the wrapped function.

        This function is normally unncecessary thanks to
        `tornado.stack_context`.
        """
        return self.ws_connection.async_callback(callback, *args, **kwargs)

    def _not_supported(self, *args, **kwargs):
        raise Exception("Method not supported for Web Sockets")

    def on_connection_close(self):
        if self.ws_connection:
            self.ws_connection.on_connection_close()
            self.ws_connection = None
            self.on_close()


for method in ["write", "redirect", "set_header", "send_error", "set_cookie",
               "set_status", "flush", "finish"]:
    setattr(WebSocketHandler, method, WebSocketHandler._not_supported)


class WebSocketProtocol(object):
    """Base class for WebSocket protocol versions.
    """
    def __init__(self, handler):
        self.handler = handler
        self.request = handler.request
        self.stream = handler.stream
        self.client_terminated = False
        self.server_terminated = False

    def async_callback(self, callback, *args, **kwargs):
        """Wrap callbacks with this if they are used on asynchronous requests.

        Catches exceptions properly and closes this WebSocket if an exception
        is uncaught.
        """
        if args or kwargs:
            callback = functools.partial(callback, *args, **kwargs)

        def wrapper(*args, **kwargs):
            try:
                return callback(*args, **kwargs)
            except Exception:
                app_log.error("Uncaught exception in %s",
                              self.request.path, exc_info=True)
                self._abort()
        return wrapper

    def on_connection_close(self):
        self._abort()

    def _abort(self):
        """Instantly aborts the WebSocket connection by closing the socket"""
        self.client_terminated = True
        self.server_terminated = True
        self.stream.close()  # forcibly tear down the connection
        self.close()  # let the subclass cleanup


class WebSocketProtocol76(WebSocketProtocol):
    """Implementation of the WebSockets protocol, version hixie-76.

    This class provides basic functionality to process WebSockets requests as
    specified in
    http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-76
    """
    def __init__(self, handler):
        WebSocketProtocol.__init__(self, handler)
        self.challenge = None
        self._waiting = None

    def accept_connection(self):
        try:
            self._handle_websocket_headers()
        except ValueError:
            gen_log.debug("Malformed WebSocket request received")
            self._abort()
            return

        scheme = self.handler.get_websocket_scheme()

        # draft76 only allows a single subprotocol
        subprotocol_header = ''
        subprotocol = self.request.headers.get("Sec-WebSocket-Protocol", None)
        if subprotocol:
            selected = self.handler.select_subprotocol([subprotocol])
            if selected:
                assert selected == subprotocol
                subprotocol_header = "Sec-WebSocket-Protocol: %s\r\n" % selected

        # Write the initial headers before attempting to read the challenge.
        # This is necessary when using proxies (such as HAProxy), which
        # need to see the Upgrade headers before passing through the
        # non-HTTP traffic that follows.
        self.stream.write(tornado.escape.utf8(
            "HTTP/1.1 101 WebSocket Protocol Handshake\r\n"
            "Upgrade: WebSocket\r\n"
            "Connection: Upgrade\r\n"
            "Server: TornadoServer/%(version)s\r\n"
            "Sec-WebSocket-Origin: %(origin)s\r\n"
            "Sec-WebSocket-Location: %(scheme)s://%(host)s%(uri)s\r\n"
            "%(subprotocol)s"
            "\r\n" % (dict(
                version=tornado.version,
                origin=self.request.headers["Origin"],
                scheme=scheme,
                host=self.request.host,
                uri=self.request.uri,
                subprotocol=subprotocol_header))))
        self.stream.read_bytes(8, self._handle_challenge)

    def challenge_response(self, challenge):
        """Generates the challenge response that's needed in the handshake

        The challenge parameter should be the raw bytes as sent from the
        client.
        """
        key_1 = self.request.headers.get("Sec-Websocket-Key1")
        key_2 = self.request.headers.get("Sec-Websocket-Key2")
        try:
            part_1 = self._calculate_part(key_1)
            part_2 = self._calculate_part(key_2)
        except ValueError:
            raise ValueError("Invalid Keys/Challenge")
        return self._generate_challenge_response(part_1, part_2, challenge)

    def _handle_challenge(self, challenge):
        try:
            challenge_response = self.challenge_response(challenge)
        except ValueError:
            gen_log.debug("Malformed key data in WebSocket request")
            self._abort()
            return
        self._write_response(challenge_response)

    def _write_response(self, challenge):
        self.stream.write(challenge)
        self.async_callback(self.handler.open)(*self.handler.open_args, **self.handler.open_kwargs)
        self._receive_message()

    def _handle_websocket_headers(self):
        """Verifies all invariant- and required headers

        If a header is missing or have an incorrect value ValueError will be
        raised
        """
        fields = ("Origin", "Host", "Sec-Websocket-Key1",
                  "Sec-Websocket-Key2")
        if not all(map(lambda f: self.request.headers.get(f), fields)):
            raise ValueError("Missing/Invalid WebSocket headers")

    def _calculate_part(self, key):
        """Processes the key headers and calculates their key value.

        Raises ValueError when feed invalid key."""
        # pyflakes complains about variable reuse if both of these lines use 'c'
        number = int(''.join(c for c in key if c.isdigit()))
        spaces = len([c2 for c2 in key if c2.isspace()])
        try:
            key_number = number // spaces
        except (ValueError, ZeroDivisionError):
            raise ValueError
        return struct.pack(">I", key_number)

    def _generate_challenge_response(self, part_1, part_2, part_3):
        m = hashlib.md5()
        m.update(part_1)
        m.update(part_2)
        m.update(part_3)
        return m.digest()

    def _receive_message(self):
        self.stream.read_bytes(1, self._on_frame_type)

    def _on_frame_type(self, byte):
        frame_type = ord(byte)
        if frame_type == 0x00:
            self.stream.read_until(b"\xff", self._on_end_delimiter)
        elif frame_type == 0xff:
            self.stream.read_bytes(1, self._on_length_indicator)
        else:
            self._abort()

    def _on_end_delimiter(self, frame):
        if not self.client_terminated:
            self.async_callback(self.handler.on_message)(
                frame[:-1].decode("utf-8", "replace"))
        if not self.client_terminated:
            self._receive_message()

    def _on_length_indicator(self, byte):
        if ord(byte) != 0x00:
            self._abort()
            return
        self.client_terminated = True
        self.close()

    def write_message(self, message, binary=False):
        """Sends the given message to the client of this Web Socket."""
        if binary:
            raise ValueError(
                "Binary messages not supported by this version of websockets")
        if isinstance(message, unicode_type):
            message = message.encode("utf-8")
        assert isinstance(message, bytes_type)
        self.stream.write(b"\x00" + message + b"\xff")

    def write_ping(self, data):
        """Send ping frame."""
        raise ValueError("Ping messages not supported by this version of websockets")

    def close(self, code=None, reason=None):
        """Closes the WebSocket connection."""
        if not self.server_terminated:
            if not self.stream.closed():
                self.stream.write("\xff\x00")
            self.server_terminated = True
        if self.client_terminated:
            if self._waiting is not None:
                self.stream.io_loop.remove_timeout(self._waiting)
            self._waiting = None
            self.stream.close()
        elif self._waiting is None:
            self._waiting = self.stream.io_loop.add_timeout(
                time.time() + 5, self._abort)


class WebSocketProtocol13(WebSocketProtocol):
    """Implementation of the WebSocket protocol from RFC 6455.

    This class supports versions 7 and 8 of the protocol in addition to the
    final version 13.
    """
    def __init__(self, handler, mask_outgoing=False):
        WebSocketProtocol.__init__(self, handler)
        self.mask_outgoing = mask_outgoing
        self._final_frame = False
        self._frame_opcode = None
        self._masked_frame = None
        self._frame_mask = None
        self._frame_length = None
        self._fragmented_message_buffer = None
        self._fragmented_message_opcode = None
        self._waiting = None

    def accept_connection(self):
        try:
            self._handle_websocket_headers()
            self._accept_connection()
        except ValueError:
            gen_log.debug("Malformed WebSocket request received", exc_info=True)
            self._abort()
            return

    def _handle_websocket_headers(self):
        """Verifies all invariant- and required headers

        If a header is missing or have an incorrect value ValueError will be
        raised
        """
        fields = ("Host", "Sec-Websocket-Key", "Sec-Websocket-Version")
        if not all(map(lambda f: self.request.headers.get(f), fields)):
            raise ValueError("Missing/Invalid WebSocket headers")

    @staticmethod
    def compute_accept_value(key):
        """Computes the value for the Sec-WebSocket-Accept header,
        given the value for Sec-WebSocket-Key.
        """
        sha1 = hashlib.sha1()
        sha1.update(utf8(key))
        sha1.update(b"258EAFA5-E914-47DA-95CA-C5AB0DC85B11")  # Magic value
        return native_str(base64.b64encode(sha1.digest()))

    def _challenge_response(self):
        return WebSocketProtocol13.compute_accept_value(
            self.request.headers.get("Sec-Websocket-Key"))

    def _accept_connection(self):
        subprotocol_header = ''
        subprotocols = self.request.headers.get("Sec-WebSocket-Protocol", '')
        subprotocols = [s.strip() for s in subprotocols.split(',')]
        if subprotocols:
            selected = self.handler.select_subprotocol(subprotocols)
            if selected:
                assert selected in subprotocols
                subprotocol_header = "Sec-WebSocket-Protocol: %s\r\n" % selected

        self.stream.write(tornado.escape.utf8(
            "HTTP/1.1 101 Switching Protocols\r\n"
            "Upgrade: websocket\r\n"
            "Connection: Upgrade\r\n"
            "Sec-WebSocket-Accept: %s\r\n"
            "%s"
            "\r\n" % (self._challenge_response(), subprotocol_header)))

        self.async_callback(self.handler.open)(*self.handler.open_args, **self.handler.open_kwargs)
        self._receive_frame()

    def _write_frame(self, fin, opcode, data):
        if fin:
            finbit = 0x80
        else:
            finbit = 0
        frame = struct.pack("B", finbit | opcode)
        l = len(data)
        if self.mask_outgoing:
            mask_bit = 0x80
        else:
            mask_bit = 0
        if l < 126:
            frame += struct.pack("B", l | mask_bit)
        elif l <= 0xFFFF:
            frame += struct.pack("!BH", 126 | mask_bit, l)
        else:
            frame += struct.pack("!BQ", 127 | mask_bit, l)
        if self.mask_outgoing:
            mask = os.urandom(4)
            data = mask + _websocket_mask(mask, data)
        frame += data
        self.stream.write(frame)

    def write_message(self, message, binary=False):
        """Sends the given message to the client of this Web Socket."""
        if binary:
            opcode = 0x2
        else:
            opcode = 0x1
        message = tornado.escape.utf8(message)
        assert isinstance(message, bytes_type)
        try:
            self._write_frame(True, opcode, message)
        except StreamClosedError:
            self._abort()

    def write_ping(self, data):
        """Send ping frame."""
        assert isinstance(data, bytes_type)
        self._write_frame(True, 0x9, data)

    def _receive_frame(self):
        try:
            self.stream.read_bytes(2, self._on_frame_start)
        except StreamClosedError:
            self._abort()

    def _on_frame_start(self, data):
        header, payloadlen = struct.unpack("BB", data)
        self._final_frame = header & 0x80
        reserved_bits = header & 0x70
        self._frame_opcode = header & 0xf
        self._frame_opcode_is_control = self._frame_opcode & 0x8
        if reserved_bits:
            # client is using as-yet-undefined extensions; abort
            self._abort()
            return
        self._masked_frame = bool(payloadlen & 0x80)
        payloadlen = payloadlen & 0x7f
        if self._frame_opcode_is_control and payloadlen >= 126:
            # control frames must have payload < 126
            self._abort()
            return
        try:
            if payloadlen < 126:
                self._frame_length = payloadlen
                if self._masked_frame:
                    self.stream.read_bytes(4, self._on_masking_key)
                else:
                    self.stream.read_bytes(self._frame_length, self._on_frame_data)
            elif payloadlen == 126:
                self.stream.read_bytes(2, self._on_frame_length_16)
            elif payloadlen == 127:
                self.stream.read_bytes(8, self._on_frame_length_64)
        except StreamClosedError:
            self._abort()

    def _on_frame_length_16(self, data):
        self._frame_length = struct.unpack("!H", data)[0]
        try:
            if self._masked_frame:
                self.stream.read_bytes(4, self._on_masking_key)
            else:
                self.stream.read_bytes(self._frame_length, self._on_frame_data)
        except StreamClosedError:
            self._abort()

    def _on_frame_length_64(self, data):
        self._frame_length = struct.unpack("!Q", data)[0]
        try:
            if self._masked_frame:
                self.stream.read_bytes(4, self._on_masking_key)
            else:
                self.stream.read_bytes(self._frame_length, self._on_frame_data)
        except StreamClosedError:
            self._abort()

    def _on_masking_key(self, data):
        self._frame_mask = data
        try:
            self.stream.read_bytes(self._frame_length, self._on_masked_frame_data)
        except StreamClosedError:
            self._abort()

    def _on_masked_frame_data(self, data):
        self._on_frame_data(_websocket_mask(self._frame_mask, data))

    def _on_frame_data(self, data):
        if self._frame_opcode_is_control:
            # control frames may be interleaved with a series of fragmented
            # data frames, so control frames must not interact with
            # self._fragmented_*
            if not self._final_frame:
                # control frames must not be fragmented
                self._abort()
                return
            opcode = self._frame_opcode
        elif self._frame_opcode == 0:  # continuation frame
            if self._fragmented_message_buffer is None:
                # nothing to continue
                self._abort()
                return
            self._fragmented_message_buffer += data
            if self._final_frame:
                opcode = self._fragmented_message_opcode
                data = self._fragmented_message_buffer
                self._fragmented_message_buffer = None
        else:  # start of new data message
            if self._fragmented_message_buffer is not None:
                # can't start new message until the old one is finished
                self._abort()
                return
            if self._final_frame:
                opcode = self._frame_opcode
            else:
                self._fragmented_message_opcode = self._frame_opcode
                self._fragmented_message_buffer = data

        if self._final_frame:
            self._handle_message(opcode, data)

        if not self.client_terminated:
            self._receive_frame()

    def _handle_message(self, opcode, data):
        if self.client_terminated:
            return

        if opcode == 0x1:
            # UTF-8 data
            try:
                decoded = data.decode("utf-8")
            except UnicodeDecodeError:
                self._abort()
                return
            self.async_callback(self.handler.on_message)(decoded)
        elif opcode == 0x2:
            # Binary data
            self.async_callback(self.handler.on_message)(data)
        elif opcode == 0x8:
            # Close
            self.client_terminated = True
            if len(data) >= 2:
                self.handler.close_code = struct.unpack('>H', data[:2])[0]
            if len(data) > 2:
                self.handler.close_reason = to_unicode(data[2:])
            self.close()
        elif opcode == 0x9:
            # Ping
            self._write_frame(True, 0xA, data)
        elif opcode == 0xA:
            # Pong
            self.async_callback(self.handler.on_pong)(data)
        else:
            self._abort()

    def close(self, code=None, reason=None):
        """Closes the WebSocket connection."""
        if not self.server_terminated:
            if not self.stream.closed():
                if code is None and reason is not None:
                    code = 1000  # "normal closure" status code
                if code is None:
                    close_data = b''
                else:
                    close_data = struct.pack('>H', code)
                if reason is not None:
                    close_data += utf8(reason)
                self._write_frame(True, 0x8, close_data)
            self.server_terminated = True
        if self.client_terminated:
            if self._waiting is not None:
                self.stream.io_loop.remove_timeout(self._waiting)
                self._waiting = None
            self.stream.close()
        elif self._waiting is None:
            # Give the client a few seconds to complete a clean shutdown,
            # otherwise just close the connection.
            self._waiting = self.stream.io_loop.add_timeout(
                self.stream.io_loop.time() + 5, self._abort)


class WebSocketClientConnection(simple_httpclient._HTTPConnection):
    """WebSocket client connection.

    This class should not be instantiated directly; use the
    `websocket_connect` function instead.
    """
    def __init__(self, io_loop, request):
        self.connect_future = TracebackFuture()
        self.read_future = None
        self.read_queue = collections.deque()
        self.key = base64.b64encode(os.urandom(16))

        scheme, sep, rest = request.url.partition(':')
        scheme = {'ws': 'http', 'wss': 'https'}[scheme]
        request.url = scheme + sep + rest
        request.headers.update({
            'Upgrade': 'websocket',
            'Connection': 'Upgrade',
            'Sec-WebSocket-Key': self.key,
            'Sec-WebSocket-Version': '13',
        })

        self.tcp_client = TCPClient(io_loop=io_loop)
        super(WebSocketClientConnection, self).__init__(
            io_loop, None, request, lambda: None, self._on_http_response,
            104857600, self.tcp_client, 65536)

    def close(self, code=None, reason=None):
        """Closes the websocket connection.

        ``code`` and ``reason`` are documented under
        `WebSocketHandler.close`.

        .. versionadded:: 3.2

        .. versionchanged:: 3.3

           Added the ``code`` and ``reason`` arguments.
        """
        if self.protocol is not None:
            self.protocol.close(code, reason)
            self.protocol = None

    def _on_close(self):
        self.on_message(None)
        self.resolver.close()
        super(WebSocketClientConnection, self)._on_close()

    def _on_http_response(self, response):
        if not self.connect_future.done():
            if response.error:
                self.connect_future.set_exception(response.error)
            else:
                self.connect_future.set_exception(WebSocketError(
                    "Non-websocket response"))

    def headers_received(self, start_line, headers):
        if start_line.code != 101:
            return super(WebSocketClientConnection, self).headers_received(
                start_line, headers)

        self.headers = headers
        assert self.headers['Upgrade'].lower() == 'websocket'
        assert self.headers['Connection'].lower() == 'upgrade'
        accept = WebSocketProtocol13.compute_accept_value(self.key)
        assert self.headers['Sec-Websocket-Accept'] == accept

        self.protocol = WebSocketProtocol13(self, mask_outgoing=True)
        self.protocol._receive_frame()

        if self._timeout is not None:
            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)

    def write_message(self, message, binary=False):
        """Sends a message to the WebSocket server."""
        self.protocol.write_message(message, binary)

    def read_message(self, callback=None):
        """Reads a message from the WebSocket server.

        Returns a future whose result is the message, or None
        if the connection is closed.  If a callback argument
        is given it will be called with the future when it is
        ready.
        """
        assert self.read_future is None
        future = TracebackFuture()
        if self.read_queue:
            future.set_result(self.read_queue.popleft())
        else:
            self.read_future = future
        if callback is not None:
            self.io_loop.add_future(future, callback)
        return future

    def on_message(self, message):
        if self.read_future is not None:
            self.read_future.set_result(message)
            self.read_future = None
        else:
            self.read_queue.append(message)

    def on_pong(self, data):
        pass


def websocket_connect(url, io_loop=None, callback=None, connect_timeout=None):
    """Client-side websocket support.

    Takes a url and returns a Future whose result is a
    `WebSocketClientConnection`.

    .. versionchanged:: 3.2
       Also accepts ``HTTPRequest`` objects in place of urls.
    """
    if io_loop is None:
        io_loop = IOLoop.current()
    if isinstance(url, httpclient.HTTPRequest):
        assert connect_timeout is None
        request = url
        # Copy and convert the headers dict/object (see comments in
        # AsyncHTTPClient.fetch)
        request.headers = httputil.HTTPHeaders(request.headers)
    else:
        request = httpclient.HTTPRequest(url, connect_timeout=connect_timeout)
    request = httpclient._RequestProxy(
        request, httpclient.HTTPRequest._DEFAULTS)
    conn = WebSocketClientConnection(io_loop, request)
    if callback is not None:
        io_loop.add_future(conn.connect_future, callback)
    return conn.connect_future


def _websocket_mask_python(mask, data):
    """Websocket masking function.

    `mask` is a `bytes` object of length 4; `data` is a `bytes` object of any length.
    Returns a `bytes` object of the same length as `data` with the mask applied
    as specified in section 5.3 of RFC 6455.

    This pure-python implementation may be replaced by an optimized version when available.
    """
    mask = array.array("B", mask)
    unmasked = array.array("B", data)
    for i in xrange(len(data)):
        unmasked[i] = unmasked[i] ^ mask[i % 4]
    if hasattr(unmasked, 'tobytes'):
        # tostring was deprecated in py32.  It hasn't been removed,
        # but since we turn on deprecation warnings in our tests
        # we need to use the right one.
        return unmasked.tobytes()
    else:
        return unmasked.tostring()

if (os.environ.get('TORNADO_NO_EXTENSION') or
        os.environ.get('TORNADO_EXTENSION') == '0'):
    # These environment variables exist to make it easier to do performance
    # comparisons; they are not guaranteed to remain supported in the future.
    _websocket_mask = _websocket_mask_python
else:
    try:
        from tornado.speedups import websocket_mask as _websocket_mask
    except ImportError:
        if os.environ.get('TORNADO_EXTENSION') == '1':
            raise
        _websocket_mask = _websocket_mask_python

```
--- END FILE ---

Please first localize the bug based on the issue statement, and then generate *SEARCH/REPLACE* edits to fix the issue.

Every *SEARCH/REPLACE* edit must use this format:
1. The file path
2. The start of search block: <<<<<<< SEARCH
3. A contiguous chunk of lines to search for in the existing source code
4. The dividing line: =======
5. The lines to replace into the source code
6. The end of the replace block: >>>>>>> REPLACE

Here is an example:

```python
### mathweb/flask/app.py
<<<<<<< SEARCH
from flask import Flask
=======
import math
from flask import Flask
>>>>>>> REPLACE
```
</solution>

Please note that the *SEARCH/REPLACE* edit REQUIRES PROPER INDENTATION. If you would like to add the line '        print(x)', you must fully write that out, with all those spaces before the code!
Wrap each *SEARCH/REPLACE* edit in a code block as shown in the example above. If you have multiple *SEARCH/REPLACE* edits, use a separate code block for each one.
[ISSUE]

**WebSocket Server Accepts Connections with Invalid Origin Headers**

**Description**

When a client attempts to establish a WebSocket connection with an invalid `Origin` header, the server does not reject the connection as expected. This behavior allows unauthorized cross-origin WebSocket connections, potentially leading to security vulnerabilities.

**Example Code**

```python
headers = {'Origin': 'http://somewhereelse.com'}
ws = websocket_connect(HTTPRequest('ws://localhost:PORT/echo', headers=headers))
# Expected to receive an HTTP 403 error, but the connection is accepted instead.
```

**Expected Behavior**

The server should reject WebSocket connections that include invalid `Origin` headers by responding with an HTTP 403 status code. This ensures that only authorized origins can establish WebSocket connections, enforcing proper cross-origin restrictions.

**Actual Behavior**

Connections with invalid `Origin` headers are accepted without raising an error, bypassing the intended security checks and allowing unauthorized cross-origin access.

[/ISSUE]
{
    "CythonMaskFunctionTest.test_mask": "PASSED",
    "PythonMaskFunctionTest.test_mask": "PASSED",
    "WebSocketTest.test_check_origin_invalid": "PASSED",
    "WebSocketTest.test_check_origin_invalid2": "PASSED",
    "WebSocketTest.test_check_origin_valid": "PASSED",
    "WebSocketTest.test_check_origin_valid2": "PASSED",
    "WebSocketTest.test_check_origin_with_path": "PASSED",
    "WebSocketTest.test_client_close_reason": "PASSED",
    "WebSocketTest.test_server_close_reason": "PASSED",
    "WebSocketTest.test_websocket_callbacks": "PASSED",
    "WebSocketTest.test_websocket_close_buffered_data": "PASSED",
    "WebSocketTest.test_websocket_gen": "PASSED",
    "WebSocketTest.test_websocket_headers": "PASSED",
    "WebSocketTest.test_websocket_http_fail": "PASSED",
    "WebSocketTest.test_websocket_http_success": "PASSED",
    "WebSocketTest.test_websocket_network_fail": "PASSED"
}
diff --git a/tornado/websocket.py b/tornado/websocket.py
index bfb90d18..d797a0cd 100644
--- a/tornado/websocket.py
+++ b/tornado/websocket.py
@@ -41,6 +41,11 @@ from tornado import simple_httpclient
 from tornado.tcpclient import TCPClient
 from tornado.util import bytes_type, unicode_type
 
+try:
+    from urllib.parse import urlparse # py2
+except ImportError:
+    from urlparse import urlparse # py3
+
 try:
     xrange  # py2
 except NameError:
@@ -141,9 +146,26 @@ class WebSocketHandler(tornado.web.RequestHandler):
             self.stream.close()
             return
 
+        # Handle WebSocket Origin naming convention differences
         # The difference between version 8 and 13 is that in 8 the
         # client sends a "Sec-Websocket-Origin" header and in 13 it's
         # simply "Origin".
+        if "Origin" in self.request.headers:
+            origin = self.request.headers.get("Origin")
+        else:
+            origin = self.request.headers.get("Sec-Websocket-Origin", None)
+
+
+        # If there was an origin header, check to make sure it matches
+        # according to check_origin. When the origin is None, we assume it
+        # came from a browser and that it can be passed on.
+        if origin is not None and not self.check_origin(origin):
+            self.stream.write(tornado.escape.utf8(
+                "HTTP/1.1 403 Cross Origin Websockets Disabled\r\n\r\n"
+            ))
+            self.stream.close()
+            return
+
         if self.request.headers.get("Sec-WebSocket-Version") in ("7", "8", "13"):
             self.ws_connection = WebSocketProtocol13(self)
             self.ws_connection.accept_connection()
@@ -157,6 +179,7 @@ class WebSocketHandler(tornado.web.RequestHandler):
                 "Sec-WebSocket-Version: 8\r\n\r\n"))
             self.stream.close()
 
+
     def write_message(self, message, binary=False):
         """Sends the given message to the client of this Web Socket.
 
@@ -252,6 +275,29 @@ class WebSocketHandler(tornado.web.RequestHandler):
             self.ws_connection.close(code, reason)
             self.ws_connection = None
 
+    def check_origin(self, origin):
+        """Override to enable support for allowing alternate origins.
+        
+        By default, this checks to see that the host matches the origin
+        provided.
+
+        This is a security protection against cross site scripting attacks on
+        browsers, since WebSockets don't have CORS headers.
+        """
+
+        # Due to how stdlib's urlparse is implemented, urls without a //
+        # are interpreted to be paths (resulting in netloc being None)
+        if("//" not in origin):
+            origin = "//" + origin
+        parsed_origin = urlparse(origin)
+        origin = parsed_origin.netloc
+        origin = origin.lower()
+
+        host = self.request.headers.get("Host")
+
+        # Check to see that origin matches host directly, including ports
+        return origin == host
+
     def allow_draft76(self):
         """Override to enable support for the older "draft76" protocol.
 
 

{"tornado/websocket.py": "\"\"\"Implementation of the WebSocket protocol.\n\n`WebSockets <http://dev.w3.org/html5/websockets/>`_ allow for bidirectional\ncommunication between the browser and server.\n\n.. warning::\n\n   The WebSocket protocol was recently finalized as `RFC 6455\n   <http://tools.ietf.org/html/rfc6455>`_ and is not yet supported in\n   all browsers.  Refer to http://caniuse.com/websockets for details\n   on compatibility.  In addition, during development the protocol\n   went through several incompatible versions, and some browsers only\n   support older versions.  By default this module only supports the\n   latest version of the protocol, but optional support for an older\n   version (known as \"draft 76\" or \"hixie-76\") can be enabled by\n   overriding `WebSocketHandler.allow_draft76` (see that method's\n   documentation for caveats).\n\"\"\"\n\nfrom __future__ import absolute_import, division, print_function, with_statement\n# Author: Jacob Kristhammar, 2010\n\nimport array\nimport base64\nimport collections\nimport functools\nimport hashlib\nimport os\nimport struct\nimport time\nimport tornado.escape\nimport tornado.web\n\nfrom tornado.concurrent import TracebackFuture\nfrom tornado.escape import utf8, native_str, to_unicode\nfrom tornado import httpclient, httputil\nfrom tornado.ioloop import IOLoop\nfrom tornado.iostream import StreamClosedError\nfrom tornado.log import gen_log, app_log\nfrom tornado import simple_httpclient\nfrom tornado.tcpclient import TCPClient\nfrom tornado.util import bytes_type, unicode_type\n\ntry:\n    xrange  # py2\nexcept NameError:\n    xrange = range  # py3\n\n\nclass WebSocketError(Exception):\n    pass\n\n\nclass WebSocketClosedError(WebSocketError):\n    \"\"\"Raised by operations on a closed connection.\n\n    .. versionadded:: 3.2\n    \"\"\"\n    pass\n\n\nclass WebSocketHandler(tornado.web.RequestHandler):\n    \"\"\"Subclass this class to create a basic WebSocket handler.\n\n    Override `on_message` to handle incoming messages, and use\n    `write_message` to send messages to the client. You can also\n    override `open` and `on_close` to handle opened and closed\n    connections.\n\n    See http://dev.w3.org/html5/websockets/ for details on the\n    JavaScript interface.  The protocol is specified at\n    http://tools.ietf.org/html/rfc6455.\n\n    Here is an example WebSocket handler that echos back all received messages\n    back to the client::\n\n      class EchoWebSocket(websocket.WebSocketHandler):\n          def open(self):\n              print \"WebSocket opened\"\n\n          def on_message(self, message):\n              self.write_message(u\"You said: \" + message)\n\n          def on_close(self):\n              print \"WebSocket closed\"\n\n    WebSockets are not standard HTTP connections. The \"handshake\" is\n    HTTP, but after the handshake, the protocol is\n    message-based. Consequently, most of the Tornado HTTP facilities\n    are not available in handlers of this type. The only communication\n    methods available to you are `write_message()`, `ping()`, and\n    `close()`. Likewise, your request handler class should implement\n    `open()` method rather than ``get()`` or ``post()``.\n\n    If you map the handler above to ``/websocket`` in your application, you can\n    invoke it in JavaScript with::\n\n      var ws = new WebSocket(\"ws://localhost:8888/websocket\");\n      ws.onopen = function() {\n         ws.send(\"Hello, world\");\n      };\n      ws.onmessage = function (evt) {\n         alert(evt.data);\n      };\n\n    This script pops up an alert box that says \"You said: Hello, world\".\n    \"\"\"\n    def __init__(self, application, request, **kwargs):\n        tornado.web.RequestHandler.__init__(self, application, request,\n                                            **kwargs)\n        self.ws_connection = None\n        self.close_code = None\n        self.close_reason = None\n\n    @tornado.web.asynchronous\n    def get(self, *args, **kwargs):\n        self.open_args = args\n        self.open_kwargs = kwargs\n\n        self.stream = self.request.connection.detach()\n        self.stream.set_close_callback(self.on_connection_close)\n\n        # Upgrade header should be present and should be equal to WebSocket\n        if self.request.headers.get(\"Upgrade\", \"\").lower() != 'websocket':\n            self.stream.write(tornado.escape.utf8(\n                \"HTTP/1.1 400 Bad Request\\r\\n\\r\\n\"\n                \"Can \\\"Upgrade\\\" only to \\\"WebSocket\\\".\"\n            ))\n            self.stream.close()\n            return\n\n        # Connection header should be upgrade. Some proxy servers/load balancers\n        # might mess with it.\n        headers = self.request.headers\n        connection = map(lambda s: s.strip().lower(), headers.get(\"Connection\", \"\").split(\",\"))\n        if 'upgrade' not in connection:\n            self.stream.write(tornado.escape.utf8(\n                \"HTTP/1.1 400 Bad Request\\r\\n\\r\\n\"\n                \"\\\"Connection\\\" must be \\\"Upgrade\\\".\"\n            ))\n            self.stream.close()\n            return\n\n        # The difference between version 8 and 13 is that in 8 the\n        # client sends a \"Sec-Websocket-Origin\" header and in 13 it's\n        # simply \"Origin\".\n        if self.request.headers.get(\"Sec-WebSocket-Version\") in (\"7\", \"8\", \"13\"):\n            self.ws_connection = WebSocketProtocol13(self)\n            self.ws_connection.accept_connection()\n        elif (self.allow_draft76() and\n              \"Sec-WebSocket-Version\" not in self.request.headers):\n            self.ws_connection = WebSocketProtocol76(self)\n            self.ws_connection.accept_connection()\n        else:\n            self.stream.write(tornado.escape.utf8(\n                \"HTTP/1.1 426 Upgrade Required\\r\\n\"\n                \"Sec-WebSocket-Version: 8\\r\\n\\r\\n\"))\n            self.stream.close()\n\n    def write_message(self, message, binary=False):\n        \"\"\"Sends the given message to the client of this Web Socket.\n\n        The message may be either a string or a dict (which will be\n        encoded as json).  If the ``binary`` argument is false, the\n        message will be sent as utf8; in binary mode any byte string\n        is allowed.\n\n        If the connection is already closed, raises `WebSocketClosedError`.\n\n        .. versionchanged:: 3.2\n           `WebSocketClosedError` was added (previously a closed connection\n           would raise an `AttributeError`)\n        \"\"\"\n        if self.ws_connection is None:\n            raise WebSocketClosedError()\n        if isinstance(message, dict):\n            message = tornado.escape.json_encode(message)\n        self.ws_connection.write_message(message, binary=binary)\n\n    def select_subprotocol(self, subprotocols):\n        \"\"\"Invoked when a new WebSocket requests specific subprotocols.\n\n        ``subprotocols`` is a list of strings identifying the\n        subprotocols proposed by the client.  This method may be\n        overridden to return one of those strings to select it, or\n        ``None`` to not select a subprotocol.  Failure to select a\n        subprotocol does not automatically abort the connection,\n        although clients may close the connection if none of their\n        proposed subprotocols was selected.\n        \"\"\"\n        return None\n\n    def open(self):\n        \"\"\"Invoked when a new WebSocket is opened.\n\n        The arguments to `open` are extracted from the `tornado.web.URLSpec`\n        regular expression, just like the arguments to\n        `tornado.web.RequestHandler.get`.\n        \"\"\"\n        pass\n\n    def on_message(self, message):\n        \"\"\"Handle incoming messages on the WebSocket\n\n        This method must be overridden.\n        \"\"\"\n        raise NotImplementedError\n\n    def ping(self, data):\n        \"\"\"Send ping frame to the remote end.\"\"\"\n        if self.ws_connection is None:\n            raise WebSocketClosedError()\n        self.ws_connection.write_ping(data)\n\n    def on_pong(self, data):\n        \"\"\"Invoked when the response to a ping frame is received.\"\"\"\n        pass\n\n    def on_close(self):\n        \"\"\"Invoked when the WebSocket is closed.\n\n        If the connection was closed cleanly and a status code or reason\n        phrase was supplied, these values will be available as the attributes\n        ``self.close_code`` and ``self.close_reason``.\n\n        .. versionchanged:: 3.3\n\n           Added ``close_code`` and ``close_reason`` attributes.\n        \"\"\"\n        pass\n\n    def close(self, code=None, reason=None):\n        \"\"\"Closes this Web Socket.\n\n        Once the close handshake is successful the socket will be closed.\n\n        ``code`` may be a numeric status code, taken from the values\n        defined in `RFC 6455 section 7.4.1\n        <https://tools.ietf.org/html/rfc6455#section-7.4.1>`_.\n        ``reason`` may be a textual message about why the connection is\n        closing.  These values are made available to the client, but are\n        not otherwise interpreted by the websocket protocol.\n\n        The ``code`` and ``reason`` arguments are ignored in the \"draft76\"\n        protocol version.\n\n        .. versionchanged:: 3.3\n\n           Added the ``code`` and ``reason`` arguments.\n        \"\"\"\n        if self.ws_connection:\n            self.ws_connection.close(code, reason)\n            self.ws_connection = None\n\n    def allow_draft76(self):\n        \"\"\"Override to enable support for the older \"draft76\" protocol.\n\n        The draft76 version of the websocket protocol is disabled by\n        default due to security concerns, but it can be enabled by\n        overriding this method to return True.\n\n        Connections using the draft76 protocol do not support the\n        ``binary=True`` flag to `write_message`.\n\n        Support for the draft76 protocol is deprecated and will be\n        removed in a future version of Tornado.\n        \"\"\"\n        return False\n\n    def set_nodelay(self, value):\n        \"\"\"Set the no-delay flag for this stream.\n\n        By default, small messages may be delayed and/or combined to minimize\n        the number of packets sent.  This can sometimes cause 200-500ms delays\n        due to the interaction between Nagle's algorithm and TCP delayed\n        ACKs.  To reduce this delay (at the expense of possibly increasing\n        bandwidth usage), call ``self.set_nodelay(True)`` once the websocket\n        connection is established.\n\n        See `.BaseIOStream.set_nodelay` for additional details.\n\n        .. versionadded:: 3.1\n        \"\"\"\n        self.stream.set_nodelay(value)\n\n    def get_websocket_scheme(self):\n        \"\"\"Return the url scheme used for this request, either \"ws\" or \"wss\".\n\n        This is normally decided by HTTPServer, but applications\n        may wish to override this if they are using an SSL proxy\n        that does not provide the X-Scheme header as understood\n        by HTTPServer.\n\n        Note that this is only used by the draft76 protocol.\n        \"\"\"\n        return \"wss\" if self.request.protocol == \"https\" else \"ws\"\n\n    def async_callback(self, callback, *args, **kwargs):\n        \"\"\"Obsolete - catches exceptions from the wrapped function.\n\n        This function is normally unncecessary thanks to\n        `tornado.stack_context`.\n        \"\"\"\n        return self.ws_connection.async_callback(callback, *args, **kwargs)\n\n    def _not_supported(self, *args, **kwargs):\n        raise Exception(\"Method not supported for Web Sockets\")\n\n    def on_connection_close(self):\n        if self.ws_connection:\n            self.ws_connection.on_connection_close()\n            self.ws_connection = None\n            self.on_close()\n\n\nfor method in [\"write\", \"redirect\", \"set_header\", \"send_error\", \"set_cookie\",\n               \"set_status\", \"flush\", \"finish\"]:\n    setattr(WebSocketHandler, method, WebSocketHandler._not_supported)\n\n\nclass WebSocketProtocol(object):\n    \"\"\"Base class for WebSocket protocol versions.\n    \"\"\"\n    def __init__(self, handler):\n        self.handler = handler\n        self.request = handler.request\n        self.stream = handler.stream\n        self.client_terminated = False\n        self.server_terminated = False\n\n    def async_callback(self, callback, *args, **kwargs):\n        \"\"\"Wrap callbacks with this if they are used on asynchronous requests.\n\n        Catches exceptions properly and closes this WebSocket if an exception\n        is uncaught.\n        \"\"\"\n        if args or kwargs:\n            callback = functools.partial(callback, *args, **kwargs)\n\n        def wrapper(*args, **kwargs):\n            try:\n                return callback(*args, **kwargs)\n            except Exception:\n                app_log.error(\"Uncaught exception in %s\",\n                              self.request.path, exc_info=True)\n                self._abort()\n        return wrapper\n\n    def on_connection_close(self):\n        self._abort()\n\n    def _abort(self):\n        \"\"\"Instantly aborts the WebSocket connection by closing the socket\"\"\"\n        self.client_terminated = True\n        self.server_terminated = True\n        self.stream.close()  # forcibly tear down the connection\n        self.close()  # let the subclass cleanup\n\n\nclass WebSocketProtocol76(WebSocketProtocol):\n    \"\"\"Implementation of the WebSockets protocol, version hixie-76.\n\n    This class provides basic functionality to process WebSockets requests as\n    specified in\n    http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-76\n    \"\"\"\n    def __init__(self, handler):\n        WebSocketProtocol.__init__(self, handler)\n        self.challenge = None\n        self._waiting = None\n\n    def accept_connection(self):\n        try:\n            self._handle_websocket_headers()\n        except ValueError:\n            gen_log.debug(\"Malformed WebSocket request received\")\n            self._abort()\n            return\n\n        scheme = self.handler.get_websocket_scheme()\n\n        # draft76 only allows a single subprotocol\n        subprotocol_header = ''\n        subprotocol = self.request.headers.get(\"Sec-WebSocket-Protocol\", None)\n        if subprotocol:\n            selected = self.handler.select_subprotocol([subprotocol])\n            if selected:\n                assert selected == subprotocol\n                subprotocol_header = \"Sec-WebSocket-Protocol: %s\\r\\n\" % selected\n\n        # Write the initial headers before attempting to read the challenge.\n        # This is necessary when using proxies (such as HAProxy), which\n        # need to see the Upgrade headers before passing through the\n        # non-HTTP traffic that follows.\n        self.stream.write(tornado.escape.utf8(\n            \"HTTP/1.1 101 WebSocket Protocol Handshake\\r\\n\"\n            \"Upgrade: WebSocket\\r\\n\"\n            \"Connection: Upgrade\\r\\n\"\n            \"Server: TornadoServer/%(version)s\\r\\n\"\n            \"Sec-WebSocket-Origin: %(origin)s\\r\\n\"\n            \"Sec-WebSocket-Location: %(scheme)s://%(host)s%(uri)s\\r\\n\"\n            \"%(subprotocol)s\"\n            \"\\r\\n\" % (dict(\n                version=tornado.version,\n                origin=self.request.headers[\"Origin\"],\n                scheme=scheme,\n                host=self.request.host,\n                uri=self.request.uri,\n                subprotocol=subprotocol_header))))\n        self.stream.read_bytes(8, self._handle_challenge)\n\n    def challenge_response(self, challenge):\n        \"\"\"Generates the challenge response that's needed in the handshake\n\n        The challenge parameter should be the raw bytes as sent from the\n        client.\n        \"\"\"\n        key_1 = self.request.headers.get(\"Sec-Websocket-Key1\")\n        key_2 = self.request.headers.get(\"Sec-Websocket-Key2\")\n        try:\n            part_1 = self._calculate_part(key_1)\n            part_2 = self._calculate_part(key_2)\n        except ValueError:\n            raise ValueError(\"Invalid Keys/Challenge\")\n        return self._generate_challenge_response(part_1, part_2, challenge)\n\n    def _handle_challenge(self, challenge):\n        try:\n            challenge_response = self.challenge_response(challenge)\n        except ValueError:\n            gen_log.debug(\"Malformed key data in WebSocket request\")\n            self._abort()\n            return\n        self._write_response(challenge_response)\n\n    def _write_response(self, challenge):\n        self.stream.write(challenge)\n        self.async_callback(self.handler.open)(*self.handler.open_args, **self.handler.open_kwargs)\n        self._receive_message()\n\n    def _handle_websocket_headers(self):\n        \"\"\"Verifies all invariant- and required headers\n\n        If a header is missing or have an incorrect value ValueError will be\n        raised\n        \"\"\"\n        fields = (\"Origin\", \"Host\", \"Sec-Websocket-Key1\",\n                  \"Sec-Websocket-Key2\")\n        if not all(map(lambda f: self.request.headers.get(f), fields)):\n            raise ValueError(\"Missing/Invalid WebSocket headers\")\n\n    def _calculate_part(self, key):\n        \"\"\"Processes the key headers and calculates their key value.\n\n        Raises ValueError when feed invalid key.\"\"\"\n        # pyflakes complains about variable reuse if both of these lines use 'c'\n        number = int(''.join(c for c in key if c.isdigit()))\n        spaces = len([c2 for c2 in key if c2.isspace()])\n        try:\n            key_number = number // spaces\n        except (ValueError, ZeroDivisionError):\n            raise ValueError\n        return struct.pack(\">I\", key_number)\n\n    def _generate_challenge_response(self, part_1, part_2, part_3):\n        m = hashlib.md5()\n        m.update(part_1)\n        m.update(part_2)\n        m.update(part_3)\n        return m.digest()\n\n    def _receive_message(self):\n        self.stream.read_bytes(1, self._on_frame_type)\n\n    def _on_frame_type(self, byte):\n        frame_type = ord(byte)\n        if frame_type == 0x00:\n            self.stream.read_until(b\"\\xff\", self._on_end_delimiter)\n        elif frame_type == 0xff:\n            self.stream.read_bytes(1, self._on_length_indicator)\n        else:\n            self._abort()\n\n    def _on_end_delimiter(self, frame):\n        if not self.client_terminated:\n            self.async_callback(self.handler.on_message)(\n                frame[:-1].decode(\"utf-8\", \"replace\"))\n        if not self.client_terminated:\n            self._receive_message()\n\n    def _on_length_indicator(self, byte):\n        if ord(byte) != 0x00:\n            self._abort()\n            return\n        self.client_terminated = True\n        self.close()\n\n    def write_message(self, message, binary=False):\n        \"\"\"Sends the given message to the client of this Web Socket.\"\"\"\n        if binary:\n            raise ValueError(\n                \"Binary messages not supported by this version of websockets\")\n        if isinstance(message, unicode_type):\n            message = message.encode(\"utf-8\")\n        assert isinstance(message, bytes_type)\n        self.stream.write(b\"\\x00\" + message + b\"\\xff\")\n\n    def write_ping(self, data):\n        \"\"\"Send ping frame.\"\"\"\n        raise ValueError(\"Ping messages not supported by this version of websockets\")\n\n    def close(self, code=None, reason=None):\n        \"\"\"Closes the WebSocket connection.\"\"\"\n        if not self.server_terminated:\n            if not self.stream.closed():\n                self.stream.write(\"\\xff\\x00\")\n            self.server_terminated = True\n        if self.client_terminated:\n            if self._waiting is not None:\n                self.stream.io_loop.remove_timeout(self._waiting)\n            self._waiting = None\n            self.stream.close()\n        elif self._waiting is None:\n            self._waiting = self.stream.io_loop.add_timeout(\n                time.time() + 5, self._abort)\n\n\nclass WebSocketProtocol13(WebSocketProtocol):\n    \"\"\"Implementation of the WebSocket protocol from RFC 6455.\n\n    This class supports versions 7 and 8 of the protocol in addition to the\n    final version 13.\n    \"\"\"\n    def __init__(self, handler, mask_outgoing=False):\n        WebSocketProtocol.__init__(self, handler)\n        self.mask_outgoing = mask_outgoing\n        self._final_frame = False\n        self._frame_opcode = None\n        self._masked_frame = None\n        self._frame_mask = None\n        self._frame_length = None\n        self._fragmented_message_buffer = None\n        self._fragmented_message_opcode = None\n        self._waiting = None\n\n    def accept_connection(self):\n        try:\n            self._handle_websocket_headers()\n            self._accept_connection()\n        except ValueError:\n            gen_log.debug(\"Malformed WebSocket request received\", exc_info=True)\n            self._abort()\n            return\n\n    def _handle_websocket_headers(self):\n        \"\"\"Verifies all invariant- and required headers\n\n        If a header is missing or have an incorrect value ValueError will be\n        raised\n        \"\"\"\n        fields = (\"Host\", \"Sec-Websocket-Key\", \"Sec-Websocket-Version\")\n        if not all(map(lambda f: self.request.headers.get(f), fields)):\n            raise ValueError(\"Missing/Invalid WebSocket headers\")\n\n    @staticmethod\n    def compute_accept_value(key):\n        \"\"\"Computes the value for the Sec-WebSocket-Accept header,\n        given the value for Sec-WebSocket-Key.\n        \"\"\"\n        sha1 = hashlib.sha1()\n        sha1.update(utf8(key))\n        sha1.update(b\"258EAFA5-E914-47DA-95CA-C5AB0DC85B11\")  # Magic value\n        return native_str(base64.b64encode(sha1.digest()))\n\n    def _challenge_response(self):\n        return WebSocketProtocol13.compute_accept_value(\n            self.request.headers.get(\"Sec-Websocket-Key\"))\n\n    def _accept_connection(self):\n        subprotocol_header = ''\n        subprotocols = self.request.headers.get(\"Sec-WebSocket-Protocol\", '')\n        subprotocols = [s.strip() for s in subprotocols.split(',')]\n        if subprotocols:\n            selected = self.handler.select_subprotocol(subprotocols)\n            if selected:\n                assert selected in subprotocols\n                subprotocol_header = \"Sec-WebSocket-Protocol: %s\\r\\n\" % selected\n\n        self.stream.write(tornado.escape.utf8(\n            \"HTTP/1.1 101 Switching Protocols\\r\\n\"\n            \"Upgrade: websocket\\r\\n\"\n            \"Connection: Upgrade\\r\\n\"\n            \"Sec-WebSocket-Accept: %s\\r\\n\"\n            \"%s\"\n            \"\\r\\n\" % (self._challenge_response(), subprotocol_header)))\n\n        self.async_callback(self.handler.open)(*self.handler.open_args, **self.handler.open_kwargs)\n        self._receive_frame()\n\n    def _write_frame(self, fin, opcode, data):\n        if fin:\n            finbit = 0x80\n        else:\n            finbit = 0\n        frame = struct.pack(\"B\", finbit | opcode)\n        l = len(data)\n        if self.mask_outgoing:\n            mask_bit = 0x80\n        else:\n            mask_bit = 0\n        if l < 126:\n            frame += struct.pack(\"B\", l | mask_bit)\n        elif l <= 0xFFFF:\n            frame += struct.pack(\"!BH\", 126 | mask_bit, l)\n        else:\n            frame += struct.pack(\"!BQ\", 127 | mask_bit, l)\n        if self.mask_outgoing:\n            mask = os.urandom(4)\n            data = mask + _websocket_mask(mask, data)\n        frame += data\n        self.stream.write(frame)\n\n    def write_message(self, message, binary=False):\n        \"\"\"Sends the given message to the client of this Web Socket.\"\"\"\n        if binary:\n            opcode = 0x2\n        else:\n            opcode = 0x1\n        message = tornado.escape.utf8(message)\n        assert isinstance(message, bytes_type)\n        try:\n            self._write_frame(True, opcode, message)\n        except StreamClosedError:\n            self._abort()\n\n    def write_ping(self, data):\n        \"\"\"Send ping frame.\"\"\"\n        assert isinstance(data, bytes_type)\n        self._write_frame(True, 0x9, data)\n\n    def _receive_frame(self):\n        try:\n            self.stream.read_bytes(2, self._on_frame_start)\n        except StreamClosedError:\n            self._abort()\n\n    def _on_frame_start(self, data):\n        header, payloadlen = struct.unpack(\"BB\", data)\n        self._final_frame = header & 0x80\n        reserved_bits = header & 0x70\n        self._frame_opcode = header & 0xf\n        self._frame_opcode_is_control = self._frame_opcode & 0x8\n        if reserved_bits:\n            # client is using as-yet-undefined extensions; abort\n            self._abort()\n            return\n        self._masked_frame = bool(payloadlen & 0x80)\n        payloadlen = payloadlen & 0x7f\n        if self._frame_opcode_is_control and payloadlen >= 126:\n            # control frames must have payload < 126\n            self._abort()\n            return\n        try:\n            if payloadlen < 126:\n                self._frame_length = payloadlen\n                if self._masked_frame:\n                    self.stream.read_bytes(4, self._on_masking_key)\n                else:\n                    self.stream.read_bytes(self._frame_length, self._on_frame_data)\n            elif payloadlen == 126:\n                self.stream.read_bytes(2, self._on_frame_length_16)\n            elif payloadlen == 127:\n                self.stream.read_bytes(8, self._on_frame_length_64)\n        except StreamClosedError:\n            self._abort()\n\n    def _on_frame_length_16(self, data):\n        self._frame_length = struct.unpack(\"!H\", data)[0]\n        try:\n            if self._masked_frame:\n                self.stream.read_bytes(4, self._on_masking_key)\n            else:\n                self.stream.read_bytes(self._frame_length, self._on_frame_data)\n        except StreamClosedError:\n            self._abort()\n\n    def _on_frame_length_64(self, data):\n        self._frame_length = struct.unpack(\"!Q\", data)[0]\n        try:\n            if self._masked_frame:\n                self.stream.read_bytes(4, self._on_masking_key)\n            else:\n                self.stream.read_bytes(self._frame_length, self._on_frame_data)\n        except StreamClosedError:\n            self._abort()\n\n    def _on_masking_key(self, data):\n        self._frame_mask = data\n        try:\n            self.stream.read_bytes(self._frame_length, self._on_masked_frame_data)\n        except StreamClosedError:\n            self._abort()\n\n    def _on_masked_frame_data(self, data):\n        self._on_frame_data(_websocket_mask(self._frame_mask, data))\n\n    def _on_frame_data(self, data):\n        if self._frame_opcode_is_control:\n            # control frames may be interleaved with a series of fragmented\n            # data frames, so control frames must not interact with\n            # self._fragmented_*\n            if not self._final_frame:\n                # control frames must not be fragmented\n                self._abort()\n                return\n            opcode = self._frame_opcode\n        elif self._frame_opcode == 0:  # continuation frame\n            if self._fragmented_message_buffer is None:\n                # nothing to continue\n                self._abort()\n                return\n            self._fragmented_message_buffer += data\n            if self._final_frame:\n                opcode = self._fragmented_message_opcode\n                data = self._fragmented_message_buffer\n                self._fragmented_message_buffer = None\n        else:  # start of new data message\n            if self._fragmented_message_buffer is not None:\n                # can't start new message until the old one is finished\n                self._abort()\n                return\n            if self._final_frame:\n                opcode = self._frame_opcode\n            else:\n                self._fragmented_message_opcode = self._frame_opcode\n                self._fragmented_message_buffer = data\n\n        if self._final_frame:\n            self._handle_message(opcode, data)\n\n        if not self.client_terminated:\n            self._receive_frame()\n\n    def _handle_message(self, opcode, data):\n        if self.client_terminated:\n            return\n\n        if opcode == 0x1:\n            # UTF-8 data\n            try:\n                decoded = data.decode(\"utf-8\")\n            except UnicodeDecodeError:\n                self._abort()\n                return\n            self.async_callback(self.handler.on_message)(decoded)\n        elif opcode == 0x2:\n            # Binary data\n            self.async_callback(self.handler.on_message)(data)\n        elif opcode == 0x8:\n            # Close\n            self.client_terminated = True\n            if len(data) >= 2:\n                self.handler.close_code = struct.unpack('>H', data[:2])[0]\n            if len(data) > 2:\n                self.handler.close_reason = to_unicode(data[2:])\n            self.close()\n        elif opcode == 0x9:\n            # Ping\n            self._write_frame(True, 0xA, data)\n        elif opcode == 0xA:\n            # Pong\n            self.async_callback(self.handler.on_pong)(data)\n        else:\n            self._abort()\n\n    def close(self, code=None, reason=None):\n        \"\"\"Closes the WebSocket connection.\"\"\"\n        if not self.server_terminated:\n            if not self.stream.closed():\n                if code is None and reason is not None:\n                    code = 1000  # \"normal closure\" status code\n                if code is None:\n                    close_data = b''\n                else:\n                    close_data = struct.pack('>H', code)\n                if reason is not None:\n                    close_data += utf8(reason)\n                self._write_frame(True, 0x8, close_data)\n            self.server_terminated = True\n        if self.client_terminated:\n            if self._waiting is not None:\n                self.stream.io_loop.remove_timeout(self._waiting)\n                self._waiting = None\n            self.stream.close()\n        elif self._waiting is None:\n            # Give the client a few seconds to complete a clean shutdown,\n            # otherwise just close the connection.\n            self._waiting = self.stream.io_loop.add_timeout(\n                self.stream.io_loop.time() + 5, self._abort)\n\n\nclass WebSocketClientConnection(simple_httpclient._HTTPConnection):\n    \"\"\"WebSocket client connection.\n\n    This class should not be instantiated directly; use the\n    `websocket_connect` function instead.\n    \"\"\"\n    def __init__(self, io_loop, request):\n        self.connect_future = TracebackFuture()\n        self.read_future = None\n        self.read_queue = collections.deque()\n        self.key = base64.b64encode(os.urandom(16))\n\n        scheme, sep, rest = request.url.partition(':')\n        scheme = {'ws': 'http', 'wss': 'https'}[scheme]\n        request.url = scheme + sep + rest\n        request.headers.update({\n            'Upgrade': 'websocket',\n            'Connection': 'Upgrade',\n            'Sec-WebSocket-Key': self.key,\n            'Sec-WebSocket-Version': '13',\n        })\n\n        self.tcp_client = TCPClient(io_loop=io_loop)\n        super(WebSocketClientConnection, self).__init__(\n            io_loop, None, request, lambda: None, self._on_http_response,\n            104857600, self.tcp_client, 65536)\n\n    def close(self, code=None, reason=None):\n        \"\"\"Closes the websocket connection.\n\n        ``code`` and ``reason`` are documented under\n        `WebSocketHandler.close`.\n\n        .. versionadded:: 3.2\n\n        .. versionchanged:: 3.3\n\n           Added the ``code`` and ``reason`` arguments.\n        \"\"\"\n        if self.protocol is not None:\n            self.protocol.close(code, reason)\n            self.protocol = None\n\n    def _on_close(self):\n        self.on_message(None)\n        self.resolver.close()\n        super(WebSocketClientConnection, self)._on_close()\n\n    def _on_http_response(self, response):\n        if not self.connect_future.done():\n            if response.error:\n                self.connect_future.set_exception(response.error)\n            else:\n                self.connect_future.set_exception(WebSocketError(\n                    \"Non-websocket response\"))\n\n    def headers_received(self, start_line, headers):\n        if start_line.code != 101:\n            return super(WebSocketClientConnection, self).headers_received(\n                start_line, headers)\n\n        self.headers = headers\n        assert self.headers['Upgrade'].lower() == 'websocket'\n        assert self.headers['Connection'].lower() == 'upgrade'\n        accept = WebSocketProtocol13.compute_accept_value(self.key)\n        assert self.headers['Sec-Websocket-Accept'] == accept\n\n        self.protocol = WebSocketProtocol13(self, mask_outgoing=True)\n        self.protocol._receive_frame()\n\n        if self._timeout is not None:\n            self.io_loop.remove_timeout(self._timeout)\n            self._timeout = None\n\n        self.stream = self.connection.detach()\n        self.stream.set_close_callback(self._on_close)\n\n        self.connect_future.set_result(self)\n\n    def write_message(self, message, binary=False):\n        \"\"\"Sends a message to the WebSocket server.\"\"\"\n        self.protocol.write_message(message, binary)\n\n    def read_message(self, callback=None):\n        \"\"\"Reads a message from the WebSocket server.\n\n        Returns a future whose result is the message, or None\n        if the connection is closed.  If a callback argument\n        is given it will be called with the future when it is\n        ready.\n        \"\"\"\n        assert self.read_future is None\n        future = TracebackFuture()\n        if self.read_queue:\n            future.set_result(self.read_queue.popleft())\n        else:\n            self.read_future = future\n        if callback is not None:\n            self.io_loop.add_future(future, callback)\n        return future\n\n    def on_message(self, message):\n        if self.read_future is not None:\n            self.read_future.set_result(message)\n            self.read_future = None\n        else:\n            self.read_queue.append(message)\n\n    def on_pong(self, data):\n        pass\n\n\ndef websocket_connect(url, io_loop=None, callback=None, connect_timeout=None):\n    \"\"\"Client-side websocket support.\n\n    Takes a url and returns a Future whose result is a\n    `WebSocketClientConnection`.\n\n    .. versionchanged:: 3.2\n       Also accepts ``HTTPRequest`` objects in place of urls.\n    \"\"\"\n    if io_loop is None:\n        io_loop = IOLoop.current()\n    if isinstance(url, httpclient.HTTPRequest):\n        assert connect_timeout is None\n        request = url\n        # Copy and convert the headers dict/object (see comments in\n        # AsyncHTTPClient.fetch)\n        request.headers = httputil.HTTPHeaders(request.headers)\n    else:\n        request = httpclient.HTTPRequest(url, connect_timeout=connect_timeout)\n    request = httpclient._RequestProxy(\n        request, httpclient.HTTPRequest._DEFAULTS)\n    conn = WebSocketClientConnection(io_loop, request)\n    if callback is not None:\n        io_loop.add_future(conn.connect_future, callback)\n    return conn.connect_future\n\n\ndef _websocket_mask_python(mask, data):\n    \"\"\"Websocket masking function.\n\n    `mask` is a `bytes` object of length 4; `data` is a `bytes` object of any length.\n    Returns a `bytes` object of the same length as `data` with the mask applied\n    as specified in section 5.3 of RFC 6455.\n\n    This pure-python implementation may be replaced by an optimized version when available.\n    \"\"\"\n    mask = array.array(\"B\", mask)\n    unmasked = array.array(\"B\", data)\n    for i in xrange(len(data)):\n        unmasked[i] = unmasked[i] ^ mask[i % 4]\n    if hasattr(unmasked, 'tobytes'):\n        # tostring was deprecated in py32.  It hasn't been removed,\n        # but since we turn on deprecation warnings in our tests\n        # we need to use the right one.\n        return unmasked.tobytes()\n    else:\n        return unmasked.tostring()\n\nif (os.environ.get('TORNADO_NO_EXTENSION') or\n        os.environ.get('TORNADO_EXTENSION') == '0'):\n    # These environment variables exist to make it easier to do performance\n    # comparisons; they are not guaranteed to remain supported in the future.\n    _websocket_mask = _websocket_mask_python\nelse:\n    try:\n        from tornado.speedups import websocket_mask as _websocket_mask\n    except ImportError:\n        if os.environ.get('TORNADO_EXTENSION') == '1':\n            raise\n        _websocket_mask = _websocket_mask_python\n"}
A user will ask you to solve a task. You should first draft your thinking process (inner monologue). Then, generate the solution.

Your response format must follow the template below:
<think>
Your thoughts or/and draft, like working through an exercise on scratch paper. Be as casual and as long as you want until you are confident to generate a correct solution.
</think>
<solution>
Final solution presented to the user.
</solution>
system
We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[ISSUE]

**WebSocket Server Accepts Connections with Invalid Origin Headers**

**Description**

When a client attempts to establish a WebSocket connection with an invalid `Origin` header, the server does not reject the connection as expected. This behavior allows unauthorized cross-origin WebSocket connections, potentially leading to security vulnerabilities.

**Example Code**

```python
headers = {'Origin': 'http://somewhereelse.com'}
ws = websocket_connect(HTTPRequest('ws://localhost:PORT/echo', headers=headers))
# Expected to receive an HTTP 403 error, but the connection is accepted instead.
```

**Expected Behavior**

The server should reject WebSocket connections that include invalid `Origin` headers by responding with an HTTP 403 status code. This ensures that only authorized origins can establish WebSocket connections, enforcing proper cross-origin restrictions.

**Actual Behavior**

Connections with invalid `Origin` headers are accepted without raising an error, bypassing the intended security checks and allowing unauthorized cross-origin access.

[/ISSUE]
--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.

--- BEGIN FILE ---
```
### tornado/websocket.py
"""Implementation of the WebSocket protocol.

`WebSockets <http://dev.w3.org/html5/websockets/>`_ allow for bidirectional
communication between the browser and server.

.. warning::

   The WebSocket protocol was recently finalized as `RFC 6455
   <http://tools.ietf.org/html/rfc6455>`_ and is not yet supported in
   all browsers.  Refer to http://caniuse.com/websockets for details
   on compatibility.  In addition, during development the protocol
   went through several incompatible versions, and some browsers only
   support older versions.  By default this module only supports the
   latest version of the protocol, but optional support for an older
   version (known as "draft 76" or "hixie-76") can be enabled by
   overriding `WebSocketHandler.allow_draft76` (see that method's
   documentation for caveats).
"""

from __future__ import absolute_import, division, print_function, with_statement
# Author: Jacob Kristhammar, 2010

import array
import base64
import collections
import functools
import hashlib
import os
import struct
import time
import tornado.escape
import tornado.web

from tornado.concurrent import TracebackFuture
from tornado.escape import utf8, native_str, to_unicode
from tornado import httpclient, httputil
from tornado.ioloop import IOLoop
from tornado.iostream import StreamClosedError
from tornado.log import gen_log, app_log
from tornado import simple_httpclient
from tornado.tcpclient import TCPClient
from tornado.util import bytes_type, unicode_type

try:
    xrange  # py2
except NameError:
    xrange = range  # py3


class WebSocketError(Exception):
    pass


class WebSocketClosedError(WebSocketError):
    """Raised by operations on a closed connection.

    .. versionadded:: 3.2
    """
    pass


class WebSocketHandler(tornado.web.RequestHandler):
    """Subclass this class to create a basic WebSocket handler.

    Override `on_message` to handle incoming messages, and use
    `write_message` to send messages to the client. You can also
    override `open` and `on_close` to handle opened and closed
    connections.

    See http://dev.w3.org/html5/websockets/ for details on the
    JavaScript interface.  The protocol is specified at
    http://tools.ietf.org/html/rfc6455.

    Here is an example WebSocket handler that echos back all received messages
    back to the client::

      class EchoWebSocket(websocket.WebSocketHandler):
          def open(self):
              print "WebSocket opened"

          def on_message(self, message):
              self.write_message(u"You said: " + message)

          def on_close(self):
              print "WebSocket closed"

    WebSockets are not standard HTTP connections. The "handshake" is
    HTTP, but after the handshake, the protocol is
    message-based. Consequently, most of the Tornado HTTP facilities
    are not available in handlers of this type. The only communication
    methods available to you are `write_message()`, `ping()`, and
    `close()`. Likewise, your request handler class should implement
    `open()` method rather than ``get()`` or ``post()``.

    If you map the handler above to ``/websocket`` in your application, you can
    invoke it in JavaScript with::

      var ws = new WebSocket("ws://localhost:8888/websocket");
      ws.onopen = function() {
         ws.send("Hello, world");
      };
      ws.onmessage = function (evt) {
         alert(evt.data);
      };

    This script pops up an alert box that says "You said: Hello, world".
    """
    def __init__(self, application, request, **kwargs):
        tornado.web.RequestHandler.__init__(self, application, request,
                                            **kwargs)
        self.ws_connection = None
        self.close_code = None
        self.close_reason = None

    @tornado.web.asynchronous
    def get(self, *args, **kwargs):
        self.open_args = args
        self.open_kwargs = kwargs

        self.stream = self.request.connection.detach()
        self.stream.set_close_callback(self.on_connection_close)

        # Upgrade header should be present and should be equal to WebSocket
        if self.request.headers.get("Upgrade", "").lower() != 'websocket':
            self.stream.write(tornado.escape.utf8(
                "HTTP/1.1 400 Bad Request\r\n\r\n"
                "Can \"Upgrade\" only to \"WebSocket\"."
            ))
            self.stream.close()
            return

        # Connection header should be upgrade. Some proxy servers/load balancers
        # might mess with it.
        headers = self.request.headers
        connection = map(lambda s: s.strip().lower(), headers.get("Connection", "").split(","))
        if 'upgrade' not in connection:
            self.stream.write(tornado.escape.utf8(
                "HTTP/1.1 400 Bad Request\r\n\r\n"
                "\"Connection\" must be \"Upgrade\"."
            ))
            self.stream.close()
            return

        # The difference between version 8 and 13 is that in 8 the
        # client sends a "Sec-Websocket-Origin" header and in 13 it's
        # simply "Origin".
        if self.request.headers.get("Sec-WebSocket-Version") in ("7", "8", "13"):
            self.ws_connection = WebSocketProtocol13(self)
            self.ws_connection.accept_connection()
        elif (self.allow_draft76() and
              "Sec-WebSocket-Version" not in self.request.headers):
            self.ws_connection = WebSocketProtocol76(self)
            self.ws_connection.accept_connection()
        else:
            self.stream.write(tornado.escape.utf8(
                "HTTP/1.1 426 Upgrade Required\r\n"
                "Sec-WebSocket-Version: 8\r\n\r\n"))
            self.stream.close()

    def write_message(self, message, binary=False):
        """Sends the given message to the client of this Web Socket.

        The message may be either a string or a dict (which will be
        encoded as json).  If the ``binary`` argument is false, the
        message will be sent as utf8; in binary mode any byte string
        is allowed.

        If the connection is already closed, raises `WebSocketClosedError`.

        .. versionchanged:: 3.2
           `WebSocketClosedError` was added (previously a closed connection
           would raise an `AttributeError`)
        """
        if self.ws_connection is None:
            raise WebSocketClosedError()
        if isinstance(message, dict):
            message = tornado.escape.json_encode(message)
        self.ws_connection.write_message(message, binary=binary)

    def select_subprotocol(self, subprotocols):
        """Invoked when a new WebSocket requests specific subprotocols.

        ``subprotocols`` is a list of strings identifying the
        subprotocols proposed by the client.  This method may be
        overridden to return one of those strings to select it, or
        ``None`` to not select a subprotocol.  Failure to select a
        subprotocol does not automatically abort the connection,
        although clients may close the connection if none of their
        proposed subprotocols was selected.
        """
        return None

    def open(self):
        """Invoked when a new WebSocket is opened.

        The arguments to `open` are extracted from the `tornado.web.URLSpec`
        regular expression, just like the arguments to
        `tornado.web.RequestHandler.get`.
        """
        pass

    def on_message(self, message):
        """Handle incoming messages on the WebSocket

        This method must be overridden.
        """
        raise NotImplementedError

    def ping(self, data):
        """Send ping frame to the remote end."""
        if self.ws_connection is None:
            raise WebSocketClosedError()
        self.ws_connection.write_ping(data)

    def on_pong(self, data):
        """Invoked when the response to a ping frame is received."""
        pass

    def on_close(self):
        """Invoked when the WebSocket is closed.

        If the connection was closed cleanly and a status code or reason
        phrase was supplied, these values will be available as the attributes
        ``self.close_code`` and ``self.close_reason``.

        .. versionchanged:: 3.3

           Added ``close_code`` and ``close_reason`` attributes.
        """
        pass

    def close(self, code=None, reason=None):
        """Closes this Web Socket.

        Once the close handshake is successful the socket will be closed.

        ``code`` may be a numeric status code, taken from the values
        defined in `RFC 6455 section 7.4.1
        <https://tools.ietf.org/html/rfc6455#section-7.4.1>`_.
        ``reason`` may be a textual message about why the connection is
        closing.  These values are made available to the client, but are
        not otherwise interpreted by the websocket protocol.

        The ``code`` and ``reason`` arguments are ignored in the "draft76"
        protocol version.

        .. versionchanged:: 3.3

           Added the ``code`` and ``reason`` arguments.
        """
        if self.ws_connection:
            self.ws_connection.close(code, reason)
            self.ws_connection = None

    def allow_draft76(self):
        """Override to enable support for the older "draft76" protocol.

        The draft76 version of the websocket protocol is disabled by
        default due to security concerns, but it can be enabled by
        overriding this method to return True.

        Connections using the draft76 protocol do not support the
        ``binary=True`` flag to `write_message`.

        Support for the draft76 protocol is deprecated and will be
        removed in a future version of Tornado.
        """
        return False

    def set_nodelay(self, value):
        """Set the no-delay flag for this stream.

        By default, small messages may be delayed and/or combined to minimize
        the number of packets sent.  This can sometimes cause 200-500ms delays
        due to the interaction between Nagle's algorithm and TCP delayed
        ACKs.  To reduce this delay (at the expense of possibly increasing
        bandwidth usage), call ``self.set_nodelay(True)`` once the websocket
        connection is established.

        See `.BaseIOStream.set_nodelay` for additional details.

        .. versionadded:: 3.1
        """
        self.stream.set_nodelay(value)

    def get_websocket_scheme(self):
        """Return the url scheme used for this request, either "ws" or "wss".

        This is normally decided by HTTPServer, but applications
        may wish to override this if they are using an SSL proxy
        that does not provide the X-Scheme header as understood
        by HTTPServer.

        Note that this is only used by the draft76 protocol.
        """
        return "wss" if self.request.protocol == "https" else "ws"

    def async_callback(self, callback, *args, **kwargs):
        """Obsolete - catches exceptions from the wrapped function.

        This function is normally unncecessary thanks to
        `tornado.stack_context`.
        """
        return self.ws_connection.async_callback(callback, *args, **kwargs)

    def _not_supported(self, *args, **kwargs):
        raise Exception("Method not supported for Web Sockets")

    def on_connection_close(self):
        if self.ws_connection:
            self.ws_connection.on_connection_close()
            self.ws_connection = None
            self.on_close()


for method in ["write", "redirect", "set_header", "send_error", "set_cookie",
               "set_status", "flush", "finish"]:
    setattr(WebSocketHandler, method, WebSocketHandler._not_supported)


class WebSocketProtocol(object):
    """Base class for WebSocket protocol versions.
    """
    def __init__(self, handler):
        self.handler = handler
        self.request = handler.request
        self.stream = handler.stream
        self.client_terminated = False
        self.server_terminated = False

    def async_callback(self, callback, *args, **kwargs):
        """Wrap callbacks with this if they are used on asynchronous requests.

        Catches exceptions properly and closes this WebSocket if an exception
        is uncaught.
        """
        if args or kwargs:
            callback = functools.partial(callback, *args, **kwargs)

        def wrapper(*args, **kwargs):
            try:
                return callback(*args, **kwargs)
            except Exception:
                app_log.error("Uncaught exception in %s",
                              self.request.path, exc_info=True)
                self._abort()
        return wrapper

    def on_connection_close(self):
        self._abort()

    def _abort(self):
        """Instantly aborts the WebSocket connection by closing the socket"""
        self.client_terminated = True
        self.server_terminated = True
        self.stream.close()  # forcibly tear down the connection
        self.close()  # let the subclass cleanup


class WebSocketProtocol76(WebSocketProtocol):
    """Implementation of the WebSockets protocol, version hixie-76.

    This class provides basic functionality to process WebSockets requests as
    specified in
    http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-76
    """
    def __init__(self, handler):
        WebSocketProtocol.__init__(self, handler)
        self.challenge = None
        self._waiting = None

    def accept_connection(self):
        try:
            self._handle_websocket_headers()
        except ValueError:
            gen_log.debug("Malformed WebSocket request received")
            self._abort()
            return

        scheme = self.handler.get_websocket_scheme()

        # draft76 only allows a single subprotocol
        subprotocol_header = ''
        subprotocol = self.request.headers.get("Sec-WebSocket-Protocol", None)
        if subprotocol:
            selected = self.handler.select_subprotocol([subprotocol])
            if selected:
                assert selected == subprotocol
                subprotocol_header = "Sec-WebSocket-Protocol: %s\r\n" % selected

        # Write the initial headers before attempting to read the challenge.
        # This is necessary when using proxies (such as HAProxy), which
        # need to see the Upgrade headers before passing through the
        # non-HTTP traffic that follows.
        self.stream.write(tornado.escape.utf8(
            "HTTP/1.1 101 WebSocket Protocol Handshake\r\n"
            "Upgrade: WebSocket\r\n"
            "Connection: Upgrade\r\n"
            "Server: TornadoServer/%(version)s\r\n"
            "Sec-WebSocket-Origin: %(origin)s\r\n"
            "Sec-WebSocket-Location: %(scheme)s://%(host)s%(uri)s\r\n"
            "%(subprotocol)s"
            "\r\n" % (dict(
                version=tornado.version,
                origin=self.request.headers["Origin"],
                scheme=scheme,
                host=self.request.host,
                uri=self.request.uri,
                subprotocol=subprotocol_header))))
        self.stream.read_bytes(8, self._handle_challenge)

    def challenge_response(self, challenge):
        """Generates the challenge response that's needed in the handshake

        The challenge parameter should be the raw bytes as sent from the
        client.
        """
        key_1 = self.request.headers.get("Sec-Websocket-Key1")
        key_2 = self.request.headers.get("Sec-Websocket-Key2")
        try:
            part_1 = self._calculate_part(key_1)
            part_2 = self._calculate_part(key_2)
        except ValueError:
            raise ValueError("Invalid Keys/Challenge")
        return self._generate_challenge_response(part_1, part_2, challenge)

    def _handle_challenge(self, challenge):
        try:
            challenge_response = self.challenge_response(challenge)
        except ValueError:
            gen_log.debug("Malformed key data in WebSocket request")
            self._abort()
            return
        self._write_response(challenge_response)

    def _write_response(self, challenge):
        self.stream.write(challenge)
        self.async_callback(self.handler.open)(*self.handler.open_args, **self.handler.open_kwargs)
        self._receive_message()

    def _handle_websocket_headers(self):
        """Verifies all invariant- and required headers

        If a header is missing or have an incorrect value ValueError will be
        raised
        """
        fields = ("Origin", "Host", "Sec-Websocket-Key1",
                  "Sec-Websocket-Key2")
        if not all(map(lambda f: self.request.headers.get(f), fields)):
            raise ValueError("Missing/Invalid WebSocket headers")

    def _calculate_part(self, key):
        """Processes the key headers and calculates their key value.

        Raises ValueError when feed invalid key."""
        # pyflakes complains about variable reuse if both of these lines use 'c'
        number = int(''.join(c for c in key if c.isdigit()))
        spaces = len([c2 for c2 in key if c2.isspace()])
        try:
            key_number = number // spaces
        except (ValueError, ZeroDivisionError):
            raise ValueError
        return struct.pack(">I", key_number)

    def _generate_challenge_response(self, part_1, part_2, part_3):
        m = hashlib.md5()
        m.update(part_1)
        m.update(part_2)
        m.update(part_3)
        return m.digest()

    def _receive_message(self):
        self.stream.read_bytes(1, self._on_frame_type)

    def _on_frame_type(self, byte):
        frame_type = ord(byte)
        if frame_type == 0x00:
            self.stream.read_until(b"\xff", self._on_end_delimiter)
        elif frame_type == 0xff:
            self.stream.read_bytes(1, self._on_length_indicator)
        else:
            self._abort()

    def _on_end_delimiter(self, frame):
        if not self.client_terminated:
            self.async_callback(self.handler.on_message)(
                frame[:-1].decode("utf-8", "replace"))
        if not self.client_terminated:
            self._receive_message()

    def _on_length_indicator(self, byte):
        if ord(byte) != 0x00:
            self._abort()
            return
        self.client_terminated = True
        self.close()

    def write_message(self, message, binary=False):
        """Sends the given message to the client of this Web Socket."""
        if binary:
            raise ValueError(
                "Binary messages not supported by this version of websockets")
        if isinstance(message, unicode_type):
            message = message.encode("utf-8")
        assert isinstance(message, bytes_type)
        self.stream.write(b"\x00" + message + b"\xff")

    def write_ping(self, data):
        """Send ping frame."""
        raise ValueError("Ping messages not supported by this version of websockets")

    def close(self, code=None, reason=None):
        """Closes the WebSocket connection."""
        if not self.server_terminated:
            if not self.stream.closed():
                self.stream.write("\xff\x00")
            self.server_terminated = True
        if self.client_terminated:
            if self._waiting is not None:
                self.stream.io_loop.remove_timeout(self._waiting)
            self._waiting = None
            self.stream.close()
        elif self._waiting is None:
            self._waiting = self.stream.io_loop.add_timeout(
                time.time() + 5, self._abort)


class WebSocketProtocol13(WebSocketProtocol):
    """Implementation of the WebSocket protocol from RFC 6455.

    This class supports versions 7 and 8 of the protocol in addition to the
    final version 13.
    """
    def __init__(self, handler, mask_outgoing=False):
        WebSocketProtocol.__init__(self, handler)
        self.mask_outgoing = mask_outgoing
        self._final_frame = False
        self._frame_opcode = None
        self._masked_frame = None
        self._frame_mask = None
        self._frame_length = None
        self._fragmented_message_buffer = None
        self._fragmented_message_opcode = None
        self._waiting = None

    def accept_connection(self):
        try:
            self._handle_websocket_headers()
            self._accept_connection()
        except ValueError:
            gen_log.debug("Malformed WebSocket request received", exc_info=True)
            self._abort()
            return

    def _handle_websocket_headers(self):
        """Verifies all invariant- and required headers

        If a header is missing or have an incorrect value ValueError will be
        raised
        """
        fields = ("Host", "Sec-Websocket-Key", "Sec-Websocket-Version")
        if not all(map(lambda f: self.request.headers.get(f), fields)):
            raise ValueError("Missing/Invalid WebSocket headers")

    @staticmethod
    def compute_accept_value(key):
        """Computes the value for the Sec-WebSocket-Accept header,
        given the value for Sec-WebSocket-Key.
        """
        sha1 = hashlib.sha1()
        sha1.update(utf8(key))
        sha1.update(b"258EAFA5-E914-47DA-95CA-C5AB0DC85B11")  # Magic value
        return native_str(base64.b64encode(sha1.digest()))

    def _challenge_response(self):
        return WebSocketProtocol13.compute_accept_value(
            self.request.headers.get("Sec-Websocket-Key"))

    def _accept_connection(self):
        subprotocol_header = ''
        subprotocols = self.request.headers.get("Sec-WebSocket-Protocol", '')
        subprotocols = [s.strip() for s in subprotocols.split(',')]
        if subprotocols:
            selected = self.handler.select_subprotocol(subprotocols)
            if selected:
                assert selected in subprotocols
                subprotocol_header = "Sec-WebSocket-Protocol: %s\r\n" % selected

        self.stream.write(tornado.escape.utf8(
            "HTTP/1.1 101 Switching Protocols\r\n"
            "Upgrade: websocket\r\n"
            "Connection: Upgrade\r\n"
            "Sec-WebSocket-Accept: %s\r\n"
            "%s"
            "\r\n" % (self._challenge_response(), subprotocol_header)))

        self.async_callback(self.handler.open)(*self.handler.open_args, **self.handler.open_kwargs)
        self._receive_frame()

    def _write_frame(self, fin, opcode, data):
        if fin:
            finbit = 0x80
        else:
            finbit = 0
        frame = struct.pack("B", finbit | opcode)
        l = len(data)
        if self.mask_outgoing:
            mask_bit = 0x80
        else:
            mask_bit = 0
        if l < 126:
            frame += struct.pack("B", l | mask_bit)
        elif l <= 0xFFFF:
            frame += struct.pack("!BH", 126 | mask_bit, l)
        else:
            frame += struct.pack("!BQ", 127 | mask_bit, l)
        if self.mask_outgoing:
            mask = os.urandom(4)
            data = mask + _websocket_mask(mask, data)
        frame += data
        self.stream.write(frame)

    def write_message(self, message, binary=False):
        """Sends the given message to the client of this Web Socket."""
        if binary:
            opcode = 0x2
        else:
            opcode = 0x1
        message = tornado.escape.utf8(message)
        assert isinstance(message, bytes_type)
        try:
            self._write_frame(True, opcode, message)
        except StreamClosedError:
            self._abort()

    def write_ping(self, data):
        """Send ping frame."""
        assert isinstance(data, bytes_type)
        self._write_frame(True, 0x9, data)

    def _receive_frame(self):
        try:
            self.stream.read_bytes(2, self._on_frame_start)
        except StreamClosedError:
            self._abort()

    def _on_frame_start(self, data):
        header, payloadlen = struct.unpack("BB", data)
        self._final_frame = header & 0x80
        reserved_bits = header & 0x70
        self._frame_opcode = header & 0xf
        self._frame_opcode_is_control = self._frame_opcode & 0x8
        if reserved_bits:
            # client is using as-yet-undefined extensions; abort
            self._abort()
            return
        self._masked_frame = bool(payloadlen & 0x80)
        payloadlen = payloadlen & 0x7f
        if self._frame_opcode_is_control and payloadlen >= 126:
            # control frames must have payload < 126
            self._abort()
            return
        try:
            if payloadlen < 126:
                self._frame_length = payloadlen
                if self._masked_frame:
                    self.stream.read_bytes(4, self._on_masking_key)
                else:
                    self.stream.read_bytes(self._frame_length, self._on_frame_data)
            elif payloadlen == 126:
                self.stream.read_bytes(2, self._on_frame_length_16)
            elif payloadlen == 127:
                self.stream.read_bytes(8, self._on_frame_length_64)
        except StreamClosedError:
            self._abort()

    def _on_frame_length_16(self, data):
        self._frame_length = struct.unpack("!H", data)[0]
        try:
            if self._masked_frame:
                self.stream.read_bytes(4, self._on_masking_key)
            else:
                self.stream.read_bytes(self._frame_length, self._on_frame_data)
        except StreamClosedError:
            self._abort()

    def _on_frame_length_64(self, data):
        self._frame_length = struct.unpack("!Q", data)[0]
        try:
            if self._masked_frame:
                self.stream.read_bytes(4, self._on_masking_key)
            else:
                self.stream.read_bytes(self._frame_length, self._on_frame_data)
        except StreamClosedError:
            self._abort()

    def _on_masking_key(self, data):
        self._frame_mask = data
        try:
            self.stream.read_bytes(self._frame_length, self._on_masked_frame_data)
        except StreamClosedError:
            self._abort()

    def _on_masked_frame_data(self, data):
        self._on_frame_data(_websocket_mask(self._frame_mask, data))

    def _on_frame_data(self, data):
        if self._frame_opcode_is_control:
            # control frames may be interleaved with a series of fragmented
            # data frames, so control frames must not interact with
            # self._fragmented_*
            if not self._final_frame:
                # control frames must not be fragmented
                self._abort()
                return
            opcode = self._frame_opcode
        elif self._frame_opcode == 0:  # continuation frame
            if self._fragmented_message_buffer is None:
                # nothing to continue
                self._abort()
                return
            self._fragmented_message_buffer += data
            if self._final_frame:
                opcode = self._fragmented_message_opcode
                data = self._fragmented_message_buffer
                self._fragmented_message_buffer = None
        else:  # start of new data message
            if self._fragmented_message_buffer is not None:
                # can't start new message until the old one is finished
                self._abort()
                return
            if self._final_frame:
                opcode = self._frame_opcode
            else:
                self._fragmented_message_opcode = self._frame_opcode
                self._fragmented_message_buffer = data

        if self._final_frame:
            self._handle_message(opcode, data)

        if not self.client_terminated:
            self._receive_frame()

    def _handle_message(self, opcode, data):
        if self.client_terminated:
            return

        if opcode == 0x1:
            # UTF-8 data
            try:
                decoded = data.decode("utf-8")
            except UnicodeDecodeError:
                self._abort()
                return
            self.async_callback(self.handler.on_message)(decoded)
        elif opcode == 0x2:
            # Binary data
            self.async_callback(self.handler.on_message)(data)
        elif opcode == 0x8:
            # Close
            self.client_terminated = True
            if len(data) >= 2:
                self.handler.close_code = struct.unpack('>H', data[:2])[0]
            if len(data) > 2:
                self.handler.close_reason = to_unicode(data[2:])
            self.close()
        elif opcode == 0x9:
            # Ping
            self._write_frame(True, 0xA, data)
        elif opcode == 0xA:
            # Pong
            self.async_callback(self.handler.on_pong)(data)
        else:
            self._abort()

    def close(self, code=None, reason=None):
        """Closes the WebSocket connection."""
        if not self.server_terminated:
            if not self.stream.closed():
                if code is None and reason is not None:
                    code = 1000  # "normal closure" status code
                if code is None:
                    close_data = b''
                else:
                    close_data = struct.pack('>H', code)
                if reason is not None:
                    close_data += utf8(reason)
                self._write_frame(True, 0x8, close_data)
            self.server_terminated = True
        if self.client_terminated:
            if self._waiting is not None:
                self.stream.io_loop.remove_timeout(self._waiting)
                self._waiting = None
            self.stream.close()
        elif self._waiting is None:
            # Give the client a few seconds to complete a clean shutdown,
            # otherwise just close the connection.
            self._waiting = self.stream.io_loop.add_timeout(
                self.stream.io_loop.time() + 5, self._abort)


class WebSocketClientConnection(simple_httpclient._HTTPConnection):
    """WebSocket client connection.

    This class should not be instantiated directly; use the
    `websocket_connect` function instead.
    """
    def __init__(self, io_loop, request):
        self.connect_future = TracebackFuture()
        self.read_future = None
        self.read_queue = collections.deque()
        self.key = base64.b64encode(os.urandom(16))

        scheme, sep, rest = request.url.partition(':')
        scheme = {'ws': 'http', 'wss': 'https'}[scheme]
        request.url = scheme + sep + rest
        request.headers.update({
            'Upgrade': 'websocket',
            'Connection': 'Upgrade',
            'Sec-WebSocket-Key': self.key,
            'Sec-WebSocket-Version': '13',
        })

        self.tcp_client = TCPClient(io_loop=io_loop)
        super(WebSocketClientConnection, self).__init__(
            io_loop, None, request, lambda: None, self._on_http_response,
            104857600, self.tcp_client, 65536)

    def close(self, code=None, reason=None):
        """Closes the websocket connection.

        ``code`` and ``reason`` are documented under
        `WebSocketHandler.close`.

        .. versionadded:: 3.2

        .. versionchanged:: 3.3

           Added the ``code`` and ``reason`` arguments.
        """
        if self.protocol is not None:
            self.protocol.close(code, reason)
            self.protocol = None

    def _on_close(self):
        self.on_message(None)
        self.resolver.close()
        super(WebSocketClientConnection, self)._on_close()

    def _on_http_response(self, response):
        if not self.connect_future.done():
            if response.error:
                self.connect_future.set_exception(response.error)
            else:
                self.connect_future.set_exception(WebSocketError(
                    "Non-websocket response"))

    def headers_received(self, start_line, headers):
        if start_line.code != 101:
            return super(WebSocketClientConnection, self).headers_received(
                start_line, headers)

        self.headers = headers
        assert self.headers['Upgrade'].lower() == 'websocket'
        assert self.headers['Connection'].lower() == 'upgrade'
        accept = WebSocketProtocol13.compute_accept_value(self.key)
        assert self.headers['Sec-Websocket-Accept'] == accept

        self.protocol = WebSocketProtocol13(self, mask_outgoing=True)
        self.protocol._receive_frame()

        if self._timeout is not None:
            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)

    def write_message(self, message, binary=False):
        """Sends a message to the WebSocket server."""
        self.protocol.write_message(message, binary)

    def read_message(self, callback=None):
        """Reads a message from the WebSocket server.

        Returns a future whose result is the message, or None
        if the connection is closed.  If a callback argument
        is given it will be called with the future when it is
        ready.
        """
        assert self.read_future is None
        future = TracebackFuture()
        if self.read_queue:
            future.set_result(self.read_queue.popleft())
        else:
            self.read_future = future
        if callback is not None:
            self.io_loop.add_future(future, callback)
        return future

    def on_message(self, message):
        if self.read_future is not None:
            self.read_future.set_result(message)
            self.read_future = None
        else:
            self.read_queue.append(message)

    def on_pong(self, data):
        pass


def websocket_connect(url, io_loop=None, callback=None, connect_timeout=None):
    """Client-side websocket support.

    Takes a url and returns a Future whose result is a
    `WebSocketClientConnection`.

    .. versionchanged:: 3.2
       Also accepts ``HTTPRequest`` objects in place of urls.
    """
    if io_loop is None:
        io_loop = IOLoop.current()
    if isinstance(url, httpclient.HTTPRequest):
        assert connect_timeout is None
        request = url
        # Copy and convert the headers dict/object (see comments in
        # AsyncHTTPClient.fetch)
        request.headers = httputil.HTTPHeaders(request.headers)
    else:
        request = httpclient.HTTPRequest(url, connect_timeout=connect_timeout)
    request = httpclient._RequestProxy(
        request, httpclient.HTTPRequest._DEFAULTS)
    conn = WebSocketClientConnection(io_loop, request)
    if callback is not None:
        io_loop.add_future(conn.connect_future, callback)
    return conn.connect_future


def _websocket_mask_python(mask, data):
    """Websocket masking function.

    `mask` is a `bytes` object of length 4; `data` is a `bytes` object of any length.
    Returns a `bytes` object of the same length as `data` with the mask applied
    as specified in section 5.3 of RFC 6455.

    This pure-python implementation may be replaced by an optimized version when available.
    """
    mask = array.array("B", mask)
    unmasked = array.array("B", data)
    for i in xrange(len(data)):
        unmasked[i] = unmasked[i] ^ mask[i % 4]
    if hasattr(unmasked, 'tobytes'):
        # tostring was deprecated in py32.  It hasn't been removed,
        # but since we turn on deprecation warnings in our tests
        # we need to use the right one.
        return unmasked.tobytes()
    else:
        return unmasked.tostring()

if (os.environ.get('TORNADO_NO_EXTENSION') or
        os.environ.get('TORNADO_EXTENSION') == '0'):
    # These environment variables exist to make it easier to do performance
    # comparisons; they are not guaranteed to remain supported in the future.
    _websocket_mask = _websocket_mask_python
else:
    try:
        from tornado.speedups import websocket_mask as _websocket_mask
    except ImportError:
        if os.environ.get('TORNADO_EXTENSION') == '1':
            raise
        _websocket_mask = _websocket_mask_python

```
--- END FILE ---

Please first localize the bug based on the issue statement, and then generate *SEARCH/REPLACE* edits to fix the issue.

Every *SEARCH/REPLACE* edit must use this format:
1. The file path
2. The start of search block: <<<<<<< SEARCH
3. A contiguous chunk of lines to search for in the existing source code
4. The dividing line: =======
5. The lines to replace into the source code
6. The end of the replace block: >>>>>>> REPLACE

Here is an example:

```python
### mathweb/flask/app.py
<<<<<<< SEARCH
from flask import Flask
=======
import math
from flask import Flask
>>>>>>> REPLACE
```
</solution>

Please note that the *SEARCH/REPLACE* edit REQUIRES PROPER INDENTATION. If you would like to add the line '        print(x)', you must fully write that out, with all those spaces before the code!
Wrap each *SEARCH/REPLACE* edit in a code block as shown in the example above. If you have multiple *SEARCH/REPLACE* edits, use a separate code block for each one.
user