diff --git a/CHANGES.rst b/CHANGES.rst index e0f2b6d..fc3740c 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,7 +1,3 @@ -========= -Changelog -========= - .. You should *NOT* be adding new change log entries to this file, this file is managed by towncrier. You *may* edit previous change logs to @@ -14,7 +10,482 @@ Changelog .. towncrier release notes start -3.7.3 (2021-02-25) +3.8.6 (2023-10-07) +================== + +Security bugfixes +----------------- + +- Upgraded the vendored copy of llhttp_ to v9.1.3 -- by :user:`Dreamsorcerer` + + Thanks to :user:`kenballus` for reporting this, see + https://github.com/aio-libs/aiohttp/security/advisories/GHSA-pjjw-qhg8-p2p9. + + .. _llhttp: https://llhttp.org + + `#7647 `_ + +- Updated Python parser to comply with RFCs 9110/9112 -- by :user:`Dreamorcerer` + + Thanks to :user:`kenballus` for reporting this, see + https://github.com/aio-libs/aiohttp/security/advisories/GHSA-gfw2-4jvh-wgfg. + + `#7663 `_ + + +Deprecation +----------- + +- Added ``fallback_charset_resolver`` parameter in ``ClientSession`` to allow a user-supplied + character set detection function. + + Character set detection will no longer be included in 3.9 as a default. If this feature is needed, + please use `fallback_charset_resolver `_. + + `#7561 `_ + + +Features +-------- + +- Enabled lenient response parsing for more flexible parsing in the client + (this should resolve some regressions when dealing with badly formatted HTTP responses). -- by :user:`Dreamsorcerer` + + `#7490 `_ + + + +Bugfixes +-------- + +- Fixed ``PermissionError`` when ``.netrc`` is unreadable due to permissions. + + `#7237 `_ + +- Fixed output of parsing errors pointing to a ``\n``. -- by :user:`Dreamsorcerer` + + `#7468 `_ + +- Fixed ``GunicornWebWorker`` max_requests_jitter not working. + + `#7518 `_ + +- Fixed sorting in ``filter_cookies`` to use cookie with longest path. -- by :user:`marq24`. + + `#7577 `_ + +- Fixed display of ``BadStatusLine`` messages from llhttp_. -- by :user:`Dreamsorcerer` + + `#7651 `_ + + +---- + + +3.8.5 (2023-07-19) +================== + +Security bugfixes +----------------- + +- Upgraded the vendored copy of llhttp_ to v8.1.1 -- by :user:`webknjaz` + and :user:`Dreamsorcerer`. + + Thanks to :user:`sethmlarson` for reporting this and providing us with + comprehensive reproducer, workarounds and fixing details! For more + information, see + https://github.com/aio-libs/aiohttp/security/advisories/GHSA-45c4-8wx5-qw6w. + + .. _llhttp: https://llhttp.org + + `#7346 `_ + + +Features +-------- + +- Added information to C parser exceptions to show which character caused the error. -- by :user:`Dreamsorcerer` + + `#7366 `_ + + +Bugfixes +-------- + +- Fixed a transport is :data:`None` error -- by :user:`Dreamsorcerer`. + + `#3355 `_ + + +---- + + +3.8.4 (2023-02-12) +================== + +Bugfixes +-------- + +- Fixed incorrectly overwriting cookies with the same name and domain, but different path. + `#6638 `_ +- Fixed ``ConnectionResetError`` not being raised after client disconnection in SSL environments. + `#7180 `_ + + +---- + + +3.8.3 (2022-09-21) +================== + +.. attention:: + + This is the last :doc:`aiohttp ` release tested under + Python 3.6. The 3.9 stream is dropping it from the CI and the + distribution package metadata. + +Bugfixes +-------- + +- Increased the upper boundary of the :doc:`multidict:index` dependency + to allow for the version 6 -- by :user:`hugovk`. + + It used to be limited below version 7 in :doc:`aiohttp ` v3.8.1 but + was lowered in v3.8.2 via :pr:`6550` and never brought back, causing + problems with dependency pins when upgrading. :doc:`aiohttp ` v3.8.3 + fixes that by recovering the original boundary of ``< 7``. + `#6950 `_ + + +---- + + +3.8.2 (2022-09-20, subsequently yanked on 2022-09-21) +===================================================== + +.. note:: + + This release has some compatibility fixes for Python 3.11 but it may + still have some quirks. Some tests are still flaky in the CI. + +.. caution:: + + This release has been yanked from PyPI. Modern pip will not pick it + up automatically. The reason is that is has ``multidict < 6`` set in + the distribution package metadata (see :pr:`6950`). Please, use + ``aiohttp ~= 3.8.3, != 3.8.1`` instead, if you can. + +Bugfixes +-------- + +- Added support for registering :rfc:`OPTIONS <9110#OPTIONS>` + HTTP method handlers via :py:class:`~aiohttp.web.RouteTableDef`. + `#4663 `_ +- Started supporting :rfc:`authority-form <9112#authority-form>` and + :rfc:`absolute-form <9112#absolute-form>` URLs on the server-side. + `#6227 `_ +- Fixed Python 3.11 incompatibilities by using Cython 0.29.25. + `#6396 `_ +- Extended the ``sock`` argument typing declaration of the + :py:func:`~aiohttp.web.run_app` function as optionally + accepting iterables. + `#6401 `_ +- Fixed a regression where :py:exc:`~asyncio.CancelledError` + occurs on client disconnection. + `#6719 `_ +- Started exporting :py:class:`~aiohttp.web.PrefixedSubAppResource` + under :py:mod:`aiohttp.web` -- by :user:`Dreamsorcerer`. + + This fixes a regression introduced by :pr:`3469`. + `#6889 `_ +- Dropped the :class:`object` type possibility from + the :py:attr:`aiohttp.ClientSession.timeout` + property return type declaration. + `#6917 `_, + `#6923 `_ + + +Improved Documentation +---------------------- + +- Added clarification on configuring the app object with + settings such as a database connection. + `#4137 `_ +- Extended the ``sock`` argument typing declaration of the + :py:func:`~aiohttp.web.run_app` function as optionally + accepting iterables. + `#6401 `_ +- Dropped the :class:`object` type possibility from + the :py:attr:`aiohttp.ClientSession.timeout` + property return type declaration. + `#6917 `_, + `#6923 `_ + + +Deprecations and Removals +------------------------- + +- Dropped Python 3.5 support, :doc:`aiohttp ` only works + under Python 3.6 and higher from now on. + `#4046 `_ + + +Misc +---- + +- Removed a deprecated usage of :py:func:`pytest.warns(None) + ` in tests. + `#6663 `_ +- `#6369 `_, `#6399 `_, `#6550 `_, `#6708 `_, `#6757 `_, `#6857 `_, `#6872 `_. + + +---- + + +3.8.1 (2021-11-14) +================== + +Bugfixes +-------- + +- Fix the error in handling the return value of `getaddrinfo`. + `getaddrinfo` will return an `(int, bytes)` tuple, if CPython could not handle the address family. + It will cause a index out of range error in aiohttp. For example, if user compile CPython with + `--disable-ipv6` option but his system enable the ipv6. + `#5901 `_ +- Do not install "examples" as a top-level package. + `#6189 `_ +- Restored ability to connect IPv6-only host. + `#6195 `_ +- Remove ``Signal`` from ``__all__``, replace ``aiohttp.Signal`` with ``aiosignal.Signal`` in docs + `#6201 `_ +- Made chunked encoding HTTP header check stricter. + `#6305 `_ + + +Improved Documentation +---------------------- + +- update quick starter demo codes. + `#6240 `_ +- Added an explanation of how tiny timeouts affect performance to the client reference document. + `#6274 `_ +- Add flake8-docstrings to flake8 configuration, enable subset of checks. + `#6276 `_ +- Added information on running complex applications with additional tasks/processes -- :user:`Dreamsorcerer`. + `#6278 `_ + + +Misc +---- + +- `#6205 `_ + + +---- + + +3.8.0 (2021-10-31) +================== + +Features +-------- + +- Added a ``GunicornWebWorker`` feature for extending the aiohttp server configuration by allowing the 'wsgi' coroutine to return ``web.AppRunner`` object. + `#2988 `_ +- Switch from ``http-parser`` to ``llhttp`` + `#3561 `_ +- Use Brotli instead of brotlipy + `#3803 `_ +- Disable implicit switch-back to pure python mode. The build fails loudly if aiohttp + cannot be compiled with C Accelerators. Use AIOHTTP_NO_EXTENSIONS=1 to explicitly + disable C Extensions complication and switch to Pure-Python mode. Note that Pure-Python + mode is significantly slower than compiled one. + `#3828 `_ +- Make access log use local time with timezone + `#3853 `_ +- Implemented ``readuntil`` in ``StreamResponse`` + `#4054 `_ +- FileResponse now supports ETag. + `#4594 `_ +- Add a request handler type alias ``aiohttp.typedefs.Handler``. + `#4686 `_ +- ``AioHTTPTestCase`` is more async friendly now. + + For people who use unittest and are used to use :py:exc:`~unittest.TestCase` + it will be easier to write new test cases like the sync version of the :py:exc:`~unittest.TestCase` class, + without using the decorator `@unittest_run_loop`, just `async def test_*`. + The only difference is that for the people using python3.7 and below a new dependency is needed, it is ``asynctestcase``. + `#4700 `_ +- Add validation of HTTP header keys and values to prevent header injection. + `#4818 `_ +- Add predicate to ``AbstractCookieJar.clear``. + Add ``AbstractCookieJar.clear_domain`` to clean all domain and subdomains cookies only. + `#4942 `_ +- Add keepalive_timeout parameter to web.run_app. + `#5094 `_ +- Tracing for client sent headers + `#5105 `_ +- Make type hints for http parser stricter + `#5267 `_ +- Add final declarations for constants. + `#5275 `_ +- Switch to external frozenlist and aiosignal libraries. + `#5293 `_ +- Don't send secure cookies by insecure transports. + + By default, the transport is secure if https or wss scheme is used. + Use `CookieJar(treat_as_secure_origin="http://127.0.0.1")` to override the default security checker. + `#5571 `_ +- Always create a new event loop in ``aiohttp.web.run_app()``. + This adds better compatibility with ``asyncio.run()`` or if trying to run multiple apps in sequence. + `#5572 `_ +- Add ``aiohttp.pytest_plugin.AiohttpClient`` for static typing of pytest plugin. + `#5585 `_ +- Added a ``socket_factory`` argument to ``BaseTestServer``. + `#5844 `_ +- Add compression strategy parameter to enable_compression method. + `#5909 `_ +- Added support for Python 3.10 to Github Actions CI/CD workflows and fix the related deprecation warnings -- :user:`Hanaasagi`. + `#5927 `_ +- Switched ``chardet`` to ``charset-normalizer`` for guessing the HTTP payload body encoding -- :user:`Ousret`. + `#5930 `_ +- Added optional auto_decompress argument for HttpRequestParser + `#5957 `_ +- Added support for HTTPS proxies to the extent CPython's + :py:mod:`asyncio` supports it -- by :user:`bmbouter`, + :user:`jborean93` and :user:`webknjaz`. + `#5992 `_ +- Added ``base_url`` parameter to the initializer of :class:`~aiohttp.ClientSession`. + `#6013 `_ +- Add Trove classifier and create binary wheels for 3.10. -- :user:`hugovk`. + `#6079 `_ +- Started shipping platform-specific wheels with the ``musl`` tag targeting typical Alpine Linux runtimes — :user:`asvetlov`. + `#6139 `_ +- Started shipping platform-specific arm64 wheels for Apple Silicon — :user:`asvetlov`. + `#6139 `_ + + +Bugfixes +-------- + +- Modify _drain_helper() to handle concurrent `await resp.write(...)` or `ws.send_json(...)` calls without race-condition. + `#2934 `_ +- Started using `MultiLoopChildWatcher` when it's available under POSIX while setting up the test I/O loop. + `#3450 `_ +- Only encode content-disposition filename parameter using percent-encoding. + Other parameters are encoded to quoted-string or RFC2231 extended parameter + value. + `#4012 `_ +- Fixed HTTP client requests to honor ``no_proxy`` environment variables. + `#4431 `_ +- Fix supporting WebSockets proxies configured via environment variables. + `#4648 `_ +- Change return type on URLDispatcher to UrlMappingMatchInfo to improve type annotations. + `#4748 `_ +- Ensure a cleanup context is cleaned up even when an exception occurs during startup. + `#4799 `_ +- Added a new exception type for Unix socket client errors which provides a more useful error message. + `#4984 `_ +- Remove Transfer-Encoding and Content-Type headers for 204 in StreamResponse + `#5106 `_ +- Only depend on typing_extensions for Python <3.8 + `#5107 `_ +- Add ABNORMAL_CLOSURE and BAD_GATEWAY to WSCloseCode + `#5192 `_ +- Fix cookies disappearing from HTTPExceptions. + `#5233 `_ +- StaticResource prefixes no longer match URLs with a non-folder prefix. For example ``routes.static('/foo', '/foo')`` no longer matches the URL ``/foobar``. Previously, this would attempt to load the file ``/foo/ar``. + `#5250 `_ +- Acquire the connection before running traces to prevent race condition. + `#5259 `_ +- Add missing slots to ```_RequestContextManager`` and ``_WSRequestContextManager`` + `#5329 `_ +- Ensure sending a zero byte file does not throw an exception (round 2) + `#5380 `_ +- Set "text/plain" when data is an empty string in client requests. + `#5392 `_ +- Stop automatically releasing the ``ClientResponse`` object on calls to the ``ok`` property for the failed requests. + `#5403 `_ +- Include query parameters from `params` keyword argument in tracing `URL`. + `#5432 `_ +- Fix annotations + `#5466 `_ +- Fixed the multipart POST requests processing to always release file + descriptors for the ``tempfile.Temporaryfile``-created + ``_io.BufferedRandom`` instances of files sent within multipart request + bodies via HTTP POST requests -- by :user:`webknjaz`. + `#5494 `_ +- Fix 0 being incorrectly treated as an immediate timeout. + `#5527 `_ +- Fixes failing tests when an environment variable _proxy is set. + `#5554 `_ +- Replace deprecated app handler design in ``tests/autobahn/server.py`` with call to ``web.run_app``; replace deprecated ``aiohttp.ws_connect`` calls in ``tests/autobahn/client.py`` with ``aiohttp.ClienSession.ws_connect``. + `#5606 `_ +- Fixed test for ``HTTPUnauthorized`` that access the ``text`` argument. This is not used in any part of the code, so it's removed now. + `#5657 `_ +- Remove incorrect default from docs + `#5727 `_ +- Remove external test dependency to http://httpbin.org + `#5840 `_ +- Don't cancel current task when entering a cancelled timer. + `#5853 `_ +- Added ``params`` keyword argument to ``ClientSession.ws_connect``. -- :user:`hoh`. + `#5868 `_ +- Uses :py:class:`~asyncio.ThreadedChildWatcher` under POSIX to allow setting up test loop in non-main thread. + `#5877 `_ +- Fix the error in handling the return value of `getaddrinfo`. + `getaddrinfo` will return an `(int, bytes)` tuple, if CPython could not handle the address family. + It will cause a index out of range error in aiohttp. For example, if user compile CPython with + `--disable-ipv6` option but his system enable the ipv6. + `#5901 `_ +- Removed the deprecated ``loop`` argument from the ``asyncio.sleep``/``gather`` calls + `#5905 `_ +- Return ``None`` from ``request.if_modified_since``, ``request.if_unmodified_since``, ``request.if_range`` and ``response.last_modified`` when corresponding http date headers are invalid. + `#5925 `_ +- Fix resetting `SIGCHLD` signals in Gunicorn aiohttp Worker to fix `subprocesses` that capture output having an incorrect `returncode`. + `#6130 `_ +- Raise ``400: Content-Length can't be present with Transfer-Encoding`` if both ``Content-Length`` and ``Transfer-Encoding`` are sent by peer by both C and Python implementations + `#6182 `_ + + +Improved Documentation +---------------------- + +- Refactored OpenAPI/Swagger aiohttp addons, added ``aio-openapi`` + `#5326 `_ +- Fixed docs on request cookies type, so it matches what is actually used in the code (a + read-only dictionary-like object). + `#5725 `_ +- Documented that the HTTP client ``Authorization`` header is removed + on redirects to a different host or protocol. + `#5850 `_ + + +Misc +---- + +- `#3927 `_, `#4247 `_, `#4247 `_, `#5389 `_, `#5457 `_, `#5486 `_, `#5494 `_, `#5515 `_, `#5625 `_, `#5635 `_, `#5648 `_, `#5657 `_, `#5890 `_, `#5914 `_, `#5932 `_, `#6002 `_, `#6045 `_, `#6131 `_, `#6156 `_, `#6165 `_, `#6166 `_ + + +---- + + +3.7.4.post0 (2021-03-06) +======================== + +Misc +---- + +- Bumped upper bound of the ``chardet`` runtime dependency + to allow their v4.0 version stream. + `#5366 `_ + + +---- + + +3.7.4 (2021-02-25) ================== Bugfixes diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index ad63ce9..f8a8df5 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -3,9 +3,11 @@ A. Jesse Jiryu Davis Adam Bannister Adam Cooper +Adam Horacek Adam Mills Adrian Krupa Adrián Chaves +Ahmed Tahri Alan Tse Alec Hanefeld Alejandro Gómez @@ -30,6 +32,7 @@ Alexey Stepanov Amin Etesamian Amit Tulshyan Amy Boyle +Anas El Amraoui Anders Melchiorsen Andrei Ursulenko Andrej Antonov @@ -38,21 +41,27 @@ Andrew Lytvyn Andrew Svetlov Andrew Zhou Andrii Soldatenko +Anes Abismail Antoine Pietri Anton Kasyanov Anton Zhdan-Pushkin Arseny Timoniq Artem Yushkovskiy Arthur Darcet +Austin Scola Ben Bader +Ben Greiner Ben Timby Benedikt Reinartz +Bob Haddleton Boris Feld Boyi Chen Brett Cannon +Brian Bouterse Brian C. Lane Brian Muller Bruce Merry +Bruno Souza Cabral Bryan Kok Bryce Drennan Carl George @@ -67,6 +76,7 @@ Claudiu Popa Colin Dunklau Cong Xu Damien Nadé +Dan King Dan Xu Daniel García Daniel Grossmann-Kavanagh @@ -76,6 +86,7 @@ David Bibb David Michael Brown Denilson Amorim Denis Matiychuk +Denis Moshensky Dennis Kliban Dima Veselov Dimitar Dimitrov @@ -106,6 +117,7 @@ Felix Yan Fernanda Guimarães FichteFoll Florian Scheffler +Franek Magiera Frederik Gladhorn Frederik Peter Aalund Gabriel Tremblay @@ -119,10 +131,13 @@ Gustavo Carneiro Günther Jena Hans Adema Harmon Y. +Harry Liu +Hiroshi Ogawa Hrishikesh Paranjape Hu Bo Hugh Young Hugo Herter +Hugo van Kemenade Hynek Schlawack Igor Alexandrov Igor Davydenko @@ -137,6 +152,8 @@ Jaesung Lee Jake Davis Jakob Ackermann Jakub Wilk +Jan Buchar +Jan Gosmann Jashandeep Sohi Jens Steinhauser Jeonghun Lee @@ -146,12 +163,14 @@ Jesus Cea Jian Zeng Jinkyu Yi Joel Watts +John Parton Jon Nabozny Jonas Krüger Svensson Jonas Obrist Jonathan Wright Jonny Tan Joongi Kim +Jordan Borean Josep Cugat Josh Junon Joshu Coats @@ -186,13 +205,17 @@ Manuel Miranda Marat Sharafutdinov Marco Paolini Mariano Anaya +Mariusz Masztalerczuk +Marko Kohtala Martijn Pieters Martin Melka Martin Richard Mathias Fröjdman Mathieu Dugré +Matthias Marquardt Matthieu Hauglustaine Matthieu Rigal +Meet Mangukiya Michael Ihnatenko Michał Górny Mikhail Burshteyn @@ -208,6 +231,8 @@ Navid Sheikhol Nicolas Braem Nikolay Kim Nikolay Novik +Nikolay Tiunov +Nándor Mátravölgyi Oisin Aylward Olaf Conradi Pahaz Blinov @@ -219,11 +244,14 @@ Paulius Šileikis Paulus Schoutsen Pavel Kamaev Pavel Polyakov +Pavel Sapezhko +Pavol Vargovčík Pawel Kowalski Pawel Miech Pepe Osca Philipp A. Pieter van Beek +Qiao Han Rafael Viotti Raphael Bialon Raúl Cumplido @@ -250,6 +278,7 @@ Stanislav Prokop Stefan Tjarks Stepan Pletnev Stephan Jaensch +Stephen Cirelli Stephen Granade Steven Seguin Sunghyun Hwang @@ -292,6 +321,7 @@ Vladyslav Bondar W. Trevor King Wei Lin Weiwei Wang +Will Fatherley Will McGugan Willem de Groot William Grzybowski @@ -305,8 +335,11 @@ Yegor Roganov Yifei Kong Young-Ho Cha Yuriy Shatrov +Yury Pliner Yury Selivanov Yusuke Tsutsumi +Yuval Ofir +Zeal Wierslee Zlatan Sičanica Марк Коренберг Семён Марьясин diff --git a/LICENSE.txt b/LICENSE.txt index 90c9d01..e497a32 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,192 +1,4 @@ -Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2013-2020 aiohttp maintainers + Copyright aio-libs contributors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/Makefile b/Makefile index 13cd764..98a8812 100644 --- a/Makefile +++ b/Makefile @@ -7,9 +7,10 @@ CYS := $(wildcard aiohttp/*.pyx) $(wildcard aiohttp/*.pyi) $(wildcard aiohttp/* PYXS := $(wildcard aiohttp/*.pyx) CS := $(wildcard aiohttp/*.c) PYS := $(wildcard aiohttp/*.py) -REQS := $(wildcard requirements/*.txt) +IN := doc-spelling lint cython dev ALLS := $(sort $(CYS) $(CS) $(PYS) $(REQS)) + .PHONY: all all: test @@ -45,9 +46,11 @@ endif # Enumerate intermediate files to don't remove them automatically. .SECONDARY: $(call to-hash,$(ALLS)) +.update-pip: + @python -m pip install --upgrade pip -.install-cython: $(call to-hash,requirements/cython.txt) - pip install -r requirements/cython.txt +.install-cython: .update-pip $(call to-hash,requirements/cython.txt) + @python -m pip install -r requirements/cython.txt -c requirements/constraints.txt @touch .install-cython aiohttp/_find_header.c: $(call to-hash,aiohttp/hdrs.py ./tools/gen.py) @@ -55,14 +58,23 @@ aiohttp/_find_header.c: $(call to-hash,aiohttp/hdrs.py ./tools/gen.py) # _find_headers generator creates _headers.pyi as well aiohttp/%.c: aiohttp/%.pyx $(call to-hash,$(CYS)) aiohttp/_find_header.c - cython -3 -o $@ $< -I aiohttp + cython -3 -o $@ $< -I aiohttp -Werror + +vendor/llhttp/node_modules: vendor/llhttp/package.json + cd vendor/llhttp; npm install + +.llhttp-gen: vendor/llhttp/node_modules + $(MAKE) -C vendor/llhttp generate + @touch .llhttp-gen +.PHONY: generate-llhttp +generate-llhttp: .llhttp-gen .PHONY: cythonize cythonize: .install-cython $(PYXS:.pyx=.c) .install-deps: .install-cython $(PYXS:.pyx=.c) $(call to-hash,$(CYS) $(REQS)) - pip install -r requirements/dev.txt + @python -m pip install -r requirements/dev.txt -c requirements/constraints.txt @touch .install-deps .PHONY: lint @@ -74,10 +86,10 @@ fmt format: .PHONY: mypy mypy: - mypy aiohttp + mypy -.develop: .install-deps $(call to-hash,$(PYS) $(CYS) $(CS)) - pip install -e . +.develop: .install-deps generate-llhttp $(call to-hash,$(PYS) $(CYS) $(CS)) + python -m pip install -e . -c requirements/constraints.txt @touch .develop .PHONY: test @@ -92,6 +104,30 @@ vtest: .develop vvtest: .develop @pytest -vv + +define run_tests_in_docker + DOCKER_BUILDKIT=1 docker build --build-arg PYTHON_VERSION=$(1) --build-arg AIOHTTP_NO_EXTENSIONS=$(2) -t "aiohttp-test-$(1)-$(2)" -f tools/testing/Dockerfile . + docker run --rm -ti -v `pwd`:/src -w /src "aiohttp-test-$(1)-$(2)" $(TEST_SPEC) +endef + +.PHONY: test-3.7-no-extensions test-3.7 test-3.8-no-extensions test-3.8 test-3.9-no-extensions test-3.9 test-3.10-no-extensions test-3.10 +test-3.7-no-extensions: + $(call run_tests_in_docker,3.7,y) +test-3.7: + $(call run_tests_in_docker,3.7,n) +test-3.8-no-extensions: + $(call run_tests_in_docker,3.8,y) +test-3.8: + $(call run_tests_in_docker,3.8,n) +test-3.9-no-extensions: + $(call run_tests_in_docker,3.9,y) +test-3.9: + $(call run_tests_in_docker,3.9,n) +test-3.10-no-extensions: + $(call run_tests_in_docker,3.10,y) +test-3.10: + $(call run_tests_in_docker,3.10,n) + .PHONY: clean clean: @rm -rf `find . -name __pycache__` @@ -125,20 +161,28 @@ clean: @rm -rf aiohttp.egg-info @rm -f .install-deps @rm -f .install-cython + @rm -rf vendor/llhttp/node_modules + @rm -f .llhttp-gen + @$(MAKE) -C vendor/llhttp clean .PHONY: doc doc: - @make -C docs html SPHINXOPTS="-W -E" + @make -C docs html SPHINXOPTS="-W --keep-going -n -E" @echo "open file://`pwd`/docs/_build/html/index.html" .PHONY: doc-spelling doc-spelling: - @make -C docs spelling SPHINXOPTS="-W -E" + @make -C docs spelling SPHINXOPTS="-W --keep-going -n -E" + +.PHONY: compile-deps +compile-deps: .update-pip $(REQS) + pip-compile --no-header --allow-unsafe -q --strip-extras \ + -o requirements/constraints.txt \ + requirements/constraints.in .PHONY: install -install: - @pip install -U 'pip' - @pip install -Ur requirements/dev.txt +install: .update-pip + @python -m pip install -r requirements/dev.txt -c requirements/constraints.txt .PHONY: install-dev install-dev: .develop diff --git a/PKG-INFO b/PKG-INFO index 51ea8f8..b2d329d 100644 --- a/PKG-INFO +++ b/PKG-INFO @@ -1,952 +1,254 @@ Metadata-Version: 2.1 Name: aiohttp -Version: 3.7.4 +Version: 3.8.6 Summary: Async http client/server framework (asyncio) Home-page: https://github.com/aio-libs/aiohttp -Author: Nikolay Kim -Author-email: fafhrd91@gmail.com -Maintainer: Nikolay Kim , Andrew Svetlov -Maintainer-email: aio-libs@googlegroups.com +Maintainer: aiohttp team +Maintainer-email: team@aiohttp.org License: Apache 2 -Project-URL: Chat: Gitter, https://gitter.im/aio-libs/Lobby -Project-URL: CI: Azure Pipelines, https://dev.azure.com/aio-libs/aiohttp/_build +Project-URL: Chat: Matrix, https://matrix.to/#/#aio-libs:matrix.org +Project-URL: Chat: Matrix Space, https://matrix.to/#/#aio-libs-space:matrix.org +Project-URL: CI: GitHub Actions, https://github.com/aio-libs/aiohttp/actions?query=workflow%3ACI Project-URL: Coverage: codecov, https://codecov.io/github/aio-libs/aiohttp +Project-URL: Docs: Changelog, https://docs.aiohttp.org/en/stable/changes.html Project-URL: Docs: RTD, https://docs.aiohttp.org Project-URL: GitHub: issues, https://github.com/aio-libs/aiohttp/issues Project-URL: GitHub: repo, https://github.com/aio-libs/aiohttp -Description: ================================== - Async http client/server framework - ================================== - - .. image:: https://raw.githubusercontent.com/aio-libs/aiohttp/master/docs/_static/aiohttp-icon-128x128.png - :height: 64px - :width: 64px - :alt: aiohttp logo - - | - - .. image:: https://github.com/aio-libs/aiohttp/workflows/CI/badge.svg - :target: https://github.com/aio-libs/aiohttp/actions?query=workflow%3ACI - :alt: GitHub Actions status for master branch - - .. image:: https://codecov.io/gh/aio-libs/aiohttp/branch/master/graph/badge.svg - :target: https://codecov.io/gh/aio-libs/aiohttp - :alt: codecov.io status for master branch - - .. image:: https://badge.fury.io/py/aiohttp.svg - :target: https://pypi.org/project/aiohttp - :alt: Latest PyPI package version - - .. image:: https://readthedocs.org/projects/aiohttp/badge/?version=latest - :target: https://docs.aiohttp.org/ - :alt: Latest Read The Docs - - .. image:: https://img.shields.io/discourse/status?server=https%3A%2F%2Faio-libs.discourse.group - :target: https://aio-libs.discourse.group - :alt: Discourse status - - .. image:: https://badges.gitter.im/Join%20Chat.svg - :target: https://gitter.im/aio-libs/Lobby - :alt: Chat on Gitter - - - Key Features - ============ - - - Supports both client and server side of HTTP protocol. - - Supports both client and server Web-Sockets out-of-the-box and avoids - Callback Hell. - - Provides Web-server with middlewares and plugable routing. - - - Getting started - =============== - - Client - ------ - - To get something from the web: - - .. code-block:: python - - import aiohttp - import asyncio - - async def main(): - - async with aiohttp.ClientSession() as session: - async with session.get('http://python.org') as response: - - print("Status:", response.status) - print("Content-type:", response.headers['content-type']) - - html = await response.text() - print("Body:", html[:15], "...") - - loop = asyncio.get_event_loop() - loop.run_until_complete(main()) - - This prints: - - .. code-block:: - - Status: 200 - Content-type: text/html; charset=utf-8 - Body: ... - - Coming from `requests `_ ? Read `why we need so many lines `_. - - Server - ------ - - An example using a simple server: - - .. code-block:: python - - # examples/server_simple.py - from aiohttp import web - - async def handle(request): - name = request.match_info.get('name', "Anonymous") - text = "Hello, " + name - return web.Response(text=text) - - async def wshandle(request): - ws = web.WebSocketResponse() - await ws.prepare(request) - - async for msg in ws: - if msg.type == web.WSMsgType.text: - await ws.send_str("Hello, {}".format(msg.data)) - elif msg.type == web.WSMsgType.binary: - await ws.send_bytes(msg.data) - elif msg.type == web.WSMsgType.close: - break - - return ws - - - app = web.Application() - app.add_routes([web.get('/', handle), - web.get('/echo', wshandle), - web.get('/{name}', handle)]) - - if __name__ == '__main__': - web.run_app(app) - - - Documentation - ============= - - https://aiohttp.readthedocs.io/ - - - Demos - ===== - - https://github.com/aio-libs/aiohttp-demos - - - External links - ============== - - * `Third party libraries - `_ - * `Built with aiohttp - `_ - * `Powered by aiohttp - `_ - - Feel free to make a Pull Request for adding your link to these pages! - - - Communication channels - ====================== - - *aio-libs discourse group*: https://aio-libs.discourse.group - - *gitter chat* https://gitter.im/aio-libs/Lobby - - We support `Stack Overflow - `_. - Please add *aiohttp* tag to your question there. - - Requirements - ============ - - - Python >= 3.6 - - async-timeout_ - - attrs_ - - chardet_ - - multidict_ - - yarl_ - - Optionally you may install the cChardet_ and aiodns_ libraries (highly - recommended for sake of speed). - - .. _chardet: https://pypi.python.org/pypi/chardet - .. _aiodns: https://pypi.python.org/pypi/aiodns - .. _attrs: https://github.com/python-attrs/attrs - .. _multidict: https://pypi.python.org/pypi/multidict - .. _yarl: https://pypi.python.org/pypi/yarl - .. _async-timeout: https://pypi.python.org/pypi/async_timeout - .. _cChardet: https://pypi.python.org/pypi/cchardet - - License - ======= - - ``aiohttp`` is offered under the Apache 2 license. - - - Keepsafe - ======== - - The aiohttp community would like to thank Keepsafe - (https://www.getkeepsafe.com) for its support in the early days of - the project. - - - Source code - =========== - - The latest developer version is available in a GitHub repository: - https://github.com/aio-libs/aiohttp - - Benchmarks - ========== - - If you are interested in efficiency, the AsyncIO community maintains a - list of benchmarks on the official wiki: - https://github.com/python/asyncio/wiki/Benchmarks - - ========= - Changelog - ========= - - .. - You should *NOT* be adding new change log entries to this file, this - file is managed by towncrier. You *may* edit previous change logs to - fix problems like typo corrections or such. - To add a new change log entry, please see - https://pip.pypa.io/en/latest/development/#adding-a-news-entry - we named the news folder "changes". - - WARNING: Don't drop the next directive! - - .. towncrier release notes start - - 3.7.3 (2021-02-25) - ================== - - Bugfixes - -------- - - - **(SECURITY BUG)** Started preventing open redirects in the - ``aiohttp.web.normalize_path_middleware`` middleware. For - more details, see - https://github.com/aio-libs/aiohttp/security/advisories/GHSA-v6wp-4m6f-gcjg. - - Thanks to `Beast Glatisant `__ for - finding the first instance of this issue and `Jelmer Vernooij - `__ for reporting and tracking it down - in aiohttp. - `#5497 `_ - - Fix interpretation difference of the pure-Python and the Cython-based - HTTP parsers construct a ``yarl.URL`` object for HTTP request-target. - - Before this fix, the Python parser would turn the URI's absolute-path - for ``//some-path`` into ``/`` while the Cython code preserved it as - ``//some-path``. Now, both do the latter. - `#5498 `_ - - - ---- - - - 3.7.3 (2020-11-18) - ================== - - Features - -------- - - - Use Brotli instead of brotlipy - `#3803 `_ - - Made exceptions pickleable. Also changed the repr of some exceptions. - `#4077 `_ - - - Bugfixes - -------- - - - Raise a ClientResponseError instead of an AssertionError for a blank - HTTP Reason Phrase. - `#3532 `_ - - Fix ``web_middlewares.normalize_path_middleware`` behavior for patch without slash. - `#3669 `_ - - Fix overshadowing of overlapped sub-applications prefixes. - `#3701 `_ - - Make `BaseConnector.close()` a coroutine and wait until the client closes all connections. Drop deprecated "with Connector():" syntax. - `#3736 `_ - - Reset the ``sock_read`` timeout each time data is received for a ``aiohttp.client`` response. - `#3808 `_ - - Fixed type annotation for add_view method of UrlDispatcher to accept any subclass of View - `#3880 `_ - - Fixed querying the address families from DNS that the current host supports. - `#5156 `_ - - Change return type of MultipartReader.__aiter__() and BodyPartReader.__aiter__() to AsyncIterator. - `#5163 `_ - - Provide x86 Windows wheels. - `#5230 `_ - - - Improved Documentation - ---------------------- - - - Add documentation for ``aiohttp.web.FileResponse``. - `#3958 `_ - - Removed deprecation warning in tracing example docs - `#3964 `_ - - Fixed wrong "Usage" docstring of ``aiohttp.client.request``. - `#4603 `_ - - Add aiohttp-pydantic to third party libraries - `#5228 `_ - - - Misc - ---- - - - `#4102 `_ - - - ---- - - - 3.7.2 (2020-10-27) - ================== - - Bugfixes - -------- - - - Fixed static files handling for loops without ``.sendfile()`` support - `#5149 `_ - - - ---- - - - 3.7.1 (2020-10-25) - ================== - - Bugfixes - -------- - - - Fixed a type error caused by the conditional import of `Protocol`. - `#5111 `_ - - Server doesn't send Content-Length for 1xx or 204 - `#4901 `_ - - Fix run_app typing - `#4957 `_ - - Always require ``typing_extensions`` library. - `#5107 `_ - - Fix a variable-shadowing bug causing `ThreadedResolver.resolve` to - return the resolved IP as the ``hostname`` in each record, which prevented - validation of HTTPS connections. - `#5110 `_ - - Added annotations to all public attributes. - `#5115 `_ - - Fix flaky test_when_timeout_smaller_second - `#5116 `_ - - Ensure sending a zero byte file does not throw an exception - `#5124 `_ - - Fix a bug in ``web.run_app()`` about Python version checking on Windows - `#5127 `_ - - - ---- - - - 3.7.0 (2020-10-24) - ================== - - Features - -------- - - - Response headers are now prepared prior to running ``on_response_prepare`` hooks, directly before headers are sent to the client. - `#1958 `_ - - Add a ``quote_cookie`` option to ``CookieJar``, a way to skip quotation wrapping of cookies containing special characters. - `#2571 `_ - - Call ``AccessLogger.log`` with the current exception available from ``sys.exc_info()``. - `#3557 `_ - - `web.UrlDispatcher.add_routes` and `web.Application.add_routes` return a list - of registered `AbstractRoute` instances. `AbstractRouteDef.register` (and all - subclasses) return a list of registered resources registered resource. - `#3866 `_ - - Added properties of default ClientSession params to ClientSession class so it is available for introspection - `#3882 `_ - - Don't cancel web handler on peer disconnection, raise `OSError` on reading/writing instead. - `#4080 `_ - - Implement BaseRequest.get_extra_info() to access a protocol transports' extra info. - `#4189 `_ - - Added `ClientSession.timeout` property. - `#4191 `_ - - allow use of SameSite in cookies. - `#4224 `_ - - Use ``loop.sendfile()`` instead of custom implementation if available. - `#4269 `_ - - Apply SO_REUSEADDR to test server's socket. - `#4393 `_ - - Use .raw_host instead of slower .host in client API - `#4402 `_ - - Allow configuring the buffer size of input stream by passing ``read_bufsize`` argument. - `#4453 `_ - - Pass tests on Python 3.8 for Windows. - `#4513 `_ - - Add `method` and `url` attributes to `TraceRequestChunkSentParams` and `TraceResponseChunkReceivedParams`. - `#4674 `_ - - Add ClientResponse.ok property for checking status code under 400. - `#4711 `_ - - Don't ceil timeouts that are smaller than 5 seconds. - `#4850 `_ - - TCPSite now listens by default on all interfaces instead of just IPv4 when `None` is passed in as the host. - `#4894 `_ - - Bump ``http_parser`` to 2.9.4 - `#5070 `_ - - - Bugfixes - -------- - - - Fix keepalive connections not being closed in time - `#3296 `_ - - Fix failed websocket handshake leaving connection hanging. - `#3380 `_ - - Fix tasks cancellation order on exit. The run_app task needs to be cancelled first for cleanup hooks to run with all tasks intact. - `#3805 `_ - - Don't start heartbeat until _writer is set - `#4062 `_ - - Fix handling of multipart file uploads without a content type. - `#4089 `_ - - Preserve view handler function attributes across middlewares - `#4174 `_ - - Fix the string representation of ``ServerDisconnectedError``. - `#4175 `_ - - Raising RuntimeError when trying to get encoding from not read body - `#4214 `_ - - Remove warning messages from noop. - `#4282 `_ - - Raise ClientPayloadError if FormData re-processed. - `#4345 `_ - - Fix a warning about unfinished task in ``web_protocol.py`` - `#4408 `_ - - Fixed 'deflate' compression. According to RFC 2616 now. - `#4506 `_ - - Fixed OverflowError on platforms with 32-bit time_t - `#4515 `_ - - Fixed request.body_exists returns wrong value for methods without body. - `#4528 `_ - - Fix connecting to link-local IPv6 addresses. - `#4554 `_ - - Fix a problem with connection waiters that are never awaited. - `#4562 `_ - - Always make sure transport is not closing before reuse a connection. - - Reuse a protocol based on keepalive in headers is unreliable. - For example, uWSGI will not support keepalive even it serves a - HTTP 1.1 request, except explicitly configure uWSGI with a - ``--http-keepalive`` option. - - Servers designed like uWSGI could cause aiohttp intermittently - raise a ConnectionResetException when the protocol poll runs - out and some protocol is reused. - `#4587 `_ - - Handle the last CRLF correctly even if it is received via separate TCP segment. - `#4630 `_ - - Fix the register_resource function to validate route name before splitting it so that route name can include python keywords. - `#4691 `_ - - Improve typing annotations for ``web.Request``, ``aiohttp.ClientResponse`` and - ``multipart`` module. - `#4736 `_ - - Fix resolver task is not awaited when connector is cancelled - `#4795 `_ - - Fix a bug "Aiohttp doesn't return any error on invalid request methods" - `#4798 `_ - - Fix HEAD requests for static content. - `#4809 `_ - - Fix incorrect size calculation for memoryview - `#4890 `_ - - Add HTTPMove to _all__. - `#4897 `_ - - Fixed the type annotations in the ``tracing`` module. - `#4912 `_ - - Fix typing for multipart ``__aiter__``. - `#4931 `_ - - Fix for race condition on connections in BaseConnector that leads to exceeding the connection limit. - `#4936 `_ - - Add forced UTF-8 encoding for ``application/rdap+json`` responses. - `#4938 `_ - - Fix inconsistency between Python and C http request parsers in parsing pct-encoded URL. - `#4972 `_ - - Fix connection closing issue in HEAD request. - `#5012 `_ - - Fix type hint on BaseRunner.addresses (from ``List[str]`` to ``List[Any]``) - `#5086 `_ - - Make `web.run_app()` more responsive to Ctrl+C on Windows for Python < 3.8. It slightly - increases CPU load as a side effect. - `#5098 `_ - - - Improved Documentation - ---------------------- - - - Fix example code in client quick-start - `#3376 `_ - - Updated the docs so there is no contradiction in ``ttl_dns_cache`` default value - `#3512 `_ - - Add 'Deploy with SSL' to docs. - `#4201 `_ - - Change typing of the secure argument on StreamResponse.set_cookie from ``Optional[str]`` to ``Optional[bool]`` - `#4204 `_ - - Changes ``ttl_dns_cache`` type from int to Optional[int]. - `#4270 `_ - - Simplify README hello word example and add a documentation page for people coming from requests. - `#4272 `_ - - Improve some code examples in the documentation involving websockets and starting a simple HTTP site with an AppRunner. - `#4285 `_ - - Fix typo in code example in Multipart docs - `#4312 `_ - - Fix code example in Multipart section. - `#4314 `_ - - Update contributing guide so new contributors read the most recent version of that guide. Update command used to create test coverage reporting. - `#4810 `_ - - Spelling: Change "canonize" to "canonicalize". - `#4986 `_ - - Add ``aiohttp-sse-client`` library to third party usage list. - `#5084 `_ - - - Misc - ---- - - - `#2856 `_, `#4218 `_, `#4250 `_ - - - ---- - - - 3.6.3 (2020-10-12) - ================== - - Bugfixes - -------- - - - Pin yarl to ``<1.6.0`` to avoid buggy behavior that will be fixed by the next aiohttp - release. - - 3.6.2 (2019-10-09) - ================== - - Features - -------- - - - Made exceptions pickleable. Also changed the repr of some exceptions. - `#4077 `_ - - Use ``Iterable`` type hint instead of ``Sequence`` for ``Application`` *middleware* - parameter. `#4125 `_ - - - Bugfixes - -------- - - - Reset the ``sock_read`` timeout each time data is received for a - ``aiohttp.ClientResponse``. `#3808 - `_ - - Fix handling of expired cookies so they are not stored in CookieJar. - `#4063 `_ - - Fix misleading message in the string representation of ``ClientConnectorError``; - ``self.ssl == None`` means default SSL context, not SSL disabled `#4097 - `_ - - Don't clobber HTTP status when using FileResponse. - `#4106 `_ - - - Improved Documentation - ---------------------- - - - Added minimal required logging configuration to logging documentation. - `#2469 `_ - - Update docs to reflect proxy support. - `#4100 `_ - - Fix typo in code example in testing docs. - `#4108 `_ - - - Misc - ---- - - - `#4102 `_ - - - ---- - - - 3.6.1 (2019-09-19) - ================== - - Features - -------- - - - Compatibility with Python 3.8. - `#4056 `_ - - - Bugfixes - -------- - - - correct some exception string format - `#4068 `_ - - Emit a warning when ``ssl.OP_NO_COMPRESSION`` is - unavailable because the runtime is built against - an outdated OpenSSL. - `#4052 `_ - - Update multidict requirement to >= 4.5 - `#4057 `_ - - - Improved Documentation - ---------------------- - - - Provide pytest-aiohttp namespace for pytest fixtures in docs. - `#3723 `_ - - - ---- - - - 3.6.0 (2019-09-06) - ================== - - Features - -------- - - - Add support for Named Pipes (Site and Connector) under Windows. This feature requires - Proactor event loop to work. `#3629 - `_ - - Removed ``Transfer-Encoding: chunked`` header from websocket responses to be - compatible with more http proxy servers. `#3798 - `_ - - Accept non-GET request for starting websocket handshake on server side. - `#3980 `_ - - - Bugfixes - -------- - - - Raise a ClientResponseError instead of an AssertionError for a blank - HTTP Reason Phrase. - `#3532 `_ - - Fix an issue where cookies would sometimes not be set during a redirect. - `#3576 `_ - - Change normalize_path_middleware to use 308 redirect instead of 301. - - This behavior should prevent clients from being unable to use PUT/POST - methods on endpoints that are redirected because of a trailing slash. - `#3579 `_ - - Drop the processed task from ``all_tasks()`` list early. It prevents logging about a - task with unhandled exception when the server is used in conjunction with - ``asyncio.run()``. `#3587 `_ - - ``Signal`` type annotation changed from ``Signal[Callable[['TraceConfig'], - Awaitable[None]]]`` to ``Signal[Callable[ClientSession, SimpleNamespace, ...]``. - `#3595 `_ - - Use sanitized URL as Location header in redirects - `#3614 `_ - - Improve typing annotations for multipart.py along with changes required - by mypy in files that references multipart.py. - `#3621 `_ - - Close session created inside ``aiohttp.request`` when unhandled exception occurs - `#3628 `_ - - Cleanup per-chunk data in generic data read. Memory leak fixed. - `#3631 `_ - - Use correct type for add_view and family - `#3633 `_ - - Fix _keepalive field in __slots__ of ``RequestHandler``. - `#3644 `_ - - Properly handle ConnectionResetError, to silence the "Cannot write to closing - transport" exception when clients disconnect uncleanly. - `#3648 `_ - - Suppress pytest warnings due to ``test_utils`` classes - `#3660 `_ - - Fix overshadowing of overlapped sub-application prefixes. - `#3701 `_ - - Fixed return type annotation for WSMessage.json() - `#3720 `_ - - Properly expose TooManyRedirects publicly as documented. - `#3818 `_ - - Fix missing brackets for IPv6 in proxy CONNECT request - `#3841 `_ - - Make the signature of ``aiohttp.test_utils.TestClient.request`` match - ``asyncio.ClientSession.request`` according to the docs `#3852 - `_ - - Use correct style for re-exported imports, makes mypy ``--strict`` mode happy. - `#3868 `_ - - Fixed type annotation for add_view method of UrlDispatcher to accept any subclass of - View `#3880 `_ - - Made cython HTTP parser set Reason-Phrase of the response to an empty string if it is - missing. `#3906 `_ - - Add URL to the string representation of ClientResponseError. - `#3959 `_ - - Accept ``istr`` keys in ``LooseHeaders`` type hints. - `#3976 `_ - - Fixed race conditions in _resolve_host caching and throttling when tracing is enabled. - `#4013 `_ - - For URLs like "unix://localhost/..." set Host HTTP header to "localhost" instead of - "localhost:None". `#4039 `_ - - - Improved Documentation - ---------------------- - - - Modify documentation for Background Tasks to remove deprecated usage of event loop. - `#3526 `_ - - use ``if __name__ == '__main__':`` in server examples. - `#3775 `_ - - Update documentation reference to the default access logger. - `#3783 `_ - - Improve documentation for ``web.BaseRequest.path`` and ``web.BaseRequest.raw_path``. - `#3791 `_ - - Removed deprecation warning in tracing example docs - `#3964 `_ - - - ---- - - - 3.5.4 (2019-01-12) - ================== - - Bugfixes - -------- - - - Fix stream ``.read()`` / ``.readany()`` / ``.iter_any()`` which used to return a - partial content only in case of compressed content - `#3525 `_ - - - 3.5.3 (2019-01-10) - ================== - - Bugfixes - -------- - - - Fix type stubs for ``aiohttp.web.run_app(access_log=True)`` and fix edge case of - ``access_log=True`` and the event loop being in debug mode. `#3504 - `_ - - Fix ``aiohttp.ClientTimeout`` type annotations to accept ``None`` for fields - `#3511 `_ - - Send custom per-request cookies even if session jar is empty - `#3515 `_ - - Restore Linux binary wheels publishing on PyPI - - ---- - - - 3.5.2 (2019-01-08) - ================== - - Features - -------- - - - ``FileResponse`` from ``web_fileresponse.py`` uses a ``ThreadPoolExecutor`` to work - with files asynchronously. I/O based payloads from ``payload.py`` uses a - ``ThreadPoolExecutor`` to work with I/O objects asynchronously. `#3313 - `_ - - Internal Server Errors in plain text if the browser does not support HTML. - `#3483 `_ - - - Bugfixes - -------- - - - Preserve MultipartWriter parts headers on write. Refactor the way how - ``Payload.headers`` are handled. Payload instances now always have headers and - Content-Type defined. Fix Payload Content-Disposition header reset after initial - creation. `#3035 `_ - - Log suppressed exceptions in ``GunicornWebWorker``. - `#3464 `_ - - Remove wildcard imports. - `#3468 `_ - - Use the same task for app initialization and web server handling in gunicorn workers. - It allows to use Python3.7 context vars smoothly. - `#3471 `_ - - Fix handling of chunked+gzipped response when first chunk does not give uncompressed - data `#3477 `_ - - Replace ``collections.MutableMapping`` with ``collections.abc.MutableMapping`` to - avoid a deprecation warning. `#3480 - `_ - - ``Payload.size`` type annotation changed from ``Optional[float]`` to - ``Optional[int]``. `#3484 `_ - - Ignore done tasks when cancels pending activities on ``web.run_app`` finalization. - `#3497 `_ - - - Improved Documentation - ---------------------- - - - Add documentation for ``aiohttp.web.HTTPException``. - `#3490 `_ - - - Misc - ---- - - - `#3487 `_ - - - ---- - - - 3.5.1 (2018-12-24) - ==================== - - - Fix a regression about ``ClientSession._requote_redirect_url`` modification in debug - mode. - - 3.5.0 (2018-12-22) - ==================== - - Features - -------- - - - The library type annotations are checked in strict mode now. - - Add support for setting cookies for individual request (`#2387 - `_) - - Application.add_domain implementation (`#2809 - `_) - - The default ``app`` in the request returned by ``test_utils.make_mocked_request`` can - now have objects assigned to it and retrieved using the ``[]`` operator. (`#3174 - `_) - - Make ``request.url`` accessible when transport is closed. (`#3177 - `_) - - Add ``zlib_executor_size`` argument to ``Response`` constructor to allow compression - to run in a background executor to avoid blocking the main thread and potentially - triggering health check failures. (`#3205 - `_) - - Enable users to set ``ClientTimeout`` in ``aiohttp.request`` (`#3213 - `_) - - Don't raise a warning if ``NETRC`` environment variable is not set and ``~/.netrc`` - file doesn't exist. (`#3267 `_) - - Add default logging handler to web.run_app If the ``Application.debug``` flag is set - and the default logger ``aiohttp.access`` is used, access logs will now be output - using a *stderr* ``StreamHandler`` if no handlers are attached. Furthermore, if the - default logger has no log level set, the log level will be set to ``DEBUG``. (`#3324 - `_) - - Add method argument to ``session.ws_connect()``. Sometimes server API requires a - different HTTP method for WebSocket connection establishment. For example, ``Docker - exec`` needs POST. (`#3378 `_) - - Create a task per request handling. (`#3406 - `_) - - - Bugfixes - -------- - - - Enable passing ``access_log_class`` via ``handler_args`` (`#3158 - `_) - - Return empty bytes with end-of-chunk marker in empty stream reader. (`#3186 - `_) - - Accept ``CIMultiDictProxy`` instances for ``headers`` argument in ``web.Response`` - constructor. (`#3207 `_) - - Don't uppercase HTTP method in parser (`#3233 - `_) - - Make method match regexp RFC-7230 compliant (`#3235 - `_) - - Add ``app.pre_frozen`` state to properly handle startup signals in - sub-applications. (`#3237 `_) - - Enhanced parsing and validation of helpers.BasicAuth.decode. (`#3239 - `_) - - Change imports from collections module in preparation for 3.8. (`#3258 - `_) - - Ensure Host header is added first to ClientRequest to better replicate browser (`#3265 - `_) - - Fix forward compatibility with Python 3.8: importing ABCs directly from the - collections module will not be supported anymore. (`#3273 - `_) - - Keep the query string by ``normalize_path_middleware``. (`#3278 - `_) - - Fix missing parameter ``raise_for_status`` for aiohttp.request() (`#3290 - `_) - - Bracket IPv6 addresses in the HOST header (`#3304 - `_) - - Fix default message for server ping and pong frames. (`#3308 - `_) - - Fix tests/test_connector.py typo and tests/autobahn/server.py duplicate loop - def. (`#3337 `_) - - Fix false-negative indicator end_of_HTTP_chunk in StreamReader.readchunk function - (`#3361 `_) - - Release HTTP response before raising status exception (`#3364 - `_) - - Fix task cancellation when ``sendfile()`` syscall is used by static file - handling. (`#3383 `_) - - Fix stack trace for ``asyncio.TimeoutError`` which was not logged, when it is caught - in the handler. (`#3414 `_) - - - Improved Documentation - ---------------------- - - - Improve documentation of ``Application.make_handler`` parameters. (`#3152 - `_) - - Fix BaseRequest.raw_headers doc. (`#3215 - `_) - - Fix typo in TypeError exception reason in ``web.Application._handle`` (`#3229 - `_) - - Make server access log format placeholder %b documentation reflect - behavior and docstring. (`#3307 `_) - - - Deprecations and Removals - ------------------------- - - - Deprecate modification of ``session.requote_redirect_url`` (`#2278 - `_) - - Deprecate ``stream.unread_data()`` (`#3260 - `_) - - Deprecated use of boolean in ``resp.enable_compression()`` (`#3318 - `_) - - Encourage creation of aiohttp public objects inside a coroutine (`#3331 - `_) - - Drop dead ``Connection.detach()`` and ``Connection.writer``. Both methods were broken - for more than 2 years. (`#3358 `_) - - Deprecate ``app.loop``, ``request.loop``, ``client.loop`` and ``connector.loop`` - properties. (`#3374 `_) - - Deprecate explicit debug argument. Use asyncio debug mode instead. (`#3381 - `_) - - Deprecate body parameter in HTTPException (and derived classes) constructor. (`#3385 - `_) - - Deprecate bare connector close, use ``async with connector:`` and ``await - connector.close()`` instead. (`#3417 - `_) - - Deprecate obsolete ``read_timeout`` and ``conn_timeout`` in ``ClientSession`` - constructor. (`#3438 `_) - - - Misc - ---- - - - #3341, #3351 -Platform: UNKNOWN -Classifier: License :: OSI Approved :: Apache Software License +Classifier: Development Status :: 5 - Production/Stable +Classifier: Framework :: AsyncIO Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: Apache Software License +Classifier: Operating System :: POSIX +Classifier: Operating System :: MacOS :: MacOS X +Classifier: Operating System :: Microsoft :: Windows Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 -Classifier: Development Status :: 5 - Production/Stable -Classifier: Operating System :: POSIX -Classifier: Operating System :: MacOS :: MacOS X -Classifier: Operating System :: Microsoft :: Windows +Classifier: Programming Language :: Python :: 3.10 Classifier: Topic :: Internet :: WWW/HTTP -Classifier: Framework :: AsyncIO Requires-Python: >=3.6 +Description-Content-Type: text/x-rst +License-File: LICENSE.txt +Requires-Dist: attrs>=17.3.0 +Requires-Dist: charset-normalizer<4.0,>=2.0 +Requires-Dist: multidict<7.0,>=4.5 +Requires-Dist: async_timeout<5.0,>=4.0.0a3 +Requires-Dist: asynctest==0.13.0; python_version < "3.8" +Requires-Dist: yarl<2.0,>=1.0 +Requires-Dist: idna-ssl>=1.0; python_version < "3.7" +Requires-Dist: typing_extensions>=3.7.4; python_version < "3.8" +Requires-Dist: frozenlist>=1.1.1 +Requires-Dist: aiosignal>=1.1.2 Provides-Extra: speedups +Requires-Dist: aiodns; extra == "speedups" +Requires-Dist: Brotli; extra == "speedups" +Requires-Dist: cchardet; python_version < "3.10" and extra == "speedups" + +================================== +Async http client/server framework +================================== + +.. image:: https://raw.githubusercontent.com/aio-libs/aiohttp/master/docs/aiohttp-plain.svg + :height: 64px + :width: 64px + :alt: aiohttp logo + +| + +.. image:: https://github.com/aio-libs/aiohttp/workflows/CI/badge.svg + :target: https://github.com/aio-libs/aiohttp/actions?query=workflow%3ACI + :alt: GitHub Actions status for master branch + +.. image:: https://codecov.io/gh/aio-libs/aiohttp/branch/master/graph/badge.svg + :target: https://codecov.io/gh/aio-libs/aiohttp + :alt: codecov.io status for master branch + +.. image:: https://badge.fury.io/py/aiohttp.svg + :target: https://pypi.org/project/aiohttp + :alt: Latest PyPI package version + +.. image:: https://readthedocs.org/projects/aiohttp/badge/?version=latest + :target: https://docs.aiohttp.org/ + :alt: Latest Read The Docs + +.. image:: https://img.shields.io/matrix/aio-libs:matrix.org?label=Discuss%20on%20Matrix%20at%20%23aio-libs%3Amatrix.org&logo=matrix&server_fqdn=matrix.org&style=flat + :target: https://matrix.to/#/%23aio-libs:matrix.org + :alt: Matrix Room — #aio-libs:matrix.org + +.. image:: https://img.shields.io/matrix/aio-libs-space:matrix.org?label=Discuss%20on%20Matrix%20at%20%23aio-libs-space%3Amatrix.org&logo=matrix&server_fqdn=matrix.org&style=flat + :target: https://matrix.to/#/%23aio-libs-space:matrix.org + :alt: Matrix Space — #aio-libs-space:matrix.org + + +Key Features +============ + +- Supports both client and server side of HTTP protocol. +- Supports both client and server Web-Sockets out-of-the-box and avoids + Callback Hell. +- Provides Web-server with middlewares and plugable routing. + + +Getting started +=============== + +Client +------ + +To get something from the web: + +.. code-block:: python + + import aiohttp + import asyncio + + async def main(): + + async with aiohttp.ClientSession() as session: + async with session.get('http://python.org') as response: + + print("Status:", response.status) + print("Content-type:", response.headers['content-type']) + + html = await response.text() + print("Body:", html[:15], "...") + + asyncio.run(main()) + +This prints: + +.. code-block:: + + Status: 200 + Content-type: text/html; charset=utf-8 + Body: ... + +Coming from `requests `_ ? Read `why we need so many lines `_. + +Server +------ + +An example using a simple server: + +.. code-block:: python + + # examples/server_simple.py + from aiohttp import web + + async def handle(request): + name = request.match_info.get('name', "Anonymous") + text = "Hello, " + name + return web.Response(text=text) + + async def wshandle(request): + ws = web.WebSocketResponse() + await ws.prepare(request) + + async for msg in ws: + if msg.type == web.WSMsgType.text: + await ws.send_str("Hello, {}".format(msg.data)) + elif msg.type == web.WSMsgType.binary: + await ws.send_bytes(msg.data) + elif msg.type == web.WSMsgType.close: + break + + return ws + + + app = web.Application() + app.add_routes([web.get('/', handle), + web.get('/echo', wshandle), + web.get('/{name}', handle)]) + + if __name__ == '__main__': + web.run_app(app) + + +Documentation +============= + +https://aiohttp.readthedocs.io/ + + +Demos +===== + +https://github.com/aio-libs/aiohttp-demos + + +External links +============== + +* `Third party libraries + `_ +* `Built with aiohttp + `_ +* `Powered by aiohttp + `_ + +Feel free to make a Pull Request for adding your link to these pages! + + +Communication channels +====================== + +*aio-libs discourse group*: https://aio-libs.discourse.group + +*gitter chat* https://gitter.im/aio-libs/Lobby + +We support `Stack Overflow +`_. +Please add *aiohttp* tag to your question there. + +Requirements +============ + +- Python >= 3.6 +- async-timeout_ +- attrs_ +- charset-normalizer_ +- multidict_ +- yarl_ +- frozenlist_ + +Optionally you may install the cChardet_ and aiodns_ libraries (highly +recommended for sake of speed). + +.. _charset-normalizer: https://pypi.org/project/charset-normalizer +.. _aiodns: https://pypi.python.org/pypi/aiodns +.. _attrs: https://github.com/python-attrs/attrs +.. _multidict: https://pypi.python.org/pypi/multidict +.. _frozenlist: https://pypi.org/project/frozenlist/ +.. _yarl: https://pypi.python.org/pypi/yarl +.. _async-timeout: https://pypi.python.org/pypi/async_timeout +.. _cChardet: https://pypi.python.org/pypi/cchardet + +License +======= + +``aiohttp`` is offered under the Apache 2 license. + + +Keepsafe +======== + +The aiohttp community would like to thank Keepsafe +(https://www.getkeepsafe.com) for its support in the early days of +the project. + + +Source code +=========== + +The latest developer version is available in a GitHub repository: +https://github.com/aio-libs/aiohttp + +Benchmarks +========== + +If you are interested in efficiency, the AsyncIO community maintains a +list of benchmarks on the official wiki: +https://github.com/python/asyncio/wiki/Benchmarks diff --git a/README.rst b/README.rst index 338adbc..5841cbc 100644 --- a/README.rst +++ b/README.rst @@ -2,7 +2,7 @@ Async http client/server framework ================================== -.. image:: https://raw.githubusercontent.com/aio-libs/aiohttp/master/docs/_static/aiohttp-icon-128x128.png +.. image:: https://raw.githubusercontent.com/aio-libs/aiohttp/master/docs/aiohttp-plain.svg :height: 64px :width: 64px :alt: aiohttp logo @@ -25,13 +25,13 @@ Async http client/server framework :target: https://docs.aiohttp.org/ :alt: Latest Read The Docs -.. image:: https://img.shields.io/discourse/status?server=https%3A%2F%2Faio-libs.discourse.group - :target: https://aio-libs.discourse.group - :alt: Discourse status +.. image:: https://img.shields.io/matrix/aio-libs:matrix.org?label=Discuss%20on%20Matrix%20at%20%23aio-libs%3Amatrix.org&logo=matrix&server_fqdn=matrix.org&style=flat + :target: https://matrix.to/#/%23aio-libs:matrix.org + :alt: Matrix Room — #aio-libs:matrix.org -.. image:: https://badges.gitter.im/Join%20Chat.svg - :target: https://gitter.im/aio-libs/Lobby - :alt: Chat on Gitter +.. image:: https://img.shields.io/matrix/aio-libs-space:matrix.org?label=Discuss%20on%20Matrix%20at%20%23aio-libs-space%3Amatrix.org&logo=matrix&server_fqdn=matrix.org&style=flat + :target: https://matrix.to/#/%23aio-libs-space:matrix.org + :alt: Matrix Space — #aio-libs-space:matrix.org Key Features @@ -67,8 +67,7 @@ To get something from the web: html = await response.text() print("Body:", html[:15], "...") - loop = asyncio.get_event_loop() - loop.run_until_complete(main()) + asyncio.run(main()) This prints: @@ -161,17 +160,19 @@ Requirements - Python >= 3.6 - async-timeout_ - attrs_ -- chardet_ +- charset-normalizer_ - multidict_ - yarl_ +- frozenlist_ Optionally you may install the cChardet_ and aiodns_ libraries (highly recommended for sake of speed). -.. _chardet: https://pypi.python.org/pypi/chardet +.. _charset-normalizer: https://pypi.org/project/charset-normalizer .. _aiodns: https://pypi.python.org/pypi/aiodns .. _attrs: https://github.com/python-attrs/attrs .. _multidict: https://pypi.python.org/pypi/multidict +.. _frozenlist: https://pypi.org/project/frozenlist/ .. _yarl: https://pypi.python.org/pypi/yarl .. _async-timeout: https://pypi.python.org/pypi/async_timeout .. _cChardet: https://pypi.python.org/pypi/cchardet diff --git a/aiohttp.egg-info/PKG-INFO b/aiohttp.egg-info/PKG-INFO index 51ea8f8..b2d329d 100644 --- a/aiohttp.egg-info/PKG-INFO +++ b/aiohttp.egg-info/PKG-INFO @@ -1,952 +1,254 @@ Metadata-Version: 2.1 Name: aiohttp -Version: 3.7.4 +Version: 3.8.6 Summary: Async http client/server framework (asyncio) Home-page: https://github.com/aio-libs/aiohttp -Author: Nikolay Kim -Author-email: fafhrd91@gmail.com -Maintainer: Nikolay Kim , Andrew Svetlov -Maintainer-email: aio-libs@googlegroups.com +Maintainer: aiohttp team +Maintainer-email: team@aiohttp.org License: Apache 2 -Project-URL: Chat: Gitter, https://gitter.im/aio-libs/Lobby -Project-URL: CI: Azure Pipelines, https://dev.azure.com/aio-libs/aiohttp/_build +Project-URL: Chat: Matrix, https://matrix.to/#/#aio-libs:matrix.org +Project-URL: Chat: Matrix Space, https://matrix.to/#/#aio-libs-space:matrix.org +Project-URL: CI: GitHub Actions, https://github.com/aio-libs/aiohttp/actions?query=workflow%3ACI Project-URL: Coverage: codecov, https://codecov.io/github/aio-libs/aiohttp +Project-URL: Docs: Changelog, https://docs.aiohttp.org/en/stable/changes.html Project-URL: Docs: RTD, https://docs.aiohttp.org Project-URL: GitHub: issues, https://github.com/aio-libs/aiohttp/issues Project-URL: GitHub: repo, https://github.com/aio-libs/aiohttp -Description: ================================== - Async http client/server framework - ================================== - - .. image:: https://raw.githubusercontent.com/aio-libs/aiohttp/master/docs/_static/aiohttp-icon-128x128.png - :height: 64px - :width: 64px - :alt: aiohttp logo - - | - - .. image:: https://github.com/aio-libs/aiohttp/workflows/CI/badge.svg - :target: https://github.com/aio-libs/aiohttp/actions?query=workflow%3ACI - :alt: GitHub Actions status for master branch - - .. image:: https://codecov.io/gh/aio-libs/aiohttp/branch/master/graph/badge.svg - :target: https://codecov.io/gh/aio-libs/aiohttp - :alt: codecov.io status for master branch - - .. image:: https://badge.fury.io/py/aiohttp.svg - :target: https://pypi.org/project/aiohttp - :alt: Latest PyPI package version - - .. image:: https://readthedocs.org/projects/aiohttp/badge/?version=latest - :target: https://docs.aiohttp.org/ - :alt: Latest Read The Docs - - .. image:: https://img.shields.io/discourse/status?server=https%3A%2F%2Faio-libs.discourse.group - :target: https://aio-libs.discourse.group - :alt: Discourse status - - .. image:: https://badges.gitter.im/Join%20Chat.svg - :target: https://gitter.im/aio-libs/Lobby - :alt: Chat on Gitter - - - Key Features - ============ - - - Supports both client and server side of HTTP protocol. - - Supports both client and server Web-Sockets out-of-the-box and avoids - Callback Hell. - - Provides Web-server with middlewares and plugable routing. - - - Getting started - =============== - - Client - ------ - - To get something from the web: - - .. code-block:: python - - import aiohttp - import asyncio - - async def main(): - - async with aiohttp.ClientSession() as session: - async with session.get('http://python.org') as response: - - print("Status:", response.status) - print("Content-type:", response.headers['content-type']) - - html = await response.text() - print("Body:", html[:15], "...") - - loop = asyncio.get_event_loop() - loop.run_until_complete(main()) - - This prints: - - .. code-block:: - - Status: 200 - Content-type: text/html; charset=utf-8 - Body: ... - - Coming from `requests `_ ? Read `why we need so many lines `_. - - Server - ------ - - An example using a simple server: - - .. code-block:: python - - # examples/server_simple.py - from aiohttp import web - - async def handle(request): - name = request.match_info.get('name', "Anonymous") - text = "Hello, " + name - return web.Response(text=text) - - async def wshandle(request): - ws = web.WebSocketResponse() - await ws.prepare(request) - - async for msg in ws: - if msg.type == web.WSMsgType.text: - await ws.send_str("Hello, {}".format(msg.data)) - elif msg.type == web.WSMsgType.binary: - await ws.send_bytes(msg.data) - elif msg.type == web.WSMsgType.close: - break - - return ws - - - app = web.Application() - app.add_routes([web.get('/', handle), - web.get('/echo', wshandle), - web.get('/{name}', handle)]) - - if __name__ == '__main__': - web.run_app(app) - - - Documentation - ============= - - https://aiohttp.readthedocs.io/ - - - Demos - ===== - - https://github.com/aio-libs/aiohttp-demos - - - External links - ============== - - * `Third party libraries - `_ - * `Built with aiohttp - `_ - * `Powered by aiohttp - `_ - - Feel free to make a Pull Request for adding your link to these pages! - - - Communication channels - ====================== - - *aio-libs discourse group*: https://aio-libs.discourse.group - - *gitter chat* https://gitter.im/aio-libs/Lobby - - We support `Stack Overflow - `_. - Please add *aiohttp* tag to your question there. - - Requirements - ============ - - - Python >= 3.6 - - async-timeout_ - - attrs_ - - chardet_ - - multidict_ - - yarl_ - - Optionally you may install the cChardet_ and aiodns_ libraries (highly - recommended for sake of speed). - - .. _chardet: https://pypi.python.org/pypi/chardet - .. _aiodns: https://pypi.python.org/pypi/aiodns - .. _attrs: https://github.com/python-attrs/attrs - .. _multidict: https://pypi.python.org/pypi/multidict - .. _yarl: https://pypi.python.org/pypi/yarl - .. _async-timeout: https://pypi.python.org/pypi/async_timeout - .. _cChardet: https://pypi.python.org/pypi/cchardet - - License - ======= - - ``aiohttp`` is offered under the Apache 2 license. - - - Keepsafe - ======== - - The aiohttp community would like to thank Keepsafe - (https://www.getkeepsafe.com) for its support in the early days of - the project. - - - Source code - =========== - - The latest developer version is available in a GitHub repository: - https://github.com/aio-libs/aiohttp - - Benchmarks - ========== - - If you are interested in efficiency, the AsyncIO community maintains a - list of benchmarks on the official wiki: - https://github.com/python/asyncio/wiki/Benchmarks - - ========= - Changelog - ========= - - .. - You should *NOT* be adding new change log entries to this file, this - file is managed by towncrier. You *may* edit previous change logs to - fix problems like typo corrections or such. - To add a new change log entry, please see - https://pip.pypa.io/en/latest/development/#adding-a-news-entry - we named the news folder "changes". - - WARNING: Don't drop the next directive! - - .. towncrier release notes start - - 3.7.3 (2021-02-25) - ================== - - Bugfixes - -------- - - - **(SECURITY BUG)** Started preventing open redirects in the - ``aiohttp.web.normalize_path_middleware`` middleware. For - more details, see - https://github.com/aio-libs/aiohttp/security/advisories/GHSA-v6wp-4m6f-gcjg. - - Thanks to `Beast Glatisant `__ for - finding the first instance of this issue and `Jelmer Vernooij - `__ for reporting and tracking it down - in aiohttp. - `#5497 `_ - - Fix interpretation difference of the pure-Python and the Cython-based - HTTP parsers construct a ``yarl.URL`` object for HTTP request-target. - - Before this fix, the Python parser would turn the URI's absolute-path - for ``//some-path`` into ``/`` while the Cython code preserved it as - ``//some-path``. Now, both do the latter. - `#5498 `_ - - - ---- - - - 3.7.3 (2020-11-18) - ================== - - Features - -------- - - - Use Brotli instead of brotlipy - `#3803 `_ - - Made exceptions pickleable. Also changed the repr of some exceptions. - `#4077 `_ - - - Bugfixes - -------- - - - Raise a ClientResponseError instead of an AssertionError for a blank - HTTP Reason Phrase. - `#3532 `_ - - Fix ``web_middlewares.normalize_path_middleware`` behavior for patch without slash. - `#3669 `_ - - Fix overshadowing of overlapped sub-applications prefixes. - `#3701 `_ - - Make `BaseConnector.close()` a coroutine and wait until the client closes all connections. Drop deprecated "with Connector():" syntax. - `#3736 `_ - - Reset the ``sock_read`` timeout each time data is received for a ``aiohttp.client`` response. - `#3808 `_ - - Fixed type annotation for add_view method of UrlDispatcher to accept any subclass of View - `#3880 `_ - - Fixed querying the address families from DNS that the current host supports. - `#5156 `_ - - Change return type of MultipartReader.__aiter__() and BodyPartReader.__aiter__() to AsyncIterator. - `#5163 `_ - - Provide x86 Windows wheels. - `#5230 `_ - - - Improved Documentation - ---------------------- - - - Add documentation for ``aiohttp.web.FileResponse``. - `#3958 `_ - - Removed deprecation warning in tracing example docs - `#3964 `_ - - Fixed wrong "Usage" docstring of ``aiohttp.client.request``. - `#4603 `_ - - Add aiohttp-pydantic to third party libraries - `#5228 `_ - - - Misc - ---- - - - `#4102 `_ - - - ---- - - - 3.7.2 (2020-10-27) - ================== - - Bugfixes - -------- - - - Fixed static files handling for loops without ``.sendfile()`` support - `#5149 `_ - - - ---- - - - 3.7.1 (2020-10-25) - ================== - - Bugfixes - -------- - - - Fixed a type error caused by the conditional import of `Protocol`. - `#5111 `_ - - Server doesn't send Content-Length for 1xx or 204 - `#4901 `_ - - Fix run_app typing - `#4957 `_ - - Always require ``typing_extensions`` library. - `#5107 `_ - - Fix a variable-shadowing bug causing `ThreadedResolver.resolve` to - return the resolved IP as the ``hostname`` in each record, which prevented - validation of HTTPS connections. - `#5110 `_ - - Added annotations to all public attributes. - `#5115 `_ - - Fix flaky test_when_timeout_smaller_second - `#5116 `_ - - Ensure sending a zero byte file does not throw an exception - `#5124 `_ - - Fix a bug in ``web.run_app()`` about Python version checking on Windows - `#5127 `_ - - - ---- - - - 3.7.0 (2020-10-24) - ================== - - Features - -------- - - - Response headers are now prepared prior to running ``on_response_prepare`` hooks, directly before headers are sent to the client. - `#1958 `_ - - Add a ``quote_cookie`` option to ``CookieJar``, a way to skip quotation wrapping of cookies containing special characters. - `#2571 `_ - - Call ``AccessLogger.log`` with the current exception available from ``sys.exc_info()``. - `#3557 `_ - - `web.UrlDispatcher.add_routes` and `web.Application.add_routes` return a list - of registered `AbstractRoute` instances. `AbstractRouteDef.register` (and all - subclasses) return a list of registered resources registered resource. - `#3866 `_ - - Added properties of default ClientSession params to ClientSession class so it is available for introspection - `#3882 `_ - - Don't cancel web handler on peer disconnection, raise `OSError` on reading/writing instead. - `#4080 `_ - - Implement BaseRequest.get_extra_info() to access a protocol transports' extra info. - `#4189 `_ - - Added `ClientSession.timeout` property. - `#4191 `_ - - allow use of SameSite in cookies. - `#4224 `_ - - Use ``loop.sendfile()`` instead of custom implementation if available. - `#4269 `_ - - Apply SO_REUSEADDR to test server's socket. - `#4393 `_ - - Use .raw_host instead of slower .host in client API - `#4402 `_ - - Allow configuring the buffer size of input stream by passing ``read_bufsize`` argument. - `#4453 `_ - - Pass tests on Python 3.8 for Windows. - `#4513 `_ - - Add `method` and `url` attributes to `TraceRequestChunkSentParams` and `TraceResponseChunkReceivedParams`. - `#4674 `_ - - Add ClientResponse.ok property for checking status code under 400. - `#4711 `_ - - Don't ceil timeouts that are smaller than 5 seconds. - `#4850 `_ - - TCPSite now listens by default on all interfaces instead of just IPv4 when `None` is passed in as the host. - `#4894 `_ - - Bump ``http_parser`` to 2.9.4 - `#5070 `_ - - - Bugfixes - -------- - - - Fix keepalive connections not being closed in time - `#3296 `_ - - Fix failed websocket handshake leaving connection hanging. - `#3380 `_ - - Fix tasks cancellation order on exit. The run_app task needs to be cancelled first for cleanup hooks to run with all tasks intact. - `#3805 `_ - - Don't start heartbeat until _writer is set - `#4062 `_ - - Fix handling of multipart file uploads without a content type. - `#4089 `_ - - Preserve view handler function attributes across middlewares - `#4174 `_ - - Fix the string representation of ``ServerDisconnectedError``. - `#4175 `_ - - Raising RuntimeError when trying to get encoding from not read body - `#4214 `_ - - Remove warning messages from noop. - `#4282 `_ - - Raise ClientPayloadError if FormData re-processed. - `#4345 `_ - - Fix a warning about unfinished task in ``web_protocol.py`` - `#4408 `_ - - Fixed 'deflate' compression. According to RFC 2616 now. - `#4506 `_ - - Fixed OverflowError on platforms with 32-bit time_t - `#4515 `_ - - Fixed request.body_exists returns wrong value for methods without body. - `#4528 `_ - - Fix connecting to link-local IPv6 addresses. - `#4554 `_ - - Fix a problem with connection waiters that are never awaited. - `#4562 `_ - - Always make sure transport is not closing before reuse a connection. - - Reuse a protocol based on keepalive in headers is unreliable. - For example, uWSGI will not support keepalive even it serves a - HTTP 1.1 request, except explicitly configure uWSGI with a - ``--http-keepalive`` option. - - Servers designed like uWSGI could cause aiohttp intermittently - raise a ConnectionResetException when the protocol poll runs - out and some protocol is reused. - `#4587 `_ - - Handle the last CRLF correctly even if it is received via separate TCP segment. - `#4630 `_ - - Fix the register_resource function to validate route name before splitting it so that route name can include python keywords. - `#4691 `_ - - Improve typing annotations for ``web.Request``, ``aiohttp.ClientResponse`` and - ``multipart`` module. - `#4736 `_ - - Fix resolver task is not awaited when connector is cancelled - `#4795 `_ - - Fix a bug "Aiohttp doesn't return any error on invalid request methods" - `#4798 `_ - - Fix HEAD requests for static content. - `#4809 `_ - - Fix incorrect size calculation for memoryview - `#4890 `_ - - Add HTTPMove to _all__. - `#4897 `_ - - Fixed the type annotations in the ``tracing`` module. - `#4912 `_ - - Fix typing for multipart ``__aiter__``. - `#4931 `_ - - Fix for race condition on connections in BaseConnector that leads to exceeding the connection limit. - `#4936 `_ - - Add forced UTF-8 encoding for ``application/rdap+json`` responses. - `#4938 `_ - - Fix inconsistency between Python and C http request parsers in parsing pct-encoded URL. - `#4972 `_ - - Fix connection closing issue in HEAD request. - `#5012 `_ - - Fix type hint on BaseRunner.addresses (from ``List[str]`` to ``List[Any]``) - `#5086 `_ - - Make `web.run_app()` more responsive to Ctrl+C on Windows for Python < 3.8. It slightly - increases CPU load as a side effect. - `#5098 `_ - - - Improved Documentation - ---------------------- - - - Fix example code in client quick-start - `#3376 `_ - - Updated the docs so there is no contradiction in ``ttl_dns_cache`` default value - `#3512 `_ - - Add 'Deploy with SSL' to docs. - `#4201 `_ - - Change typing of the secure argument on StreamResponse.set_cookie from ``Optional[str]`` to ``Optional[bool]`` - `#4204 `_ - - Changes ``ttl_dns_cache`` type from int to Optional[int]. - `#4270 `_ - - Simplify README hello word example and add a documentation page for people coming from requests. - `#4272 `_ - - Improve some code examples in the documentation involving websockets and starting a simple HTTP site with an AppRunner. - `#4285 `_ - - Fix typo in code example in Multipart docs - `#4312 `_ - - Fix code example in Multipart section. - `#4314 `_ - - Update contributing guide so new contributors read the most recent version of that guide. Update command used to create test coverage reporting. - `#4810 `_ - - Spelling: Change "canonize" to "canonicalize". - `#4986 `_ - - Add ``aiohttp-sse-client`` library to third party usage list. - `#5084 `_ - - - Misc - ---- - - - `#2856 `_, `#4218 `_, `#4250 `_ - - - ---- - - - 3.6.3 (2020-10-12) - ================== - - Bugfixes - -------- - - - Pin yarl to ``<1.6.0`` to avoid buggy behavior that will be fixed by the next aiohttp - release. - - 3.6.2 (2019-10-09) - ================== - - Features - -------- - - - Made exceptions pickleable. Also changed the repr of some exceptions. - `#4077 `_ - - Use ``Iterable`` type hint instead of ``Sequence`` for ``Application`` *middleware* - parameter. `#4125 `_ - - - Bugfixes - -------- - - - Reset the ``sock_read`` timeout each time data is received for a - ``aiohttp.ClientResponse``. `#3808 - `_ - - Fix handling of expired cookies so they are not stored in CookieJar. - `#4063 `_ - - Fix misleading message in the string representation of ``ClientConnectorError``; - ``self.ssl == None`` means default SSL context, not SSL disabled `#4097 - `_ - - Don't clobber HTTP status when using FileResponse. - `#4106 `_ - - - Improved Documentation - ---------------------- - - - Added minimal required logging configuration to logging documentation. - `#2469 `_ - - Update docs to reflect proxy support. - `#4100 `_ - - Fix typo in code example in testing docs. - `#4108 `_ - - - Misc - ---- - - - `#4102 `_ - - - ---- - - - 3.6.1 (2019-09-19) - ================== - - Features - -------- - - - Compatibility with Python 3.8. - `#4056 `_ - - - Bugfixes - -------- - - - correct some exception string format - `#4068 `_ - - Emit a warning when ``ssl.OP_NO_COMPRESSION`` is - unavailable because the runtime is built against - an outdated OpenSSL. - `#4052 `_ - - Update multidict requirement to >= 4.5 - `#4057 `_ - - - Improved Documentation - ---------------------- - - - Provide pytest-aiohttp namespace for pytest fixtures in docs. - `#3723 `_ - - - ---- - - - 3.6.0 (2019-09-06) - ================== - - Features - -------- - - - Add support for Named Pipes (Site and Connector) under Windows. This feature requires - Proactor event loop to work. `#3629 - `_ - - Removed ``Transfer-Encoding: chunked`` header from websocket responses to be - compatible with more http proxy servers. `#3798 - `_ - - Accept non-GET request for starting websocket handshake on server side. - `#3980 `_ - - - Bugfixes - -------- - - - Raise a ClientResponseError instead of an AssertionError for a blank - HTTP Reason Phrase. - `#3532 `_ - - Fix an issue where cookies would sometimes not be set during a redirect. - `#3576 `_ - - Change normalize_path_middleware to use 308 redirect instead of 301. - - This behavior should prevent clients from being unable to use PUT/POST - methods on endpoints that are redirected because of a trailing slash. - `#3579 `_ - - Drop the processed task from ``all_tasks()`` list early. It prevents logging about a - task with unhandled exception when the server is used in conjunction with - ``asyncio.run()``. `#3587 `_ - - ``Signal`` type annotation changed from ``Signal[Callable[['TraceConfig'], - Awaitable[None]]]`` to ``Signal[Callable[ClientSession, SimpleNamespace, ...]``. - `#3595 `_ - - Use sanitized URL as Location header in redirects - `#3614 `_ - - Improve typing annotations for multipart.py along with changes required - by mypy in files that references multipart.py. - `#3621 `_ - - Close session created inside ``aiohttp.request`` when unhandled exception occurs - `#3628 `_ - - Cleanup per-chunk data in generic data read. Memory leak fixed. - `#3631 `_ - - Use correct type for add_view and family - `#3633 `_ - - Fix _keepalive field in __slots__ of ``RequestHandler``. - `#3644 `_ - - Properly handle ConnectionResetError, to silence the "Cannot write to closing - transport" exception when clients disconnect uncleanly. - `#3648 `_ - - Suppress pytest warnings due to ``test_utils`` classes - `#3660 `_ - - Fix overshadowing of overlapped sub-application prefixes. - `#3701 `_ - - Fixed return type annotation for WSMessage.json() - `#3720 `_ - - Properly expose TooManyRedirects publicly as documented. - `#3818 `_ - - Fix missing brackets for IPv6 in proxy CONNECT request - `#3841 `_ - - Make the signature of ``aiohttp.test_utils.TestClient.request`` match - ``asyncio.ClientSession.request`` according to the docs `#3852 - `_ - - Use correct style for re-exported imports, makes mypy ``--strict`` mode happy. - `#3868 `_ - - Fixed type annotation for add_view method of UrlDispatcher to accept any subclass of - View `#3880 `_ - - Made cython HTTP parser set Reason-Phrase of the response to an empty string if it is - missing. `#3906 `_ - - Add URL to the string representation of ClientResponseError. - `#3959 `_ - - Accept ``istr`` keys in ``LooseHeaders`` type hints. - `#3976 `_ - - Fixed race conditions in _resolve_host caching and throttling when tracing is enabled. - `#4013 `_ - - For URLs like "unix://localhost/..." set Host HTTP header to "localhost" instead of - "localhost:None". `#4039 `_ - - - Improved Documentation - ---------------------- - - - Modify documentation for Background Tasks to remove deprecated usage of event loop. - `#3526 `_ - - use ``if __name__ == '__main__':`` in server examples. - `#3775 `_ - - Update documentation reference to the default access logger. - `#3783 `_ - - Improve documentation for ``web.BaseRequest.path`` and ``web.BaseRequest.raw_path``. - `#3791 `_ - - Removed deprecation warning in tracing example docs - `#3964 `_ - - - ---- - - - 3.5.4 (2019-01-12) - ================== - - Bugfixes - -------- - - - Fix stream ``.read()`` / ``.readany()`` / ``.iter_any()`` which used to return a - partial content only in case of compressed content - `#3525 `_ - - - 3.5.3 (2019-01-10) - ================== - - Bugfixes - -------- - - - Fix type stubs for ``aiohttp.web.run_app(access_log=True)`` and fix edge case of - ``access_log=True`` and the event loop being in debug mode. `#3504 - `_ - - Fix ``aiohttp.ClientTimeout`` type annotations to accept ``None`` for fields - `#3511 `_ - - Send custom per-request cookies even if session jar is empty - `#3515 `_ - - Restore Linux binary wheels publishing on PyPI - - ---- - - - 3.5.2 (2019-01-08) - ================== - - Features - -------- - - - ``FileResponse`` from ``web_fileresponse.py`` uses a ``ThreadPoolExecutor`` to work - with files asynchronously. I/O based payloads from ``payload.py`` uses a - ``ThreadPoolExecutor`` to work with I/O objects asynchronously. `#3313 - `_ - - Internal Server Errors in plain text if the browser does not support HTML. - `#3483 `_ - - - Bugfixes - -------- - - - Preserve MultipartWriter parts headers on write. Refactor the way how - ``Payload.headers`` are handled. Payload instances now always have headers and - Content-Type defined. Fix Payload Content-Disposition header reset after initial - creation. `#3035 `_ - - Log suppressed exceptions in ``GunicornWebWorker``. - `#3464 `_ - - Remove wildcard imports. - `#3468 `_ - - Use the same task for app initialization and web server handling in gunicorn workers. - It allows to use Python3.7 context vars smoothly. - `#3471 `_ - - Fix handling of chunked+gzipped response when first chunk does not give uncompressed - data `#3477 `_ - - Replace ``collections.MutableMapping`` with ``collections.abc.MutableMapping`` to - avoid a deprecation warning. `#3480 - `_ - - ``Payload.size`` type annotation changed from ``Optional[float]`` to - ``Optional[int]``. `#3484 `_ - - Ignore done tasks when cancels pending activities on ``web.run_app`` finalization. - `#3497 `_ - - - Improved Documentation - ---------------------- - - - Add documentation for ``aiohttp.web.HTTPException``. - `#3490 `_ - - - Misc - ---- - - - `#3487 `_ - - - ---- - - - 3.5.1 (2018-12-24) - ==================== - - - Fix a regression about ``ClientSession._requote_redirect_url`` modification in debug - mode. - - 3.5.0 (2018-12-22) - ==================== - - Features - -------- - - - The library type annotations are checked in strict mode now. - - Add support for setting cookies for individual request (`#2387 - `_) - - Application.add_domain implementation (`#2809 - `_) - - The default ``app`` in the request returned by ``test_utils.make_mocked_request`` can - now have objects assigned to it and retrieved using the ``[]`` operator. (`#3174 - `_) - - Make ``request.url`` accessible when transport is closed. (`#3177 - `_) - - Add ``zlib_executor_size`` argument to ``Response`` constructor to allow compression - to run in a background executor to avoid blocking the main thread and potentially - triggering health check failures. (`#3205 - `_) - - Enable users to set ``ClientTimeout`` in ``aiohttp.request`` (`#3213 - `_) - - Don't raise a warning if ``NETRC`` environment variable is not set and ``~/.netrc`` - file doesn't exist. (`#3267 `_) - - Add default logging handler to web.run_app If the ``Application.debug``` flag is set - and the default logger ``aiohttp.access`` is used, access logs will now be output - using a *stderr* ``StreamHandler`` if no handlers are attached. Furthermore, if the - default logger has no log level set, the log level will be set to ``DEBUG``. (`#3324 - `_) - - Add method argument to ``session.ws_connect()``. Sometimes server API requires a - different HTTP method for WebSocket connection establishment. For example, ``Docker - exec`` needs POST. (`#3378 `_) - - Create a task per request handling. (`#3406 - `_) - - - Bugfixes - -------- - - - Enable passing ``access_log_class`` via ``handler_args`` (`#3158 - `_) - - Return empty bytes with end-of-chunk marker in empty stream reader. (`#3186 - `_) - - Accept ``CIMultiDictProxy`` instances for ``headers`` argument in ``web.Response`` - constructor. (`#3207 `_) - - Don't uppercase HTTP method in parser (`#3233 - `_) - - Make method match regexp RFC-7230 compliant (`#3235 - `_) - - Add ``app.pre_frozen`` state to properly handle startup signals in - sub-applications. (`#3237 `_) - - Enhanced parsing and validation of helpers.BasicAuth.decode. (`#3239 - `_) - - Change imports from collections module in preparation for 3.8. (`#3258 - `_) - - Ensure Host header is added first to ClientRequest to better replicate browser (`#3265 - `_) - - Fix forward compatibility with Python 3.8: importing ABCs directly from the - collections module will not be supported anymore. (`#3273 - `_) - - Keep the query string by ``normalize_path_middleware``. (`#3278 - `_) - - Fix missing parameter ``raise_for_status`` for aiohttp.request() (`#3290 - `_) - - Bracket IPv6 addresses in the HOST header (`#3304 - `_) - - Fix default message for server ping and pong frames. (`#3308 - `_) - - Fix tests/test_connector.py typo and tests/autobahn/server.py duplicate loop - def. (`#3337 `_) - - Fix false-negative indicator end_of_HTTP_chunk in StreamReader.readchunk function - (`#3361 `_) - - Release HTTP response before raising status exception (`#3364 - `_) - - Fix task cancellation when ``sendfile()`` syscall is used by static file - handling. (`#3383 `_) - - Fix stack trace for ``asyncio.TimeoutError`` which was not logged, when it is caught - in the handler. (`#3414 `_) - - - Improved Documentation - ---------------------- - - - Improve documentation of ``Application.make_handler`` parameters. (`#3152 - `_) - - Fix BaseRequest.raw_headers doc. (`#3215 - `_) - - Fix typo in TypeError exception reason in ``web.Application._handle`` (`#3229 - `_) - - Make server access log format placeholder %b documentation reflect - behavior and docstring. (`#3307 `_) - - - Deprecations and Removals - ------------------------- - - - Deprecate modification of ``session.requote_redirect_url`` (`#2278 - `_) - - Deprecate ``stream.unread_data()`` (`#3260 - `_) - - Deprecated use of boolean in ``resp.enable_compression()`` (`#3318 - `_) - - Encourage creation of aiohttp public objects inside a coroutine (`#3331 - `_) - - Drop dead ``Connection.detach()`` and ``Connection.writer``. Both methods were broken - for more than 2 years. (`#3358 `_) - - Deprecate ``app.loop``, ``request.loop``, ``client.loop`` and ``connector.loop`` - properties. (`#3374 `_) - - Deprecate explicit debug argument. Use asyncio debug mode instead. (`#3381 - `_) - - Deprecate body parameter in HTTPException (and derived classes) constructor. (`#3385 - `_) - - Deprecate bare connector close, use ``async with connector:`` and ``await - connector.close()`` instead. (`#3417 - `_) - - Deprecate obsolete ``read_timeout`` and ``conn_timeout`` in ``ClientSession`` - constructor. (`#3438 `_) - - - Misc - ---- - - - #3341, #3351 -Platform: UNKNOWN -Classifier: License :: OSI Approved :: Apache Software License +Classifier: Development Status :: 5 - Production/Stable +Classifier: Framework :: AsyncIO Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: Apache Software License +Classifier: Operating System :: POSIX +Classifier: Operating System :: MacOS :: MacOS X +Classifier: Operating System :: Microsoft :: Windows Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 -Classifier: Development Status :: 5 - Production/Stable -Classifier: Operating System :: POSIX -Classifier: Operating System :: MacOS :: MacOS X -Classifier: Operating System :: Microsoft :: Windows +Classifier: Programming Language :: Python :: 3.10 Classifier: Topic :: Internet :: WWW/HTTP -Classifier: Framework :: AsyncIO Requires-Python: >=3.6 +Description-Content-Type: text/x-rst +License-File: LICENSE.txt +Requires-Dist: attrs>=17.3.0 +Requires-Dist: charset-normalizer<4.0,>=2.0 +Requires-Dist: multidict<7.0,>=4.5 +Requires-Dist: async_timeout<5.0,>=4.0.0a3 +Requires-Dist: asynctest==0.13.0; python_version < "3.8" +Requires-Dist: yarl<2.0,>=1.0 +Requires-Dist: idna-ssl>=1.0; python_version < "3.7" +Requires-Dist: typing_extensions>=3.7.4; python_version < "3.8" +Requires-Dist: frozenlist>=1.1.1 +Requires-Dist: aiosignal>=1.1.2 Provides-Extra: speedups +Requires-Dist: aiodns; extra == "speedups" +Requires-Dist: Brotli; extra == "speedups" +Requires-Dist: cchardet; python_version < "3.10" and extra == "speedups" + +================================== +Async http client/server framework +================================== + +.. image:: https://raw.githubusercontent.com/aio-libs/aiohttp/master/docs/aiohttp-plain.svg + :height: 64px + :width: 64px + :alt: aiohttp logo + +| + +.. image:: https://github.com/aio-libs/aiohttp/workflows/CI/badge.svg + :target: https://github.com/aio-libs/aiohttp/actions?query=workflow%3ACI + :alt: GitHub Actions status for master branch + +.. image:: https://codecov.io/gh/aio-libs/aiohttp/branch/master/graph/badge.svg + :target: https://codecov.io/gh/aio-libs/aiohttp + :alt: codecov.io status for master branch + +.. image:: https://badge.fury.io/py/aiohttp.svg + :target: https://pypi.org/project/aiohttp + :alt: Latest PyPI package version + +.. image:: https://readthedocs.org/projects/aiohttp/badge/?version=latest + :target: https://docs.aiohttp.org/ + :alt: Latest Read The Docs + +.. image:: https://img.shields.io/matrix/aio-libs:matrix.org?label=Discuss%20on%20Matrix%20at%20%23aio-libs%3Amatrix.org&logo=matrix&server_fqdn=matrix.org&style=flat + :target: https://matrix.to/#/%23aio-libs:matrix.org + :alt: Matrix Room — #aio-libs:matrix.org + +.. image:: https://img.shields.io/matrix/aio-libs-space:matrix.org?label=Discuss%20on%20Matrix%20at%20%23aio-libs-space%3Amatrix.org&logo=matrix&server_fqdn=matrix.org&style=flat + :target: https://matrix.to/#/%23aio-libs-space:matrix.org + :alt: Matrix Space — #aio-libs-space:matrix.org + + +Key Features +============ + +- Supports both client and server side of HTTP protocol. +- Supports both client and server Web-Sockets out-of-the-box and avoids + Callback Hell. +- Provides Web-server with middlewares and plugable routing. + + +Getting started +=============== + +Client +------ + +To get something from the web: + +.. code-block:: python + + import aiohttp + import asyncio + + async def main(): + + async with aiohttp.ClientSession() as session: + async with session.get('http://python.org') as response: + + print("Status:", response.status) + print("Content-type:", response.headers['content-type']) + + html = await response.text() + print("Body:", html[:15], "...") + + asyncio.run(main()) + +This prints: + +.. code-block:: + + Status: 200 + Content-type: text/html; charset=utf-8 + Body: ... + +Coming from `requests `_ ? Read `why we need so many lines `_. + +Server +------ + +An example using a simple server: + +.. code-block:: python + + # examples/server_simple.py + from aiohttp import web + + async def handle(request): + name = request.match_info.get('name', "Anonymous") + text = "Hello, " + name + return web.Response(text=text) + + async def wshandle(request): + ws = web.WebSocketResponse() + await ws.prepare(request) + + async for msg in ws: + if msg.type == web.WSMsgType.text: + await ws.send_str("Hello, {}".format(msg.data)) + elif msg.type == web.WSMsgType.binary: + await ws.send_bytes(msg.data) + elif msg.type == web.WSMsgType.close: + break + + return ws + + + app = web.Application() + app.add_routes([web.get('/', handle), + web.get('/echo', wshandle), + web.get('/{name}', handle)]) + + if __name__ == '__main__': + web.run_app(app) + + +Documentation +============= + +https://aiohttp.readthedocs.io/ + + +Demos +===== + +https://github.com/aio-libs/aiohttp-demos + + +External links +============== + +* `Third party libraries + `_ +* `Built with aiohttp + `_ +* `Powered by aiohttp + `_ + +Feel free to make a Pull Request for adding your link to these pages! + + +Communication channels +====================== + +*aio-libs discourse group*: https://aio-libs.discourse.group + +*gitter chat* https://gitter.im/aio-libs/Lobby + +We support `Stack Overflow +`_. +Please add *aiohttp* tag to your question there. + +Requirements +============ + +- Python >= 3.6 +- async-timeout_ +- attrs_ +- charset-normalizer_ +- multidict_ +- yarl_ +- frozenlist_ + +Optionally you may install the cChardet_ and aiodns_ libraries (highly +recommended for sake of speed). + +.. _charset-normalizer: https://pypi.org/project/charset-normalizer +.. _aiodns: https://pypi.python.org/pypi/aiodns +.. _attrs: https://github.com/python-attrs/attrs +.. _multidict: https://pypi.python.org/pypi/multidict +.. _frozenlist: https://pypi.org/project/frozenlist/ +.. _yarl: https://pypi.python.org/pypi/yarl +.. _async-timeout: https://pypi.python.org/pypi/async_timeout +.. _cChardet: https://pypi.python.org/pypi/cchardet + +License +======= + +``aiohttp`` is offered under the Apache 2 license. + + +Keepsafe +======== + +The aiohttp community would like to thank Keepsafe +(https://www.getkeepsafe.com) for its support in the early days of +the project. + + +Source code +=========== + +The latest developer version is available in a GitHub repository: +https://github.com/aio-libs/aiohttp + +Benchmarks +========== + +If you are interested in efficiency, the AsyncIO community maintains a +list of benchmarks on the official wiki: +https://github.com/python/asyncio/wiki/Benchmarks diff --git a/aiohttp.egg-info/SOURCES.txt b/aiohttp.egg-info/SOURCES.txt index e006e2a..6aed10d 100644 --- a/aiohttp.egg-info/SOURCES.txt +++ b/aiohttp.egg-info/SOURCES.txt @@ -12,8 +12,6 @@ aiohttp/_cparser.pxd aiohttp/_find_header.c aiohttp/_find_header.h aiohttp/_find_header.pxd -aiohttp/_frozenlist.c -aiohttp/_frozenlist.pyx aiohttp/_headers.pxi aiohttp/_helpers.c aiohttp/_helpers.pyi @@ -34,8 +32,6 @@ aiohttp/client_ws.py aiohttp/connector.py aiohttp/cookiejar.py aiohttp/formdata.py -aiohttp/frozenlist.py -aiohttp/frozenlist.pyi aiohttp/hdrs.py aiohttp/helpers.py aiohttp/http.py @@ -51,8 +47,6 @@ aiohttp/payload_streamer.py aiohttp/py.typed aiohttp/pytest_plugin.py aiohttp/resolver.py -aiohttp/signals.py -aiohttp/signals.pyi aiohttp/streams.py aiohttp/tcp_helpers.py aiohttp/test_utils.py @@ -76,19 +70,17 @@ aiohttp/worker.py aiohttp.egg-info/PKG-INFO aiohttp.egg-info/SOURCES.txt aiohttp.egg-info/dependency_links.txt +aiohttp.egg-info/not-zip-safe aiohttp.egg-info/requires.txt aiohttp.egg-info/top_level.txt aiohttp/.hash/_cparser.pxd.hash aiohttp/.hash/_find_header.pxd.hash -aiohttp/.hash/_frozenlist.pyx.hash aiohttp/.hash/_helpers.pyi.hash aiohttp/.hash/_helpers.pyx.hash aiohttp/.hash/_http_parser.pyx.hash aiohttp/.hash/_http_writer.pyx.hash aiohttp/.hash/_websocket.pyx.hash -aiohttp/.hash/frozenlist.pyi.hash aiohttp/.hash/hdrs.py.hash -aiohttp/.hash/signals.pyi.hash docs/Makefile docs/abc.rst docs/aiohttp-icon.svg @@ -119,7 +111,6 @@ docs/new_router.rst docs/old-logo.png docs/old-logo.svg docs/powered_by.rst -docs/signals.rst docs/spelling_wordlist.txt docs/streams.rst docs/structures.rst @@ -135,7 +126,9 @@ docs/web_reference.rst docs/websocket_utilities.rst docs/whats_new_1_1.rst docs/whats_new_3_0.rst -docs/_static/aiohttp-icon-128x128.png +docs/_snippets/cchardet-unmaintained-admonition.rst +docs/_static/css/logo-adjustments.css +examples/__init__.py examples/background_tasks.py examples/cli_app.py examples/client_auth.py @@ -157,16 +150,16 @@ examples/web_srv_route_deco.py examples/web_srv_route_table.py examples/web_ws.py examples/websocket.html -examples/legacy/crawl.py -examples/legacy/srv.py -examples/legacy/tcp_protocol_parser.py tests/aiohttp.jpg tests/aiohttp.png tests/conftest.py tests/data.unknown_mime_type tests/data.zero_bytes tests/hello.txt.gz +tests/sample.txt +tests/test___all__.py tests/test_base_protocol.py +tests/test_circular_imports.py tests/test_classbasedview.py tests/test_client_connection.py tests/test_client_exceptions.py @@ -182,7 +175,6 @@ tests/test_connector.py tests/test_cookiejar.py tests/test_flowcontrol_streams.py tests/test_formdata.py -tests/test_frozenlist.py tests/test_helpers.py tests/test_http_exceptions.py tests/test_http_parser.py @@ -198,7 +190,6 @@ tests/test_pytest_plugin.py tests/test_resolver.py tests/test_route_def.py tests/test_run_app.py -tests/test_signals.py tests/test_streams.py tests/test_tcp_helpers.py tests/test_test_utils.py @@ -210,7 +201,6 @@ tests/test_web_exceptions.py tests/test_web_functional.py tests/test_web_log.py tests/test_web_middleware.py -tests/test_web_protocol.py tests/test_web_request.py tests/test_web_request_handler.py tests/test_web_response.py @@ -225,22 +215,77 @@ tests/test_websocket_handshake.py tests/test_websocket_parser.py tests/test_websocket_writer.py tests/test_worker.py -tests/autobahn/client.py -tests/autobahn/fuzzingclient.json -tests/autobahn/fuzzingserver.json -tests/autobahn/server.py -vendor/http-parser/.git -vendor/http-parser/.gitignore -vendor/http-parser/.mailmap -vendor/http-parser/.travis.yml -vendor/http-parser/AUTHORS -vendor/http-parser/LICENSE-MIT -vendor/http-parser/Makefile -vendor/http-parser/README.md -vendor/http-parser/bench.c -vendor/http-parser/http_parser.c -vendor/http-parser/http_parser.gyp -vendor/http-parser/http_parser.h -vendor/http-parser/test.c -vendor/http-parser/contrib/parsertrace.c -vendor/http-parser/contrib/url_parser.c \ No newline at end of file +tests/autobahn/Dockerfile.aiohttp +tests/autobahn/Dockerfile.autobahn +tests/autobahn/test_autobahn.py +tests/autobahn/client/client.py +tests/autobahn/client/fuzzingserver.json +tests/autobahn/server/fuzzingclient.json +tests/autobahn/server/server.py +vendor/README.rst +vendor/llhttp/.dockerignore +vendor/llhttp/.eslintrc.js +vendor/llhttp/.git +vendor/llhttp/.gitignore +vendor/llhttp/.npmrc +vendor/llhttp/CMakeLists.txt +vendor/llhttp/CNAME +vendor/llhttp/CODE_OF_CONDUCT.md +vendor/llhttp/Dockerfile +vendor/llhttp/LICENSE-MIT +vendor/llhttp/Makefile +vendor/llhttp/README.md +vendor/llhttp/_config.yml +vendor/llhttp/libllhttp.pc.in +vendor/llhttp/package-lock.json +vendor/llhttp/package.json +vendor/llhttp/tsconfig.json +vendor/llhttp/tslint.json +vendor/llhttp/.github/workflows/aiohttp.yml +vendor/llhttp/.github/workflows/ci.yaml +vendor/llhttp/bench/index.ts +vendor/llhttp/bin/build_wasm.ts +vendor/llhttp/bin/generate.ts +vendor/llhttp/build/llhttp.h +vendor/llhttp/build/c/llhttp.c +vendor/llhttp/docs/releasing.md +vendor/llhttp/examples/wasm.ts +vendor/llhttp/images/http-loose-none.png +vendor/llhttp/images/http-strict-none.png +vendor/llhttp/src/common.gypi +vendor/llhttp/src/llhttp.gyp +vendor/llhttp/src/llhttp.ts +vendor/llhttp/src/llhttp/c-headers.ts +vendor/llhttp/src/llhttp/constants.ts +vendor/llhttp/src/llhttp/http.ts +vendor/llhttp/src/llhttp/url.ts +vendor/llhttp/src/llhttp/utils.ts +vendor/llhttp/src/native/api.c +vendor/llhttp/src/native/api.h +vendor/llhttp/src/native/http.c +vendor/llhttp/test/md-test.ts +vendor/llhttp/test/url.md +vendor/llhttp/test/fixtures/extra.c +vendor/llhttp/test/fixtures/index.ts +vendor/llhttp/test/fuzzers/fuzz_parser.c +vendor/llhttp/test/request/connection.md +vendor/llhttp/test/request/content-length.md +vendor/llhttp/test/request/finish.md +vendor/llhttp/test/request/invalid.md +vendor/llhttp/test/request/lenient-headers.md +vendor/llhttp/test/request/lenient-version.md +vendor/llhttp/test/request/method.md +vendor/llhttp/test/request/pausing.md +vendor/llhttp/test/request/pipelining.md +vendor/llhttp/test/request/sample.md +vendor/llhttp/test/request/transfer-encoding.md +vendor/llhttp/test/request/uri.md +vendor/llhttp/test/response/connection.md +vendor/llhttp/test/response/content-length.md +vendor/llhttp/test/response/finish.md +vendor/llhttp/test/response/invalid.md +vendor/llhttp/test/response/lenient-version.md +vendor/llhttp/test/response/pausing.md +vendor/llhttp/test/response/pipelining.md +vendor/llhttp/test/response/sample.md +vendor/llhttp/test/response/transfer-encoding.md \ No newline at end of file diff --git a/aiohttp.egg-info/not-zip-safe b/aiohttp.egg-info/not-zip-safe new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/aiohttp.egg-info/not-zip-safe @@ -0,0 +1 @@ + diff --git a/aiohttp.egg-info/requires.txt b/aiohttp.egg-info/requires.txt index ea57466..7c8bd86 100644 --- a/aiohttp.egg-info/requires.txt +++ b/aiohttp.egg-info/requires.txt @@ -1,14 +1,21 @@ attrs>=17.3.0 -chardet<4.0,>=2.0 +charset-normalizer<4.0,>=2.0 multidict<7.0,>=4.5 -async_timeout<4.0,>=3.0 +async_timeout<5.0,>=4.0.0a3 yarl<2.0,>=1.0 -typing_extensions>=3.6.5 +frozenlist>=1.1.1 +aiosignal>=1.1.2 [:python_version < "3.7"] idna-ssl>=1.0 +[:python_version < "3.8"] +asynctest==0.13.0 +typing_extensions>=3.7.4 + [speedups] aiodns -brotlipy +Brotli + +[speedups:python_version < "3.10"] cchardet diff --git a/aiohttp/.hash/_cparser.pxd.hash b/aiohttp/.hash/_cparser.pxd.hash index 7f4060a..65e3d4b 100644 --- a/aiohttp/.hash/_cparser.pxd.hash +++ b/aiohttp/.hash/_cparser.pxd.hash @@ -1 +1 @@ -b60c37d122fa91049ccf318c94c871d82ba17ff3bc3fc64f8a65426fce7120b7 /home/runner/work/aiohttp/aiohttp/aiohttp/_cparser.pxd +f2318883e549f69de597009a914603b0f1b10381e265ef5d98af499ad973fb98 /home/runner/work/aiohttp/aiohttp/aiohttp/_cparser.pxd diff --git a/aiohttp/.hash/_frozenlist.pyx.hash b/aiohttp/.hash/_frozenlist.pyx.hash deleted file mode 100644 index ccad753..0000000 --- a/aiohttp/.hash/_frozenlist.pyx.hash +++ /dev/null @@ -1 +0,0 @@ -043f0b704444c6c59da38ab3bae43ce1ff8bfe91d5ce45103b494400e7b71688 /home/runner/work/aiohttp/aiohttp/aiohttp/_frozenlist.pyx diff --git a/aiohttp/.hash/_http_parser.pyx.hash b/aiohttp/.hash/_http_parser.pyx.hash index ea0ea79..8e5a141 100644 --- a/aiohttp/.hash/_http_parser.pyx.hash +++ b/aiohttp/.hash/_http_parser.pyx.hash @@ -1 +1 @@ -f0688fb2e81ea92bf0a17822260d9591a30979101da12a4b873113fc459fb5fa /home/runner/work/aiohttp/aiohttp/aiohttp/_http_parser.pyx +7f32b0c1595c1a71957a218ece8d3977ed9171caad97df8fcd82aa80addfc5d2 /home/runner/work/aiohttp/aiohttp/aiohttp/_http_parser.pyx diff --git a/aiohttp/.hash/_http_writer.pyx.hash b/aiohttp/.hash/_http_writer.pyx.hash index b325e7d..8e1aaab 100644 --- a/aiohttp/.hash/_http_writer.pyx.hash +++ b/aiohttp/.hash/_http_writer.pyx.hash @@ -1 +1 @@ -4e7b7f7baa5c65954e85a5b7c8db7786a0ec3498081b0a9420f792a803086281 /home/runner/work/aiohttp/aiohttp/aiohttp/_http_writer.pyx +6881c0a7c838655e646c645d99971efaf5e310bc3633a7c62b226e39d81842ac /home/runner/work/aiohttp/aiohttp/aiohttp/_http_writer.pyx diff --git a/aiohttp/.hash/frozenlist.pyi.hash b/aiohttp/.hash/frozenlist.pyi.hash deleted file mode 100644 index e461073..0000000 --- a/aiohttp/.hash/frozenlist.pyi.hash +++ /dev/null @@ -1 +0,0 @@ -6d134aa08da3d6ba0f76d81fc7f9ec7836a7bc1a99b1950d1c3aa65ed7e3951a /home/runner/work/aiohttp/aiohttp/aiohttp/frozenlist.pyi diff --git a/aiohttp/.hash/hdrs.py.hash b/aiohttp/.hash/hdrs.py.hash index 0e34777..1c8653f 100644 --- a/aiohttp/.hash/hdrs.py.hash +++ b/aiohttp/.hash/hdrs.py.hash @@ -1 +1 @@ -5ac8c3258003604c8993bfa8357361036337330b722e4849024972ccbb5c95f5 /home/runner/work/aiohttp/aiohttp/aiohttp/hdrs.py +a30351c34760a1d7835b2a1b0552e463cf1d2db90da0cdb473313dc66e34a031 /home/runner/work/aiohttp/aiohttp/aiohttp/hdrs.py diff --git a/aiohttp/.hash/signals.pyi.hash b/aiohttp/.hash/signals.pyi.hash deleted file mode 100644 index 29acd69..0000000 --- a/aiohttp/.hash/signals.pyi.hash +++ /dev/null @@ -1 +0,0 @@ -48b4df50f771d7e8385524ea0a7057ca1482974f8a43e674982b04b08bc17d5e /home/runner/work/aiohttp/aiohttp/aiohttp/signals.pyi diff --git a/aiohttp/__init__.py b/aiohttp/__init__.py index 23cd5c9..8bc7a4a 100644 --- a/aiohttp/__init__.py +++ b/aiohttp/__init__.py @@ -1,4 +1,4 @@ -__version__ = "3.7.4" +__version__ = "3.8.6" from typing import Tuple @@ -38,7 +38,7 @@ ) from .cookiejar import CookieJar as CookieJar, DummyCookieJar as DummyCookieJar from .formdata import FormData as FormData -from .helpers import BasicAuth as BasicAuth, ChainMapProxy as ChainMapProxy +from .helpers import BasicAuth, ChainMapProxy, ETag from .http import ( HttpVersion as HttpVersion, HttpVersion10 as HttpVersion10, @@ -78,7 +78,6 @@ DefaultResolver as DefaultResolver, ThreadedResolver as ThreadedResolver, ) -from .signals import Signal as Signal from .streams import ( EMPTY_PAYLOAD as EMPTY_PAYLOAD, DataQueue as DataQueue, @@ -147,6 +146,7 @@ # helpers "BasicAuth", "ChainMapProxy", + "ETag", # http "HttpVersion", "HttpVersion10", @@ -183,8 +183,7 @@ "AsyncResolver", "DefaultResolver", "ThreadedResolver", - # signals - "Signal", + # streams "DataQueue", "EMPTY_PAYLOAD", "EofStream", diff --git a/aiohttp/_cparser.pxd b/aiohttp/_cparser.pxd index 0f9fc00..c2cd5a9 100644 --- a/aiohttp/_cparser.pxd +++ b/aiohttp/_cparser.pxd @@ -1,140 +1,158 @@ -from libc.stdint cimport uint16_t, uint32_t, uint64_t +from libc.stdint cimport int32_t, uint8_t, uint16_t, uint64_t -cdef extern from "../vendor/http-parser/http_parser.h": - ctypedef int (*http_data_cb) (http_parser*, - const char *at, - size_t length) except -1 +cdef extern from "../vendor/llhttp/build/llhttp.h": - ctypedef int (*http_cb) (http_parser*) except -1 - - struct http_parser: - unsigned int type - unsigned int flags - unsigned int state - unsigned int header_state - unsigned int index - - uint32_t nread + struct llhttp__internal_s: + int32_t _index + void* _span_pos0 + void* _span_cb0 + int32_t error + const char* reason + const char* error_pos + void* data + void* _current uint64_t content_length - - unsigned short http_major - unsigned short http_minor - unsigned int status_code - unsigned int method - unsigned int http_errno - - unsigned int upgrade - - void *data - - struct http_parser_settings: - http_cb on_message_begin - http_data_cb on_url - http_data_cb on_status - http_data_cb on_header_field - http_data_cb on_header_value - http_cb on_headers_complete - http_data_cb on_body - http_cb on_message_complete - http_cb on_chunk_header - http_cb on_chunk_complete - - enum http_parser_type: - HTTP_REQUEST, - HTTP_RESPONSE, - HTTP_BOTH - - enum http_errno: + uint8_t type + uint8_t method + uint8_t http_major + uint8_t http_minor + uint8_t header_state + uint8_t lenient_flags + uint8_t upgrade + uint8_t finish + uint16_t flags + uint16_t status_code + void* settings + + ctypedef llhttp__internal_s llhttp__internal_t + ctypedef llhttp__internal_t llhttp_t + + ctypedef int (*llhttp_data_cb)(llhttp_t*, const char *at, size_t length) except -1 + ctypedef int (*llhttp_cb)(llhttp_t*) except -1 + + struct llhttp_settings_s: + llhttp_cb on_message_begin + llhttp_data_cb on_url + llhttp_data_cb on_status + llhttp_data_cb on_header_field + llhttp_data_cb on_header_value + llhttp_cb on_headers_complete + llhttp_data_cb on_body + llhttp_cb on_message_complete + llhttp_cb on_chunk_header + llhttp_cb on_chunk_complete + + llhttp_cb on_url_complete + llhttp_cb on_status_complete + llhttp_cb on_header_field_complete + llhttp_cb on_header_value_complete + + ctypedef llhttp_settings_s llhttp_settings_t + + enum llhttp_errno: HPE_OK, - HPE_CB_message_begin, - HPE_CB_url, - HPE_CB_header_field, - HPE_CB_header_value, - HPE_CB_headers_complete, - HPE_CB_body, - HPE_CB_message_complete, - HPE_CB_status, - HPE_CB_chunk_header, - HPE_CB_chunk_complete, - HPE_INVALID_EOF_STATE, - HPE_HEADER_OVERFLOW, + HPE_INTERNAL, + HPE_STRICT, + HPE_LF_EXPECTED, + HPE_UNEXPECTED_CONTENT_LENGTH, HPE_CLOSED_CONNECTION, - HPE_INVALID_VERSION, - HPE_INVALID_STATUS, HPE_INVALID_METHOD, HPE_INVALID_URL, - HPE_INVALID_HOST, - HPE_INVALID_PORT, - HPE_INVALID_PATH, - HPE_INVALID_QUERY_STRING, - HPE_INVALID_FRAGMENT, - HPE_LF_EXPECTED, + HPE_INVALID_CONSTANT, + HPE_INVALID_VERSION, HPE_INVALID_HEADER_TOKEN, HPE_INVALID_CONTENT_LENGTH, HPE_INVALID_CHUNK_SIZE, - HPE_INVALID_CONSTANT, - HPE_INVALID_INTERNAL_STATE, - HPE_STRICT, + HPE_INVALID_STATUS, + HPE_INVALID_EOF_STATE, + HPE_INVALID_TRANSFER_ENCODING, + HPE_CB_MESSAGE_BEGIN, + HPE_CB_HEADERS_COMPLETE, + HPE_CB_MESSAGE_COMPLETE, + HPE_CB_CHUNK_HEADER, + HPE_CB_CHUNK_COMPLETE, HPE_PAUSED, - HPE_UNKNOWN + HPE_PAUSED_UPGRADE, + HPE_USER - enum flags: + ctypedef llhttp_errno llhttp_errno_t + + enum llhttp_flags: F_CHUNKED, - F_CONNECTION_KEEP_ALIVE, - F_CONNECTION_CLOSE, - F_CONNECTION_UPGRADE, - F_TRAILING, - F_UPGRADE, - F_SKIPBODY, - F_CONTENTLENGTH - - enum http_method: - DELETE, GET, HEAD, POST, PUT, CONNECT, OPTIONS, TRACE, COPY, - LOCK, MKCOL, MOVE, PROPFIND, PROPPATCH, SEARCH, UNLOCK, BIND, - REBIND, UNBIND, ACL, REPORT, MKACTIVITY, CHECKOUT, MERGE, - MSEARCH, NOTIFY, SUBSCRIBE, UNSUBSCRIBE, PATCH, PURGE, MKCALENDAR, - LINK, UNLINK - - void http_parser_init(http_parser *parser, http_parser_type type) - - size_t http_parser_execute(http_parser *parser, - const http_parser_settings *settings, - const char *data, - size_t len) - - int http_should_keep_alive(const http_parser *parser) - - void http_parser_settings_init(http_parser_settings *settings) - - const char *http_errno_name(http_errno err) - const char *http_errno_description(http_errno err) - const char *http_method_str(http_method m) - - # URL Parser - - enum http_parser_url_fields: - UF_SCHEMA = 0, - UF_HOST = 1, - UF_PORT = 2, - UF_PATH = 3, - UF_QUERY = 4, - UF_FRAGMENT = 5, - UF_USERINFO = 6, - UF_MAX = 7 - - struct http_parser_url_field_data: - uint16_t off - uint16_t len - - struct http_parser_url: - uint16_t field_set - uint16_t port - http_parser_url_field_data[UF_MAX] field_data - - void http_parser_url_init(http_parser_url *u) - - int http_parser_parse_url(const char *buf, - size_t buflen, - int is_connect, - http_parser_url *u) + F_CONTENT_LENGTH + + enum llhttp_type: + HTTP_REQUEST, + HTTP_RESPONSE, + HTTP_BOTH + + enum llhttp_method: + HTTP_DELETE, + HTTP_GET, + HTTP_HEAD, + HTTP_POST, + HTTP_PUT, + HTTP_CONNECT, + HTTP_OPTIONS, + HTTP_TRACE, + HTTP_COPY, + HTTP_LOCK, + HTTP_MKCOL, + HTTP_MOVE, + HTTP_PROPFIND, + HTTP_PROPPATCH, + HTTP_SEARCH, + HTTP_UNLOCK, + HTTP_BIND, + HTTP_REBIND, + HTTP_UNBIND, + HTTP_ACL, + HTTP_REPORT, + HTTP_MKACTIVITY, + HTTP_CHECKOUT, + HTTP_MERGE, + HTTP_MSEARCH, + HTTP_NOTIFY, + HTTP_SUBSCRIBE, + HTTP_UNSUBSCRIBE, + HTTP_PATCH, + HTTP_PURGE, + HTTP_MKCALENDAR, + HTTP_LINK, + HTTP_UNLINK, + HTTP_SOURCE, + HTTP_PRI, + HTTP_DESCRIBE, + HTTP_ANNOUNCE, + HTTP_SETUP, + HTTP_PLAY, + HTTP_PAUSE, + HTTP_TEARDOWN, + HTTP_GET_PARAMETER, + HTTP_SET_PARAMETER, + HTTP_REDIRECT, + HTTP_RECORD, + HTTP_FLUSH + + ctypedef llhttp_method llhttp_method_t; + + void llhttp_settings_init(llhttp_settings_t* settings) + void llhttp_init(llhttp_t* parser, llhttp_type type, + const llhttp_settings_t* settings) + + llhttp_errno_t llhttp_execute(llhttp_t* parser, const char* data, size_t len) + + int llhttp_should_keep_alive(const llhttp_t* parser) + + void llhttp_resume_after_upgrade(llhttp_t* parser) + + llhttp_errno_t llhttp_get_errno(const llhttp_t* parser) + const char* llhttp_get_error_reason(const llhttp_t* parser) + const char* llhttp_get_error_pos(const llhttp_t* parser) + + const char* llhttp_method_name(llhttp_method_t method) + + void llhttp_set_lenient_headers(llhttp_t* parser, int enabled) + void llhttp_set_lenient_optional_cr_before_lf(llhttp_t* parser, int enabled) + void llhttp_set_lenient_spaces_after_chunk_size(llhttp_t* parser, int enabled) diff --git a/aiohttp/_frozenlist.c b/aiohttp/_frozenlist.c deleted file mode 100644 index 4a9d382..0000000 --- a/aiohttp/_frozenlist.c +++ /dev/null @@ -1,7512 +0,0 @@ -/* Generated by Cython 0.29.21 */ - -#define PY_SSIZE_T_CLEAN -#include "Python.h" -#ifndef Py_PYTHON_H - #error Python headers needed to compile C extensions, please install development version of Python. -#elif PY_VERSION_HEX < 0x02060000 || (0x03000000 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x03030000) - #error Cython requires Python 2.6+ or Python 3.3+. -#else -#define CYTHON_ABI "0_29_21" -#define CYTHON_HEX_VERSION 0x001D15F0 -#define CYTHON_FUTURE_DIVISION 1 -#include -#ifndef offsetof - #define offsetof(type, member) ( (size_t) & ((type*)0) -> member ) -#endif -#if !defined(WIN32) && !defined(MS_WINDOWS) - #ifndef __stdcall - #define __stdcall - #endif - #ifndef __cdecl - #define __cdecl - #endif - #ifndef __fastcall - #define __fastcall - #endif -#endif -#ifndef DL_IMPORT - #define DL_IMPORT(t) t -#endif -#ifndef DL_EXPORT - #define DL_EXPORT(t) t -#endif -#define __PYX_COMMA , -#ifndef HAVE_LONG_LONG - #if PY_VERSION_HEX >= 0x02070000 - #define HAVE_LONG_LONG - #endif -#endif -#ifndef PY_LONG_LONG - #define PY_LONG_LONG LONG_LONG -#endif -#ifndef Py_HUGE_VAL - #define Py_HUGE_VAL HUGE_VAL -#endif -#ifdef PYPY_VERSION - #define CYTHON_COMPILING_IN_PYPY 1 - #define CYTHON_COMPILING_IN_PYSTON 0 - #define CYTHON_COMPILING_IN_CPYTHON 0 - #undef CYTHON_USE_TYPE_SLOTS - #define CYTHON_USE_TYPE_SLOTS 0 - #undef CYTHON_USE_PYTYPE_LOOKUP - #define CYTHON_USE_PYTYPE_LOOKUP 0 - #if PY_VERSION_HEX < 0x03050000 - #undef CYTHON_USE_ASYNC_SLOTS - #define CYTHON_USE_ASYNC_SLOTS 0 - #elif !defined(CYTHON_USE_ASYNC_SLOTS) - #define CYTHON_USE_ASYNC_SLOTS 1 - #endif - #undef CYTHON_USE_PYLIST_INTERNALS - #define CYTHON_USE_PYLIST_INTERNALS 0 - #undef CYTHON_USE_UNICODE_INTERNALS - #define CYTHON_USE_UNICODE_INTERNALS 0 - #undef CYTHON_USE_UNICODE_WRITER - #define CYTHON_USE_UNICODE_WRITER 0 - #undef CYTHON_USE_PYLONG_INTERNALS - #define CYTHON_USE_PYLONG_INTERNALS 0 - #undef CYTHON_AVOID_BORROWED_REFS - #define CYTHON_AVOID_BORROWED_REFS 1 - #undef CYTHON_ASSUME_SAFE_MACROS - #define CYTHON_ASSUME_SAFE_MACROS 0 - #undef CYTHON_UNPACK_METHODS - #define CYTHON_UNPACK_METHODS 0 - #undef CYTHON_FAST_THREAD_STATE - #define CYTHON_FAST_THREAD_STATE 0 - #undef CYTHON_FAST_PYCALL - #define CYTHON_FAST_PYCALL 0 - #undef CYTHON_PEP489_MULTI_PHASE_INIT - #define CYTHON_PEP489_MULTI_PHASE_INIT 0 - #undef CYTHON_USE_TP_FINALIZE - #define CYTHON_USE_TP_FINALIZE 0 - #undef CYTHON_USE_DICT_VERSIONS - #define CYTHON_USE_DICT_VERSIONS 0 - #undef CYTHON_USE_EXC_INFO_STACK - #define CYTHON_USE_EXC_INFO_STACK 0 -#elif defined(PYSTON_VERSION) - #define CYTHON_COMPILING_IN_PYPY 0 - #define CYTHON_COMPILING_IN_PYSTON 1 - #define CYTHON_COMPILING_IN_CPYTHON 0 - #ifndef CYTHON_USE_TYPE_SLOTS - #define CYTHON_USE_TYPE_SLOTS 1 - #endif - #undef CYTHON_USE_PYTYPE_LOOKUP - #define CYTHON_USE_PYTYPE_LOOKUP 0 - #undef CYTHON_USE_ASYNC_SLOTS - #define CYTHON_USE_ASYNC_SLOTS 0 - #undef CYTHON_USE_PYLIST_INTERNALS - #define CYTHON_USE_PYLIST_INTERNALS 0 - #ifndef CYTHON_USE_UNICODE_INTERNALS - #define CYTHON_USE_UNICODE_INTERNALS 1 - #endif - #undef CYTHON_USE_UNICODE_WRITER - #define CYTHON_USE_UNICODE_WRITER 0 - #undef CYTHON_USE_PYLONG_INTERNALS - #define CYTHON_USE_PYLONG_INTERNALS 0 - #ifndef CYTHON_AVOID_BORROWED_REFS - #define CYTHON_AVOID_BORROWED_REFS 0 - #endif - #ifndef CYTHON_ASSUME_SAFE_MACROS - #define CYTHON_ASSUME_SAFE_MACROS 1 - #endif - #ifndef CYTHON_UNPACK_METHODS - #define CYTHON_UNPACK_METHODS 1 - #endif - #undef CYTHON_FAST_THREAD_STATE - #define CYTHON_FAST_THREAD_STATE 0 - #undef CYTHON_FAST_PYCALL - #define CYTHON_FAST_PYCALL 0 - #undef CYTHON_PEP489_MULTI_PHASE_INIT - #define CYTHON_PEP489_MULTI_PHASE_INIT 0 - #undef CYTHON_USE_TP_FINALIZE - #define CYTHON_USE_TP_FINALIZE 0 - #undef CYTHON_USE_DICT_VERSIONS - #define CYTHON_USE_DICT_VERSIONS 0 - #undef CYTHON_USE_EXC_INFO_STACK - #define CYTHON_USE_EXC_INFO_STACK 0 -#else - #define CYTHON_COMPILING_IN_PYPY 0 - #define CYTHON_COMPILING_IN_PYSTON 0 - #define CYTHON_COMPILING_IN_CPYTHON 1 - #ifndef CYTHON_USE_TYPE_SLOTS - #define CYTHON_USE_TYPE_SLOTS 1 - #endif - #if PY_VERSION_HEX < 0x02070000 - #undef CYTHON_USE_PYTYPE_LOOKUP - #define CYTHON_USE_PYTYPE_LOOKUP 0 - #elif !defined(CYTHON_USE_PYTYPE_LOOKUP) - #define CYTHON_USE_PYTYPE_LOOKUP 1 - #endif - #if PY_MAJOR_VERSION < 3 - #undef CYTHON_USE_ASYNC_SLOTS - #define CYTHON_USE_ASYNC_SLOTS 0 - #elif !defined(CYTHON_USE_ASYNC_SLOTS) - #define CYTHON_USE_ASYNC_SLOTS 1 - #endif - #if PY_VERSION_HEX < 0x02070000 - #undef CYTHON_USE_PYLONG_INTERNALS - #define CYTHON_USE_PYLONG_INTERNALS 0 - #elif !defined(CYTHON_USE_PYLONG_INTERNALS) - #define CYTHON_USE_PYLONG_INTERNALS 1 - #endif - #ifndef CYTHON_USE_PYLIST_INTERNALS - #define CYTHON_USE_PYLIST_INTERNALS 1 - #endif - #ifndef CYTHON_USE_UNICODE_INTERNALS - #define CYTHON_USE_UNICODE_INTERNALS 1 - #endif - #if PY_VERSION_HEX < 0x030300F0 - #undef CYTHON_USE_UNICODE_WRITER - #define CYTHON_USE_UNICODE_WRITER 0 - #elif !defined(CYTHON_USE_UNICODE_WRITER) - #define CYTHON_USE_UNICODE_WRITER 1 - #endif - #ifndef CYTHON_AVOID_BORROWED_REFS - #define CYTHON_AVOID_BORROWED_REFS 0 - #endif - #ifndef CYTHON_ASSUME_SAFE_MACROS - #define CYTHON_ASSUME_SAFE_MACROS 1 - #endif - #ifndef CYTHON_UNPACK_METHODS - #define CYTHON_UNPACK_METHODS 1 - #endif - #ifndef CYTHON_FAST_THREAD_STATE - #define CYTHON_FAST_THREAD_STATE 1 - #endif - #ifndef CYTHON_FAST_PYCALL - #define CYTHON_FAST_PYCALL 1 - #endif - #ifndef CYTHON_PEP489_MULTI_PHASE_INIT - #define CYTHON_PEP489_MULTI_PHASE_INIT (PY_VERSION_HEX >= 0x03050000) - #endif - #ifndef CYTHON_USE_TP_FINALIZE - #define CYTHON_USE_TP_FINALIZE (PY_VERSION_HEX >= 0x030400a1) - #endif - #ifndef CYTHON_USE_DICT_VERSIONS - #define CYTHON_USE_DICT_VERSIONS (PY_VERSION_HEX >= 0x030600B1) - #endif - #ifndef CYTHON_USE_EXC_INFO_STACK - #define CYTHON_USE_EXC_INFO_STACK (PY_VERSION_HEX >= 0x030700A3) - #endif -#endif -#if !defined(CYTHON_FAST_PYCCALL) -#define CYTHON_FAST_PYCCALL (CYTHON_FAST_PYCALL && PY_VERSION_HEX >= 0x030600B1) -#endif -#if CYTHON_USE_PYLONG_INTERNALS - #include "longintrepr.h" - #undef SHIFT - #undef BASE - #undef MASK - #ifdef SIZEOF_VOID_P - enum { __pyx_check_sizeof_voidp = 1 / (int)(SIZEOF_VOID_P == sizeof(void*)) }; - #endif -#endif -#ifndef __has_attribute - #define __has_attribute(x) 0 -#endif -#ifndef __has_cpp_attribute - #define __has_cpp_attribute(x) 0 -#endif -#ifndef CYTHON_RESTRICT - #if defined(__GNUC__) - #define CYTHON_RESTRICT __restrict__ - #elif defined(_MSC_VER) && _MSC_VER >= 1400 - #define CYTHON_RESTRICT __restrict - #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L - #define CYTHON_RESTRICT restrict - #else - #define CYTHON_RESTRICT - #endif -#endif -#ifndef CYTHON_UNUSED -# if defined(__GNUC__) -# if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) -# define CYTHON_UNUSED __attribute__ ((__unused__)) -# else -# define CYTHON_UNUSED -# endif -# elif defined(__ICC) || (defined(__INTEL_COMPILER) && !defined(_MSC_VER)) -# define CYTHON_UNUSED __attribute__ ((__unused__)) -# else -# define CYTHON_UNUSED -# endif -#endif -#ifndef CYTHON_MAYBE_UNUSED_VAR -# if defined(__cplusplus) - template void CYTHON_MAYBE_UNUSED_VAR( const T& ) { } -# else -# define CYTHON_MAYBE_UNUSED_VAR(x) (void)(x) -# endif -#endif -#ifndef CYTHON_NCP_UNUSED -# if CYTHON_COMPILING_IN_CPYTHON -# define CYTHON_NCP_UNUSED -# else -# define CYTHON_NCP_UNUSED CYTHON_UNUSED -# endif -#endif -#define __Pyx_void_to_None(void_result) ((void)(void_result), Py_INCREF(Py_None), Py_None) -#ifdef _MSC_VER - #ifndef _MSC_STDINT_H_ - #if _MSC_VER < 1300 - typedef unsigned char uint8_t; - typedef unsigned int uint32_t; - #else - typedef unsigned __int8 uint8_t; - typedef unsigned __int32 uint32_t; - #endif - #endif -#else - #include -#endif -#ifndef CYTHON_FALLTHROUGH - #if defined(__cplusplus) && __cplusplus >= 201103L - #if __has_cpp_attribute(fallthrough) - #define CYTHON_FALLTHROUGH [[fallthrough]] - #elif __has_cpp_attribute(clang::fallthrough) - #define CYTHON_FALLTHROUGH [[clang::fallthrough]] - #elif __has_cpp_attribute(gnu::fallthrough) - #define CYTHON_FALLTHROUGH [[gnu::fallthrough]] - #endif - #endif - #ifndef CYTHON_FALLTHROUGH - #if __has_attribute(fallthrough) - #define CYTHON_FALLTHROUGH __attribute__((fallthrough)) - #else - #define CYTHON_FALLTHROUGH - #endif - #endif - #if defined(__clang__ ) && defined(__apple_build_version__) - #if __apple_build_version__ < 7000000 - #undef CYTHON_FALLTHROUGH - #define CYTHON_FALLTHROUGH - #endif - #endif -#endif - -#ifndef CYTHON_INLINE - #if defined(__clang__) - #define CYTHON_INLINE __inline__ __attribute__ ((__unused__)) - #elif defined(__GNUC__) - #define CYTHON_INLINE __inline__ - #elif defined(_MSC_VER) - #define CYTHON_INLINE __inline - #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L - #define CYTHON_INLINE inline - #else - #define CYTHON_INLINE - #endif -#endif - -#if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX < 0x02070600 && !defined(Py_OptimizeFlag) - #define Py_OptimizeFlag 0 -#endif -#define __PYX_BUILD_PY_SSIZE_T "n" -#define CYTHON_FORMAT_SSIZE_T "z" -#if PY_MAJOR_VERSION < 3 - #define __Pyx_BUILTIN_MODULE_NAME "__builtin__" - #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ - PyCode_New(a+k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) - #define __Pyx_DefaultClassType PyClass_Type -#else - #define __Pyx_BUILTIN_MODULE_NAME "builtins" -#if PY_VERSION_HEX >= 0x030800A4 && PY_VERSION_HEX < 0x030800B2 - #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ - PyCode_New(a, 0, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) -#else - #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ - PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) -#endif - #define __Pyx_DefaultClassType PyType_Type -#endif -#ifndef Py_TPFLAGS_CHECKTYPES - #define Py_TPFLAGS_CHECKTYPES 0 -#endif -#ifndef Py_TPFLAGS_HAVE_INDEX - #define Py_TPFLAGS_HAVE_INDEX 0 -#endif -#ifndef Py_TPFLAGS_HAVE_NEWBUFFER - #define Py_TPFLAGS_HAVE_NEWBUFFER 0 -#endif -#ifndef Py_TPFLAGS_HAVE_FINALIZE - #define Py_TPFLAGS_HAVE_FINALIZE 0 -#endif -#ifndef METH_STACKLESS - #define METH_STACKLESS 0 -#endif -#if PY_VERSION_HEX <= 0x030700A3 || !defined(METH_FASTCALL) - #ifndef METH_FASTCALL - #define METH_FASTCALL 0x80 - #endif - typedef PyObject *(*__Pyx_PyCFunctionFast) (PyObject *self, PyObject *const *args, Py_ssize_t nargs); - typedef PyObject *(*__Pyx_PyCFunctionFastWithKeywords) (PyObject *self, PyObject *const *args, - Py_ssize_t nargs, PyObject *kwnames); -#else - #define __Pyx_PyCFunctionFast _PyCFunctionFast - #define __Pyx_PyCFunctionFastWithKeywords _PyCFunctionFastWithKeywords -#endif -#if CYTHON_FAST_PYCCALL -#define __Pyx_PyFastCFunction_Check(func)\ - ((PyCFunction_Check(func) && (METH_FASTCALL == (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST | METH_KEYWORDS | METH_STACKLESS))))) -#else -#define __Pyx_PyFastCFunction_Check(func) 0 -#endif -#if CYTHON_COMPILING_IN_PYPY && !defined(PyObject_Malloc) - #define PyObject_Malloc(s) PyMem_Malloc(s) - #define PyObject_Free(p) PyMem_Free(p) - #define PyObject_Realloc(p) PyMem_Realloc(p) -#endif -#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX < 0x030400A1 - #define PyMem_RawMalloc(n) PyMem_Malloc(n) - #define PyMem_RawRealloc(p, n) PyMem_Realloc(p, n) - #define PyMem_RawFree(p) PyMem_Free(p) -#endif -#if CYTHON_COMPILING_IN_PYSTON - #define __Pyx_PyCode_HasFreeVars(co) PyCode_HasFreeVars(co) - #define __Pyx_PyFrame_SetLineNumber(frame, lineno) PyFrame_SetLineNumber(frame, lineno) -#else - #define __Pyx_PyCode_HasFreeVars(co) (PyCode_GetNumFree(co) > 0) - #define __Pyx_PyFrame_SetLineNumber(frame, lineno) (frame)->f_lineno = (lineno) -#endif -#if !CYTHON_FAST_THREAD_STATE || PY_VERSION_HEX < 0x02070000 - #define __Pyx_PyThreadState_Current PyThreadState_GET() -#elif PY_VERSION_HEX >= 0x03060000 - #define __Pyx_PyThreadState_Current _PyThreadState_UncheckedGet() -#elif PY_VERSION_HEX >= 0x03000000 - #define __Pyx_PyThreadState_Current PyThreadState_GET() -#else - #define __Pyx_PyThreadState_Current _PyThreadState_Current -#endif -#if PY_VERSION_HEX < 0x030700A2 && !defined(PyThread_tss_create) && !defined(Py_tss_NEEDS_INIT) -#include "pythread.h" -#define Py_tss_NEEDS_INIT 0 -typedef int Py_tss_t; -static CYTHON_INLINE int PyThread_tss_create(Py_tss_t *key) { - *key = PyThread_create_key(); - return 0; -} -static CYTHON_INLINE Py_tss_t * PyThread_tss_alloc(void) { - Py_tss_t *key = (Py_tss_t *)PyObject_Malloc(sizeof(Py_tss_t)); - *key = Py_tss_NEEDS_INIT; - return key; -} -static CYTHON_INLINE void PyThread_tss_free(Py_tss_t *key) { - PyObject_Free(key); -} -static CYTHON_INLINE int PyThread_tss_is_created(Py_tss_t *key) { - return *key != Py_tss_NEEDS_INIT; -} -static CYTHON_INLINE void PyThread_tss_delete(Py_tss_t *key) { - PyThread_delete_key(*key); - *key = Py_tss_NEEDS_INIT; -} -static CYTHON_INLINE int PyThread_tss_set(Py_tss_t *key, void *value) { - return PyThread_set_key_value(*key, value); -} -static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) { - return PyThread_get_key_value(*key); -} -#endif -#if CYTHON_COMPILING_IN_CPYTHON || defined(_PyDict_NewPresized) -#define __Pyx_PyDict_NewPresized(n) ((n <= 8) ? PyDict_New() : _PyDict_NewPresized(n)) -#else -#define __Pyx_PyDict_NewPresized(n) PyDict_New() -#endif -#if PY_MAJOR_VERSION >= 3 || CYTHON_FUTURE_DIVISION - #define __Pyx_PyNumber_Divide(x,y) PyNumber_TrueDivide(x,y) - #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceTrueDivide(x,y) -#else - #define __Pyx_PyNumber_Divide(x,y) PyNumber_Divide(x,y) - #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceDivide(x,y) -#endif -#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030500A1 && CYTHON_USE_UNICODE_INTERNALS -#define __Pyx_PyDict_GetItemStr(dict, name) _PyDict_GetItem_KnownHash(dict, name, ((PyASCIIObject *) name)->hash) -#else -#define __Pyx_PyDict_GetItemStr(dict, name) PyDict_GetItem(dict, name) -#endif -#if PY_VERSION_HEX > 0x03030000 && defined(PyUnicode_KIND) - #define CYTHON_PEP393_ENABLED 1 - #define __Pyx_PyUnicode_READY(op) (likely(PyUnicode_IS_READY(op)) ?\ - 0 : _PyUnicode_Ready((PyObject *)(op))) - #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_LENGTH(u) - #define __Pyx_PyUnicode_READ_CHAR(u, i) PyUnicode_READ_CHAR(u, i) - #define __Pyx_PyUnicode_MAX_CHAR_VALUE(u) PyUnicode_MAX_CHAR_VALUE(u) - #define __Pyx_PyUnicode_KIND(u) PyUnicode_KIND(u) - #define __Pyx_PyUnicode_DATA(u) PyUnicode_DATA(u) - #define __Pyx_PyUnicode_READ(k, d, i) PyUnicode_READ(k, d, i) - #define __Pyx_PyUnicode_WRITE(k, d, i, ch) PyUnicode_WRITE(k, d, i, ch) - #if defined(PyUnicode_IS_READY) && defined(PyUnicode_GET_SIZE) - #define __Pyx_PyUnicode_IS_TRUE(u) (0 != (likely(PyUnicode_IS_READY(u)) ? PyUnicode_GET_LENGTH(u) : PyUnicode_GET_SIZE(u))) - #else - #define __Pyx_PyUnicode_IS_TRUE(u) (0 != PyUnicode_GET_LENGTH(u)) - #endif -#else - #define CYTHON_PEP393_ENABLED 0 - #define PyUnicode_1BYTE_KIND 1 - #define PyUnicode_2BYTE_KIND 2 - #define PyUnicode_4BYTE_KIND 4 - #define __Pyx_PyUnicode_READY(op) (0) - #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_SIZE(u) - #define __Pyx_PyUnicode_READ_CHAR(u, i) ((Py_UCS4)(PyUnicode_AS_UNICODE(u)[i])) - #define __Pyx_PyUnicode_MAX_CHAR_VALUE(u) ((sizeof(Py_UNICODE) == 2) ? 65535 : 1114111) - #define __Pyx_PyUnicode_KIND(u) (sizeof(Py_UNICODE)) - #define __Pyx_PyUnicode_DATA(u) ((void*)PyUnicode_AS_UNICODE(u)) - #define __Pyx_PyUnicode_READ(k, d, i) ((void)(k), (Py_UCS4)(((Py_UNICODE*)d)[i])) - #define __Pyx_PyUnicode_WRITE(k, d, i, ch) (((void)(k)), ((Py_UNICODE*)d)[i] = ch) - #define __Pyx_PyUnicode_IS_TRUE(u) (0 != PyUnicode_GET_SIZE(u)) -#endif -#if CYTHON_COMPILING_IN_PYPY - #define __Pyx_PyUnicode_Concat(a, b) PyNumber_Add(a, b) - #define __Pyx_PyUnicode_ConcatSafe(a, b) PyNumber_Add(a, b) -#else - #define __Pyx_PyUnicode_Concat(a, b) PyUnicode_Concat(a, b) - #define __Pyx_PyUnicode_ConcatSafe(a, b) ((unlikely((a) == Py_None) || unlikely((b) == Py_None)) ?\ - PyNumber_Add(a, b) : __Pyx_PyUnicode_Concat(a, b)) -#endif -#if CYTHON_COMPILING_IN_PYPY && !defined(PyUnicode_Contains) - #define PyUnicode_Contains(u, s) PySequence_Contains(u, s) -#endif -#if CYTHON_COMPILING_IN_PYPY && !defined(PyByteArray_Check) - #define PyByteArray_Check(obj) PyObject_TypeCheck(obj, &PyByteArray_Type) -#endif -#if CYTHON_COMPILING_IN_PYPY && !defined(PyObject_Format) - #define PyObject_Format(obj, fmt) PyObject_CallMethod(obj, "__format__", "O", fmt) -#endif -#define __Pyx_PyString_FormatSafe(a, b) ((unlikely((a) == Py_None || (PyString_Check(b) && !PyString_CheckExact(b)))) ? PyNumber_Remainder(a, b) : __Pyx_PyString_Format(a, b)) -#define __Pyx_PyUnicode_FormatSafe(a, b) ((unlikely((a) == Py_None || (PyUnicode_Check(b) && !PyUnicode_CheckExact(b)))) ? PyNumber_Remainder(a, b) : PyUnicode_Format(a, b)) -#if PY_MAJOR_VERSION >= 3 - #define __Pyx_PyString_Format(a, b) PyUnicode_Format(a, b) -#else - #define __Pyx_PyString_Format(a, b) PyString_Format(a, b) -#endif -#if PY_MAJOR_VERSION < 3 && !defined(PyObject_ASCII) - #define PyObject_ASCII(o) PyObject_Repr(o) -#endif -#if PY_MAJOR_VERSION >= 3 - #define PyBaseString_Type PyUnicode_Type - #define PyStringObject PyUnicodeObject - #define PyString_Type PyUnicode_Type - #define PyString_Check PyUnicode_Check - #define PyString_CheckExact PyUnicode_CheckExact -#ifndef PyObject_Unicode - #define PyObject_Unicode PyObject_Str -#endif -#endif -#if PY_MAJOR_VERSION >= 3 - #define __Pyx_PyBaseString_Check(obj) PyUnicode_Check(obj) - #define __Pyx_PyBaseString_CheckExact(obj) PyUnicode_CheckExact(obj) -#else - #define __Pyx_PyBaseString_Check(obj) (PyString_Check(obj) || PyUnicode_Check(obj)) - #define __Pyx_PyBaseString_CheckExact(obj) (PyString_CheckExact(obj) || PyUnicode_CheckExact(obj)) -#endif -#ifndef PySet_CheckExact - #define PySet_CheckExact(obj) (Py_TYPE(obj) == &PySet_Type) -#endif -#if PY_VERSION_HEX >= 0x030900A4 - #define __Pyx_SET_REFCNT(obj, refcnt) Py_SET_REFCNT(obj, refcnt) - #define __Pyx_SET_SIZE(obj, size) Py_SET_SIZE(obj, size) -#else - #define __Pyx_SET_REFCNT(obj, refcnt) Py_REFCNT(obj) = (refcnt) - #define __Pyx_SET_SIZE(obj, size) Py_SIZE(obj) = (size) -#endif -#if CYTHON_ASSUME_SAFE_MACROS - #define __Pyx_PySequence_SIZE(seq) Py_SIZE(seq) -#else - #define __Pyx_PySequence_SIZE(seq) PySequence_Size(seq) -#endif -#if PY_MAJOR_VERSION >= 3 - #define PyIntObject PyLongObject - #define PyInt_Type PyLong_Type - #define PyInt_Check(op) PyLong_Check(op) - #define PyInt_CheckExact(op) PyLong_CheckExact(op) - #define PyInt_FromString PyLong_FromString - #define PyInt_FromUnicode PyLong_FromUnicode - #define PyInt_FromLong PyLong_FromLong - #define PyInt_FromSize_t PyLong_FromSize_t - #define PyInt_FromSsize_t PyLong_FromSsize_t - #define PyInt_AsLong PyLong_AsLong - #define PyInt_AS_LONG PyLong_AS_LONG - #define PyInt_AsSsize_t PyLong_AsSsize_t - #define PyInt_AsUnsignedLongMask PyLong_AsUnsignedLongMask - #define PyInt_AsUnsignedLongLongMask PyLong_AsUnsignedLongLongMask - #define PyNumber_Int PyNumber_Long -#endif -#if PY_MAJOR_VERSION >= 3 - #define PyBoolObject PyLongObject -#endif -#if PY_MAJOR_VERSION >= 3 && CYTHON_COMPILING_IN_PYPY - #ifndef PyUnicode_InternFromString - #define PyUnicode_InternFromString(s) PyUnicode_FromString(s) - #endif -#endif -#if PY_VERSION_HEX < 0x030200A4 - typedef long Py_hash_t; - #define __Pyx_PyInt_FromHash_t PyInt_FromLong - #define __Pyx_PyInt_AsHash_t PyInt_AsLong -#else - #define __Pyx_PyInt_FromHash_t PyInt_FromSsize_t - #define __Pyx_PyInt_AsHash_t PyInt_AsSsize_t -#endif -#if PY_MAJOR_VERSION >= 3 - #define __Pyx_PyMethod_New(func, self, klass) ((self) ? ((void)(klass), PyMethod_New(func, self)) : __Pyx_NewRef(func)) -#else - #define __Pyx_PyMethod_New(func, self, klass) PyMethod_New(func, self, klass) -#endif -#if CYTHON_USE_ASYNC_SLOTS - #if PY_VERSION_HEX >= 0x030500B1 - #define __Pyx_PyAsyncMethodsStruct PyAsyncMethods - #define __Pyx_PyType_AsAsync(obj) (Py_TYPE(obj)->tp_as_async) - #else - #define __Pyx_PyType_AsAsync(obj) ((__Pyx_PyAsyncMethodsStruct*) (Py_TYPE(obj)->tp_reserved)) - #endif -#else - #define __Pyx_PyType_AsAsync(obj) NULL -#endif -#ifndef __Pyx_PyAsyncMethodsStruct - typedef struct { - unaryfunc am_await; - unaryfunc am_aiter; - unaryfunc am_anext; - } __Pyx_PyAsyncMethodsStruct; -#endif - -#if defined(WIN32) || defined(MS_WINDOWS) - #define _USE_MATH_DEFINES -#endif -#include -#ifdef NAN -#define __PYX_NAN() ((float) NAN) -#else -static CYTHON_INLINE float __PYX_NAN() { - float value; - memset(&value, 0xFF, sizeof(value)); - return value; -} -#endif -#if defined(__CYGWIN__) && defined(_LDBL_EQ_DBL) -#define __Pyx_truncl trunc -#else -#define __Pyx_truncl truncl -#endif - -#define __PYX_MARK_ERR_POS(f_index, lineno) \ - { __pyx_filename = __pyx_f[f_index]; (void)__pyx_filename; __pyx_lineno = lineno; (void)__pyx_lineno; __pyx_clineno = __LINE__; (void)__pyx_clineno; } -#define __PYX_ERR(f_index, lineno, Ln_error) \ - { __PYX_MARK_ERR_POS(f_index, lineno) goto Ln_error; } - -#ifndef __PYX_EXTERN_C - #ifdef __cplusplus - #define __PYX_EXTERN_C extern "C" - #else - #define __PYX_EXTERN_C extern - #endif -#endif - -#define __PYX_HAVE__aiohttp___frozenlist -#define __PYX_HAVE_API__aiohttp___frozenlist -/* Early includes */ -#ifdef _OPENMP -#include -#endif /* _OPENMP */ - -#if defined(PYREX_WITHOUT_ASSERTIONS) && !defined(CYTHON_WITHOUT_ASSERTIONS) -#define CYTHON_WITHOUT_ASSERTIONS -#endif - -typedef struct {PyObject **p; const char *s; const Py_ssize_t n; const char* encoding; - const char is_unicode; const char is_str; const char intern; } __Pyx_StringTabEntry; - -#define __PYX_DEFAULT_STRING_ENCODING_IS_ASCII 0 -#define __PYX_DEFAULT_STRING_ENCODING_IS_UTF8 0 -#define __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT (PY_MAJOR_VERSION >= 3 && __PYX_DEFAULT_STRING_ENCODING_IS_UTF8) -#define __PYX_DEFAULT_STRING_ENCODING "" -#define __Pyx_PyObject_FromString __Pyx_PyBytes_FromString -#define __Pyx_PyObject_FromStringAndSize __Pyx_PyBytes_FromStringAndSize -#define __Pyx_uchar_cast(c) ((unsigned char)c) -#define __Pyx_long_cast(x) ((long)x) -#define __Pyx_fits_Py_ssize_t(v, type, is_signed) (\ - (sizeof(type) < sizeof(Py_ssize_t)) ||\ - (sizeof(type) > sizeof(Py_ssize_t) &&\ - likely(v < (type)PY_SSIZE_T_MAX ||\ - v == (type)PY_SSIZE_T_MAX) &&\ - (!is_signed || likely(v > (type)PY_SSIZE_T_MIN ||\ - v == (type)PY_SSIZE_T_MIN))) ||\ - (sizeof(type) == sizeof(Py_ssize_t) &&\ - (is_signed || likely(v < (type)PY_SSIZE_T_MAX ||\ - v == (type)PY_SSIZE_T_MAX))) ) -static CYTHON_INLINE int __Pyx_is_valid_index(Py_ssize_t i, Py_ssize_t limit) { - return (size_t) i < (size_t) limit; -} -#if defined (__cplusplus) && __cplusplus >= 201103L - #include - #define __Pyx_sst_abs(value) std::abs(value) -#elif SIZEOF_INT >= SIZEOF_SIZE_T - #define __Pyx_sst_abs(value) abs(value) -#elif SIZEOF_LONG >= SIZEOF_SIZE_T - #define __Pyx_sst_abs(value) labs(value) -#elif defined (_MSC_VER) - #define __Pyx_sst_abs(value) ((Py_ssize_t)_abs64(value)) -#elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L - #define __Pyx_sst_abs(value) llabs(value) -#elif defined (__GNUC__) - #define __Pyx_sst_abs(value) __builtin_llabs(value) -#else - #define __Pyx_sst_abs(value) ((value<0) ? -value : value) -#endif -static CYTHON_INLINE const char* __Pyx_PyObject_AsString(PyObject*); -static CYTHON_INLINE const char* __Pyx_PyObject_AsStringAndSize(PyObject*, Py_ssize_t* length); -#define __Pyx_PyByteArray_FromString(s) PyByteArray_FromStringAndSize((const char*)s, strlen((const char*)s)) -#define __Pyx_PyByteArray_FromStringAndSize(s, l) PyByteArray_FromStringAndSize((const char*)s, l) -#define __Pyx_PyBytes_FromString PyBytes_FromString -#define __Pyx_PyBytes_FromStringAndSize PyBytes_FromStringAndSize -static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char*); -#if PY_MAJOR_VERSION < 3 - #define __Pyx_PyStr_FromString __Pyx_PyBytes_FromString - #define __Pyx_PyStr_FromStringAndSize __Pyx_PyBytes_FromStringAndSize -#else - #define __Pyx_PyStr_FromString __Pyx_PyUnicode_FromString - #define __Pyx_PyStr_FromStringAndSize __Pyx_PyUnicode_FromStringAndSize -#endif -#define __Pyx_PyBytes_AsWritableString(s) ((char*) PyBytes_AS_STRING(s)) -#define __Pyx_PyBytes_AsWritableSString(s) ((signed char*) PyBytes_AS_STRING(s)) -#define __Pyx_PyBytes_AsWritableUString(s) ((unsigned char*) PyBytes_AS_STRING(s)) -#define __Pyx_PyBytes_AsString(s) ((const char*) PyBytes_AS_STRING(s)) -#define __Pyx_PyBytes_AsSString(s) ((const signed char*) PyBytes_AS_STRING(s)) -#define __Pyx_PyBytes_AsUString(s) ((const unsigned char*) PyBytes_AS_STRING(s)) -#define __Pyx_PyObject_AsWritableString(s) ((char*) __Pyx_PyObject_AsString(s)) -#define __Pyx_PyObject_AsWritableSString(s) ((signed char*) __Pyx_PyObject_AsString(s)) -#define __Pyx_PyObject_AsWritableUString(s) ((unsigned char*) __Pyx_PyObject_AsString(s)) -#define __Pyx_PyObject_AsSString(s) ((const signed char*) __Pyx_PyObject_AsString(s)) -#define __Pyx_PyObject_AsUString(s) ((const unsigned char*) __Pyx_PyObject_AsString(s)) -#define __Pyx_PyObject_FromCString(s) __Pyx_PyObject_FromString((const char*)s) -#define __Pyx_PyBytes_FromCString(s) __Pyx_PyBytes_FromString((const char*)s) -#define __Pyx_PyByteArray_FromCString(s) __Pyx_PyByteArray_FromString((const char*)s) -#define __Pyx_PyStr_FromCString(s) __Pyx_PyStr_FromString((const char*)s) -#define __Pyx_PyUnicode_FromCString(s) __Pyx_PyUnicode_FromString((const char*)s) -static CYTHON_INLINE size_t __Pyx_Py_UNICODE_strlen(const Py_UNICODE *u) { - const Py_UNICODE *u_end = u; - while (*u_end++) ; - return (size_t)(u_end - u - 1); -} -#define __Pyx_PyUnicode_FromUnicode(u) PyUnicode_FromUnicode(u, __Pyx_Py_UNICODE_strlen(u)) -#define __Pyx_PyUnicode_FromUnicodeAndLength PyUnicode_FromUnicode -#define __Pyx_PyUnicode_AsUnicode PyUnicode_AsUnicode -#define __Pyx_NewRef(obj) (Py_INCREF(obj), obj) -#define __Pyx_Owned_Py_None(b) __Pyx_NewRef(Py_None) -static CYTHON_INLINE PyObject * __Pyx_PyBool_FromLong(long b); -static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject*); -static CYTHON_INLINE int __Pyx_PyObject_IsTrueAndDecref(PyObject*); -static CYTHON_INLINE PyObject* __Pyx_PyNumber_IntOrLong(PyObject* x); -#define __Pyx_PySequence_Tuple(obj)\ - (likely(PyTuple_CheckExact(obj)) ? __Pyx_NewRef(obj) : PySequence_Tuple(obj)) -static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject*); -static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t); -#if CYTHON_ASSUME_SAFE_MACROS -#define __pyx_PyFloat_AsDouble(x) (PyFloat_CheckExact(x) ? PyFloat_AS_DOUBLE(x) : PyFloat_AsDouble(x)) -#else -#define __pyx_PyFloat_AsDouble(x) PyFloat_AsDouble(x) -#endif -#define __pyx_PyFloat_AsFloat(x) ((float) __pyx_PyFloat_AsDouble(x)) -#if PY_MAJOR_VERSION >= 3 -#define __Pyx_PyNumber_Int(x) (PyLong_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Long(x)) -#else -#define __Pyx_PyNumber_Int(x) (PyInt_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Int(x)) -#endif -#define __Pyx_PyNumber_Float(x) (PyFloat_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Float(x)) -#if PY_MAJOR_VERSION < 3 && __PYX_DEFAULT_STRING_ENCODING_IS_ASCII -static int __Pyx_sys_getdefaultencoding_not_ascii; -static int __Pyx_init_sys_getdefaultencoding_params(void) { - PyObject* sys; - PyObject* default_encoding = NULL; - PyObject* ascii_chars_u = NULL; - PyObject* ascii_chars_b = NULL; - const char* default_encoding_c; - sys = PyImport_ImportModule("sys"); - if (!sys) goto bad; - default_encoding = PyObject_CallMethod(sys, (char*) "getdefaultencoding", NULL); - Py_DECREF(sys); - if (!default_encoding) goto bad; - default_encoding_c = PyBytes_AsString(default_encoding); - if (!default_encoding_c) goto bad; - if (strcmp(default_encoding_c, "ascii") == 0) { - __Pyx_sys_getdefaultencoding_not_ascii = 0; - } else { - char ascii_chars[128]; - int c; - for (c = 0; c < 128; c++) { - ascii_chars[c] = c; - } - __Pyx_sys_getdefaultencoding_not_ascii = 1; - ascii_chars_u = PyUnicode_DecodeASCII(ascii_chars, 128, NULL); - if (!ascii_chars_u) goto bad; - ascii_chars_b = PyUnicode_AsEncodedString(ascii_chars_u, default_encoding_c, NULL); - if (!ascii_chars_b || !PyBytes_Check(ascii_chars_b) || memcmp(ascii_chars, PyBytes_AS_STRING(ascii_chars_b), 128) != 0) { - PyErr_Format( - PyExc_ValueError, - "This module compiled with c_string_encoding=ascii, but default encoding '%.200s' is not a superset of ascii.", - default_encoding_c); - goto bad; - } - Py_DECREF(ascii_chars_u); - Py_DECREF(ascii_chars_b); - } - Py_DECREF(default_encoding); - return 0; -bad: - Py_XDECREF(default_encoding); - Py_XDECREF(ascii_chars_u); - Py_XDECREF(ascii_chars_b); - return -1; -} -#endif -#if __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT && PY_MAJOR_VERSION >= 3 -#define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_DecodeUTF8(c_str, size, NULL) -#else -#define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_Decode(c_str, size, __PYX_DEFAULT_STRING_ENCODING, NULL) -#if __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT -static char* __PYX_DEFAULT_STRING_ENCODING; -static int __Pyx_init_sys_getdefaultencoding_params(void) { - PyObject* sys; - PyObject* default_encoding = NULL; - char* default_encoding_c; - sys = PyImport_ImportModule("sys"); - if (!sys) goto bad; - default_encoding = PyObject_CallMethod(sys, (char*) (const char*) "getdefaultencoding", NULL); - Py_DECREF(sys); - if (!default_encoding) goto bad; - default_encoding_c = PyBytes_AsString(default_encoding); - if (!default_encoding_c) goto bad; - __PYX_DEFAULT_STRING_ENCODING = (char*) malloc(strlen(default_encoding_c) + 1); - if (!__PYX_DEFAULT_STRING_ENCODING) goto bad; - strcpy(__PYX_DEFAULT_STRING_ENCODING, default_encoding_c); - Py_DECREF(default_encoding); - return 0; -bad: - Py_XDECREF(default_encoding); - return -1; -} -#endif -#endif - - -/* Test for GCC > 2.95 */ -#if defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95))) - #define likely(x) __builtin_expect(!!(x), 1) - #define unlikely(x) __builtin_expect(!!(x), 0) -#else /* !__GNUC__ or GCC < 2.95 */ - #define likely(x) (x) - #define unlikely(x) (x) -#endif /* __GNUC__ */ -static CYTHON_INLINE void __Pyx_pretend_to_initialize(void* ptr) { (void)ptr; } - -static PyObject *__pyx_m = NULL; -static PyObject *__pyx_d; -static PyObject *__pyx_b; -static PyObject *__pyx_cython_runtime = NULL; -static PyObject *__pyx_empty_tuple; -static PyObject *__pyx_empty_bytes; -static PyObject *__pyx_empty_unicode; -static int __pyx_lineno; -static int __pyx_clineno = 0; -static const char * __pyx_cfilenm= __FILE__; -static const char *__pyx_filename; - - -static const char *__pyx_f[] = { - "aiohttp/_frozenlist.pyx", - "stringsource", -}; - -/*--- Type declarations ---*/ -struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList; - -/* "aiohttp/_frozenlist.pyx":4 - * - * - * cdef class FrozenList: # <<<<<<<<<<<<<< - * - * cdef readonly bint frozen - */ -struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList { - PyObject_HEAD - struct __pyx_vtabstruct_7aiohttp_11_frozenlist_FrozenList *__pyx_vtab; - int frozen; - PyObject *_items; -}; - - - -struct __pyx_vtabstruct_7aiohttp_11_frozenlist_FrozenList { - PyObject *(*_check_frozen)(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *); - PyObject *(*_fast_len)(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *); -}; -static struct __pyx_vtabstruct_7aiohttp_11_frozenlist_FrozenList *__pyx_vtabptr_7aiohttp_11_frozenlist_FrozenList; -static CYTHON_INLINE PyObject *__pyx_f_7aiohttp_11_frozenlist_10FrozenList__fast_len(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *); - -/* --- Runtime support code (head) --- */ -/* Refnanny.proto */ -#ifndef CYTHON_REFNANNY - #define CYTHON_REFNANNY 0 -#endif -#if CYTHON_REFNANNY - typedef struct { - void (*INCREF)(void*, PyObject*, int); - void (*DECREF)(void*, PyObject*, int); - void (*GOTREF)(void*, PyObject*, int); - void (*GIVEREF)(void*, PyObject*, int); - void* (*SetupContext)(const char*, int, const char*); - void (*FinishContext)(void**); - } __Pyx_RefNannyAPIStruct; - static __Pyx_RefNannyAPIStruct *__Pyx_RefNanny = NULL; - static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname); - #define __Pyx_RefNannyDeclarations void *__pyx_refnanny = NULL; -#ifdef WITH_THREAD - #define __Pyx_RefNannySetupContext(name, acquire_gil)\ - if (acquire_gil) {\ - PyGILState_STATE __pyx_gilstate_save = PyGILState_Ensure();\ - __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__);\ - PyGILState_Release(__pyx_gilstate_save);\ - } else {\ - __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__);\ - } -#else - #define __Pyx_RefNannySetupContext(name, acquire_gil)\ - __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__) -#endif - #define __Pyx_RefNannyFinishContext()\ - __Pyx_RefNanny->FinishContext(&__pyx_refnanny) - #define __Pyx_INCREF(r) __Pyx_RefNanny->INCREF(__pyx_refnanny, (PyObject *)(r), __LINE__) - #define __Pyx_DECREF(r) __Pyx_RefNanny->DECREF(__pyx_refnanny, (PyObject *)(r), __LINE__) - #define __Pyx_GOTREF(r) __Pyx_RefNanny->GOTREF(__pyx_refnanny, (PyObject *)(r), __LINE__) - #define __Pyx_GIVEREF(r) __Pyx_RefNanny->GIVEREF(__pyx_refnanny, (PyObject *)(r), __LINE__) - #define __Pyx_XINCREF(r) do { if((r) != NULL) {__Pyx_INCREF(r); }} while(0) - #define __Pyx_XDECREF(r) do { if((r) != NULL) {__Pyx_DECREF(r); }} while(0) - #define __Pyx_XGOTREF(r) do { if((r) != NULL) {__Pyx_GOTREF(r); }} while(0) - #define __Pyx_XGIVEREF(r) do { if((r) != NULL) {__Pyx_GIVEREF(r);}} while(0) -#else - #define __Pyx_RefNannyDeclarations - #define __Pyx_RefNannySetupContext(name, acquire_gil) - #define __Pyx_RefNannyFinishContext() - #define __Pyx_INCREF(r) Py_INCREF(r) - #define __Pyx_DECREF(r) Py_DECREF(r) - #define __Pyx_GOTREF(r) - #define __Pyx_GIVEREF(r) - #define __Pyx_XINCREF(r) Py_XINCREF(r) - #define __Pyx_XDECREF(r) Py_XDECREF(r) - #define __Pyx_XGOTREF(r) - #define __Pyx_XGIVEREF(r) -#endif -#define __Pyx_XDECREF_SET(r, v) do {\ - PyObject *tmp = (PyObject *) r;\ - r = v; __Pyx_XDECREF(tmp);\ - } while (0) -#define __Pyx_DECREF_SET(r, v) do {\ - PyObject *tmp = (PyObject *) r;\ - r = v; __Pyx_DECREF(tmp);\ - } while (0) -#define __Pyx_CLEAR(r) do { PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);} while(0) -#define __Pyx_XCLEAR(r) do { if((r) != NULL) {PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);}} while(0) - -/* PyObjectGetAttrStr.proto */ -#if CYTHON_USE_TYPE_SLOTS -static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStr(PyObject* obj, PyObject* attr_name); -#else -#define __Pyx_PyObject_GetAttrStr(o,n) PyObject_GetAttr(o,n) -#endif - -/* GetBuiltinName.proto */ -static PyObject *__Pyx_GetBuiltinName(PyObject *name); - -/* RaiseDoubleKeywords.proto */ -static void __Pyx_RaiseDoubleKeywordsError(const char* func_name, PyObject* kw_name); - -/* ParseKeywords.proto */ -static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[],\ - PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args,\ - const char* function_name); - -/* RaiseArgTupleInvalid.proto */ -static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact, - Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); - -/* PyObjectCall.proto */ -#if CYTHON_COMPILING_IN_CPYTHON -static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw); -#else -#define __Pyx_PyObject_Call(func, arg, kw) PyObject_Call(func, arg, kw) -#endif - -/* PyThreadStateGet.proto */ -#if CYTHON_FAST_THREAD_STATE -#define __Pyx_PyThreadState_declare PyThreadState *__pyx_tstate; -#define __Pyx_PyThreadState_assign __pyx_tstate = __Pyx_PyThreadState_Current; -#define __Pyx_PyErr_Occurred() __pyx_tstate->curexc_type -#else -#define __Pyx_PyThreadState_declare -#define __Pyx_PyThreadState_assign -#define __Pyx_PyErr_Occurred() PyErr_Occurred() -#endif - -/* PyErrFetchRestore.proto */ -#if CYTHON_FAST_THREAD_STATE -#define __Pyx_PyErr_Clear() __Pyx_ErrRestore(NULL, NULL, NULL) -#define __Pyx_ErrRestoreWithState(type, value, tb) __Pyx_ErrRestoreInState(PyThreadState_GET(), type, value, tb) -#define __Pyx_ErrFetchWithState(type, value, tb) __Pyx_ErrFetchInState(PyThreadState_GET(), type, value, tb) -#define __Pyx_ErrRestore(type, value, tb) __Pyx_ErrRestoreInState(__pyx_tstate, type, value, tb) -#define __Pyx_ErrFetch(type, value, tb) __Pyx_ErrFetchInState(__pyx_tstate, type, value, tb) -static CYTHON_INLINE void __Pyx_ErrRestoreInState(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb); -static CYTHON_INLINE void __Pyx_ErrFetchInState(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb); -#if CYTHON_COMPILING_IN_CPYTHON -#define __Pyx_PyErr_SetNone(exc) (Py_INCREF(exc), __Pyx_ErrRestore((exc), NULL, NULL)) -#else -#define __Pyx_PyErr_SetNone(exc) PyErr_SetNone(exc) -#endif -#else -#define __Pyx_PyErr_Clear() PyErr_Clear() -#define __Pyx_PyErr_SetNone(exc) PyErr_SetNone(exc) -#define __Pyx_ErrRestoreWithState(type, value, tb) PyErr_Restore(type, value, tb) -#define __Pyx_ErrFetchWithState(type, value, tb) PyErr_Fetch(type, value, tb) -#define __Pyx_ErrRestoreInState(tstate, type, value, tb) PyErr_Restore(type, value, tb) -#define __Pyx_ErrFetchInState(tstate, type, value, tb) PyErr_Fetch(type, value, tb) -#define __Pyx_ErrRestore(type, value, tb) PyErr_Restore(type, value, tb) -#define __Pyx_ErrFetch(type, value, tb) PyErr_Fetch(type, value, tb) -#endif - -/* RaiseException.proto */ -static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause); - -/* GetItemInt.proto */ -#define __Pyx_GetItemInt(o, i, type, is_signed, to_py_func, is_list, wraparound, boundscheck)\ - (__Pyx_fits_Py_ssize_t(i, type, is_signed) ?\ - __Pyx_GetItemInt_Fast(o, (Py_ssize_t)i, is_list, wraparound, boundscheck) :\ - (is_list ? (PyErr_SetString(PyExc_IndexError, "list index out of range"), (PyObject*)NULL) :\ - __Pyx_GetItemInt_Generic(o, to_py_func(i)))) -#define __Pyx_GetItemInt_List(o, i, type, is_signed, to_py_func, is_list, wraparound, boundscheck)\ - (__Pyx_fits_Py_ssize_t(i, type, is_signed) ?\ - __Pyx_GetItemInt_List_Fast(o, (Py_ssize_t)i, wraparound, boundscheck) :\ - (PyErr_SetString(PyExc_IndexError, "list index out of range"), (PyObject*)NULL)) -static CYTHON_INLINE PyObject *__Pyx_GetItemInt_List_Fast(PyObject *o, Py_ssize_t i, - int wraparound, int boundscheck); -#define __Pyx_GetItemInt_Tuple(o, i, type, is_signed, to_py_func, is_list, wraparound, boundscheck)\ - (__Pyx_fits_Py_ssize_t(i, type, is_signed) ?\ - __Pyx_GetItemInt_Tuple_Fast(o, (Py_ssize_t)i, wraparound, boundscheck) :\ - (PyErr_SetString(PyExc_IndexError, "tuple index out of range"), (PyObject*)NULL)) -static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Tuple_Fast(PyObject *o, Py_ssize_t i, - int wraparound, int boundscheck); -static PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j); -static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i, - int is_list, int wraparound, int boundscheck); - -/* ObjectGetItem.proto */ -#if CYTHON_USE_TYPE_SLOTS -static CYTHON_INLINE PyObject *__Pyx_PyObject_GetItem(PyObject *obj, PyObject* key); -#else -#define __Pyx_PyObject_GetItem(obj, key) PyObject_GetItem(obj, key) -#endif - -/* PyFunctionFastCall.proto */ -#if CYTHON_FAST_PYCALL -#define __Pyx_PyFunction_FastCall(func, args, nargs)\ - __Pyx_PyFunction_FastCallDict((func), (args), (nargs), NULL) -#if 1 || PY_VERSION_HEX < 0x030600B1 -static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs, PyObject *kwargs); -#else -#define __Pyx_PyFunction_FastCallDict(func, args, nargs, kwargs) _PyFunction_FastCallDict(func, args, nargs, kwargs) -#endif -#define __Pyx_BUILD_ASSERT_EXPR(cond)\ - (sizeof(char [1 - 2*!(cond)]) - 1) -#ifndef Py_MEMBER_SIZE -#define Py_MEMBER_SIZE(type, member) sizeof(((type *)0)->member) -#endif - static size_t __pyx_pyframe_localsplus_offset = 0; - #include "frameobject.h" - #define __Pxy_PyFrame_Initialize_Offsets()\ - ((void)__Pyx_BUILD_ASSERT_EXPR(sizeof(PyFrameObject) == offsetof(PyFrameObject, f_localsplus) + Py_MEMBER_SIZE(PyFrameObject, f_localsplus)),\ - (void)(__pyx_pyframe_localsplus_offset = ((size_t)PyFrame_Type.tp_basicsize) - Py_MEMBER_SIZE(PyFrameObject, f_localsplus))) - #define __Pyx_PyFrame_GetLocalsplus(frame)\ - (assert(__pyx_pyframe_localsplus_offset), (PyObject **)(((char *)(frame)) + __pyx_pyframe_localsplus_offset)) -#endif - -/* PyObjectCallMethO.proto */ -#if CYTHON_COMPILING_IN_CPYTHON -static CYTHON_INLINE PyObject* __Pyx_PyObject_CallMethO(PyObject *func, PyObject *arg); -#endif - -/* PyObjectCallNoArg.proto */ -#if CYTHON_COMPILING_IN_CPYTHON -static CYTHON_INLINE PyObject* __Pyx_PyObject_CallNoArg(PyObject *func); -#else -#define __Pyx_PyObject_CallNoArg(func) __Pyx_PyObject_Call(func, __pyx_empty_tuple, NULL) -#endif - -/* PyCFunctionFastCall.proto */ -#if CYTHON_FAST_PYCCALL -static CYTHON_INLINE PyObject *__Pyx_PyCFunction_FastCall(PyObject *func, PyObject **args, Py_ssize_t nargs); -#else -#define __Pyx_PyCFunction_FastCall(func, args, nargs) (assert(0), NULL) -#endif - -/* PyObjectCallOneArg.proto */ -static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg); - -/* PyIntCompare.proto */ -static CYTHON_INLINE PyObject* __Pyx_PyInt_EqObjC(PyObject *op1, PyObject *op2, long intval, long inplace); - -/* PySequenceContains.proto */ -static CYTHON_INLINE int __Pyx_PySequence_ContainsTF(PyObject* item, PyObject* seq, int eq) { - int result = PySequence_Contains(seq, item); - return unlikely(result < 0) ? result : (result == (eq == Py_EQ)); -} - -/* PyObjectCall2Args.proto */ -static CYTHON_UNUSED PyObject* __Pyx_PyObject_Call2Args(PyObject* function, PyObject* arg1, PyObject* arg2); - -/* PyObjectGetMethod.proto */ -static int __Pyx_PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **method); - -/* PyObjectCallMethod1.proto */ -static PyObject* __Pyx_PyObject_CallMethod1(PyObject* obj, PyObject* method_name, PyObject* arg); - -/* pop_index.proto */ -static PyObject* __Pyx__PyObject_PopNewIndex(PyObject* L, PyObject* py_ix); -static PyObject* __Pyx__PyObject_PopIndex(PyObject* L, PyObject* py_ix); -#if CYTHON_USE_PYLIST_INTERNALS && CYTHON_ASSUME_SAFE_MACROS -static PyObject* __Pyx__PyList_PopIndex(PyObject* L, PyObject* py_ix, Py_ssize_t ix); -#define __Pyx_PyObject_PopIndex(L, py_ix, ix, is_signed, type, to_py_func) (\ - (likely(PyList_CheckExact(L) && __Pyx_fits_Py_ssize_t(ix, type, is_signed))) ?\ - __Pyx__PyList_PopIndex(L, py_ix, ix) : (\ - (unlikely((py_ix) == Py_None)) ? __Pyx__PyObject_PopNewIndex(L, to_py_func(ix)) :\ - __Pyx__PyObject_PopIndex(L, py_ix))) -#define __Pyx_PyList_PopIndex(L, py_ix, ix, is_signed, type, to_py_func) (\ - __Pyx_fits_Py_ssize_t(ix, type, is_signed) ?\ - __Pyx__PyList_PopIndex(L, py_ix, ix) : (\ - (unlikely((py_ix) == Py_None)) ? __Pyx__PyObject_PopNewIndex(L, to_py_func(ix)) :\ - __Pyx__PyObject_PopIndex(L, py_ix))) -#else -#define __Pyx_PyList_PopIndex(L, py_ix, ix, is_signed, type, to_py_func)\ - __Pyx_PyObject_PopIndex(L, py_ix, ix, is_signed, type, to_py_func) -#define __Pyx_PyObject_PopIndex(L, py_ix, ix, is_signed, type, to_py_func) (\ - (unlikely((py_ix) == Py_None)) ? __Pyx__PyObject_PopNewIndex(L, to_py_func(ix)) :\ - __Pyx__PyObject_PopIndex(L, py_ix)) -#endif - -/* ListAppend.proto */ -#if CYTHON_USE_PYLIST_INTERNALS && CYTHON_ASSUME_SAFE_MACROS -static CYTHON_INLINE int __Pyx_PyList_Append(PyObject* list, PyObject* x) { - PyListObject* L = (PyListObject*) list; - Py_ssize_t len = Py_SIZE(list); - if (likely(L->allocated > len) & likely(len > (L->allocated >> 1))) { - Py_INCREF(x); - PyList_SET_ITEM(list, len, x); - __Pyx_SET_SIZE(list, len + 1); - return 0; - } - return PyList_Append(list, x); -} -#else -#define __Pyx_PyList_Append(L,x) PyList_Append(L,x) -#endif - -/* PyErrExceptionMatches.proto */ -#if CYTHON_FAST_THREAD_STATE -#define __Pyx_PyErr_ExceptionMatches(err) __Pyx_PyErr_ExceptionMatchesInState(__pyx_tstate, err) -static CYTHON_INLINE int __Pyx_PyErr_ExceptionMatchesInState(PyThreadState* tstate, PyObject* err); -#else -#define __Pyx_PyErr_ExceptionMatches(err) PyErr_ExceptionMatches(err) -#endif - -/* GetAttr.proto */ -static CYTHON_INLINE PyObject *__Pyx_GetAttr(PyObject *, PyObject *); - -/* GetAttr3.proto */ -static CYTHON_INLINE PyObject *__Pyx_GetAttr3(PyObject *, PyObject *, PyObject *); - -/* PyDictVersioning.proto */ -#if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_TYPE_SLOTS -#define __PYX_DICT_VERSION_INIT ((PY_UINT64_T) -1) -#define __PYX_GET_DICT_VERSION(dict) (((PyDictObject*)(dict))->ma_version_tag) -#define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var)\ - (version_var) = __PYX_GET_DICT_VERSION(dict);\ - (cache_var) = (value); -#define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) {\ - static PY_UINT64_T __pyx_dict_version = 0;\ - static PyObject *__pyx_dict_cached_value = NULL;\ - if (likely(__PYX_GET_DICT_VERSION(DICT) == __pyx_dict_version)) {\ - (VAR) = __pyx_dict_cached_value;\ - } else {\ - (VAR) = __pyx_dict_cached_value = (LOOKUP);\ - __pyx_dict_version = __PYX_GET_DICT_VERSION(DICT);\ - }\ -} -static CYTHON_INLINE PY_UINT64_T __Pyx_get_tp_dict_version(PyObject *obj); -static CYTHON_INLINE PY_UINT64_T __Pyx_get_object_dict_version(PyObject *obj); -static CYTHON_INLINE int __Pyx_object_dict_version_matches(PyObject* obj, PY_UINT64_T tp_dict_version, PY_UINT64_T obj_dict_version); -#else -#define __PYX_GET_DICT_VERSION(dict) (0) -#define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var) -#define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) (VAR) = (LOOKUP); -#endif - -/* GetModuleGlobalName.proto */ -#if CYTHON_USE_DICT_VERSIONS -#define __Pyx_GetModuleGlobalName(var, name) {\ - static PY_UINT64_T __pyx_dict_version = 0;\ - static PyObject *__pyx_dict_cached_value = NULL;\ - (var) = (likely(__pyx_dict_version == __PYX_GET_DICT_VERSION(__pyx_d))) ?\ - (likely(__pyx_dict_cached_value) ? __Pyx_NewRef(__pyx_dict_cached_value) : __Pyx_GetBuiltinName(name)) :\ - __Pyx__GetModuleGlobalName(name, &__pyx_dict_version, &__pyx_dict_cached_value);\ -} -#define __Pyx_GetModuleGlobalNameUncached(var, name) {\ - PY_UINT64_T __pyx_dict_version;\ - PyObject *__pyx_dict_cached_value;\ - (var) = __Pyx__GetModuleGlobalName(name, &__pyx_dict_version, &__pyx_dict_cached_value);\ -} -static PyObject *__Pyx__GetModuleGlobalName(PyObject *name, PY_UINT64_T *dict_version, PyObject **dict_cached_value); -#else -#define __Pyx_GetModuleGlobalName(var, name) (var) = __Pyx__GetModuleGlobalName(name) -#define __Pyx_GetModuleGlobalNameUncached(var, name) (var) = __Pyx__GetModuleGlobalName(name) -static CYTHON_INLINE PyObject *__Pyx__GetModuleGlobalName(PyObject *name); -#endif - -/* Import.proto */ -static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, int level); - -/* ImportFrom.proto */ -static PyObject* __Pyx_ImportFrom(PyObject* module, PyObject* name); - -/* HasAttr.proto */ -static CYTHON_INLINE int __Pyx_HasAttr(PyObject *, PyObject *); - -/* PyObject_GenericGetAttrNoDict.proto */ -#if CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP && PY_VERSION_HEX < 0x03070000 -static CYTHON_INLINE PyObject* __Pyx_PyObject_GenericGetAttrNoDict(PyObject* obj, PyObject* attr_name); -#else -#define __Pyx_PyObject_GenericGetAttrNoDict PyObject_GenericGetAttr -#endif - -/* PyObject_GenericGetAttr.proto */ -#if CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP && PY_VERSION_HEX < 0x03070000 -static PyObject* __Pyx_PyObject_GenericGetAttr(PyObject* obj, PyObject* attr_name); -#else -#define __Pyx_PyObject_GenericGetAttr PyObject_GenericGetAttr -#endif - -/* SetVTable.proto */ -static int __Pyx_SetVtable(PyObject *dict, void *vtable); - -/* PyObjectGetAttrStrNoError.proto */ -static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStrNoError(PyObject* obj, PyObject* attr_name); - -/* SetupReduce.proto */ -static int __Pyx_setup_reduce(PyObject* type_obj); - -/* CLineInTraceback.proto */ -#ifdef CYTHON_CLINE_IN_TRACEBACK -#define __Pyx_CLineForTraceback(tstate, c_line) (((CYTHON_CLINE_IN_TRACEBACK)) ? c_line : 0) -#else -static int __Pyx_CLineForTraceback(PyThreadState *tstate, int c_line); -#endif - -/* CodeObjectCache.proto */ -typedef struct { - PyCodeObject* code_object; - int code_line; -} __Pyx_CodeObjectCacheEntry; -struct __Pyx_CodeObjectCache { - int count; - int max_count; - __Pyx_CodeObjectCacheEntry* entries; -}; -static struct __Pyx_CodeObjectCache __pyx_code_cache = {0,0,NULL}; -static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line); -static PyCodeObject *__pyx_find_code_object(int code_line); -static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object); - -/* AddTraceback.proto */ -static void __Pyx_AddTraceback(const char *funcname, int c_line, - int py_line, const char *filename); - -/* CIntToPy.proto */ -static CYTHON_INLINE PyObject* __Pyx_PyInt_From_int(int value); - -/* CIntToPy.proto */ -static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value); - -/* CIntFromPy.proto */ -static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *); - -/* CIntFromPy.proto */ -static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *); - -/* FastTypeChecks.proto */ -#if CYTHON_COMPILING_IN_CPYTHON -#define __Pyx_TypeCheck(obj, type) __Pyx_IsSubtype(Py_TYPE(obj), (PyTypeObject *)type) -static CYTHON_INLINE int __Pyx_IsSubtype(PyTypeObject *a, PyTypeObject *b); -static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches(PyObject *err, PyObject *type); -static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches2(PyObject *err, PyObject *type1, PyObject *type2); -#else -#define __Pyx_TypeCheck(obj, type) PyObject_TypeCheck(obj, (PyTypeObject *)type) -#define __Pyx_PyErr_GivenExceptionMatches(err, type) PyErr_GivenExceptionMatches(err, type) -#define __Pyx_PyErr_GivenExceptionMatches2(err, type1, type2) (PyErr_GivenExceptionMatches(err, type1) || PyErr_GivenExceptionMatches(err, type2)) -#endif -#define __Pyx_PyException_Check(obj) __Pyx_TypeCheck(obj, PyExc_Exception) - -/* CheckBinaryVersion.proto */ -static int __Pyx_check_binary_version(void); - -/* InitStrings.proto */ -static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); - -static PyObject *__pyx_f_7aiohttp_11_frozenlist_10FrozenList__check_frozen(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self); /* proto*/ -static CYTHON_INLINE PyObject *__pyx_f_7aiohttp_11_frozenlist_10FrozenList__fast_len(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self); /* proto*/ - -/* Module declarations from 'aiohttp._frozenlist' */ -static PyTypeObject *__pyx_ptype_7aiohttp_11_frozenlist_FrozenList = 0; -static PyObject *__pyx_f_7aiohttp_11_frozenlist___pyx_unpickle_FrozenList__set_state(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *, PyObject *); /*proto*/ -#define __Pyx_MODULE_NAME "aiohttp._frozenlist" -extern int __pyx_module_is_main_aiohttp___frozenlist; -int __pyx_module_is_main_aiohttp___frozenlist = 0; - -/* Implementation of 'aiohttp._frozenlist' */ -static PyObject *__pyx_builtin_RuntimeError; -static const char __pyx_k_new[] = "__new__"; -static const char __pyx_k_pop[] = "pop"; -static const char __pyx_k_pos[] = "pos"; -static const char __pyx_k_dict[] = "__dict__"; -static const char __pyx_k_item[] = "item"; -static const char __pyx_k_iter[] = "__iter__"; -static const char __pyx_k_main[] = "__main__"; -static const char __pyx_k_name[] = "__name__"; -static const char __pyx_k_test[] = "__test__"; -static const char __pyx_k_clear[] = "clear"; -static const char __pyx_k_count[] = "count"; -static const char __pyx_k_index[] = "index"; -static const char __pyx_k_items[] = "items"; -static const char __pyx_k_format[] = "format"; -static const char __pyx_k_import[] = "__import__"; -static const char __pyx_k_pickle[] = "pickle"; -static const char __pyx_k_reduce[] = "__reduce__"; -static const char __pyx_k_remove[] = "remove"; -static const char __pyx_k_update[] = "update"; -static const char __pyx_k_getstate[] = "__getstate__"; -static const char __pyx_k_pyx_type[] = "__pyx_type"; -static const char __pyx_k_register[] = "register"; -static const char __pyx_k_reversed[] = "__reversed__"; -static const char __pyx_k_setstate[] = "__setstate__"; -static const char __pyx_k_pyx_state[] = "__pyx_state"; -static const char __pyx_k_reduce_ex[] = "__reduce_ex__"; -static const char __pyx_k_FrozenList[] = "FrozenList"; -static const char __pyx_k_pyx_result[] = "__pyx_result"; -static const char __pyx_k_pyx_vtable[] = "__pyx_vtable__"; -static const char __pyx_k_PickleError[] = "PickleError"; -static const char __pyx_k_RuntimeError[] = "RuntimeError"; -static const char __pyx_k_pyx_checksum[] = "__pyx_checksum"; -static const char __pyx_k_stringsource[] = "stringsource"; -static const char __pyx_k_reduce_cython[] = "__reduce_cython__"; -static const char __pyx_k_MutableSequence[] = "MutableSequence"; -static const char __pyx_k_collections_abc[] = "collections.abc"; -static const char __pyx_k_pyx_PickleError[] = "__pyx_PickleError"; -static const char __pyx_k_setstate_cython[] = "__setstate_cython__"; -static const char __pyx_k_cline_in_traceback[] = "cline_in_traceback"; -static const char __pyx_k_FrozenList_frozen_r[] = ""; -static const char __pyx_k_aiohttp__frozenlist[] = "aiohttp._frozenlist"; -static const char __pyx_k_pyx_unpickle_FrozenList[] = "__pyx_unpickle_FrozenList"; -static const char __pyx_k_Cannot_modify_frozen_list[] = "Cannot modify frozen list."; -static const char __pyx_k_Incompatible_checksums_s_vs_0x94[] = "Incompatible checksums (%s vs 0x949a143 = (_items, frozen))"; -static PyObject *__pyx_kp_u_Cannot_modify_frozen_list; -static PyObject *__pyx_n_s_FrozenList; -static PyObject *__pyx_kp_u_FrozenList_frozen_r; -static PyObject *__pyx_kp_s_Incompatible_checksums_s_vs_0x94; -static PyObject *__pyx_n_s_MutableSequence; -static PyObject *__pyx_n_s_PickleError; -static PyObject *__pyx_n_s_RuntimeError; -static PyObject *__pyx_n_s_aiohttp__frozenlist; -static PyObject *__pyx_n_s_clear; -static PyObject *__pyx_n_s_cline_in_traceback; -static PyObject *__pyx_n_s_collections_abc; -static PyObject *__pyx_n_s_count; -static PyObject *__pyx_n_s_dict; -static PyObject *__pyx_n_s_format; -static PyObject *__pyx_n_s_getstate; -static PyObject *__pyx_n_s_import; -static PyObject *__pyx_n_s_index; -static PyObject *__pyx_n_s_item; -static PyObject *__pyx_n_s_items; -static PyObject *__pyx_n_s_iter; -static PyObject *__pyx_n_s_main; -static PyObject *__pyx_n_s_name; -static PyObject *__pyx_n_s_new; -static PyObject *__pyx_n_s_pickle; -static PyObject *__pyx_n_s_pop; -static PyObject *__pyx_n_s_pos; -static PyObject *__pyx_n_s_pyx_PickleError; -static PyObject *__pyx_n_s_pyx_checksum; -static PyObject *__pyx_n_s_pyx_result; -static PyObject *__pyx_n_s_pyx_state; -static PyObject *__pyx_n_s_pyx_type; -static PyObject *__pyx_n_s_pyx_unpickle_FrozenList; -static PyObject *__pyx_n_s_pyx_vtable; -static PyObject *__pyx_n_s_reduce; -static PyObject *__pyx_n_s_reduce_cython; -static PyObject *__pyx_n_s_reduce_ex; -static PyObject *__pyx_n_s_register; -static PyObject *__pyx_n_s_remove; -static PyObject *__pyx_n_s_reversed; -static PyObject *__pyx_n_s_setstate; -static PyObject *__pyx_n_s_setstate_cython; -static PyObject *__pyx_kp_s_stringsource; -static PyObject *__pyx_n_s_test; -static PyObject *__pyx_n_s_update; -static int __pyx_pf_7aiohttp_11_frozenlist_10FrozenList___init__(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v_items); /* proto */ -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_2freeze(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self); /* proto */ -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_4__getitem__(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v_index); /* proto */ -static int __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_6__setitem__(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v_index, PyObject *__pyx_v_value); /* proto */ -static int __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_8__delitem__(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v_index); /* proto */ -static Py_ssize_t __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_10__len__(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self); /* proto */ -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_12__iter__(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self); /* proto */ -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_14__reversed__(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self); /* proto */ -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_16__richcmp__(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v_other, PyObject *__pyx_v_op); /* proto */ -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_18insert(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v_pos, PyObject *__pyx_v_item); /* proto */ -static int __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_20__contains__(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v_item); /* proto */ -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_22__iadd__(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v_items); /* proto */ -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_24index(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v_item); /* proto */ -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_26remove(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v_item); /* proto */ -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_28clear(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self); /* proto */ -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_30extend(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v_items); /* proto */ -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_32reverse(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self); /* proto */ -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_34pop(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v_index); /* proto */ -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_36append(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v_item); /* proto */ -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_38count(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v_item); /* proto */ -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_40__repr__(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self); /* proto */ -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_6frozen___get__(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self); /* proto */ -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_42__reduce_cython__(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self); /* proto */ -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_44__setstate_cython__(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v___pyx_state); /* proto */ -static PyObject *__pyx_pf_7aiohttp_11_frozenlist___pyx_unpickle_FrozenList(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v___pyx_type, long __pyx_v___pyx_checksum, PyObject *__pyx_v___pyx_state); /* proto */ -static PyObject *__pyx_tp_new_7aiohttp_11_frozenlist_FrozenList(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/ -static PyObject *__pyx_int_0; -static PyObject *__pyx_int_1; -static PyObject *__pyx_int_2; -static PyObject *__pyx_int_3; -static PyObject *__pyx_int_4; -static PyObject *__pyx_int_5; -static PyObject *__pyx_int_155820355; -static PyObject *__pyx_int_neg_1; -static PyObject *__pyx_tuple_; -static PyObject *__pyx_tuple__2; -static PyObject *__pyx_codeobj__3; -/* Late includes */ - -/* "aiohttp/_frozenlist.pyx":9 - * cdef list _items - * - * def __init__(self, items=None): # <<<<<<<<<<<<<< - * self.frozen = False - * if items is not None: - */ - -/* Python wrapper */ -static int __pyx_pw_7aiohttp_11_frozenlist_10FrozenList_1__init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ -static int __pyx_pw_7aiohttp_11_frozenlist_10FrozenList_1__init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { - PyObject *__pyx_v_items = 0; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - int __pyx_r; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__init__ (wrapper)", 0); - { - static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_items,0}; - PyObject* values[1] = {0}; - values[0] = ((PyObject *)Py_None); - if (unlikely(__pyx_kwds)) { - Py_ssize_t kw_args; - const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); - switch (pos_args) { - case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); - CYTHON_FALLTHROUGH; - case 0: break; - default: goto __pyx_L5_argtuple_error; - } - kw_args = PyDict_Size(__pyx_kwds); - switch (pos_args) { - case 0: - if (kw_args > 0) { - PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_items); - if (value) { values[0] = value; kw_args--; } - } - } - if (unlikely(kw_args > 0)) { - if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__init__") < 0)) __PYX_ERR(0, 9, __pyx_L3_error) - } - } else { - switch (PyTuple_GET_SIZE(__pyx_args)) { - case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); - CYTHON_FALLTHROUGH; - case 0: break; - default: goto __pyx_L5_argtuple_error; - } - } - __pyx_v_items = values[0]; - } - goto __pyx_L4_argument_unpacking_done; - __pyx_L5_argtuple_error:; - __Pyx_RaiseArgtupleInvalid("__init__", 0, 0, 1, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 9, __pyx_L3_error) - __pyx_L3_error:; - __Pyx_AddTraceback("aiohttp._frozenlist.FrozenList.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __Pyx_RefNannyFinishContext(); - return -1; - __pyx_L4_argument_unpacking_done:; - __pyx_r = __pyx_pf_7aiohttp_11_frozenlist_10FrozenList___init__(((struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self), __pyx_v_items); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static int __pyx_pf_7aiohttp_11_frozenlist_10FrozenList___init__(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v_items) { - int __pyx_r; - __Pyx_RefNannyDeclarations - int __pyx_t_1; - int __pyx_t_2; - PyObject *__pyx_t_3 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("__init__", 0); - __Pyx_INCREF(__pyx_v_items); - - /* "aiohttp/_frozenlist.pyx":10 - * - * def __init__(self, items=None): - * self.frozen = False # <<<<<<<<<<<<<< - * if items is not None: - * items = list(items) - */ - __pyx_v_self->frozen = 0; - - /* "aiohttp/_frozenlist.pyx":11 - * def __init__(self, items=None): - * self.frozen = False - * if items is not None: # <<<<<<<<<<<<<< - * items = list(items) - * else: - */ - __pyx_t_1 = (__pyx_v_items != Py_None); - __pyx_t_2 = (__pyx_t_1 != 0); - if (__pyx_t_2) { - - /* "aiohttp/_frozenlist.pyx":12 - * self.frozen = False - * if items is not None: - * items = list(items) # <<<<<<<<<<<<<< - * else: - * items = [] - */ - __pyx_t_3 = PySequence_List(__pyx_v_items); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 12, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF_SET(__pyx_v_items, __pyx_t_3); - __pyx_t_3 = 0; - - /* "aiohttp/_frozenlist.pyx":11 - * def __init__(self, items=None): - * self.frozen = False - * if items is not None: # <<<<<<<<<<<<<< - * items = list(items) - * else: - */ - goto __pyx_L3; - } - - /* "aiohttp/_frozenlist.pyx":14 - * items = list(items) - * else: - * items = [] # <<<<<<<<<<<<<< - * self._items = items - * - */ - /*else*/ { - __pyx_t_3 = PyList_New(0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 14, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF_SET(__pyx_v_items, __pyx_t_3); - __pyx_t_3 = 0; - } - __pyx_L3:; - - /* "aiohttp/_frozenlist.pyx":15 - * else: - * items = [] - * self._items = items # <<<<<<<<<<<<<< - * - * cdef object _check_frozen(self): - */ - if (!(likely(PyList_CheckExact(__pyx_v_items))||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "list", Py_TYPE(__pyx_v_items)->tp_name), 0))) __PYX_ERR(0, 15, __pyx_L1_error) - __pyx_t_3 = __pyx_v_items; - __Pyx_INCREF(__pyx_t_3); - __Pyx_GIVEREF(__pyx_t_3); - __Pyx_GOTREF(__pyx_v_self->_items); - __Pyx_DECREF(__pyx_v_self->_items); - __pyx_v_self->_items = ((PyObject*)__pyx_t_3); - __pyx_t_3 = 0; - - /* "aiohttp/_frozenlist.pyx":9 - * cdef list _items - * - * def __init__(self, items=None): # <<<<<<<<<<<<<< - * self.frozen = False - * if items is not None: - */ - - /* function exit code */ - __pyx_r = 0; - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_3); - __Pyx_AddTraceback("aiohttp._frozenlist.FrozenList.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = -1; - __pyx_L0:; - __Pyx_XDECREF(__pyx_v_items); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "aiohttp/_frozenlist.pyx":17 - * self._items = items - * - * cdef object _check_frozen(self): # <<<<<<<<<<<<<< - * if self.frozen: - * raise RuntimeError("Cannot modify frozen list.") - */ - -static PyObject *__pyx_f_7aiohttp_11_frozenlist_10FrozenList__check_frozen(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - int __pyx_t_1; - PyObject *__pyx_t_2 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("_check_frozen", 0); - - /* "aiohttp/_frozenlist.pyx":18 - * - * cdef object _check_frozen(self): - * if self.frozen: # <<<<<<<<<<<<<< - * raise RuntimeError("Cannot modify frozen list.") - * - */ - __pyx_t_1 = (__pyx_v_self->frozen != 0); - if (unlikely(__pyx_t_1)) { - - /* "aiohttp/_frozenlist.pyx":19 - * cdef object _check_frozen(self): - * if self.frozen: - * raise RuntimeError("Cannot modify frozen list.") # <<<<<<<<<<<<<< - * - * cdef inline object _fast_len(self): - */ - __pyx_t_2 = __Pyx_PyObject_Call(__pyx_builtin_RuntimeError, __pyx_tuple_, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 19, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __Pyx_Raise(__pyx_t_2, 0, 0, 0); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __PYX_ERR(0, 19, __pyx_L1_error) - - /* "aiohttp/_frozenlist.pyx":18 - * - * cdef object _check_frozen(self): - * if self.frozen: # <<<<<<<<<<<<<< - * raise RuntimeError("Cannot modify frozen list.") - * - */ - } - - /* "aiohttp/_frozenlist.pyx":17 - * self._items = items - * - * cdef object _check_frozen(self): # <<<<<<<<<<<<<< - * if self.frozen: - * raise RuntimeError("Cannot modify frozen list.") - */ - - /* function exit code */ - __pyx_r = Py_None; __Pyx_INCREF(Py_None); - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_2); - __Pyx_AddTraceback("aiohttp._frozenlist.FrozenList._check_frozen", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = 0; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "aiohttp/_frozenlist.pyx":21 - * raise RuntimeError("Cannot modify frozen list.") - * - * cdef inline object _fast_len(self): # <<<<<<<<<<<<<< - * return len(self._items) - * - */ - -static CYTHON_INLINE PyObject *__pyx_f_7aiohttp_11_frozenlist_10FrozenList__fast_len(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - Py_ssize_t __pyx_t_2; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("_fast_len", 0); - - /* "aiohttp/_frozenlist.pyx":22 - * - * cdef inline object _fast_len(self): - * return len(self._items) # <<<<<<<<<<<<<< - * - * def freeze(self): - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_1 = __pyx_v_self->_items; - __Pyx_INCREF(__pyx_t_1); - if (unlikely(__pyx_t_1 == Py_None)) { - PyErr_SetString(PyExc_TypeError, "object of type 'NoneType' has no len()"); - __PYX_ERR(0, 22, __pyx_L1_error) - } - __pyx_t_2 = PyList_GET_SIZE(__pyx_t_1); if (unlikely(__pyx_t_2 == ((Py_ssize_t)-1))) __PYX_ERR(0, 22, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __pyx_t_1 = PyInt_FromSsize_t(__pyx_t_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 22, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_r = __pyx_t_1; - __pyx_t_1 = 0; - goto __pyx_L0; - - /* "aiohttp/_frozenlist.pyx":21 - * raise RuntimeError("Cannot modify frozen list.") - * - * cdef inline object _fast_len(self): # <<<<<<<<<<<<<< - * return len(self._items) - * - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_AddTraceback("aiohttp._frozenlist.FrozenList._fast_len", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = 0; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "aiohttp/_frozenlist.pyx":24 - * return len(self._items) - * - * def freeze(self): # <<<<<<<<<<<<<< - * self.frozen = True - * - */ - -/* Python wrapper */ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_3freeze(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_3freeze(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("freeze (wrapper)", 0); - __pyx_r = __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_2freeze(((struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_2freeze(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("freeze", 0); - - /* "aiohttp/_frozenlist.pyx":25 - * - * def freeze(self): - * self.frozen = True # <<<<<<<<<<<<<< - * - * def __getitem__(self, index): - */ - __pyx_v_self->frozen = 1; - - /* "aiohttp/_frozenlist.pyx":24 - * return len(self._items) - * - * def freeze(self): # <<<<<<<<<<<<<< - * self.frozen = True - * - */ - - /* function exit code */ - __pyx_r = Py_None; __Pyx_INCREF(Py_None); - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "aiohttp/_frozenlist.pyx":27 - * self.frozen = True - * - * def __getitem__(self, index): # <<<<<<<<<<<<<< - * return self._items[index] - * - */ - -/* Python wrapper */ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_5__getitem__(PyObject *__pyx_v_self, PyObject *__pyx_v_index); /*proto*/ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_5__getitem__(PyObject *__pyx_v_self, PyObject *__pyx_v_index) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__getitem__ (wrapper)", 0); - __pyx_r = __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_4__getitem__(((struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self), ((PyObject *)__pyx_v_index)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_4__getitem__(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v_index) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("__getitem__", 0); - - /* "aiohttp/_frozenlist.pyx":28 - * - * def __getitem__(self, index): - * return self._items[index] # <<<<<<<<<<<<<< - * - * def __setitem__(self, index, value): - */ - __Pyx_XDECREF(__pyx_r); - if (unlikely(__pyx_v_self->_items == Py_None)) { - PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); - __PYX_ERR(0, 28, __pyx_L1_error) - } - __pyx_t_1 = __Pyx_PyObject_GetItem(__pyx_v_self->_items, __pyx_v_index); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 28, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_r = __pyx_t_1; - __pyx_t_1 = 0; - goto __pyx_L0; - - /* "aiohttp/_frozenlist.pyx":27 - * self.frozen = True - * - * def __getitem__(self, index): # <<<<<<<<<<<<<< - * return self._items[index] - * - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_AddTraceback("aiohttp._frozenlist.FrozenList.__getitem__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "aiohttp/_frozenlist.pyx":30 - * return self._items[index] - * - * def __setitem__(self, index, value): # <<<<<<<<<<<<<< - * self._check_frozen() - * self._items[index] = value - */ - -/* Python wrapper */ -static int __pyx_pw_7aiohttp_11_frozenlist_10FrozenList_7__setitem__(PyObject *__pyx_v_self, PyObject *__pyx_v_index, PyObject *__pyx_v_value); /*proto*/ -static int __pyx_pw_7aiohttp_11_frozenlist_10FrozenList_7__setitem__(PyObject *__pyx_v_self, PyObject *__pyx_v_index, PyObject *__pyx_v_value) { - int __pyx_r; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__setitem__ (wrapper)", 0); - __pyx_r = __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_6__setitem__(((struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self), ((PyObject *)__pyx_v_index), ((PyObject *)__pyx_v_value)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static int __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_6__setitem__(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v_index, PyObject *__pyx_v_value) { - int __pyx_r; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("__setitem__", 0); - - /* "aiohttp/_frozenlist.pyx":31 - * - * def __setitem__(self, index, value): - * self._check_frozen() # <<<<<<<<<<<<<< - * self._items[index] = value - * - */ - __pyx_t_1 = ((struct __pyx_vtabstruct_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self->__pyx_vtab)->_check_frozen(__pyx_v_self); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 31, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - - /* "aiohttp/_frozenlist.pyx":32 - * def __setitem__(self, index, value): - * self._check_frozen() - * self._items[index] = value # <<<<<<<<<<<<<< - * - * def __delitem__(self, index): - */ - if (unlikely(__pyx_v_self->_items == Py_None)) { - PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); - __PYX_ERR(0, 32, __pyx_L1_error) - } - if (unlikely(PyObject_SetItem(__pyx_v_self->_items, __pyx_v_index, __pyx_v_value) < 0)) __PYX_ERR(0, 32, __pyx_L1_error) - - /* "aiohttp/_frozenlist.pyx":30 - * return self._items[index] - * - * def __setitem__(self, index, value): # <<<<<<<<<<<<<< - * self._check_frozen() - * self._items[index] = value - */ - - /* function exit code */ - __pyx_r = 0; - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_AddTraceback("aiohttp._frozenlist.FrozenList.__setitem__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = -1; - __pyx_L0:; - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "aiohttp/_frozenlist.pyx":34 - * self._items[index] = value - * - * def __delitem__(self, index): # <<<<<<<<<<<<<< - * self._check_frozen() - * del self._items[index] - */ - -/* Python wrapper */ -static int __pyx_pw_7aiohttp_11_frozenlist_10FrozenList_9__delitem__(PyObject *__pyx_v_self, PyObject *__pyx_v_index); /*proto*/ -static int __pyx_pw_7aiohttp_11_frozenlist_10FrozenList_9__delitem__(PyObject *__pyx_v_self, PyObject *__pyx_v_index) { - int __pyx_r; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__delitem__ (wrapper)", 0); - __pyx_r = __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_8__delitem__(((struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self), ((PyObject *)__pyx_v_index)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static int __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_8__delitem__(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v_index) { - int __pyx_r; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("__delitem__", 0); - - /* "aiohttp/_frozenlist.pyx":35 - * - * def __delitem__(self, index): - * self._check_frozen() # <<<<<<<<<<<<<< - * del self._items[index] - * - */ - __pyx_t_1 = ((struct __pyx_vtabstruct_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self->__pyx_vtab)->_check_frozen(__pyx_v_self); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 35, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - - /* "aiohttp/_frozenlist.pyx":36 - * def __delitem__(self, index): - * self._check_frozen() - * del self._items[index] # <<<<<<<<<<<<<< - * - * def __len__(self): - */ - if (unlikely(__pyx_v_self->_items == Py_None)) { - PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); - __PYX_ERR(0, 36, __pyx_L1_error) - } - if (unlikely(PyObject_DelItem(__pyx_v_self->_items, __pyx_v_index) < 0)) __PYX_ERR(0, 36, __pyx_L1_error) - - /* "aiohttp/_frozenlist.pyx":34 - * self._items[index] = value - * - * def __delitem__(self, index): # <<<<<<<<<<<<<< - * self._check_frozen() - * del self._items[index] - */ - - /* function exit code */ - __pyx_r = 0; - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_AddTraceback("aiohttp._frozenlist.FrozenList.__delitem__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = -1; - __pyx_L0:; - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "aiohttp/_frozenlist.pyx":38 - * del self._items[index] - * - * def __len__(self): # <<<<<<<<<<<<<< - * return self._fast_len() - * - */ - -/* Python wrapper */ -static Py_ssize_t __pyx_pw_7aiohttp_11_frozenlist_10FrozenList_11__len__(PyObject *__pyx_v_self); /*proto*/ -static Py_ssize_t __pyx_pw_7aiohttp_11_frozenlist_10FrozenList_11__len__(PyObject *__pyx_v_self) { - Py_ssize_t __pyx_r; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__len__ (wrapper)", 0); - __pyx_r = __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_10__len__(((struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static Py_ssize_t __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_10__len__(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self) { - Py_ssize_t __pyx_r; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - Py_ssize_t __pyx_t_2; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("__len__", 0); - - /* "aiohttp/_frozenlist.pyx":39 - * - * def __len__(self): - * return self._fast_len() # <<<<<<<<<<<<<< - * - * def __iter__(self): - */ - __pyx_t_1 = __pyx_f_7aiohttp_11_frozenlist_10FrozenList__fast_len(__pyx_v_self); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 39, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_2 = __Pyx_PyIndex_AsSsize_t(__pyx_t_1); if (unlikely((__pyx_t_2 == (Py_ssize_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 39, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __pyx_r = __pyx_t_2; - goto __pyx_L0; - - /* "aiohttp/_frozenlist.pyx":38 - * del self._items[index] - * - * def __len__(self): # <<<<<<<<<<<<<< - * return self._fast_len() - * - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_AddTraceback("aiohttp._frozenlist.FrozenList.__len__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = -1; - __pyx_L0:; - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "aiohttp/_frozenlist.pyx":41 - * return self._fast_len() - * - * def __iter__(self): # <<<<<<<<<<<<<< - * return self._items.__iter__() - * - */ - -/* Python wrapper */ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_13__iter__(PyObject *__pyx_v_self); /*proto*/ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_13__iter__(PyObject *__pyx_v_self) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__iter__ (wrapper)", 0); - __pyx_r = __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_12__iter__(((struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_12__iter__(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - PyObject *__pyx_t_2 = NULL; - PyObject *__pyx_t_3 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("__iter__", 0); - - /* "aiohttp/_frozenlist.pyx":42 - * - * def __iter__(self): - * return self._items.__iter__() # <<<<<<<<<<<<<< - * - * def __reversed__(self): - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_self->_items, __pyx_n_s_iter); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 42, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = NULL; - if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) { - __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2); - if (likely(__pyx_t_3)) { - PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2); - __Pyx_INCREF(__pyx_t_3); - __Pyx_INCREF(function); - __Pyx_DECREF_SET(__pyx_t_2, function); - } - } - __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3) : __Pyx_PyObject_CallNoArg(__pyx_t_2); - __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; - if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 42, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_r = __pyx_t_1; - __pyx_t_1 = 0; - goto __pyx_L0; - - /* "aiohttp/_frozenlist.pyx":41 - * return self._fast_len() - * - * def __iter__(self): # <<<<<<<<<<<<<< - * return self._items.__iter__() - * - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_XDECREF(__pyx_t_2); - __Pyx_XDECREF(__pyx_t_3); - __Pyx_AddTraceback("aiohttp._frozenlist.FrozenList.__iter__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "aiohttp/_frozenlist.pyx":44 - * return self._items.__iter__() - * - * def __reversed__(self): # <<<<<<<<<<<<<< - * return self._items.__reversed__() - * - */ - -/* Python wrapper */ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_15__reversed__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_15__reversed__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__reversed__ (wrapper)", 0); - __pyx_r = __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_14__reversed__(((struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_14__reversed__(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - PyObject *__pyx_t_2 = NULL; - PyObject *__pyx_t_3 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("__reversed__", 0); - - /* "aiohttp/_frozenlist.pyx":45 - * - * def __reversed__(self): - * return self._items.__reversed__() # <<<<<<<<<<<<<< - * - * def __richcmp__(self, other, op): - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_self->_items, __pyx_n_s_reversed); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 45, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = NULL; - if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) { - __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2); - if (likely(__pyx_t_3)) { - PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2); - __Pyx_INCREF(__pyx_t_3); - __Pyx_INCREF(function); - __Pyx_DECREF_SET(__pyx_t_2, function); - } - } - __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3) : __Pyx_PyObject_CallNoArg(__pyx_t_2); - __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; - if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 45, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_r = __pyx_t_1; - __pyx_t_1 = 0; - goto __pyx_L0; - - /* "aiohttp/_frozenlist.pyx":44 - * return self._items.__iter__() - * - * def __reversed__(self): # <<<<<<<<<<<<<< - * return self._items.__reversed__() - * - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_XDECREF(__pyx_t_2); - __Pyx_XDECREF(__pyx_t_3); - __Pyx_AddTraceback("aiohttp._frozenlist.FrozenList.__reversed__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "aiohttp/_frozenlist.pyx":47 - * return self._items.__reversed__() - * - * def __richcmp__(self, other, op): # <<<<<<<<<<<<<< - * if op == 0: # < - * return list(self) < other - */ - -/* Python wrapper */ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_17__richcmp__(PyObject *__pyx_v_self, PyObject *__pyx_v_other, int __pyx_arg_op); /*proto*/ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_17__richcmp__(PyObject *__pyx_v_self, PyObject *__pyx_v_other, int __pyx_arg_op) { - PyObject *__pyx_v_op = 0; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__richcmp__ (wrapper)", 0); - __pyx_v_op = __Pyx_PyInt_From_int(__pyx_arg_op); if (unlikely(!__pyx_v_op)) __PYX_ERR(0, 47, __pyx_L3_error) - __Pyx_GOTREF(__pyx_v_op); - goto __pyx_L4_argument_unpacking_done; - __pyx_L3_error:; - __Pyx_AddTraceback("aiohttp._frozenlist.FrozenList.__richcmp__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __Pyx_RefNannyFinishContext(); - return NULL; - __pyx_L4_argument_unpacking_done:; - __pyx_r = __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_16__richcmp__(((struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self), ((PyObject *)__pyx_v_other), ((PyObject *)__pyx_v_op)); - - /* function exit code */ - __Pyx_XDECREF(__pyx_v_op); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_16__richcmp__(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v_other, PyObject *__pyx_v_op) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - int __pyx_t_2; - PyObject *__pyx_t_3 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("__richcmp__", 0); - - /* "aiohttp/_frozenlist.pyx":48 - * - * def __richcmp__(self, other, op): - * if op == 0: # < # <<<<<<<<<<<<<< - * return list(self) < other - * if op == 1: # <= - */ - __pyx_t_1 = __Pyx_PyInt_EqObjC(__pyx_v_op, __pyx_int_0, 0, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 48, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 48, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - if (__pyx_t_2) { - - /* "aiohttp/_frozenlist.pyx":49 - * def __richcmp__(self, other, op): - * if op == 0: # < - * return list(self) < other # <<<<<<<<<<<<<< - * if op == 1: # <= - * return list(self) <= other - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_1 = PySequence_List(((PyObject *)__pyx_v_self)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 49, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_3 = PyObject_RichCompare(__pyx_t_1, __pyx_v_other, Py_LT); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 49, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __pyx_r = __pyx_t_3; - __pyx_t_3 = 0; - goto __pyx_L0; - - /* "aiohttp/_frozenlist.pyx":48 - * - * def __richcmp__(self, other, op): - * if op == 0: # < # <<<<<<<<<<<<<< - * return list(self) < other - * if op == 1: # <= - */ - } - - /* "aiohttp/_frozenlist.pyx":50 - * if op == 0: # < - * return list(self) < other - * if op == 1: # <= # <<<<<<<<<<<<<< - * return list(self) <= other - * if op == 2: # == - */ - __pyx_t_3 = __Pyx_PyInt_EqObjC(__pyx_v_op, __pyx_int_1, 1, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 50, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 50, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - if (__pyx_t_2) { - - /* "aiohttp/_frozenlist.pyx":51 - * return list(self) < other - * if op == 1: # <= - * return list(self) <= other # <<<<<<<<<<<<<< - * if op == 2: # == - * return list(self) == other - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_3 = PySequence_List(((PyObject *)__pyx_v_self)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 51, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __pyx_t_1 = PyObject_RichCompare(__pyx_t_3, __pyx_v_other, Py_LE); __Pyx_XGOTREF(__pyx_t_1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 51, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __pyx_r = __pyx_t_1; - __pyx_t_1 = 0; - goto __pyx_L0; - - /* "aiohttp/_frozenlist.pyx":50 - * if op == 0: # < - * return list(self) < other - * if op == 1: # <= # <<<<<<<<<<<<<< - * return list(self) <= other - * if op == 2: # == - */ - } - - /* "aiohttp/_frozenlist.pyx":52 - * if op == 1: # <= - * return list(self) <= other - * if op == 2: # == # <<<<<<<<<<<<<< - * return list(self) == other - * if op == 3: # != - */ - __pyx_t_1 = __Pyx_PyInt_EqObjC(__pyx_v_op, __pyx_int_2, 2, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 52, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 52, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - if (__pyx_t_2) { - - /* "aiohttp/_frozenlist.pyx":53 - * return list(self) <= other - * if op == 2: # == - * return list(self) == other # <<<<<<<<<<<<<< - * if op == 3: # != - * return list(self) != other - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_1 = PySequence_List(((PyObject *)__pyx_v_self)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 53, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_3 = PyObject_RichCompare(__pyx_t_1, __pyx_v_other, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 53, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __pyx_r = __pyx_t_3; - __pyx_t_3 = 0; - goto __pyx_L0; - - /* "aiohttp/_frozenlist.pyx":52 - * if op == 1: # <= - * return list(self) <= other - * if op == 2: # == # <<<<<<<<<<<<<< - * return list(self) == other - * if op == 3: # != - */ - } - - /* "aiohttp/_frozenlist.pyx":54 - * if op == 2: # == - * return list(self) == other - * if op == 3: # != # <<<<<<<<<<<<<< - * return list(self) != other - * if op == 4: # > - */ - __pyx_t_3 = __Pyx_PyInt_EqObjC(__pyx_v_op, __pyx_int_3, 3, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 54, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 54, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - if (__pyx_t_2) { - - /* "aiohttp/_frozenlist.pyx":55 - * return list(self) == other - * if op == 3: # != - * return list(self) != other # <<<<<<<<<<<<<< - * if op == 4: # > - * return list(self) > other - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_3 = PySequence_List(((PyObject *)__pyx_v_self)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 55, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __pyx_t_1 = PyObject_RichCompare(__pyx_t_3, __pyx_v_other, Py_NE); __Pyx_XGOTREF(__pyx_t_1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 55, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __pyx_r = __pyx_t_1; - __pyx_t_1 = 0; - goto __pyx_L0; - - /* "aiohttp/_frozenlist.pyx":54 - * if op == 2: # == - * return list(self) == other - * if op == 3: # != # <<<<<<<<<<<<<< - * return list(self) != other - * if op == 4: # > - */ - } - - /* "aiohttp/_frozenlist.pyx":56 - * if op == 3: # != - * return list(self) != other - * if op == 4: # > # <<<<<<<<<<<<<< - * return list(self) > other - * if op == 5: # => - */ - __pyx_t_1 = __Pyx_PyInt_EqObjC(__pyx_v_op, __pyx_int_4, 4, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 56, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 56, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - if (__pyx_t_2) { - - /* "aiohttp/_frozenlist.pyx":57 - * return list(self) != other - * if op == 4: # > - * return list(self) > other # <<<<<<<<<<<<<< - * if op == 5: # => - * return list(self) >= other - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_1 = PySequence_List(((PyObject *)__pyx_v_self)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 57, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_3 = PyObject_RichCompare(__pyx_t_1, __pyx_v_other, Py_GT); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 57, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __pyx_r = __pyx_t_3; - __pyx_t_3 = 0; - goto __pyx_L0; - - /* "aiohttp/_frozenlist.pyx":56 - * if op == 3: # != - * return list(self) != other - * if op == 4: # > # <<<<<<<<<<<<<< - * return list(self) > other - * if op == 5: # => - */ - } - - /* "aiohttp/_frozenlist.pyx":58 - * if op == 4: # > - * return list(self) > other - * if op == 5: # => # <<<<<<<<<<<<<< - * return list(self) >= other - * - */ - __pyx_t_3 = __Pyx_PyInt_EqObjC(__pyx_v_op, __pyx_int_5, 5, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 58, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 58, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - if (__pyx_t_2) { - - /* "aiohttp/_frozenlist.pyx":59 - * return list(self) > other - * if op == 5: # => - * return list(self) >= other # <<<<<<<<<<<<<< - * - * def insert(self, pos, item): - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_3 = PySequence_List(((PyObject *)__pyx_v_self)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 59, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __pyx_t_1 = PyObject_RichCompare(__pyx_t_3, __pyx_v_other, Py_GE); __Pyx_XGOTREF(__pyx_t_1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 59, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __pyx_r = __pyx_t_1; - __pyx_t_1 = 0; - goto __pyx_L0; - - /* "aiohttp/_frozenlist.pyx":58 - * if op == 4: # > - * return list(self) > other - * if op == 5: # => # <<<<<<<<<<<<<< - * return list(self) >= other - * - */ - } - - /* "aiohttp/_frozenlist.pyx":47 - * return self._items.__reversed__() - * - * def __richcmp__(self, other, op): # <<<<<<<<<<<<<< - * if op == 0: # < - * return list(self) < other - */ - - /* function exit code */ - __pyx_r = Py_None; __Pyx_INCREF(Py_None); - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_XDECREF(__pyx_t_3); - __Pyx_AddTraceback("aiohttp._frozenlist.FrozenList.__richcmp__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "aiohttp/_frozenlist.pyx":61 - * return list(self) >= other - * - * def insert(self, pos, item): # <<<<<<<<<<<<<< - * self._check_frozen() - * self._items.insert(pos, item) - */ - -/* Python wrapper */ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_19insert(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_19insert(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { - PyObject *__pyx_v_pos = 0; - PyObject *__pyx_v_item = 0; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("insert (wrapper)", 0); - { - static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_pos,&__pyx_n_s_item,0}; - PyObject* values[2] = {0,0}; - if (unlikely(__pyx_kwds)) { - Py_ssize_t kw_args; - const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); - switch (pos_args) { - case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); - CYTHON_FALLTHROUGH; - case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); - CYTHON_FALLTHROUGH; - case 0: break; - default: goto __pyx_L5_argtuple_error; - } - kw_args = PyDict_Size(__pyx_kwds); - switch (pos_args) { - case 0: - if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_pos)) != 0)) kw_args--; - else goto __pyx_L5_argtuple_error; - CYTHON_FALLTHROUGH; - case 1: - if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_item)) != 0)) kw_args--; - else { - __Pyx_RaiseArgtupleInvalid("insert", 1, 2, 2, 1); __PYX_ERR(0, 61, __pyx_L3_error) - } - } - if (unlikely(kw_args > 0)) { - if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "insert") < 0)) __PYX_ERR(0, 61, __pyx_L3_error) - } - } else if (PyTuple_GET_SIZE(__pyx_args) != 2) { - goto __pyx_L5_argtuple_error; - } else { - values[0] = PyTuple_GET_ITEM(__pyx_args, 0); - values[1] = PyTuple_GET_ITEM(__pyx_args, 1); - } - __pyx_v_pos = values[0]; - __pyx_v_item = values[1]; - } - goto __pyx_L4_argument_unpacking_done; - __pyx_L5_argtuple_error:; - __Pyx_RaiseArgtupleInvalid("insert", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 61, __pyx_L3_error) - __pyx_L3_error:; - __Pyx_AddTraceback("aiohttp._frozenlist.FrozenList.insert", __pyx_clineno, __pyx_lineno, __pyx_filename); - __Pyx_RefNannyFinishContext(); - return NULL; - __pyx_L4_argument_unpacking_done:; - __pyx_r = __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_18insert(((struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self), __pyx_v_pos, __pyx_v_item); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_18insert(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v_pos, PyObject *__pyx_v_item) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - Py_ssize_t __pyx_t_2; - int __pyx_t_3; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("insert", 0); - - /* "aiohttp/_frozenlist.pyx":62 - * - * def insert(self, pos, item): - * self._check_frozen() # <<<<<<<<<<<<<< - * self._items.insert(pos, item) - * - */ - __pyx_t_1 = ((struct __pyx_vtabstruct_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self->__pyx_vtab)->_check_frozen(__pyx_v_self); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 62, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - - /* "aiohttp/_frozenlist.pyx":63 - * def insert(self, pos, item): - * self._check_frozen() - * self._items.insert(pos, item) # <<<<<<<<<<<<<< - * - * def __contains__(self, item): - */ - if (unlikely(__pyx_v_self->_items == Py_None)) { - PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "insert"); - __PYX_ERR(0, 63, __pyx_L1_error) - } - __pyx_t_2 = __Pyx_PyIndex_AsSsize_t(__pyx_v_pos); if (unlikely((__pyx_t_2 == (Py_ssize_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 63, __pyx_L1_error) - __pyx_t_3 = PyList_Insert(__pyx_v_self->_items, __pyx_t_2, __pyx_v_item); if (unlikely(__pyx_t_3 == ((int)-1))) __PYX_ERR(0, 63, __pyx_L1_error) - - /* "aiohttp/_frozenlist.pyx":61 - * return list(self) >= other - * - * def insert(self, pos, item): # <<<<<<<<<<<<<< - * self._check_frozen() - * self._items.insert(pos, item) - */ - - /* function exit code */ - __pyx_r = Py_None; __Pyx_INCREF(Py_None); - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_AddTraceback("aiohttp._frozenlist.FrozenList.insert", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "aiohttp/_frozenlist.pyx":65 - * self._items.insert(pos, item) - * - * def __contains__(self, item): # <<<<<<<<<<<<<< - * return item in self._items - * - */ - -/* Python wrapper */ -static int __pyx_pw_7aiohttp_11_frozenlist_10FrozenList_21__contains__(PyObject *__pyx_v_self, PyObject *__pyx_v_item); /*proto*/ -static int __pyx_pw_7aiohttp_11_frozenlist_10FrozenList_21__contains__(PyObject *__pyx_v_self, PyObject *__pyx_v_item) { - int __pyx_r; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__contains__ (wrapper)", 0); - __pyx_r = __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_20__contains__(((struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self), ((PyObject *)__pyx_v_item)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static int __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_20__contains__(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v_item) { - int __pyx_r; - __Pyx_RefNannyDeclarations - int __pyx_t_1; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("__contains__", 0); - - /* "aiohttp/_frozenlist.pyx":66 - * - * def __contains__(self, item): - * return item in self._items # <<<<<<<<<<<<<< - * - * def __iadd__(self, items): - */ - __pyx_t_1 = (__Pyx_PySequence_ContainsTF(__pyx_v_item, __pyx_v_self->_items, Py_EQ)); if (unlikely(__pyx_t_1 < 0)) __PYX_ERR(0, 66, __pyx_L1_error) - __pyx_r = __pyx_t_1; - goto __pyx_L0; - - /* "aiohttp/_frozenlist.pyx":65 - * self._items.insert(pos, item) - * - * def __contains__(self, item): # <<<<<<<<<<<<<< - * return item in self._items - * - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_AddTraceback("aiohttp._frozenlist.FrozenList.__contains__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = -1; - __pyx_L0:; - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "aiohttp/_frozenlist.pyx":68 - * return item in self._items - * - * def __iadd__(self, items): # <<<<<<<<<<<<<< - * self._check_frozen() - * self._items += list(items) - */ - -/* Python wrapper */ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_23__iadd__(PyObject *__pyx_v_self, PyObject *__pyx_v_items); /*proto*/ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_23__iadd__(PyObject *__pyx_v_self, PyObject *__pyx_v_items) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__iadd__ (wrapper)", 0); - __pyx_r = __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_22__iadd__(((struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self), ((PyObject *)__pyx_v_items)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_22__iadd__(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v_items) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - PyObject *__pyx_t_2 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("__iadd__", 0); - - /* "aiohttp/_frozenlist.pyx":69 - * - * def __iadd__(self, items): - * self._check_frozen() # <<<<<<<<<<<<<< - * self._items += list(items) - * return self - */ - __pyx_t_1 = ((struct __pyx_vtabstruct_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self->__pyx_vtab)->_check_frozen(__pyx_v_self); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 69, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - - /* "aiohttp/_frozenlist.pyx":70 - * def __iadd__(self, items): - * self._check_frozen() - * self._items += list(items) # <<<<<<<<<<<<<< - * return self - * - */ - __pyx_t_1 = PySequence_List(__pyx_v_items); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 70, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_2 = PyNumber_InPlaceAdd(__pyx_v_self->_items, __pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 70, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __Pyx_GIVEREF(__pyx_t_2); - __Pyx_GOTREF(__pyx_v_self->_items); - __Pyx_DECREF(__pyx_v_self->_items); - __pyx_v_self->_items = ((PyObject*)__pyx_t_2); - __pyx_t_2 = 0; - - /* "aiohttp/_frozenlist.pyx":71 - * self._check_frozen() - * self._items += list(items) - * return self # <<<<<<<<<<<<<< - * - * def index(self, item): - */ - __Pyx_XDECREF(__pyx_r); - __Pyx_INCREF(((PyObject *)__pyx_v_self)); - __pyx_r = ((PyObject *)__pyx_v_self); - goto __pyx_L0; - - /* "aiohttp/_frozenlist.pyx":68 - * return item in self._items - * - * def __iadd__(self, items): # <<<<<<<<<<<<<< - * self._check_frozen() - * self._items += list(items) - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_XDECREF(__pyx_t_2); - __Pyx_AddTraceback("aiohttp._frozenlist.FrozenList.__iadd__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "aiohttp/_frozenlist.pyx":73 - * return self - * - * def index(self, item): # <<<<<<<<<<<<<< - * return self._items.index(item) - * - */ - -/* Python wrapper */ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_25index(PyObject *__pyx_v_self, PyObject *__pyx_v_item); /*proto*/ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_25index(PyObject *__pyx_v_self, PyObject *__pyx_v_item) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("index (wrapper)", 0); - __pyx_r = __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_24index(((struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self), ((PyObject *)__pyx_v_item)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_24index(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v_item) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - PyObject *__pyx_t_2 = NULL; - PyObject *__pyx_t_3 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("index", 0); - - /* "aiohttp/_frozenlist.pyx":74 - * - * def index(self, item): - * return self._items.index(item) # <<<<<<<<<<<<<< - * - * def remove(self, item): - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_self->_items, __pyx_n_s_index); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 74, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = NULL; - if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) { - __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2); - if (likely(__pyx_t_3)) { - PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2); - __Pyx_INCREF(__pyx_t_3); - __Pyx_INCREF(function); - __Pyx_DECREF_SET(__pyx_t_2, function); - } - } - __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_3, __pyx_v_item) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_v_item); - __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; - if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 74, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_r = __pyx_t_1; - __pyx_t_1 = 0; - goto __pyx_L0; - - /* "aiohttp/_frozenlist.pyx":73 - * return self - * - * def index(self, item): # <<<<<<<<<<<<<< - * return self._items.index(item) - * - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_XDECREF(__pyx_t_2); - __Pyx_XDECREF(__pyx_t_3); - __Pyx_AddTraceback("aiohttp._frozenlist.FrozenList.index", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "aiohttp/_frozenlist.pyx":76 - * return self._items.index(item) - * - * def remove(self, item): # <<<<<<<<<<<<<< - * self._check_frozen() - * self._items.remove(item) - */ - -/* Python wrapper */ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_27remove(PyObject *__pyx_v_self, PyObject *__pyx_v_item); /*proto*/ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_27remove(PyObject *__pyx_v_self, PyObject *__pyx_v_item) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("remove (wrapper)", 0); - __pyx_r = __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_26remove(((struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self), ((PyObject *)__pyx_v_item)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_26remove(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v_item) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - PyObject *__pyx_t_2 = NULL; - PyObject *__pyx_t_3 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("remove", 0); - - /* "aiohttp/_frozenlist.pyx":77 - * - * def remove(self, item): - * self._check_frozen() # <<<<<<<<<<<<<< - * self._items.remove(item) - * - */ - __pyx_t_1 = ((struct __pyx_vtabstruct_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self->__pyx_vtab)->_check_frozen(__pyx_v_self); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 77, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - - /* "aiohttp/_frozenlist.pyx":78 - * def remove(self, item): - * self._check_frozen() - * self._items.remove(item) # <<<<<<<<<<<<<< - * - * def clear(self): - */ - __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_self->_items, __pyx_n_s_remove); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 78, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = NULL; - if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) { - __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2); - if (likely(__pyx_t_3)) { - PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2); - __Pyx_INCREF(__pyx_t_3); - __Pyx_INCREF(function); - __Pyx_DECREF_SET(__pyx_t_2, function); - } - } - __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_3, __pyx_v_item) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_v_item); - __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; - if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 78, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - - /* "aiohttp/_frozenlist.pyx":76 - * return self._items.index(item) - * - * def remove(self, item): # <<<<<<<<<<<<<< - * self._check_frozen() - * self._items.remove(item) - */ - - /* function exit code */ - __pyx_r = Py_None; __Pyx_INCREF(Py_None); - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_XDECREF(__pyx_t_2); - __Pyx_XDECREF(__pyx_t_3); - __Pyx_AddTraceback("aiohttp._frozenlist.FrozenList.remove", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "aiohttp/_frozenlist.pyx":80 - * self._items.remove(item) - * - * def clear(self): # <<<<<<<<<<<<<< - * self._check_frozen() - * self._items.clear() - */ - -/* Python wrapper */ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_29clear(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_29clear(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("clear (wrapper)", 0); - __pyx_r = __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_28clear(((struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_28clear(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - PyObject *__pyx_t_2 = NULL; - PyObject *__pyx_t_3 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("clear", 0); - - /* "aiohttp/_frozenlist.pyx":81 - * - * def clear(self): - * self._check_frozen() # <<<<<<<<<<<<<< - * self._items.clear() - * - */ - __pyx_t_1 = ((struct __pyx_vtabstruct_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self->__pyx_vtab)->_check_frozen(__pyx_v_self); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 81, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - - /* "aiohttp/_frozenlist.pyx":82 - * def clear(self): - * self._check_frozen() - * self._items.clear() # <<<<<<<<<<<<<< - * - * def extend(self, items): - */ - __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_self->_items, __pyx_n_s_clear); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 82, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = NULL; - if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) { - __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2); - if (likely(__pyx_t_3)) { - PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2); - __Pyx_INCREF(__pyx_t_3); - __Pyx_INCREF(function); - __Pyx_DECREF_SET(__pyx_t_2, function); - } - } - __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3) : __Pyx_PyObject_CallNoArg(__pyx_t_2); - __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; - if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 82, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - - /* "aiohttp/_frozenlist.pyx":80 - * self._items.remove(item) - * - * def clear(self): # <<<<<<<<<<<<<< - * self._check_frozen() - * self._items.clear() - */ - - /* function exit code */ - __pyx_r = Py_None; __Pyx_INCREF(Py_None); - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_XDECREF(__pyx_t_2); - __Pyx_XDECREF(__pyx_t_3); - __Pyx_AddTraceback("aiohttp._frozenlist.FrozenList.clear", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "aiohttp/_frozenlist.pyx":84 - * self._items.clear() - * - * def extend(self, items): # <<<<<<<<<<<<<< - * self._check_frozen() - * self._items += list(items) - */ - -/* Python wrapper */ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_31extend(PyObject *__pyx_v_self, PyObject *__pyx_v_items); /*proto*/ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_31extend(PyObject *__pyx_v_self, PyObject *__pyx_v_items) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("extend (wrapper)", 0); - __pyx_r = __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_30extend(((struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self), ((PyObject *)__pyx_v_items)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_30extend(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v_items) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - PyObject *__pyx_t_2 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("extend", 0); - - /* "aiohttp/_frozenlist.pyx":85 - * - * def extend(self, items): - * self._check_frozen() # <<<<<<<<<<<<<< - * self._items += list(items) - * - */ - __pyx_t_1 = ((struct __pyx_vtabstruct_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self->__pyx_vtab)->_check_frozen(__pyx_v_self); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 85, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - - /* "aiohttp/_frozenlist.pyx":86 - * def extend(self, items): - * self._check_frozen() - * self._items += list(items) # <<<<<<<<<<<<<< - * - * def reverse(self): - */ - __pyx_t_1 = PySequence_List(__pyx_v_items); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 86, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_2 = PyNumber_InPlaceAdd(__pyx_v_self->_items, __pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 86, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __Pyx_GIVEREF(__pyx_t_2); - __Pyx_GOTREF(__pyx_v_self->_items); - __Pyx_DECREF(__pyx_v_self->_items); - __pyx_v_self->_items = ((PyObject*)__pyx_t_2); - __pyx_t_2 = 0; - - /* "aiohttp/_frozenlist.pyx":84 - * self._items.clear() - * - * def extend(self, items): # <<<<<<<<<<<<<< - * self._check_frozen() - * self._items += list(items) - */ - - /* function exit code */ - __pyx_r = Py_None; __Pyx_INCREF(Py_None); - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_XDECREF(__pyx_t_2); - __Pyx_AddTraceback("aiohttp._frozenlist.FrozenList.extend", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "aiohttp/_frozenlist.pyx":88 - * self._items += list(items) - * - * def reverse(self): # <<<<<<<<<<<<<< - * self._check_frozen() - * self._items.reverse() - */ - -/* Python wrapper */ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_33reverse(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_33reverse(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("reverse (wrapper)", 0); - __pyx_r = __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_32reverse(((struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_32reverse(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - int __pyx_t_2; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("reverse", 0); - - /* "aiohttp/_frozenlist.pyx":89 - * - * def reverse(self): - * self._check_frozen() # <<<<<<<<<<<<<< - * self._items.reverse() - * - */ - __pyx_t_1 = ((struct __pyx_vtabstruct_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self->__pyx_vtab)->_check_frozen(__pyx_v_self); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 89, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - - /* "aiohttp/_frozenlist.pyx":90 - * def reverse(self): - * self._check_frozen() - * self._items.reverse() # <<<<<<<<<<<<<< - * - * def pop(self, index=-1): - */ - if (unlikely(__pyx_v_self->_items == Py_None)) { - PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "reverse"); - __PYX_ERR(0, 90, __pyx_L1_error) - } - __pyx_t_2 = PyList_Reverse(__pyx_v_self->_items); if (unlikely(__pyx_t_2 == ((int)-1))) __PYX_ERR(0, 90, __pyx_L1_error) - - /* "aiohttp/_frozenlist.pyx":88 - * self._items += list(items) - * - * def reverse(self): # <<<<<<<<<<<<<< - * self._check_frozen() - * self._items.reverse() - */ - - /* function exit code */ - __pyx_r = Py_None; __Pyx_INCREF(Py_None); - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_AddTraceback("aiohttp._frozenlist.FrozenList.reverse", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "aiohttp/_frozenlist.pyx":92 - * self._items.reverse() - * - * def pop(self, index=-1): # <<<<<<<<<<<<<< - * self._check_frozen() - * return self._items.pop(index) - */ - -/* Python wrapper */ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_35pop(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_35pop(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { - PyObject *__pyx_v_index = 0; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("pop (wrapper)", 0); - { - static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_index,0}; - PyObject* values[1] = {0}; - values[0] = ((PyObject *)__pyx_int_neg_1); - if (unlikely(__pyx_kwds)) { - Py_ssize_t kw_args; - const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); - switch (pos_args) { - case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); - CYTHON_FALLTHROUGH; - case 0: break; - default: goto __pyx_L5_argtuple_error; - } - kw_args = PyDict_Size(__pyx_kwds); - switch (pos_args) { - case 0: - if (kw_args > 0) { - PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_index); - if (value) { values[0] = value; kw_args--; } - } - } - if (unlikely(kw_args > 0)) { - if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "pop") < 0)) __PYX_ERR(0, 92, __pyx_L3_error) - } - } else { - switch (PyTuple_GET_SIZE(__pyx_args)) { - case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); - CYTHON_FALLTHROUGH; - case 0: break; - default: goto __pyx_L5_argtuple_error; - } - } - __pyx_v_index = values[0]; - } - goto __pyx_L4_argument_unpacking_done; - __pyx_L5_argtuple_error:; - __Pyx_RaiseArgtupleInvalid("pop", 0, 0, 1, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 92, __pyx_L3_error) - __pyx_L3_error:; - __Pyx_AddTraceback("aiohttp._frozenlist.FrozenList.pop", __pyx_clineno, __pyx_lineno, __pyx_filename); - __Pyx_RefNannyFinishContext(); - return NULL; - __pyx_L4_argument_unpacking_done:; - __pyx_r = __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_34pop(((struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self), __pyx_v_index); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_34pop(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v_index) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - Py_ssize_t __pyx_t_2; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("pop", 0); - - /* "aiohttp/_frozenlist.pyx":93 - * - * def pop(self, index=-1): - * self._check_frozen() # <<<<<<<<<<<<<< - * return self._items.pop(index) - * - */ - __pyx_t_1 = ((struct __pyx_vtabstruct_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self->__pyx_vtab)->_check_frozen(__pyx_v_self); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 93, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - - /* "aiohttp/_frozenlist.pyx":94 - * def pop(self, index=-1): - * self._check_frozen() - * return self._items.pop(index) # <<<<<<<<<<<<<< - * - * def append(self, item): - */ - __Pyx_XDECREF(__pyx_r); - if (unlikely(__pyx_v_self->_items == Py_None)) { - PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "pop"); - __PYX_ERR(0, 94, __pyx_L1_error) - } - __pyx_t_2 = __Pyx_PyIndex_AsSsize_t(__pyx_v_index); if (unlikely((__pyx_t_2 == (Py_ssize_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 94, __pyx_L1_error) - __pyx_t_1 = __Pyx_PyList_PopIndex(__pyx_v_self->_items, __pyx_v_index, __pyx_t_2, 1, Py_ssize_t, PyInt_FromSsize_t); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 94, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_r = __pyx_t_1; - __pyx_t_1 = 0; - goto __pyx_L0; - - /* "aiohttp/_frozenlist.pyx":92 - * self._items.reverse() - * - * def pop(self, index=-1): # <<<<<<<<<<<<<< - * self._check_frozen() - * return self._items.pop(index) - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_AddTraceback("aiohttp._frozenlist.FrozenList.pop", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "aiohttp/_frozenlist.pyx":96 - * return self._items.pop(index) - * - * def append(self, item): # <<<<<<<<<<<<<< - * self._check_frozen() - * return self._items.append(item) - */ - -/* Python wrapper */ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_37append(PyObject *__pyx_v_self, PyObject *__pyx_v_item); /*proto*/ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_37append(PyObject *__pyx_v_self, PyObject *__pyx_v_item) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("append (wrapper)", 0); - __pyx_r = __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_36append(((struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self), ((PyObject *)__pyx_v_item)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_36append(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v_item) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - int __pyx_t_2; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("append", 0); - - /* "aiohttp/_frozenlist.pyx":97 - * - * def append(self, item): - * self._check_frozen() # <<<<<<<<<<<<<< - * return self._items.append(item) - * - */ - __pyx_t_1 = ((struct __pyx_vtabstruct_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self->__pyx_vtab)->_check_frozen(__pyx_v_self); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 97, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - - /* "aiohttp/_frozenlist.pyx":98 - * def append(self, item): - * self._check_frozen() - * return self._items.append(item) # <<<<<<<<<<<<<< - * - * def count(self, item): - */ - __Pyx_XDECREF(__pyx_r); - if (unlikely(__pyx_v_self->_items == Py_None)) { - PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "append"); - __PYX_ERR(0, 98, __pyx_L1_error) - } - __pyx_t_2 = __Pyx_PyList_Append(__pyx_v_self->_items, __pyx_v_item); if (unlikely(__pyx_t_2 == ((int)-1))) __PYX_ERR(0, 98, __pyx_L1_error) - __pyx_t_1 = __Pyx_Owned_Py_None(__pyx_t_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 98, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_r = __pyx_t_1; - __pyx_t_1 = 0; - goto __pyx_L0; - - /* "aiohttp/_frozenlist.pyx":96 - * return self._items.pop(index) - * - * def append(self, item): # <<<<<<<<<<<<<< - * self._check_frozen() - * return self._items.append(item) - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_AddTraceback("aiohttp._frozenlist.FrozenList.append", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "aiohttp/_frozenlist.pyx":100 - * return self._items.append(item) - * - * def count(self, item): # <<<<<<<<<<<<<< - * return self._items.count(item) - * - */ - -/* Python wrapper */ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_39count(PyObject *__pyx_v_self, PyObject *__pyx_v_item); /*proto*/ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_39count(PyObject *__pyx_v_self, PyObject *__pyx_v_item) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("count (wrapper)", 0); - __pyx_r = __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_38count(((struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self), ((PyObject *)__pyx_v_item)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_38count(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v_item) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - PyObject *__pyx_t_2 = NULL; - PyObject *__pyx_t_3 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("count", 0); - - /* "aiohttp/_frozenlist.pyx":101 - * - * def count(self, item): - * return self._items.count(item) # <<<<<<<<<<<<<< - * - * def __repr__(self): - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_self->_items, __pyx_n_s_count); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 101, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = NULL; - if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) { - __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2); - if (likely(__pyx_t_3)) { - PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2); - __Pyx_INCREF(__pyx_t_3); - __Pyx_INCREF(function); - __Pyx_DECREF_SET(__pyx_t_2, function); - } - } - __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_3, __pyx_v_item) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_v_item); - __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; - if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 101, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_r = __pyx_t_1; - __pyx_t_1 = 0; - goto __pyx_L0; - - /* "aiohttp/_frozenlist.pyx":100 - * return self._items.append(item) - * - * def count(self, item): # <<<<<<<<<<<<<< - * return self._items.count(item) - * - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_XDECREF(__pyx_t_2); - __Pyx_XDECREF(__pyx_t_3); - __Pyx_AddTraceback("aiohttp._frozenlist.FrozenList.count", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "aiohttp/_frozenlist.pyx":103 - * return self._items.count(item) - * - * def __repr__(self): # <<<<<<<<<<<<<< - * return ''.format(self.frozen, - * self._items) - */ - -/* Python wrapper */ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_41__repr__(PyObject *__pyx_v_self); /*proto*/ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_41__repr__(PyObject *__pyx_v_self) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__repr__ (wrapper)", 0); - __pyx_r = __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_40__repr__(((struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_40__repr__(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - PyObject *__pyx_t_2 = NULL; - PyObject *__pyx_t_3 = NULL; - PyObject *__pyx_t_4 = NULL; - int __pyx_t_5; - PyObject *__pyx_t_6 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("__repr__", 0); - - /* "aiohttp/_frozenlist.pyx":104 - * - * def __repr__(self): - * return ''.format(self.frozen, # <<<<<<<<<<<<<< - * self._items) - * - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_kp_u_FrozenList_frozen_r, __pyx_n_s_format); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 104, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = __Pyx_PyBool_FromLong(__pyx_v_self->frozen); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 104, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - - /* "aiohttp/_frozenlist.pyx":105 - * def __repr__(self): - * return ''.format(self.frozen, - * self._items) # <<<<<<<<<<<<<< - * - * - */ - __pyx_t_4 = NULL; - __pyx_t_5 = 0; - if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) { - __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_2); - if (likely(__pyx_t_4)) { - PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2); - __Pyx_INCREF(__pyx_t_4); - __Pyx_INCREF(function); - __Pyx_DECREF_SET(__pyx_t_2, function); - __pyx_t_5 = 1; - } - } - #if CYTHON_FAST_PYCALL - if (PyFunction_Check(__pyx_t_2)) { - PyObject *__pyx_temp[3] = {__pyx_t_4, __pyx_t_3, __pyx_v_self->_items}; - __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_2, __pyx_temp+1-__pyx_t_5, 2+__pyx_t_5); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 104, __pyx_L1_error) - __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - } else - #endif - #if CYTHON_FAST_PYCCALL - if (__Pyx_PyFastCFunction_Check(__pyx_t_2)) { - PyObject *__pyx_temp[3] = {__pyx_t_4, __pyx_t_3, __pyx_v_self->_items}; - __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_2, __pyx_temp+1-__pyx_t_5, 2+__pyx_t_5); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 104, __pyx_L1_error) - __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - } else - #endif - { - __pyx_t_6 = PyTuple_New(2+__pyx_t_5); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 104, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_6); - if (__pyx_t_4) { - __Pyx_GIVEREF(__pyx_t_4); PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_t_4); __pyx_t_4 = NULL; - } - __Pyx_GIVEREF(__pyx_t_3); - PyTuple_SET_ITEM(__pyx_t_6, 0+__pyx_t_5, __pyx_t_3); - __Pyx_INCREF(__pyx_v_self->_items); - __Pyx_GIVEREF(__pyx_v_self->_items); - PyTuple_SET_ITEM(__pyx_t_6, 1+__pyx_t_5, __pyx_v_self->_items); - __pyx_t_3 = 0; - __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_6, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 104, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; - } - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_r = __pyx_t_1; - __pyx_t_1 = 0; - goto __pyx_L0; - - /* "aiohttp/_frozenlist.pyx":103 - * return self._items.count(item) - * - * def __repr__(self): # <<<<<<<<<<<<<< - * return ''.format(self.frozen, - * self._items) - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_XDECREF(__pyx_t_2); - __Pyx_XDECREF(__pyx_t_3); - __Pyx_XDECREF(__pyx_t_4); - __Pyx_XDECREF(__pyx_t_6); - __Pyx_AddTraceback("aiohttp._frozenlist.FrozenList.__repr__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "aiohttp/_frozenlist.pyx":6 - * cdef class FrozenList: - * - * cdef readonly bint frozen # <<<<<<<<<<<<<< - * cdef list _items - * - */ - -/* Python wrapper */ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_6frozen_1__get__(PyObject *__pyx_v_self); /*proto*/ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_6frozen_1__get__(PyObject *__pyx_v_self) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); - __pyx_r = __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_6frozen___get__(((struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_6frozen___get__(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("__get__", 0); - __Pyx_XDECREF(__pyx_r); - __pyx_t_1 = __Pyx_PyBool_FromLong(__pyx_v_self->frozen); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 6, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_r = __pyx_t_1; - __pyx_t_1 = 0; - goto __pyx_L0; - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_AddTraceback("aiohttp._frozenlist.FrozenList.frozen.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "(tree fragment)":1 - * def __reduce_cython__(self): # <<<<<<<<<<<<<< - * cdef tuple state - * cdef object _dict - */ - -/* Python wrapper */ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_43__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_43__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__reduce_cython__ (wrapper)", 0); - __pyx_r = __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_42__reduce_cython__(((struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_42__reduce_cython__(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self) { - PyObject *__pyx_v_state = 0; - PyObject *__pyx_v__dict = 0; - int __pyx_v_use_setstate; - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - PyObject *__pyx_t_2 = NULL; - int __pyx_t_3; - int __pyx_t_4; - PyObject *__pyx_t_5 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("__reduce_cython__", 0); - - /* "(tree fragment)":5 - * cdef object _dict - * cdef bint use_setstate - * state = (self._items, self.frozen) # <<<<<<<<<<<<<< - * _dict = getattr(self, '__dict__', None) - * if _dict is not None: - */ - __pyx_t_1 = __Pyx_PyBool_FromLong(__pyx_v_self->frozen); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 5, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 5, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __Pyx_INCREF(__pyx_v_self->_items); - __Pyx_GIVEREF(__pyx_v_self->_items); - PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_v_self->_items); - __Pyx_GIVEREF(__pyx_t_1); - PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_t_1); - __pyx_t_1 = 0; - __pyx_v_state = ((PyObject*)__pyx_t_2); - __pyx_t_2 = 0; - - /* "(tree fragment)":6 - * cdef bint use_setstate - * state = (self._items, self.frozen) - * _dict = getattr(self, '__dict__', None) # <<<<<<<<<<<<<< - * if _dict is not None: - * state += (_dict,) - */ - __pyx_t_2 = __Pyx_GetAttr3(((PyObject *)__pyx_v_self), __pyx_n_s_dict, Py_None); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 6, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __pyx_v__dict = __pyx_t_2; - __pyx_t_2 = 0; - - /* "(tree fragment)":7 - * state = (self._items, self.frozen) - * _dict = getattr(self, '__dict__', None) - * if _dict is not None: # <<<<<<<<<<<<<< - * state += (_dict,) - * use_setstate = True - */ - __pyx_t_3 = (__pyx_v__dict != Py_None); - __pyx_t_4 = (__pyx_t_3 != 0); - if (__pyx_t_4) { - - /* "(tree fragment)":8 - * _dict = getattr(self, '__dict__', None) - * if _dict is not None: - * state += (_dict,) # <<<<<<<<<<<<<< - * use_setstate = True - * else: - */ - __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 8, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __Pyx_INCREF(__pyx_v__dict); - __Pyx_GIVEREF(__pyx_v__dict); - PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_v__dict); - __pyx_t_1 = PyNumber_InPlaceAdd(__pyx_v_state, __pyx_t_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 8, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __Pyx_DECREF_SET(__pyx_v_state, ((PyObject*)__pyx_t_1)); - __pyx_t_1 = 0; - - /* "(tree fragment)":9 - * if _dict is not None: - * state += (_dict,) - * use_setstate = True # <<<<<<<<<<<<<< - * else: - * use_setstate = self._items is not None - */ - __pyx_v_use_setstate = 1; - - /* "(tree fragment)":7 - * state = (self._items, self.frozen) - * _dict = getattr(self, '__dict__', None) - * if _dict is not None: # <<<<<<<<<<<<<< - * state += (_dict,) - * use_setstate = True - */ - goto __pyx_L3; - } - - /* "(tree fragment)":11 - * use_setstate = True - * else: - * use_setstate = self._items is not None # <<<<<<<<<<<<<< - * if use_setstate: - * return __pyx_unpickle_FrozenList, (type(self), 0x949a143, None), state - */ - /*else*/ { - __pyx_t_4 = (__pyx_v_self->_items != ((PyObject*)Py_None)); - __pyx_v_use_setstate = __pyx_t_4; - } - __pyx_L3:; - - /* "(tree fragment)":12 - * else: - * use_setstate = self._items is not None - * if use_setstate: # <<<<<<<<<<<<<< - * return __pyx_unpickle_FrozenList, (type(self), 0x949a143, None), state - * else: - */ - __pyx_t_4 = (__pyx_v_use_setstate != 0); - if (__pyx_t_4) { - - /* "(tree fragment)":13 - * use_setstate = self._items is not None - * if use_setstate: - * return __pyx_unpickle_FrozenList, (type(self), 0x949a143, None), state # <<<<<<<<<<<<<< - * else: - * return __pyx_unpickle_FrozenList, (type(self), 0x949a143, state) - */ - __Pyx_XDECREF(__pyx_r); - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_pyx_unpickle_FrozenList); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 13, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_2 = PyTuple_New(3); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 13, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __Pyx_INCREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); - __Pyx_GIVEREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); - PyTuple_SET_ITEM(__pyx_t_2, 0, ((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); - __Pyx_INCREF(__pyx_int_155820355); - __Pyx_GIVEREF(__pyx_int_155820355); - PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_int_155820355); - __Pyx_INCREF(Py_None); - __Pyx_GIVEREF(Py_None); - PyTuple_SET_ITEM(__pyx_t_2, 2, Py_None); - __pyx_t_5 = PyTuple_New(3); if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 13, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_5); - __Pyx_GIVEREF(__pyx_t_1); - PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_1); - __Pyx_GIVEREF(__pyx_t_2); - PyTuple_SET_ITEM(__pyx_t_5, 1, __pyx_t_2); - __Pyx_INCREF(__pyx_v_state); - __Pyx_GIVEREF(__pyx_v_state); - PyTuple_SET_ITEM(__pyx_t_5, 2, __pyx_v_state); - __pyx_t_1 = 0; - __pyx_t_2 = 0; - __pyx_r = __pyx_t_5; - __pyx_t_5 = 0; - goto __pyx_L0; - - /* "(tree fragment)":12 - * else: - * use_setstate = self._items is not None - * if use_setstate: # <<<<<<<<<<<<<< - * return __pyx_unpickle_FrozenList, (type(self), 0x949a143, None), state - * else: - */ - } - - /* "(tree fragment)":15 - * return __pyx_unpickle_FrozenList, (type(self), 0x949a143, None), state - * else: - * return __pyx_unpickle_FrozenList, (type(self), 0x949a143, state) # <<<<<<<<<<<<<< - * def __setstate_cython__(self, __pyx_state): - * __pyx_unpickle_FrozenList__set_state(self, __pyx_state) - */ - /*else*/ { - __Pyx_XDECREF(__pyx_r); - __Pyx_GetModuleGlobalName(__pyx_t_5, __pyx_n_s_pyx_unpickle_FrozenList); if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 15, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_5); - __pyx_t_2 = PyTuple_New(3); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 15, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __Pyx_INCREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); - __Pyx_GIVEREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); - PyTuple_SET_ITEM(__pyx_t_2, 0, ((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); - __Pyx_INCREF(__pyx_int_155820355); - __Pyx_GIVEREF(__pyx_int_155820355); - PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_int_155820355); - __Pyx_INCREF(__pyx_v_state); - __Pyx_GIVEREF(__pyx_v_state); - PyTuple_SET_ITEM(__pyx_t_2, 2, __pyx_v_state); - __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 15, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_GIVEREF(__pyx_t_5); - PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_5); - __Pyx_GIVEREF(__pyx_t_2); - PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_t_2); - __pyx_t_5 = 0; - __pyx_t_2 = 0; - __pyx_r = __pyx_t_1; - __pyx_t_1 = 0; - goto __pyx_L0; - } - - /* "(tree fragment)":1 - * def __reduce_cython__(self): # <<<<<<<<<<<<<< - * cdef tuple state - * cdef object _dict - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_XDECREF(__pyx_t_2); - __Pyx_XDECREF(__pyx_t_5); - __Pyx_AddTraceback("aiohttp._frozenlist.FrozenList.__reduce_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XDECREF(__pyx_v_state); - __Pyx_XDECREF(__pyx_v__dict); - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "(tree fragment)":16 - * else: - * return __pyx_unpickle_FrozenList, (type(self), 0x949a143, state) - * def __setstate_cython__(self, __pyx_state): # <<<<<<<<<<<<<< - * __pyx_unpickle_FrozenList__set_state(self, __pyx_state) - */ - -/* Python wrapper */ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_45__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state); /*proto*/ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_45__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__setstate_cython__ (wrapper)", 0); - __pyx_r = __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_44__setstate_cython__(((struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self), ((PyObject *)__pyx_v___pyx_state)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_44__setstate_cython__(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v___pyx_state) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("__setstate_cython__", 0); - - /* "(tree fragment)":17 - * return __pyx_unpickle_FrozenList, (type(self), 0x949a143, state) - * def __setstate_cython__(self, __pyx_state): - * __pyx_unpickle_FrozenList__set_state(self, __pyx_state) # <<<<<<<<<<<<<< - */ - if (!(likely(PyTuple_CheckExact(__pyx_v___pyx_state))||((__pyx_v___pyx_state) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_v___pyx_state)->tp_name), 0))) __PYX_ERR(1, 17, __pyx_L1_error) - __pyx_t_1 = __pyx_f_7aiohttp_11_frozenlist___pyx_unpickle_FrozenList__set_state(__pyx_v_self, ((PyObject*)__pyx_v___pyx_state)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 17, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - - /* "(tree fragment)":16 - * else: - * return __pyx_unpickle_FrozenList, (type(self), 0x949a143, state) - * def __setstate_cython__(self, __pyx_state): # <<<<<<<<<<<<<< - * __pyx_unpickle_FrozenList__set_state(self, __pyx_state) - */ - - /* function exit code */ - __pyx_r = Py_None; __Pyx_INCREF(Py_None); - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_AddTraceback("aiohttp._frozenlist.FrozenList.__setstate_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "(tree fragment)":1 - * def __pyx_unpickle_FrozenList(__pyx_type, long __pyx_checksum, __pyx_state): # <<<<<<<<<<<<<< - * cdef object __pyx_PickleError - * cdef object __pyx_result - */ - -/* Python wrapper */ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_1__pyx_unpickle_FrozenList(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ -static PyMethodDef __pyx_mdef_7aiohttp_11_frozenlist_1__pyx_unpickle_FrozenList = {"__pyx_unpickle_FrozenList", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_7aiohttp_11_frozenlist_1__pyx_unpickle_FrozenList, METH_VARARGS|METH_KEYWORDS, 0}; -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_1__pyx_unpickle_FrozenList(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { - PyObject *__pyx_v___pyx_type = 0; - long __pyx_v___pyx_checksum; - PyObject *__pyx_v___pyx_state = 0; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__pyx_unpickle_FrozenList (wrapper)", 0); - { - static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_pyx_type,&__pyx_n_s_pyx_checksum,&__pyx_n_s_pyx_state,0}; - PyObject* values[3] = {0,0,0}; - if (unlikely(__pyx_kwds)) { - Py_ssize_t kw_args; - const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); - switch (pos_args) { - case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); - CYTHON_FALLTHROUGH; - case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); - CYTHON_FALLTHROUGH; - case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); - CYTHON_FALLTHROUGH; - case 0: break; - default: goto __pyx_L5_argtuple_error; - } - kw_args = PyDict_Size(__pyx_kwds); - switch (pos_args) { - case 0: - if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_pyx_type)) != 0)) kw_args--; - else goto __pyx_L5_argtuple_error; - CYTHON_FALLTHROUGH; - case 1: - if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_pyx_checksum)) != 0)) kw_args--; - else { - __Pyx_RaiseArgtupleInvalid("__pyx_unpickle_FrozenList", 1, 3, 3, 1); __PYX_ERR(1, 1, __pyx_L3_error) - } - CYTHON_FALLTHROUGH; - case 2: - if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_pyx_state)) != 0)) kw_args--; - else { - __Pyx_RaiseArgtupleInvalid("__pyx_unpickle_FrozenList", 1, 3, 3, 2); __PYX_ERR(1, 1, __pyx_L3_error) - } - } - if (unlikely(kw_args > 0)) { - if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__pyx_unpickle_FrozenList") < 0)) __PYX_ERR(1, 1, __pyx_L3_error) - } - } else if (PyTuple_GET_SIZE(__pyx_args) != 3) { - goto __pyx_L5_argtuple_error; - } else { - values[0] = PyTuple_GET_ITEM(__pyx_args, 0); - values[1] = PyTuple_GET_ITEM(__pyx_args, 1); - values[2] = PyTuple_GET_ITEM(__pyx_args, 2); - } - __pyx_v___pyx_type = values[0]; - __pyx_v___pyx_checksum = __Pyx_PyInt_As_long(values[1]); if (unlikely((__pyx_v___pyx_checksum == (long)-1) && PyErr_Occurred())) __PYX_ERR(1, 1, __pyx_L3_error) - __pyx_v___pyx_state = values[2]; - } - goto __pyx_L4_argument_unpacking_done; - __pyx_L5_argtuple_error:; - __Pyx_RaiseArgtupleInvalid("__pyx_unpickle_FrozenList", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(1, 1, __pyx_L3_error) - __pyx_L3_error:; - __Pyx_AddTraceback("aiohttp._frozenlist.__pyx_unpickle_FrozenList", __pyx_clineno, __pyx_lineno, __pyx_filename); - __Pyx_RefNannyFinishContext(); - return NULL; - __pyx_L4_argument_unpacking_done:; - __pyx_r = __pyx_pf_7aiohttp_11_frozenlist___pyx_unpickle_FrozenList(__pyx_self, __pyx_v___pyx_type, __pyx_v___pyx_checksum, __pyx_v___pyx_state); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf_7aiohttp_11_frozenlist___pyx_unpickle_FrozenList(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v___pyx_type, long __pyx_v___pyx_checksum, PyObject *__pyx_v___pyx_state) { - PyObject *__pyx_v___pyx_PickleError = 0; - PyObject *__pyx_v___pyx_result = 0; - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - int __pyx_t_1; - PyObject *__pyx_t_2 = NULL; - PyObject *__pyx_t_3 = NULL; - PyObject *__pyx_t_4 = NULL; - PyObject *__pyx_t_5 = NULL; - int __pyx_t_6; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("__pyx_unpickle_FrozenList", 0); - - /* "(tree fragment)":4 - * cdef object __pyx_PickleError - * cdef object __pyx_result - * if __pyx_checksum != 0x949a143: # <<<<<<<<<<<<<< - * from pickle import PickleError as __pyx_PickleError - * raise __pyx_PickleError("Incompatible checksums (%s vs 0x949a143 = (_items, frozen))" % __pyx_checksum) - */ - __pyx_t_1 = ((__pyx_v___pyx_checksum != 0x949a143) != 0); - if (__pyx_t_1) { - - /* "(tree fragment)":5 - * cdef object __pyx_result - * if __pyx_checksum != 0x949a143: - * from pickle import PickleError as __pyx_PickleError # <<<<<<<<<<<<<< - * raise __pyx_PickleError("Incompatible checksums (%s vs 0x949a143 = (_items, frozen))" % __pyx_checksum) - * __pyx_result = FrozenList.__new__(__pyx_type) - */ - __pyx_t_2 = PyList_New(1); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 5, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __Pyx_INCREF(__pyx_n_s_PickleError); - __Pyx_GIVEREF(__pyx_n_s_PickleError); - PyList_SET_ITEM(__pyx_t_2, 0, __pyx_n_s_PickleError); - __pyx_t_3 = __Pyx_Import(__pyx_n_s_pickle, __pyx_t_2, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 5, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_2 = __Pyx_ImportFrom(__pyx_t_3, __pyx_n_s_PickleError); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 5, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __Pyx_INCREF(__pyx_t_2); - __pyx_v___pyx_PickleError = __pyx_t_2; - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - - /* "(tree fragment)":6 - * if __pyx_checksum != 0x949a143: - * from pickle import PickleError as __pyx_PickleError - * raise __pyx_PickleError("Incompatible checksums (%s vs 0x949a143 = (_items, frozen))" % __pyx_checksum) # <<<<<<<<<<<<<< - * __pyx_result = FrozenList.__new__(__pyx_type) - * if __pyx_state is not None: - */ - __pyx_t_2 = __Pyx_PyInt_From_long(__pyx_v___pyx_checksum); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 6, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_4 = __Pyx_PyString_Format(__pyx_kp_s_Incompatible_checksums_s_vs_0x94, __pyx_t_2); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 6, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __Pyx_INCREF(__pyx_v___pyx_PickleError); - __pyx_t_2 = __pyx_v___pyx_PickleError; __pyx_t_5 = NULL; - if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) { - __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_2); - if (likely(__pyx_t_5)) { - PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2); - __Pyx_INCREF(__pyx_t_5); - __Pyx_INCREF(function); - __Pyx_DECREF_SET(__pyx_t_2, function); - } - } - __pyx_t_3 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_5, __pyx_t_4) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_4); - __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 6, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __Pyx_Raise(__pyx_t_3, 0, 0, 0); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __PYX_ERR(1, 6, __pyx_L1_error) - - /* "(tree fragment)":4 - * cdef object __pyx_PickleError - * cdef object __pyx_result - * if __pyx_checksum != 0x949a143: # <<<<<<<<<<<<<< - * from pickle import PickleError as __pyx_PickleError - * raise __pyx_PickleError("Incompatible checksums (%s vs 0x949a143 = (_items, frozen))" % __pyx_checksum) - */ - } - - /* "(tree fragment)":7 - * from pickle import PickleError as __pyx_PickleError - * raise __pyx_PickleError("Incompatible checksums (%s vs 0x949a143 = (_items, frozen))" % __pyx_checksum) - * __pyx_result = FrozenList.__new__(__pyx_type) # <<<<<<<<<<<<<< - * if __pyx_state is not None: - * __pyx_unpickle_FrozenList__set_state( __pyx_result, __pyx_state) - */ - __pyx_t_2 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_ptype_7aiohttp_11_frozenlist_FrozenList), __pyx_n_s_new); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 7, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_4 = NULL; - if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) { - __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_2); - if (likely(__pyx_t_4)) { - PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2); - __Pyx_INCREF(__pyx_t_4); - __Pyx_INCREF(function); - __Pyx_DECREF_SET(__pyx_t_2, function); - } - } - __pyx_t_3 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_4, __pyx_v___pyx_type) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_v___pyx_type); - __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; - if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 7, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_v___pyx_result = __pyx_t_3; - __pyx_t_3 = 0; - - /* "(tree fragment)":8 - * raise __pyx_PickleError("Incompatible checksums (%s vs 0x949a143 = (_items, frozen))" % __pyx_checksum) - * __pyx_result = FrozenList.__new__(__pyx_type) - * if __pyx_state is not None: # <<<<<<<<<<<<<< - * __pyx_unpickle_FrozenList__set_state( __pyx_result, __pyx_state) - * return __pyx_result - */ - __pyx_t_1 = (__pyx_v___pyx_state != Py_None); - __pyx_t_6 = (__pyx_t_1 != 0); - if (__pyx_t_6) { - - /* "(tree fragment)":9 - * __pyx_result = FrozenList.__new__(__pyx_type) - * if __pyx_state is not None: - * __pyx_unpickle_FrozenList__set_state( __pyx_result, __pyx_state) # <<<<<<<<<<<<<< - * return __pyx_result - * cdef __pyx_unpickle_FrozenList__set_state(FrozenList __pyx_result, tuple __pyx_state): - */ - if (!(likely(PyTuple_CheckExact(__pyx_v___pyx_state))||((__pyx_v___pyx_state) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_v___pyx_state)->tp_name), 0))) __PYX_ERR(1, 9, __pyx_L1_error) - __pyx_t_3 = __pyx_f_7aiohttp_11_frozenlist___pyx_unpickle_FrozenList__set_state(((struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *)__pyx_v___pyx_result), ((PyObject*)__pyx_v___pyx_state)); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 9, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - - /* "(tree fragment)":8 - * raise __pyx_PickleError("Incompatible checksums (%s vs 0x949a143 = (_items, frozen))" % __pyx_checksum) - * __pyx_result = FrozenList.__new__(__pyx_type) - * if __pyx_state is not None: # <<<<<<<<<<<<<< - * __pyx_unpickle_FrozenList__set_state( __pyx_result, __pyx_state) - * return __pyx_result - */ - } - - /* "(tree fragment)":10 - * if __pyx_state is not None: - * __pyx_unpickle_FrozenList__set_state( __pyx_result, __pyx_state) - * return __pyx_result # <<<<<<<<<<<<<< - * cdef __pyx_unpickle_FrozenList__set_state(FrozenList __pyx_result, tuple __pyx_state): - * __pyx_result._items = __pyx_state[0]; __pyx_result.frozen = __pyx_state[1] - */ - __Pyx_XDECREF(__pyx_r); - __Pyx_INCREF(__pyx_v___pyx_result); - __pyx_r = __pyx_v___pyx_result; - goto __pyx_L0; - - /* "(tree fragment)":1 - * def __pyx_unpickle_FrozenList(__pyx_type, long __pyx_checksum, __pyx_state): # <<<<<<<<<<<<<< - * cdef object __pyx_PickleError - * cdef object __pyx_result - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_2); - __Pyx_XDECREF(__pyx_t_3); - __Pyx_XDECREF(__pyx_t_4); - __Pyx_XDECREF(__pyx_t_5); - __Pyx_AddTraceback("aiohttp._frozenlist.__pyx_unpickle_FrozenList", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XDECREF(__pyx_v___pyx_PickleError); - __Pyx_XDECREF(__pyx_v___pyx_result); - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "(tree fragment)":11 - * __pyx_unpickle_FrozenList__set_state( __pyx_result, __pyx_state) - * return __pyx_result - * cdef __pyx_unpickle_FrozenList__set_state(FrozenList __pyx_result, tuple __pyx_state): # <<<<<<<<<<<<<< - * __pyx_result._items = __pyx_state[0]; __pyx_result.frozen = __pyx_state[1] - * if len(__pyx_state) > 2 and hasattr(__pyx_result, '__dict__'): - */ - -static PyObject *__pyx_f_7aiohttp_11_frozenlist___pyx_unpickle_FrozenList__set_state(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v___pyx_result, PyObject *__pyx_v___pyx_state) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - int __pyx_t_2; - Py_ssize_t __pyx_t_3; - int __pyx_t_4; - int __pyx_t_5; - PyObject *__pyx_t_6 = NULL; - PyObject *__pyx_t_7 = NULL; - PyObject *__pyx_t_8 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("__pyx_unpickle_FrozenList__set_state", 0); - - /* "(tree fragment)":12 - * return __pyx_result - * cdef __pyx_unpickle_FrozenList__set_state(FrozenList __pyx_result, tuple __pyx_state): - * __pyx_result._items = __pyx_state[0]; __pyx_result.frozen = __pyx_state[1] # <<<<<<<<<<<<<< - * if len(__pyx_state) > 2 and hasattr(__pyx_result, '__dict__'): - * __pyx_result.__dict__.update(__pyx_state[2]) - */ - if (unlikely(__pyx_v___pyx_state == Py_None)) { - PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); - __PYX_ERR(1, 12, __pyx_L1_error) - } - __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 12, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - if (!(likely(PyList_CheckExact(__pyx_t_1))||((__pyx_t_1) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "list", Py_TYPE(__pyx_t_1)->tp_name), 0))) __PYX_ERR(1, 12, __pyx_L1_error) - __Pyx_GIVEREF(__pyx_t_1); - __Pyx_GOTREF(__pyx_v___pyx_result->_items); - __Pyx_DECREF(__pyx_v___pyx_result->_items); - __pyx_v___pyx_result->_items = ((PyObject*)__pyx_t_1); - __pyx_t_1 = 0; - if (unlikely(__pyx_v___pyx_state == Py_None)) { - PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); - __PYX_ERR(1, 12, __pyx_L1_error) - } - __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 1, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 12, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely((__pyx_t_2 == (int)-1) && PyErr_Occurred())) __PYX_ERR(1, 12, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __pyx_v___pyx_result->frozen = __pyx_t_2; - - /* "(tree fragment)":13 - * cdef __pyx_unpickle_FrozenList__set_state(FrozenList __pyx_result, tuple __pyx_state): - * __pyx_result._items = __pyx_state[0]; __pyx_result.frozen = __pyx_state[1] - * if len(__pyx_state) > 2 and hasattr(__pyx_result, '__dict__'): # <<<<<<<<<<<<<< - * __pyx_result.__dict__.update(__pyx_state[2]) - */ - if (unlikely(__pyx_v___pyx_state == Py_None)) { - PyErr_SetString(PyExc_TypeError, "object of type 'NoneType' has no len()"); - __PYX_ERR(1, 13, __pyx_L1_error) - } - __pyx_t_3 = PyTuple_GET_SIZE(__pyx_v___pyx_state); if (unlikely(__pyx_t_3 == ((Py_ssize_t)-1))) __PYX_ERR(1, 13, __pyx_L1_error) - __pyx_t_4 = ((__pyx_t_3 > 2) != 0); - if (__pyx_t_4) { - } else { - __pyx_t_2 = __pyx_t_4; - goto __pyx_L4_bool_binop_done; - } - __pyx_t_4 = __Pyx_HasAttr(((PyObject *)__pyx_v___pyx_result), __pyx_n_s_dict); if (unlikely(__pyx_t_4 == ((int)-1))) __PYX_ERR(1, 13, __pyx_L1_error) - __pyx_t_5 = (__pyx_t_4 != 0); - __pyx_t_2 = __pyx_t_5; - __pyx_L4_bool_binop_done:; - if (__pyx_t_2) { - - /* "(tree fragment)":14 - * __pyx_result._items = __pyx_state[0]; __pyx_result.frozen = __pyx_state[1] - * if len(__pyx_state) > 2 and hasattr(__pyx_result, '__dict__'): - * __pyx_result.__dict__.update(__pyx_state[2]) # <<<<<<<<<<<<<< - */ - __pyx_t_6 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v___pyx_result), __pyx_n_s_dict); if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 14, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_6); - __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_6, __pyx_n_s_update); if (unlikely(!__pyx_t_7)) __PYX_ERR(1, 14, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_7); - __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; - if (unlikely(__pyx_v___pyx_state == Py_None)) { - PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); - __PYX_ERR(1, 14, __pyx_L1_error) - } - __pyx_t_6 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 2, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 14, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_6); - __pyx_t_8 = NULL; - if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_7))) { - __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_7); - if (likely(__pyx_t_8)) { - PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_7); - __Pyx_INCREF(__pyx_t_8); - __Pyx_INCREF(function); - __Pyx_DECREF_SET(__pyx_t_7, function); - } - } - __pyx_t_1 = (__pyx_t_8) ? __Pyx_PyObject_Call2Args(__pyx_t_7, __pyx_t_8, __pyx_t_6) : __Pyx_PyObject_CallOneArg(__pyx_t_7, __pyx_t_6); - __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; - __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; - if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 14, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - - /* "(tree fragment)":13 - * cdef __pyx_unpickle_FrozenList__set_state(FrozenList __pyx_result, tuple __pyx_state): - * __pyx_result._items = __pyx_state[0]; __pyx_result.frozen = __pyx_state[1] - * if len(__pyx_state) > 2 and hasattr(__pyx_result, '__dict__'): # <<<<<<<<<<<<<< - * __pyx_result.__dict__.update(__pyx_state[2]) - */ - } - - /* "(tree fragment)":11 - * __pyx_unpickle_FrozenList__set_state( __pyx_result, __pyx_state) - * return __pyx_result - * cdef __pyx_unpickle_FrozenList__set_state(FrozenList __pyx_result, tuple __pyx_state): # <<<<<<<<<<<<<< - * __pyx_result._items = __pyx_state[0]; __pyx_result.frozen = __pyx_state[1] - * if len(__pyx_state) > 2 and hasattr(__pyx_result, '__dict__'): - */ - - /* function exit code */ - __pyx_r = Py_None; __Pyx_INCREF(Py_None); - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_XDECREF(__pyx_t_6); - __Pyx_XDECREF(__pyx_t_7); - __Pyx_XDECREF(__pyx_t_8); - __Pyx_AddTraceback("aiohttp._frozenlist.__pyx_unpickle_FrozenList__set_state", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = 0; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} -static struct __pyx_vtabstruct_7aiohttp_11_frozenlist_FrozenList __pyx_vtable_7aiohttp_11_frozenlist_FrozenList; - -static PyObject *__pyx_tp_new_7aiohttp_11_frozenlist_FrozenList(PyTypeObject *t, CYTHON_UNUSED PyObject *a, CYTHON_UNUSED PyObject *k) { - struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *p; - PyObject *o; - if (likely((t->tp_flags & Py_TPFLAGS_IS_ABSTRACT) == 0)) { - o = (*t->tp_alloc)(t, 0); - } else { - o = (PyObject *) PyBaseObject_Type.tp_new(t, __pyx_empty_tuple, 0); - } - if (unlikely(!o)) return 0; - p = ((struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *)o); - p->__pyx_vtab = __pyx_vtabptr_7aiohttp_11_frozenlist_FrozenList; - p->_items = ((PyObject*)Py_None); Py_INCREF(Py_None); - return o; -} - -static void __pyx_tp_dealloc_7aiohttp_11_frozenlist_FrozenList(PyObject *o) { - struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *p = (struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *)o; - #if CYTHON_USE_TP_FINALIZE - if (unlikely(PyType_HasFeature(Py_TYPE(o), Py_TPFLAGS_HAVE_FINALIZE) && Py_TYPE(o)->tp_finalize) && !_PyGC_FINALIZED(o)) { - if (PyObject_CallFinalizerFromDealloc(o)) return; - } - #endif - PyObject_GC_UnTrack(o); - Py_CLEAR(p->_items); - (*Py_TYPE(o)->tp_free)(o); -} - -static int __pyx_tp_traverse_7aiohttp_11_frozenlist_FrozenList(PyObject *o, visitproc v, void *a) { - int e; - struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *p = (struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *)o; - if (p->_items) { - e = (*v)(p->_items, a); if (e) return e; - } - return 0; -} - -static int __pyx_tp_clear_7aiohttp_11_frozenlist_FrozenList(PyObject *o) { - PyObject* tmp; - struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *p = (struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *)o; - tmp = ((PyObject*)p->_items); - p->_items = ((PyObject*)Py_None); Py_INCREF(Py_None); - Py_XDECREF(tmp); - return 0; -} -static PyObject *__pyx_sq_item_7aiohttp_11_frozenlist_FrozenList(PyObject *o, Py_ssize_t i) { - PyObject *r; - PyObject *x = PyInt_FromSsize_t(i); if(!x) return 0; - r = Py_TYPE(o)->tp_as_mapping->mp_subscript(o, x); - Py_DECREF(x); - return r; -} - -static int __pyx_mp_ass_subscript_7aiohttp_11_frozenlist_FrozenList(PyObject *o, PyObject *i, PyObject *v) { - if (v) { - return __pyx_pw_7aiohttp_11_frozenlist_10FrozenList_7__setitem__(o, i, v); - } - else { - return __pyx_pw_7aiohttp_11_frozenlist_10FrozenList_9__delitem__(o, i); - } -} - -static PyObject *__pyx_getprop_7aiohttp_11_frozenlist_10FrozenList_frozen(PyObject *o, CYTHON_UNUSED void *x) { - return __pyx_pw_7aiohttp_11_frozenlist_10FrozenList_6frozen_1__get__(o); -} - -static PyMethodDef __pyx_methods_7aiohttp_11_frozenlist_FrozenList[] = { - {"freeze", (PyCFunction)__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_3freeze, METH_NOARGS, 0}, - {"__reversed__", (PyCFunction)__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_15__reversed__, METH_NOARGS, 0}, - {"insert", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_19insert, METH_VARARGS|METH_KEYWORDS, 0}, - {"index", (PyCFunction)__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_25index, METH_O, 0}, - {"remove", (PyCFunction)__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_27remove, METH_O, 0}, - {"clear", (PyCFunction)__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_29clear, METH_NOARGS, 0}, - {"extend", (PyCFunction)__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_31extend, METH_O, 0}, - {"reverse", (PyCFunction)__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_33reverse, METH_NOARGS, 0}, - {"pop", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_35pop, METH_VARARGS|METH_KEYWORDS, 0}, - {"append", (PyCFunction)__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_37append, METH_O, 0}, - {"count", (PyCFunction)__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_39count, METH_O, 0}, - {"__reduce_cython__", (PyCFunction)__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_43__reduce_cython__, METH_NOARGS, 0}, - {"__setstate_cython__", (PyCFunction)__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_45__setstate_cython__, METH_O, 0}, - {0, 0, 0, 0} -}; - -static struct PyGetSetDef __pyx_getsets_7aiohttp_11_frozenlist_FrozenList[] = { - {(char *)"frozen", __pyx_getprop_7aiohttp_11_frozenlist_10FrozenList_frozen, 0, (char *)0, 0}, - {0, 0, 0, 0, 0} -}; - -static PyNumberMethods __pyx_tp_as_number_FrozenList = { - 0, /*nb_add*/ - 0, /*nb_subtract*/ - 0, /*nb_multiply*/ - #if PY_MAJOR_VERSION < 3 || (CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX < 0x03050000) - 0, /*nb_divide*/ - #endif - 0, /*nb_remainder*/ - 0, /*nb_divmod*/ - 0, /*nb_power*/ - 0, /*nb_negative*/ - 0, /*nb_positive*/ - 0, /*nb_absolute*/ - 0, /*nb_nonzero*/ - 0, /*nb_invert*/ - 0, /*nb_lshift*/ - 0, /*nb_rshift*/ - 0, /*nb_and*/ - 0, /*nb_xor*/ - 0, /*nb_or*/ - #if PY_MAJOR_VERSION < 3 || (CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX < 0x03050000) - 0, /*nb_coerce*/ - #endif - 0, /*nb_int*/ - #if PY_MAJOR_VERSION < 3 - 0, /*nb_long*/ - #else - 0, /*reserved*/ - #endif - 0, /*nb_float*/ - #if PY_MAJOR_VERSION < 3 || (CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX < 0x03050000) - 0, /*nb_oct*/ - #endif - #if PY_MAJOR_VERSION < 3 || (CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX < 0x03050000) - 0, /*nb_hex*/ - #endif - __pyx_pw_7aiohttp_11_frozenlist_10FrozenList_23__iadd__, /*nb_inplace_add*/ - 0, /*nb_inplace_subtract*/ - 0, /*nb_inplace_multiply*/ - #if PY_MAJOR_VERSION < 3 || (CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX < 0x03050000) - 0, /*nb_inplace_divide*/ - #endif - 0, /*nb_inplace_remainder*/ - 0, /*nb_inplace_power*/ - 0, /*nb_inplace_lshift*/ - 0, /*nb_inplace_rshift*/ - 0, /*nb_inplace_and*/ - 0, /*nb_inplace_xor*/ - 0, /*nb_inplace_or*/ - 0, /*nb_floor_divide*/ - 0, /*nb_true_divide*/ - 0, /*nb_inplace_floor_divide*/ - 0, /*nb_inplace_true_divide*/ - 0, /*nb_index*/ - #if PY_VERSION_HEX >= 0x03050000 - 0, /*nb_matrix_multiply*/ - #endif - #if PY_VERSION_HEX >= 0x03050000 - 0, /*nb_inplace_matrix_multiply*/ - #endif -}; - -static PySequenceMethods __pyx_tp_as_sequence_FrozenList = { - __pyx_pw_7aiohttp_11_frozenlist_10FrozenList_11__len__, /*sq_length*/ - 0, /*sq_concat*/ - 0, /*sq_repeat*/ - __pyx_sq_item_7aiohttp_11_frozenlist_FrozenList, /*sq_item*/ - 0, /*sq_slice*/ - 0, /*sq_ass_item*/ - 0, /*sq_ass_slice*/ - __pyx_pw_7aiohttp_11_frozenlist_10FrozenList_21__contains__, /*sq_contains*/ - 0, /*sq_inplace_concat*/ - 0, /*sq_inplace_repeat*/ -}; - -static PyMappingMethods __pyx_tp_as_mapping_FrozenList = { - __pyx_pw_7aiohttp_11_frozenlist_10FrozenList_11__len__, /*mp_length*/ - __pyx_pw_7aiohttp_11_frozenlist_10FrozenList_5__getitem__, /*mp_subscript*/ - __pyx_mp_ass_subscript_7aiohttp_11_frozenlist_FrozenList, /*mp_ass_subscript*/ -}; - -static PyTypeObject __pyx_type_7aiohttp_11_frozenlist_FrozenList = { - PyVarObject_HEAD_INIT(0, 0) - "aiohttp._frozenlist.FrozenList", /*tp_name*/ - sizeof(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - __pyx_tp_dealloc_7aiohttp_11_frozenlist_FrozenList, /*tp_dealloc*/ - #if PY_VERSION_HEX < 0x030800b4 - 0, /*tp_print*/ - #endif - #if PY_VERSION_HEX >= 0x030800b4 - 0, /*tp_vectorcall_offset*/ - #endif - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - #if PY_MAJOR_VERSION < 3 - 0, /*tp_compare*/ - #endif - #if PY_MAJOR_VERSION >= 3 - 0, /*tp_as_async*/ - #endif - __pyx_pw_7aiohttp_11_frozenlist_10FrozenList_41__repr__, /*tp_repr*/ - &__pyx_tp_as_number_FrozenList, /*tp_as_number*/ - &__pyx_tp_as_sequence_FrozenList, /*tp_as_sequence*/ - &__pyx_tp_as_mapping_FrozenList, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_VERSION_TAG|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, /*tp_flags*/ - 0, /*tp_doc*/ - __pyx_tp_traverse_7aiohttp_11_frozenlist_FrozenList, /*tp_traverse*/ - __pyx_tp_clear_7aiohttp_11_frozenlist_FrozenList, /*tp_clear*/ - __pyx_pw_7aiohttp_11_frozenlist_10FrozenList_17__richcmp__, /*tp_richcompare*/ - 0, /*tp_weaklistoffset*/ - __pyx_pw_7aiohttp_11_frozenlist_10FrozenList_13__iter__, /*tp_iter*/ - 0, /*tp_iternext*/ - __pyx_methods_7aiohttp_11_frozenlist_FrozenList, /*tp_methods*/ - 0, /*tp_members*/ - __pyx_getsets_7aiohttp_11_frozenlist_FrozenList, /*tp_getset*/ - 0, /*tp_base*/ - 0, /*tp_dict*/ - 0, /*tp_descr_get*/ - 0, /*tp_descr_set*/ - 0, /*tp_dictoffset*/ - __pyx_pw_7aiohttp_11_frozenlist_10FrozenList_1__init__, /*tp_init*/ - 0, /*tp_alloc*/ - __pyx_tp_new_7aiohttp_11_frozenlist_FrozenList, /*tp_new*/ - 0, /*tp_free*/ - 0, /*tp_is_gc*/ - 0, /*tp_bases*/ - 0, /*tp_mro*/ - 0, /*tp_cache*/ - 0, /*tp_subclasses*/ - 0, /*tp_weaklist*/ - 0, /*tp_del*/ - 0, /*tp_version_tag*/ - #if PY_VERSION_HEX >= 0x030400a1 - 0, /*tp_finalize*/ - #endif - #if PY_VERSION_HEX >= 0x030800b1 - 0, /*tp_vectorcall*/ - #endif - #if PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x03090000 - 0, /*tp_print*/ - #endif -}; - -static PyMethodDef __pyx_methods[] = { - {0, 0, 0, 0} -}; - -#if PY_MAJOR_VERSION >= 3 -#if CYTHON_PEP489_MULTI_PHASE_INIT -static PyObject* __pyx_pymod_create(PyObject *spec, PyModuleDef *def); /*proto*/ -static int __pyx_pymod_exec__frozenlist(PyObject* module); /*proto*/ -static PyModuleDef_Slot __pyx_moduledef_slots[] = { - {Py_mod_create, (void*)__pyx_pymod_create}, - {Py_mod_exec, (void*)__pyx_pymod_exec__frozenlist}, - {0, NULL} -}; -#endif - -static struct PyModuleDef __pyx_moduledef = { - PyModuleDef_HEAD_INIT, - "_frozenlist", - 0, /* m_doc */ - #if CYTHON_PEP489_MULTI_PHASE_INIT - 0, /* m_size */ - #else - -1, /* m_size */ - #endif - __pyx_methods /* m_methods */, - #if CYTHON_PEP489_MULTI_PHASE_INIT - __pyx_moduledef_slots, /* m_slots */ - #else - NULL, /* m_reload */ - #endif - NULL, /* m_traverse */ - NULL, /* m_clear */ - NULL /* m_free */ -}; -#endif -#ifndef CYTHON_SMALL_CODE -#if defined(__clang__) - #define CYTHON_SMALL_CODE -#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) - #define CYTHON_SMALL_CODE __attribute__((cold)) -#else - #define CYTHON_SMALL_CODE -#endif -#endif - -static __Pyx_StringTabEntry __pyx_string_tab[] = { - {&__pyx_kp_u_Cannot_modify_frozen_list, __pyx_k_Cannot_modify_frozen_list, sizeof(__pyx_k_Cannot_modify_frozen_list), 0, 1, 0, 0}, - {&__pyx_n_s_FrozenList, __pyx_k_FrozenList, sizeof(__pyx_k_FrozenList), 0, 0, 1, 1}, - {&__pyx_kp_u_FrozenList_frozen_r, __pyx_k_FrozenList_frozen_r, sizeof(__pyx_k_FrozenList_frozen_r), 0, 1, 0, 0}, - {&__pyx_kp_s_Incompatible_checksums_s_vs_0x94, __pyx_k_Incompatible_checksums_s_vs_0x94, sizeof(__pyx_k_Incompatible_checksums_s_vs_0x94), 0, 0, 1, 0}, - {&__pyx_n_s_MutableSequence, __pyx_k_MutableSequence, sizeof(__pyx_k_MutableSequence), 0, 0, 1, 1}, - {&__pyx_n_s_PickleError, __pyx_k_PickleError, sizeof(__pyx_k_PickleError), 0, 0, 1, 1}, - {&__pyx_n_s_RuntimeError, __pyx_k_RuntimeError, sizeof(__pyx_k_RuntimeError), 0, 0, 1, 1}, - {&__pyx_n_s_aiohttp__frozenlist, __pyx_k_aiohttp__frozenlist, sizeof(__pyx_k_aiohttp__frozenlist), 0, 0, 1, 1}, - {&__pyx_n_s_clear, __pyx_k_clear, sizeof(__pyx_k_clear), 0, 0, 1, 1}, - {&__pyx_n_s_cline_in_traceback, __pyx_k_cline_in_traceback, sizeof(__pyx_k_cline_in_traceback), 0, 0, 1, 1}, - {&__pyx_n_s_collections_abc, __pyx_k_collections_abc, sizeof(__pyx_k_collections_abc), 0, 0, 1, 1}, - {&__pyx_n_s_count, __pyx_k_count, sizeof(__pyx_k_count), 0, 0, 1, 1}, - {&__pyx_n_s_dict, __pyx_k_dict, sizeof(__pyx_k_dict), 0, 0, 1, 1}, - {&__pyx_n_s_format, __pyx_k_format, sizeof(__pyx_k_format), 0, 0, 1, 1}, - {&__pyx_n_s_getstate, __pyx_k_getstate, sizeof(__pyx_k_getstate), 0, 0, 1, 1}, - {&__pyx_n_s_import, __pyx_k_import, sizeof(__pyx_k_import), 0, 0, 1, 1}, - {&__pyx_n_s_index, __pyx_k_index, sizeof(__pyx_k_index), 0, 0, 1, 1}, - {&__pyx_n_s_item, __pyx_k_item, sizeof(__pyx_k_item), 0, 0, 1, 1}, - {&__pyx_n_s_items, __pyx_k_items, sizeof(__pyx_k_items), 0, 0, 1, 1}, - {&__pyx_n_s_iter, __pyx_k_iter, sizeof(__pyx_k_iter), 0, 0, 1, 1}, - {&__pyx_n_s_main, __pyx_k_main, sizeof(__pyx_k_main), 0, 0, 1, 1}, - {&__pyx_n_s_name, __pyx_k_name, sizeof(__pyx_k_name), 0, 0, 1, 1}, - {&__pyx_n_s_new, __pyx_k_new, sizeof(__pyx_k_new), 0, 0, 1, 1}, - {&__pyx_n_s_pickle, __pyx_k_pickle, sizeof(__pyx_k_pickle), 0, 0, 1, 1}, - {&__pyx_n_s_pop, __pyx_k_pop, sizeof(__pyx_k_pop), 0, 0, 1, 1}, - {&__pyx_n_s_pos, __pyx_k_pos, sizeof(__pyx_k_pos), 0, 0, 1, 1}, - {&__pyx_n_s_pyx_PickleError, __pyx_k_pyx_PickleError, sizeof(__pyx_k_pyx_PickleError), 0, 0, 1, 1}, - {&__pyx_n_s_pyx_checksum, __pyx_k_pyx_checksum, sizeof(__pyx_k_pyx_checksum), 0, 0, 1, 1}, - {&__pyx_n_s_pyx_result, __pyx_k_pyx_result, sizeof(__pyx_k_pyx_result), 0, 0, 1, 1}, - {&__pyx_n_s_pyx_state, __pyx_k_pyx_state, sizeof(__pyx_k_pyx_state), 0, 0, 1, 1}, - {&__pyx_n_s_pyx_type, __pyx_k_pyx_type, sizeof(__pyx_k_pyx_type), 0, 0, 1, 1}, - {&__pyx_n_s_pyx_unpickle_FrozenList, __pyx_k_pyx_unpickle_FrozenList, sizeof(__pyx_k_pyx_unpickle_FrozenList), 0, 0, 1, 1}, - {&__pyx_n_s_pyx_vtable, __pyx_k_pyx_vtable, sizeof(__pyx_k_pyx_vtable), 0, 0, 1, 1}, - {&__pyx_n_s_reduce, __pyx_k_reduce, sizeof(__pyx_k_reduce), 0, 0, 1, 1}, - {&__pyx_n_s_reduce_cython, __pyx_k_reduce_cython, sizeof(__pyx_k_reduce_cython), 0, 0, 1, 1}, - {&__pyx_n_s_reduce_ex, __pyx_k_reduce_ex, sizeof(__pyx_k_reduce_ex), 0, 0, 1, 1}, - {&__pyx_n_s_register, __pyx_k_register, sizeof(__pyx_k_register), 0, 0, 1, 1}, - {&__pyx_n_s_remove, __pyx_k_remove, sizeof(__pyx_k_remove), 0, 0, 1, 1}, - {&__pyx_n_s_reversed, __pyx_k_reversed, sizeof(__pyx_k_reversed), 0, 0, 1, 1}, - {&__pyx_n_s_setstate, __pyx_k_setstate, sizeof(__pyx_k_setstate), 0, 0, 1, 1}, - {&__pyx_n_s_setstate_cython, __pyx_k_setstate_cython, sizeof(__pyx_k_setstate_cython), 0, 0, 1, 1}, - {&__pyx_kp_s_stringsource, __pyx_k_stringsource, sizeof(__pyx_k_stringsource), 0, 0, 1, 0}, - {&__pyx_n_s_test, __pyx_k_test, sizeof(__pyx_k_test), 0, 0, 1, 1}, - {&__pyx_n_s_update, __pyx_k_update, sizeof(__pyx_k_update), 0, 0, 1, 1}, - {0, 0, 0, 0, 0, 0, 0} -}; -static CYTHON_SMALL_CODE int __Pyx_InitCachedBuiltins(void) { - __pyx_builtin_RuntimeError = __Pyx_GetBuiltinName(__pyx_n_s_RuntimeError); if (!__pyx_builtin_RuntimeError) __PYX_ERR(0, 19, __pyx_L1_error) - return 0; - __pyx_L1_error:; - return -1; -} - -static CYTHON_SMALL_CODE int __Pyx_InitCachedConstants(void) { - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__Pyx_InitCachedConstants", 0); - - /* "aiohttp/_frozenlist.pyx":19 - * cdef object _check_frozen(self): - * if self.frozen: - * raise RuntimeError("Cannot modify frozen list.") # <<<<<<<<<<<<<< - * - * cdef inline object _fast_len(self): - */ - __pyx_tuple_ = PyTuple_Pack(1, __pyx_kp_u_Cannot_modify_frozen_list); if (unlikely(!__pyx_tuple_)) __PYX_ERR(0, 19, __pyx_L1_error) - __Pyx_GOTREF(__pyx_tuple_); - __Pyx_GIVEREF(__pyx_tuple_); - - /* "(tree fragment)":1 - * def __pyx_unpickle_FrozenList(__pyx_type, long __pyx_checksum, __pyx_state): # <<<<<<<<<<<<<< - * cdef object __pyx_PickleError - * cdef object __pyx_result - */ - __pyx_tuple__2 = PyTuple_Pack(5, __pyx_n_s_pyx_type, __pyx_n_s_pyx_checksum, __pyx_n_s_pyx_state, __pyx_n_s_pyx_PickleError, __pyx_n_s_pyx_result); if (unlikely(!__pyx_tuple__2)) __PYX_ERR(1, 1, __pyx_L1_error) - __Pyx_GOTREF(__pyx_tuple__2); - __Pyx_GIVEREF(__pyx_tuple__2); - __pyx_codeobj__3 = (PyObject*)__Pyx_PyCode_New(3, 0, 5, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__2, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_stringsource, __pyx_n_s_pyx_unpickle_FrozenList, 1, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__3)) __PYX_ERR(1, 1, __pyx_L1_error) - __Pyx_RefNannyFinishContext(); - return 0; - __pyx_L1_error:; - __Pyx_RefNannyFinishContext(); - return -1; -} - -static CYTHON_SMALL_CODE int __Pyx_InitGlobals(void) { - if (__Pyx_InitStrings(__pyx_string_tab) < 0) __PYX_ERR(0, 1, __pyx_L1_error); - __pyx_int_0 = PyInt_FromLong(0); if (unlikely(!__pyx_int_0)) __PYX_ERR(0, 1, __pyx_L1_error) - __pyx_int_1 = PyInt_FromLong(1); if (unlikely(!__pyx_int_1)) __PYX_ERR(0, 1, __pyx_L1_error) - __pyx_int_2 = PyInt_FromLong(2); if (unlikely(!__pyx_int_2)) __PYX_ERR(0, 1, __pyx_L1_error) - __pyx_int_3 = PyInt_FromLong(3); if (unlikely(!__pyx_int_3)) __PYX_ERR(0, 1, __pyx_L1_error) - __pyx_int_4 = PyInt_FromLong(4); if (unlikely(!__pyx_int_4)) __PYX_ERR(0, 1, __pyx_L1_error) - __pyx_int_5 = PyInt_FromLong(5); if (unlikely(!__pyx_int_5)) __PYX_ERR(0, 1, __pyx_L1_error) - __pyx_int_155820355 = PyInt_FromLong(155820355L); if (unlikely(!__pyx_int_155820355)) __PYX_ERR(0, 1, __pyx_L1_error) - __pyx_int_neg_1 = PyInt_FromLong(-1); if (unlikely(!__pyx_int_neg_1)) __PYX_ERR(0, 1, __pyx_L1_error) - return 0; - __pyx_L1_error:; - return -1; -} - -static CYTHON_SMALL_CODE int __Pyx_modinit_global_init_code(void); /*proto*/ -static CYTHON_SMALL_CODE int __Pyx_modinit_variable_export_code(void); /*proto*/ -static CYTHON_SMALL_CODE int __Pyx_modinit_function_export_code(void); /*proto*/ -static CYTHON_SMALL_CODE int __Pyx_modinit_type_init_code(void); /*proto*/ -static CYTHON_SMALL_CODE int __Pyx_modinit_type_import_code(void); /*proto*/ -static CYTHON_SMALL_CODE int __Pyx_modinit_variable_import_code(void); /*proto*/ -static CYTHON_SMALL_CODE int __Pyx_modinit_function_import_code(void); /*proto*/ - -static int __Pyx_modinit_global_init_code(void) { - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__Pyx_modinit_global_init_code", 0); - /*--- Global init code ---*/ - __Pyx_RefNannyFinishContext(); - return 0; -} - -static int __Pyx_modinit_variable_export_code(void) { - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__Pyx_modinit_variable_export_code", 0); - /*--- Variable export code ---*/ - __Pyx_RefNannyFinishContext(); - return 0; -} - -static int __Pyx_modinit_function_export_code(void) { - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__Pyx_modinit_function_export_code", 0); - /*--- Function export code ---*/ - __Pyx_RefNannyFinishContext(); - return 0; -} - -static int __Pyx_modinit_type_init_code(void) { - __Pyx_RefNannyDeclarations - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("__Pyx_modinit_type_init_code", 0); - /*--- Type init code ---*/ - __pyx_vtabptr_7aiohttp_11_frozenlist_FrozenList = &__pyx_vtable_7aiohttp_11_frozenlist_FrozenList; - __pyx_vtable_7aiohttp_11_frozenlist_FrozenList._check_frozen = (PyObject *(*)(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *))__pyx_f_7aiohttp_11_frozenlist_10FrozenList__check_frozen; - __pyx_vtable_7aiohttp_11_frozenlist_FrozenList._fast_len = (PyObject *(*)(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *))__pyx_f_7aiohttp_11_frozenlist_10FrozenList__fast_len; - if (PyType_Ready(&__pyx_type_7aiohttp_11_frozenlist_FrozenList) < 0) __PYX_ERR(0, 4, __pyx_L1_error) - #if PY_VERSION_HEX < 0x030800B1 - __pyx_type_7aiohttp_11_frozenlist_FrozenList.tp_print = 0; - #endif - if ((CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP) && likely(!__pyx_type_7aiohttp_11_frozenlist_FrozenList.tp_dictoffset && __pyx_type_7aiohttp_11_frozenlist_FrozenList.tp_getattro == PyObject_GenericGetAttr)) { - __pyx_type_7aiohttp_11_frozenlist_FrozenList.tp_getattro = __Pyx_PyObject_GenericGetAttr; - } - if (__Pyx_SetVtable(__pyx_type_7aiohttp_11_frozenlist_FrozenList.tp_dict, __pyx_vtabptr_7aiohttp_11_frozenlist_FrozenList) < 0) __PYX_ERR(0, 4, __pyx_L1_error) - if (PyObject_SetAttr(__pyx_m, __pyx_n_s_FrozenList, (PyObject *)&__pyx_type_7aiohttp_11_frozenlist_FrozenList) < 0) __PYX_ERR(0, 4, __pyx_L1_error) - if (__Pyx_setup_reduce((PyObject*)&__pyx_type_7aiohttp_11_frozenlist_FrozenList) < 0) __PYX_ERR(0, 4, __pyx_L1_error) - __pyx_ptype_7aiohttp_11_frozenlist_FrozenList = &__pyx_type_7aiohttp_11_frozenlist_FrozenList; - __Pyx_RefNannyFinishContext(); - return 0; - __pyx_L1_error:; - __Pyx_RefNannyFinishContext(); - return -1; -} - -static int __Pyx_modinit_type_import_code(void) { - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__Pyx_modinit_type_import_code", 0); - /*--- Type import code ---*/ - __Pyx_RefNannyFinishContext(); - return 0; -} - -static int __Pyx_modinit_variable_import_code(void) { - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__Pyx_modinit_variable_import_code", 0); - /*--- Variable import code ---*/ - __Pyx_RefNannyFinishContext(); - return 0; -} - -static int __Pyx_modinit_function_import_code(void) { - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__Pyx_modinit_function_import_code", 0); - /*--- Function import code ---*/ - __Pyx_RefNannyFinishContext(); - return 0; -} - - -#ifndef CYTHON_NO_PYINIT_EXPORT -#define __Pyx_PyMODINIT_FUNC PyMODINIT_FUNC -#elif PY_MAJOR_VERSION < 3 -#ifdef __cplusplus -#define __Pyx_PyMODINIT_FUNC extern "C" void -#else -#define __Pyx_PyMODINIT_FUNC void -#endif -#else -#ifdef __cplusplus -#define __Pyx_PyMODINIT_FUNC extern "C" PyObject * -#else -#define __Pyx_PyMODINIT_FUNC PyObject * -#endif -#endif - - -#if PY_MAJOR_VERSION < 3 -__Pyx_PyMODINIT_FUNC init_frozenlist(void) CYTHON_SMALL_CODE; /*proto*/ -__Pyx_PyMODINIT_FUNC init_frozenlist(void) -#else -__Pyx_PyMODINIT_FUNC PyInit__frozenlist(void) CYTHON_SMALL_CODE; /*proto*/ -__Pyx_PyMODINIT_FUNC PyInit__frozenlist(void) -#if CYTHON_PEP489_MULTI_PHASE_INIT -{ - return PyModuleDef_Init(&__pyx_moduledef); -} -static CYTHON_SMALL_CODE int __Pyx_check_single_interpreter(void) { - #if PY_VERSION_HEX >= 0x030700A1 - static PY_INT64_T main_interpreter_id = -1; - PY_INT64_T current_id = PyInterpreterState_GetID(PyThreadState_Get()->interp); - if (main_interpreter_id == -1) { - main_interpreter_id = current_id; - return (unlikely(current_id == -1)) ? -1 : 0; - } else if (unlikely(main_interpreter_id != current_id)) - #else - static PyInterpreterState *main_interpreter = NULL; - PyInterpreterState *current_interpreter = PyThreadState_Get()->interp; - if (!main_interpreter) { - main_interpreter = current_interpreter; - } else if (unlikely(main_interpreter != current_interpreter)) - #endif - { - PyErr_SetString( - PyExc_ImportError, - "Interpreter change detected - this module can only be loaded into one interpreter per process."); - return -1; - } - return 0; -} -static CYTHON_SMALL_CODE int __Pyx_copy_spec_to_module(PyObject *spec, PyObject *moddict, const char* from_name, const char* to_name, int allow_none) { - PyObject *value = PyObject_GetAttrString(spec, from_name); - int result = 0; - if (likely(value)) { - if (allow_none || value != Py_None) { - result = PyDict_SetItemString(moddict, to_name, value); - } - Py_DECREF(value); - } else if (PyErr_ExceptionMatches(PyExc_AttributeError)) { - PyErr_Clear(); - } else { - result = -1; - } - return result; -} -static CYTHON_SMALL_CODE PyObject* __pyx_pymod_create(PyObject *spec, CYTHON_UNUSED PyModuleDef *def) { - PyObject *module = NULL, *moddict, *modname; - if (__Pyx_check_single_interpreter()) - return NULL; - if (__pyx_m) - return __Pyx_NewRef(__pyx_m); - modname = PyObject_GetAttrString(spec, "name"); - if (unlikely(!modname)) goto bad; - module = PyModule_NewObject(modname); - Py_DECREF(modname); - if (unlikely(!module)) goto bad; - moddict = PyModule_GetDict(module); - if (unlikely(!moddict)) goto bad; - if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "loader", "__loader__", 1) < 0)) goto bad; - if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "origin", "__file__", 1) < 0)) goto bad; - if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "parent", "__package__", 1) < 0)) goto bad; - if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "submodule_search_locations", "__path__", 0) < 0)) goto bad; - return module; -bad: - Py_XDECREF(module); - return NULL; -} - - -static CYTHON_SMALL_CODE int __pyx_pymod_exec__frozenlist(PyObject *__pyx_pyinit_module) -#endif -#endif -{ - PyObject *__pyx_t_1 = NULL; - PyObject *__pyx_t_2 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannyDeclarations - #if CYTHON_PEP489_MULTI_PHASE_INIT - if (__pyx_m) { - if (__pyx_m == __pyx_pyinit_module) return 0; - PyErr_SetString(PyExc_RuntimeError, "Module '_frozenlist' has already been imported. Re-initialisation is not supported."); - return -1; - } - #elif PY_MAJOR_VERSION >= 3 - if (__pyx_m) return __Pyx_NewRef(__pyx_m); - #endif - #if CYTHON_REFNANNY -__Pyx_RefNanny = __Pyx_RefNannyImportAPI("refnanny"); -if (!__Pyx_RefNanny) { - PyErr_Clear(); - __Pyx_RefNanny = __Pyx_RefNannyImportAPI("Cython.Runtime.refnanny"); - if (!__Pyx_RefNanny) - Py_FatalError("failed to import 'refnanny' module"); -} -#endif - __Pyx_RefNannySetupContext("__Pyx_PyMODINIT_FUNC PyInit__frozenlist(void)", 0); - if (__Pyx_check_binary_version() < 0) __PYX_ERR(0, 1, __pyx_L1_error) - #ifdef __Pxy_PyFrame_Initialize_Offsets - __Pxy_PyFrame_Initialize_Offsets(); - #endif - __pyx_empty_tuple = PyTuple_New(0); if (unlikely(!__pyx_empty_tuple)) __PYX_ERR(0, 1, __pyx_L1_error) - __pyx_empty_bytes = PyBytes_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_bytes)) __PYX_ERR(0, 1, __pyx_L1_error) - __pyx_empty_unicode = PyUnicode_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_unicode)) __PYX_ERR(0, 1, __pyx_L1_error) - #ifdef __Pyx_CyFunction_USED - if (__pyx_CyFunction_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) - #endif - #ifdef __Pyx_FusedFunction_USED - if (__pyx_FusedFunction_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) - #endif - #ifdef __Pyx_Coroutine_USED - if (__pyx_Coroutine_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) - #endif - #ifdef __Pyx_Generator_USED - if (__pyx_Generator_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) - #endif - #ifdef __Pyx_AsyncGen_USED - if (__pyx_AsyncGen_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) - #endif - #ifdef __Pyx_StopAsyncIteration_USED - if (__pyx_StopAsyncIteration_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) - #endif - /*--- Library function declarations ---*/ - /*--- Threads initialization code ---*/ - #if defined(__PYX_FORCE_INIT_THREADS) && __PYX_FORCE_INIT_THREADS - #ifdef WITH_THREAD /* Python build with threading support? */ - PyEval_InitThreads(); - #endif - #endif - /*--- Module creation code ---*/ - #if CYTHON_PEP489_MULTI_PHASE_INIT - __pyx_m = __pyx_pyinit_module; - Py_INCREF(__pyx_m); - #else - #if PY_MAJOR_VERSION < 3 - __pyx_m = Py_InitModule4("_frozenlist", __pyx_methods, 0, 0, PYTHON_API_VERSION); Py_XINCREF(__pyx_m); - #else - __pyx_m = PyModule_Create(&__pyx_moduledef); - #endif - if (unlikely(!__pyx_m)) __PYX_ERR(0, 1, __pyx_L1_error) - #endif - __pyx_d = PyModule_GetDict(__pyx_m); if (unlikely(!__pyx_d)) __PYX_ERR(0, 1, __pyx_L1_error) - Py_INCREF(__pyx_d); - __pyx_b = PyImport_AddModule(__Pyx_BUILTIN_MODULE_NAME); if (unlikely(!__pyx_b)) __PYX_ERR(0, 1, __pyx_L1_error) - Py_INCREF(__pyx_b); - __pyx_cython_runtime = PyImport_AddModule((char *) "cython_runtime"); if (unlikely(!__pyx_cython_runtime)) __PYX_ERR(0, 1, __pyx_L1_error) - Py_INCREF(__pyx_cython_runtime); - if (PyObject_SetAttrString(__pyx_m, "__builtins__", __pyx_b) < 0) __PYX_ERR(0, 1, __pyx_L1_error); - /*--- Initialize various global constants etc. ---*/ - if (__Pyx_InitGlobals() < 0) __PYX_ERR(0, 1, __pyx_L1_error) - #if PY_MAJOR_VERSION < 3 && (__PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT) - if (__Pyx_init_sys_getdefaultencoding_params() < 0) __PYX_ERR(0, 1, __pyx_L1_error) - #endif - if (__pyx_module_is_main_aiohttp___frozenlist) { - if (PyObject_SetAttr(__pyx_m, __pyx_n_s_name, __pyx_n_s_main) < 0) __PYX_ERR(0, 1, __pyx_L1_error) - } - #if PY_MAJOR_VERSION >= 3 - { - PyObject *modules = PyImport_GetModuleDict(); if (unlikely(!modules)) __PYX_ERR(0, 1, __pyx_L1_error) - if (!PyDict_GetItemString(modules, "aiohttp._frozenlist")) { - if (unlikely(PyDict_SetItemString(modules, "aiohttp._frozenlist", __pyx_m) < 0)) __PYX_ERR(0, 1, __pyx_L1_error) - } - } - #endif - /*--- Builtin init code ---*/ - if (__Pyx_InitCachedBuiltins() < 0) __PYX_ERR(0, 1, __pyx_L1_error) - /*--- Constants init code ---*/ - if (__Pyx_InitCachedConstants() < 0) __PYX_ERR(0, 1, __pyx_L1_error) - /*--- Global type/function init code ---*/ - (void)__Pyx_modinit_global_init_code(); - (void)__Pyx_modinit_variable_export_code(); - (void)__Pyx_modinit_function_export_code(); - if (unlikely(__Pyx_modinit_type_init_code() < 0)) __PYX_ERR(0, 1, __pyx_L1_error) - (void)__Pyx_modinit_type_import_code(); - (void)__Pyx_modinit_variable_import_code(); - (void)__Pyx_modinit_function_import_code(); - /*--- Execution code ---*/ - #if defined(__Pyx_Generator_USED) || defined(__Pyx_Coroutine_USED) - if (__Pyx_patch_abc() < 0) __PYX_ERR(0, 1, __pyx_L1_error) - #endif - - /* "aiohttp/_frozenlist.pyx":1 - * from collections.abc import MutableSequence # <<<<<<<<<<<<<< - * - * - */ - __pyx_t_1 = PyList_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_INCREF(__pyx_n_s_MutableSequence); - __Pyx_GIVEREF(__pyx_n_s_MutableSequence); - PyList_SET_ITEM(__pyx_t_1, 0, __pyx_n_s_MutableSequence); - __pyx_t_2 = __Pyx_Import(__pyx_n_s_collections_abc, __pyx_t_1, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_MutableSequence); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - if (PyDict_SetItem(__pyx_d, __pyx_n_s_MutableSequence, __pyx_t_1) < 0) __PYX_ERR(0, 1, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - - /* "aiohttp/_frozenlist.pyx":108 - * - * - * MutableSequence.register(FrozenList) # <<<<<<<<<<<<<< - */ - __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_MutableSequence); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 108, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_register); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 108, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_1, ((PyObject *)__pyx_ptype_7aiohttp_11_frozenlist_FrozenList)); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 108, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - - /* "(tree fragment)":1 - * def __pyx_unpickle_FrozenList(__pyx_type, long __pyx_checksum, __pyx_state): # <<<<<<<<<<<<<< - * cdef object __pyx_PickleError - * cdef object __pyx_result - */ - __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_7aiohttp_11_frozenlist_1__pyx_unpickle_FrozenList, NULL, __pyx_n_s_aiohttp__frozenlist); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 1, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - if (PyDict_SetItem(__pyx_d, __pyx_n_s_pyx_unpickle_FrozenList, __pyx_t_2) < 0) __PYX_ERR(1, 1, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - - /* "aiohttp/_frozenlist.pyx":1 - * from collections.abc import MutableSequence # <<<<<<<<<<<<<< - * - * - */ - __pyx_t_2 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - if (PyDict_SetItem(__pyx_d, __pyx_n_s_test, __pyx_t_2) < 0) __PYX_ERR(0, 1, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - - /*--- Wrapped vars code ---*/ - - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_XDECREF(__pyx_t_2); - if (__pyx_m) { - if (__pyx_d) { - __Pyx_AddTraceback("init aiohttp._frozenlist", __pyx_clineno, __pyx_lineno, __pyx_filename); - } - Py_CLEAR(__pyx_m); - } else if (!PyErr_Occurred()) { - PyErr_SetString(PyExc_ImportError, "init aiohttp._frozenlist"); - } - __pyx_L0:; - __Pyx_RefNannyFinishContext(); - #if CYTHON_PEP489_MULTI_PHASE_INIT - return (__pyx_m != NULL) ? 0 : -1; - #elif PY_MAJOR_VERSION >= 3 - return __pyx_m; - #else - return; - #endif -} - -/* --- Runtime support code --- */ -/* Refnanny */ -#if CYTHON_REFNANNY -static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname) { - PyObject *m = NULL, *p = NULL; - void *r = NULL; - m = PyImport_ImportModule(modname); - if (!m) goto end; - p = PyObject_GetAttrString(m, "RefNannyAPI"); - if (!p) goto end; - r = PyLong_AsVoidPtr(p); -end: - Py_XDECREF(p); - Py_XDECREF(m); - return (__Pyx_RefNannyAPIStruct *)r; -} -#endif - -/* PyObjectGetAttrStr */ -#if CYTHON_USE_TYPE_SLOTS -static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStr(PyObject* obj, PyObject* attr_name) { - PyTypeObject* tp = Py_TYPE(obj); - if (likely(tp->tp_getattro)) - return tp->tp_getattro(obj, attr_name); -#if PY_MAJOR_VERSION < 3 - if (likely(tp->tp_getattr)) - return tp->tp_getattr(obj, PyString_AS_STRING(attr_name)); -#endif - return PyObject_GetAttr(obj, attr_name); -} -#endif - -/* GetBuiltinName */ -static PyObject *__Pyx_GetBuiltinName(PyObject *name) { - PyObject* result = __Pyx_PyObject_GetAttrStr(__pyx_b, name); - if (unlikely(!result)) { - PyErr_Format(PyExc_NameError, -#if PY_MAJOR_VERSION >= 3 - "name '%U' is not defined", name); -#else - "name '%.200s' is not defined", PyString_AS_STRING(name)); -#endif - } - return result; -} - -/* RaiseDoubleKeywords */ -static void __Pyx_RaiseDoubleKeywordsError( - const char* func_name, - PyObject* kw_name) -{ - PyErr_Format(PyExc_TypeError, - #if PY_MAJOR_VERSION >= 3 - "%s() got multiple values for keyword argument '%U'", func_name, kw_name); - #else - "%s() got multiple values for keyword argument '%s'", func_name, - PyString_AsString(kw_name)); - #endif -} - -/* ParseKeywords */ -static int __Pyx_ParseOptionalKeywords( - PyObject *kwds, - PyObject **argnames[], - PyObject *kwds2, - PyObject *values[], - Py_ssize_t num_pos_args, - const char* function_name) -{ - PyObject *key = 0, *value = 0; - Py_ssize_t pos = 0; - PyObject*** name; - PyObject*** first_kw_arg = argnames + num_pos_args; - while (PyDict_Next(kwds, &pos, &key, &value)) { - name = first_kw_arg; - while (*name && (**name != key)) name++; - if (*name) { - values[name-argnames] = value; - continue; - } - name = first_kw_arg; - #if PY_MAJOR_VERSION < 3 - if (likely(PyString_Check(key))) { - while (*name) { - if ((CYTHON_COMPILING_IN_PYPY || PyString_GET_SIZE(**name) == PyString_GET_SIZE(key)) - && _PyString_Eq(**name, key)) { - values[name-argnames] = value; - break; - } - name++; - } - if (*name) continue; - else { - PyObject*** argname = argnames; - while (argname != first_kw_arg) { - if ((**argname == key) || ( - (CYTHON_COMPILING_IN_PYPY || PyString_GET_SIZE(**argname) == PyString_GET_SIZE(key)) - && _PyString_Eq(**argname, key))) { - goto arg_passed_twice; - } - argname++; - } - } - } else - #endif - if (likely(PyUnicode_Check(key))) { - while (*name) { - int cmp = (**name == key) ? 0 : - #if !CYTHON_COMPILING_IN_PYPY && PY_MAJOR_VERSION >= 3 - (__Pyx_PyUnicode_GET_LENGTH(**name) != __Pyx_PyUnicode_GET_LENGTH(key)) ? 1 : - #endif - PyUnicode_Compare(**name, key); - if (cmp < 0 && unlikely(PyErr_Occurred())) goto bad; - if (cmp == 0) { - values[name-argnames] = value; - break; - } - name++; - } - if (*name) continue; - else { - PyObject*** argname = argnames; - while (argname != first_kw_arg) { - int cmp = (**argname == key) ? 0 : - #if !CYTHON_COMPILING_IN_PYPY && PY_MAJOR_VERSION >= 3 - (__Pyx_PyUnicode_GET_LENGTH(**argname) != __Pyx_PyUnicode_GET_LENGTH(key)) ? 1 : - #endif - PyUnicode_Compare(**argname, key); - if (cmp < 0 && unlikely(PyErr_Occurred())) goto bad; - if (cmp == 0) goto arg_passed_twice; - argname++; - } - } - } else - goto invalid_keyword_type; - if (kwds2) { - if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad; - } else { - goto invalid_keyword; - } - } - return 0; -arg_passed_twice: - __Pyx_RaiseDoubleKeywordsError(function_name, key); - goto bad; -invalid_keyword_type: - PyErr_Format(PyExc_TypeError, - "%.200s() keywords must be strings", function_name); - goto bad; -invalid_keyword: - PyErr_Format(PyExc_TypeError, - #if PY_MAJOR_VERSION < 3 - "%.200s() got an unexpected keyword argument '%.200s'", - function_name, PyString_AsString(key)); - #else - "%s() got an unexpected keyword argument '%U'", - function_name, key); - #endif -bad: - return -1; -} - -/* RaiseArgTupleInvalid */ -static void __Pyx_RaiseArgtupleInvalid( - const char* func_name, - int exact, - Py_ssize_t num_min, - Py_ssize_t num_max, - Py_ssize_t num_found) -{ - Py_ssize_t num_expected; - const char *more_or_less; - if (num_found < num_min) { - num_expected = num_min; - more_or_less = "at least"; - } else { - num_expected = num_max; - more_or_less = "at most"; - } - if (exact) { - more_or_less = "exactly"; - } - PyErr_Format(PyExc_TypeError, - "%.200s() takes %.8s %" CYTHON_FORMAT_SSIZE_T "d positional argument%.1s (%" CYTHON_FORMAT_SSIZE_T "d given)", - func_name, more_or_less, num_expected, - (num_expected == 1) ? "" : "s", num_found); -} - -/* PyObjectCall */ -#if CYTHON_COMPILING_IN_CPYTHON -static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw) { - PyObject *result; - ternaryfunc call = func->ob_type->tp_call; - if (unlikely(!call)) - return PyObject_Call(func, arg, kw); - if (unlikely(Py_EnterRecursiveCall((char*)" while calling a Python object"))) - return NULL; - result = (*call)(func, arg, kw); - Py_LeaveRecursiveCall(); - if (unlikely(!result) && unlikely(!PyErr_Occurred())) { - PyErr_SetString( - PyExc_SystemError, - "NULL result without error in PyObject_Call"); - } - return result; -} -#endif - -/* PyErrFetchRestore */ -#if CYTHON_FAST_THREAD_STATE -static CYTHON_INLINE void __Pyx_ErrRestoreInState(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb) { - PyObject *tmp_type, *tmp_value, *tmp_tb; - tmp_type = tstate->curexc_type; - tmp_value = tstate->curexc_value; - tmp_tb = tstate->curexc_traceback; - tstate->curexc_type = type; - tstate->curexc_value = value; - tstate->curexc_traceback = tb; - Py_XDECREF(tmp_type); - Py_XDECREF(tmp_value); - Py_XDECREF(tmp_tb); -} -static CYTHON_INLINE void __Pyx_ErrFetchInState(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) { - *type = tstate->curexc_type; - *value = tstate->curexc_value; - *tb = tstate->curexc_traceback; - tstate->curexc_type = 0; - tstate->curexc_value = 0; - tstate->curexc_traceback = 0; -} -#endif - -/* RaiseException */ -#if PY_MAJOR_VERSION < 3 -static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, - CYTHON_UNUSED PyObject *cause) { - __Pyx_PyThreadState_declare - Py_XINCREF(type); - if (!value || value == Py_None) - value = NULL; - else - Py_INCREF(value); - if (!tb || tb == Py_None) - tb = NULL; - else { - Py_INCREF(tb); - if (!PyTraceBack_Check(tb)) { - PyErr_SetString(PyExc_TypeError, - "raise: arg 3 must be a traceback or None"); - goto raise_error; - } - } - if (PyType_Check(type)) { -#if CYTHON_COMPILING_IN_PYPY - if (!value) { - Py_INCREF(Py_None); - value = Py_None; - } -#endif - PyErr_NormalizeException(&type, &value, &tb); - } else { - if (value) { - PyErr_SetString(PyExc_TypeError, - "instance exception may not have a separate value"); - goto raise_error; - } - value = type; - type = (PyObject*) Py_TYPE(type); - Py_INCREF(type); - if (!PyType_IsSubtype((PyTypeObject *)type, (PyTypeObject *)PyExc_BaseException)) { - PyErr_SetString(PyExc_TypeError, - "raise: exception class must be a subclass of BaseException"); - goto raise_error; - } - } - __Pyx_PyThreadState_assign - __Pyx_ErrRestore(type, value, tb); - return; -raise_error: - Py_XDECREF(value); - Py_XDECREF(type); - Py_XDECREF(tb); - return; -} -#else -static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause) { - PyObject* owned_instance = NULL; - if (tb == Py_None) { - tb = 0; - } else if (tb && !PyTraceBack_Check(tb)) { - PyErr_SetString(PyExc_TypeError, - "raise: arg 3 must be a traceback or None"); - goto bad; - } - if (value == Py_None) - value = 0; - if (PyExceptionInstance_Check(type)) { - if (value) { - PyErr_SetString(PyExc_TypeError, - "instance exception may not have a separate value"); - goto bad; - } - value = type; - type = (PyObject*) Py_TYPE(value); - } else if (PyExceptionClass_Check(type)) { - PyObject *instance_class = NULL; - if (value && PyExceptionInstance_Check(value)) { - instance_class = (PyObject*) Py_TYPE(value); - if (instance_class != type) { - int is_subclass = PyObject_IsSubclass(instance_class, type); - if (!is_subclass) { - instance_class = NULL; - } else if (unlikely(is_subclass == -1)) { - goto bad; - } else { - type = instance_class; - } - } - } - if (!instance_class) { - PyObject *args; - if (!value) - args = PyTuple_New(0); - else if (PyTuple_Check(value)) { - Py_INCREF(value); - args = value; - } else - args = PyTuple_Pack(1, value); - if (!args) - goto bad; - owned_instance = PyObject_Call(type, args, NULL); - Py_DECREF(args); - if (!owned_instance) - goto bad; - value = owned_instance; - if (!PyExceptionInstance_Check(value)) { - PyErr_Format(PyExc_TypeError, - "calling %R should have returned an instance of " - "BaseException, not %R", - type, Py_TYPE(value)); - goto bad; - } - } - } else { - PyErr_SetString(PyExc_TypeError, - "raise: exception class must be a subclass of BaseException"); - goto bad; - } - if (cause) { - PyObject *fixed_cause; - if (cause == Py_None) { - fixed_cause = NULL; - } else if (PyExceptionClass_Check(cause)) { - fixed_cause = PyObject_CallObject(cause, NULL); - if (fixed_cause == NULL) - goto bad; - } else if (PyExceptionInstance_Check(cause)) { - fixed_cause = cause; - Py_INCREF(fixed_cause); - } else { - PyErr_SetString(PyExc_TypeError, - "exception causes must derive from " - "BaseException"); - goto bad; - } - PyException_SetCause(value, fixed_cause); - } - PyErr_SetObject(type, value); - if (tb) { -#if CYTHON_COMPILING_IN_PYPY - PyObject *tmp_type, *tmp_value, *tmp_tb; - PyErr_Fetch(&tmp_type, &tmp_value, &tmp_tb); - Py_INCREF(tb); - PyErr_Restore(tmp_type, tmp_value, tb); - Py_XDECREF(tmp_tb); -#else - PyThreadState *tstate = __Pyx_PyThreadState_Current; - PyObject* tmp_tb = tstate->curexc_traceback; - if (tb != tmp_tb) { - Py_INCREF(tb); - tstate->curexc_traceback = tb; - Py_XDECREF(tmp_tb); - } -#endif - } -bad: - Py_XDECREF(owned_instance); - return; -} -#endif - -/* GetItemInt */ -static PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j) { - PyObject *r; - if (!j) return NULL; - r = PyObject_GetItem(o, j); - Py_DECREF(j); - return r; -} -static CYTHON_INLINE PyObject *__Pyx_GetItemInt_List_Fast(PyObject *o, Py_ssize_t i, - CYTHON_NCP_UNUSED int wraparound, - CYTHON_NCP_UNUSED int boundscheck) { -#if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS - Py_ssize_t wrapped_i = i; - if (wraparound & unlikely(i < 0)) { - wrapped_i += PyList_GET_SIZE(o); - } - if ((!boundscheck) || likely(__Pyx_is_valid_index(wrapped_i, PyList_GET_SIZE(o)))) { - PyObject *r = PyList_GET_ITEM(o, wrapped_i); - Py_INCREF(r); - return r; - } - return __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i)); -#else - return PySequence_GetItem(o, i); -#endif -} -static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Tuple_Fast(PyObject *o, Py_ssize_t i, - CYTHON_NCP_UNUSED int wraparound, - CYTHON_NCP_UNUSED int boundscheck) { -#if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS - Py_ssize_t wrapped_i = i; - if (wraparound & unlikely(i < 0)) { - wrapped_i += PyTuple_GET_SIZE(o); - } - if ((!boundscheck) || likely(__Pyx_is_valid_index(wrapped_i, PyTuple_GET_SIZE(o)))) { - PyObject *r = PyTuple_GET_ITEM(o, wrapped_i); - Py_INCREF(r); - return r; - } - return __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i)); -#else - return PySequence_GetItem(o, i); -#endif -} -static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i, int is_list, - CYTHON_NCP_UNUSED int wraparound, - CYTHON_NCP_UNUSED int boundscheck) { -#if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS && CYTHON_USE_TYPE_SLOTS - if (is_list || PyList_CheckExact(o)) { - Py_ssize_t n = ((!wraparound) | likely(i >= 0)) ? i : i + PyList_GET_SIZE(o); - if ((!boundscheck) || (likely(__Pyx_is_valid_index(n, PyList_GET_SIZE(o))))) { - PyObject *r = PyList_GET_ITEM(o, n); - Py_INCREF(r); - return r; - } - } - else if (PyTuple_CheckExact(o)) { - Py_ssize_t n = ((!wraparound) | likely(i >= 0)) ? i : i + PyTuple_GET_SIZE(o); - if ((!boundscheck) || likely(__Pyx_is_valid_index(n, PyTuple_GET_SIZE(o)))) { - PyObject *r = PyTuple_GET_ITEM(o, n); - Py_INCREF(r); - return r; - } - } else { - PySequenceMethods *m = Py_TYPE(o)->tp_as_sequence; - if (likely(m && m->sq_item)) { - if (wraparound && unlikely(i < 0) && likely(m->sq_length)) { - Py_ssize_t l = m->sq_length(o); - if (likely(l >= 0)) { - i += l; - } else { - if (!PyErr_ExceptionMatches(PyExc_OverflowError)) - return NULL; - PyErr_Clear(); - } - } - return m->sq_item(o, i); - } - } -#else - if (is_list || PySequence_Check(o)) { - return PySequence_GetItem(o, i); - } -#endif - return __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i)); -} - -/* ObjectGetItem */ -#if CYTHON_USE_TYPE_SLOTS -static PyObject *__Pyx_PyObject_GetIndex(PyObject *obj, PyObject* index) { - PyObject *runerr; - Py_ssize_t key_value; - PySequenceMethods *m = Py_TYPE(obj)->tp_as_sequence; - if (unlikely(!(m && m->sq_item))) { - PyErr_Format(PyExc_TypeError, "'%.200s' object is not subscriptable", Py_TYPE(obj)->tp_name); - return NULL; - } - key_value = __Pyx_PyIndex_AsSsize_t(index); - if (likely(key_value != -1 || !(runerr = PyErr_Occurred()))) { - return __Pyx_GetItemInt_Fast(obj, key_value, 0, 1, 1); - } - if (PyErr_GivenExceptionMatches(runerr, PyExc_OverflowError)) { - PyErr_Clear(); - PyErr_Format(PyExc_IndexError, "cannot fit '%.200s' into an index-sized integer", Py_TYPE(index)->tp_name); - } - return NULL; -} -static PyObject *__Pyx_PyObject_GetItem(PyObject *obj, PyObject* key) { - PyMappingMethods *m = Py_TYPE(obj)->tp_as_mapping; - if (likely(m && m->mp_subscript)) { - return m->mp_subscript(obj, key); - } - return __Pyx_PyObject_GetIndex(obj, key); -} -#endif - -/* PyFunctionFastCall */ -#if CYTHON_FAST_PYCALL -static PyObject* __Pyx_PyFunction_FastCallNoKw(PyCodeObject *co, PyObject **args, Py_ssize_t na, - PyObject *globals) { - PyFrameObject *f; - PyThreadState *tstate = __Pyx_PyThreadState_Current; - PyObject **fastlocals; - Py_ssize_t i; - PyObject *result; - assert(globals != NULL); - /* XXX Perhaps we should create a specialized - PyFrame_New() that doesn't take locals, but does - take builtins without sanity checking them. - */ - assert(tstate != NULL); - f = PyFrame_New(tstate, co, globals, NULL); - if (f == NULL) { - return NULL; - } - fastlocals = __Pyx_PyFrame_GetLocalsplus(f); - for (i = 0; i < na; i++) { - Py_INCREF(*args); - fastlocals[i] = *args++; - } - result = PyEval_EvalFrameEx(f,0); - ++tstate->recursion_depth; - Py_DECREF(f); - --tstate->recursion_depth; - return result; -} -#if 1 || PY_VERSION_HEX < 0x030600B1 -static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs, PyObject *kwargs) { - PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func); - PyObject *globals = PyFunction_GET_GLOBALS(func); - PyObject *argdefs = PyFunction_GET_DEFAULTS(func); - PyObject *closure; -#if PY_MAJOR_VERSION >= 3 - PyObject *kwdefs; -#endif - PyObject *kwtuple, **k; - PyObject **d; - Py_ssize_t nd; - Py_ssize_t nk; - PyObject *result; - assert(kwargs == NULL || PyDict_Check(kwargs)); - nk = kwargs ? PyDict_Size(kwargs) : 0; - if (Py_EnterRecursiveCall((char*)" while calling a Python object")) { - return NULL; - } - if ( -#if PY_MAJOR_VERSION >= 3 - co->co_kwonlyargcount == 0 && -#endif - likely(kwargs == NULL || nk == 0) && - co->co_flags == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE)) { - if (argdefs == NULL && co->co_argcount == nargs) { - result = __Pyx_PyFunction_FastCallNoKw(co, args, nargs, globals); - goto done; - } - else if (nargs == 0 && argdefs != NULL - && co->co_argcount == Py_SIZE(argdefs)) { - /* function called with no arguments, but all parameters have - a default value: use default values as arguments .*/ - args = &PyTuple_GET_ITEM(argdefs, 0); - result =__Pyx_PyFunction_FastCallNoKw(co, args, Py_SIZE(argdefs), globals); - goto done; - } - } - if (kwargs != NULL) { - Py_ssize_t pos, i; - kwtuple = PyTuple_New(2 * nk); - if (kwtuple == NULL) { - result = NULL; - goto done; - } - k = &PyTuple_GET_ITEM(kwtuple, 0); - pos = i = 0; - while (PyDict_Next(kwargs, &pos, &k[i], &k[i+1])) { - Py_INCREF(k[i]); - Py_INCREF(k[i+1]); - i += 2; - } - nk = i / 2; - } - else { - kwtuple = NULL; - k = NULL; - } - closure = PyFunction_GET_CLOSURE(func); -#if PY_MAJOR_VERSION >= 3 - kwdefs = PyFunction_GET_KW_DEFAULTS(func); -#endif - if (argdefs != NULL) { - d = &PyTuple_GET_ITEM(argdefs, 0); - nd = Py_SIZE(argdefs); - } - else { - d = NULL; - nd = 0; - } -#if PY_MAJOR_VERSION >= 3 - result = PyEval_EvalCodeEx((PyObject*)co, globals, (PyObject *)NULL, - args, (int)nargs, - k, (int)nk, - d, (int)nd, kwdefs, closure); -#else - result = PyEval_EvalCodeEx(co, globals, (PyObject *)NULL, - args, (int)nargs, - k, (int)nk, - d, (int)nd, closure); -#endif - Py_XDECREF(kwtuple); -done: - Py_LeaveRecursiveCall(); - return result; -} -#endif -#endif - -/* PyObjectCallMethO */ -#if CYTHON_COMPILING_IN_CPYTHON -static CYTHON_INLINE PyObject* __Pyx_PyObject_CallMethO(PyObject *func, PyObject *arg) { - PyObject *self, *result; - PyCFunction cfunc; - cfunc = PyCFunction_GET_FUNCTION(func); - self = PyCFunction_GET_SELF(func); - if (unlikely(Py_EnterRecursiveCall((char*)" while calling a Python object"))) - return NULL; - result = cfunc(self, arg); - Py_LeaveRecursiveCall(); - if (unlikely(!result) && unlikely(!PyErr_Occurred())) { - PyErr_SetString( - PyExc_SystemError, - "NULL result without error in PyObject_Call"); - } - return result; -} -#endif - -/* PyObjectCallNoArg */ -#if CYTHON_COMPILING_IN_CPYTHON -static CYTHON_INLINE PyObject* __Pyx_PyObject_CallNoArg(PyObject *func) { -#if CYTHON_FAST_PYCALL - if (PyFunction_Check(func)) { - return __Pyx_PyFunction_FastCall(func, NULL, 0); - } -#endif -#ifdef __Pyx_CyFunction_USED - if (likely(PyCFunction_Check(func) || __Pyx_CyFunction_Check(func))) -#else - if (likely(PyCFunction_Check(func))) -#endif - { - if (likely(PyCFunction_GET_FLAGS(func) & METH_NOARGS)) { - return __Pyx_PyObject_CallMethO(func, NULL); - } - } - return __Pyx_PyObject_Call(func, __pyx_empty_tuple, NULL); -} -#endif - -/* PyCFunctionFastCall */ -#if CYTHON_FAST_PYCCALL -static CYTHON_INLINE PyObject * __Pyx_PyCFunction_FastCall(PyObject *func_obj, PyObject **args, Py_ssize_t nargs) { - PyCFunctionObject *func = (PyCFunctionObject*)func_obj; - PyCFunction meth = PyCFunction_GET_FUNCTION(func); - PyObject *self = PyCFunction_GET_SELF(func); - int flags = PyCFunction_GET_FLAGS(func); - assert(PyCFunction_Check(func)); - assert(METH_FASTCALL == (flags & ~(METH_CLASS | METH_STATIC | METH_COEXIST | METH_KEYWORDS | METH_STACKLESS))); - assert(nargs >= 0); - assert(nargs == 0 || args != NULL); - /* _PyCFunction_FastCallDict() must not be called with an exception set, - because it may clear it (directly or indirectly) and so the - caller loses its exception */ - assert(!PyErr_Occurred()); - if ((PY_VERSION_HEX < 0x030700A0) || unlikely(flags & METH_KEYWORDS)) { - return (*((__Pyx_PyCFunctionFastWithKeywords)(void*)meth)) (self, args, nargs, NULL); - } else { - return (*((__Pyx_PyCFunctionFast)(void*)meth)) (self, args, nargs); - } -} -#endif - -/* PyObjectCallOneArg */ -#if CYTHON_COMPILING_IN_CPYTHON -static PyObject* __Pyx__PyObject_CallOneArg(PyObject *func, PyObject *arg) { - PyObject *result; - PyObject *args = PyTuple_New(1); - if (unlikely(!args)) return NULL; - Py_INCREF(arg); - PyTuple_SET_ITEM(args, 0, arg); - result = __Pyx_PyObject_Call(func, args, NULL); - Py_DECREF(args); - return result; -} -static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg) { -#if CYTHON_FAST_PYCALL - if (PyFunction_Check(func)) { - return __Pyx_PyFunction_FastCall(func, &arg, 1); - } -#endif - if (likely(PyCFunction_Check(func))) { - if (likely(PyCFunction_GET_FLAGS(func) & METH_O)) { - return __Pyx_PyObject_CallMethO(func, arg); -#if CYTHON_FAST_PYCCALL - } else if (PyCFunction_GET_FLAGS(func) & METH_FASTCALL) { - return __Pyx_PyCFunction_FastCall(func, &arg, 1); -#endif - } - } - return __Pyx__PyObject_CallOneArg(func, arg); -} -#else -static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg) { - PyObject *result; - PyObject *args = PyTuple_Pack(1, arg); - if (unlikely(!args)) return NULL; - result = __Pyx_PyObject_Call(func, args, NULL); - Py_DECREF(args); - return result; -} -#endif - -/* PyIntCompare */ -static CYTHON_INLINE PyObject* __Pyx_PyInt_EqObjC(PyObject *op1, PyObject *op2, CYTHON_UNUSED long intval, CYTHON_UNUSED long inplace) { - if (op1 == op2) { - Py_RETURN_TRUE; - } - #if PY_MAJOR_VERSION < 3 - if (likely(PyInt_CheckExact(op1))) { - const long b = intval; - long a = PyInt_AS_LONG(op1); - if (a == b) Py_RETURN_TRUE; else Py_RETURN_FALSE; - } - #endif - #if CYTHON_USE_PYLONG_INTERNALS - if (likely(PyLong_CheckExact(op1))) { - int unequal; - unsigned long uintval; - Py_ssize_t size = Py_SIZE(op1); - const digit* digits = ((PyLongObject*)op1)->ob_digit; - if (intval == 0) { - if (size == 0) Py_RETURN_TRUE; else Py_RETURN_FALSE; - } else if (intval < 0) { - if (size >= 0) - Py_RETURN_FALSE; - intval = -intval; - size = -size; - } else { - if (size <= 0) - Py_RETURN_FALSE; - } - uintval = (unsigned long) intval; -#if PyLong_SHIFT * 4 < SIZEOF_LONG*8 - if (uintval >> (PyLong_SHIFT * 4)) { - unequal = (size != 5) || (digits[0] != (uintval & (unsigned long) PyLong_MASK)) - | (digits[1] != ((uintval >> (1 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK)) | (digits[2] != ((uintval >> (2 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK)) | (digits[3] != ((uintval >> (3 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK)) | (digits[4] != ((uintval >> (4 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK)); - } else -#endif -#if PyLong_SHIFT * 3 < SIZEOF_LONG*8 - if (uintval >> (PyLong_SHIFT * 3)) { - unequal = (size != 4) || (digits[0] != (uintval & (unsigned long) PyLong_MASK)) - | (digits[1] != ((uintval >> (1 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK)) | (digits[2] != ((uintval >> (2 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK)) | (digits[3] != ((uintval >> (3 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK)); - } else -#endif -#if PyLong_SHIFT * 2 < SIZEOF_LONG*8 - if (uintval >> (PyLong_SHIFT * 2)) { - unequal = (size != 3) || (digits[0] != (uintval & (unsigned long) PyLong_MASK)) - | (digits[1] != ((uintval >> (1 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK)) | (digits[2] != ((uintval >> (2 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK)); - } else -#endif -#if PyLong_SHIFT * 1 < SIZEOF_LONG*8 - if (uintval >> (PyLong_SHIFT * 1)) { - unequal = (size != 2) || (digits[0] != (uintval & (unsigned long) PyLong_MASK)) - | (digits[1] != ((uintval >> (1 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK)); - } else -#endif - unequal = (size != 1) || (((unsigned long) digits[0]) != (uintval & (unsigned long) PyLong_MASK)); - if (unequal == 0) Py_RETURN_TRUE; else Py_RETURN_FALSE; - } - #endif - if (PyFloat_CheckExact(op1)) { - const long b = intval; - double a = PyFloat_AS_DOUBLE(op1); - if ((double)a == (double)b) Py_RETURN_TRUE; else Py_RETURN_FALSE; - } - return ( - PyObject_RichCompare(op1, op2, Py_EQ)); -} - -/* PyObjectCall2Args */ -static CYTHON_UNUSED PyObject* __Pyx_PyObject_Call2Args(PyObject* function, PyObject* arg1, PyObject* arg2) { - PyObject *args, *result = NULL; - #if CYTHON_FAST_PYCALL - if (PyFunction_Check(function)) { - PyObject *args[2] = {arg1, arg2}; - return __Pyx_PyFunction_FastCall(function, args, 2); - } - #endif - #if CYTHON_FAST_PYCCALL - if (__Pyx_PyFastCFunction_Check(function)) { - PyObject *args[2] = {arg1, arg2}; - return __Pyx_PyCFunction_FastCall(function, args, 2); - } - #endif - args = PyTuple_New(2); - if (unlikely(!args)) goto done; - Py_INCREF(arg1); - PyTuple_SET_ITEM(args, 0, arg1); - Py_INCREF(arg2); - PyTuple_SET_ITEM(args, 1, arg2); - Py_INCREF(function); - result = __Pyx_PyObject_Call(function, args, NULL); - Py_DECREF(args); - Py_DECREF(function); -done: - return result; -} - -/* PyObjectGetMethod */ -static int __Pyx_PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **method) { - PyObject *attr; -#if CYTHON_UNPACK_METHODS && CYTHON_COMPILING_IN_CPYTHON && CYTHON_USE_PYTYPE_LOOKUP - PyTypeObject *tp = Py_TYPE(obj); - PyObject *descr; - descrgetfunc f = NULL; - PyObject **dictptr, *dict; - int meth_found = 0; - assert (*method == NULL); - if (unlikely(tp->tp_getattro != PyObject_GenericGetAttr)) { - attr = __Pyx_PyObject_GetAttrStr(obj, name); - goto try_unpack; - } - if (unlikely(tp->tp_dict == NULL) && unlikely(PyType_Ready(tp) < 0)) { - return 0; - } - descr = _PyType_Lookup(tp, name); - if (likely(descr != NULL)) { - Py_INCREF(descr); -#if PY_MAJOR_VERSION >= 3 - #ifdef __Pyx_CyFunction_USED - if (likely(PyFunction_Check(descr) || (Py_TYPE(descr) == &PyMethodDescr_Type) || __Pyx_CyFunction_Check(descr))) - #else - if (likely(PyFunction_Check(descr) || (Py_TYPE(descr) == &PyMethodDescr_Type))) - #endif -#else - #ifdef __Pyx_CyFunction_USED - if (likely(PyFunction_Check(descr) || __Pyx_CyFunction_Check(descr))) - #else - if (likely(PyFunction_Check(descr))) - #endif -#endif - { - meth_found = 1; - } else { - f = Py_TYPE(descr)->tp_descr_get; - if (f != NULL && PyDescr_IsData(descr)) { - attr = f(descr, obj, (PyObject *)Py_TYPE(obj)); - Py_DECREF(descr); - goto try_unpack; - } - } - } - dictptr = _PyObject_GetDictPtr(obj); - if (dictptr != NULL && (dict = *dictptr) != NULL) { - Py_INCREF(dict); - attr = __Pyx_PyDict_GetItemStr(dict, name); - if (attr != NULL) { - Py_INCREF(attr); - Py_DECREF(dict); - Py_XDECREF(descr); - goto try_unpack; - } - Py_DECREF(dict); - } - if (meth_found) { - *method = descr; - return 1; - } - if (f != NULL) { - attr = f(descr, obj, (PyObject *)Py_TYPE(obj)); - Py_DECREF(descr); - goto try_unpack; - } - if (descr != NULL) { - *method = descr; - return 0; - } - PyErr_Format(PyExc_AttributeError, -#if PY_MAJOR_VERSION >= 3 - "'%.50s' object has no attribute '%U'", - tp->tp_name, name); -#else - "'%.50s' object has no attribute '%.400s'", - tp->tp_name, PyString_AS_STRING(name)); -#endif - return 0; -#else - attr = __Pyx_PyObject_GetAttrStr(obj, name); - goto try_unpack; -#endif -try_unpack: -#if CYTHON_UNPACK_METHODS - if (likely(attr) && PyMethod_Check(attr) && likely(PyMethod_GET_SELF(attr) == obj)) { - PyObject *function = PyMethod_GET_FUNCTION(attr); - Py_INCREF(function); - Py_DECREF(attr); - *method = function; - return 1; - } -#endif - *method = attr; - return 0; -} - -/* PyObjectCallMethod1 */ -static PyObject* __Pyx__PyObject_CallMethod1(PyObject* method, PyObject* arg) { - PyObject *result = __Pyx_PyObject_CallOneArg(method, arg); - Py_DECREF(method); - return result; -} -static PyObject* __Pyx_PyObject_CallMethod1(PyObject* obj, PyObject* method_name, PyObject* arg) { - PyObject *method = NULL, *result; - int is_method = __Pyx_PyObject_GetMethod(obj, method_name, &method); - if (likely(is_method)) { - result = __Pyx_PyObject_Call2Args(method, obj, arg); - Py_DECREF(method); - return result; - } - if (unlikely(!method)) return NULL; - return __Pyx__PyObject_CallMethod1(method, arg); -} - -/* pop_index */ -static PyObject* __Pyx__PyObject_PopNewIndex(PyObject* L, PyObject* py_ix) { - PyObject *r; - if (unlikely(!py_ix)) return NULL; - r = __Pyx__PyObject_PopIndex(L, py_ix); - Py_DECREF(py_ix); - return r; -} -static PyObject* __Pyx__PyObject_PopIndex(PyObject* L, PyObject* py_ix) { - return __Pyx_PyObject_CallMethod1(L, __pyx_n_s_pop, py_ix); -} -#if CYTHON_USE_PYLIST_INTERNALS && CYTHON_ASSUME_SAFE_MACROS -static PyObject* __Pyx__PyList_PopIndex(PyObject* L, PyObject* py_ix, Py_ssize_t ix) { - Py_ssize_t size = PyList_GET_SIZE(L); - if (likely(size > (((PyListObject*)L)->allocated >> 1))) { - Py_ssize_t cix = ix; - if (cix < 0) { - cix += size; - } - if (likely(__Pyx_is_valid_index(cix, size))) { - PyObject* v = PyList_GET_ITEM(L, cix); - __Pyx_SET_SIZE(L, Py_SIZE(L) - 1); - size -= 1; - memmove(&PyList_GET_ITEM(L, cix), &PyList_GET_ITEM(L, cix+1), (size_t)(size-cix)*sizeof(PyObject*)); - return v; - } - } - if (py_ix == Py_None) { - return __Pyx__PyObject_PopNewIndex(L, PyInt_FromSsize_t(ix)); - } else { - return __Pyx__PyObject_PopIndex(L, py_ix); - } -} -#endif - -/* PyErrExceptionMatches */ -#if CYTHON_FAST_THREAD_STATE -static int __Pyx_PyErr_ExceptionMatchesTuple(PyObject *exc_type, PyObject *tuple) { - Py_ssize_t i, n; - n = PyTuple_GET_SIZE(tuple); -#if PY_MAJOR_VERSION >= 3 - for (i=0; icurexc_type; - if (exc_type == err) return 1; - if (unlikely(!exc_type)) return 0; - if (unlikely(PyTuple_Check(err))) - return __Pyx_PyErr_ExceptionMatchesTuple(exc_type, err); - return __Pyx_PyErr_GivenExceptionMatches(exc_type, err); -} -#endif - -/* GetAttr */ -static CYTHON_INLINE PyObject *__Pyx_GetAttr(PyObject *o, PyObject *n) { -#if CYTHON_USE_TYPE_SLOTS -#if PY_MAJOR_VERSION >= 3 - if (likely(PyUnicode_Check(n))) -#else - if (likely(PyString_Check(n))) -#endif - return __Pyx_PyObject_GetAttrStr(o, n); -#endif - return PyObject_GetAttr(o, n); -} - -/* GetAttr3 */ -static PyObject *__Pyx_GetAttr3Default(PyObject *d) { - __Pyx_PyThreadState_declare - __Pyx_PyThreadState_assign - if (unlikely(!__Pyx_PyErr_ExceptionMatches(PyExc_AttributeError))) - return NULL; - __Pyx_PyErr_Clear(); - Py_INCREF(d); - return d; -} -static CYTHON_INLINE PyObject *__Pyx_GetAttr3(PyObject *o, PyObject *n, PyObject *d) { - PyObject *r = __Pyx_GetAttr(o, n); - return (likely(r)) ? r : __Pyx_GetAttr3Default(d); -} - -/* PyDictVersioning */ -#if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_TYPE_SLOTS -static CYTHON_INLINE PY_UINT64_T __Pyx_get_tp_dict_version(PyObject *obj) { - PyObject *dict = Py_TYPE(obj)->tp_dict; - return likely(dict) ? __PYX_GET_DICT_VERSION(dict) : 0; -} -static CYTHON_INLINE PY_UINT64_T __Pyx_get_object_dict_version(PyObject *obj) { - PyObject **dictptr = NULL; - Py_ssize_t offset = Py_TYPE(obj)->tp_dictoffset; - if (offset) { -#if CYTHON_COMPILING_IN_CPYTHON - dictptr = (likely(offset > 0)) ? (PyObject **) ((char *)obj + offset) : _PyObject_GetDictPtr(obj); -#else - dictptr = _PyObject_GetDictPtr(obj); -#endif - } - return (dictptr && *dictptr) ? __PYX_GET_DICT_VERSION(*dictptr) : 0; -} -static CYTHON_INLINE int __Pyx_object_dict_version_matches(PyObject* obj, PY_UINT64_T tp_dict_version, PY_UINT64_T obj_dict_version) { - PyObject *dict = Py_TYPE(obj)->tp_dict; - if (unlikely(!dict) || unlikely(tp_dict_version != __PYX_GET_DICT_VERSION(dict))) - return 0; - return obj_dict_version == __Pyx_get_object_dict_version(obj); -} -#endif - -/* GetModuleGlobalName */ -#if CYTHON_USE_DICT_VERSIONS -static PyObject *__Pyx__GetModuleGlobalName(PyObject *name, PY_UINT64_T *dict_version, PyObject **dict_cached_value) -#else -static CYTHON_INLINE PyObject *__Pyx__GetModuleGlobalName(PyObject *name) -#endif -{ - PyObject *result; -#if !CYTHON_AVOID_BORROWED_REFS -#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030500A1 - result = _PyDict_GetItem_KnownHash(__pyx_d, name, ((PyASCIIObject *) name)->hash); - __PYX_UPDATE_DICT_CACHE(__pyx_d, result, *dict_cached_value, *dict_version) - if (likely(result)) { - return __Pyx_NewRef(result); - } else if (unlikely(PyErr_Occurred())) { - return NULL; - } -#else - result = PyDict_GetItem(__pyx_d, name); - __PYX_UPDATE_DICT_CACHE(__pyx_d, result, *dict_cached_value, *dict_version) - if (likely(result)) { - return __Pyx_NewRef(result); - } -#endif -#else - result = PyObject_GetItem(__pyx_d, name); - __PYX_UPDATE_DICT_CACHE(__pyx_d, result, *dict_cached_value, *dict_version) - if (likely(result)) { - return __Pyx_NewRef(result); - } - PyErr_Clear(); -#endif - return __Pyx_GetBuiltinName(name); -} - -/* Import */ -static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, int level) { - PyObject *empty_list = 0; - PyObject *module = 0; - PyObject *global_dict = 0; - PyObject *empty_dict = 0; - PyObject *list; - #if PY_MAJOR_VERSION < 3 - PyObject *py_import; - py_import = __Pyx_PyObject_GetAttrStr(__pyx_b, __pyx_n_s_import); - if (!py_import) - goto bad; - #endif - if (from_list) - list = from_list; - else { - empty_list = PyList_New(0); - if (!empty_list) - goto bad; - list = empty_list; - } - global_dict = PyModule_GetDict(__pyx_m); - if (!global_dict) - goto bad; - empty_dict = PyDict_New(); - if (!empty_dict) - goto bad; - { - #if PY_MAJOR_VERSION >= 3 - if (level == -1) { - if ((1) && (strchr(__Pyx_MODULE_NAME, '.'))) { - module = PyImport_ImportModuleLevelObject( - name, global_dict, empty_dict, list, 1); - if (!module) { - if (!PyErr_ExceptionMatches(PyExc_ImportError)) - goto bad; - PyErr_Clear(); - } - } - level = 0; - } - #endif - if (!module) { - #if PY_MAJOR_VERSION < 3 - PyObject *py_level = PyInt_FromLong(level); - if (!py_level) - goto bad; - module = PyObject_CallFunctionObjArgs(py_import, - name, global_dict, empty_dict, list, py_level, (PyObject *)NULL); - Py_DECREF(py_level); - #else - module = PyImport_ImportModuleLevelObject( - name, global_dict, empty_dict, list, level); - #endif - } - } -bad: - #if PY_MAJOR_VERSION < 3 - Py_XDECREF(py_import); - #endif - Py_XDECREF(empty_list); - Py_XDECREF(empty_dict); - return module; -} - -/* ImportFrom */ -static PyObject* __Pyx_ImportFrom(PyObject* module, PyObject* name) { - PyObject* value = __Pyx_PyObject_GetAttrStr(module, name); - if (unlikely(!value) && PyErr_ExceptionMatches(PyExc_AttributeError)) { - PyErr_Format(PyExc_ImportError, - #if PY_MAJOR_VERSION < 3 - "cannot import name %.230s", PyString_AS_STRING(name)); - #else - "cannot import name %S", name); - #endif - } - return value; -} - -/* HasAttr */ -static CYTHON_INLINE int __Pyx_HasAttr(PyObject *o, PyObject *n) { - PyObject *r; - if (unlikely(!__Pyx_PyBaseString_Check(n))) { - PyErr_SetString(PyExc_TypeError, - "hasattr(): attribute name must be string"); - return -1; - } - r = __Pyx_GetAttr(o, n); - if (unlikely(!r)) { - PyErr_Clear(); - return 0; - } else { - Py_DECREF(r); - return 1; - } -} - -/* PyObject_GenericGetAttrNoDict */ -#if CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP && PY_VERSION_HEX < 0x03070000 -static PyObject *__Pyx_RaiseGenericGetAttributeError(PyTypeObject *tp, PyObject *attr_name) { - PyErr_Format(PyExc_AttributeError, -#if PY_MAJOR_VERSION >= 3 - "'%.50s' object has no attribute '%U'", - tp->tp_name, attr_name); -#else - "'%.50s' object has no attribute '%.400s'", - tp->tp_name, PyString_AS_STRING(attr_name)); -#endif - return NULL; -} -static CYTHON_INLINE PyObject* __Pyx_PyObject_GenericGetAttrNoDict(PyObject* obj, PyObject* attr_name) { - PyObject *descr; - PyTypeObject *tp = Py_TYPE(obj); - if (unlikely(!PyString_Check(attr_name))) { - return PyObject_GenericGetAttr(obj, attr_name); - } - assert(!tp->tp_dictoffset); - descr = _PyType_Lookup(tp, attr_name); - if (unlikely(!descr)) { - return __Pyx_RaiseGenericGetAttributeError(tp, attr_name); - } - Py_INCREF(descr); - #if PY_MAJOR_VERSION < 3 - if (likely(PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_HAVE_CLASS))) - #endif - { - descrgetfunc f = Py_TYPE(descr)->tp_descr_get; - if (unlikely(f)) { - PyObject *res = f(descr, obj, (PyObject *)tp); - Py_DECREF(descr); - return res; - } - } - return descr; -} -#endif - -/* PyObject_GenericGetAttr */ -#if CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP && PY_VERSION_HEX < 0x03070000 -static PyObject* __Pyx_PyObject_GenericGetAttr(PyObject* obj, PyObject* attr_name) { - if (unlikely(Py_TYPE(obj)->tp_dictoffset)) { - return PyObject_GenericGetAttr(obj, attr_name); - } - return __Pyx_PyObject_GenericGetAttrNoDict(obj, attr_name); -} -#endif - -/* SetVTable */ -static int __Pyx_SetVtable(PyObject *dict, void *vtable) { -#if PY_VERSION_HEX >= 0x02070000 - PyObject *ob = PyCapsule_New(vtable, 0, 0); -#else - PyObject *ob = PyCObject_FromVoidPtr(vtable, 0); -#endif - if (!ob) - goto bad; - if (PyDict_SetItem(dict, __pyx_n_s_pyx_vtable, ob) < 0) - goto bad; - Py_DECREF(ob); - return 0; -bad: - Py_XDECREF(ob); - return -1; -} - -/* PyObjectGetAttrStrNoError */ -static void __Pyx_PyObject_GetAttrStr_ClearAttributeError(void) { - __Pyx_PyThreadState_declare - __Pyx_PyThreadState_assign - if (likely(__Pyx_PyErr_ExceptionMatches(PyExc_AttributeError))) - __Pyx_PyErr_Clear(); -} -static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStrNoError(PyObject* obj, PyObject* attr_name) { - PyObject *result; -#if CYTHON_COMPILING_IN_CPYTHON && CYTHON_USE_TYPE_SLOTS && PY_VERSION_HEX >= 0x030700B1 - PyTypeObject* tp = Py_TYPE(obj); - if (likely(tp->tp_getattro == PyObject_GenericGetAttr)) { - return _PyObject_GenericGetAttrWithDict(obj, attr_name, NULL, 1); - } -#endif - result = __Pyx_PyObject_GetAttrStr(obj, attr_name); - if (unlikely(!result)) { - __Pyx_PyObject_GetAttrStr_ClearAttributeError(); - } - return result; -} - -/* SetupReduce */ -static int __Pyx_setup_reduce_is_named(PyObject* meth, PyObject* name) { - int ret; - PyObject *name_attr; - name_attr = __Pyx_PyObject_GetAttrStr(meth, __pyx_n_s_name); - if (likely(name_attr)) { - ret = PyObject_RichCompareBool(name_attr, name, Py_EQ); - } else { - ret = -1; - } - if (unlikely(ret < 0)) { - PyErr_Clear(); - ret = 0; - } - Py_XDECREF(name_attr); - return ret; -} -static int __Pyx_setup_reduce(PyObject* type_obj) { - int ret = 0; - PyObject *object_reduce = NULL; - PyObject *object_reduce_ex = NULL; - PyObject *reduce = NULL; - PyObject *reduce_ex = NULL; - PyObject *reduce_cython = NULL; - PyObject *setstate = NULL; - PyObject *setstate_cython = NULL; -#if CYTHON_USE_PYTYPE_LOOKUP - if (_PyType_Lookup((PyTypeObject*)type_obj, __pyx_n_s_getstate)) goto __PYX_GOOD; -#else - if (PyObject_HasAttr(type_obj, __pyx_n_s_getstate)) goto __PYX_GOOD; -#endif -#if CYTHON_USE_PYTYPE_LOOKUP - object_reduce_ex = _PyType_Lookup(&PyBaseObject_Type, __pyx_n_s_reduce_ex); if (!object_reduce_ex) goto __PYX_BAD; -#else - object_reduce_ex = __Pyx_PyObject_GetAttrStr((PyObject*)&PyBaseObject_Type, __pyx_n_s_reduce_ex); if (!object_reduce_ex) goto __PYX_BAD; -#endif - reduce_ex = __Pyx_PyObject_GetAttrStr(type_obj, __pyx_n_s_reduce_ex); if (unlikely(!reduce_ex)) goto __PYX_BAD; - if (reduce_ex == object_reduce_ex) { -#if CYTHON_USE_PYTYPE_LOOKUP - object_reduce = _PyType_Lookup(&PyBaseObject_Type, __pyx_n_s_reduce); if (!object_reduce) goto __PYX_BAD; -#else - object_reduce = __Pyx_PyObject_GetAttrStr((PyObject*)&PyBaseObject_Type, __pyx_n_s_reduce); if (!object_reduce) goto __PYX_BAD; -#endif - reduce = __Pyx_PyObject_GetAttrStr(type_obj, __pyx_n_s_reduce); if (unlikely(!reduce)) goto __PYX_BAD; - if (reduce == object_reduce || __Pyx_setup_reduce_is_named(reduce, __pyx_n_s_reduce_cython)) { - reduce_cython = __Pyx_PyObject_GetAttrStrNoError(type_obj, __pyx_n_s_reduce_cython); - if (likely(reduce_cython)) { - ret = PyDict_SetItem(((PyTypeObject*)type_obj)->tp_dict, __pyx_n_s_reduce, reduce_cython); if (unlikely(ret < 0)) goto __PYX_BAD; - ret = PyDict_DelItem(((PyTypeObject*)type_obj)->tp_dict, __pyx_n_s_reduce_cython); if (unlikely(ret < 0)) goto __PYX_BAD; - } else if (reduce == object_reduce || PyErr_Occurred()) { - goto __PYX_BAD; - } - setstate = __Pyx_PyObject_GetAttrStr(type_obj, __pyx_n_s_setstate); - if (!setstate) PyErr_Clear(); - if (!setstate || __Pyx_setup_reduce_is_named(setstate, __pyx_n_s_setstate_cython)) { - setstate_cython = __Pyx_PyObject_GetAttrStrNoError(type_obj, __pyx_n_s_setstate_cython); - if (likely(setstate_cython)) { - ret = PyDict_SetItem(((PyTypeObject*)type_obj)->tp_dict, __pyx_n_s_setstate, setstate_cython); if (unlikely(ret < 0)) goto __PYX_BAD; - ret = PyDict_DelItem(((PyTypeObject*)type_obj)->tp_dict, __pyx_n_s_setstate_cython); if (unlikely(ret < 0)) goto __PYX_BAD; - } else if (!setstate || PyErr_Occurred()) { - goto __PYX_BAD; - } - } - PyType_Modified((PyTypeObject*)type_obj); - } - } - goto __PYX_GOOD; -__PYX_BAD: - if (!PyErr_Occurred()) - PyErr_Format(PyExc_RuntimeError, "Unable to initialize pickling for %s", ((PyTypeObject*)type_obj)->tp_name); - ret = -1; -__PYX_GOOD: -#if !CYTHON_USE_PYTYPE_LOOKUP - Py_XDECREF(object_reduce); - Py_XDECREF(object_reduce_ex); -#endif - Py_XDECREF(reduce); - Py_XDECREF(reduce_ex); - Py_XDECREF(reduce_cython); - Py_XDECREF(setstate); - Py_XDECREF(setstate_cython); - return ret; -} - -/* CLineInTraceback */ -#ifndef CYTHON_CLINE_IN_TRACEBACK -static int __Pyx_CLineForTraceback(CYTHON_NCP_UNUSED PyThreadState *tstate, int c_line) { - PyObject *use_cline; - PyObject *ptype, *pvalue, *ptraceback; -#if CYTHON_COMPILING_IN_CPYTHON - PyObject **cython_runtime_dict; -#endif - if (unlikely(!__pyx_cython_runtime)) { - return c_line; - } - __Pyx_ErrFetchInState(tstate, &ptype, &pvalue, &ptraceback); -#if CYTHON_COMPILING_IN_CPYTHON - cython_runtime_dict = _PyObject_GetDictPtr(__pyx_cython_runtime); - if (likely(cython_runtime_dict)) { - __PYX_PY_DICT_LOOKUP_IF_MODIFIED( - use_cline, *cython_runtime_dict, - __Pyx_PyDict_GetItemStr(*cython_runtime_dict, __pyx_n_s_cline_in_traceback)) - } else -#endif - { - PyObject *use_cline_obj = __Pyx_PyObject_GetAttrStr(__pyx_cython_runtime, __pyx_n_s_cline_in_traceback); - if (use_cline_obj) { - use_cline = PyObject_Not(use_cline_obj) ? Py_False : Py_True; - Py_DECREF(use_cline_obj); - } else { - PyErr_Clear(); - use_cline = NULL; - } - } - if (!use_cline) { - c_line = 0; - PyObject_SetAttr(__pyx_cython_runtime, __pyx_n_s_cline_in_traceback, Py_False); - } - else if (use_cline == Py_False || (use_cline != Py_True && PyObject_Not(use_cline) != 0)) { - c_line = 0; - } - __Pyx_ErrRestoreInState(tstate, ptype, pvalue, ptraceback); - return c_line; -} -#endif - -/* CodeObjectCache */ -static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line) { - int start = 0, mid = 0, end = count - 1; - if (end >= 0 && code_line > entries[end].code_line) { - return count; - } - while (start < end) { - mid = start + (end - start) / 2; - if (code_line < entries[mid].code_line) { - end = mid; - } else if (code_line > entries[mid].code_line) { - start = mid + 1; - } else { - return mid; - } - } - if (code_line <= entries[mid].code_line) { - return mid; - } else { - return mid + 1; - } -} -static PyCodeObject *__pyx_find_code_object(int code_line) { - PyCodeObject* code_object; - int pos; - if (unlikely(!code_line) || unlikely(!__pyx_code_cache.entries)) { - return NULL; - } - pos = __pyx_bisect_code_objects(__pyx_code_cache.entries, __pyx_code_cache.count, code_line); - if (unlikely(pos >= __pyx_code_cache.count) || unlikely(__pyx_code_cache.entries[pos].code_line != code_line)) { - return NULL; - } - code_object = __pyx_code_cache.entries[pos].code_object; - Py_INCREF(code_object); - return code_object; -} -static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object) { - int pos, i; - __Pyx_CodeObjectCacheEntry* entries = __pyx_code_cache.entries; - if (unlikely(!code_line)) { - return; - } - if (unlikely(!entries)) { - entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Malloc(64*sizeof(__Pyx_CodeObjectCacheEntry)); - if (likely(entries)) { - __pyx_code_cache.entries = entries; - __pyx_code_cache.max_count = 64; - __pyx_code_cache.count = 1; - entries[0].code_line = code_line; - entries[0].code_object = code_object; - Py_INCREF(code_object); - } - return; - } - pos = __pyx_bisect_code_objects(__pyx_code_cache.entries, __pyx_code_cache.count, code_line); - if ((pos < __pyx_code_cache.count) && unlikely(__pyx_code_cache.entries[pos].code_line == code_line)) { - PyCodeObject* tmp = entries[pos].code_object; - entries[pos].code_object = code_object; - Py_DECREF(tmp); - return; - } - if (__pyx_code_cache.count == __pyx_code_cache.max_count) { - int new_max = __pyx_code_cache.max_count + 64; - entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Realloc( - __pyx_code_cache.entries, ((size_t)new_max) * sizeof(__Pyx_CodeObjectCacheEntry)); - if (unlikely(!entries)) { - return; - } - __pyx_code_cache.entries = entries; - __pyx_code_cache.max_count = new_max; - } - for (i=__pyx_code_cache.count; i>pos; i--) { - entries[i] = entries[i-1]; - } - entries[pos].code_line = code_line; - entries[pos].code_object = code_object; - __pyx_code_cache.count++; - Py_INCREF(code_object); -} - -/* AddTraceback */ -#include "compile.h" -#include "frameobject.h" -#include "traceback.h" -static PyCodeObject* __Pyx_CreateCodeObjectForTraceback( - const char *funcname, int c_line, - int py_line, const char *filename) { - PyCodeObject *py_code = 0; - PyObject *py_srcfile = 0; - PyObject *py_funcname = 0; - #if PY_MAJOR_VERSION < 3 - py_srcfile = PyString_FromString(filename); - #else - py_srcfile = PyUnicode_FromString(filename); - #endif - if (!py_srcfile) goto bad; - if (c_line) { - #if PY_MAJOR_VERSION < 3 - py_funcname = PyString_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line); - #else - py_funcname = PyUnicode_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line); - #endif - } - else { - #if PY_MAJOR_VERSION < 3 - py_funcname = PyString_FromString(funcname); - #else - py_funcname = PyUnicode_FromString(funcname); - #endif - } - if (!py_funcname) goto bad; - py_code = __Pyx_PyCode_New( - 0, - 0, - 0, - 0, - 0, - __pyx_empty_bytes, /*PyObject *code,*/ - __pyx_empty_tuple, /*PyObject *consts,*/ - __pyx_empty_tuple, /*PyObject *names,*/ - __pyx_empty_tuple, /*PyObject *varnames,*/ - __pyx_empty_tuple, /*PyObject *freevars,*/ - __pyx_empty_tuple, /*PyObject *cellvars,*/ - py_srcfile, /*PyObject *filename,*/ - py_funcname, /*PyObject *name,*/ - py_line, - __pyx_empty_bytes /*PyObject *lnotab*/ - ); - Py_DECREF(py_srcfile); - Py_DECREF(py_funcname); - return py_code; -bad: - Py_XDECREF(py_srcfile); - Py_XDECREF(py_funcname); - return NULL; -} -static void __Pyx_AddTraceback(const char *funcname, int c_line, - int py_line, const char *filename) { - PyCodeObject *py_code = 0; - PyFrameObject *py_frame = 0; - PyThreadState *tstate = __Pyx_PyThreadState_Current; - if (c_line) { - c_line = __Pyx_CLineForTraceback(tstate, c_line); - } - py_code = __pyx_find_code_object(c_line ? -c_line : py_line); - if (!py_code) { - py_code = __Pyx_CreateCodeObjectForTraceback( - funcname, c_line, py_line, filename); - if (!py_code) goto bad; - __pyx_insert_code_object(c_line ? -c_line : py_line, py_code); - } - py_frame = PyFrame_New( - tstate, /*PyThreadState *tstate,*/ - py_code, /*PyCodeObject *code,*/ - __pyx_d, /*PyObject *globals,*/ - 0 /*PyObject *locals*/ - ); - if (!py_frame) goto bad; - __Pyx_PyFrame_SetLineNumber(py_frame, py_line); - PyTraceBack_Here(py_frame); -bad: - Py_XDECREF(py_code); - Py_XDECREF(py_frame); -} - -/* CIntToPy */ -static CYTHON_INLINE PyObject* __Pyx_PyInt_From_int(int value) { - const int neg_one = (int) ((int) 0 - (int) 1), const_zero = (int) 0; - const int is_unsigned = neg_one > const_zero; - if (is_unsigned) { - if (sizeof(int) < sizeof(long)) { - return PyInt_FromLong((long) value); - } else if (sizeof(int) <= sizeof(unsigned long)) { - return PyLong_FromUnsignedLong((unsigned long) value); -#ifdef HAVE_LONG_LONG - } else if (sizeof(int) <= sizeof(unsigned PY_LONG_LONG)) { - return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value); -#endif - } - } else { - if (sizeof(int) <= sizeof(long)) { - return PyInt_FromLong((long) value); -#ifdef HAVE_LONG_LONG - } else if (sizeof(int) <= sizeof(PY_LONG_LONG)) { - return PyLong_FromLongLong((PY_LONG_LONG) value); -#endif - } - } - { - int one = 1; int little = (int)*(unsigned char *)&one; - unsigned char *bytes = (unsigned char *)&value; - return _PyLong_FromByteArray(bytes, sizeof(int), - little, !is_unsigned); - } -} - -/* CIntFromPyVerify */ -#define __PYX_VERIFY_RETURN_INT(target_type, func_type, func_value)\ - __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, 0) -#define __PYX_VERIFY_RETURN_INT_EXC(target_type, func_type, func_value)\ - __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, 1) -#define __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, exc)\ - {\ - func_type value = func_value;\ - if (sizeof(target_type) < sizeof(func_type)) {\ - if (unlikely(value != (func_type) (target_type) value)) {\ - func_type zero = 0;\ - if (exc && unlikely(value == (func_type)-1 && PyErr_Occurred()))\ - return (target_type) -1;\ - if (is_unsigned && unlikely(value < zero))\ - goto raise_neg_overflow;\ - else\ - goto raise_overflow;\ - }\ - }\ - return (target_type) value;\ - } - -/* CIntToPy */ -static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value) { - const long neg_one = (long) ((long) 0 - (long) 1), const_zero = (long) 0; - const int is_unsigned = neg_one > const_zero; - if (is_unsigned) { - if (sizeof(long) < sizeof(long)) { - return PyInt_FromLong((long) value); - } else if (sizeof(long) <= sizeof(unsigned long)) { - return PyLong_FromUnsignedLong((unsigned long) value); -#ifdef HAVE_LONG_LONG - } else if (sizeof(long) <= sizeof(unsigned PY_LONG_LONG)) { - return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value); -#endif - } - } else { - if (sizeof(long) <= sizeof(long)) { - return PyInt_FromLong((long) value); -#ifdef HAVE_LONG_LONG - } else if (sizeof(long) <= sizeof(PY_LONG_LONG)) { - return PyLong_FromLongLong((PY_LONG_LONG) value); -#endif - } - } - { - int one = 1; int little = (int)*(unsigned char *)&one; - unsigned char *bytes = (unsigned char *)&value; - return _PyLong_FromByteArray(bytes, sizeof(long), - little, !is_unsigned); - } -} - -/* CIntFromPy */ -static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *x) { - const long neg_one = (long) ((long) 0 - (long) 1), const_zero = (long) 0; - const int is_unsigned = neg_one > const_zero; -#if PY_MAJOR_VERSION < 3 - if (likely(PyInt_Check(x))) { - if (sizeof(long) < sizeof(long)) { - __PYX_VERIFY_RETURN_INT(long, long, PyInt_AS_LONG(x)) - } else { - long val = PyInt_AS_LONG(x); - if (is_unsigned && unlikely(val < 0)) { - goto raise_neg_overflow; - } - return (long) val; - } - } else -#endif - if (likely(PyLong_Check(x))) { - if (is_unsigned) { -#if CYTHON_USE_PYLONG_INTERNALS - const digit* digits = ((PyLongObject*)x)->ob_digit; - switch (Py_SIZE(x)) { - case 0: return (long) 0; - case 1: __PYX_VERIFY_RETURN_INT(long, digit, digits[0]) - case 2: - if (8 * sizeof(long) > 1 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(long) >= 2 * PyLong_SHIFT) { - return (long) (((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); - } - } - break; - case 3: - if (8 * sizeof(long) > 2 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(long) >= 3 * PyLong_SHIFT) { - return (long) (((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); - } - } - break; - case 4: - if (8 * sizeof(long) > 3 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(long) >= 4 * PyLong_SHIFT) { - return (long) (((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); - } - } - break; - } -#endif -#if CYTHON_COMPILING_IN_CPYTHON - if (unlikely(Py_SIZE(x) < 0)) { - goto raise_neg_overflow; - } -#else - { - int result = PyObject_RichCompareBool(x, Py_False, Py_LT); - if (unlikely(result < 0)) - return (long) -1; - if (unlikely(result == 1)) - goto raise_neg_overflow; - } -#endif - if (sizeof(long) <= sizeof(unsigned long)) { - __PYX_VERIFY_RETURN_INT_EXC(long, unsigned long, PyLong_AsUnsignedLong(x)) -#ifdef HAVE_LONG_LONG - } else if (sizeof(long) <= sizeof(unsigned PY_LONG_LONG)) { - __PYX_VERIFY_RETURN_INT_EXC(long, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x)) -#endif - } - } else { -#if CYTHON_USE_PYLONG_INTERNALS - const digit* digits = ((PyLongObject*)x)->ob_digit; - switch (Py_SIZE(x)) { - case 0: return (long) 0; - case -1: __PYX_VERIFY_RETURN_INT(long, sdigit, (sdigit) (-(sdigit)digits[0])) - case 1: __PYX_VERIFY_RETURN_INT(long, digit, +digits[0]) - case -2: - if (8 * sizeof(long) - 1 > 1 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { - return (long) (((long)-1)*(((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); - } - } - break; - case 2: - if (8 * sizeof(long) > 1 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { - return (long) ((((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); - } - } - break; - case -3: - if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { - return (long) (((long)-1)*(((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); - } - } - break; - case 3: - if (8 * sizeof(long) > 2 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { - return (long) ((((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); - } - } - break; - case -4: - if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(long) - 1 > 4 * PyLong_SHIFT) { - return (long) (((long)-1)*(((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); - } - } - break; - case 4: - if (8 * sizeof(long) > 3 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(long) - 1 > 4 * PyLong_SHIFT) { - return (long) ((((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); - } - } - break; - } -#endif - if (sizeof(long) <= sizeof(long)) { - __PYX_VERIFY_RETURN_INT_EXC(long, long, PyLong_AsLong(x)) -#ifdef HAVE_LONG_LONG - } else if (sizeof(long) <= sizeof(PY_LONG_LONG)) { - __PYX_VERIFY_RETURN_INT_EXC(long, PY_LONG_LONG, PyLong_AsLongLong(x)) -#endif - } - } - { -#if CYTHON_COMPILING_IN_PYPY && !defined(_PyLong_AsByteArray) - PyErr_SetString(PyExc_RuntimeError, - "_PyLong_AsByteArray() not available in PyPy, cannot convert large numbers"); -#else - long val; - PyObject *v = __Pyx_PyNumber_IntOrLong(x); - #if PY_MAJOR_VERSION < 3 - if (likely(v) && !PyLong_Check(v)) { - PyObject *tmp = v; - v = PyNumber_Long(tmp); - Py_DECREF(tmp); - } - #endif - if (likely(v)) { - int one = 1; int is_little = (int)*(unsigned char *)&one; - unsigned char *bytes = (unsigned char *)&val; - int ret = _PyLong_AsByteArray((PyLongObject *)v, - bytes, sizeof(val), - is_little, !is_unsigned); - Py_DECREF(v); - if (likely(!ret)) - return val; - } -#endif - return (long) -1; - } - } else { - long val; - PyObject *tmp = __Pyx_PyNumber_IntOrLong(x); - if (!tmp) return (long) -1; - val = __Pyx_PyInt_As_long(tmp); - Py_DECREF(tmp); - return val; - } -raise_overflow: - PyErr_SetString(PyExc_OverflowError, - "value too large to convert to long"); - return (long) -1; -raise_neg_overflow: - PyErr_SetString(PyExc_OverflowError, - "can't convert negative value to long"); - return (long) -1; -} - -/* CIntFromPy */ -static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *x) { - const int neg_one = (int) ((int) 0 - (int) 1), const_zero = (int) 0; - const int is_unsigned = neg_one > const_zero; -#if PY_MAJOR_VERSION < 3 - if (likely(PyInt_Check(x))) { - if (sizeof(int) < sizeof(long)) { - __PYX_VERIFY_RETURN_INT(int, long, PyInt_AS_LONG(x)) - } else { - long val = PyInt_AS_LONG(x); - if (is_unsigned && unlikely(val < 0)) { - goto raise_neg_overflow; - } - return (int) val; - } - } else -#endif - if (likely(PyLong_Check(x))) { - if (is_unsigned) { -#if CYTHON_USE_PYLONG_INTERNALS - const digit* digits = ((PyLongObject*)x)->ob_digit; - switch (Py_SIZE(x)) { - case 0: return (int) 0; - case 1: __PYX_VERIFY_RETURN_INT(int, digit, digits[0]) - case 2: - if (8 * sizeof(int) > 1 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(int) >= 2 * PyLong_SHIFT) { - return (int) (((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); - } - } - break; - case 3: - if (8 * sizeof(int) > 2 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(int) >= 3 * PyLong_SHIFT) { - return (int) (((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); - } - } - break; - case 4: - if (8 * sizeof(int) > 3 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(int) >= 4 * PyLong_SHIFT) { - return (int) (((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); - } - } - break; - } -#endif -#if CYTHON_COMPILING_IN_CPYTHON - if (unlikely(Py_SIZE(x) < 0)) { - goto raise_neg_overflow; - } -#else - { - int result = PyObject_RichCompareBool(x, Py_False, Py_LT); - if (unlikely(result < 0)) - return (int) -1; - if (unlikely(result == 1)) - goto raise_neg_overflow; - } -#endif - if (sizeof(int) <= sizeof(unsigned long)) { - __PYX_VERIFY_RETURN_INT_EXC(int, unsigned long, PyLong_AsUnsignedLong(x)) -#ifdef HAVE_LONG_LONG - } else if (sizeof(int) <= sizeof(unsigned PY_LONG_LONG)) { - __PYX_VERIFY_RETURN_INT_EXC(int, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x)) -#endif - } - } else { -#if CYTHON_USE_PYLONG_INTERNALS - const digit* digits = ((PyLongObject*)x)->ob_digit; - switch (Py_SIZE(x)) { - case 0: return (int) 0; - case -1: __PYX_VERIFY_RETURN_INT(int, sdigit, (sdigit) (-(sdigit)digits[0])) - case 1: __PYX_VERIFY_RETURN_INT(int, digit, +digits[0]) - case -2: - if (8 * sizeof(int) - 1 > 1 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(int) - 1 > 2 * PyLong_SHIFT) { - return (int) (((int)-1)*(((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); - } - } - break; - case 2: - if (8 * sizeof(int) > 1 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(int) - 1 > 2 * PyLong_SHIFT) { - return (int) ((((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); - } - } - break; - case -3: - if (8 * sizeof(int) - 1 > 2 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(int) - 1 > 3 * PyLong_SHIFT) { - return (int) (((int)-1)*(((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); - } - } - break; - case 3: - if (8 * sizeof(int) > 2 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(int) - 1 > 3 * PyLong_SHIFT) { - return (int) ((((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); - } - } - break; - case -4: - if (8 * sizeof(int) - 1 > 3 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(int) - 1 > 4 * PyLong_SHIFT) { - return (int) (((int)-1)*(((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); - } - } - break; - case 4: - if (8 * sizeof(int) > 3 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(int) - 1 > 4 * PyLong_SHIFT) { - return (int) ((((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); - } - } - break; - } -#endif - if (sizeof(int) <= sizeof(long)) { - __PYX_VERIFY_RETURN_INT_EXC(int, long, PyLong_AsLong(x)) -#ifdef HAVE_LONG_LONG - } else if (sizeof(int) <= sizeof(PY_LONG_LONG)) { - __PYX_VERIFY_RETURN_INT_EXC(int, PY_LONG_LONG, PyLong_AsLongLong(x)) -#endif - } - } - { -#if CYTHON_COMPILING_IN_PYPY && !defined(_PyLong_AsByteArray) - PyErr_SetString(PyExc_RuntimeError, - "_PyLong_AsByteArray() not available in PyPy, cannot convert large numbers"); -#else - int val; - PyObject *v = __Pyx_PyNumber_IntOrLong(x); - #if PY_MAJOR_VERSION < 3 - if (likely(v) && !PyLong_Check(v)) { - PyObject *tmp = v; - v = PyNumber_Long(tmp); - Py_DECREF(tmp); - } - #endif - if (likely(v)) { - int one = 1; int is_little = (int)*(unsigned char *)&one; - unsigned char *bytes = (unsigned char *)&val; - int ret = _PyLong_AsByteArray((PyLongObject *)v, - bytes, sizeof(val), - is_little, !is_unsigned); - Py_DECREF(v); - if (likely(!ret)) - return val; - } -#endif - return (int) -1; - } - } else { - int val; - PyObject *tmp = __Pyx_PyNumber_IntOrLong(x); - if (!tmp) return (int) -1; - val = __Pyx_PyInt_As_int(tmp); - Py_DECREF(tmp); - return val; - } -raise_overflow: - PyErr_SetString(PyExc_OverflowError, - "value too large to convert to int"); - return (int) -1; -raise_neg_overflow: - PyErr_SetString(PyExc_OverflowError, - "can't convert negative value to int"); - return (int) -1; -} - -/* FastTypeChecks */ -#if CYTHON_COMPILING_IN_CPYTHON -static int __Pyx_InBases(PyTypeObject *a, PyTypeObject *b) { - while (a) { - a = a->tp_base; - if (a == b) - return 1; - } - return b == &PyBaseObject_Type; -} -static CYTHON_INLINE int __Pyx_IsSubtype(PyTypeObject *a, PyTypeObject *b) { - PyObject *mro; - if (a == b) return 1; - mro = a->tp_mro; - if (likely(mro)) { - Py_ssize_t i, n; - n = PyTuple_GET_SIZE(mro); - for (i = 0; i < n; i++) { - if (PyTuple_GET_ITEM(mro, i) == (PyObject *)b) - return 1; - } - return 0; - } - return __Pyx_InBases(a, b); -} -#if PY_MAJOR_VERSION == 2 -static int __Pyx_inner_PyErr_GivenExceptionMatches2(PyObject *err, PyObject* exc_type1, PyObject* exc_type2) { - PyObject *exception, *value, *tb; - int res; - __Pyx_PyThreadState_declare - __Pyx_PyThreadState_assign - __Pyx_ErrFetch(&exception, &value, &tb); - res = exc_type1 ? PyObject_IsSubclass(err, exc_type1) : 0; - if (unlikely(res == -1)) { - PyErr_WriteUnraisable(err); - res = 0; - } - if (!res) { - res = PyObject_IsSubclass(err, exc_type2); - if (unlikely(res == -1)) { - PyErr_WriteUnraisable(err); - res = 0; - } - } - __Pyx_ErrRestore(exception, value, tb); - return res; -} -#else -static CYTHON_INLINE int __Pyx_inner_PyErr_GivenExceptionMatches2(PyObject *err, PyObject* exc_type1, PyObject *exc_type2) { - int res = exc_type1 ? __Pyx_IsSubtype((PyTypeObject*)err, (PyTypeObject*)exc_type1) : 0; - if (!res) { - res = __Pyx_IsSubtype((PyTypeObject*)err, (PyTypeObject*)exc_type2); - } - return res; -} -#endif -static int __Pyx_PyErr_GivenExceptionMatchesTuple(PyObject *exc_type, PyObject *tuple) { - Py_ssize_t i, n; - assert(PyExceptionClass_Check(exc_type)); - n = PyTuple_GET_SIZE(tuple); -#if PY_MAJOR_VERSION >= 3 - for (i=0; ip) { - #if PY_MAJOR_VERSION < 3 - if (t->is_unicode) { - *t->p = PyUnicode_DecodeUTF8(t->s, t->n - 1, NULL); - } else if (t->intern) { - *t->p = PyString_InternFromString(t->s); - } else { - *t->p = PyString_FromStringAndSize(t->s, t->n - 1); - } - #else - if (t->is_unicode | t->is_str) { - if (t->intern) { - *t->p = PyUnicode_InternFromString(t->s); - } else if (t->encoding) { - *t->p = PyUnicode_Decode(t->s, t->n - 1, t->encoding, NULL); - } else { - *t->p = PyUnicode_FromStringAndSize(t->s, t->n - 1); - } - } else { - *t->p = PyBytes_FromStringAndSize(t->s, t->n - 1); - } - #endif - if (!*t->p) - return -1; - if (PyObject_Hash(*t->p) == -1) - return -1; - ++t; - } - return 0; -} - -static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char* c_str) { - return __Pyx_PyUnicode_FromStringAndSize(c_str, (Py_ssize_t)strlen(c_str)); -} -static CYTHON_INLINE const char* __Pyx_PyObject_AsString(PyObject* o) { - Py_ssize_t ignore; - return __Pyx_PyObject_AsStringAndSize(o, &ignore); -} -#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT -#if !CYTHON_PEP393_ENABLED -static const char* __Pyx_PyUnicode_AsStringAndSize(PyObject* o, Py_ssize_t *length) { - char* defenc_c; - PyObject* defenc = _PyUnicode_AsDefaultEncodedString(o, NULL); - if (!defenc) return NULL; - defenc_c = PyBytes_AS_STRING(defenc); -#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII - { - char* end = defenc_c + PyBytes_GET_SIZE(defenc); - char* c; - for (c = defenc_c; c < end; c++) { - if ((unsigned char) (*c) >= 128) { - PyUnicode_AsASCIIString(o); - return NULL; - } - } - } -#endif - *length = PyBytes_GET_SIZE(defenc); - return defenc_c; -} -#else -static CYTHON_INLINE const char* __Pyx_PyUnicode_AsStringAndSize(PyObject* o, Py_ssize_t *length) { - if (unlikely(__Pyx_PyUnicode_READY(o) == -1)) return NULL; -#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII - if (likely(PyUnicode_IS_ASCII(o))) { - *length = PyUnicode_GET_LENGTH(o); - return PyUnicode_AsUTF8(o); - } else { - PyUnicode_AsASCIIString(o); - return NULL; - } -#else - return PyUnicode_AsUTF8AndSize(o, length); -#endif -} -#endif -#endif -static CYTHON_INLINE const char* __Pyx_PyObject_AsStringAndSize(PyObject* o, Py_ssize_t *length) { -#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT - if ( -#if PY_MAJOR_VERSION < 3 && __PYX_DEFAULT_STRING_ENCODING_IS_ASCII - __Pyx_sys_getdefaultencoding_not_ascii && -#endif - PyUnicode_Check(o)) { - return __Pyx_PyUnicode_AsStringAndSize(o, length); - } else -#endif -#if (!CYTHON_COMPILING_IN_PYPY) || (defined(PyByteArray_AS_STRING) && defined(PyByteArray_GET_SIZE)) - if (PyByteArray_Check(o)) { - *length = PyByteArray_GET_SIZE(o); - return PyByteArray_AS_STRING(o); - } else -#endif - { - char* result; - int r = PyBytes_AsStringAndSize(o, &result, length); - if (unlikely(r < 0)) { - return NULL; - } else { - return result; - } - } -} -static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject* x) { - int is_true = x == Py_True; - if (is_true | (x == Py_False) | (x == Py_None)) return is_true; - else return PyObject_IsTrue(x); -} -static CYTHON_INLINE int __Pyx_PyObject_IsTrueAndDecref(PyObject* x) { - int retval; - if (unlikely(!x)) return -1; - retval = __Pyx_PyObject_IsTrue(x); - Py_DECREF(x); - return retval; -} -static PyObject* __Pyx_PyNumber_IntOrLongWrongResultType(PyObject* result, const char* type_name) { -#if PY_MAJOR_VERSION >= 3 - if (PyLong_Check(result)) { - if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1, - "__int__ returned non-int (type %.200s). " - "The ability to return an instance of a strict subclass of int " - "is deprecated, and may be removed in a future version of Python.", - Py_TYPE(result)->tp_name)) { - Py_DECREF(result); - return NULL; - } - return result; - } -#endif - PyErr_Format(PyExc_TypeError, - "__%.4s__ returned non-%.4s (type %.200s)", - type_name, type_name, Py_TYPE(result)->tp_name); - Py_DECREF(result); - return NULL; -} -static CYTHON_INLINE PyObject* __Pyx_PyNumber_IntOrLong(PyObject* x) { -#if CYTHON_USE_TYPE_SLOTS - PyNumberMethods *m; -#endif - const char *name = NULL; - PyObject *res = NULL; -#if PY_MAJOR_VERSION < 3 - if (likely(PyInt_Check(x) || PyLong_Check(x))) -#else - if (likely(PyLong_Check(x))) -#endif - return __Pyx_NewRef(x); -#if CYTHON_USE_TYPE_SLOTS - m = Py_TYPE(x)->tp_as_number; - #if PY_MAJOR_VERSION < 3 - if (m && m->nb_int) { - name = "int"; - res = m->nb_int(x); - } - else if (m && m->nb_long) { - name = "long"; - res = m->nb_long(x); - } - #else - if (likely(m && m->nb_int)) { - name = "int"; - res = m->nb_int(x); - } - #endif -#else - if (!PyBytes_CheckExact(x) && !PyUnicode_CheckExact(x)) { - res = PyNumber_Int(x); - } -#endif - if (likely(res)) { -#if PY_MAJOR_VERSION < 3 - if (unlikely(!PyInt_Check(res) && !PyLong_Check(res))) { -#else - if (unlikely(!PyLong_CheckExact(res))) { -#endif - return __Pyx_PyNumber_IntOrLongWrongResultType(res, name); - } - } - else if (!PyErr_Occurred()) { - PyErr_SetString(PyExc_TypeError, - "an integer is required"); - } - return res; -} -static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) { - Py_ssize_t ival; - PyObject *x; -#if PY_MAJOR_VERSION < 3 - if (likely(PyInt_CheckExact(b))) { - if (sizeof(Py_ssize_t) >= sizeof(long)) - return PyInt_AS_LONG(b); - else - return PyInt_AsSsize_t(b); - } -#endif - if (likely(PyLong_CheckExact(b))) { - #if CYTHON_USE_PYLONG_INTERNALS - const digit* digits = ((PyLongObject*)b)->ob_digit; - const Py_ssize_t size = Py_SIZE(b); - if (likely(__Pyx_sst_abs(size) <= 1)) { - ival = likely(size) ? digits[0] : 0; - if (size == -1) ival = -ival; - return ival; - } else { - switch (size) { - case 2: - if (8 * sizeof(Py_ssize_t) > 2 * PyLong_SHIFT) { - return (Py_ssize_t) (((((size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); - } - break; - case -2: - if (8 * sizeof(Py_ssize_t) > 2 * PyLong_SHIFT) { - return -(Py_ssize_t) (((((size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); - } - break; - case 3: - if (8 * sizeof(Py_ssize_t) > 3 * PyLong_SHIFT) { - return (Py_ssize_t) (((((((size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); - } - break; - case -3: - if (8 * sizeof(Py_ssize_t) > 3 * PyLong_SHIFT) { - return -(Py_ssize_t) (((((((size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); - } - break; - case 4: - if (8 * sizeof(Py_ssize_t) > 4 * PyLong_SHIFT) { - return (Py_ssize_t) (((((((((size_t)digits[3]) << PyLong_SHIFT) | (size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); - } - break; - case -4: - if (8 * sizeof(Py_ssize_t) > 4 * PyLong_SHIFT) { - return -(Py_ssize_t) (((((((((size_t)digits[3]) << PyLong_SHIFT) | (size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); - } - break; - } - } - #endif - return PyLong_AsSsize_t(b); - } - x = PyNumber_Index(b); - if (!x) return -1; - ival = PyInt_AsSsize_t(x); - Py_DECREF(x); - return ival; -} -static CYTHON_INLINE PyObject * __Pyx_PyBool_FromLong(long b) { - return b ? __Pyx_NewRef(Py_True) : __Pyx_NewRef(Py_False); -} -static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t ival) { - return PyInt_FromSize_t(ival); -} - - -#endif /* Py_PYTHON_H */ diff --git a/aiohttp/_frozenlist.pyx b/aiohttp/_frozenlist.pyx deleted file mode 100644 index b130577..0000000 --- a/aiohttp/_frozenlist.pyx +++ /dev/null @@ -1,108 +0,0 @@ -from collections.abc import MutableSequence - - -cdef class FrozenList: - - cdef readonly bint frozen - cdef list _items - - def __init__(self, items=None): - self.frozen = False - if items is not None: - items = list(items) - else: - items = [] - self._items = items - - cdef object _check_frozen(self): - if self.frozen: - raise RuntimeError("Cannot modify frozen list.") - - cdef inline object _fast_len(self): - return len(self._items) - - def freeze(self): - self.frozen = True - - def __getitem__(self, index): - return self._items[index] - - def __setitem__(self, index, value): - self._check_frozen() - self._items[index] = value - - def __delitem__(self, index): - self._check_frozen() - del self._items[index] - - def __len__(self): - return self._fast_len() - - def __iter__(self): - return self._items.__iter__() - - def __reversed__(self): - return self._items.__reversed__() - - def __richcmp__(self, other, op): - if op == 0: # < - return list(self) < other - if op == 1: # <= - return list(self) <= other - if op == 2: # == - return list(self) == other - if op == 3: # != - return list(self) != other - if op == 4: # > - return list(self) > other - if op == 5: # => - return list(self) >= other - - def insert(self, pos, item): - self._check_frozen() - self._items.insert(pos, item) - - def __contains__(self, item): - return item in self._items - - def __iadd__(self, items): - self._check_frozen() - self._items += list(items) - return self - - def index(self, item): - return self._items.index(item) - - def remove(self, item): - self._check_frozen() - self._items.remove(item) - - def clear(self): - self._check_frozen() - self._items.clear() - - def extend(self, items): - self._check_frozen() - self._items += list(items) - - def reverse(self): - self._check_frozen() - self._items.reverse() - - def pop(self, index=-1): - self._check_frozen() - return self._items.pop(index) - - def append(self, item): - self._check_frozen() - return self._items.append(item) - - def count(self, item): - return self._items.count(item) - - def __repr__(self): - return ''.format(self.frozen, - self._items) - - -MutableSequence.register(FrozenList) diff --git a/aiohttp/_helpers.c b/aiohttp/_helpers.c index 764f998..d6400b2 100644 --- a/aiohttp/_helpers.c +++ b/aiohttp/_helpers.c @@ -1,14 +1,16 @@ -/* Generated by Cython 0.29.21 */ +/* Generated by Cython 0.29.32 */ +#ifndef PY_SSIZE_T_CLEAN #define PY_SSIZE_T_CLEAN +#endif /* PY_SSIZE_T_CLEAN */ #include "Python.h" #ifndef Py_PYTHON_H #error Python headers needed to compile C extensions, please install development version of Python. #elif PY_VERSION_HEX < 0x02060000 || (0x03000000 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x03030000) #error Cython requires Python 2.6+ or Python 3.3+. #else -#define CYTHON_ABI "0_29_21" -#define CYTHON_HEX_VERSION 0x001D15F0 +#define CYTHON_ABI "0_29_32" +#define CYTHON_HEX_VERSION 0x001D20F0 #define CYTHON_FUTURE_DIVISION 1 #include #ifndef offsetof @@ -47,6 +49,7 @@ #define CYTHON_COMPILING_IN_PYPY 1 #define CYTHON_COMPILING_IN_PYSTON 0 #define CYTHON_COMPILING_IN_CPYTHON 0 + #define CYTHON_COMPILING_IN_NOGIL 0 #undef CYTHON_USE_TYPE_SLOTS #define CYTHON_USE_TYPE_SLOTS 0 #undef CYTHON_USE_PYTYPE_LOOKUP @@ -83,10 +86,14 @@ #define CYTHON_USE_DICT_VERSIONS 0 #undef CYTHON_USE_EXC_INFO_STACK #define CYTHON_USE_EXC_INFO_STACK 0 + #ifndef CYTHON_UPDATE_DESCRIPTOR_DOC + #define CYTHON_UPDATE_DESCRIPTOR_DOC (PYPY_VERSION_HEX >= 0x07030900) + #endif #elif defined(PYSTON_VERSION) #define CYTHON_COMPILING_IN_PYPY 0 #define CYTHON_COMPILING_IN_PYSTON 1 #define CYTHON_COMPILING_IN_CPYTHON 0 + #define CYTHON_COMPILING_IN_NOGIL 0 #ifndef CYTHON_USE_TYPE_SLOTS #define CYTHON_USE_TYPE_SLOTS 1 #endif @@ -124,10 +131,59 @@ #define CYTHON_USE_DICT_VERSIONS 0 #undef CYTHON_USE_EXC_INFO_STACK #define CYTHON_USE_EXC_INFO_STACK 0 + #ifndef CYTHON_UPDATE_DESCRIPTOR_DOC + #define CYTHON_UPDATE_DESCRIPTOR_DOC 0 + #endif +#elif defined(PY_NOGIL) + #define CYTHON_COMPILING_IN_PYPY 0 + #define CYTHON_COMPILING_IN_PYSTON 0 + #define CYTHON_COMPILING_IN_CPYTHON 0 + #define CYTHON_COMPILING_IN_NOGIL 1 + #ifndef CYTHON_USE_TYPE_SLOTS + #define CYTHON_USE_TYPE_SLOTS 1 + #endif + #undef CYTHON_USE_PYTYPE_LOOKUP + #define CYTHON_USE_PYTYPE_LOOKUP 0 + #ifndef CYTHON_USE_ASYNC_SLOTS + #define CYTHON_USE_ASYNC_SLOTS 1 + #endif + #undef CYTHON_USE_PYLIST_INTERNALS + #define CYTHON_USE_PYLIST_INTERNALS 0 + #ifndef CYTHON_USE_UNICODE_INTERNALS + #define CYTHON_USE_UNICODE_INTERNALS 1 + #endif + #undef CYTHON_USE_UNICODE_WRITER + #define CYTHON_USE_UNICODE_WRITER 0 + #undef CYTHON_USE_PYLONG_INTERNALS + #define CYTHON_USE_PYLONG_INTERNALS 0 + #ifndef CYTHON_AVOID_BORROWED_REFS + #define CYTHON_AVOID_BORROWED_REFS 0 + #endif + #ifndef CYTHON_ASSUME_SAFE_MACROS + #define CYTHON_ASSUME_SAFE_MACROS 1 + #endif + #ifndef CYTHON_UNPACK_METHODS + #define CYTHON_UNPACK_METHODS 1 + #endif + #undef CYTHON_FAST_THREAD_STATE + #define CYTHON_FAST_THREAD_STATE 0 + #undef CYTHON_FAST_PYCALL + #define CYTHON_FAST_PYCALL 0 + #ifndef CYTHON_PEP489_MULTI_PHASE_INIT + #define CYTHON_PEP489_MULTI_PHASE_INIT 1 + #endif + #ifndef CYTHON_USE_TP_FINALIZE + #define CYTHON_USE_TP_FINALIZE 1 + #endif + #undef CYTHON_USE_DICT_VERSIONS + #define CYTHON_USE_DICT_VERSIONS 0 + #undef CYTHON_USE_EXC_INFO_STACK + #define CYTHON_USE_EXC_INFO_STACK 0 #else #define CYTHON_COMPILING_IN_PYPY 0 #define CYTHON_COMPILING_IN_PYSTON 0 #define CYTHON_COMPILING_IN_CPYTHON 1 + #define CYTHON_COMPILING_IN_NOGIL 0 #ifndef CYTHON_USE_TYPE_SLOTS #define CYTHON_USE_TYPE_SLOTS 1 #endif @@ -155,7 +211,7 @@ #ifndef CYTHON_USE_UNICODE_INTERNALS #define CYTHON_USE_UNICODE_INTERNALS 1 #endif - #if PY_VERSION_HEX < 0x030300F0 + #if PY_VERSION_HEX < 0x030300F0 || PY_VERSION_HEX >= 0x030B00A2 #undef CYTHON_USE_UNICODE_WRITER #define CYTHON_USE_UNICODE_WRITER 0 #elif !defined(CYTHON_USE_UNICODE_WRITER) @@ -170,11 +226,14 @@ #ifndef CYTHON_UNPACK_METHODS #define CYTHON_UNPACK_METHODS 1 #endif - #ifndef CYTHON_FAST_THREAD_STATE + #if PY_VERSION_HEX >= 0x030B00A4 + #undef CYTHON_FAST_THREAD_STATE + #define CYTHON_FAST_THREAD_STATE 0 + #elif !defined(CYTHON_FAST_THREAD_STATE) #define CYTHON_FAST_THREAD_STATE 1 #endif #ifndef CYTHON_FAST_PYCALL - #define CYTHON_FAST_PYCALL 1 + #define CYTHON_FAST_PYCALL (PY_VERSION_HEX < 0x030A0000) #endif #ifndef CYTHON_PEP489_MULTI_PHASE_INIT #define CYTHON_PEP489_MULTI_PHASE_INIT (PY_VERSION_HEX >= 0x03050000) @@ -185,15 +244,23 @@ #ifndef CYTHON_USE_DICT_VERSIONS #define CYTHON_USE_DICT_VERSIONS (PY_VERSION_HEX >= 0x030600B1) #endif - #ifndef CYTHON_USE_EXC_INFO_STACK + #if PY_VERSION_HEX >= 0x030B00A4 + #undef CYTHON_USE_EXC_INFO_STACK + #define CYTHON_USE_EXC_INFO_STACK 0 + #elif !defined(CYTHON_USE_EXC_INFO_STACK) #define CYTHON_USE_EXC_INFO_STACK (PY_VERSION_HEX >= 0x030700A3) #endif + #ifndef CYTHON_UPDATE_DESCRIPTOR_DOC + #define CYTHON_UPDATE_DESCRIPTOR_DOC 1 + #endif #endif #if !defined(CYTHON_FAST_PYCCALL) #define CYTHON_FAST_PYCCALL (CYTHON_FAST_PYCALL && PY_VERSION_HEX >= 0x030600B1) #endif #if CYTHON_USE_PYLONG_INTERNALS - #include "longintrepr.h" + #if PY_MAJOR_VERSION < 3 + #include "longintrepr.h" + #endif #undef SHIFT #undef BASE #undef MASK @@ -310,9 +377,68 @@ #define __Pyx_DefaultClassType PyClass_Type #else #define __Pyx_BUILTIN_MODULE_NAME "builtins" -#if PY_VERSION_HEX >= 0x030800A4 && PY_VERSION_HEX < 0x030800B2 - #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ - PyCode_New(a, 0, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) + #define __Pyx_DefaultClassType PyType_Type +#if PY_VERSION_HEX >= 0x030B00A1 + static CYTHON_INLINE PyCodeObject* __Pyx_PyCode_New(int a, int k, int l, int s, int f, + PyObject *code, PyObject *c, PyObject* n, PyObject *v, + PyObject *fv, PyObject *cell, PyObject* fn, + PyObject *name, int fline, PyObject *lnos) { + PyObject *kwds=NULL, *argcount=NULL, *posonlyargcount=NULL, *kwonlyargcount=NULL; + PyObject *nlocals=NULL, *stacksize=NULL, *flags=NULL, *replace=NULL, *call_result=NULL, *empty=NULL; + const char *fn_cstr=NULL; + const char *name_cstr=NULL; + PyCodeObject* co=NULL; + PyObject *type, *value, *traceback; + PyErr_Fetch(&type, &value, &traceback); + if (!(kwds=PyDict_New())) goto end; + if (!(argcount=PyLong_FromLong(a))) goto end; + if (PyDict_SetItemString(kwds, "co_argcount", argcount) != 0) goto end; + if (!(posonlyargcount=PyLong_FromLong(0))) goto end; + if (PyDict_SetItemString(kwds, "co_posonlyargcount", posonlyargcount) != 0) goto end; + if (!(kwonlyargcount=PyLong_FromLong(k))) goto end; + if (PyDict_SetItemString(kwds, "co_kwonlyargcount", kwonlyargcount) != 0) goto end; + if (!(nlocals=PyLong_FromLong(l))) goto end; + if (PyDict_SetItemString(kwds, "co_nlocals", nlocals) != 0) goto end; + if (!(stacksize=PyLong_FromLong(s))) goto end; + if (PyDict_SetItemString(kwds, "co_stacksize", stacksize) != 0) goto end; + if (!(flags=PyLong_FromLong(f))) goto end; + if (PyDict_SetItemString(kwds, "co_flags", flags) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_code", code) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_consts", c) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_names", n) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_varnames", v) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_freevars", fv) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_cellvars", cell) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_linetable", lnos) != 0) goto end; + if (!(fn_cstr=PyUnicode_AsUTF8AndSize(fn, NULL))) goto end; + if (!(name_cstr=PyUnicode_AsUTF8AndSize(name, NULL))) goto end; + if (!(co = PyCode_NewEmpty(fn_cstr, name_cstr, fline))) goto end; + if (!(replace = PyObject_GetAttrString((PyObject*)co, "replace"))) goto cleanup_code_too; + if (!(empty = PyTuple_New(0))) goto cleanup_code_too; // unfortunately __pyx_empty_tuple isn't available here + if (!(call_result = PyObject_Call(replace, empty, kwds))) goto cleanup_code_too; + Py_XDECREF((PyObject*)co); + co = (PyCodeObject*)call_result; + call_result = NULL; + if (0) { + cleanup_code_too: + Py_XDECREF((PyObject*)co); + co = NULL; + } + end: + Py_XDECREF(kwds); + Py_XDECREF(argcount); + Py_XDECREF(posonlyargcount); + Py_XDECREF(kwonlyargcount); + Py_XDECREF(nlocals); + Py_XDECREF(stacksize); + Py_XDECREF(replace); + Py_XDECREF(call_result); + Py_XDECREF(empty); + if (type) { + PyErr_Restore(type, value, traceback); + } + return co; + } #else #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) @@ -426,8 +552,12 @@ static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) { #endif #if PY_VERSION_HEX > 0x03030000 && defined(PyUnicode_KIND) #define CYTHON_PEP393_ENABLED 1 + #if defined(PyUnicode_IS_READY) #define __Pyx_PyUnicode_READY(op) (likely(PyUnicode_IS_READY(op)) ?\ 0 : _PyUnicode_Ready((PyObject *)(op))) + #else + #define __Pyx_PyUnicode_READY(op) (0) + #endif #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_LENGTH(u) #define __Pyx_PyUnicode_READ_CHAR(u, i) PyUnicode_READ_CHAR(u, i) #define __Pyx_PyUnicode_MAX_CHAR_VALUE(u) PyUnicode_MAX_CHAR_VALUE(u) @@ -436,7 +566,11 @@ static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) { #define __Pyx_PyUnicode_READ(k, d, i) PyUnicode_READ(k, d, i) #define __Pyx_PyUnicode_WRITE(k, d, i, ch) PyUnicode_WRITE(k, d, i, ch) #if defined(PyUnicode_IS_READY) && defined(PyUnicode_GET_SIZE) + #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x03090000 + #define __Pyx_PyUnicode_IS_TRUE(u) (0 != (likely(PyUnicode_IS_READY(u)) ? PyUnicode_GET_LENGTH(u) : ((PyCompactUnicodeObject *)(u))->wstr_length)) + #else #define __Pyx_PyUnicode_IS_TRUE(u) (0 != (likely(PyUnicode_IS_READY(u)) ? PyUnicode_GET_LENGTH(u) : PyUnicode_GET_SIZE(u))) + #endif #else #define __Pyx_PyUnicode_IS_TRUE(u) (0 != PyUnicode_GET_LENGTH(u)) #endif @@ -542,10 +676,10 @@ static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) { #if PY_VERSION_HEX < 0x030200A4 typedef long Py_hash_t; #define __Pyx_PyInt_FromHash_t PyInt_FromLong - #define __Pyx_PyInt_AsHash_t PyInt_AsLong + #define __Pyx_PyInt_AsHash_t __Pyx_PyIndex_AsHash_t #else #define __Pyx_PyInt_FromHash_t PyInt_FromSsize_t - #define __Pyx_PyInt_AsHash_t PyInt_AsSsize_t + #define __Pyx_PyInt_AsHash_t __Pyx_PyIndex_AsSsize_t #endif #if PY_MAJOR_VERSION >= 3 #define __Pyx_PyMethod_New(func, self, klass) ((self) ? ((void)(klass), PyMethod_New(func, self)) : __Pyx_NewRef(func)) @@ -570,8 +704,10 @@ static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) { } __Pyx_PyAsyncMethodsStruct; #endif -#if defined(WIN32) || defined(MS_WINDOWS) - #define _USE_MATH_DEFINES +#if defined(_WIN32) || defined(WIN32) || defined(MS_WINDOWS) + #if !defined(_USE_MATH_DEFINES) + #define _USE_MATH_DEFINES + #endif #endif #include #ifdef NAN @@ -701,6 +837,7 @@ static CYTHON_INLINE PyObject* __Pyx_PyNumber_IntOrLong(PyObject* x); (likely(PyTuple_CheckExact(obj)) ? __Pyx_NewRef(obj) : PySequence_Tuple(obj)) static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject*); static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t); +static CYTHON_INLINE Py_hash_t __Pyx_PyIndex_AsHash_t(PyObject*); #if CYTHON_ASSUME_SAFE_MACROS #define __pyx_PyFloat_AsDouble(x) (PyFloat_CheckExact(x) ? PyFloat_AS_DOUBLE(x) : PyFloat_AsDouble(x)) #else @@ -1011,13 +1148,21 @@ static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, #ifndef Py_MEMBER_SIZE #define Py_MEMBER_SIZE(type, member) sizeof(((type *)0)->member) #endif +#if CYTHON_FAST_PYCALL static size_t __pyx_pyframe_localsplus_offset = 0; #include "frameobject.h" +#if PY_VERSION_HEX >= 0x030b00a6 + #ifndef Py_BUILD_CORE + #define Py_BUILD_CORE 1 + #endif + #include "internal/pycore_frame.h" +#endif #define __Pxy_PyFrame_Initialize_Offsets()\ ((void)__Pyx_BUILD_ASSERT_EXPR(sizeof(PyFrameObject) == offsetof(PyFrameObject, f_localsplus) + Py_MEMBER_SIZE(PyFrameObject, f_localsplus)),\ (void)(__pyx_pyframe_localsplus_offset = ((size_t)PyFrame_Type.tp_basicsize) - Py_MEMBER_SIZE(PyFrameObject, f_localsplus))) #define __Pyx_PyFrame_GetLocalsplus(frame)\ (assert(__pyx_pyframe_localsplus_offset), (PyObject **)(((char *)(frame)) + __pyx_pyframe_localsplus_offset)) +#endif // CYTHON_FAST_PYCALL #endif /* PyObjectCall.proto */ @@ -1119,6 +1264,12 @@ static PyObject *__Pyx__GetModuleGlobalName(PyObject *name, PY_UINT64_T *dict_ve static CYTHON_INLINE PyObject *__Pyx__GetModuleGlobalName(PyObject *name); #endif +/* PySequenceContains.proto */ +static CYTHON_INLINE int __Pyx_PySequence_ContainsTF(PyObject* item, PyObject* seq, int eq) { + int result = PySequence_Contains(seq, item); + return unlikely(result < 0) ? result : (result == (eq == Py_EQ)); +} + /* Import.proto */ static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, int level); @@ -1174,12 +1325,17 @@ static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object); static void __Pyx_AddTraceback(const char *funcname, int c_line, int py_line, const char *filename); -/* CIntToPy.proto */ -static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value); +/* GCCDiagnostics.proto */ +#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) +#define __Pyx_HAS_GCC_DIAGNOSTIC +#endif /* CIntFromPy.proto */ static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *); +/* CIntToPy.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value); + /* CIntFromPy.proto */ static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *); @@ -1244,9 +1400,9 @@ static const char __pyx_k_aiohttp__helpers[] = "aiohttp._helpers"; static const char __pyx_k_cline_in_traceback[] = "cline_in_traceback"; static const char __pyx_k_pyx_unpickle_reify[] = "__pyx_unpickle_reify"; static const char __pyx_k_reified_property_is_read_only[] = "reified property is read-only"; -static const char __pyx_k_Incompatible_checksums_s_vs_0x77[] = "Incompatible checksums (%s vs 0x770cb8f = (name, wrapped))"; +static const char __pyx_k_Incompatible_checksums_0x_x_vs_0[] = "Incompatible checksums (0x%x vs (0x770cb8f, 0xeecf561, 0x545205d) = (name, wrapped))"; static PyObject *__pyx_n_s_AttributeError; -static PyObject *__pyx_kp_s_Incompatible_checksums_s_vs_0x77; +static PyObject *__pyx_kp_s_Incompatible_checksums_0x_x_vs_0; static PyObject *__pyx_n_s_KeyError; static PyObject *__pyx_n_s_PickleError; static PyObject *__pyx_n_s_aiohttp__helpers; @@ -1285,10 +1441,13 @@ static PyObject *__pyx_pf_7aiohttp_8_helpers_5reify_6__reduce_cython__(struct __ static PyObject *__pyx_pf_7aiohttp_8_helpers_5reify_8__setstate_cython__(struct __pyx_obj_7aiohttp_8_helpers_reify *__pyx_v_self, PyObject *__pyx_v___pyx_state); /* proto */ static PyObject *__pyx_pf_7aiohttp_8_helpers___pyx_unpickle_reify(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v___pyx_type, long __pyx_v___pyx_checksum, PyObject *__pyx_v___pyx_state); /* proto */ static PyObject *__pyx_tp_new_7aiohttp_8_helpers_reify(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/ +static PyObject *__pyx_int_88416349; static PyObject *__pyx_int_124832655; +static PyObject *__pyx_int_250410337; static PyObject *__pyx_tuple_; static PyObject *__pyx_tuple__2; -static PyObject *__pyx_codeobj__3; +static PyObject *__pyx_tuple__3; +static PyObject *__pyx_codeobj__4; /* Late includes */ /* "aiohttp/_helpers.pyx":13 @@ -2259,12 +2418,12 @@ static PyObject *__pyx_pf_7aiohttp_8_helpers___pyx_unpickle_reify(CYTHON_UNUSED PyObject *__pyx_v___pyx_result = 0; PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations - int __pyx_t_1; - PyObject *__pyx_t_2 = NULL; - PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_1 = NULL; + int __pyx_t_2; + int __pyx_t_3; PyObject *__pyx_t_4 = NULL; PyObject *__pyx_t_5 = NULL; - int __pyx_t_6; + PyObject *__pyx_t_6 = NULL; int __pyx_lineno = 0; const char *__pyx_filename = NULL; int __pyx_clineno = 0; @@ -2273,114 +2432,118 @@ static PyObject *__pyx_pf_7aiohttp_8_helpers___pyx_unpickle_reify(CYTHON_UNUSED /* "(tree fragment)":4 * cdef object __pyx_PickleError * cdef object __pyx_result - * if __pyx_checksum != 0x770cb8f: # <<<<<<<<<<<<<< + * if __pyx_checksum not in (0x770cb8f, 0xeecf561, 0x545205d): # <<<<<<<<<<<<<< * from pickle import PickleError as __pyx_PickleError - * raise __pyx_PickleError("Incompatible checksums (%s vs 0x770cb8f = (name, wrapped))" % __pyx_checksum) + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x770cb8f, 0xeecf561, 0x545205d) = (name, wrapped))" % __pyx_checksum) */ - __pyx_t_1 = ((__pyx_v___pyx_checksum != 0x770cb8f) != 0); - if (__pyx_t_1) { + __pyx_t_1 = __Pyx_PyInt_From_long(__pyx_v___pyx_checksum); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 4, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = (__Pyx_PySequence_ContainsTF(__pyx_t_1, __pyx_tuple__2, Py_NE)); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(1, 4, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_3 = (__pyx_t_2 != 0); + if (__pyx_t_3) { /* "(tree fragment)":5 * cdef object __pyx_result - * if __pyx_checksum != 0x770cb8f: + * if __pyx_checksum not in (0x770cb8f, 0xeecf561, 0x545205d): * from pickle import PickleError as __pyx_PickleError # <<<<<<<<<<<<<< - * raise __pyx_PickleError("Incompatible checksums (%s vs 0x770cb8f = (name, wrapped))" % __pyx_checksum) + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x770cb8f, 0xeecf561, 0x545205d) = (name, wrapped))" % __pyx_checksum) * __pyx_result = reify.__new__(__pyx_type) */ - __pyx_t_2 = PyList_New(1); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 5, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); + __pyx_t_1 = PyList_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); __Pyx_INCREF(__pyx_n_s_PickleError); __Pyx_GIVEREF(__pyx_n_s_PickleError); - PyList_SET_ITEM(__pyx_t_2, 0, __pyx_n_s_PickleError); - __pyx_t_3 = __Pyx_Import(__pyx_n_s_pickle, __pyx_t_2, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 5, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_2 = __Pyx_ImportFrom(__pyx_t_3, __pyx_n_s_PickleError); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 5, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __Pyx_INCREF(__pyx_t_2); - __pyx_v___pyx_PickleError = __pyx_t_2; - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + PyList_SET_ITEM(__pyx_t_1, 0, __pyx_n_s_PickleError); + __pyx_t_4 = __Pyx_Import(__pyx_n_s_pickle, __pyx_t_1, 0); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_4, __pyx_n_s_PickleError); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_t_1); + __pyx_v___pyx_PickleError = __pyx_t_1; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; /* "(tree fragment)":6 - * if __pyx_checksum != 0x770cb8f: + * if __pyx_checksum not in (0x770cb8f, 0xeecf561, 0x545205d): * from pickle import PickleError as __pyx_PickleError - * raise __pyx_PickleError("Incompatible checksums (%s vs 0x770cb8f = (name, wrapped))" % __pyx_checksum) # <<<<<<<<<<<<<< + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x770cb8f, 0xeecf561, 0x545205d) = (name, wrapped))" % __pyx_checksum) # <<<<<<<<<<<<<< * __pyx_result = reify.__new__(__pyx_type) * if __pyx_state is not None: */ - __pyx_t_2 = __Pyx_PyInt_From_long(__pyx_v___pyx_checksum); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 6, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_4 = __Pyx_PyString_Format(__pyx_kp_s_Incompatible_checksums_s_vs_0x77, __pyx_t_2); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 6, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_1 = __Pyx_PyInt_From_long(__pyx_v___pyx_checksum); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_5 = __Pyx_PyString_Format(__pyx_kp_s_Incompatible_checksums_0x_x_vs_0, __pyx_t_1); if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __Pyx_INCREF(__pyx_v___pyx_PickleError); - __pyx_t_2 = __pyx_v___pyx_PickleError; __pyx_t_5 = NULL; - if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) { - __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_2); - if (likely(__pyx_t_5)) { - PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2); - __Pyx_INCREF(__pyx_t_5); + __pyx_t_1 = __pyx_v___pyx_PickleError; __pyx_t_6 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_1))) { + __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_1); + if (likely(__pyx_t_6)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1); + __Pyx_INCREF(__pyx_t_6); __Pyx_INCREF(function); - __Pyx_DECREF_SET(__pyx_t_2, function); + __Pyx_DECREF_SET(__pyx_t_1, function); } } - __pyx_t_3 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_5, __pyx_t_4) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_4); - __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_4 = (__pyx_t_6) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_6, __pyx_t_5) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_Raise(__pyx_t_4, 0, 0, 0); __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 6, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __Pyx_Raise(__pyx_t_3, 0, 0, 0); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __PYX_ERR(1, 6, __pyx_L1_error) /* "(tree fragment)":4 * cdef object __pyx_PickleError * cdef object __pyx_result - * if __pyx_checksum != 0x770cb8f: # <<<<<<<<<<<<<< + * if __pyx_checksum not in (0x770cb8f, 0xeecf561, 0x545205d): # <<<<<<<<<<<<<< * from pickle import PickleError as __pyx_PickleError - * raise __pyx_PickleError("Incompatible checksums (%s vs 0x770cb8f = (name, wrapped))" % __pyx_checksum) + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x770cb8f, 0xeecf561, 0x545205d) = (name, wrapped))" % __pyx_checksum) */ } /* "(tree fragment)":7 * from pickle import PickleError as __pyx_PickleError - * raise __pyx_PickleError("Incompatible checksums (%s vs 0x770cb8f = (name, wrapped))" % __pyx_checksum) + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x770cb8f, 0xeecf561, 0x545205d) = (name, wrapped))" % __pyx_checksum) * __pyx_result = reify.__new__(__pyx_type) # <<<<<<<<<<<<<< * if __pyx_state is not None: * __pyx_unpickle_reify__set_state( __pyx_result, __pyx_state) */ - __pyx_t_2 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_ptype_7aiohttp_8_helpers_reify), __pyx_n_s_new); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 7, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_4 = NULL; - if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) { - __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_2); - if (likely(__pyx_t_4)) { - PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2); - __Pyx_INCREF(__pyx_t_4); + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_ptype_7aiohttp_8_helpers_reify), __pyx_n_s_new); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 7, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_5 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_1))) { + __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_1); + if (likely(__pyx_t_5)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1); + __Pyx_INCREF(__pyx_t_5); __Pyx_INCREF(function); - __Pyx_DECREF_SET(__pyx_t_2, function); + __Pyx_DECREF_SET(__pyx_t_1, function); } } - __pyx_t_3 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_4, __pyx_v___pyx_type) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_v___pyx_type); - __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; - if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 7, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_v___pyx_result = __pyx_t_3; - __pyx_t_3 = 0; + __pyx_t_4 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_5, __pyx_v___pyx_type) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_v___pyx_type); + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 7, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v___pyx_result = __pyx_t_4; + __pyx_t_4 = 0; /* "(tree fragment)":8 - * raise __pyx_PickleError("Incompatible checksums (%s vs 0x770cb8f = (name, wrapped))" % __pyx_checksum) + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x770cb8f, 0xeecf561, 0x545205d) = (name, wrapped))" % __pyx_checksum) * __pyx_result = reify.__new__(__pyx_type) * if __pyx_state is not None: # <<<<<<<<<<<<<< * __pyx_unpickle_reify__set_state( __pyx_result, __pyx_state) * return __pyx_result */ - __pyx_t_1 = (__pyx_v___pyx_state != Py_None); - __pyx_t_6 = (__pyx_t_1 != 0); - if (__pyx_t_6) { + __pyx_t_3 = (__pyx_v___pyx_state != Py_None); + __pyx_t_2 = (__pyx_t_3 != 0); + if (__pyx_t_2) { /* "(tree fragment)":9 * __pyx_result = reify.__new__(__pyx_type) @@ -2390,12 +2553,12 @@ static PyObject *__pyx_pf_7aiohttp_8_helpers___pyx_unpickle_reify(CYTHON_UNUSED * cdef __pyx_unpickle_reify__set_state(reify __pyx_result, tuple __pyx_state): */ if (!(likely(PyTuple_CheckExact(__pyx_v___pyx_state))||((__pyx_v___pyx_state) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_v___pyx_state)->tp_name), 0))) __PYX_ERR(1, 9, __pyx_L1_error) - __pyx_t_3 = __pyx_f_7aiohttp_8_helpers___pyx_unpickle_reify__set_state(((struct __pyx_obj_7aiohttp_8_helpers_reify *)__pyx_v___pyx_result), ((PyObject*)__pyx_v___pyx_state)); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 9, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_4 = __pyx_f_7aiohttp_8_helpers___pyx_unpickle_reify__set_state(((struct __pyx_obj_7aiohttp_8_helpers_reify *)__pyx_v___pyx_result), ((PyObject*)__pyx_v___pyx_state)); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 9, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; /* "(tree fragment)":8 - * raise __pyx_PickleError("Incompatible checksums (%s vs 0x770cb8f = (name, wrapped))" % __pyx_checksum) + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x770cb8f, 0xeecf561, 0x545205d) = (name, wrapped))" % __pyx_checksum) * __pyx_result = reify.__new__(__pyx_type) * if __pyx_state is not None: # <<<<<<<<<<<<<< * __pyx_unpickle_reify__set_state( __pyx_result, __pyx_state) @@ -2423,10 +2586,10 @@ static PyObject *__pyx_pf_7aiohttp_8_helpers___pyx_unpickle_reify(CYTHON_UNUSED /* function exit code */ __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_2); - __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_1); __Pyx_XDECREF(__pyx_t_4); __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); __Pyx_AddTraceback("aiohttp._helpers.__pyx_unpickle_reify", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = NULL; __pyx_L0:; @@ -2726,12 +2889,15 @@ static PyTypeObject __pyx_type_7aiohttp_8_helpers_reify = { #if PY_VERSION_HEX >= 0x030400a1 0, /*tp_finalize*/ #endif - #if PY_VERSION_HEX >= 0x030800b1 + #if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800) 0, /*tp_vectorcall*/ #endif #if PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x03090000 0, /*tp_print*/ #endif + #if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 + 0, /*tp_pypy_flags*/ + #endif }; static PyMethodDef __pyx_methods[] = { @@ -2781,7 +2947,7 @@ static struct PyModuleDef __pyx_moduledef = { static __Pyx_StringTabEntry __pyx_string_tab[] = { {&__pyx_n_s_AttributeError, __pyx_k_AttributeError, sizeof(__pyx_k_AttributeError), 0, 0, 1, 1}, - {&__pyx_kp_s_Incompatible_checksums_s_vs_0x77, __pyx_k_Incompatible_checksums_s_vs_0x77, sizeof(__pyx_k_Incompatible_checksums_s_vs_0x77), 0, 0, 1, 0}, + {&__pyx_kp_s_Incompatible_checksums_0x_x_vs_0, __pyx_k_Incompatible_checksums_0x_x_vs_0, sizeof(__pyx_k_Incompatible_checksums_0x_x_vs_0), 0, 0, 1, 0}, {&__pyx_n_s_KeyError, __pyx_k_KeyError, sizeof(__pyx_k_KeyError), 0, 0, 1, 1}, {&__pyx_n_s_PickleError, __pyx_k_PickleError, sizeof(__pyx_k_PickleError), 0, 0, 1, 1}, {&__pyx_n_s_aiohttp__helpers, __pyx_k_aiohttp__helpers, sizeof(__pyx_k_aiohttp__helpers), 0, 0, 1, 1}, @@ -2835,15 +3001,26 @@ static CYTHON_SMALL_CODE int __Pyx_InitCachedConstants(void) { __Pyx_GOTREF(__pyx_tuple_); __Pyx_GIVEREF(__pyx_tuple_); - /* "(tree fragment)":1 - * def __pyx_unpickle_reify(__pyx_type, long __pyx_checksum, __pyx_state): # <<<<<<<<<<<<<< + /* "(tree fragment)":4 * cdef object __pyx_PickleError * cdef object __pyx_result + * if __pyx_checksum not in (0x770cb8f, 0xeecf561, 0x545205d): # <<<<<<<<<<<<<< + * from pickle import PickleError as __pyx_PickleError + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x770cb8f, 0xeecf561, 0x545205d) = (name, wrapped))" % __pyx_checksum) */ - __pyx_tuple__2 = PyTuple_Pack(5, __pyx_n_s_pyx_type, __pyx_n_s_pyx_checksum, __pyx_n_s_pyx_state, __pyx_n_s_pyx_PickleError, __pyx_n_s_pyx_result); if (unlikely(!__pyx_tuple__2)) __PYX_ERR(1, 1, __pyx_L1_error) + __pyx_tuple__2 = PyTuple_Pack(3, __pyx_int_124832655, __pyx_int_250410337, __pyx_int_88416349); if (unlikely(!__pyx_tuple__2)) __PYX_ERR(1, 4, __pyx_L1_error) __Pyx_GOTREF(__pyx_tuple__2); __Pyx_GIVEREF(__pyx_tuple__2); - __pyx_codeobj__3 = (PyObject*)__Pyx_PyCode_New(3, 0, 5, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__2, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_stringsource, __pyx_n_s_pyx_unpickle_reify, 1, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__3)) __PYX_ERR(1, 1, __pyx_L1_error) + + /* "(tree fragment)":1 + * def __pyx_unpickle_reify(__pyx_type, long __pyx_checksum, __pyx_state): # <<<<<<<<<<<<<< + * cdef object __pyx_PickleError + * cdef object __pyx_result + */ + __pyx_tuple__3 = PyTuple_Pack(5, __pyx_n_s_pyx_type, __pyx_n_s_pyx_checksum, __pyx_n_s_pyx_state, __pyx_n_s_pyx_PickleError, __pyx_n_s_pyx_result); if (unlikely(!__pyx_tuple__3)) __PYX_ERR(1, 1, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__3); + __Pyx_GIVEREF(__pyx_tuple__3); + __pyx_codeobj__4 = (PyObject*)__Pyx_PyCode_New(3, 0, 5, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__3, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_stringsource, __pyx_n_s_pyx_unpickle_reify, 1, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__4)) __PYX_ERR(1, 1, __pyx_L1_error) __Pyx_RefNannyFinishContext(); return 0; __pyx_L1_error:; @@ -2853,7 +3030,9 @@ static CYTHON_SMALL_CODE int __Pyx_InitCachedConstants(void) { static CYTHON_SMALL_CODE int __Pyx_InitGlobals(void) { if (__Pyx_InitStrings(__pyx_string_tab) < 0) __PYX_ERR(0, 1, __pyx_L1_error); + __pyx_int_88416349 = PyInt_FromLong(88416349L); if (unlikely(!__pyx_int_88416349)) __PYX_ERR(0, 1, __pyx_L1_error) __pyx_int_124832655 = PyInt_FromLong(124832655L); if (unlikely(!__pyx_int_124832655)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_int_250410337 = PyInt_FromLong(250410337L); if (unlikely(!__pyx_int_250410337)) __PYX_ERR(0, 1, __pyx_L1_error) return 0; __pyx_L1_error:; return -1; @@ -3084,11 +3263,9 @@ if (!__Pyx_RefNanny) { #endif /*--- Library function declarations ---*/ /*--- Threads initialization code ---*/ - #if defined(__PYX_FORCE_INIT_THREADS) && __PYX_FORCE_INIT_THREADS - #ifdef WITH_THREAD /* Python build with threading support? */ + #if defined(WITH_THREAD) && PY_VERSION_HEX < 0x030700F0 && defined(__PYX_FORCE_INIT_THREADS) && __PYX_FORCE_INIT_THREADS PyEval_InitThreads(); #endif - #endif /*--- Module creation code ---*/ #if CYTHON_PEP489_MULTI_PHASE_INIT __pyx_m = __pyx_pyinit_module; @@ -3790,7 +3967,7 @@ static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, #if CYTHON_COMPILING_IN_CPYTHON static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw) { PyObject *result; - ternaryfunc call = func->ob_type->tp_call; + ternaryfunc call = Py_TYPE(func)->tp_call; if (unlikely(!call)) return PyObject_Call(func, arg, kw); if (unlikely(Py_EnterRecursiveCall((char*)" while calling a Python object"))) @@ -3877,7 +4054,7 @@ static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObjec if (likely(PyCFunction_GET_FLAGS(func) & METH_O)) { return __Pyx_PyObject_CallMethO(func, arg); #if CYTHON_FAST_PYCCALL - } else if (PyCFunction_GET_FLAGS(func) & METH_FASTCALL) { + } else if (__Pyx_PyFastCFunction_Check(func)) { return __Pyx_PyCFunction_FastCall(func, &arg, 1); #endif } @@ -4356,17 +4533,35 @@ static int __Pyx_setup_reduce_is_named(PyObject* meth, PyObject* name) { static int __Pyx_setup_reduce(PyObject* type_obj) { int ret = 0; PyObject *object_reduce = NULL; + PyObject *object_getstate = NULL; PyObject *object_reduce_ex = NULL; PyObject *reduce = NULL; PyObject *reduce_ex = NULL; PyObject *reduce_cython = NULL; PyObject *setstate = NULL; PyObject *setstate_cython = NULL; + PyObject *getstate = NULL; #if CYTHON_USE_PYTYPE_LOOKUP - if (_PyType_Lookup((PyTypeObject*)type_obj, __pyx_n_s_getstate)) goto __PYX_GOOD; + getstate = _PyType_Lookup((PyTypeObject*)type_obj, __pyx_n_s_getstate); #else - if (PyObject_HasAttr(type_obj, __pyx_n_s_getstate)) goto __PYX_GOOD; + getstate = __Pyx_PyObject_GetAttrStrNoError(type_obj, __pyx_n_s_getstate); + if (!getstate && PyErr_Occurred()) { + goto __PYX_BAD; + } #endif + if (getstate) { +#if CYTHON_USE_PYTYPE_LOOKUP + object_getstate = _PyType_Lookup(&PyBaseObject_Type, __pyx_n_s_getstate); +#else + object_getstate = __Pyx_PyObject_GetAttrStrNoError((PyObject*)&PyBaseObject_Type, __pyx_n_s_getstate); + if (!object_getstate && PyErr_Occurred()) { + goto __PYX_BAD; + } +#endif + if (object_getstate != getstate) { + goto __PYX_GOOD; + } + } #if CYTHON_USE_PYTYPE_LOOKUP object_reduce_ex = _PyType_Lookup(&PyBaseObject_Type, __pyx_n_s_reduce_ex); if (!object_reduce_ex) goto __PYX_BAD; #else @@ -4411,6 +4606,8 @@ static int __Pyx_setup_reduce(PyObject* type_obj) { #if !CYTHON_USE_PYTYPE_LOOKUP Py_XDECREF(object_reduce); Py_XDECREF(object_reduce_ex); + Py_XDECREF(object_getstate); + Py_XDECREF(getstate); #endif Py_XDECREF(reduce); Py_XDECREF(reduce_ex); @@ -4452,7 +4649,7 @@ static int __Pyx_CLineForTraceback(CYTHON_NCP_UNUSED PyThreadState *tstate, int } if (!use_cline) { c_line = 0; - PyObject_SetAttr(__pyx_cython_runtime, __pyx_n_s_cline_in_traceback, Py_False); + (void) PyObject_SetAttr(__pyx_cython_runtime, __pyx_n_s_cline_in_traceback, Py_False); } else if (use_cline == Py_False || (use_cline != Py_True && PyObject_Not(use_cline) != 0)) { c_line = 0; @@ -4546,33 +4743,40 @@ static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object) { #include "compile.h" #include "frameobject.h" #include "traceback.h" +#if PY_VERSION_HEX >= 0x030b00a6 + #ifndef Py_BUILD_CORE + #define Py_BUILD_CORE 1 + #endif + #include "internal/pycore_frame.h" +#endif static PyCodeObject* __Pyx_CreateCodeObjectForTraceback( const char *funcname, int c_line, int py_line, const char *filename) { - PyCodeObject *py_code = 0; - PyObject *py_srcfile = 0; - PyObject *py_funcname = 0; + PyCodeObject *py_code = NULL; + PyObject *py_funcname = NULL; #if PY_MAJOR_VERSION < 3 + PyObject *py_srcfile = NULL; py_srcfile = PyString_FromString(filename); - #else - py_srcfile = PyUnicode_FromString(filename); - #endif if (!py_srcfile) goto bad; + #endif if (c_line) { #if PY_MAJOR_VERSION < 3 py_funcname = PyString_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line); + if (!py_funcname) goto bad; #else py_funcname = PyUnicode_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line); + if (!py_funcname) goto bad; + funcname = PyUnicode_AsUTF8(py_funcname); + if (!funcname) goto bad; #endif } else { #if PY_MAJOR_VERSION < 3 py_funcname = PyString_FromString(funcname); - #else - py_funcname = PyUnicode_FromString(funcname); + if (!py_funcname) goto bad; #endif } - if (!py_funcname) goto bad; + #if PY_MAJOR_VERSION < 3 py_code = __Pyx_PyCode_New( 0, 0, @@ -4591,11 +4795,16 @@ static PyCodeObject* __Pyx_CreateCodeObjectForTraceback( __pyx_empty_bytes /*PyObject *lnotab*/ ); Py_DECREF(py_srcfile); - Py_DECREF(py_funcname); + #else + py_code = PyCode_NewEmpty(filename, funcname, py_line); + #endif + Py_XDECREF(py_funcname); // XDECREF since it's only set on Py3 if cline return py_code; bad: - Py_XDECREF(py_srcfile); Py_XDECREF(py_funcname); + #if PY_MAJOR_VERSION < 3 + Py_XDECREF(py_srcfile); + #endif return NULL; } static void __Pyx_AddTraceback(const char *funcname, int c_line, @@ -4603,14 +4812,24 @@ static void __Pyx_AddTraceback(const char *funcname, int c_line, PyCodeObject *py_code = 0; PyFrameObject *py_frame = 0; PyThreadState *tstate = __Pyx_PyThreadState_Current; + PyObject *ptype, *pvalue, *ptraceback; if (c_line) { c_line = __Pyx_CLineForTraceback(tstate, c_line); } py_code = __pyx_find_code_object(c_line ? -c_line : py_line); if (!py_code) { + __Pyx_ErrFetchInState(tstate, &ptype, &pvalue, &ptraceback); py_code = __Pyx_CreateCodeObjectForTraceback( funcname, c_line, py_line, filename); - if (!py_code) goto bad; + if (!py_code) { + /* If the code object creation fails, then we should clear the + fetched exception references and propagate the new exception */ + Py_XDECREF(ptype); + Py_XDECREF(pvalue); + Py_XDECREF(ptraceback); + goto bad; + } + __Pyx_ErrRestoreInState(tstate, ptype, pvalue, ptraceback); __pyx_insert_code_object(c_line ? -c_line : py_line, py_code); } py_frame = PyFrame_New( @@ -4649,40 +4868,16 @@ static void __Pyx_AddTraceback(const char *funcname, int c_line, return (target_type) value;\ } -/* CIntToPy */ -static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value) { - const long neg_one = (long) ((long) 0 - (long) 1), const_zero = (long) 0; - const int is_unsigned = neg_one > const_zero; - if (is_unsigned) { - if (sizeof(long) < sizeof(long)) { - return PyInt_FromLong((long) value); - } else if (sizeof(long) <= sizeof(unsigned long)) { - return PyLong_FromUnsignedLong((unsigned long) value); -#ifdef HAVE_LONG_LONG - } else if (sizeof(long) <= sizeof(unsigned PY_LONG_LONG)) { - return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value); -#endif - } - } else { - if (sizeof(long) <= sizeof(long)) { - return PyInt_FromLong((long) value); -#ifdef HAVE_LONG_LONG - } else if (sizeof(long) <= sizeof(PY_LONG_LONG)) { - return PyLong_FromLongLong((PY_LONG_LONG) value); -#endif - } - } - { - int one = 1; int little = (int)*(unsigned char *)&one; - unsigned char *bytes = (unsigned char *)&value; - return _PyLong_FromByteArray(bytes, sizeof(long), - little, !is_unsigned); - } -} - /* CIntFromPy */ static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *x) { - const long neg_one = (long) ((long) 0 - (long) 1), const_zero = (long) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +#endif + const long neg_one = (long) -1, const_zero = (long) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic pop +#endif const int is_unsigned = neg_one > const_zero; #if PY_MAJOR_VERSION < 3 if (likely(PyInt_Check(x))) { @@ -4869,9 +5064,54 @@ static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *x) { return (long) -1; } +/* CIntToPy */ +static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value) { +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +#endif + const long neg_one = (long) -1, const_zero = (long) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic pop +#endif + const int is_unsigned = neg_one > const_zero; + if (is_unsigned) { + if (sizeof(long) < sizeof(long)) { + return PyInt_FromLong((long) value); + } else if (sizeof(long) <= sizeof(unsigned long)) { + return PyLong_FromUnsignedLong((unsigned long) value); +#ifdef HAVE_LONG_LONG + } else if (sizeof(long) <= sizeof(unsigned PY_LONG_LONG)) { + return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value); +#endif + } + } else { + if (sizeof(long) <= sizeof(long)) { + return PyInt_FromLong((long) value); +#ifdef HAVE_LONG_LONG + } else if (sizeof(long) <= sizeof(PY_LONG_LONG)) { + return PyLong_FromLongLong((PY_LONG_LONG) value); +#endif + } + } + { + int one = 1; int little = (int)*(unsigned char *)&one; + unsigned char *bytes = (unsigned char *)&value; + return _PyLong_FromByteArray(bytes, sizeof(long), + little, !is_unsigned); + } +} + /* CIntFromPy */ static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *x) { - const int neg_one = (int) ((int) 0 - (int) 1), const_zero = (int) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +#endif + const int neg_one = (int) -1, const_zero = (int) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic pop +#endif const int is_unsigned = neg_one > const_zero; #if PY_MAJOR_VERSION < 3 if (likely(PyInt_Check(x))) { @@ -5160,11 +5400,33 @@ static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches2(PyObject *err, PyObj /* CheckBinaryVersion */ static int __Pyx_check_binary_version(void) { - char ctversion[4], rtversion[4]; - PyOS_snprintf(ctversion, 4, "%d.%d", PY_MAJOR_VERSION, PY_MINOR_VERSION); - PyOS_snprintf(rtversion, 4, "%s", Py_GetVersion()); - if (ctversion[0] != rtversion[0] || ctversion[2] != rtversion[2]) { + char ctversion[5]; + int same=1, i, found_dot; + const char* rt_from_call = Py_GetVersion(); + PyOS_snprintf(ctversion, 5, "%d.%d", PY_MAJOR_VERSION, PY_MINOR_VERSION); + found_dot = 0; + for (i = 0; i < 4; i++) { + if (!ctversion[i]) { + same = (rt_from_call[i] < '0' || rt_from_call[i] > '9'); + break; + } + if (rt_from_call[i] != ctversion[i]) { + same = 0; + break; + } + } + if (!same) { + char rtversion[5] = {'\0'}; char message[200]; + for (i=0; i<4; ++i) { + if (rt_from_call[i] == '.') { + if (found_dot) break; + found_dot = 1; + } else if (rt_from_call[i] < '0' || rt_from_call[i] > '9') { + break; + } + rtversion[i] = rt_from_call[i]; + } PyOS_snprintf(message, sizeof(message), "compiletime version %s of module '%.100s' " "does not match runtime version %s", @@ -5422,6 +5684,23 @@ static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) { Py_DECREF(x); return ival; } +static CYTHON_INLINE Py_hash_t __Pyx_PyIndex_AsHash_t(PyObject* o) { + if (sizeof(Py_hash_t) == sizeof(Py_ssize_t)) { + return (Py_hash_t) __Pyx_PyIndex_AsSsize_t(o); +#if PY_MAJOR_VERSION < 3 + } else if (likely(PyInt_CheckExact(o))) { + return PyInt_AS_LONG(o); +#endif + } else { + Py_ssize_t ival; + PyObject *x; + x = PyNumber_Index(o); + if (!x) return -1; + ival = PyInt_AsLong(x); + Py_DECREF(x); + return ival; + } +} static CYTHON_INLINE PyObject * __Pyx_PyBool_FromLong(long b) { return b ? __Pyx_NewRef(Py_True) : __Pyx_NewRef(Py_False); } diff --git a/aiohttp/_http_parser.c b/aiohttp/_http_parser.c index 096446e..9aafd43 100644 --- a/aiohttp/_http_parser.c +++ b/aiohttp/_http_parser.c @@ -1,14 +1,16 @@ -/* Generated by Cython 0.29.21 */ +/* Generated by Cython 0.29.32 */ +#ifndef PY_SSIZE_T_CLEAN #define PY_SSIZE_T_CLEAN +#endif /* PY_SSIZE_T_CLEAN */ #include "Python.h" #ifndef Py_PYTHON_H #error Python headers needed to compile C extensions, please install development version of Python. #elif PY_VERSION_HEX < 0x02060000 || (0x03000000 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x03030000) #error Cython requires Python 2.6+ or Python 3.3+. #else -#define CYTHON_ABI "0_29_21" -#define CYTHON_HEX_VERSION 0x001D15F0 +#define CYTHON_ABI "0_29_32" +#define CYTHON_HEX_VERSION 0x001D20F0 #define CYTHON_FUTURE_DIVISION 1 #include #ifndef offsetof @@ -47,6 +49,7 @@ #define CYTHON_COMPILING_IN_PYPY 1 #define CYTHON_COMPILING_IN_PYSTON 0 #define CYTHON_COMPILING_IN_CPYTHON 0 + #define CYTHON_COMPILING_IN_NOGIL 0 #undef CYTHON_USE_TYPE_SLOTS #define CYTHON_USE_TYPE_SLOTS 0 #undef CYTHON_USE_PYTYPE_LOOKUP @@ -83,10 +86,14 @@ #define CYTHON_USE_DICT_VERSIONS 0 #undef CYTHON_USE_EXC_INFO_STACK #define CYTHON_USE_EXC_INFO_STACK 0 + #ifndef CYTHON_UPDATE_DESCRIPTOR_DOC + #define CYTHON_UPDATE_DESCRIPTOR_DOC (PYPY_VERSION_HEX >= 0x07030900) + #endif #elif defined(PYSTON_VERSION) #define CYTHON_COMPILING_IN_PYPY 0 #define CYTHON_COMPILING_IN_PYSTON 1 #define CYTHON_COMPILING_IN_CPYTHON 0 + #define CYTHON_COMPILING_IN_NOGIL 0 #ifndef CYTHON_USE_TYPE_SLOTS #define CYTHON_USE_TYPE_SLOTS 1 #endif @@ -124,10 +131,59 @@ #define CYTHON_USE_DICT_VERSIONS 0 #undef CYTHON_USE_EXC_INFO_STACK #define CYTHON_USE_EXC_INFO_STACK 0 + #ifndef CYTHON_UPDATE_DESCRIPTOR_DOC + #define CYTHON_UPDATE_DESCRIPTOR_DOC 0 + #endif +#elif defined(PY_NOGIL) + #define CYTHON_COMPILING_IN_PYPY 0 + #define CYTHON_COMPILING_IN_PYSTON 0 + #define CYTHON_COMPILING_IN_CPYTHON 0 + #define CYTHON_COMPILING_IN_NOGIL 1 + #ifndef CYTHON_USE_TYPE_SLOTS + #define CYTHON_USE_TYPE_SLOTS 1 + #endif + #undef CYTHON_USE_PYTYPE_LOOKUP + #define CYTHON_USE_PYTYPE_LOOKUP 0 + #ifndef CYTHON_USE_ASYNC_SLOTS + #define CYTHON_USE_ASYNC_SLOTS 1 + #endif + #undef CYTHON_USE_PYLIST_INTERNALS + #define CYTHON_USE_PYLIST_INTERNALS 0 + #ifndef CYTHON_USE_UNICODE_INTERNALS + #define CYTHON_USE_UNICODE_INTERNALS 1 + #endif + #undef CYTHON_USE_UNICODE_WRITER + #define CYTHON_USE_UNICODE_WRITER 0 + #undef CYTHON_USE_PYLONG_INTERNALS + #define CYTHON_USE_PYLONG_INTERNALS 0 + #ifndef CYTHON_AVOID_BORROWED_REFS + #define CYTHON_AVOID_BORROWED_REFS 0 + #endif + #ifndef CYTHON_ASSUME_SAFE_MACROS + #define CYTHON_ASSUME_SAFE_MACROS 1 + #endif + #ifndef CYTHON_UNPACK_METHODS + #define CYTHON_UNPACK_METHODS 1 + #endif + #undef CYTHON_FAST_THREAD_STATE + #define CYTHON_FAST_THREAD_STATE 0 + #undef CYTHON_FAST_PYCALL + #define CYTHON_FAST_PYCALL 0 + #ifndef CYTHON_PEP489_MULTI_PHASE_INIT + #define CYTHON_PEP489_MULTI_PHASE_INIT 1 + #endif + #ifndef CYTHON_USE_TP_FINALIZE + #define CYTHON_USE_TP_FINALIZE 1 + #endif + #undef CYTHON_USE_DICT_VERSIONS + #define CYTHON_USE_DICT_VERSIONS 0 + #undef CYTHON_USE_EXC_INFO_STACK + #define CYTHON_USE_EXC_INFO_STACK 0 #else #define CYTHON_COMPILING_IN_PYPY 0 #define CYTHON_COMPILING_IN_PYSTON 0 #define CYTHON_COMPILING_IN_CPYTHON 1 + #define CYTHON_COMPILING_IN_NOGIL 0 #ifndef CYTHON_USE_TYPE_SLOTS #define CYTHON_USE_TYPE_SLOTS 1 #endif @@ -155,7 +211,7 @@ #ifndef CYTHON_USE_UNICODE_INTERNALS #define CYTHON_USE_UNICODE_INTERNALS 1 #endif - #if PY_VERSION_HEX < 0x030300F0 + #if PY_VERSION_HEX < 0x030300F0 || PY_VERSION_HEX >= 0x030B00A2 #undef CYTHON_USE_UNICODE_WRITER #define CYTHON_USE_UNICODE_WRITER 0 #elif !defined(CYTHON_USE_UNICODE_WRITER) @@ -170,11 +226,14 @@ #ifndef CYTHON_UNPACK_METHODS #define CYTHON_UNPACK_METHODS 1 #endif - #ifndef CYTHON_FAST_THREAD_STATE + #if PY_VERSION_HEX >= 0x030B00A4 + #undef CYTHON_FAST_THREAD_STATE + #define CYTHON_FAST_THREAD_STATE 0 + #elif !defined(CYTHON_FAST_THREAD_STATE) #define CYTHON_FAST_THREAD_STATE 1 #endif #ifndef CYTHON_FAST_PYCALL - #define CYTHON_FAST_PYCALL 1 + #define CYTHON_FAST_PYCALL (PY_VERSION_HEX < 0x030A0000) #endif #ifndef CYTHON_PEP489_MULTI_PHASE_INIT #define CYTHON_PEP489_MULTI_PHASE_INIT (PY_VERSION_HEX >= 0x03050000) @@ -185,15 +244,23 @@ #ifndef CYTHON_USE_DICT_VERSIONS #define CYTHON_USE_DICT_VERSIONS (PY_VERSION_HEX >= 0x030600B1) #endif - #ifndef CYTHON_USE_EXC_INFO_STACK + #if PY_VERSION_HEX >= 0x030B00A4 + #undef CYTHON_USE_EXC_INFO_STACK + #define CYTHON_USE_EXC_INFO_STACK 0 + #elif !defined(CYTHON_USE_EXC_INFO_STACK) #define CYTHON_USE_EXC_INFO_STACK (PY_VERSION_HEX >= 0x030700A3) #endif + #ifndef CYTHON_UPDATE_DESCRIPTOR_DOC + #define CYTHON_UPDATE_DESCRIPTOR_DOC 1 + #endif #endif #if !defined(CYTHON_FAST_PYCCALL) #define CYTHON_FAST_PYCCALL (CYTHON_FAST_PYCALL && PY_VERSION_HEX >= 0x030600B1) #endif #if CYTHON_USE_PYLONG_INTERNALS - #include "longintrepr.h" + #if PY_MAJOR_VERSION < 3 + #include "longintrepr.h" + #endif #undef SHIFT #undef BASE #undef MASK @@ -310,9 +377,68 @@ #define __Pyx_DefaultClassType PyClass_Type #else #define __Pyx_BUILTIN_MODULE_NAME "builtins" -#if PY_VERSION_HEX >= 0x030800A4 && PY_VERSION_HEX < 0x030800B2 - #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ - PyCode_New(a, 0, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) + #define __Pyx_DefaultClassType PyType_Type +#if PY_VERSION_HEX >= 0x030B00A1 + static CYTHON_INLINE PyCodeObject* __Pyx_PyCode_New(int a, int k, int l, int s, int f, + PyObject *code, PyObject *c, PyObject* n, PyObject *v, + PyObject *fv, PyObject *cell, PyObject* fn, + PyObject *name, int fline, PyObject *lnos) { + PyObject *kwds=NULL, *argcount=NULL, *posonlyargcount=NULL, *kwonlyargcount=NULL; + PyObject *nlocals=NULL, *stacksize=NULL, *flags=NULL, *replace=NULL, *call_result=NULL, *empty=NULL; + const char *fn_cstr=NULL; + const char *name_cstr=NULL; + PyCodeObject* co=NULL; + PyObject *type, *value, *traceback; + PyErr_Fetch(&type, &value, &traceback); + if (!(kwds=PyDict_New())) goto end; + if (!(argcount=PyLong_FromLong(a))) goto end; + if (PyDict_SetItemString(kwds, "co_argcount", argcount) != 0) goto end; + if (!(posonlyargcount=PyLong_FromLong(0))) goto end; + if (PyDict_SetItemString(kwds, "co_posonlyargcount", posonlyargcount) != 0) goto end; + if (!(kwonlyargcount=PyLong_FromLong(k))) goto end; + if (PyDict_SetItemString(kwds, "co_kwonlyargcount", kwonlyargcount) != 0) goto end; + if (!(nlocals=PyLong_FromLong(l))) goto end; + if (PyDict_SetItemString(kwds, "co_nlocals", nlocals) != 0) goto end; + if (!(stacksize=PyLong_FromLong(s))) goto end; + if (PyDict_SetItemString(kwds, "co_stacksize", stacksize) != 0) goto end; + if (!(flags=PyLong_FromLong(f))) goto end; + if (PyDict_SetItemString(kwds, "co_flags", flags) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_code", code) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_consts", c) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_names", n) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_varnames", v) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_freevars", fv) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_cellvars", cell) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_linetable", lnos) != 0) goto end; + if (!(fn_cstr=PyUnicode_AsUTF8AndSize(fn, NULL))) goto end; + if (!(name_cstr=PyUnicode_AsUTF8AndSize(name, NULL))) goto end; + if (!(co = PyCode_NewEmpty(fn_cstr, name_cstr, fline))) goto end; + if (!(replace = PyObject_GetAttrString((PyObject*)co, "replace"))) goto cleanup_code_too; + if (!(empty = PyTuple_New(0))) goto cleanup_code_too; // unfortunately __pyx_empty_tuple isn't available here + if (!(call_result = PyObject_Call(replace, empty, kwds))) goto cleanup_code_too; + Py_XDECREF((PyObject*)co); + co = (PyCodeObject*)call_result; + call_result = NULL; + if (0) { + cleanup_code_too: + Py_XDECREF((PyObject*)co); + co = NULL; + } + end: + Py_XDECREF(kwds); + Py_XDECREF(argcount); + Py_XDECREF(posonlyargcount); + Py_XDECREF(kwonlyargcount); + Py_XDECREF(nlocals); + Py_XDECREF(stacksize); + Py_XDECREF(replace); + Py_XDECREF(call_result); + Py_XDECREF(empty); + if (type) { + PyErr_Restore(type, value, traceback); + } + return co; + } #else #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) @@ -426,8 +552,12 @@ static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) { #endif #if PY_VERSION_HEX > 0x03030000 && defined(PyUnicode_KIND) #define CYTHON_PEP393_ENABLED 1 + #if defined(PyUnicode_IS_READY) #define __Pyx_PyUnicode_READY(op) (likely(PyUnicode_IS_READY(op)) ?\ 0 : _PyUnicode_Ready((PyObject *)(op))) + #else + #define __Pyx_PyUnicode_READY(op) (0) + #endif #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_LENGTH(u) #define __Pyx_PyUnicode_READ_CHAR(u, i) PyUnicode_READ_CHAR(u, i) #define __Pyx_PyUnicode_MAX_CHAR_VALUE(u) PyUnicode_MAX_CHAR_VALUE(u) @@ -436,7 +566,11 @@ static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) { #define __Pyx_PyUnicode_READ(k, d, i) PyUnicode_READ(k, d, i) #define __Pyx_PyUnicode_WRITE(k, d, i, ch) PyUnicode_WRITE(k, d, i, ch) #if defined(PyUnicode_IS_READY) && defined(PyUnicode_GET_SIZE) + #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x03090000 + #define __Pyx_PyUnicode_IS_TRUE(u) (0 != (likely(PyUnicode_IS_READY(u)) ? PyUnicode_GET_LENGTH(u) : ((PyCompactUnicodeObject *)(u))->wstr_length)) + #else #define __Pyx_PyUnicode_IS_TRUE(u) (0 != (likely(PyUnicode_IS_READY(u)) ? PyUnicode_GET_LENGTH(u) : PyUnicode_GET_SIZE(u))) + #endif #else #define __Pyx_PyUnicode_IS_TRUE(u) (0 != PyUnicode_GET_LENGTH(u)) #endif @@ -542,10 +676,10 @@ static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) { #if PY_VERSION_HEX < 0x030200A4 typedef long Py_hash_t; #define __Pyx_PyInt_FromHash_t PyInt_FromLong - #define __Pyx_PyInt_AsHash_t PyInt_AsLong + #define __Pyx_PyInt_AsHash_t __Pyx_PyIndex_AsHash_t #else #define __Pyx_PyInt_FromHash_t PyInt_FromSsize_t - #define __Pyx_PyInt_AsHash_t PyInt_AsSsize_t + #define __Pyx_PyInt_AsHash_t __Pyx_PyIndex_AsSsize_t #endif #if PY_MAJOR_VERSION >= 3 #define __Pyx_PyMethod_New(func, self, klass) ((self) ? ((void)(klass), PyMethod_New(func, self)) : __Pyx_NewRef(func)) @@ -570,8 +704,10 @@ static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) { } __Pyx_PyAsyncMethodsStruct; #endif -#if defined(WIN32) || defined(MS_WINDOWS) - #define _USE_MATH_DEFINES +#if defined(_WIN32) || defined(WIN32) || defined(MS_WINDOWS) + #if !defined(_USE_MATH_DEFINES) + #define _USE_MATH_DEFINES + #endif #endif #include #ifdef NAN @@ -610,7 +746,7 @@ static CYTHON_INLINE float __PYX_NAN() { #include "pythread.h" #include #include -#include "../vendor/http-parser/http_parser.h" +#include "../vendor/llhttp/build/llhttp.h" #include "_find_header.h" #ifdef _OPENMP #include @@ -708,6 +844,7 @@ static CYTHON_INLINE PyObject* __Pyx_PyNumber_IntOrLong(PyObject* x); (likely(PyTuple_CheckExact(obj)) ? __Pyx_NewRef(obj) : PySequence_Tuple(obj)) static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject*); static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t); +static CYTHON_INLINE Py_hash_t __Pyx_PyIndex_AsHash_t(PyObject*); #if CYTHON_ASSUME_SAFE_MACROS #define __pyx_PyFloat_AsDouble(x) (PyFloat_CheckExact(x) ? PyFloat_AS_DOUBLE(x) : PyFloat_AsDouble(x)) #else @@ -840,12 +977,12 @@ struct __pyx_obj_7aiohttp_12_http_parser___pyx_scope_struct_2___repr__; struct __pyx_obj_7aiohttp_12_http_parser___pyx_scope_struct_3_genexpr; struct __pyx_opt_args_7aiohttp_12_http_parser_10HttpParser__init; -/* "aiohttp/_http_parser.pyx":327 - * PyMem_Free(self._csettings) +/* "aiohttp/_http_parser.pyx":328 * - * cdef _init(self, cparser.http_parser_type mode, # <<<<<<<<<<<<<< - * object protocol, object loop, int limit, - * object timer=None, + * cdef _init( + * self, cparser.llhttp_type mode, # <<<<<<<<<<<<<< + * object protocol, object loop, int limit, + * object timer=None, */ struct __pyx_opt_args_7aiohttp_12_http_parser_10HttpParser__init { int __pyx_n; @@ -912,8 +1049,8 @@ struct __pyx_obj_7aiohttp_12_http_parser_RawResponseMessage { struct __pyx_obj_7aiohttp_12_http_parser_HttpParser { PyObject_HEAD struct __pyx_vtabstruct_7aiohttp_12_http_parser_HttpParser *__pyx_vtab; - struct http_parser *_cparser; - struct http_parser_settings *_csettings; + llhttp_t *_cparser; + llhttp_settings_t *_csettings; PyObject *_raw_name; PyObject *_raw_value; int _has_value; @@ -945,24 +1082,24 @@ struct __pyx_obj_7aiohttp_12_http_parser_HttpParser { }; -/* "aiohttp/_http_parser.pyx":563 +/* "aiohttp/_http_parser.pyx":574 * * * cdef class HttpRequestParser(HttpParser): # <<<<<<<<<<<<<< * - * def __init__(self, protocol, loop, int limit, timer=None, + * def __init__( */ struct __pyx_obj_7aiohttp_12_http_parser_HttpRequestParser { struct __pyx_obj_7aiohttp_12_http_parser_HttpParser __pyx_base; }; -/* "aiohttp/_http_parser.pyx":591 +/* "aiohttp/_http_parser.pyx":638 * * * cdef class HttpResponseParser(HttpParser): # <<<<<<<<<<<<<< * - * def __init__(self, protocol, loop, int limit, timer=None, + * def __init__( */ struct __pyx_obj_7aiohttp_12_http_parser_HttpResponseParser { struct __pyx_obj_7aiohttp_12_http_parser_HttpParser __pyx_base; @@ -1035,7 +1172,7 @@ struct __pyx_obj_7aiohttp_12_http_parser___pyx_scope_struct_3_genexpr { */ struct __pyx_vtabstruct_7aiohttp_12_http_parser_HttpParser { - PyObject *(*_init)(struct __pyx_obj_7aiohttp_12_http_parser_HttpParser *, enum http_parser_type, PyObject *, PyObject *, int, struct __pyx_opt_args_7aiohttp_12_http_parser_10HttpParser__init *__pyx_optional_args); + PyObject *(*_init)(struct __pyx_obj_7aiohttp_12_http_parser_HttpParser *, enum llhttp_type, PyObject *, PyObject *, int, struct __pyx_opt_args_7aiohttp_12_http_parser_10HttpParser__init *__pyx_optional_args); PyObject *(*_process_header)(struct __pyx_obj_7aiohttp_12_http_parser_HttpParser *); PyObject *(*_on_header_field)(struct __pyx_obj_7aiohttp_12_http_parser_HttpParser *, char *, size_t); PyObject *(*_on_header_value)(struct __pyx_obj_7aiohttp_12_http_parser_HttpParser *, char *, size_t); @@ -1050,12 +1187,12 @@ static struct __pyx_vtabstruct_7aiohttp_12_http_parser_HttpParser *__pyx_vtabptr static CYTHON_INLINE PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser_http_version(struct __pyx_obj_7aiohttp_12_http_parser_HttpParser *); -/* "aiohttp/_http_parser.pyx":563 +/* "aiohttp/_http_parser.pyx":574 * * * cdef class HttpRequestParser(HttpParser): # <<<<<<<<<<<<<< * - * def __init__(self, protocol, loop, int limit, timer=None, + * def __init__( */ struct __pyx_vtabstruct_7aiohttp_12_http_parser_HttpRequestParser { @@ -1064,12 +1201,12 @@ struct __pyx_vtabstruct_7aiohttp_12_http_parser_HttpRequestParser { static struct __pyx_vtabstruct_7aiohttp_12_http_parser_HttpRequestParser *__pyx_vtabptr_7aiohttp_12_http_parser_HttpRequestParser; -/* "aiohttp/_http_parser.pyx":591 +/* "aiohttp/_http_parser.pyx":638 * * * cdef class HttpResponseParser(HttpParser): # <<<<<<<<<<<<<< * - * def __init__(self, protocol, loop, int limit, timer=None, + * def __init__( */ struct __pyx_vtabstruct_7aiohttp_12_http_parser_HttpResponseParser { @@ -1398,13 +1535,21 @@ static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, #ifndef Py_MEMBER_SIZE #define Py_MEMBER_SIZE(type, member) sizeof(((type *)0)->member) #endif +#if CYTHON_FAST_PYCALL static size_t __pyx_pyframe_localsplus_offset = 0; #include "frameobject.h" +#if PY_VERSION_HEX >= 0x030b00a6 + #ifndef Py_BUILD_CORE + #define Py_BUILD_CORE 1 + #endif + #include "internal/pycore_frame.h" +#endif #define __Pxy_PyFrame_Initialize_Offsets()\ ((void)__Pyx_BUILD_ASSERT_EXPR(sizeof(PyFrameObject) == offsetof(PyFrameObject, f_localsplus) + Py_MEMBER_SIZE(PyFrameObject, f_localsplus)),\ (void)(__pyx_pyframe_localsplus_offset = ((size_t)PyFrame_Type.tp_basicsize) - Py_MEMBER_SIZE(PyFrameObject, f_localsplus))) #define __Pyx_PyFrame_GetLocalsplus(frame)\ (assert(__pyx_pyframe_localsplus_offset), (PyObject **)(((char *)(frame)) + __pyx_pyframe_localsplus_offset)) +#endif // CYTHON_FAST_PYCALL #endif /* PyObjectCall.proto */ @@ -1473,6 +1618,18 @@ static CYTHON_INLINE PyObject* __Pyx_decode_bytearray( start, stop, encoding, errors, decode_func); } +/* GetItemIntUnicode.proto */ +#define __Pyx_GetItemInt_Unicode(o, i, type, is_signed, to_py_func, is_list, wraparound, boundscheck)\ + (__Pyx_fits_Py_ssize_t(i, type, is_signed) ?\ + __Pyx_GetItemInt_Unicode_Fast(o, (Py_ssize_t)i, wraparound, boundscheck) :\ + (PyErr_SetString(PyExc_IndexError, "string index out of range"), (Py_UCS4)-1)) +static CYTHON_INLINE Py_UCS4 __Pyx_GetItemInt_Unicode_Fast(PyObject* ustring, Py_ssize_t i, + int wraparound, int boundscheck); + +/* PyUnicode_Substring.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyUnicode_Substring( + PyObject* text, Py_ssize_t start, Py_ssize_t stop); + /* GetException.proto */ #if CYTHON_FAST_THREAD_STATE #define __Pyx_GetException(type, value, tb) __Pyx__GetException(__pyx_tstate, type, value, tb) @@ -1505,29 +1662,6 @@ static CYTHON_INLINE void __Pyx__ExceptionReset(PyThreadState *tstate, PyObject #define __Pyx_ExceptionReset(type, value, tb) PyErr_SetExcInfo(type, value, tb) #endif -/* decode_c_string.proto */ -static CYTHON_INLINE PyObject* __Pyx_decode_c_string( - const char* cstring, Py_ssize_t start, Py_ssize_t stop, - const char* encoding, const char* errors, - PyObject* (*decode_func)(const char *s, Py_ssize_t size, const char *errors)); - -/* UnpackUnboundCMethod.proto */ -typedef struct { - PyObject *type; - PyObject **method_name; - PyCFunction func; - PyObject *method; - int flag; -} __Pyx_CachedCFunction; - -/* CallUnboundCMethod1.proto */ -static PyObject* __Pyx__CallUnboundCMethod1(__Pyx_CachedCFunction* cfunc, PyObject* self, PyObject* arg); -#if CYTHON_COMPILING_IN_CPYTHON -static CYTHON_INLINE PyObject* __Pyx_CallUnboundCMethod1(__Pyx_CachedCFunction* cfunc, PyObject* self, PyObject* arg); -#else -#define __Pyx_CallUnboundCMethod1(cfunc, self, arg) __Pyx__CallUnboundCMethod1(cfunc, self, arg) -#endif - /* Import.proto */ static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, int level); @@ -1571,6 +1705,12 @@ enum __Pyx_ImportType_CheckSize { static PyTypeObject *__Pyx_ImportType(PyObject* module, const char *module_name, const char *class_name, size_t size, enum __Pyx_ImportType_CheckSize check_size); #endif +/* decode_c_string.proto */ +static CYTHON_INLINE PyObject* __Pyx_decode_c_string( + const char* cstring, Py_ssize_t start, Py_ssize_t stop, + const char* encoding, const char* errors, + PyObject* (*decode_func)(const char *s, Py_ssize_t size, const char *errors)); + /* CLineInTraceback.proto */ #ifdef CYTHON_CLINE_IN_TRACEBACK #define __Pyx_CLineForTraceback(tstate, c_line) (((CYTHON_CLINE_IN_TRACEBACK)) ? c_line : 0) @@ -1597,26 +1737,19 @@ static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object); static void __Pyx_AddTraceback(const char *funcname, int c_line, int py_line, const char *filename); -/* CIntToPy.proto */ -static CYTHON_INLINE PyObject* __Pyx_PyInt_From_int(int value); - -/* CIntToPy.proto */ -static CYTHON_INLINE PyObject* __Pyx_PyInt_From_unsigned_int(unsigned int value); - -/* CIntToPy.proto */ -static CYTHON_INLINE PyObject* __Pyx_PyInt_From_unsigned_short(unsigned short value); - -/* CIntToPy.proto */ -static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value); +/* GCCDiagnostics.proto */ +#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) +#define __Pyx_HAS_GCC_DIAGNOSTIC +#endif /* CIntToPy.proto */ -static CYTHON_INLINE PyObject* __Pyx_PyInt_From_uint16_t(uint16_t value); +static CYTHON_INLINE PyObject* __Pyx_PyInt_From_int(int value); /* CIntFromPy.proto */ static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *); /* CIntFromPy.proto */ -static CYTHON_INLINE enum http_method __Pyx_PyInt_As_enum__http_method(PyObject *); +static CYTHON_INLINE enum llhttp_method __Pyx_PyInt_As_enum__llhttp_method(PyObject *); /* CIntFromPy.proto */ static CYTHON_INLINE size_t __Pyx_PyInt_As_size_t(PyObject *); @@ -1624,6 +1757,12 @@ static CYTHON_INLINE size_t __Pyx_PyInt_As_size_t(PyObject *); /* CIntFromPy.proto */ static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *); +/* CIntToPy.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyInt_From_uint8_t(uint8_t value); + +/* CIntToPy.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value); + /* FastTypeChecks.proto */ #if CYTHON_COMPILING_IN_CPYTHON #define __Pyx_TypeCheck(obj, type) __Pyx_IsSubtype(Py_TYPE(obj), (PyTypeObject *)type) @@ -1669,6 +1808,7 @@ typedef struct { PyObject *gi_qualname; PyObject *gi_modulename; PyObject *gi_code; + PyObject *gi_frame; int resume_label; char is_running; } __pyx_CoroutineObject; @@ -1727,7 +1867,7 @@ static int __Pyx_check_binary_version(void); /* InitStrings.proto */ static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); -static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__init(struct __pyx_obj_7aiohttp_12_http_parser_HttpParser *__pyx_v_self, enum http_parser_type __pyx_v_mode, PyObject *__pyx_v_protocol, PyObject *__pyx_v_loop, int __pyx_v_limit, struct __pyx_opt_args_7aiohttp_12_http_parser_10HttpParser__init *__pyx_optional_args); /* proto*/ +static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__init(struct __pyx_obj_7aiohttp_12_http_parser_HttpParser *__pyx_v_self, enum llhttp_type __pyx_v_mode, PyObject *__pyx_v_protocol, PyObject *__pyx_v_loop, int __pyx_v_limit, struct __pyx_opt_args_7aiohttp_12_http_parser_10HttpParser__init *__pyx_optional_args); /* proto*/ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__process_header(struct __pyx_obj_7aiohttp_12_http_parser_HttpParser *__pyx_v_self); /* proto*/ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_header_field(struct __pyx_obj_7aiohttp_12_http_parser_HttpParser *__pyx_v_self, char *__pyx_v_at, size_t __pyx_v_length); /* proto*/ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_header_value(struct __pyx_obj_7aiohttp_12_http_parser_HttpParser *__pyx_v_self, char *__pyx_v_at, size_t __pyx_v_length); /* proto*/ @@ -1864,18 +2004,17 @@ static CYTHON_INLINE PyObject *__pyx_f_7aiohttp_12_http_parser_http_method_str(i static CYTHON_INLINE PyObject *__pyx_f_7aiohttp_12_http_parser_find_header(PyObject *); /*proto*/ static PyObject *__pyx_f_7aiohttp_12_http_parser__new_request_message(PyObject *, PyObject *, PyObject *, PyObject *, PyObject *, int, PyObject *, int, int, PyObject *); /*proto*/ static PyObject *__pyx_f_7aiohttp_12_http_parser__new_response_message(PyObject *, int, PyObject *, PyObject *, PyObject *, int, PyObject *, int, int); /*proto*/ -static int __pyx_f_7aiohttp_12_http_parser_cb_on_message_begin(struct http_parser *); /*proto*/ -static int __pyx_f_7aiohttp_12_http_parser_cb_on_url(struct http_parser *, char const *, size_t); /*proto*/ -static int __pyx_f_7aiohttp_12_http_parser_cb_on_status(struct http_parser *, char const *, size_t); /*proto*/ -static int __pyx_f_7aiohttp_12_http_parser_cb_on_header_field(struct http_parser *, char const *, size_t); /*proto*/ -static int __pyx_f_7aiohttp_12_http_parser_cb_on_header_value(struct http_parser *, char const *, size_t); /*proto*/ -static int __pyx_f_7aiohttp_12_http_parser_cb_on_headers_complete(struct http_parser *); /*proto*/ -static int __pyx_f_7aiohttp_12_http_parser_cb_on_body(struct http_parser *, char const *, size_t); /*proto*/ -static int __pyx_f_7aiohttp_12_http_parser_cb_on_message_complete(struct http_parser *); /*proto*/ -static int __pyx_f_7aiohttp_12_http_parser_cb_on_chunk_header(struct http_parser *); /*proto*/ -static int __pyx_f_7aiohttp_12_http_parser_cb_on_chunk_complete(struct http_parser *); /*proto*/ -static PyObject *__pyx_f_7aiohttp_12_http_parser_parser_error_from_errno(enum http_errno); /*proto*/ -static PyObject *__pyx_f_7aiohttp_12_http_parser__parse_url(char *, size_t); /*proto*/ +static int __pyx_f_7aiohttp_12_http_parser_cb_on_message_begin(llhttp_t *); /*proto*/ +static int __pyx_f_7aiohttp_12_http_parser_cb_on_url(llhttp_t *, char const *, size_t); /*proto*/ +static int __pyx_f_7aiohttp_12_http_parser_cb_on_status(llhttp_t *, char const *, size_t); /*proto*/ +static int __pyx_f_7aiohttp_12_http_parser_cb_on_header_field(llhttp_t *, char const *, size_t); /*proto*/ +static int __pyx_f_7aiohttp_12_http_parser_cb_on_header_value(llhttp_t *, char const *, size_t); /*proto*/ +static int __pyx_f_7aiohttp_12_http_parser_cb_on_headers_complete(llhttp_t *); /*proto*/ +static int __pyx_f_7aiohttp_12_http_parser_cb_on_body(llhttp_t *, char const *, size_t); /*proto*/ +static int __pyx_f_7aiohttp_12_http_parser_cb_on_message_complete(llhttp_t *); /*proto*/ +static int __pyx_f_7aiohttp_12_http_parser_cb_on_chunk_header(llhttp_t *); /*proto*/ +static int __pyx_f_7aiohttp_12_http_parser_cb_on_chunk_complete(llhttp_t *); /*proto*/ +static PyObject *__pyx_f_7aiohttp_12_http_parser_parser_error_from_errno(llhttp_t *, PyObject *, PyObject *); /*proto*/ static PyObject *__pyx_f_7aiohttp_12_http_parser___pyx_unpickle_RawRequestMessage__set_state(struct __pyx_obj_7aiohttp_12_http_parser_RawRequestMessage *, PyObject *); /*proto*/ static PyObject *__pyx_f_7aiohttp_12_http_parser___pyx_unpickle_RawResponseMessage__set_state(struct __pyx_obj_7aiohttp_12_http_parser_RawResponseMessage *, PyObject *); /*proto*/ #define __Pyx_MODULE_NAME "aiohttp._http_parser" @@ -1889,16 +2028,21 @@ static PyObject *__pyx_builtin_TypeError; static PyObject *__pyx_builtin_BaseException; static const char __pyx_k_[] = "="; static const char __pyx_k_i[] = "i"; +static const char __pyx_k_r[] = "{}:\n\n {!r}\n {}"; static const char __pyx_k_TE[] = "TE"; static const char __pyx_k__2[] = ", "; static const char __pyx_k__3[] = ")>"; -static const char __pyx_k__4[] = ""; +static const char __pyx_k__4[] = "\r\n"; +static const char __pyx_k__6[] = " "; +static const char __pyx_k__7[] = "^"; +static const char __pyx_k__8[] = ""; static const char __pyx_k_br[] = "br"; static const char __pyx_k_AGE[] = "AGE"; static const char __pyx_k_URI[] = "URI"; static const char __pyx_k_URL[] = "URL"; static const char __pyx_k_VIA[] = "VIA"; -static const char __pyx_k__11[] = ":"; +static const char __pyx_k__11[] = "?"; +static const char __pyx_k__12[] = "#"; static const char __pyx_k_add[] = "add"; static const char __pyx_k_all[] = "__all__"; static const char __pyx_k_new[] = "__new__"; @@ -1914,24 +2058,24 @@ static const char __pyx_k_code[] = "code"; static const char __pyx_k_dict[] = "__dict__"; static const char __pyx_k_gzip[] = "gzip"; static const char __pyx_k_hdrs[] = "hdrs"; -static const char __pyx_k_host[] = "host"; static const char __pyx_k_loop[] = "loop"; static const char __pyx_k_main[] = "__main__"; static const char __pyx_k_name[] = "__name__"; static const char __pyx_k_path[] = "path"; -static const char __pyx_k_port[] = "port"; static const char __pyx_k_send[] = "send"; static const char __pyx_k_test[] = "__test__"; -static const char __pyx_k_user[] = "user"; static const char __pyx_k_yarl[] = "yarl"; static const char __pyx_k_ALLOW[] = "ALLOW"; +static const char __pyx_k_DEBUG[] = "DEBUG"; static const char __pyx_k_RANGE[] = "RANGE"; static const char __pyx_k_URL_2[] = "_URL"; static const char __pyx_k_build[] = "build"; static const char __pyx_k_close[] = "close"; +static const char __pyx_k_error[] = "error"; static const char __pyx_k_limit[] = "limit"; static const char __pyx_k_lower[] = "lower"; static const char __pyx_k_range[] = "range"; +static const char __pyx_k_split[] = "split"; static const char __pyx_k_throw[] = "throw"; static const char __pyx_k_timer[] = "timer"; static const char __pyx_k_ACCEPT[] = "ACCEPT"; @@ -1945,10 +2089,9 @@ static const char __pyx_k_format[] = "format"; static const char __pyx_k_import[] = "__import__"; static const char __pyx_k_method[] = "method"; static const char __pyx_k_pickle[] = "pickle"; -static const char __pyx_k_py_buf[] = "py_buf"; static const char __pyx_k_reason[] = "reason"; static const char __pyx_k_reduce[] = "__reduce__"; -static const char __pyx_k_scheme[] = "scheme"; +static const char __pyx_k_rsplit[] = "rsplit"; static const char __pyx_k_update[] = "update"; static const char __pyx_k_EXPIRES[] = "EXPIRES"; static const char __pyx_k_REFERER[] = "REFERER"; @@ -1968,20 +2111,17 @@ static const char __pyx_k_version[] = "version"; static const char __pyx_k_IF_MATCH[] = "IF_MATCH"; static const char __pyx_k_IF_RANGE[] = "IF_RANGE"; static const char __pyx_k_LOCATION[] = "LOCATION"; -static const char __pyx_k_buf_data[] = "buf_data"; static const char __pyx_k_feed_eof[] = "feed_eof"; static const char __pyx_k_fragment[] = "fragment"; static const char __pyx_k_getstate[] = "__getstate__"; -static const char __pyx_k_password[] = "password"; static const char __pyx_k_protocol[] = "protocol"; static const char __pyx_k_pyx_type[] = "__pyx_type"; static const char __pyx_k_setstate[] = "__setstate__"; static const char __pyx_k_FORWARDED[] = "FORWARDED"; static const char __pyx_k_TypeError[] = "TypeError"; +static const char __pyx_k_authority[] = "authority"; static const char __pyx_k_feed_data[] = "feed_data"; static const char __pyx_k_multidict[] = "multidict"; -static const char __pyx_k_parse_url[] = "parse_url"; -static const char __pyx_k_partition[] = "partition"; static const char __pyx_k_pyx_state[] = "__pyx_state"; static const char __pyx_k_reduce_ex[] = "__reduce_ex__"; static const char __pyx_k_CONNECTION[] = "CONNECTION"; @@ -2027,7 +2167,6 @@ static const char __pyx_k_IF_NONE_MATCH[] = "IF_NONE_MATCH"; static const char __pyx_k_InvalidHeader[] = "InvalidHeader"; static const char __pyx_k_LAST_EVENT_ID[] = "LAST_EVENT_ID"; static const char __pyx_k_LAST_MODIFIED[] = "LAST_MODIFIED"; -static const char __pyx_k_invalid_url_r[] = "invalid url {!r}"; static const char __pyx_k_max_line_size[] = "max_line_size"; static const char __pyx_k_reduce_cython[] = "__reduce_cython__"; static const char __pyx_k_set_exception[] = "set_exception"; @@ -2045,6 +2184,7 @@ static const char __pyx_k_HttpVersion10_2[] = "_HttpVersion10"; static const char __pyx_k_HttpVersion11_2[] = "_HttpVersion11"; static const char __pyx_k_InvalidURLError[] = "InvalidURLError"; static const char __pyx_k_X_FORWARDED_FOR[] = "X_FORWARDED_FOR"; +static const char __pyx_k_aiohttp_helpers[] = "aiohttp.helpers"; static const char __pyx_k_auto_decompress[] = "auto_decompress"; static const char __pyx_k_http_exceptions[] = "http_exceptions"; static const char __pyx_k_pyx_PickleError[] = "__pyx_PickleError"; @@ -2087,7 +2227,6 @@ static const char __pyx_k_Header_name_is_too_long[] = "Header name is too long"; static const char __pyx_k_Status_line_is_too_long[] = "Status line is too long"; static const char __pyx_k_Header_value_is_too_long[] = "Header value is too long"; static const char __pyx_k_SEC_WEBSOCKET_EXTENSIONS[] = "SEC_WEBSOCKET_EXTENSIONS"; -static const char __pyx_k_aiohttp__http_parser_pyx[] = "aiohttp/_http_parser.pyx"; static const char __pyx_k_end_http_chunk_receiving[] = "end_http_chunk_receiving"; static const char __pyx_k_CONTENT_TRANSFER_ENCODING[] = "CONTENT_TRANSFER_ENCODING"; static const char __pyx_k_begin_http_chunk_receiving[] = "begin_http_chunk_receiving"; @@ -2100,11 +2239,11 @@ static const char __pyx_k_ACCESS_CONTROL_REQUEST_HEADERS[] = "ACCESS_CONTROL_REQ static const char __pyx_k_pyx_unpickle_RawRequestMessage[] = "__pyx_unpickle_RawRequestMessage"; static const char __pyx_k_pyx_unpickle_RawResponseMessag[] = "__pyx_unpickle_RawResponseMessage"; static const char __pyx_k_ACCESS_CONTROL_ALLOW_CREDENTIALS[] = "ACCESS_CONTROL_ALLOW_CREDENTIALS"; -static const char __pyx_k_Incompatible_checksums_s_vs_0x14[] = "Incompatible checksums (%s vs 0x1408252 = (chunked, compression, headers, method, path, raw_headers, should_close, upgrade, url, version))"; -static const char __pyx_k_Incompatible_checksums_s_vs_0xc7[] = "Incompatible checksums (%s vs 0xc7706dc = (chunked, code, compression, headers, raw_headers, reason, should_close, upgrade, version))"; +static const char __pyx_k_Incompatible_checksums_0x_x_vs_0[] = "Incompatible checksums (0x%x vs (0x1408252, 0xf602a9f, 0x03e51e3) = (chunked, compression, headers, method, path, raw_headers, should_close, upgrade, url, version))"; static const char __pyx_k_Not_enough_data_for_satisfy_cont[] = "Not enough data for satisfy content length header."; static const char __pyx_k_Not_enough_data_for_satisfy_tran[] = "Not enough data for satisfy transfer length header."; static const char __pyx_k_no_default___reduce___due_to_non[] = "no default __reduce__ due to non-trivial __cinit__"; +static const char __pyx_k_Incompatible_checksums_0x_x_vs_0_2[] = "Incompatible checksums (0x%x vs (0xc7706dc, 0xcb2b2ba, 0x4febc0e) = (chunked, code, compression, headers, raw_headers, reason, should_close, upgrade, version))"; static PyObject *__pyx_kp_u_; static PyObject *__pyx_n_s_ACCEPT; static PyObject *__pyx_n_s_ACCEPT_CHARSET; @@ -2143,6 +2282,7 @@ static PyObject *__pyx_n_s_CONTENT_TYPE; static PyObject *__pyx_n_s_COOKIE; static PyObject *__pyx_n_s_ContentLengthError; static PyObject *__pyx_n_s_DATE; +static PyObject *__pyx_n_s_DEBUG; static PyObject *__pyx_n_s_DESTINATION; static PyObject *__pyx_n_s_DIGEST; static PyObject *__pyx_n_s_DeflateBuffer; @@ -2172,8 +2312,8 @@ static PyObject *__pyx_n_s_IF_MODIFIED_SINCE; static PyObject *__pyx_n_s_IF_NONE_MATCH; static PyObject *__pyx_n_s_IF_RANGE; static PyObject *__pyx_n_s_IF_UNMODIFIED_SINCE; -static PyObject *__pyx_kp_s_Incompatible_checksums_s_vs_0x14; -static PyObject *__pyx_kp_s_Incompatible_checksums_s_vs_0xc7; +static PyObject *__pyx_kp_s_Incompatible_checksums_0x_x_vs_0; +static PyObject *__pyx_kp_s_Incompatible_checksums_0x_x_vs_0_2; static PyObject *__pyx_n_s_InvalidHeader; static PyObject *__pyx_n_s_InvalidURLError; static PyObject *__pyx_n_s_KEEP_ALIVE; @@ -2231,21 +2371,25 @@ static PyObject *__pyx_n_s_X_FORWARDED_FOR; static PyObject *__pyx_n_s_X_FORWARDED_HOST; static PyObject *__pyx_n_s_X_FORWARDED_PROTO; static PyObject *__pyx_kp_u__11; +static PyObject *__pyx_kp_u__12; static PyObject *__pyx_kp_u__2; static PyObject *__pyx_kp_u__3; -static PyObject *__pyx_n_s__4; static PyObject *__pyx_kp_b__4; -static PyObject *__pyx_kp_u__4; +static PyObject *__pyx_kp_u__6; +static PyObject *__pyx_kp_u__7; +static PyObject *__pyx_n_s__8; +static PyObject *__pyx_kp_b__8; +static PyObject *__pyx_kp_u__8; static PyObject *__pyx_n_s_add; static PyObject *__pyx_n_s_aiohttp; static PyObject *__pyx_n_s_aiohttp__http_parser; -static PyObject *__pyx_kp_s_aiohttp__http_parser_pyx; +static PyObject *__pyx_n_s_aiohttp_helpers; static PyObject *__pyx_n_s_all; static PyObject *__pyx_n_s_args; +static PyObject *__pyx_n_s_authority; static PyObject *__pyx_n_s_auto_decompress; static PyObject *__pyx_n_s_begin_http_chunk_receiving; static PyObject *__pyx_n_u_br; -static PyObject *__pyx_n_s_buf_data; static PyObject *__pyx_n_s_build; static PyObject *__pyx_n_s_chunked; static PyObject *__pyx_n_u_chunked; @@ -2259,6 +2403,7 @@ static PyObject *__pyx_n_u_deflate; static PyObject *__pyx_n_s_dict; static PyObject *__pyx_n_s_encoded; static PyObject *__pyx_n_s_end_http_chunk_receiving; +static PyObject *__pyx_n_s_error; static PyObject *__pyx_n_s_feed_data; static PyObject *__pyx_n_s_feed_eof; static PyObject *__pyx_n_s_format; @@ -2269,13 +2414,11 @@ static PyObject *__pyx_n_u_gzip; static PyObject *__pyx_n_s_hdrs; static PyObject *__pyx_n_s_headers; static PyObject *__pyx_n_u_headers; -static PyObject *__pyx_n_s_host; static PyObject *__pyx_n_s_http_exceptions; static PyObject *__pyx_n_s_http_parser; static PyObject *__pyx_n_s_http_writer; static PyObject *__pyx_n_s_i; static PyObject *__pyx_n_s_import; -static PyObject *__pyx_kp_u_invalid_url_r; static PyObject *__pyx_n_s_limit; static PyObject *__pyx_n_s_loop; static PyObject *__pyx_n_s_lower; @@ -2289,16 +2432,11 @@ static PyObject *__pyx_n_s_multidict; static PyObject *__pyx_n_s_name; static PyObject *__pyx_n_s_new; static PyObject *__pyx_kp_s_no_default___reduce___due_to_non; -static PyObject *__pyx_n_s_parse_url; -static PyObject *__pyx_n_s_partition; -static PyObject *__pyx_n_s_password; static PyObject *__pyx_n_s_path; static PyObject *__pyx_n_u_path; static PyObject *__pyx_n_s_payload_exception; static PyObject *__pyx_n_s_pickle; -static PyObject *__pyx_n_s_port; static PyObject *__pyx_n_s_protocol; -static PyObject *__pyx_n_s_py_buf; static PyObject *__pyx_n_s_pyx_PickleError; static PyObject *__pyx_n_s_pyx_checksum; static PyObject *__pyx_n_s_pyx_result; @@ -2308,6 +2446,7 @@ static PyObject *__pyx_n_s_pyx_unpickle_RawRequestMessage; static PyObject *__pyx_n_s_pyx_unpickle_RawResponseMessag; static PyObject *__pyx_n_s_pyx_vtable; static PyObject *__pyx_n_s_query_string; +static PyObject *__pyx_kp_u_r; static PyObject *__pyx_n_s_range; static PyObject *__pyx_n_s_raw_headers; static PyObject *__pyx_n_u_raw_headers; @@ -2319,13 +2458,14 @@ static PyObject *__pyx_n_s_reduce_cython; static PyObject *__pyx_n_s_reduce_ex; static PyObject *__pyx_n_s_repr___locals_genexpr; static PyObject *__pyx_n_s_response_with_body; -static PyObject *__pyx_n_s_scheme; +static PyObject *__pyx_n_s_rsplit; static PyObject *__pyx_n_s_send; static PyObject *__pyx_n_s_set_exception; static PyObject *__pyx_n_s_setstate; static PyObject *__pyx_n_s_setstate_cython; static PyObject *__pyx_n_s_should_close; static PyObject *__pyx_n_u_should_close; +static PyObject *__pyx_n_s_split; static PyObject *__pyx_n_s_streams; static PyObject *__pyx_kp_s_stringsource; static PyObject *__pyx_n_s_test; @@ -2337,7 +2477,6 @@ static PyObject *__pyx_n_s_upgrade; static PyObject *__pyx_n_u_upgrade; static PyObject *__pyx_n_s_url; static PyObject *__pyx_n_u_url; -static PyObject *__pyx_n_s_user; static PyObject *__pyx_n_s_version; static PyObject *__pyx_n_u_version; static PyObject *__pyx_n_s_yarl; @@ -2378,15 +2517,14 @@ static PyObject *__pyx_pf_7aiohttp_12_http_parser_10HttpParser_6feed_data(struct static PyObject *__pyx_pf_7aiohttp_12_http_parser_10HttpParser_8set_upgraded(struct __pyx_obj_7aiohttp_12_http_parser_HttpParser *__pyx_v_self, PyObject *__pyx_v_val); /* proto */ static PyObject *__pyx_pf_7aiohttp_12_http_parser_10HttpParser_10__reduce_cython__(CYTHON_UNUSED struct __pyx_obj_7aiohttp_12_http_parser_HttpParser *__pyx_v_self); /* proto */ static PyObject *__pyx_pf_7aiohttp_12_http_parser_10HttpParser_12__setstate_cython__(CYTHON_UNUSED struct __pyx_obj_7aiohttp_12_http_parser_HttpParser *__pyx_v_self, CYTHON_UNUSED PyObject *__pyx_v___pyx_state); /* proto */ -static int __pyx_pf_7aiohttp_12_http_parser_17HttpRequestParser___init__(struct __pyx_obj_7aiohttp_12_http_parser_HttpRequestParser *__pyx_v_self, PyObject *__pyx_v_protocol, PyObject *__pyx_v_loop, int __pyx_v_limit, PyObject *__pyx_v_timer, size_t __pyx_v_max_line_size, size_t __pyx_v_max_headers, size_t __pyx_v_max_field_size, PyObject *__pyx_v_payload_exception, int __pyx_v_response_with_body, int __pyx_v_read_until_eof); /* proto */ +static int __pyx_pf_7aiohttp_12_http_parser_17HttpRequestParser___init__(struct __pyx_obj_7aiohttp_12_http_parser_HttpRequestParser *__pyx_v_self, PyObject *__pyx_v_protocol, PyObject *__pyx_v_loop, int __pyx_v_limit, PyObject *__pyx_v_timer, size_t __pyx_v_max_line_size, size_t __pyx_v_max_headers, size_t __pyx_v_max_field_size, PyObject *__pyx_v_payload_exception, int __pyx_v_response_with_body, int __pyx_v_read_until_eof, int __pyx_v_auto_decompress); /* proto */ static PyObject *__pyx_pf_7aiohttp_12_http_parser_17HttpRequestParser_2__reduce_cython__(CYTHON_UNUSED struct __pyx_obj_7aiohttp_12_http_parser_HttpRequestParser *__pyx_v_self); /* proto */ static PyObject *__pyx_pf_7aiohttp_12_http_parser_17HttpRequestParser_4__setstate_cython__(CYTHON_UNUSED struct __pyx_obj_7aiohttp_12_http_parser_HttpRequestParser *__pyx_v_self, CYTHON_UNUSED PyObject *__pyx_v___pyx_state); /* proto */ static int __pyx_pf_7aiohttp_12_http_parser_18HttpResponseParser___init__(struct __pyx_obj_7aiohttp_12_http_parser_HttpResponseParser *__pyx_v_self, PyObject *__pyx_v_protocol, PyObject *__pyx_v_loop, int __pyx_v_limit, PyObject *__pyx_v_timer, size_t __pyx_v_max_line_size, size_t __pyx_v_max_headers, size_t __pyx_v_max_field_size, PyObject *__pyx_v_payload_exception, int __pyx_v_response_with_body, int __pyx_v_read_until_eof, int __pyx_v_auto_decompress); /* proto */ static PyObject *__pyx_pf_7aiohttp_12_http_parser_18HttpResponseParser_2__reduce_cython__(CYTHON_UNUSED struct __pyx_obj_7aiohttp_12_http_parser_HttpResponseParser *__pyx_v_self); /* proto */ static PyObject *__pyx_pf_7aiohttp_12_http_parser_18HttpResponseParser_4__setstate_cython__(CYTHON_UNUSED struct __pyx_obj_7aiohttp_12_http_parser_HttpResponseParser *__pyx_v_self, CYTHON_UNUSED PyObject *__pyx_v___pyx_state); /* proto */ -static PyObject *__pyx_pf_7aiohttp_12_http_parser_parse_url(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_url); /* proto */ -static PyObject *__pyx_pf_7aiohttp_12_http_parser_2__pyx_unpickle_RawRequestMessage(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v___pyx_type, long __pyx_v___pyx_checksum, PyObject *__pyx_v___pyx_state); /* proto */ -static PyObject *__pyx_pf_7aiohttp_12_http_parser_4__pyx_unpickle_RawResponseMessage(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v___pyx_type, long __pyx_v___pyx_checksum, PyObject *__pyx_v___pyx_state); /* proto */ +static PyObject *__pyx_pf_7aiohttp_12_http_parser___pyx_unpickle_RawRequestMessage(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v___pyx_type, long __pyx_v___pyx_checksum, PyObject *__pyx_v___pyx_state); /* proto */ +static PyObject *__pyx_pf_7aiohttp_12_http_parser_2__pyx_unpickle_RawResponseMessage(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v___pyx_type, long __pyx_v___pyx_checksum, PyObject *__pyx_v___pyx_state); /* proto */ static PyObject *__pyx_tp_new_7aiohttp_12_http_parser_RawRequestMessage(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/ static PyObject *__pyx_tp_new_7aiohttp_12_http_parser_RawResponseMessage(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/ static PyObject *__pyx_tp_new_7aiohttp_12_http_parser_HttpParser(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/ @@ -2396,22 +2534,27 @@ static PyObject *__pyx_tp_new_7aiohttp_12_http_parser___pyx_scope_struct____repr static PyObject *__pyx_tp_new_7aiohttp_12_http_parser___pyx_scope_struct_1_genexpr(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/ static PyObject *__pyx_tp_new_7aiohttp_12_http_parser___pyx_scope_struct_2___repr__(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/ static PyObject *__pyx_tp_new_7aiohttp_12_http_parser___pyx_scope_struct_3_genexpr(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/ -static __Pyx_CachedCFunction __pyx_umethod_PyUnicode_Type_partition = {0, &__pyx_n_s_partition, 0, 0, 0}; +static PyObject *__pyx_int_1; +static PyObject *__pyx_int_4084195; static PyObject *__pyx_int_21004882; +static PyObject *__pyx_int_83803150; static PyObject *__pyx_int_209127132; +static PyObject *__pyx_int_213037754; +static PyObject *__pyx_int_257960607; static PyObject *__pyx_tuple__5; -static PyObject *__pyx_tuple__6; -static PyObject *__pyx_tuple__7; -static PyObject *__pyx_tuple__8; static PyObject *__pyx_tuple__9; static PyObject *__pyx_tuple__10; -static PyObject *__pyx_tuple__12; static PyObject *__pyx_tuple__13; +static PyObject *__pyx_tuple__14; static PyObject *__pyx_tuple__15; +static PyObject *__pyx_tuple__16; static PyObject *__pyx_tuple__17; -static PyObject *__pyx_codeobj__14; -static PyObject *__pyx_codeobj__16; -static PyObject *__pyx_codeobj__18; +static PyObject *__pyx_tuple__18; +static PyObject *__pyx_tuple__19; +static PyObject *__pyx_tuple__20; +static PyObject *__pyx_tuple__22; +static PyObject *__pyx_codeobj__21; +static PyObject *__pyx_codeobj__23; /* Late includes */ /* "aiohttp/_http_parser.pyx":74 @@ -2516,7 +2659,7 @@ static CYTHON_INLINE PyObject *__pyx_f_7aiohttp_12_http_parser_http_method_str(i * return _http_method[i] * else: */ - __pyx_t_1 = ((__pyx_v_i < 34) != 0); + __pyx_t_1 = ((__pyx_v_i < 46) != 0); if (__pyx_t_1) { /* "aiohttp/_http_parser.pyx":94 @@ -3225,6 +3368,7 @@ static PyObject *__pyx_gb_7aiohttp_12_http_parser_17RawRequestMessage_8__repr___ static PyObject *__pyx_pf_7aiohttp_12_http_parser_17RawRequestMessage_2__repr__(struct __pyx_obj_7aiohttp_12_http_parser_RawRequestMessage *__pyx_v_self) { struct __pyx_obj_7aiohttp_12_http_parser___pyx_scope_struct____repr__ *__pyx_cur_scope; PyObject *__pyx_v_sinfo = NULL; + PyObject *__pyx_gb_7aiohttp_12_http_parser_17RawRequestMessage_8__repr___2generator = 0; PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; @@ -3487,6 +3631,7 @@ static PyObject *__pyx_pf_7aiohttp_12_http_parser_17RawRequestMessage_2__repr__( __pyx_r = NULL; __pyx_L0:; __Pyx_XDECREF(__pyx_v_sinfo); + __Pyx_XDECREF(__pyx_gb_7aiohttp_12_http_parser_17RawRequestMessage_8__repr___2generator); __Pyx_DECREF(((PyObject *)__pyx_cur_scope)); __Pyx_XGIVEREF(__pyx_r); __Pyx_RefNannyFinishContext(); @@ -5506,6 +5651,7 @@ static PyObject *__pyx_gb_7aiohttp_12_http_parser_18RawResponseMessage_8__repr__ static PyObject *__pyx_pf_7aiohttp_12_http_parser_18RawResponseMessage_2__repr__(struct __pyx_obj_7aiohttp_12_http_parser_RawResponseMessage *__pyx_v_self) { struct __pyx_obj_7aiohttp_12_http_parser___pyx_scope_struct_2___repr__ *__pyx_cur_scope; PyObject *__pyx_v_sinfo = NULL; + PyObject *__pyx_gb_7aiohttp_12_http_parser_18RawResponseMessage_8__repr___2generator1 = 0; PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; @@ -5752,6 +5898,7 @@ static PyObject *__pyx_pf_7aiohttp_12_http_parser_18RawResponseMessage_2__repr__ __pyx_r = NULL; __pyx_L0:; __Pyx_XDECREF(__pyx_v_sinfo); + __Pyx_XDECREF(__pyx_gb_7aiohttp_12_http_parser_18RawResponseMessage_8__repr___2generator1); __Pyx_DECREF(((PyObject *)__pyx_cur_scope)); __Pyx_XGIVEREF(__pyx_r); __Pyx_RefNannyFinishContext(); @@ -6658,8 +6805,8 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser__new_response_message(PyObject * Py_buffer py_buf * * def __cinit__(self): # <<<<<<<<<<<<<< - * self._cparser = \ - * PyMem_Malloc(sizeof(cparser.http_parser)) + * self._cparser = \ + * PyMem_Malloc(sizeof(cparser.llhttp_t)) */ /* Python wrapper */ @@ -6690,15 +6837,15 @@ static int __pyx_pf_7aiohttp_12_http_parser_10HttpParser___cinit__(struct __pyx_ /* "aiohttp/_http_parser.pyx":313 * * def __cinit__(self): - * self._cparser = \ # <<<<<<<<<<<<<< - * PyMem_Malloc(sizeof(cparser.http_parser)) + * self._cparser = \ # <<<<<<<<<<<<<< + * PyMem_Malloc(sizeof(cparser.llhttp_t)) * if self._cparser is NULL: */ - __pyx_v_self->_cparser = ((struct http_parser *)PyMem_Malloc((sizeof(struct http_parser)))); + __pyx_v_self->_cparser = ((llhttp_t *)PyMem_Malloc((sizeof(llhttp_t)))); /* "aiohttp/_http_parser.pyx":315 - * self._cparser = \ - * PyMem_Malloc(sizeof(cparser.http_parser)) + * self._cparser = \ + * PyMem_Malloc(sizeof(cparser.llhttp_t)) * if self._cparser is NULL: # <<<<<<<<<<<<<< * raise MemoryError() * @@ -6707,17 +6854,17 @@ static int __pyx_pf_7aiohttp_12_http_parser_10HttpParser___cinit__(struct __pyx_ if (unlikely(__pyx_t_1)) { /* "aiohttp/_http_parser.pyx":316 - * PyMem_Malloc(sizeof(cparser.http_parser)) + * PyMem_Malloc(sizeof(cparser.llhttp_t)) * if self._cparser is NULL: * raise MemoryError() # <<<<<<<<<<<<<< * - * self._csettings = \ + * self._csettings = \ */ PyErr_NoMemory(); __PYX_ERR(0, 316, __pyx_L1_error) /* "aiohttp/_http_parser.pyx":315 - * self._cparser = \ - * PyMem_Malloc(sizeof(cparser.http_parser)) + * self._cparser = \ + * PyMem_Malloc(sizeof(cparser.llhttp_t)) * if self._cparser is NULL: # <<<<<<<<<<<<<< * raise MemoryError() * @@ -6727,15 +6874,15 @@ static int __pyx_pf_7aiohttp_12_http_parser_10HttpParser___cinit__(struct __pyx_ /* "aiohttp/_http_parser.pyx":318 * raise MemoryError() * - * self._csettings = \ # <<<<<<<<<<<<<< - * PyMem_Malloc(sizeof(cparser.http_parser_settings)) + * self._csettings = \ # <<<<<<<<<<<<<< + * PyMem_Malloc(sizeof(cparser.llhttp_settings_t)) * if self._csettings is NULL: */ - __pyx_v_self->_csettings = ((struct http_parser_settings *)PyMem_Malloc((sizeof(struct http_parser_settings)))); + __pyx_v_self->_csettings = ((llhttp_settings_t *)PyMem_Malloc((sizeof(llhttp_settings_t)))); /* "aiohttp/_http_parser.pyx":320 - * self._csettings = \ - * PyMem_Malloc(sizeof(cparser.http_parser_settings)) + * self._csettings = \ + * PyMem_Malloc(sizeof(cparser.llhttp_settings_t)) * if self._csettings is NULL: # <<<<<<<<<<<<<< * raise MemoryError() * @@ -6744,7 +6891,7 @@ static int __pyx_pf_7aiohttp_12_http_parser_10HttpParser___cinit__(struct __pyx_ if (unlikely(__pyx_t_1)) { /* "aiohttp/_http_parser.pyx":321 - * PyMem_Malloc(sizeof(cparser.http_parser_settings)) + * PyMem_Malloc(sizeof(cparser.llhttp_settings_t)) * if self._csettings is NULL: * raise MemoryError() # <<<<<<<<<<<<<< * @@ -6753,8 +6900,8 @@ static int __pyx_pf_7aiohttp_12_http_parser_10HttpParser___cinit__(struct __pyx_ PyErr_NoMemory(); __PYX_ERR(0, 321, __pyx_L1_error) /* "aiohttp/_http_parser.pyx":320 - * self._csettings = \ - * PyMem_Malloc(sizeof(cparser.http_parser_settings)) + * self._csettings = \ + * PyMem_Malloc(sizeof(cparser.llhttp_settings_t)) * if self._csettings is NULL: # <<<<<<<<<<<<<< * raise MemoryError() * @@ -6765,8 +6912,8 @@ static int __pyx_pf_7aiohttp_12_http_parser_10HttpParser___cinit__(struct __pyx_ * Py_buffer py_buf * * def __cinit__(self): # <<<<<<<<<<<<<< - * self._cparser = \ - * PyMem_Malloc(sizeof(cparser.http_parser)) + * self._cparser = \ + * PyMem_Malloc(sizeof(cparser.llhttp_t)) */ /* function exit code */ @@ -6817,7 +6964,7 @@ static void __pyx_pf_7aiohttp_12_http_parser_10HttpParser_2__dealloc__(struct __ * PyMem_Free(self._cparser) * PyMem_Free(self._csettings) # <<<<<<<<<<<<<< * - * cdef _init(self, cparser.http_parser_type mode, + * cdef _init( */ PyMem_Free(__pyx_v_self->_csettings); @@ -6836,50 +6983,50 @@ static void __pyx_pf_7aiohttp_12_http_parser_10HttpParser_2__dealloc__(struct __ /* "aiohttp/_http_parser.pyx":327 * PyMem_Free(self._csettings) * - * cdef _init(self, cparser.http_parser_type mode, # <<<<<<<<<<<<<< - * object protocol, object loop, int limit, - * object timer=None, + * cdef _init( # <<<<<<<<<<<<<< + * self, cparser.llhttp_type mode, + * object protocol, object loop, int limit, */ -static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__init(struct __pyx_obj_7aiohttp_12_http_parser_HttpParser *__pyx_v_self, enum http_parser_type __pyx_v_mode, PyObject *__pyx_v_protocol, PyObject *__pyx_v_loop, int __pyx_v_limit, struct __pyx_opt_args_7aiohttp_12_http_parser_10HttpParser__init *__pyx_optional_args) { +static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__init(struct __pyx_obj_7aiohttp_12_http_parser_HttpParser *__pyx_v_self, enum llhttp_type __pyx_v_mode, PyObject *__pyx_v_protocol, PyObject *__pyx_v_loop, int __pyx_v_limit, struct __pyx_opt_args_7aiohttp_12_http_parser_10HttpParser__init *__pyx_optional_args) { - /* "aiohttp/_http_parser.pyx":329 - * cdef _init(self, cparser.http_parser_type mode, - * object protocol, object loop, int limit, - * object timer=None, # <<<<<<<<<<<<<< - * size_t max_line_size=8190, size_t max_headers=32768, - * size_t max_field_size=8190, payload_exception=None, + /* "aiohttp/_http_parser.pyx":330 + * self, cparser.llhttp_type mode, + * object protocol, object loop, int limit, + * object timer=None, # <<<<<<<<<<<<<< + * size_t max_line_size=8190, size_t max_headers=32768, + * size_t max_field_size=8190, payload_exception=None, */ PyObject *__pyx_v_timer = ((PyObject *)Py_None); size_t __pyx_v_max_line_size = ((size_t)0x1FFE); size_t __pyx_v_max_headers = ((size_t)0x8000); size_t __pyx_v_max_field_size = ((size_t)0x1FFE); - /* "aiohttp/_http_parser.pyx":331 - * object timer=None, - * size_t max_line_size=8190, size_t max_headers=32768, - * size_t max_field_size=8190, payload_exception=None, # <<<<<<<<<<<<<< - * bint response_with_body=True, bint read_until_eof=False, - * bint auto_decompress=True): + /* "aiohttp/_http_parser.pyx":332 + * object timer=None, + * size_t max_line_size=8190, size_t max_headers=32768, + * size_t max_field_size=8190, payload_exception=None, # <<<<<<<<<<<<<< + * bint response_with_body=True, bint read_until_eof=False, + * bint auto_decompress=True, */ PyObject *__pyx_v_payload_exception = ((PyObject *)Py_None); - /* "aiohttp/_http_parser.pyx":332 - * size_t max_line_size=8190, size_t max_headers=32768, - * size_t max_field_size=8190, payload_exception=None, - * bint response_with_body=True, bint read_until_eof=False, # <<<<<<<<<<<<<< - * bint auto_decompress=True): - * cparser.http_parser_init(self._cparser, mode) + /* "aiohttp/_http_parser.pyx":333 + * size_t max_line_size=8190, size_t max_headers=32768, + * size_t max_field_size=8190, payload_exception=None, + * bint response_with_body=True, bint read_until_eof=False, # <<<<<<<<<<<<<< + * bint auto_decompress=True, + * ): */ int __pyx_v_response_with_body = ((int)1); int __pyx_v_read_until_eof = ((int)0); - /* "aiohttp/_http_parser.pyx":333 - * size_t max_field_size=8190, payload_exception=None, - * bint response_with_body=True, bint read_until_eof=False, - * bint auto_decompress=True): # <<<<<<<<<<<<<< - * cparser.http_parser_init(self._cparser, mode) - * self._cparser.data = self + /* "aiohttp/_http_parser.pyx":334 + * size_t max_field_size=8190, payload_exception=None, + * bint response_with_body=True, bint read_until_eof=False, + * bint auto_decompress=True, # <<<<<<<<<<<<<< + * ): + * cparser.llhttp_settings_init(self._csettings) */ int __pyx_v_auto_decompress = ((int)1); PyObject *__pyx_r = NULL; @@ -6916,45 +7063,45 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__init(struct __pyx } } - /* "aiohttp/_http_parser.pyx":334 - * bint response_with_body=True, bint read_until_eof=False, - * bint auto_decompress=True): - * cparser.http_parser_init(self._cparser, mode) # <<<<<<<<<<<<<< + /* "aiohttp/_http_parser.pyx":336 + * bint auto_decompress=True, + * ): + * cparser.llhttp_settings_init(self._csettings) # <<<<<<<<<<<<<< + * cparser.llhttp_init(self._cparser, mode, self._csettings) + * self._cparser.data = self + */ + llhttp_settings_init(__pyx_v_self->_csettings); + + /* "aiohttp/_http_parser.pyx":337 + * ): + * cparser.llhttp_settings_init(self._csettings) + * cparser.llhttp_init(self._cparser, mode, self._csettings) # <<<<<<<<<<<<<< * self._cparser.data = self * self._cparser.content_length = 0 */ - http_parser_init(__pyx_v_self->_cparser, __pyx_v_mode); + llhttp_init(__pyx_v_self->_cparser, __pyx_v_mode, __pyx_v_self->_csettings); - /* "aiohttp/_http_parser.pyx":335 - * bint auto_decompress=True): - * cparser.http_parser_init(self._cparser, mode) + /* "aiohttp/_http_parser.pyx":338 + * cparser.llhttp_settings_init(self._csettings) + * cparser.llhttp_init(self._cparser, mode, self._csettings) * self._cparser.data = self # <<<<<<<<<<<<<< * self._cparser.content_length = 0 * */ __pyx_v_self->_cparser->data = ((void *)__pyx_v_self); - /* "aiohttp/_http_parser.pyx":336 - * cparser.http_parser_init(self._cparser, mode) + /* "aiohttp/_http_parser.pyx":339 + * cparser.llhttp_init(self._cparser, mode, self._csettings) * self._cparser.data = self * self._cparser.content_length = 0 # <<<<<<<<<<<<<< * - * cparser.http_parser_settings_init(self._csettings) + * self._protocol = protocol */ __pyx_v_self->_cparser->content_length = 0; - /* "aiohttp/_http_parser.pyx":338 + /* "aiohttp/_http_parser.pyx":341 * self._cparser.content_length = 0 * - * cparser.http_parser_settings_init(self._csettings) # <<<<<<<<<<<<<< - * - * self._protocol = protocol - */ - http_parser_settings_init(__pyx_v_self->_csettings); - - /* "aiohttp/_http_parser.pyx":340 - * cparser.http_parser_settings_init(self._csettings) - * * self._protocol = protocol # <<<<<<<<<<<<<< * self._loop = loop * self._timer = timer @@ -6965,7 +7112,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__init(struct __pyx __Pyx_DECREF(__pyx_v_self->_protocol); __pyx_v_self->_protocol = __pyx_v_protocol; - /* "aiohttp/_http_parser.pyx":341 + /* "aiohttp/_http_parser.pyx":342 * * self._protocol = protocol * self._loop = loop # <<<<<<<<<<<<<< @@ -6978,7 +7125,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__init(struct __pyx __Pyx_DECREF(__pyx_v_self->_loop); __pyx_v_self->_loop = __pyx_v_loop; - /* "aiohttp/_http_parser.pyx":342 + /* "aiohttp/_http_parser.pyx":343 * self._protocol = protocol * self._loop = loop * self._timer = timer # <<<<<<<<<<<<<< @@ -6991,14 +7138,14 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__init(struct __pyx __Pyx_DECREF(__pyx_v_self->_timer); __pyx_v_self->_timer = __pyx_v_timer; - /* "aiohttp/_http_parser.pyx":344 + /* "aiohttp/_http_parser.pyx":345 * self._timer = timer * * self._buf = bytearray() # <<<<<<<<<<<<<< * self._payload = None * self._payload_error = 0 */ - __pyx_t_1 = __Pyx_PyObject_CallNoArg(((PyObject *)(&PyByteArray_Type))); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 344, __pyx_L1_error) + __pyx_t_1 = __Pyx_PyObject_CallNoArg(((PyObject *)(&PyByteArray_Type))); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 345, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_GIVEREF(__pyx_t_1); __Pyx_GOTREF(__pyx_v_self->_buf); @@ -7006,7 +7153,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__init(struct __pyx __pyx_v_self->_buf = ((PyObject*)__pyx_t_1); __pyx_t_1 = 0; - /* "aiohttp/_http_parser.pyx":345 + /* "aiohttp/_http_parser.pyx":346 * * self._buf = bytearray() * self._payload = None # <<<<<<<<<<<<<< @@ -7019,7 +7166,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__init(struct __pyx __Pyx_DECREF(__pyx_v_self->_payload); __pyx_v_self->_payload = Py_None; - /* "aiohttp/_http_parser.pyx":346 + /* "aiohttp/_http_parser.pyx":347 * self._buf = bytearray() * self._payload = None * self._payload_error = 0 # <<<<<<<<<<<<<< @@ -7028,7 +7175,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__init(struct __pyx */ __pyx_v_self->_payload_error = 0; - /* "aiohttp/_http_parser.pyx":347 + /* "aiohttp/_http_parser.pyx":348 * self._payload = None * self._payload_error = 0 * self._payload_exception = payload_exception # <<<<<<<<<<<<<< @@ -7041,14 +7188,14 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__init(struct __pyx __Pyx_DECREF(__pyx_v_self->_payload_exception); __pyx_v_self->_payload_exception = __pyx_v_payload_exception; - /* "aiohttp/_http_parser.pyx":348 + /* "aiohttp/_http_parser.pyx":349 * self._payload_error = 0 * self._payload_exception = payload_exception * self._messages = [] # <<<<<<<<<<<<<< * * self._raw_name = bytearray() */ - __pyx_t_1 = PyList_New(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 348, __pyx_L1_error) + __pyx_t_1 = PyList_New(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 349, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_GIVEREF(__pyx_t_1); __Pyx_GOTREF(__pyx_v_self->_messages); @@ -7056,14 +7203,14 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__init(struct __pyx __pyx_v_self->_messages = ((PyObject*)__pyx_t_1); __pyx_t_1 = 0; - /* "aiohttp/_http_parser.pyx":350 + /* "aiohttp/_http_parser.pyx":351 * self._messages = [] * * self._raw_name = bytearray() # <<<<<<<<<<<<<< * self._raw_value = bytearray() * self._has_value = False */ - __pyx_t_1 = __Pyx_PyObject_CallNoArg(((PyObject *)(&PyByteArray_Type))); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 350, __pyx_L1_error) + __pyx_t_1 = __Pyx_PyObject_CallNoArg(((PyObject *)(&PyByteArray_Type))); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 351, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_GIVEREF(__pyx_t_1); __Pyx_GOTREF(__pyx_v_self->_raw_name); @@ -7071,14 +7218,14 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__init(struct __pyx __pyx_v_self->_raw_name = ((PyObject*)__pyx_t_1); __pyx_t_1 = 0; - /* "aiohttp/_http_parser.pyx":351 + /* "aiohttp/_http_parser.pyx":352 * * self._raw_name = bytearray() * self._raw_value = bytearray() # <<<<<<<<<<<<<< * self._has_value = False * */ - __pyx_t_1 = __Pyx_PyObject_CallNoArg(((PyObject *)(&PyByteArray_Type))); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 351, __pyx_L1_error) + __pyx_t_1 = __Pyx_PyObject_CallNoArg(((PyObject *)(&PyByteArray_Type))); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 352, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_GIVEREF(__pyx_t_1); __Pyx_GOTREF(__pyx_v_self->_raw_value); @@ -7086,7 +7233,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__init(struct __pyx __pyx_v_self->_raw_value = ((PyObject*)__pyx_t_1); __pyx_t_1 = 0; - /* "aiohttp/_http_parser.pyx":352 + /* "aiohttp/_http_parser.pyx":353 * self._raw_name = bytearray() * self._raw_value = bytearray() * self._has_value = False # <<<<<<<<<<<<<< @@ -7095,7 +7242,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__init(struct __pyx */ __pyx_v_self->_has_value = 0; - /* "aiohttp/_http_parser.pyx":354 + /* "aiohttp/_http_parser.pyx":355 * self._has_value = False * * self._max_line_size = max_line_size # <<<<<<<<<<<<<< @@ -7104,7 +7251,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__init(struct __pyx */ __pyx_v_self->_max_line_size = __pyx_v_max_line_size; - /* "aiohttp/_http_parser.pyx":355 + /* "aiohttp/_http_parser.pyx":356 * * self._max_line_size = max_line_size * self._max_headers = max_headers # <<<<<<<<<<<<<< @@ -7113,7 +7260,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__init(struct __pyx */ __pyx_v_self->_max_headers = __pyx_v_max_headers; - /* "aiohttp/_http_parser.pyx":356 + /* "aiohttp/_http_parser.pyx":357 * self._max_line_size = max_line_size * self._max_headers = max_headers * self._max_field_size = max_field_size # <<<<<<<<<<<<<< @@ -7122,7 +7269,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__init(struct __pyx */ __pyx_v_self->_max_field_size = __pyx_v_max_field_size; - /* "aiohttp/_http_parser.pyx":357 + /* "aiohttp/_http_parser.pyx":358 * self._max_headers = max_headers * self._max_field_size = max_field_size * self._response_with_body = response_with_body # <<<<<<<<<<<<<< @@ -7131,7 +7278,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__init(struct __pyx */ __pyx_v_self->_response_with_body = __pyx_v_response_with_body; - /* "aiohttp/_http_parser.pyx":358 + /* "aiohttp/_http_parser.pyx":359 * self._max_field_size = max_field_size * self._response_with_body = response_with_body * self._read_until_eof = read_until_eof # <<<<<<<<<<<<<< @@ -7140,7 +7287,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__init(struct __pyx */ __pyx_v_self->_read_until_eof = __pyx_v_read_until_eof; - /* "aiohttp/_http_parser.pyx":359 + /* "aiohttp/_http_parser.pyx":360 * self._response_with_body = response_with_body * self._read_until_eof = read_until_eof * self._upgraded = False # <<<<<<<<<<<<<< @@ -7149,7 +7296,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__init(struct __pyx */ __pyx_v_self->_upgraded = 0; - /* "aiohttp/_http_parser.pyx":360 + /* "aiohttp/_http_parser.pyx":361 * self._read_until_eof = read_until_eof * self._upgraded = False * self._auto_decompress = auto_decompress # <<<<<<<<<<<<<< @@ -7158,7 +7305,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__init(struct __pyx */ __pyx_v_self->_auto_decompress = __pyx_v_auto_decompress; - /* "aiohttp/_http_parser.pyx":361 + /* "aiohttp/_http_parser.pyx":362 * self._upgraded = False * self._auto_decompress = auto_decompress * self._content_encoding = None # <<<<<<<<<<<<<< @@ -7171,7 +7318,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__init(struct __pyx __Pyx_DECREF(__pyx_v_self->_content_encoding); __pyx_v_self->_content_encoding = ((PyObject*)Py_None); - /* "aiohttp/_http_parser.pyx":363 + /* "aiohttp/_http_parser.pyx":364 * self._content_encoding = None * * self._csettings.on_url = cb_on_url # <<<<<<<<<<<<<< @@ -7180,7 +7327,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__init(struct __pyx */ __pyx_v_self->_csettings->on_url = __pyx_f_7aiohttp_12_http_parser_cb_on_url; - /* "aiohttp/_http_parser.pyx":364 + /* "aiohttp/_http_parser.pyx":365 * * self._csettings.on_url = cb_on_url * self._csettings.on_status = cb_on_status # <<<<<<<<<<<<<< @@ -7189,7 +7336,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__init(struct __pyx */ __pyx_v_self->_csettings->on_status = __pyx_f_7aiohttp_12_http_parser_cb_on_status; - /* "aiohttp/_http_parser.pyx":365 + /* "aiohttp/_http_parser.pyx":366 * self._csettings.on_url = cb_on_url * self._csettings.on_status = cb_on_status * self._csettings.on_header_field = cb_on_header_field # <<<<<<<<<<<<<< @@ -7198,7 +7345,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__init(struct __pyx */ __pyx_v_self->_csettings->on_header_field = __pyx_f_7aiohttp_12_http_parser_cb_on_header_field; - /* "aiohttp/_http_parser.pyx":366 + /* "aiohttp/_http_parser.pyx":367 * self._csettings.on_status = cb_on_status * self._csettings.on_header_field = cb_on_header_field * self._csettings.on_header_value = cb_on_header_value # <<<<<<<<<<<<<< @@ -7207,7 +7354,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__init(struct __pyx */ __pyx_v_self->_csettings->on_header_value = __pyx_f_7aiohttp_12_http_parser_cb_on_header_value; - /* "aiohttp/_http_parser.pyx":367 + /* "aiohttp/_http_parser.pyx":368 * self._csettings.on_header_field = cb_on_header_field * self._csettings.on_header_value = cb_on_header_value * self._csettings.on_headers_complete = cb_on_headers_complete # <<<<<<<<<<<<<< @@ -7216,7 +7363,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__init(struct __pyx */ __pyx_v_self->_csettings->on_headers_complete = __pyx_f_7aiohttp_12_http_parser_cb_on_headers_complete; - /* "aiohttp/_http_parser.pyx":368 + /* "aiohttp/_http_parser.pyx":369 * self._csettings.on_header_value = cb_on_header_value * self._csettings.on_headers_complete = cb_on_headers_complete * self._csettings.on_body = cb_on_body # <<<<<<<<<<<<<< @@ -7225,7 +7372,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__init(struct __pyx */ __pyx_v_self->_csettings->on_body = __pyx_f_7aiohttp_12_http_parser_cb_on_body; - /* "aiohttp/_http_parser.pyx":369 + /* "aiohttp/_http_parser.pyx":370 * self._csettings.on_headers_complete = cb_on_headers_complete * self._csettings.on_body = cb_on_body * self._csettings.on_message_begin = cb_on_message_begin # <<<<<<<<<<<<<< @@ -7234,7 +7381,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__init(struct __pyx */ __pyx_v_self->_csettings->on_message_begin = __pyx_f_7aiohttp_12_http_parser_cb_on_message_begin; - /* "aiohttp/_http_parser.pyx":370 + /* "aiohttp/_http_parser.pyx":371 * self._csettings.on_body = cb_on_body * self._csettings.on_message_begin = cb_on_message_begin * self._csettings.on_message_complete = cb_on_message_complete # <<<<<<<<<<<<<< @@ -7243,7 +7390,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__init(struct __pyx */ __pyx_v_self->_csettings->on_message_complete = __pyx_f_7aiohttp_12_http_parser_cb_on_message_complete; - /* "aiohttp/_http_parser.pyx":371 + /* "aiohttp/_http_parser.pyx":372 * self._csettings.on_message_begin = cb_on_message_begin * self._csettings.on_message_complete = cb_on_message_complete * self._csettings.on_chunk_header = cb_on_chunk_header # <<<<<<<<<<<<<< @@ -7252,7 +7399,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__init(struct __pyx */ __pyx_v_self->_csettings->on_chunk_header = __pyx_f_7aiohttp_12_http_parser_cb_on_chunk_header; - /* "aiohttp/_http_parser.pyx":372 + /* "aiohttp/_http_parser.pyx":373 * self._csettings.on_message_complete = cb_on_message_complete * self._csettings.on_chunk_header = cb_on_chunk_header * self._csettings.on_chunk_complete = cb_on_chunk_complete # <<<<<<<<<<<<<< @@ -7261,7 +7408,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__init(struct __pyx */ __pyx_v_self->_csettings->on_chunk_complete = __pyx_f_7aiohttp_12_http_parser_cb_on_chunk_complete; - /* "aiohttp/_http_parser.pyx":374 + /* "aiohttp/_http_parser.pyx":375 * self._csettings.on_chunk_complete = cb_on_chunk_complete * * self._last_error = None # <<<<<<<<<<<<<< @@ -7274,7 +7421,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__init(struct __pyx __Pyx_DECREF(__pyx_v_self->_last_error); __pyx_v_self->_last_error = Py_None; - /* "aiohttp/_http_parser.pyx":375 + /* "aiohttp/_http_parser.pyx":376 * * self._last_error = None * self._limit = limit # <<<<<<<<<<<<<< @@ -7286,9 +7433,9 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__init(struct __pyx /* "aiohttp/_http_parser.pyx":327 * PyMem_Free(self._csettings) * - * cdef _init(self, cparser.http_parser_type mode, # <<<<<<<<<<<<<< - * object protocol, object loop, int limit, - * object timer=None, + * cdef _init( # <<<<<<<<<<<<<< + * self, cparser.llhttp_type mode, + * object protocol, object loop, int limit, */ /* function exit code */ @@ -7304,7 +7451,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__init(struct __pyx return __pyx_r; } -/* "aiohttp/_http_parser.pyx":377 +/* "aiohttp/_http_parser.pyx":378 * self._limit = limit * * cdef _process_header(self): # <<<<<<<<<<<<<< @@ -7332,7 +7479,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__process_header(st int __pyx_clineno = 0; __Pyx_RefNannySetupContext("_process_header", 0); - /* "aiohttp/_http_parser.pyx":378 + /* "aiohttp/_http_parser.pyx":379 * * cdef _process_header(self): * if self._raw_name: # <<<<<<<<<<<<<< @@ -7342,62 +7489,62 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__process_header(st __pyx_t_1 = (__pyx_v_self->_raw_name != Py_None)&&(PyByteArray_GET_SIZE(__pyx_v_self->_raw_name) != 0); if (__pyx_t_1) { - /* "aiohttp/_http_parser.pyx":379 + /* "aiohttp/_http_parser.pyx":380 * cdef _process_header(self): * if self._raw_name: * raw_name = bytes(self._raw_name) # <<<<<<<<<<<<<< * raw_value = bytes(self._raw_value) * */ - __pyx_t_2 = __Pyx_PyObject_CallOneArg(((PyObject *)(&PyBytes_Type)), __pyx_v_self->_raw_name); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 379, __pyx_L1_error) + __pyx_t_2 = __Pyx_PyObject_CallOneArg(((PyObject *)(&PyBytes_Type)), __pyx_v_self->_raw_name); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 380, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); __pyx_v_raw_name = ((PyObject*)__pyx_t_2); __pyx_t_2 = 0; - /* "aiohttp/_http_parser.pyx":380 + /* "aiohttp/_http_parser.pyx":381 * if self._raw_name: * raw_name = bytes(self._raw_name) * raw_value = bytes(self._raw_value) # <<<<<<<<<<<<<< * * name = find_header(raw_name) */ - __pyx_t_2 = __Pyx_PyObject_CallOneArg(((PyObject *)(&PyBytes_Type)), __pyx_v_self->_raw_value); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 380, __pyx_L1_error) + __pyx_t_2 = __Pyx_PyObject_CallOneArg(((PyObject *)(&PyBytes_Type)), __pyx_v_self->_raw_value); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 381, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); __pyx_v_raw_value = ((PyObject*)__pyx_t_2); __pyx_t_2 = 0; - /* "aiohttp/_http_parser.pyx":382 + /* "aiohttp/_http_parser.pyx":383 * raw_value = bytes(self._raw_value) * * name = find_header(raw_name) # <<<<<<<<<<<<<< * value = raw_value.decode('utf-8', 'surrogateescape') * */ - __pyx_t_2 = __pyx_f_7aiohttp_12_http_parser_find_header(__pyx_v_raw_name); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 382, __pyx_L1_error) + __pyx_t_2 = __pyx_f_7aiohttp_12_http_parser_find_header(__pyx_v_raw_name); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 383, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); __pyx_v_name = __pyx_t_2; __pyx_t_2 = 0; - /* "aiohttp/_http_parser.pyx":383 + /* "aiohttp/_http_parser.pyx":384 * * name = find_header(raw_name) * value = raw_value.decode('utf-8', 'surrogateescape') # <<<<<<<<<<<<<< * * self._headers.add(name, value) */ - __pyx_t_2 = __Pyx_decode_bytes(__pyx_v_raw_value, 0, PY_SSIZE_T_MAX, NULL, ((char const *)"surrogateescape"), PyUnicode_DecodeUTF8); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 383, __pyx_L1_error) + __pyx_t_2 = __Pyx_decode_bytes(__pyx_v_raw_value, 0, PY_SSIZE_T_MAX, NULL, ((char const *)"surrogateescape"), PyUnicode_DecodeUTF8); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 384, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); __pyx_v_value = __pyx_t_2; __pyx_t_2 = 0; - /* "aiohttp/_http_parser.pyx":385 + /* "aiohttp/_http_parser.pyx":386 * value = raw_value.decode('utf-8', 'surrogateescape') * * self._headers.add(name, value) # <<<<<<<<<<<<<< * * if name is CONTENT_ENCODING: */ - __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_self->_headers, __pyx_n_s_add); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 385, __pyx_L1_error) + __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_self->_headers, __pyx_n_s_add); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 386, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_4 = NULL; __pyx_t_5 = 0; @@ -7414,7 +7561,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__process_header(st #if CYTHON_FAST_PYCALL if (PyFunction_Check(__pyx_t_3)) { PyObject *__pyx_temp[3] = {__pyx_t_4, __pyx_v_name, __pyx_v_value}; - __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_5, 2+__pyx_t_5); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 385, __pyx_L1_error) + __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_5, 2+__pyx_t_5); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 386, __pyx_L1_error) __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; __Pyx_GOTREF(__pyx_t_2); } else @@ -7422,13 +7569,13 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__process_header(st #if CYTHON_FAST_PYCCALL if (__Pyx_PyFastCFunction_Check(__pyx_t_3)) { PyObject *__pyx_temp[3] = {__pyx_t_4, __pyx_v_name, __pyx_v_value}; - __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_5, 2+__pyx_t_5); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 385, __pyx_L1_error) + __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_5, 2+__pyx_t_5); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 386, __pyx_L1_error) __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; __Pyx_GOTREF(__pyx_t_2); } else #endif { - __pyx_t_6 = PyTuple_New(2+__pyx_t_5); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 385, __pyx_L1_error) + __pyx_t_6 = PyTuple_New(2+__pyx_t_5); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 386, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_6); if (__pyx_t_4) { __Pyx_GIVEREF(__pyx_t_4); PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_t_4); __pyx_t_4 = NULL; @@ -7439,14 +7586,14 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__process_header(st __Pyx_INCREF(__pyx_v_value); __Pyx_GIVEREF(__pyx_v_value); PyTuple_SET_ITEM(__pyx_t_6, 1+__pyx_t_5, __pyx_v_value); - __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_6, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 385, __pyx_L1_error) + __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_6, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 386, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; } __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - /* "aiohttp/_http_parser.pyx":387 + /* "aiohttp/_http_parser.pyx":388 * self._headers.add(name, value) * * if name is CONTENT_ENCODING: # <<<<<<<<<<<<<< @@ -7457,14 +7604,14 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__process_header(st __pyx_t_7 = (__pyx_t_1 != 0); if (__pyx_t_7) { - /* "aiohttp/_http_parser.pyx":388 + /* "aiohttp/_http_parser.pyx":389 * * if name is CONTENT_ENCODING: * self._content_encoding = value # <<<<<<<<<<<<<< * * PyByteArray_Resize(self._raw_name, 0) */ - if (!(likely(PyUnicode_CheckExact(__pyx_v_value))||((__pyx_v_value) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "unicode", Py_TYPE(__pyx_v_value)->tp_name), 0))) __PYX_ERR(0, 388, __pyx_L1_error) + if (!(likely(PyUnicode_CheckExact(__pyx_v_value))||((__pyx_v_value) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "unicode", Py_TYPE(__pyx_v_value)->tp_name), 0))) __PYX_ERR(0, 389, __pyx_L1_error) __pyx_t_2 = __pyx_v_value; __Pyx_INCREF(__pyx_t_2); __Pyx_GIVEREF(__pyx_t_2); @@ -7473,7 +7620,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__process_header(st __pyx_v_self->_content_encoding = ((PyObject*)__pyx_t_2); __pyx_t_2 = 0; - /* "aiohttp/_http_parser.pyx":387 + /* "aiohttp/_http_parser.pyx":388 * self._headers.add(name, value) * * if name is CONTENT_ENCODING: # <<<<<<<<<<<<<< @@ -7482,7 +7629,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__process_header(st */ } - /* "aiohttp/_http_parser.pyx":390 + /* "aiohttp/_http_parser.pyx":391 * self._content_encoding = value * * PyByteArray_Resize(self._raw_name, 0) # <<<<<<<<<<<<<< @@ -7491,10 +7638,10 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__process_header(st */ __pyx_t_2 = __pyx_v_self->_raw_name; __Pyx_INCREF(__pyx_t_2); - __pyx_t_5 = PyByteArray_Resize(__pyx_t_2, 0); if (unlikely(__pyx_t_5 == ((int)-1))) __PYX_ERR(0, 390, __pyx_L1_error) + __pyx_t_5 = PyByteArray_Resize(__pyx_t_2, 0); if (unlikely(__pyx_t_5 == ((int)-1))) __PYX_ERR(0, 391, __pyx_L1_error) __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - /* "aiohttp/_http_parser.pyx":391 + /* "aiohttp/_http_parser.pyx":392 * * PyByteArray_Resize(self._raw_name, 0) * PyByteArray_Resize(self._raw_value, 0) # <<<<<<<<<<<<<< @@ -7503,10 +7650,10 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__process_header(st */ __pyx_t_2 = __pyx_v_self->_raw_value; __Pyx_INCREF(__pyx_t_2); - __pyx_t_5 = PyByteArray_Resize(__pyx_t_2, 0); if (unlikely(__pyx_t_5 == ((int)-1))) __PYX_ERR(0, 391, __pyx_L1_error) + __pyx_t_5 = PyByteArray_Resize(__pyx_t_2, 0); if (unlikely(__pyx_t_5 == ((int)-1))) __PYX_ERR(0, 392, __pyx_L1_error) __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - /* "aiohttp/_http_parser.pyx":392 + /* "aiohttp/_http_parser.pyx":393 * PyByteArray_Resize(self._raw_name, 0) * PyByteArray_Resize(self._raw_value, 0) * self._has_value = False # <<<<<<<<<<<<<< @@ -7515,7 +7662,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__process_header(st */ __pyx_v_self->_has_value = 0; - /* "aiohttp/_http_parser.pyx":393 + /* "aiohttp/_http_parser.pyx":394 * PyByteArray_Resize(self._raw_value, 0) * self._has_value = False * self._raw_headers.append((raw_name, raw_value)) # <<<<<<<<<<<<<< @@ -7524,9 +7671,9 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__process_header(st */ if (unlikely(__pyx_v_self->_raw_headers == Py_None)) { PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "append"); - __PYX_ERR(0, 393, __pyx_L1_error) + __PYX_ERR(0, 394, __pyx_L1_error) } - __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 393, __pyx_L1_error) + __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 394, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); __Pyx_INCREF(__pyx_v_raw_name); __Pyx_GIVEREF(__pyx_v_raw_name); @@ -7534,10 +7681,10 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__process_header(st __Pyx_INCREF(__pyx_v_raw_value); __Pyx_GIVEREF(__pyx_v_raw_value); PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_v_raw_value); - __pyx_t_8 = __Pyx_PyList_Append(__pyx_v_self->_raw_headers, __pyx_t_2); if (unlikely(__pyx_t_8 == ((int)-1))) __PYX_ERR(0, 393, __pyx_L1_error) + __pyx_t_8 = __Pyx_PyList_Append(__pyx_v_self->_raw_headers, __pyx_t_2); if (unlikely(__pyx_t_8 == ((int)-1))) __PYX_ERR(0, 394, __pyx_L1_error) __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - /* "aiohttp/_http_parser.pyx":378 + /* "aiohttp/_http_parser.pyx":379 * * cdef _process_header(self): * if self._raw_name: # <<<<<<<<<<<<<< @@ -7546,7 +7693,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__process_header(st */ } - /* "aiohttp/_http_parser.pyx":377 + /* "aiohttp/_http_parser.pyx":378 * self._limit = limit * * cdef _process_header(self): # <<<<<<<<<<<<<< @@ -7574,7 +7721,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__process_header(st return __pyx_r; } -/* "aiohttp/_http_parser.pyx":395 +/* "aiohttp/_http_parser.pyx":396 * self._raw_headers.append((raw_name, raw_value)) * * cdef _on_header_field(self, char* at, size_t length): # <<<<<<<<<<<<<< @@ -7596,7 +7743,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_header_field(s int __pyx_clineno = 0; __Pyx_RefNannySetupContext("_on_header_field", 0); - /* "aiohttp/_http_parser.pyx":398 + /* "aiohttp/_http_parser.pyx":399 * cdef Py_ssize_t size * cdef char *buf * if self._has_value: # <<<<<<<<<<<<<< @@ -7606,18 +7753,18 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_header_field(s __pyx_t_1 = (__pyx_v_self->_has_value != 0); if (__pyx_t_1) { - /* "aiohttp/_http_parser.pyx":399 + /* "aiohttp/_http_parser.pyx":400 * cdef char *buf * if self._has_value: * self._process_header() # <<<<<<<<<<<<<< * * size = PyByteArray_Size(self._raw_name) */ - __pyx_t_2 = ((struct __pyx_vtabstruct_7aiohttp_12_http_parser_HttpParser *)__pyx_v_self->__pyx_vtab)->_process_header(__pyx_v_self); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 399, __pyx_L1_error) + __pyx_t_2 = ((struct __pyx_vtabstruct_7aiohttp_12_http_parser_HttpParser *)__pyx_v_self->__pyx_vtab)->_process_header(__pyx_v_self); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 400, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - /* "aiohttp/_http_parser.pyx":398 + /* "aiohttp/_http_parser.pyx":399 * cdef Py_ssize_t size * cdef char *buf * if self._has_value: # <<<<<<<<<<<<<< @@ -7626,7 +7773,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_header_field(s */ } - /* "aiohttp/_http_parser.pyx":401 + /* "aiohttp/_http_parser.pyx":402 * self._process_header() * * size = PyByteArray_Size(self._raw_name) # <<<<<<<<<<<<<< @@ -7635,11 +7782,11 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_header_field(s */ __pyx_t_2 = __pyx_v_self->_raw_name; __Pyx_INCREF(__pyx_t_2); - __pyx_t_3 = PyByteArray_Size(__pyx_t_2); if (unlikely(__pyx_t_3 == ((Py_ssize_t)-1L))) __PYX_ERR(0, 401, __pyx_L1_error) + __pyx_t_3 = PyByteArray_Size(__pyx_t_2); if (unlikely(__pyx_t_3 == ((Py_ssize_t)-1L))) __PYX_ERR(0, 402, __pyx_L1_error) __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; __pyx_v_size = __pyx_t_3; - /* "aiohttp/_http_parser.pyx":402 + /* "aiohttp/_http_parser.pyx":403 * * size = PyByteArray_Size(self._raw_name) * PyByteArray_Resize(self._raw_name, size + length) # <<<<<<<<<<<<<< @@ -7648,10 +7795,10 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_header_field(s */ __pyx_t_2 = __pyx_v_self->_raw_name; __Pyx_INCREF(__pyx_t_2); - __pyx_t_4 = PyByteArray_Resize(__pyx_t_2, (__pyx_v_size + __pyx_v_length)); if (unlikely(__pyx_t_4 == ((int)-1))) __PYX_ERR(0, 402, __pyx_L1_error) + __pyx_t_4 = PyByteArray_Resize(__pyx_t_2, (__pyx_v_size + __pyx_v_length)); if (unlikely(__pyx_t_4 == ((int)-1))) __PYX_ERR(0, 403, __pyx_L1_error) __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - /* "aiohttp/_http_parser.pyx":403 + /* "aiohttp/_http_parser.pyx":404 * size = PyByteArray_Size(self._raw_name) * PyByteArray_Resize(self._raw_name, size + length) * buf = PyByteArray_AsString(self._raw_name) # <<<<<<<<<<<<<< @@ -7663,7 +7810,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_header_field(s __pyx_v_buf = PyByteArray_AsString(__pyx_t_2); __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - /* "aiohttp/_http_parser.pyx":404 + /* "aiohttp/_http_parser.pyx":405 * PyByteArray_Resize(self._raw_name, size + length) * buf = PyByteArray_AsString(self._raw_name) * memcpy(buf + size, at, length) # <<<<<<<<<<<<<< @@ -7672,7 +7819,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_header_field(s */ (void)(memcpy((__pyx_v_buf + __pyx_v_size), __pyx_v_at, __pyx_v_length)); - /* "aiohttp/_http_parser.pyx":395 + /* "aiohttp/_http_parser.pyx":396 * self._raw_headers.append((raw_name, raw_value)) * * cdef _on_header_field(self, char* at, size_t length): # <<<<<<<<<<<<<< @@ -7693,7 +7840,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_header_field(s return __pyx_r; } -/* "aiohttp/_http_parser.pyx":406 +/* "aiohttp/_http_parser.pyx":407 * memcpy(buf + size, at, length) * * cdef _on_header_value(self, char* at, size_t length): # <<<<<<<<<<<<<< @@ -7714,7 +7861,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_header_value(s int __pyx_clineno = 0; __Pyx_RefNannySetupContext("_on_header_value", 0); - /* "aiohttp/_http_parser.pyx":410 + /* "aiohttp/_http_parser.pyx":411 * cdef char *buf * * size = PyByteArray_Size(self._raw_value) # <<<<<<<<<<<<<< @@ -7723,11 +7870,11 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_header_value(s */ __pyx_t_1 = __pyx_v_self->_raw_value; __Pyx_INCREF(__pyx_t_1); - __pyx_t_2 = PyByteArray_Size(__pyx_t_1); if (unlikely(__pyx_t_2 == ((Py_ssize_t)-1L))) __PYX_ERR(0, 410, __pyx_L1_error) + __pyx_t_2 = PyByteArray_Size(__pyx_t_1); if (unlikely(__pyx_t_2 == ((Py_ssize_t)-1L))) __PYX_ERR(0, 411, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __pyx_v_size = __pyx_t_2; - /* "aiohttp/_http_parser.pyx":411 + /* "aiohttp/_http_parser.pyx":412 * * size = PyByteArray_Size(self._raw_value) * PyByteArray_Resize(self._raw_value, size + length) # <<<<<<<<<<<<<< @@ -7736,10 +7883,10 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_header_value(s */ __pyx_t_1 = __pyx_v_self->_raw_value; __Pyx_INCREF(__pyx_t_1); - __pyx_t_3 = PyByteArray_Resize(__pyx_t_1, (__pyx_v_size + __pyx_v_length)); if (unlikely(__pyx_t_3 == ((int)-1))) __PYX_ERR(0, 411, __pyx_L1_error) + __pyx_t_3 = PyByteArray_Resize(__pyx_t_1, (__pyx_v_size + __pyx_v_length)); if (unlikely(__pyx_t_3 == ((int)-1))) __PYX_ERR(0, 412, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - /* "aiohttp/_http_parser.pyx":412 + /* "aiohttp/_http_parser.pyx":413 * size = PyByteArray_Size(self._raw_value) * PyByteArray_Resize(self._raw_value, size + length) * buf = PyByteArray_AsString(self._raw_value) # <<<<<<<<<<<<<< @@ -7751,7 +7898,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_header_value(s __pyx_v_buf = PyByteArray_AsString(__pyx_t_1); __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - /* "aiohttp/_http_parser.pyx":413 + /* "aiohttp/_http_parser.pyx":414 * PyByteArray_Resize(self._raw_value, size + length) * buf = PyByteArray_AsString(self._raw_value) * memcpy(buf + size, at, length) # <<<<<<<<<<<<<< @@ -7760,7 +7907,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_header_value(s */ (void)(memcpy((__pyx_v_buf + __pyx_v_size), __pyx_v_at, __pyx_v_length)); - /* "aiohttp/_http_parser.pyx":414 + /* "aiohttp/_http_parser.pyx":415 * buf = PyByteArray_AsString(self._raw_value) * memcpy(buf + size, at, length) * self._has_value = True # <<<<<<<<<<<<<< @@ -7769,7 +7916,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_header_value(s */ __pyx_v_self->_has_value = 1; - /* "aiohttp/_http_parser.pyx":406 + /* "aiohttp/_http_parser.pyx":407 * memcpy(buf + size, at, length) * * cdef _on_header_value(self, char* at, size_t length): # <<<<<<<<<<<<<< @@ -7790,7 +7937,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_header_value(s return __pyx_r; } -/* "aiohttp/_http_parser.pyx":416 +/* "aiohttp/_http_parser.pyx":417 * self._has_value = True * * cdef _on_headers_complete(self): # <<<<<<<<<<<<<< @@ -7801,8 +7948,8 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_header_value(s static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_headers_complete(struct __pyx_obj_7aiohttp_12_http_parser_HttpParser *__pyx_v_self) { PyObject *__pyx_v_method = NULL; int __pyx_v_should_close; - unsigned int __pyx_v_upgrade; - unsigned int __pyx_v_chunked; + uint8_t __pyx_v_upgrade; + int __pyx_v_chunked; PyObject *__pyx_v_raw_headers = NULL; PyObject *__pyx_v_headers = NULL; PyObject *__pyx_v_encoding = NULL; @@ -7812,7 +7959,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_headers_comple PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; - unsigned int __pyx_t_2; + uint8_t __pyx_t_2; PyObject *__pyx_t_3 = NULL; PyObject *__pyx_t_4 = NULL; int __pyx_t_5; @@ -7826,41 +7973,41 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_headers_comple int __pyx_clineno = 0; __Pyx_RefNannySetupContext("_on_headers_complete", 0); - /* "aiohttp/_http_parser.pyx":417 + /* "aiohttp/_http_parser.pyx":418 * * cdef _on_headers_complete(self): * self._process_header() # <<<<<<<<<<<<<< * * method = http_method_str(self._cparser.method) */ - __pyx_t_1 = ((struct __pyx_vtabstruct_7aiohttp_12_http_parser_HttpParser *)__pyx_v_self->__pyx_vtab)->_process_header(__pyx_v_self); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 417, __pyx_L1_error) + __pyx_t_1 = ((struct __pyx_vtabstruct_7aiohttp_12_http_parser_HttpParser *)__pyx_v_self->__pyx_vtab)->_process_header(__pyx_v_self); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 418, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - /* "aiohttp/_http_parser.pyx":419 + /* "aiohttp/_http_parser.pyx":420 * self._process_header() * * method = http_method_str(self._cparser.method) # <<<<<<<<<<<<<< - * should_close = not cparser.http_should_keep_alive(self._cparser) + * should_close = not cparser.llhttp_should_keep_alive(self._cparser) * upgrade = self._cparser.upgrade */ - __pyx_t_1 = __pyx_f_7aiohttp_12_http_parser_http_method_str(__pyx_v_self->_cparser->method); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 419, __pyx_L1_error) + __pyx_t_1 = __pyx_f_7aiohttp_12_http_parser_http_method_str(__pyx_v_self->_cparser->method); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 420, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_v_method = ((PyObject*)__pyx_t_1); __pyx_t_1 = 0; - /* "aiohttp/_http_parser.pyx":420 + /* "aiohttp/_http_parser.pyx":421 * * method = http_method_str(self._cparser.method) - * should_close = not cparser.http_should_keep_alive(self._cparser) # <<<<<<<<<<<<<< + * should_close = not cparser.llhttp_should_keep_alive(self._cparser) # <<<<<<<<<<<<<< * upgrade = self._cparser.upgrade * chunked = self._cparser.flags & cparser.F_CHUNKED */ - __pyx_v_should_close = (!(http_should_keep_alive(__pyx_v_self->_cparser) != 0)); + __pyx_v_should_close = (!(llhttp_should_keep_alive(__pyx_v_self->_cparser) != 0)); - /* "aiohttp/_http_parser.pyx":421 + /* "aiohttp/_http_parser.pyx":422 * method = http_method_str(self._cparser.method) - * should_close = not cparser.http_should_keep_alive(self._cparser) + * should_close = not cparser.llhttp_should_keep_alive(self._cparser) * upgrade = self._cparser.upgrade # <<<<<<<<<<<<<< * chunked = self._cparser.flags & cparser.F_CHUNKED * @@ -7868,8 +8015,8 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_headers_comple __pyx_t_2 = __pyx_v_self->_cparser->upgrade; __pyx_v_upgrade = __pyx_t_2; - /* "aiohttp/_http_parser.pyx":422 - * should_close = not cparser.http_should_keep_alive(self._cparser) + /* "aiohttp/_http_parser.pyx":423 + * should_close = not cparser.llhttp_should_keep_alive(self._cparser) * upgrade = self._cparser.upgrade * chunked = self._cparser.flags & cparser.F_CHUNKED # <<<<<<<<<<<<<< * @@ -7877,7 +8024,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_headers_comple */ __pyx_v_chunked = (__pyx_v_self->_cparser->flags & F_CHUNKED); - /* "aiohttp/_http_parser.pyx":424 + /* "aiohttp/_http_parser.pyx":425 * chunked = self._cparser.flags & cparser.F_CHUNKED * * raw_headers = tuple(self._raw_headers) # <<<<<<<<<<<<<< @@ -7886,19 +8033,19 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_headers_comple */ if (unlikely(__pyx_v_self->_raw_headers == Py_None)) { PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable"); - __PYX_ERR(0, 424, __pyx_L1_error) + __PYX_ERR(0, 425, __pyx_L1_error) } - __pyx_t_1 = PyList_AsTuple(__pyx_v_self->_raw_headers); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 424, __pyx_L1_error) + __pyx_t_1 = PyList_AsTuple(__pyx_v_self->_raw_headers); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 425, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_v_raw_headers = ((PyObject*)__pyx_t_1); __pyx_t_1 = 0; - /* "aiohttp/_http_parser.pyx":425 + /* "aiohttp/_http_parser.pyx":426 * * raw_headers = tuple(self._raw_headers) * headers = CIMultiDictProxy(self._headers) # <<<<<<<<<<<<<< * - * if upgrade or self._cparser.method == 5: # cparser.CONNECT: + * if upgrade or self._cparser.method == cparser.HTTP_CONNECT: */ __Pyx_INCREF(__pyx_v_7aiohttp_12_http_parser_CIMultiDictProxy); __pyx_t_3 = __pyx_v_7aiohttp_12_http_parser_CIMultiDictProxy; __pyx_t_4 = NULL; @@ -7913,16 +8060,16 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_headers_comple } __pyx_t_1 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_4, __pyx_v_self->_headers) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_v_self->_headers); __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; - if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 425, __pyx_L1_error) + if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 426, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __pyx_v_headers = __pyx_t_1; __pyx_t_1 = 0; - /* "aiohttp/_http_parser.pyx":427 + /* "aiohttp/_http_parser.pyx":428 * headers = CIMultiDictProxy(self._headers) * - * if upgrade or self._cparser.method == 5: # cparser.CONNECT: # <<<<<<<<<<<<<< + * if upgrade or self._cparser.method == cparser.HTTP_CONNECT: # <<<<<<<<<<<<<< * self._upgraded = True * */ @@ -7932,48 +8079,48 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_headers_comple __pyx_t_5 = __pyx_t_6; goto __pyx_L4_bool_binop_done; } - __pyx_t_6 = ((__pyx_v_self->_cparser->method == 5) != 0); + __pyx_t_6 = ((__pyx_v_self->_cparser->method == HTTP_CONNECT) != 0); __pyx_t_5 = __pyx_t_6; __pyx_L4_bool_binop_done:; if (__pyx_t_5) { - /* "aiohttp/_http_parser.pyx":428 + /* "aiohttp/_http_parser.pyx":429 * - * if upgrade or self._cparser.method == 5: # cparser.CONNECT: + * if upgrade or self._cparser.method == cparser.HTTP_CONNECT: * self._upgraded = True # <<<<<<<<<<<<<< * * # do not support old websocket spec */ __pyx_v_self->_upgraded = 1; - /* "aiohttp/_http_parser.pyx":427 + /* "aiohttp/_http_parser.pyx":428 * headers = CIMultiDictProxy(self._headers) * - * if upgrade or self._cparser.method == 5: # cparser.CONNECT: # <<<<<<<<<<<<<< + * if upgrade or self._cparser.method == cparser.HTTP_CONNECT: # <<<<<<<<<<<<<< * self._upgraded = True * */ } - /* "aiohttp/_http_parser.pyx":431 + /* "aiohttp/_http_parser.pyx":432 * * # do not support old websocket spec * if SEC_WEBSOCKET_KEY1 in headers: # <<<<<<<<<<<<<< * raise InvalidHeader(SEC_WEBSOCKET_KEY1) * */ - __pyx_t_5 = (__Pyx_PySequence_ContainsTF(__pyx_v_7aiohttp_12_http_parser_SEC_WEBSOCKET_KEY1, __pyx_v_headers, Py_EQ)); if (unlikely(__pyx_t_5 < 0)) __PYX_ERR(0, 431, __pyx_L1_error) + __pyx_t_5 = (__Pyx_PySequence_ContainsTF(__pyx_v_7aiohttp_12_http_parser_SEC_WEBSOCKET_KEY1, __pyx_v_headers, Py_EQ)); if (unlikely(__pyx_t_5 < 0)) __PYX_ERR(0, 432, __pyx_L1_error) __pyx_t_6 = (__pyx_t_5 != 0); if (unlikely(__pyx_t_6)) { - /* "aiohttp/_http_parser.pyx":432 + /* "aiohttp/_http_parser.pyx":433 * # do not support old websocket spec * if SEC_WEBSOCKET_KEY1 in headers: * raise InvalidHeader(SEC_WEBSOCKET_KEY1) # <<<<<<<<<<<<<< * * encoding = None */ - __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_InvalidHeader); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 432, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_InvalidHeader); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 433, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_4 = NULL; if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) { @@ -7987,14 +8134,14 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_headers_comple } __pyx_t_1 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_4, __pyx_v_7aiohttp_12_http_parser_SEC_WEBSOCKET_KEY1) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_v_7aiohttp_12_http_parser_SEC_WEBSOCKET_KEY1); __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; - if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 432, __pyx_L1_error) + if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 433, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __Pyx_Raise(__pyx_t_1, 0, 0, 0); __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __PYX_ERR(0, 432, __pyx_L1_error) + __PYX_ERR(0, 433, __pyx_L1_error) - /* "aiohttp/_http_parser.pyx":431 + /* "aiohttp/_http_parser.pyx":432 * * # do not support old websocket spec * if SEC_WEBSOCKET_KEY1 in headers: # <<<<<<<<<<<<<< @@ -8003,7 +8150,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_headers_comple */ } - /* "aiohttp/_http_parser.pyx":434 + /* "aiohttp/_http_parser.pyx":435 * raise InvalidHeader(SEC_WEBSOCKET_KEY1) * * encoding = None # <<<<<<<<<<<<<< @@ -8013,7 +8160,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_headers_comple __Pyx_INCREF(Py_None); __pyx_v_encoding = Py_None; - /* "aiohttp/_http_parser.pyx":435 + /* "aiohttp/_http_parser.pyx":436 * * encoding = None * enc = self._content_encoding # <<<<<<<<<<<<<< @@ -8025,7 +8172,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_headers_comple __pyx_v_enc = __pyx_t_1; __pyx_t_1 = 0; - /* "aiohttp/_http_parser.pyx":436 + /* "aiohttp/_http_parser.pyx":437 * encoding = None * enc = self._content_encoding * if enc is not None: # <<<<<<<<<<<<<< @@ -8036,7 +8183,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_headers_comple __pyx_t_5 = (__pyx_t_6 != 0); if (__pyx_t_5) { - /* "aiohttp/_http_parser.pyx":437 + /* "aiohttp/_http_parser.pyx":438 * enc = self._content_encoding * if enc is not None: * self._content_encoding = None # <<<<<<<<<<<<<< @@ -8049,14 +8196,14 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_headers_comple __Pyx_DECREF(__pyx_v_self->_content_encoding); __pyx_v_self->_content_encoding = ((PyObject*)Py_None); - /* "aiohttp/_http_parser.pyx":438 + /* "aiohttp/_http_parser.pyx":439 * if enc is not None: * self._content_encoding = None * enc = enc.lower() # <<<<<<<<<<<<<< * if enc in ('gzip', 'deflate', 'br'): * encoding = enc */ - __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_enc, __pyx_n_s_lower); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 438, __pyx_L1_error) + __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_enc, __pyx_n_s_lower); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 439, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_4 = NULL; if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_3))) { @@ -8070,13 +8217,13 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_headers_comple } __pyx_t_1 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3); __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; - if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 438, __pyx_L1_error) + if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 439, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __Pyx_DECREF_SET(__pyx_v_enc, __pyx_t_1); __pyx_t_1 = 0; - /* "aiohttp/_http_parser.pyx":439 + /* "aiohttp/_http_parser.pyx":440 * self._content_encoding = None * enc = enc.lower() * if enc in ('gzip', 'deflate', 'br'): # <<<<<<<<<<<<<< @@ -8085,26 +8232,26 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_headers_comple */ __Pyx_INCREF(__pyx_v_enc); __pyx_t_1 = __pyx_v_enc; - __pyx_t_6 = (__Pyx_PyUnicode_Equals(__pyx_t_1, __pyx_n_u_gzip, Py_EQ)); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(0, 439, __pyx_L1_error) + __pyx_t_6 = (__Pyx_PyUnicode_Equals(__pyx_t_1, __pyx_n_u_gzip, Py_EQ)); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(0, 440, __pyx_L1_error) if (!__pyx_t_6) { } else { __pyx_t_5 = __pyx_t_6; goto __pyx_L9_bool_binop_done; } - __pyx_t_6 = (__Pyx_PyUnicode_Equals(__pyx_t_1, __pyx_n_u_deflate, Py_EQ)); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(0, 439, __pyx_L1_error) + __pyx_t_6 = (__Pyx_PyUnicode_Equals(__pyx_t_1, __pyx_n_u_deflate, Py_EQ)); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(0, 440, __pyx_L1_error) if (!__pyx_t_6) { } else { __pyx_t_5 = __pyx_t_6; goto __pyx_L9_bool_binop_done; } - __pyx_t_6 = (__Pyx_PyUnicode_Equals(__pyx_t_1, __pyx_n_u_br, Py_EQ)); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(0, 439, __pyx_L1_error) + __pyx_t_6 = (__Pyx_PyUnicode_Equals(__pyx_t_1, __pyx_n_u_br, Py_EQ)); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(0, 440, __pyx_L1_error) __pyx_t_5 = __pyx_t_6; __pyx_L9_bool_binop_done:; __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __pyx_t_6 = (__pyx_t_5 != 0); if (__pyx_t_6) { - /* "aiohttp/_http_parser.pyx":440 + /* "aiohttp/_http_parser.pyx":441 * enc = enc.lower() * if enc in ('gzip', 'deflate', 'br'): * encoding = enc # <<<<<<<<<<<<<< @@ -8114,7 +8261,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_headers_comple __Pyx_INCREF(__pyx_v_enc); __Pyx_DECREF_SET(__pyx_v_encoding, __pyx_v_enc); - /* "aiohttp/_http_parser.pyx":439 + /* "aiohttp/_http_parser.pyx":440 * self._content_encoding = None * enc = enc.lower() * if enc in ('gzip', 'deflate', 'br'): # <<<<<<<<<<<<<< @@ -8123,7 +8270,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_headers_comple */ } - /* "aiohttp/_http_parser.pyx":436 + /* "aiohttp/_http_parser.pyx":437 * encoding = None * enc = self._content_encoding * if enc is not None: # <<<<<<<<<<<<<< @@ -8132,7 +8279,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_headers_comple */ } - /* "aiohttp/_http_parser.pyx":442 + /* "aiohttp/_http_parser.pyx":443 * encoding = enc * * if self._cparser.type == cparser.HTTP_REQUEST: # <<<<<<<<<<<<<< @@ -8142,7 +8289,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_headers_comple __pyx_t_6 = ((__pyx_v_self->_cparser->type == HTTP_REQUEST) != 0); if (__pyx_t_6) { - /* "aiohttp/_http_parser.pyx":444 + /* "aiohttp/_http_parser.pyx":445 * if self._cparser.type == cparser.HTTP_REQUEST: * msg = _new_request_message( * method, self._path, # <<<<<<<<<<<<<< @@ -8152,17 +8299,17 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_headers_comple __pyx_t_1 = __pyx_v_self->_path; __Pyx_INCREF(__pyx_t_1); - /* "aiohttp/_http_parser.pyx":445 + /* "aiohttp/_http_parser.pyx":446 * msg = _new_request_message( * method, self._path, * self.http_version(), headers, raw_headers, # <<<<<<<<<<<<<< * should_close, encoding, upgrade, chunked, self._url) * else: */ - __pyx_t_3 = __pyx_f_7aiohttp_12_http_parser_10HttpParser_http_version(__pyx_v_self); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 445, __pyx_L1_error) + __pyx_t_3 = __pyx_f_7aiohttp_12_http_parser_10HttpParser_http_version(__pyx_v_self); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 446, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); - /* "aiohttp/_http_parser.pyx":446 + /* "aiohttp/_http_parser.pyx":447 * method, self._path, * self.http_version(), headers, raw_headers, * should_close, encoding, upgrade, chunked, self._url) # <<<<<<<<<<<<<< @@ -8172,14 +8319,14 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_headers_comple __pyx_t_4 = __pyx_v_self->_url; __Pyx_INCREF(__pyx_t_4); - /* "aiohttp/_http_parser.pyx":443 + /* "aiohttp/_http_parser.pyx":444 * * if self._cparser.type == cparser.HTTP_REQUEST: * msg = _new_request_message( # <<<<<<<<<<<<<< * method, self._path, * self.http_version(), headers, raw_headers, */ - __pyx_t_7 = __pyx_f_7aiohttp_12_http_parser__new_request_message(__pyx_v_method, ((PyObject*)__pyx_t_1), __pyx_t_3, __pyx_v_headers, __pyx_v_raw_headers, __pyx_v_should_close, __pyx_v_encoding, __pyx_v_upgrade, __pyx_v_chunked, __pyx_t_4); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 443, __pyx_L1_error) + __pyx_t_7 = __pyx_f_7aiohttp_12_http_parser__new_request_message(__pyx_v_method, ((PyObject*)__pyx_t_1), __pyx_t_3, __pyx_v_headers, __pyx_v_raw_headers, __pyx_v_should_close, __pyx_v_encoding, __pyx_v_upgrade, __pyx_v_chunked, __pyx_t_4); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 444, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_7); __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; @@ -8187,7 +8334,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_headers_comple __pyx_v_msg = __pyx_t_7; __pyx_t_7 = 0; - /* "aiohttp/_http_parser.pyx":442 + /* "aiohttp/_http_parser.pyx":443 * encoding = enc * * if self._cparser.type == cparser.HTTP_REQUEST: # <<<<<<<<<<<<<< @@ -8197,7 +8344,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_headers_comple goto __pyx_L12; } - /* "aiohttp/_http_parser.pyx":448 + /* "aiohttp/_http_parser.pyx":449 * should_close, encoding, upgrade, chunked, self._url) * else: * msg = _new_response_message( # <<<<<<<<<<<<<< @@ -8206,26 +8353,26 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_headers_comple */ /*else*/ { - /* "aiohttp/_http_parser.pyx":449 + /* "aiohttp/_http_parser.pyx":450 * else: * msg = _new_response_message( * self.http_version(), self._cparser.status_code, self._reason, # <<<<<<<<<<<<<< * headers, raw_headers, should_close, encoding, * upgrade, chunked) */ - __pyx_t_7 = __pyx_f_7aiohttp_12_http_parser_10HttpParser_http_version(__pyx_v_self); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 449, __pyx_L1_error) + __pyx_t_7 = __pyx_f_7aiohttp_12_http_parser_10HttpParser_http_version(__pyx_v_self); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 450, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_7); __pyx_t_4 = __pyx_v_self->_reason; __Pyx_INCREF(__pyx_t_4); - /* "aiohttp/_http_parser.pyx":448 + /* "aiohttp/_http_parser.pyx":449 * should_close, encoding, upgrade, chunked, self._url) * else: * msg = _new_response_message( # <<<<<<<<<<<<<< * self.http_version(), self._cparser.status_code, self._reason, * headers, raw_headers, should_close, encoding, */ - __pyx_t_3 = __pyx_f_7aiohttp_12_http_parser__new_response_message(__pyx_t_7, __pyx_v_self->_cparser->status_code, ((PyObject*)__pyx_t_4), __pyx_v_headers, __pyx_v_raw_headers, __pyx_v_should_close, __pyx_v_encoding, __pyx_v_upgrade, __pyx_v_chunked); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 448, __pyx_L1_error) + __pyx_t_3 = __pyx_f_7aiohttp_12_http_parser__new_response_message(__pyx_t_7, __pyx_v_self->_cparser->status_code, ((PyObject*)__pyx_t_4), __pyx_v_headers, __pyx_v_raw_headers, __pyx_v_should_close, __pyx_v_encoding, __pyx_v_upgrade, __pyx_v_chunked); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 449, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; @@ -8234,12 +8381,12 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_headers_comple } __pyx_L12:; - /* "aiohttp/_http_parser.pyx":453 - * upgrade, chunked) + /* "aiohttp/_http_parser.pyx":455 * - * if (ULLONG_MAX > self._cparser.content_length > 0 or chunked or # <<<<<<<<<<<<<< - * self._cparser.method == 5 or # CONNECT: 5 - * (self._cparser.status_code >= 199 and + * if ( + * ULLONG_MAX > self._cparser.content_length > 0 or chunked or # <<<<<<<<<<<<<< + * self._cparser.method == cparser.HTTP_CONNECT or + * (self._cparser.status_code >= 199 and */ __pyx_t_5 = (ULLONG_MAX > __pyx_v_self->_cparser->content_length); if (__pyx_t_5) { @@ -8258,26 +8405,26 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_headers_comple goto __pyx_L14_bool_binop_done; } - /* "aiohttp/_http_parser.pyx":454 - * - * if (ULLONG_MAX > self._cparser.content_length > 0 or chunked or - * self._cparser.method == 5 or # CONNECT: 5 # <<<<<<<<<<<<<< - * (self._cparser.status_code >= 199 and - * self._cparser.content_length == ULLONG_MAX and + /* "aiohttp/_http_parser.pyx":456 + * if ( + * ULLONG_MAX > self._cparser.content_length > 0 or chunked or + * self._cparser.method == cparser.HTTP_CONNECT or # <<<<<<<<<<<<<< + * (self._cparser.status_code >= 199 and + * self._cparser.content_length == 0 and */ - __pyx_t_8 = ((__pyx_v_self->_cparser->method == 5) != 0); + __pyx_t_8 = ((__pyx_v_self->_cparser->method == HTTP_CONNECT) != 0); if (!__pyx_t_8) { } else { __pyx_t_6 = __pyx_t_8; goto __pyx_L14_bool_binop_done; } - /* "aiohttp/_http_parser.pyx":455 - * if (ULLONG_MAX > self._cparser.content_length > 0 or chunked or - * self._cparser.method == 5 or # CONNECT: 5 - * (self._cparser.status_code >= 199 and # <<<<<<<<<<<<<< - * self._cparser.content_length == ULLONG_MAX and - * self._read_until_eof) + /* "aiohttp/_http_parser.pyx":457 + * ULLONG_MAX > self._cparser.content_length > 0 or chunked or + * self._cparser.method == cparser.HTTP_CONNECT or + * (self._cparser.status_code >= 199 and # <<<<<<<<<<<<<< + * self._cparser.content_length == 0 and + * self._read_until_eof) */ __pyx_t_8 = ((__pyx_v_self->_cparser->status_code >= 0xC7) != 0); if (__pyx_t_8) { @@ -8286,24 +8433,24 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_headers_comple goto __pyx_L14_bool_binop_done; } - /* "aiohttp/_http_parser.pyx":456 - * self._cparser.method == 5 or # CONNECT: 5 - * (self._cparser.status_code >= 199 and - * self._cparser.content_length == ULLONG_MAX and # <<<<<<<<<<<<<< - * self._read_until_eof) + /* "aiohttp/_http_parser.pyx":458 + * self._cparser.method == cparser.HTTP_CONNECT or + * (self._cparser.status_code >= 199 and + * self._cparser.content_length == 0 and # <<<<<<<<<<<<<< + * self._read_until_eof) * ): */ - __pyx_t_8 = ((__pyx_v_self->_cparser->content_length == ULLONG_MAX) != 0); + __pyx_t_8 = ((__pyx_v_self->_cparser->content_length == 0) != 0); if (__pyx_t_8) { } else { __pyx_t_6 = __pyx_t_8; goto __pyx_L14_bool_binop_done; } - /* "aiohttp/_http_parser.pyx":457 - * (self._cparser.status_code >= 199 and - * self._cparser.content_length == ULLONG_MAX and - * self._read_until_eof) # <<<<<<<<<<<<<< + /* "aiohttp/_http_parser.pyx":459 + * (self._cparser.status_code >= 199 and + * self._cparser.content_length == 0 and + * self._read_until_eof) # <<<<<<<<<<<<<< * ): * payload = StreamReader( */ @@ -8311,77 +8458,77 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_headers_comple __pyx_t_6 = __pyx_t_8; __pyx_L14_bool_binop_done:; - /* "aiohttp/_http_parser.pyx":453 + /* "aiohttp/_http_parser.pyx":454 * upgrade, chunked) * - * if (ULLONG_MAX > self._cparser.content_length > 0 or chunked or # <<<<<<<<<<<<<< - * self._cparser.method == 5 or # CONNECT: 5 - * (self._cparser.status_code >= 199 and + * if ( # <<<<<<<<<<<<<< + * ULLONG_MAX > self._cparser.content_length > 0 or chunked or + * self._cparser.method == cparser.HTTP_CONNECT or */ if (__pyx_t_6) { - /* "aiohttp/_http_parser.pyx":459 - * self._read_until_eof) + /* "aiohttp/_http_parser.pyx":461 + * self._read_until_eof) * ): * payload = StreamReader( # <<<<<<<<<<<<<< * self._protocol, timer=self._timer, loop=self._loop, * limit=self._limit) */ - __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 459, __pyx_L1_error) + __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 461, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __Pyx_INCREF(__pyx_v_self->_protocol); __Pyx_GIVEREF(__pyx_v_self->_protocol); PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_self->_protocol); - /* "aiohttp/_http_parser.pyx":460 + /* "aiohttp/_http_parser.pyx":462 * ): * payload = StreamReader( * self._protocol, timer=self._timer, loop=self._loop, # <<<<<<<<<<<<<< * limit=self._limit) * else: */ - __pyx_t_4 = __Pyx_PyDict_NewPresized(3); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 460, __pyx_L1_error) + __pyx_t_4 = __Pyx_PyDict_NewPresized(3); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 462, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); - if (PyDict_SetItem(__pyx_t_4, __pyx_n_s_timer, __pyx_v_self->_timer) < 0) __PYX_ERR(0, 460, __pyx_L1_error) - if (PyDict_SetItem(__pyx_t_4, __pyx_n_s_loop, __pyx_v_self->_loop) < 0) __PYX_ERR(0, 460, __pyx_L1_error) + if (PyDict_SetItem(__pyx_t_4, __pyx_n_s_timer, __pyx_v_self->_timer) < 0) __PYX_ERR(0, 462, __pyx_L1_error) + if (PyDict_SetItem(__pyx_t_4, __pyx_n_s_loop, __pyx_v_self->_loop) < 0) __PYX_ERR(0, 462, __pyx_L1_error) - /* "aiohttp/_http_parser.pyx":461 + /* "aiohttp/_http_parser.pyx":463 * payload = StreamReader( * self._protocol, timer=self._timer, loop=self._loop, * limit=self._limit) # <<<<<<<<<<<<<< * else: * payload = EMPTY_PAYLOAD */ - __pyx_t_7 = __Pyx_PyInt_From_int(__pyx_v_self->_limit); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 461, __pyx_L1_error) + __pyx_t_7 = __Pyx_PyInt_From_int(__pyx_v_self->_limit); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 463, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_7); - if (PyDict_SetItem(__pyx_t_4, __pyx_n_s_limit, __pyx_t_7) < 0) __PYX_ERR(0, 460, __pyx_L1_error) + if (PyDict_SetItem(__pyx_t_4, __pyx_n_s_limit, __pyx_t_7) < 0) __PYX_ERR(0, 462, __pyx_L1_error) __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; - /* "aiohttp/_http_parser.pyx":459 - * self._read_until_eof) + /* "aiohttp/_http_parser.pyx":461 + * self._read_until_eof) * ): * payload = StreamReader( # <<<<<<<<<<<<<< * self._protocol, timer=self._timer, loop=self._loop, * limit=self._limit) */ - __pyx_t_7 = __Pyx_PyObject_Call(__pyx_v_7aiohttp_12_http_parser_StreamReader, __pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 459, __pyx_L1_error) + __pyx_t_7 = __Pyx_PyObject_Call(__pyx_v_7aiohttp_12_http_parser_StreamReader, __pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 461, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_7); __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __pyx_v_payload = __pyx_t_7; __pyx_t_7 = 0; - /* "aiohttp/_http_parser.pyx":453 + /* "aiohttp/_http_parser.pyx":454 * upgrade, chunked) * - * if (ULLONG_MAX > self._cparser.content_length > 0 or chunked or # <<<<<<<<<<<<<< - * self._cparser.method == 5 or # CONNECT: 5 - * (self._cparser.status_code >= 199 and + * if ( # <<<<<<<<<<<<<< + * ULLONG_MAX > self._cparser.content_length > 0 or chunked or + * self._cparser.method == cparser.HTTP_CONNECT or */ goto __pyx_L13; } - /* "aiohttp/_http_parser.pyx":463 + /* "aiohttp/_http_parser.pyx":465 * limit=self._limit) * else: * payload = EMPTY_PAYLOAD # <<<<<<<<<<<<<< @@ -8394,7 +8541,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_headers_comple } __pyx_L13:; - /* "aiohttp/_http_parser.pyx":465 + /* "aiohttp/_http_parser.pyx":467 * payload = EMPTY_PAYLOAD * * self._payload = payload # <<<<<<<<<<<<<< @@ -8407,7 +8554,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_headers_comple __Pyx_DECREF(__pyx_v_self->_payload); __pyx_v_self->_payload = __pyx_v_payload; - /* "aiohttp/_http_parser.pyx":466 + /* "aiohttp/_http_parser.pyx":468 * * self._payload = payload * if encoding is not None and self._auto_decompress: # <<<<<<<<<<<<<< @@ -8426,7 +8573,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_headers_comple __pyx_L21_bool_binop_done:; if (__pyx_t_6) { - /* "aiohttp/_http_parser.pyx":467 + /* "aiohttp/_http_parser.pyx":469 * self._payload = payload * if encoding is not None and self._auto_decompress: * self._payload = DeflateBuffer(payload, encoding) # <<<<<<<<<<<<<< @@ -8449,7 +8596,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_headers_comple #if CYTHON_FAST_PYCALL if (PyFunction_Check(__pyx_t_4)) { PyObject *__pyx_temp[3] = {__pyx_t_3, __pyx_v_payload, __pyx_v_encoding}; - __pyx_t_7 = __Pyx_PyFunction_FastCall(__pyx_t_4, __pyx_temp+1-__pyx_t_9, 2+__pyx_t_9); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 467, __pyx_L1_error) + __pyx_t_7 = __Pyx_PyFunction_FastCall(__pyx_t_4, __pyx_temp+1-__pyx_t_9, 2+__pyx_t_9); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 469, __pyx_L1_error) __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; __Pyx_GOTREF(__pyx_t_7); } else @@ -8457,13 +8604,13 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_headers_comple #if CYTHON_FAST_PYCCALL if (__Pyx_PyFastCFunction_Check(__pyx_t_4)) { PyObject *__pyx_temp[3] = {__pyx_t_3, __pyx_v_payload, __pyx_v_encoding}; - __pyx_t_7 = __Pyx_PyCFunction_FastCall(__pyx_t_4, __pyx_temp+1-__pyx_t_9, 2+__pyx_t_9); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 467, __pyx_L1_error) + __pyx_t_7 = __Pyx_PyCFunction_FastCall(__pyx_t_4, __pyx_temp+1-__pyx_t_9, 2+__pyx_t_9); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 469, __pyx_L1_error) __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; __Pyx_GOTREF(__pyx_t_7); } else #endif { - __pyx_t_1 = PyTuple_New(2+__pyx_t_9); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 467, __pyx_L1_error) + __pyx_t_1 = PyTuple_New(2+__pyx_t_9); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 469, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); if (__pyx_t_3) { __Pyx_GIVEREF(__pyx_t_3); PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_3); __pyx_t_3 = NULL; @@ -8474,7 +8621,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_headers_comple __Pyx_INCREF(__pyx_v_encoding); __Pyx_GIVEREF(__pyx_v_encoding); PyTuple_SET_ITEM(__pyx_t_1, 1+__pyx_t_9, __pyx_v_encoding); - __pyx_t_7 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_1, NULL); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 467, __pyx_L1_error) + __pyx_t_7 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_1, NULL); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 469, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_7); __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; } @@ -8485,7 +8632,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_headers_comple __pyx_v_self->_payload = __pyx_t_7; __pyx_t_7 = 0; - /* "aiohttp/_http_parser.pyx":466 + /* "aiohttp/_http_parser.pyx":468 * * self._payload = payload * if encoding is not None and self._auto_decompress: # <<<<<<<<<<<<<< @@ -8494,7 +8641,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_headers_comple */ } - /* "aiohttp/_http_parser.pyx":469 + /* "aiohttp/_http_parser.pyx":471 * self._payload = DeflateBuffer(payload, encoding) * * if not self._response_with_body: # <<<<<<<<<<<<<< @@ -8504,7 +8651,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_headers_comple __pyx_t_6 = ((!(__pyx_v_self->_response_with_body != 0)) != 0); if (__pyx_t_6) { - /* "aiohttp/_http_parser.pyx":470 + /* "aiohttp/_http_parser.pyx":472 * * if not self._response_with_body: * payload = EMPTY_PAYLOAD # <<<<<<<<<<<<<< @@ -8514,7 +8661,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_headers_comple __Pyx_INCREF(__pyx_v_7aiohttp_12_http_parser_EMPTY_PAYLOAD); __Pyx_DECREF_SET(__pyx_v_payload, __pyx_v_7aiohttp_12_http_parser_EMPTY_PAYLOAD); - /* "aiohttp/_http_parser.pyx":469 + /* "aiohttp/_http_parser.pyx":471 * self._payload = DeflateBuffer(payload, encoding) * * if not self._response_with_body: # <<<<<<<<<<<<<< @@ -8523,7 +8670,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_headers_comple */ } - /* "aiohttp/_http_parser.pyx":472 + /* "aiohttp/_http_parser.pyx":474 * payload = EMPTY_PAYLOAD * * self._messages.append((msg, payload)) # <<<<<<<<<<<<<< @@ -8532,9 +8679,9 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_headers_comple */ if (unlikely(__pyx_v_self->_messages == Py_None)) { PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "append"); - __PYX_ERR(0, 472, __pyx_L1_error) + __PYX_ERR(0, 474, __pyx_L1_error) } - __pyx_t_7 = PyTuple_New(2); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 472, __pyx_L1_error) + __pyx_t_7 = PyTuple_New(2); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 474, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_7); __Pyx_INCREF(__pyx_v_msg); __Pyx_GIVEREF(__pyx_v_msg); @@ -8542,10 +8689,10 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_headers_comple __Pyx_INCREF(__pyx_v_payload); __Pyx_GIVEREF(__pyx_v_payload); PyTuple_SET_ITEM(__pyx_t_7, 1, __pyx_v_payload); - __pyx_t_10 = __Pyx_PyList_Append(__pyx_v_self->_messages, __pyx_t_7); if (unlikely(__pyx_t_10 == ((int)-1))) __PYX_ERR(0, 472, __pyx_L1_error) + __pyx_t_10 = __Pyx_PyList_Append(__pyx_v_self->_messages, __pyx_t_7); if (unlikely(__pyx_t_10 == ((int)-1))) __PYX_ERR(0, 474, __pyx_L1_error) __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; - /* "aiohttp/_http_parser.pyx":416 + /* "aiohttp/_http_parser.pyx":417 * self._has_value = True * * cdef _on_headers_complete(self): # <<<<<<<<<<<<<< @@ -8576,7 +8723,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_headers_comple return __pyx_r; } -/* "aiohttp/_http_parser.pyx":474 +/* "aiohttp/_http_parser.pyx":476 * self._messages.append((msg, payload)) * * cdef _on_message_complete(self): # <<<<<<<<<<<<<< @@ -8595,14 +8742,14 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_message_comple int __pyx_clineno = 0; __Pyx_RefNannySetupContext("_on_message_complete", 0); - /* "aiohttp/_http_parser.pyx":475 + /* "aiohttp/_http_parser.pyx":477 * * cdef _on_message_complete(self): * self._payload.feed_eof() # <<<<<<<<<<<<<< * self._payload = None * */ - __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_self->_payload, __pyx_n_s_feed_eof); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 475, __pyx_L1_error) + __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_self->_payload, __pyx_n_s_feed_eof); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 477, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); __pyx_t_3 = NULL; if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) { @@ -8616,12 +8763,12 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_message_comple } __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3) : __Pyx_PyObject_CallNoArg(__pyx_t_2); __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; - if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 475, __pyx_L1_error) + if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 477, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - /* "aiohttp/_http_parser.pyx":476 + /* "aiohttp/_http_parser.pyx":478 * cdef _on_message_complete(self): * self._payload.feed_eof() * self._payload = None # <<<<<<<<<<<<<< @@ -8634,7 +8781,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_message_comple __Pyx_DECREF(__pyx_v_self->_payload); __pyx_v_self->_payload = Py_None; - /* "aiohttp/_http_parser.pyx":474 + /* "aiohttp/_http_parser.pyx":476 * self._messages.append((msg, payload)) * * cdef _on_message_complete(self): # <<<<<<<<<<<<<< @@ -8657,7 +8804,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_message_comple return __pyx_r; } -/* "aiohttp/_http_parser.pyx":478 +/* "aiohttp/_http_parser.pyx":480 * self._payload = None * * cdef _on_chunk_header(self): # <<<<<<<<<<<<<< @@ -8676,14 +8823,14 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_chunk_header(s int __pyx_clineno = 0; __Pyx_RefNannySetupContext("_on_chunk_header", 0); - /* "aiohttp/_http_parser.pyx":479 + /* "aiohttp/_http_parser.pyx":481 * * cdef _on_chunk_header(self): * self._payload.begin_http_chunk_receiving() # <<<<<<<<<<<<<< * * cdef _on_chunk_complete(self): */ - __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_self->_payload, __pyx_n_s_begin_http_chunk_receiving); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 479, __pyx_L1_error) + __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_self->_payload, __pyx_n_s_begin_http_chunk_receiving); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 481, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); __pyx_t_3 = NULL; if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) { @@ -8697,12 +8844,12 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_chunk_header(s } __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3) : __Pyx_PyObject_CallNoArg(__pyx_t_2); __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; - if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 479, __pyx_L1_error) + if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 481, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - /* "aiohttp/_http_parser.pyx":478 + /* "aiohttp/_http_parser.pyx":480 * self._payload = None * * cdef _on_chunk_header(self): # <<<<<<<<<<<<<< @@ -8725,7 +8872,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_chunk_header(s return __pyx_r; } -/* "aiohttp/_http_parser.pyx":481 +/* "aiohttp/_http_parser.pyx":483 * self._payload.begin_http_chunk_receiving() * * cdef _on_chunk_complete(self): # <<<<<<<<<<<<<< @@ -8744,14 +8891,14 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_chunk_complete int __pyx_clineno = 0; __Pyx_RefNannySetupContext("_on_chunk_complete", 0); - /* "aiohttp/_http_parser.pyx":482 + /* "aiohttp/_http_parser.pyx":484 * * cdef _on_chunk_complete(self): * self._payload.end_http_chunk_receiving() # <<<<<<<<<<<<<< * * cdef object _on_status_complete(self): */ - __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_self->_payload, __pyx_n_s_end_http_chunk_receiving); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 482, __pyx_L1_error) + __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_self->_payload, __pyx_n_s_end_http_chunk_receiving); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 484, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); __pyx_t_3 = NULL; if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) { @@ -8765,12 +8912,12 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_chunk_complete } __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3) : __Pyx_PyObject_CallNoArg(__pyx_t_2); __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; - if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 482, __pyx_L1_error) + if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 484, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - /* "aiohttp/_http_parser.pyx":481 + /* "aiohttp/_http_parser.pyx":483 * self._payload.begin_http_chunk_receiving() * * cdef _on_chunk_complete(self): # <<<<<<<<<<<<<< @@ -8793,7 +8940,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_chunk_complete return __pyx_r; } -/* "aiohttp/_http_parser.pyx":484 +/* "aiohttp/_http_parser.pyx":486 * self._payload.end_http_chunk_receiving() * * cdef object _on_status_complete(self): # <<<<<<<<<<<<<< @@ -8813,19 +8960,19 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_status_complet return __pyx_r; } -/* "aiohttp/_http_parser.pyx":487 +/* "aiohttp/_http_parser.pyx":489 * pass * * cdef inline http_version(self): # <<<<<<<<<<<<<< - * cdef cparser.http_parser* parser = self._cparser + * cdef cparser.llhttp_t* parser = self._cparser * */ static CYTHON_INLINE PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser_http_version(struct __pyx_obj_7aiohttp_12_http_parser_HttpParser *__pyx_v_self) { - struct http_parser *__pyx_v_parser; + llhttp_t *__pyx_v_parser; PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations - struct http_parser *__pyx_t_1; + llhttp_t *__pyx_t_1; int __pyx_t_2; PyObject *__pyx_t_3 = NULL; PyObject *__pyx_t_4 = NULL; @@ -8839,18 +8986,18 @@ static CYTHON_INLINE PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser_http int __pyx_clineno = 0; __Pyx_RefNannySetupContext("http_version", 0); - /* "aiohttp/_http_parser.pyx":488 + /* "aiohttp/_http_parser.pyx":490 * * cdef inline http_version(self): - * cdef cparser.http_parser* parser = self._cparser # <<<<<<<<<<<<<< + * cdef cparser.llhttp_t* parser = self._cparser # <<<<<<<<<<<<<< * * if parser.http_major == 1: */ __pyx_t_1 = __pyx_v_self->_cparser; __pyx_v_parser = __pyx_t_1; - /* "aiohttp/_http_parser.pyx":490 - * cdef cparser.http_parser* parser = self._cparser + /* "aiohttp/_http_parser.pyx":492 + * cdef cparser.llhttp_t* parser = self._cparser * * if parser.http_major == 1: # <<<<<<<<<<<<<< * if parser.http_minor == 0: @@ -8859,7 +9006,7 @@ static CYTHON_INLINE PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser_http __pyx_t_2 = ((__pyx_v_parser->http_major == 1) != 0); if (__pyx_t_2) { - /* "aiohttp/_http_parser.pyx":491 + /* "aiohttp/_http_parser.pyx":493 * * if parser.http_major == 1: * if parser.http_minor == 0: # <<<<<<<<<<<<<< @@ -8869,7 +9016,7 @@ static CYTHON_INLINE PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser_http switch (__pyx_v_parser->http_minor) { case 0: - /* "aiohttp/_http_parser.pyx":492 + /* "aiohttp/_http_parser.pyx":494 * if parser.http_major == 1: * if parser.http_minor == 0: * return HttpVersion10 # <<<<<<<<<<<<<< @@ -8881,7 +9028,7 @@ static CYTHON_INLINE PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser_http __pyx_r = __pyx_v_7aiohttp_12_http_parser_HttpVersion10; goto __pyx_L0; - /* "aiohttp/_http_parser.pyx":491 + /* "aiohttp/_http_parser.pyx":493 * * if parser.http_major == 1: * if parser.http_minor == 0: # <<<<<<<<<<<<<< @@ -8891,7 +9038,7 @@ static CYTHON_INLINE PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser_http break; case 1: - /* "aiohttp/_http_parser.pyx":494 + /* "aiohttp/_http_parser.pyx":496 * return HttpVersion10 * elif parser.http_minor == 1: * return HttpVersion11 # <<<<<<<<<<<<<< @@ -8903,7 +9050,7 @@ static CYTHON_INLINE PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser_http __pyx_r = __pyx_v_7aiohttp_12_http_parser_HttpVersion11; goto __pyx_L0; - /* "aiohttp/_http_parser.pyx":493 + /* "aiohttp/_http_parser.pyx":495 * if parser.http_minor == 0: * return HttpVersion10 * elif parser.http_minor == 1: # <<<<<<<<<<<<<< @@ -8914,8 +9061,8 @@ static CYTHON_INLINE PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser_http default: break; } - /* "aiohttp/_http_parser.pyx":490 - * cdef cparser.http_parser* parser = self._cparser + /* "aiohttp/_http_parser.pyx":492 + * cdef cparser.llhttp_t* parser = self._cparser * * if parser.http_major == 1: # <<<<<<<<<<<<<< * if parser.http_minor == 0: @@ -8923,7 +9070,7 @@ static CYTHON_INLINE PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser_http */ } - /* "aiohttp/_http_parser.pyx":496 + /* "aiohttp/_http_parser.pyx":498 * return HttpVersion11 * * return HttpVersion(parser.http_major, parser.http_minor) # <<<<<<<<<<<<<< @@ -8931,9 +9078,9 @@ static CYTHON_INLINE PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser_http * ### Public API ### */ __Pyx_XDECREF(__pyx_r); - __pyx_t_4 = __Pyx_PyInt_From_unsigned_short(__pyx_v_parser->http_major); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 496, __pyx_L1_error) + __pyx_t_4 = __Pyx_PyInt_From_uint8_t(__pyx_v_parser->http_major); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 498, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); - __pyx_t_5 = __Pyx_PyInt_From_unsigned_short(__pyx_v_parser->http_minor); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 496, __pyx_L1_error) + __pyx_t_5 = __Pyx_PyInt_From_uint8_t(__pyx_v_parser->http_minor); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 498, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_5); __Pyx_INCREF(__pyx_v_7aiohttp_12_http_parser_HttpVersion); __pyx_t_6 = __pyx_v_7aiohttp_12_http_parser_HttpVersion; __pyx_t_7 = NULL; @@ -8951,7 +9098,7 @@ static CYTHON_INLINE PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser_http #if CYTHON_FAST_PYCALL if (PyFunction_Check(__pyx_t_6)) { PyObject *__pyx_temp[3] = {__pyx_t_7, __pyx_t_4, __pyx_t_5}; - __pyx_t_3 = __Pyx_PyFunction_FastCall(__pyx_t_6, __pyx_temp+1-__pyx_t_8, 2+__pyx_t_8); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 496, __pyx_L1_error) + __pyx_t_3 = __Pyx_PyFunction_FastCall(__pyx_t_6, __pyx_temp+1-__pyx_t_8, 2+__pyx_t_8); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 498, __pyx_L1_error) __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; __Pyx_GOTREF(__pyx_t_3); __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; @@ -8961,7 +9108,7 @@ static CYTHON_INLINE PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser_http #if CYTHON_FAST_PYCCALL if (__Pyx_PyFastCFunction_Check(__pyx_t_6)) { PyObject *__pyx_temp[3] = {__pyx_t_7, __pyx_t_4, __pyx_t_5}; - __pyx_t_3 = __Pyx_PyCFunction_FastCall(__pyx_t_6, __pyx_temp+1-__pyx_t_8, 2+__pyx_t_8); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 496, __pyx_L1_error) + __pyx_t_3 = __Pyx_PyCFunction_FastCall(__pyx_t_6, __pyx_temp+1-__pyx_t_8, 2+__pyx_t_8); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 498, __pyx_L1_error) __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; __Pyx_GOTREF(__pyx_t_3); __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; @@ -8969,7 +9116,7 @@ static CYTHON_INLINE PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser_http } else #endif { - __pyx_t_9 = PyTuple_New(2+__pyx_t_8); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 496, __pyx_L1_error) + __pyx_t_9 = PyTuple_New(2+__pyx_t_8); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 498, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_9); if (__pyx_t_7) { __Pyx_GIVEREF(__pyx_t_7); PyTuple_SET_ITEM(__pyx_t_9, 0, __pyx_t_7); __pyx_t_7 = NULL; @@ -8980,7 +9127,7 @@ static CYTHON_INLINE PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser_http PyTuple_SET_ITEM(__pyx_t_9, 1+__pyx_t_8, __pyx_t_5); __pyx_t_4 = 0; __pyx_t_5 = 0; - __pyx_t_3 = __Pyx_PyObject_Call(__pyx_t_6, __pyx_t_9, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 496, __pyx_L1_error) + __pyx_t_3 = __Pyx_PyObject_Call(__pyx_t_6, __pyx_t_9, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 498, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; } @@ -8989,11 +9136,11 @@ static CYTHON_INLINE PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser_http __pyx_t_3 = 0; goto __pyx_L0; - /* "aiohttp/_http_parser.pyx":487 + /* "aiohttp/_http_parser.pyx":489 * pass * * cdef inline http_version(self): # <<<<<<<<<<<<<< - * cdef cparser.http_parser* parser = self._cparser + * cdef cparser.llhttp_t* parser = self._cparser * */ @@ -9013,7 +9160,7 @@ static CYTHON_INLINE PyObject *__pyx_f_7aiohttp_12_http_parser_10HttpParser_http return __pyx_r; } -/* "aiohttp/_http_parser.pyx":500 +/* "aiohttp/_http_parser.pyx":502 * ### Public API ### * * def feed_eof(self): # <<<<<<<<<<<<<< @@ -9049,7 +9196,7 @@ static PyObject *__pyx_pf_7aiohttp_12_http_parser_10HttpParser_4feed_eof(struct int __pyx_clineno = 0; __Pyx_RefNannySetupContext("feed_eof", 0); - /* "aiohttp/_http_parser.pyx":503 + /* "aiohttp/_http_parser.pyx":505 * cdef bytes desc * * if self._payload is not None: # <<<<<<<<<<<<<< @@ -9060,7 +9207,7 @@ static PyObject *__pyx_pf_7aiohttp_12_http_parser_10HttpParser_4feed_eof(struct __pyx_t_2 = (__pyx_t_1 != 0); if (__pyx_t_2) { - /* "aiohttp/_http_parser.pyx":504 + /* "aiohttp/_http_parser.pyx":506 * * if self._payload is not None: * if self._cparser.flags & cparser.F_CHUNKED: # <<<<<<<<<<<<<< @@ -9070,14 +9217,14 @@ static PyObject *__pyx_pf_7aiohttp_12_http_parser_10HttpParser_4feed_eof(struct __pyx_t_2 = ((__pyx_v_self->_cparser->flags & F_CHUNKED) != 0); if (unlikely(__pyx_t_2)) { - /* "aiohttp/_http_parser.pyx":505 + /* "aiohttp/_http_parser.pyx":507 * if self._payload is not None: * if self._cparser.flags & cparser.F_CHUNKED: * raise TransferEncodingError( # <<<<<<<<<<<<<< * "Not enough data for satisfy transfer length header.") - * elif self._cparser.flags & cparser.F_CONTENTLENGTH: + * elif self._cparser.flags & cparser.F_CONTENT_LENGTH: */ - __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_TransferEncodingError); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 505, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_TransferEncodingError); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 507, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __pyx_t_5 = NULL; if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) { @@ -9091,14 +9238,14 @@ static PyObject *__pyx_pf_7aiohttp_12_http_parser_10HttpParser_4feed_eof(struct } __pyx_t_3 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_5, __pyx_kp_u_Not_enough_data_for_satisfy_tran) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_kp_u_Not_enough_data_for_satisfy_tran); __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; - if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 505, __pyx_L1_error) + if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 507, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __Pyx_Raise(__pyx_t_3, 0, 0, 0); __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __PYX_ERR(0, 505, __pyx_L1_error) + __PYX_ERR(0, 507, __pyx_L1_error) - /* "aiohttp/_http_parser.pyx":504 + /* "aiohttp/_http_parser.pyx":506 * * if self._payload is not None: * if self._cparser.flags & cparser.F_CHUNKED: # <<<<<<<<<<<<<< @@ -9107,24 +9254,24 @@ static PyObject *__pyx_pf_7aiohttp_12_http_parser_10HttpParser_4feed_eof(struct */ } - /* "aiohttp/_http_parser.pyx":507 + /* "aiohttp/_http_parser.pyx":509 * raise TransferEncodingError( * "Not enough data for satisfy transfer length header.") - * elif self._cparser.flags & cparser.F_CONTENTLENGTH: # <<<<<<<<<<<<<< + * elif self._cparser.flags & cparser.F_CONTENT_LENGTH: # <<<<<<<<<<<<<< * raise ContentLengthError( * "Not enough data for satisfy content length header.") */ - __pyx_t_2 = ((__pyx_v_self->_cparser->flags & F_CONTENTLENGTH) != 0); + __pyx_t_2 = ((__pyx_v_self->_cparser->flags & F_CONTENT_LENGTH) != 0); if (unlikely(__pyx_t_2)) { - /* "aiohttp/_http_parser.pyx":508 + /* "aiohttp/_http_parser.pyx":510 * "Not enough data for satisfy transfer length header.") - * elif self._cparser.flags & cparser.F_CONTENTLENGTH: + * elif self._cparser.flags & cparser.F_CONTENT_LENGTH: * raise ContentLengthError( # <<<<<<<<<<<<<< * "Not enough data for satisfy content length header.") - * elif self._cparser.http_errno != cparser.HPE_OK: + * elif cparser.llhttp_get_errno(self._cparser) != cparser.HPE_OK: */ - __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_ContentLengthError); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 508, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_ContentLengthError); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 510, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __pyx_t_5 = NULL; if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) { @@ -9138,54 +9285,54 @@ static PyObject *__pyx_pf_7aiohttp_12_http_parser_10HttpParser_4feed_eof(struct } __pyx_t_3 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_5, __pyx_kp_u_Not_enough_data_for_satisfy_cont) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_kp_u_Not_enough_data_for_satisfy_cont); __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; - if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 508, __pyx_L1_error) + if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 510, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __Pyx_Raise(__pyx_t_3, 0, 0, 0); __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __PYX_ERR(0, 508, __pyx_L1_error) + __PYX_ERR(0, 510, __pyx_L1_error) - /* "aiohttp/_http_parser.pyx":507 + /* "aiohttp/_http_parser.pyx":509 * raise TransferEncodingError( * "Not enough data for satisfy transfer length header.") - * elif self._cparser.flags & cparser.F_CONTENTLENGTH: # <<<<<<<<<<<<<< + * elif self._cparser.flags & cparser.F_CONTENT_LENGTH: # <<<<<<<<<<<<<< * raise ContentLengthError( * "Not enough data for satisfy content length header.") */ } - /* "aiohttp/_http_parser.pyx":510 + /* "aiohttp/_http_parser.pyx":512 * raise ContentLengthError( * "Not enough data for satisfy content length header.") - * elif self._cparser.http_errno != cparser.HPE_OK: # <<<<<<<<<<<<<< - * desc = cparser.http_errno_description( - * self._cparser.http_errno) + * elif cparser.llhttp_get_errno(self._cparser) != cparser.HPE_OK: # <<<<<<<<<<<<<< + * desc = cparser.llhttp_get_error_reason(self._cparser) + * raise PayloadEncodingError(desc.decode('latin-1')) */ - __pyx_t_2 = ((__pyx_v_self->_cparser->http_errno != HPE_OK) != 0); + __pyx_t_2 = ((llhttp_get_errno(__pyx_v_self->_cparser) != HPE_OK) != 0); if (unlikely(__pyx_t_2)) { - /* "aiohttp/_http_parser.pyx":511 + /* "aiohttp/_http_parser.pyx":513 * "Not enough data for satisfy content length header.") - * elif self._cparser.http_errno != cparser.HPE_OK: - * desc = cparser.http_errno_description( # <<<<<<<<<<<<<< - * self._cparser.http_errno) + * elif cparser.llhttp_get_errno(self._cparser) != cparser.HPE_OK: + * desc = cparser.llhttp_get_error_reason(self._cparser) # <<<<<<<<<<<<<< * raise PayloadEncodingError(desc.decode('latin-1')) + * else: */ - __pyx_t_3 = __Pyx_PyBytes_FromString(http_errno_description(((enum http_errno)__pyx_v_self->_cparser->http_errno))); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 511, __pyx_L1_error) + __pyx_t_3 = __Pyx_PyBytes_FromString(llhttp_get_error_reason(__pyx_v_self->_cparser)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 513, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_v_desc = ((PyObject*)__pyx_t_3); __pyx_t_3 = 0; - /* "aiohttp/_http_parser.pyx":513 - * desc = cparser.http_errno_description( - * self._cparser.http_errno) + /* "aiohttp/_http_parser.pyx":514 + * elif cparser.llhttp_get_errno(self._cparser) != cparser.HPE_OK: + * desc = cparser.llhttp_get_error_reason(self._cparser) * raise PayloadEncodingError(desc.decode('latin-1')) # <<<<<<<<<<<<<< * else: * self._payload.feed_eof() */ - __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_PayloadEncodingError); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 513, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_PayloadEncodingError); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 514, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); - __pyx_t_5 = __Pyx_decode_bytes(__pyx_v_desc, 0, PY_SSIZE_T_MAX, NULL, NULL, PyUnicode_DecodeLatin1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 513, __pyx_L1_error) + __pyx_t_5 = __Pyx_decode_bytes(__pyx_v_desc, 0, PY_SSIZE_T_MAX, NULL, NULL, PyUnicode_DecodeLatin1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 514, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_5); __pyx_t_6 = NULL; if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) { @@ -9200,23 +9347,23 @@ static PyObject *__pyx_pf_7aiohttp_12_http_parser_10HttpParser_4feed_eof(struct __pyx_t_3 = (__pyx_t_6) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_6, __pyx_t_5) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_5); __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; - if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 513, __pyx_L1_error) + if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 514, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __Pyx_Raise(__pyx_t_3, 0, 0, 0); __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __PYX_ERR(0, 513, __pyx_L1_error) + __PYX_ERR(0, 514, __pyx_L1_error) - /* "aiohttp/_http_parser.pyx":510 + /* "aiohttp/_http_parser.pyx":512 * raise ContentLengthError( * "Not enough data for satisfy content length header.") - * elif self._cparser.http_errno != cparser.HPE_OK: # <<<<<<<<<<<<<< - * desc = cparser.http_errno_description( - * self._cparser.http_errno) + * elif cparser.llhttp_get_errno(self._cparser) != cparser.HPE_OK: # <<<<<<<<<<<<<< + * desc = cparser.llhttp_get_error_reason(self._cparser) + * raise PayloadEncodingError(desc.decode('latin-1')) */ } - /* "aiohttp/_http_parser.pyx":515 + /* "aiohttp/_http_parser.pyx":516 * raise PayloadEncodingError(desc.decode('latin-1')) * else: * self._payload.feed_eof() # <<<<<<<<<<<<<< @@ -9224,7 +9371,7 @@ static PyObject *__pyx_pf_7aiohttp_12_http_parser_10HttpParser_4feed_eof(struct * self._on_headers_complete() */ /*else*/ { - __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_self->_payload, __pyx_n_s_feed_eof); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 515, __pyx_L1_error) + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_self->_payload, __pyx_n_s_feed_eof); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 516, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __pyx_t_5 = NULL; if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_4))) { @@ -9238,13 +9385,13 @@ static PyObject *__pyx_pf_7aiohttp_12_http_parser_10HttpParser_4feed_eof(struct } __pyx_t_3 = (__pyx_t_5) ? __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_5) : __Pyx_PyObject_CallNoArg(__pyx_t_4); __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; - if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 515, __pyx_L1_error) + if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 516, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; } - /* "aiohttp/_http_parser.pyx":503 + /* "aiohttp/_http_parser.pyx":505 * cdef bytes desc * * if self._payload is not None: # <<<<<<<<<<<<<< @@ -9254,7 +9401,7 @@ static PyObject *__pyx_pf_7aiohttp_12_http_parser_10HttpParser_4feed_eof(struct goto __pyx_L3; } - /* "aiohttp/_http_parser.pyx":516 + /* "aiohttp/_http_parser.pyx":517 * else: * self._payload.feed_eof() * elif self._started: # <<<<<<<<<<<<<< @@ -9264,18 +9411,18 @@ static PyObject *__pyx_pf_7aiohttp_12_http_parser_10HttpParser_4feed_eof(struct __pyx_t_2 = (__pyx_v_self->_started != 0); if (__pyx_t_2) { - /* "aiohttp/_http_parser.pyx":517 + /* "aiohttp/_http_parser.pyx":518 * self._payload.feed_eof() * elif self._started: * self._on_headers_complete() # <<<<<<<<<<<<<< * if self._messages: * return self._messages[-1][0] */ - __pyx_t_3 = ((struct __pyx_vtabstruct_7aiohttp_12_http_parser_HttpParser *)__pyx_v_self->__pyx_vtab)->_on_headers_complete(__pyx_v_self); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 517, __pyx_L1_error) + __pyx_t_3 = ((struct __pyx_vtabstruct_7aiohttp_12_http_parser_HttpParser *)__pyx_v_self->__pyx_vtab)->_on_headers_complete(__pyx_v_self); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 518, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - /* "aiohttp/_http_parser.pyx":518 + /* "aiohttp/_http_parser.pyx":519 * elif self._started: * self._on_headers_complete() * if self._messages: # <<<<<<<<<<<<<< @@ -9285,7 +9432,7 @@ static PyObject *__pyx_pf_7aiohttp_12_http_parser_10HttpParser_4feed_eof(struct __pyx_t_2 = (__pyx_v_self->_messages != Py_None)&&(PyList_GET_SIZE(__pyx_v_self->_messages) != 0); if (__pyx_t_2) { - /* "aiohttp/_http_parser.pyx":519 + /* "aiohttp/_http_parser.pyx":520 * self._on_headers_complete() * if self._messages: * return self._messages[-1][0] # <<<<<<<<<<<<<< @@ -9295,18 +9442,18 @@ static PyObject *__pyx_pf_7aiohttp_12_http_parser_10HttpParser_4feed_eof(struct __Pyx_XDECREF(__pyx_r); if (unlikely(__pyx_v_self->_messages == Py_None)) { PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); - __PYX_ERR(0, 519, __pyx_L1_error) + __PYX_ERR(0, 520, __pyx_L1_error) } - __pyx_t_3 = __Pyx_GetItemInt_List(__pyx_v_self->_messages, -1L, long, 1, __Pyx_PyInt_From_long, 1, 1, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 519, __pyx_L1_error) + __pyx_t_3 = __Pyx_GetItemInt_List(__pyx_v_self->_messages, -1L, long, 1, __Pyx_PyInt_From_long, 1, 1, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 520, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); - __pyx_t_4 = __Pyx_GetItemInt(__pyx_t_3, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 519, __pyx_L1_error) + __pyx_t_4 = __Pyx_GetItemInt(__pyx_t_3, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 520, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __pyx_r = __pyx_t_4; __pyx_t_4 = 0; goto __pyx_L0; - /* "aiohttp/_http_parser.pyx":518 + /* "aiohttp/_http_parser.pyx":519 * elif self._started: * self._on_headers_complete() * if self._messages: # <<<<<<<<<<<<<< @@ -9315,7 +9462,7 @@ static PyObject *__pyx_pf_7aiohttp_12_http_parser_10HttpParser_4feed_eof(struct */ } - /* "aiohttp/_http_parser.pyx":516 + /* "aiohttp/_http_parser.pyx":517 * else: * self._payload.feed_eof() * elif self._started: # <<<<<<<<<<<<<< @@ -9325,7 +9472,7 @@ static PyObject *__pyx_pf_7aiohttp_12_http_parser_10HttpParser_4feed_eof(struct } __pyx_L3:; - /* "aiohttp/_http_parser.pyx":500 + /* "aiohttp/_http_parser.pyx":502 * ### Public API ### * * def feed_eof(self): # <<<<<<<<<<<<<< @@ -9350,7 +9497,7 @@ static PyObject *__pyx_pf_7aiohttp_12_http_parser_10HttpParser_4feed_eof(struct return __pyx_r; } -/* "aiohttp/_http_parser.pyx":521 +/* "aiohttp/_http_parser.pyx":522 * return self._messages[-1][0] * * def feed_data(self, data): # <<<<<<<<<<<<<< @@ -9374,7 +9521,12 @@ static PyObject *__pyx_pw_7aiohttp_12_http_parser_10HttpParser_7feed_data(PyObje static PyObject *__pyx_pf_7aiohttp_12_http_parser_10HttpParser_6feed_data(struct __pyx_obj_7aiohttp_12_http_parser_HttpParser *__pyx_v_self, PyObject *__pyx_v_data) { size_t __pyx_v_data_len; size_t __pyx_v_nb; + llhttp_errno_t __pyx_v_errno; PyObject *__pyx_v_ex = NULL; + char const *__pyx_v_after; + PyObject *__pyx_v_before = NULL; + PyObject *__pyx_v_after_b = NULL; + PyObject *__pyx_v_pointer = NULL; PyObject *__pyx_v_messages = NULL; PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations @@ -9383,79 +9535,127 @@ static PyObject *__pyx_pf_7aiohttp_12_http_parser_10HttpParser_6feed_data(struct int __pyx_t_3; PyObject *__pyx_t_4 = NULL; PyObject *__pyx_t_5 = NULL; + Py_ssize_t __pyx_t_6; int __pyx_lineno = 0; const char *__pyx_filename = NULL; int __pyx_clineno = 0; __Pyx_RefNannySetupContext("feed_data", 0); + __Pyx_INCREF(__pyx_v_data); - /* "aiohttp/_http_parser.pyx":526 - * size_t nb + /* "aiohttp/_http_parser.pyx":528 + * cdef cparser.llhttp_errno_t errno * * PyObject_GetBuffer(data, &self.py_buf, PyBUF_SIMPLE) # <<<<<<<<<<<<<< * data_len = self.py_buf.len * */ - __pyx_t_1 = PyObject_GetBuffer(__pyx_v_data, (&__pyx_v_self->py_buf), PyBUF_SIMPLE); if (unlikely(__pyx_t_1 == ((int)-1))) __PYX_ERR(0, 526, __pyx_L1_error) + __pyx_t_1 = PyObject_GetBuffer(__pyx_v_data, (&__pyx_v_self->py_buf), PyBUF_SIMPLE); if (unlikely(__pyx_t_1 == ((int)-1))) __PYX_ERR(0, 528, __pyx_L1_error) - /* "aiohttp/_http_parser.pyx":527 + /* "aiohttp/_http_parser.pyx":529 * * PyObject_GetBuffer(data, &self.py_buf, PyBUF_SIMPLE) * data_len = self.py_buf.len # <<<<<<<<<<<<<< * - * nb = cparser.http_parser_execute( + * errno = cparser.llhttp_execute( */ __pyx_v_data_len = ((size_t)__pyx_v_self->py_buf.len); - /* "aiohttp/_http_parser.pyx":529 + /* "aiohttp/_http_parser.pyx":531 * data_len = self.py_buf.len * - * nb = cparser.http_parser_execute( # <<<<<<<<<<<<<< + * errno = cparser.llhttp_execute( # <<<<<<<<<<<<<< * self._cparser, - * self._csettings, + * self.py_buf.buf, + */ + __pyx_v_errno = llhttp_execute(__pyx_v_self->_cparser, ((char *)__pyx_v_self->py_buf.buf), __pyx_v_data_len); + + /* "aiohttp/_http_parser.pyx":536 + * data_len) + * + * if errno is cparser.HPE_PAUSED_UPGRADE: # <<<<<<<<<<<<<< + * cparser.llhttp_resume_after_upgrade(self._cparser) + * + */ + __pyx_t_2 = ((__pyx_v_errno == HPE_PAUSED_UPGRADE) != 0); + if (__pyx_t_2) { + + /* "aiohttp/_http_parser.pyx":537 + * + * if errno is cparser.HPE_PAUSED_UPGRADE: + * cparser.llhttp_resume_after_upgrade(self._cparser) # <<<<<<<<<<<<<< + * + * nb = cparser.llhttp_get_error_pos(self._cparser) - self.py_buf.buf + */ + llhttp_resume_after_upgrade(__pyx_v_self->_cparser); + + /* "aiohttp/_http_parser.pyx":539 + * cparser.llhttp_resume_after_upgrade(self._cparser) + * + * nb = cparser.llhttp_get_error_pos(self._cparser) - self.py_buf.buf # <<<<<<<<<<<<<< + * + * PyBuffer_Release(&self.py_buf) */ - __pyx_v_nb = http_parser_execute(__pyx_v_self->_cparser, __pyx_v_self->_csettings, ((char *)__pyx_v_self->py_buf.buf), __pyx_v_data_len); + __pyx_v_nb = (llhttp_get_error_pos(__pyx_v_self->_cparser) - ((char *)__pyx_v_self->py_buf.buf)); - /* "aiohttp/_http_parser.pyx":535 + /* "aiohttp/_http_parser.pyx":536 * data_len) * + * if errno is cparser.HPE_PAUSED_UPGRADE: # <<<<<<<<<<<<<< + * cparser.llhttp_resume_after_upgrade(self._cparser) + * + */ + } + + /* "aiohttp/_http_parser.pyx":541 + * nb = cparser.llhttp_get_error_pos(self._cparser) - self.py_buf.buf + * * PyBuffer_Release(&self.py_buf) # <<<<<<<<<<<<<< * - * if (self._cparser.http_errno != cparser.HPE_OK): + * if errno not in (cparser.HPE_OK, cparser.HPE_PAUSED_UPGRADE): */ PyBuffer_Release((&__pyx_v_self->py_buf)); - /* "aiohttp/_http_parser.pyx":537 + /* "aiohttp/_http_parser.pyx":543 * PyBuffer_Release(&self.py_buf) * - * if (self._cparser.http_errno != cparser.HPE_OK): # <<<<<<<<<<<<<< + * if errno not in (cparser.HPE_OK, cparser.HPE_PAUSED_UPGRADE): # <<<<<<<<<<<<<< * if self._payload_error == 0: * if self._last_error is not None: */ - __pyx_t_2 = ((__pyx_v_self->_cparser->http_errno != HPE_OK) != 0); - if (__pyx_t_2) { + switch (__pyx_v_errno) { + case HPE_OK: + case HPE_PAUSED_UPGRADE: + __pyx_t_2 = 0; + break; + default: + __pyx_t_2 = 1; + break; + } + __pyx_t_3 = (__pyx_t_2 != 0); + if (__pyx_t_3) { - /* "aiohttp/_http_parser.pyx":538 + /* "aiohttp/_http_parser.pyx":544 * - * if (self._cparser.http_errno != cparser.HPE_OK): + * if errno not in (cparser.HPE_OK, cparser.HPE_PAUSED_UPGRADE): * if self._payload_error == 0: # <<<<<<<<<<<<<< * if self._last_error is not None: * ex = self._last_error */ - __pyx_t_2 = ((__pyx_v_self->_payload_error == 0) != 0); - if (__pyx_t_2) { + __pyx_t_3 = ((__pyx_v_self->_payload_error == 0) != 0); + if (__pyx_t_3) { - /* "aiohttp/_http_parser.pyx":539 - * if (self._cparser.http_errno != cparser.HPE_OK): + /* "aiohttp/_http_parser.pyx":545 + * if errno not in (cparser.HPE_OK, cparser.HPE_PAUSED_UPGRADE): * if self._payload_error == 0: * if self._last_error is not None: # <<<<<<<<<<<<<< * ex = self._last_error * self._last_error = None */ - __pyx_t_2 = (__pyx_v_self->_last_error != Py_None); - __pyx_t_3 = (__pyx_t_2 != 0); - if (__pyx_t_3) { + __pyx_t_3 = (__pyx_v_self->_last_error != Py_None); + __pyx_t_2 = (__pyx_t_3 != 0); + if (__pyx_t_2) { - /* "aiohttp/_http_parser.pyx":540 + /* "aiohttp/_http_parser.pyx":546 * if self._payload_error == 0: * if self._last_error is not None: * ex = self._last_error # <<<<<<<<<<<<<< @@ -9467,12 +9667,12 @@ static PyObject *__pyx_pf_7aiohttp_12_http_parser_10HttpParser_6feed_data(struct __pyx_v_ex = __pyx_t_4; __pyx_t_4 = 0; - /* "aiohttp/_http_parser.pyx":541 + /* "aiohttp/_http_parser.pyx":547 * if self._last_error is not None: * ex = self._last_error * self._last_error = None # <<<<<<<<<<<<<< * else: - * ex = parser_error_from_errno( + * after = cparser.llhttp_get_error_pos(self._cparser) */ __Pyx_INCREF(Py_None); __Pyx_GIVEREF(Py_None); @@ -9480,42 +9680,129 @@ static PyObject *__pyx_pf_7aiohttp_12_http_parser_10HttpParser_6feed_data(struct __Pyx_DECREF(__pyx_v_self->_last_error); __pyx_v_self->_last_error = Py_None; - /* "aiohttp/_http_parser.pyx":539 - * if (self._cparser.http_errno != cparser.HPE_OK): + /* "aiohttp/_http_parser.pyx":545 + * if errno not in (cparser.HPE_OK, cparser.HPE_PAUSED_UPGRADE): * if self._payload_error == 0: * if self._last_error is not None: # <<<<<<<<<<<<<< * ex = self._last_error * self._last_error = None */ - goto __pyx_L5; + goto __pyx_L6; } - /* "aiohttp/_http_parser.pyx":543 + /* "aiohttp/_http_parser.pyx":549 * self._last_error = None * else: - * ex = parser_error_from_errno( # <<<<<<<<<<<<<< - * self._cparser.http_errno) - * self._payload = None + * after = cparser.llhttp_get_error_pos(self._cparser) # <<<<<<<<<<<<<< + * before = data[:after - self.py_buf.buf] + * after_b = after.split(b"\r\n", 1)[0] */ /*else*/ { + __pyx_v_after = llhttp_get_error_pos(__pyx_v_self->_cparser); - /* "aiohttp/_http_parser.pyx":544 + /* "aiohttp/_http_parser.pyx":550 * else: - * ex = parser_error_from_errno( - * self._cparser.http_errno) # <<<<<<<<<<<<<< - * self._payload = None - * raise ex + * after = cparser.llhttp_get_error_pos(self._cparser) + * before = data[:after - self.py_buf.buf] # <<<<<<<<<<<<<< + * after_b = after.split(b"\r\n", 1)[0] + * before = before.rsplit(b"\r\n", 1)[-1] */ - __pyx_t_4 = __pyx_f_7aiohttp_12_http_parser_parser_error_from_errno(((enum http_errno)__pyx_v_self->_cparser->http_errno)); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 543, __pyx_L1_error) + __pyx_t_4 = __Pyx_PyObject_GetSlice(__pyx_v_data, 0, (__pyx_v_after - ((char *)__pyx_v_self->py_buf.buf)), NULL, NULL, NULL, 0, 1, 1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 550, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); - __pyx_v_ex = __pyx_t_4; + __pyx_v_before = __pyx_t_4; __pyx_t_4 = 0; + + /* "aiohttp/_http_parser.pyx":551 + * after = cparser.llhttp_get_error_pos(self._cparser) + * before = data[:after - self.py_buf.buf] + * after_b = after.split(b"\r\n", 1)[0] # <<<<<<<<<<<<<< + * before = before.rsplit(b"\r\n", 1)[-1] + * data = before + after_b + */ + __pyx_t_4 = __Pyx_PyBytes_FromString(__pyx_v_after); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 551, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_n_s_split); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 551, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_4 = __Pyx_PyObject_Call(__pyx_t_5, __pyx_tuple__5, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 551, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_5 = __Pyx_GetItemInt(__pyx_t_4, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 551, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_v_after_b = __pyx_t_5; + __pyx_t_5 = 0; + + /* "aiohttp/_http_parser.pyx":552 + * before = data[:after - self.py_buf.buf] + * after_b = after.split(b"\r\n", 1)[0] + * before = before.rsplit(b"\r\n", 1)[-1] # <<<<<<<<<<<<<< + * data = before + after_b + * pointer = " " * (len(repr(before))-1) + "^" + */ + __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_before, __pyx_n_s_rsplit); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 552, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_4 = __Pyx_PyObject_Call(__pyx_t_5, __pyx_tuple__5, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 552, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_5 = __Pyx_GetItemInt(__pyx_t_4, -1L, long, 1, __Pyx_PyInt_From_long, 0, 1, 1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 552, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_DECREF_SET(__pyx_v_before, __pyx_t_5); + __pyx_t_5 = 0; + + /* "aiohttp/_http_parser.pyx":553 + * after_b = after.split(b"\r\n", 1)[0] + * before = before.rsplit(b"\r\n", 1)[-1] + * data = before + after_b # <<<<<<<<<<<<<< + * pointer = " " * (len(repr(before))-1) + "^" + * ex = parser_error_from_errno(self._cparser, data, pointer) + */ + __pyx_t_5 = PyNumber_Add(__pyx_v_before, __pyx_v_after_b); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 553, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF_SET(__pyx_v_data, __pyx_t_5); + __pyx_t_5 = 0; + + /* "aiohttp/_http_parser.pyx":554 + * before = before.rsplit(b"\r\n", 1)[-1] + * data = before + after_b + * pointer = " " * (len(repr(before))-1) + "^" # <<<<<<<<<<<<<< + * ex = parser_error_from_errno(self._cparser, data, pointer) + * self._payload = None + */ + __pyx_t_5 = PyObject_Repr(__pyx_v_before); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 554, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_6 = PyObject_Length(__pyx_t_5); if (unlikely(__pyx_t_6 == ((Py_ssize_t)-1))) __PYX_ERR(0, 554, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_5 = PyInt_FromSsize_t((__pyx_t_6 - 1)); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 554, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_4 = PyNumber_Multiply(__pyx_kp_u__6, __pyx_t_5); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 554, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_5 = PyNumber_Add(__pyx_t_4, __pyx_kp_u__7); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 554, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + if (!(likely(PyUnicode_CheckExact(__pyx_t_5))||((__pyx_t_5) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "unicode", Py_TYPE(__pyx_t_5)->tp_name), 0))) __PYX_ERR(0, 554, __pyx_L1_error) + __pyx_v_pointer = ((PyObject*)__pyx_t_5); + __pyx_t_5 = 0; + + /* "aiohttp/_http_parser.pyx":555 + * data = before + after_b + * pointer = " " * (len(repr(before))-1) + "^" + * ex = parser_error_from_errno(self._cparser, data, pointer) # <<<<<<<<<<<<<< + * self._payload = None + * raise ex + */ + __pyx_t_5 = __pyx_f_7aiohttp_12_http_parser_parser_error_from_errno(__pyx_v_self->_cparser, __pyx_v_data, __pyx_v_pointer); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 555, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __pyx_v_ex = __pyx_t_5; + __pyx_t_5 = 0; } - __pyx_L5:; + __pyx_L6:; - /* "aiohttp/_http_parser.pyx":545 - * ex = parser_error_from_errno( - * self._cparser.http_errno) + /* "aiohttp/_http_parser.pyx":556 + * pointer = " " * (len(repr(before))-1) + "^" + * ex = parser_error_from_errno(self._cparser, data, pointer) * self._payload = None # <<<<<<<<<<<<<< * raise ex * @@ -9526,82 +9813,82 @@ static PyObject *__pyx_pf_7aiohttp_12_http_parser_10HttpParser_6feed_data(struct __Pyx_DECREF(__pyx_v_self->_payload); __pyx_v_self->_payload = Py_None; - /* "aiohttp/_http_parser.pyx":546 - * self._cparser.http_errno) + /* "aiohttp/_http_parser.pyx":557 + * ex = parser_error_from_errno(self._cparser, data, pointer) * self._payload = None * raise ex # <<<<<<<<<<<<<< * * if self._messages: */ __Pyx_Raise(__pyx_v_ex, 0, 0, 0); - __PYX_ERR(0, 546, __pyx_L1_error) + __PYX_ERR(0, 557, __pyx_L1_error) - /* "aiohttp/_http_parser.pyx":538 + /* "aiohttp/_http_parser.pyx":544 * - * if (self._cparser.http_errno != cparser.HPE_OK): + * if errno not in (cparser.HPE_OK, cparser.HPE_PAUSED_UPGRADE): * if self._payload_error == 0: # <<<<<<<<<<<<<< * if self._last_error is not None: * ex = self._last_error */ } - /* "aiohttp/_http_parser.pyx":537 + /* "aiohttp/_http_parser.pyx":543 * PyBuffer_Release(&self.py_buf) * - * if (self._cparser.http_errno != cparser.HPE_OK): # <<<<<<<<<<<<<< + * if errno not in (cparser.HPE_OK, cparser.HPE_PAUSED_UPGRADE): # <<<<<<<<<<<<<< * if self._payload_error == 0: * if self._last_error is not None: */ } - /* "aiohttp/_http_parser.pyx":548 + /* "aiohttp/_http_parser.pyx":559 * raise ex * * if self._messages: # <<<<<<<<<<<<<< * messages = self._messages * self._messages = [] */ - __pyx_t_3 = (__pyx_v_self->_messages != Py_None)&&(PyList_GET_SIZE(__pyx_v_self->_messages) != 0); - if (__pyx_t_3) { + __pyx_t_2 = (__pyx_v_self->_messages != Py_None)&&(PyList_GET_SIZE(__pyx_v_self->_messages) != 0); + if (__pyx_t_2) { - /* "aiohttp/_http_parser.pyx":549 + /* "aiohttp/_http_parser.pyx":560 * * if self._messages: * messages = self._messages # <<<<<<<<<<<<<< * self._messages = [] * else: */ - __pyx_t_4 = __pyx_v_self->_messages; - __Pyx_INCREF(__pyx_t_4); - __pyx_v_messages = __pyx_t_4; - __pyx_t_4 = 0; + __pyx_t_5 = __pyx_v_self->_messages; + __Pyx_INCREF(__pyx_t_5); + __pyx_v_messages = __pyx_t_5; + __pyx_t_5 = 0; - /* "aiohttp/_http_parser.pyx":550 + /* "aiohttp/_http_parser.pyx":561 * if self._messages: * messages = self._messages * self._messages = [] # <<<<<<<<<<<<<< * else: * messages = () */ - __pyx_t_4 = PyList_New(0); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 550, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __Pyx_GIVEREF(__pyx_t_4); + __pyx_t_5 = PyList_New(0); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 561, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_GIVEREF(__pyx_t_5); __Pyx_GOTREF(__pyx_v_self->_messages); __Pyx_DECREF(__pyx_v_self->_messages); - __pyx_v_self->_messages = ((PyObject*)__pyx_t_4); - __pyx_t_4 = 0; + __pyx_v_self->_messages = ((PyObject*)__pyx_t_5); + __pyx_t_5 = 0; - /* "aiohttp/_http_parser.pyx":548 + /* "aiohttp/_http_parser.pyx":559 * raise ex * * if self._messages: # <<<<<<<<<<<<<< * messages = self._messages * self._messages = [] */ - goto __pyx_L6; + goto __pyx_L7; } - /* "aiohttp/_http_parser.pyx":552 + /* "aiohttp/_http_parser.pyx":563 * self._messages = [] * else: * messages = () # <<<<<<<<<<<<<< @@ -9612,19 +9899,19 @@ static PyObject *__pyx_pf_7aiohttp_12_http_parser_10HttpParser_6feed_data(struct __Pyx_INCREF(__pyx_empty_tuple); __pyx_v_messages = __pyx_empty_tuple; } - __pyx_L6:; + __pyx_L7:; - /* "aiohttp/_http_parser.pyx":554 + /* "aiohttp/_http_parser.pyx":565 * messages = () * * if self._upgraded: # <<<<<<<<<<<<<< * return messages, True, data[nb:] * else: */ - __pyx_t_3 = (__pyx_v_self->_upgraded != 0); - if (__pyx_t_3) { + __pyx_t_2 = (__pyx_v_self->_upgraded != 0); + if (__pyx_t_2) { - /* "aiohttp/_http_parser.pyx":555 + /* "aiohttp/_http_parser.pyx":566 * * if self._upgraded: * return messages, True, data[nb:] # <<<<<<<<<<<<<< @@ -9632,24 +9919,24 @@ static PyObject *__pyx_pf_7aiohttp_12_http_parser_10HttpParser_6feed_data(struct * return messages, False, b'' */ __Pyx_XDECREF(__pyx_r); - __pyx_t_4 = __Pyx_PyObject_GetSlice(__pyx_v_data, __pyx_v_nb, 0, NULL, NULL, NULL, 1, 0, 1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 555, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __pyx_t_5 = PyTuple_New(3); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 555, __pyx_L1_error) + __pyx_t_5 = __Pyx_PyObject_GetSlice(__pyx_v_data, __pyx_v_nb, 0, NULL, NULL, NULL, 1, 0, 1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 566, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_5); + __pyx_t_4 = PyTuple_New(3); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 566, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); __Pyx_INCREF(__pyx_v_messages); __Pyx_GIVEREF(__pyx_v_messages); - PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_v_messages); + PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_messages); __Pyx_INCREF(Py_True); __Pyx_GIVEREF(Py_True); - PyTuple_SET_ITEM(__pyx_t_5, 1, Py_True); - __Pyx_GIVEREF(__pyx_t_4); - PyTuple_SET_ITEM(__pyx_t_5, 2, __pyx_t_4); - __pyx_t_4 = 0; - __pyx_r = __pyx_t_5; + PyTuple_SET_ITEM(__pyx_t_4, 1, Py_True); + __Pyx_GIVEREF(__pyx_t_5); + PyTuple_SET_ITEM(__pyx_t_4, 2, __pyx_t_5); __pyx_t_5 = 0; + __pyx_r = __pyx_t_4; + __pyx_t_4 = 0; goto __pyx_L0; - /* "aiohttp/_http_parser.pyx":554 + /* "aiohttp/_http_parser.pyx":565 * messages = () * * if self._upgraded: # <<<<<<<<<<<<<< @@ -9658,7 +9945,7 @@ static PyObject *__pyx_pf_7aiohttp_12_http_parser_10HttpParser_6feed_data(struct */ } - /* "aiohttp/_http_parser.pyx":557 + /* "aiohttp/_http_parser.pyx":568 * return messages, True, data[nb:] * else: * return messages, False, b'' # <<<<<<<<<<<<<< @@ -9667,23 +9954,23 @@ static PyObject *__pyx_pf_7aiohttp_12_http_parser_10HttpParser_6feed_data(struct */ /*else*/ { __Pyx_XDECREF(__pyx_r); - __pyx_t_5 = PyTuple_New(3); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 557, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_5); + __pyx_t_4 = PyTuple_New(3); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 568, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); __Pyx_INCREF(__pyx_v_messages); __Pyx_GIVEREF(__pyx_v_messages); - PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_v_messages); + PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_messages); __Pyx_INCREF(Py_False); __Pyx_GIVEREF(Py_False); - PyTuple_SET_ITEM(__pyx_t_5, 1, Py_False); - __Pyx_INCREF(__pyx_kp_b__4); - __Pyx_GIVEREF(__pyx_kp_b__4); - PyTuple_SET_ITEM(__pyx_t_5, 2, __pyx_kp_b__4); - __pyx_r = __pyx_t_5; - __pyx_t_5 = 0; + PyTuple_SET_ITEM(__pyx_t_4, 1, Py_False); + __Pyx_INCREF(__pyx_kp_b__8); + __Pyx_GIVEREF(__pyx_kp_b__8); + PyTuple_SET_ITEM(__pyx_t_4, 2, __pyx_kp_b__8); + __pyx_r = __pyx_t_4; + __pyx_t_4 = 0; goto __pyx_L0; } - /* "aiohttp/_http_parser.pyx":521 + /* "aiohttp/_http_parser.pyx":522 * return self._messages[-1][0] * * def feed_data(self, data): # <<<<<<<<<<<<<< @@ -9699,13 +9986,17 @@ static PyObject *__pyx_pf_7aiohttp_12_http_parser_10HttpParser_6feed_data(struct __pyx_r = NULL; __pyx_L0:; __Pyx_XDECREF(__pyx_v_ex); + __Pyx_XDECREF(__pyx_v_before); + __Pyx_XDECREF(__pyx_v_after_b); + __Pyx_XDECREF(__pyx_v_pointer); __Pyx_XDECREF(__pyx_v_messages); + __Pyx_XDECREF(__pyx_v_data); __Pyx_XGIVEREF(__pyx_r); __Pyx_RefNannyFinishContext(); return __pyx_r; } -/* "aiohttp/_http_parser.pyx":559 +/* "aiohttp/_http_parser.pyx":570 * return messages, False, b'' * * def set_upgraded(self, val): # <<<<<<<<<<<<<< @@ -9735,17 +10026,17 @@ static PyObject *__pyx_pf_7aiohttp_12_http_parser_10HttpParser_8set_upgraded(str int __pyx_clineno = 0; __Pyx_RefNannySetupContext("set_upgraded", 0); - /* "aiohttp/_http_parser.pyx":560 + /* "aiohttp/_http_parser.pyx":571 * * def set_upgraded(self, val): * self._upgraded = val # <<<<<<<<<<<<<< * * */ - __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_v_val); if (unlikely((__pyx_t_1 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 560, __pyx_L1_error) + __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_v_val); if (unlikely((__pyx_t_1 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 571, __pyx_L1_error) __pyx_v_self->_upgraded = __pyx_t_1; - /* "aiohttp/_http_parser.pyx":559 + /* "aiohttp/_http_parser.pyx":570 * return messages, False, b'' * * def set_upgraded(self, val): # <<<<<<<<<<<<<< @@ -9799,7 +10090,7 @@ static PyObject *__pyx_pf_7aiohttp_12_http_parser_10HttpParser_10__reduce_cython * def __setstate_cython__(self, __pyx_state): * raise TypeError("no default __reduce__ due to non-trivial __cinit__") */ - __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__5, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 2, __pyx_L1_error) + __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__9, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 2, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_Raise(__pyx_t_1, 0, 0, 0); __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; @@ -9855,7 +10146,7 @@ static PyObject *__pyx_pf_7aiohttp_12_http_parser_10HttpParser_12__setstate_cyth * def __setstate_cython__(self, __pyx_state): * raise TypeError("no default __reduce__ due to non-trivial __cinit__") # <<<<<<<<<<<<<< */ - __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__6, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 4, __pyx_L1_error) + __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__10, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 4, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_Raise(__pyx_t_1, 0, 0, 0); __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; @@ -9878,12 +10169,12 @@ static PyObject *__pyx_pf_7aiohttp_12_http_parser_10HttpParser_12__setstate_cyth return __pyx_r; } -/* "aiohttp/_http_parser.pyx":565 +/* "aiohttp/_http_parser.pyx":576 * cdef class HttpRequestParser(HttpParser): * - * def __init__(self, protocol, loop, int limit, timer=None, # <<<<<<<<<<<<<< - * size_t max_line_size=8190, size_t max_headers=32768, - * size_t max_field_size=8190, payload_exception=None, + * def __init__( # <<<<<<<<<<<<<< + * self, protocol, loop, int limit, timer=None, + * size_t max_line_size=8190, size_t max_headers=32768, */ /* Python wrapper */ @@ -9899,6 +10190,7 @@ static int __pyx_pw_7aiohttp_12_http_parser_17HttpRequestParser_1__init__(PyObje PyObject *__pyx_v_payload_exception = 0; int __pyx_v_response_with_body; int __pyx_v_read_until_eof; + int __pyx_v_auto_decompress; int __pyx_lineno = 0; const char *__pyx_filename = NULL; int __pyx_clineno = 0; @@ -9906,22 +10198,32 @@ static int __pyx_pw_7aiohttp_12_http_parser_17HttpRequestParser_1__init__(PyObje __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("__init__ (wrapper)", 0); { - static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_protocol,&__pyx_n_s_loop,&__pyx_n_s_limit,&__pyx_n_s_timer,&__pyx_n_s_max_line_size,&__pyx_n_s_max_headers,&__pyx_n_s_max_field_size,&__pyx_n_s_payload_exception,&__pyx_n_s_response_with_body,&__pyx_n_s_read_until_eof,0}; - PyObject* values[10] = {0,0,0,0,0,0,0,0,0,0}; + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_protocol,&__pyx_n_s_loop,&__pyx_n_s_limit,&__pyx_n_s_timer,&__pyx_n_s_max_line_size,&__pyx_n_s_max_headers,&__pyx_n_s_max_field_size,&__pyx_n_s_payload_exception,&__pyx_n_s_response_with_body,&__pyx_n_s_read_until_eof,&__pyx_n_s_auto_decompress,0}; + PyObject* values[11] = {0,0,0,0,0,0,0,0,0,0,0}; + + /* "aiohttp/_http_parser.pyx":577 + * + * def __init__( + * self, protocol, loop, int limit, timer=None, # <<<<<<<<<<<<<< + * size_t max_line_size=8190, size_t max_headers=32768, + * size_t max_field_size=8190, payload_exception=None, + */ values[3] = ((PyObject *)Py_None); - /* "aiohttp/_http_parser.pyx":567 - * def __init__(self, protocol, loop, int limit, timer=None, - * size_t max_line_size=8190, size_t max_headers=32768, - * size_t max_field_size=8190, payload_exception=None, # <<<<<<<<<<<<<< - * bint response_with_body=True, bint read_until_eof=False, - * ): + /* "aiohttp/_http_parser.pyx":579 + * self, protocol, loop, int limit, timer=None, + * size_t max_line_size=8190, size_t max_headers=32768, + * size_t max_field_size=8190, payload_exception=None, # <<<<<<<<<<<<<< + * bint response_with_body=True, bint read_until_eof=False, + * bint auto_decompress=True, */ values[7] = ((PyObject *)Py_None); if (unlikely(__pyx_kwds)) { Py_ssize_t kw_args; const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); switch (pos_args) { + case 11: values[10] = PyTuple_GET_ITEM(__pyx_args, 10); + CYTHON_FALLTHROUGH; case 10: values[9] = PyTuple_GET_ITEM(__pyx_args, 9); CYTHON_FALLTHROUGH; case 9: values[8] = PyTuple_GET_ITEM(__pyx_args, 8); @@ -9954,13 +10256,13 @@ static int __pyx_pw_7aiohttp_12_http_parser_17HttpRequestParser_1__init__(PyObje case 1: if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_loop)) != 0)) kw_args--; else { - __Pyx_RaiseArgtupleInvalid("__init__", 0, 3, 10, 1); __PYX_ERR(0, 565, __pyx_L3_error) + __Pyx_RaiseArgtupleInvalid("__init__", 0, 3, 11, 1); __PYX_ERR(0, 576, __pyx_L3_error) } CYTHON_FALLTHROUGH; case 2: if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_limit)) != 0)) kw_args--; else { - __Pyx_RaiseArgtupleInvalid("__init__", 0, 3, 10, 2); __PYX_ERR(0, 565, __pyx_L3_error) + __Pyx_RaiseArgtupleInvalid("__init__", 0, 3, 11, 2); __PYX_ERR(0, 576, __pyx_L3_error) } CYTHON_FALLTHROUGH; case 3: @@ -10004,12 +10306,20 @@ static int __pyx_pw_7aiohttp_12_http_parser_17HttpRequestParser_1__init__(PyObje PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_read_until_eof); if (value) { values[9] = value; kw_args--; } } + CYTHON_FALLTHROUGH; + case 10: + if (kw_args > 0) { + PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_auto_decompress); + if (value) { values[10] = value; kw_args--; } + } } if (unlikely(kw_args > 0)) { - if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__init__") < 0)) __PYX_ERR(0, 565, __pyx_L3_error) + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__init__") < 0)) __PYX_ERR(0, 576, __pyx_L3_error) } } else { switch (PyTuple_GET_SIZE(__pyx_args)) { + case 11: values[10] = PyTuple_GET_ITEM(__pyx_args, 10); + CYTHON_FALLTHROUGH; case 10: values[9] = PyTuple_GET_ITEM(__pyx_args, 9); CYTHON_FALLTHROUGH; case 9: values[8] = PyTuple_GET_ITEM(__pyx_args, 8); @@ -10033,59 +10343,72 @@ static int __pyx_pw_7aiohttp_12_http_parser_17HttpRequestParser_1__init__(PyObje } __pyx_v_protocol = values[0]; __pyx_v_loop = values[1]; - __pyx_v_limit = __Pyx_PyInt_As_int(values[2]); if (unlikely((__pyx_v_limit == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 565, __pyx_L3_error) + __pyx_v_limit = __Pyx_PyInt_As_int(values[2]); if (unlikely((__pyx_v_limit == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 577, __pyx_L3_error) __pyx_v_timer = values[3]; if (values[4]) { - __pyx_v_max_line_size = __Pyx_PyInt_As_size_t(values[4]); if (unlikely((__pyx_v_max_line_size == (size_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 566, __pyx_L3_error) + __pyx_v_max_line_size = __Pyx_PyInt_As_size_t(values[4]); if (unlikely((__pyx_v_max_line_size == (size_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 578, __pyx_L3_error) } else { __pyx_v_max_line_size = ((size_t)0x1FFE); } if (values[5]) { - __pyx_v_max_headers = __Pyx_PyInt_As_size_t(values[5]); if (unlikely((__pyx_v_max_headers == (size_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 566, __pyx_L3_error) + __pyx_v_max_headers = __Pyx_PyInt_As_size_t(values[5]); if (unlikely((__pyx_v_max_headers == (size_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 578, __pyx_L3_error) } else { __pyx_v_max_headers = ((size_t)0x8000); } if (values[6]) { - __pyx_v_max_field_size = __Pyx_PyInt_As_size_t(values[6]); if (unlikely((__pyx_v_max_field_size == (size_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 567, __pyx_L3_error) + __pyx_v_max_field_size = __Pyx_PyInt_As_size_t(values[6]); if (unlikely((__pyx_v_max_field_size == (size_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 579, __pyx_L3_error) } else { __pyx_v_max_field_size = ((size_t)0x1FFE); } __pyx_v_payload_exception = values[7]; if (values[8]) { - __pyx_v_response_with_body = __Pyx_PyObject_IsTrue(values[8]); if (unlikely((__pyx_v_response_with_body == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 568, __pyx_L3_error) + __pyx_v_response_with_body = __Pyx_PyObject_IsTrue(values[8]); if (unlikely((__pyx_v_response_with_body == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 580, __pyx_L3_error) } else { - /* "aiohttp/_http_parser.pyx":568 - * size_t max_line_size=8190, size_t max_headers=32768, - * size_t max_field_size=8190, payload_exception=None, - * bint response_with_body=True, bint read_until_eof=False, # <<<<<<<<<<<<<< + /* "aiohttp/_http_parser.pyx":580 + * size_t max_line_size=8190, size_t max_headers=32768, + * size_t max_field_size=8190, payload_exception=None, + * bint response_with_body=True, bint read_until_eof=False, # <<<<<<<<<<<<<< + * bint auto_decompress=True, * ): - * self._init(cparser.HTTP_REQUEST, protocol, loop, limit, timer, */ __pyx_v_response_with_body = ((int)1); } if (values[9]) { - __pyx_v_read_until_eof = __Pyx_PyObject_IsTrue(values[9]); if (unlikely((__pyx_v_read_until_eof == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 568, __pyx_L3_error) + __pyx_v_read_until_eof = __Pyx_PyObject_IsTrue(values[9]); if (unlikely((__pyx_v_read_until_eof == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 580, __pyx_L3_error) } else { __pyx_v_read_until_eof = ((int)0); } + if (values[10]) { + __pyx_v_auto_decompress = __Pyx_PyObject_IsTrue(values[10]); if (unlikely((__pyx_v_auto_decompress == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 581, __pyx_L3_error) + } else { + + /* "aiohttp/_http_parser.pyx":581 + * size_t max_field_size=8190, payload_exception=None, + * bint response_with_body=True, bint read_until_eof=False, + * bint auto_decompress=True, # <<<<<<<<<<<<<< + * ): + * self._init(cparser.HTTP_REQUEST, protocol, loop, limit, timer, + */ + __pyx_v_auto_decompress = ((int)1); + } } goto __pyx_L4_argument_unpacking_done; __pyx_L5_argtuple_error:; - __Pyx_RaiseArgtupleInvalid("__init__", 0, 3, 10, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 565, __pyx_L3_error) + __Pyx_RaiseArgtupleInvalid("__init__", 0, 3, 11, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 576, __pyx_L3_error) __pyx_L3_error:; __Pyx_AddTraceback("aiohttp._http_parser.HttpRequestParser.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename); __Pyx_RefNannyFinishContext(); return -1; __pyx_L4_argument_unpacking_done:; - __pyx_r = __pyx_pf_7aiohttp_12_http_parser_17HttpRequestParser___init__(((struct __pyx_obj_7aiohttp_12_http_parser_HttpRequestParser *)__pyx_v_self), __pyx_v_protocol, __pyx_v_loop, __pyx_v_limit, __pyx_v_timer, __pyx_v_max_line_size, __pyx_v_max_headers, __pyx_v_max_field_size, __pyx_v_payload_exception, __pyx_v_response_with_body, __pyx_v_read_until_eof); + __pyx_r = __pyx_pf_7aiohttp_12_http_parser_17HttpRequestParser___init__(((struct __pyx_obj_7aiohttp_12_http_parser_HttpRequestParser *)__pyx_v_self), __pyx_v_protocol, __pyx_v_loop, __pyx_v_limit, __pyx_v_timer, __pyx_v_max_line_size, __pyx_v_max_headers, __pyx_v_max_field_size, __pyx_v_payload_exception, __pyx_v_response_with_body, __pyx_v_read_until_eof, __pyx_v_auto_decompress); - /* "aiohttp/_http_parser.pyx":565 + /* "aiohttp/_http_parser.pyx":576 * cdef class HttpRequestParser(HttpParser): * - * def __init__(self, protocol, loop, int limit, timer=None, # <<<<<<<<<<<<<< - * size_t max_line_size=8190, size_t max_headers=32768, - * size_t max_field_size=8190, payload_exception=None, + * def __init__( # <<<<<<<<<<<<<< + * self, protocol, loop, int limit, timer=None, + * size_t max_line_size=8190, size_t max_headers=32768, */ /* function exit code */ @@ -10093,7 +10416,7 @@ static int __pyx_pw_7aiohttp_12_http_parser_17HttpRequestParser_1__init__(PyObje return __pyx_r; } -static int __pyx_pf_7aiohttp_12_http_parser_17HttpRequestParser___init__(struct __pyx_obj_7aiohttp_12_http_parser_HttpRequestParser *__pyx_v_self, PyObject *__pyx_v_protocol, PyObject *__pyx_v_loop, int __pyx_v_limit, PyObject *__pyx_v_timer, size_t __pyx_v_max_line_size, size_t __pyx_v_max_headers, size_t __pyx_v_max_field_size, PyObject *__pyx_v_payload_exception, int __pyx_v_response_with_body, int __pyx_v_read_until_eof) { +static int __pyx_pf_7aiohttp_12_http_parser_17HttpRequestParser___init__(struct __pyx_obj_7aiohttp_12_http_parser_HttpRequestParser *__pyx_v_self, PyObject *__pyx_v_protocol, PyObject *__pyx_v_loop, int __pyx_v_limit, PyObject *__pyx_v_timer, size_t __pyx_v_max_line_size, size_t __pyx_v_max_headers, size_t __pyx_v_max_field_size, PyObject *__pyx_v_payload_exception, int __pyx_v_response_with_body, int __pyx_v_read_until_eof, int __pyx_v_auto_decompress) { int __pyx_r; __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; @@ -10103,14 +10426,14 @@ static int __pyx_pf_7aiohttp_12_http_parser_17HttpRequestParser___init__(struct int __pyx_clineno = 0; __Pyx_RefNannySetupContext("__init__", 0); - /* "aiohttp/_http_parser.pyx":570 - * bint response_with_body=True, bint read_until_eof=False, + /* "aiohttp/_http_parser.pyx":583 + * bint auto_decompress=True, * ): - * self._init(cparser.HTTP_REQUEST, protocol, loop, limit, timer, # <<<<<<<<<<<<<< - * max_line_size, max_headers, max_field_size, - * payload_exception, response_with_body, read_until_eof) + * self._init(cparser.HTTP_REQUEST, protocol, loop, limit, timer, # <<<<<<<<<<<<<< + * max_line_size, max_headers, max_field_size, + * payload_exception, response_with_body, read_until_eof, */ - __pyx_t_2.__pyx_n = 7; + __pyx_t_2.__pyx_n = 8; __pyx_t_2.timer = __pyx_v_timer; __pyx_t_2.max_line_size = __pyx_v_max_line_size; __pyx_t_2.max_headers = __pyx_v_max_headers; @@ -10118,16 +10441,17 @@ static int __pyx_pf_7aiohttp_12_http_parser_17HttpRequestParser___init__(struct __pyx_t_2.payload_exception = __pyx_v_payload_exception; __pyx_t_2.response_with_body = __pyx_v_response_with_body; __pyx_t_2.read_until_eof = __pyx_v_read_until_eof; - __pyx_t_1 = ((struct __pyx_vtabstruct_7aiohttp_12_http_parser_HttpRequestParser *)__pyx_v_self->__pyx_base.__pyx_vtab)->__pyx_base._init(((struct __pyx_obj_7aiohttp_12_http_parser_HttpParser *)__pyx_v_self), HTTP_REQUEST, __pyx_v_protocol, __pyx_v_loop, __pyx_v_limit, &__pyx_t_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 570, __pyx_L1_error) + __pyx_t_2.auto_decompress = __pyx_v_auto_decompress; + __pyx_t_1 = ((struct __pyx_vtabstruct_7aiohttp_12_http_parser_HttpRequestParser *)__pyx_v_self->__pyx_base.__pyx_vtab)->__pyx_base._init(((struct __pyx_obj_7aiohttp_12_http_parser_HttpParser *)__pyx_v_self), HTTP_REQUEST, __pyx_v_protocol, __pyx_v_loop, __pyx_v_limit, &__pyx_t_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 583, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - /* "aiohttp/_http_parser.pyx":565 + /* "aiohttp/_http_parser.pyx":576 * cdef class HttpRequestParser(HttpParser): * - * def __init__(self, protocol, loop, int limit, timer=None, # <<<<<<<<<<<<<< - * size_t max_line_size=8190, size_t max_headers=32768, - * size_t max_field_size=8190, payload_exception=None, + * def __init__( # <<<<<<<<<<<<<< + * self, protocol, loop, int limit, timer=None, + * size_t max_line_size=8190, size_t max_headers=32768, */ /* function exit code */ @@ -10142,80 +10466,89 @@ static int __pyx_pf_7aiohttp_12_http_parser_17HttpRequestParser___init__(struct return __pyx_r; } -/* "aiohttp/_http_parser.pyx":574 - * payload_exception, response_with_body, read_until_eof) +/* "aiohttp/_http_parser.pyx":588 + * auto_decompress) * * cdef object _on_status_complete(self): # <<<<<<<<<<<<<< - * cdef Py_buffer py_buf - * if not self._buf: + * cdef int idx1, idx2 + * if not self._buf: */ static PyObject *__pyx_f_7aiohttp_12_http_parser_17HttpRequestParser__on_status_complete(struct __pyx_obj_7aiohttp_12_http_parser_HttpRequestParser *__pyx_v_self) { - Py_buffer __pyx_v_py_buf; + int __pyx_v_idx1; + int __pyx_v_idx2; + Py_ssize_t __pyx_v_idx3; + PyObject *__pyx_v_query = NULL; + PyObject *__pyx_v_path = NULL; + PyObject *__pyx_v_fragment = NULL; PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations int __pyx_t_1; int __pyx_t_2; PyObject *__pyx_t_3 = NULL; - PyObject *__pyx_t_4 = NULL; + Py_ssize_t __pyx_t_4; PyObject *__pyx_t_5 = NULL; - int __pyx_t_6; - int __pyx_t_7; - char const *__pyx_t_8; - PyObject *__pyx_t_9 = NULL; - PyObject *__pyx_t_10 = NULL; - PyObject *__pyx_t_11 = NULL; + PyObject *__pyx_t_6 = NULL; + Py_UCS4 __pyx_t_7; + Py_ssize_t __pyx_t_8; + int __pyx_t_9; + int __pyx_t_10; + char const *__pyx_t_11; PyObject *__pyx_t_12 = NULL; PyObject *__pyx_t_13 = NULL; PyObject *__pyx_t_14 = NULL; + PyObject *__pyx_t_15 = NULL; + PyObject *__pyx_t_16 = NULL; + PyObject *__pyx_t_17 = NULL; + int __pyx_t_18; int __pyx_lineno = 0; const char *__pyx_filename = NULL; int __pyx_clineno = 0; __Pyx_RefNannySetupContext("_on_status_complete", 0); - /* "aiohttp/_http_parser.pyx":576 + /* "aiohttp/_http_parser.pyx":590 * cdef object _on_status_complete(self): - * cdef Py_buffer py_buf - * if not self._buf: # <<<<<<<<<<<<<< - * return - * self._path = self._buf.decode('utf-8', 'surrogateescape') + * cdef int idx1, idx2 + * if not self._buf: # <<<<<<<<<<<<<< + * return + * self._path = self._buf.decode('utf-8', 'surrogateescape') */ __pyx_t_1 = (__pyx_v_self->__pyx_base._buf != Py_None)&&(PyByteArray_GET_SIZE(__pyx_v_self->__pyx_base._buf) != 0); __pyx_t_2 = ((!__pyx_t_1) != 0); if (__pyx_t_2) { - /* "aiohttp/_http_parser.pyx":577 - * cdef Py_buffer py_buf - * if not self._buf: - * return # <<<<<<<<<<<<<< - * self._path = self._buf.decode('utf-8', 'surrogateescape') - * if self._cparser.method == 5: # CONNECT + /* "aiohttp/_http_parser.pyx":591 + * cdef int idx1, idx2 + * if not self._buf: + * return # <<<<<<<<<<<<<< + * self._path = self._buf.decode('utf-8', 'surrogateescape') + * try: */ __Pyx_XDECREF(__pyx_r); __pyx_r = Py_None; __Pyx_INCREF(Py_None); goto __pyx_L0; - /* "aiohttp/_http_parser.pyx":576 + /* "aiohttp/_http_parser.pyx":590 * cdef object _on_status_complete(self): - * cdef Py_buffer py_buf - * if not self._buf: # <<<<<<<<<<<<<< - * return - * self._path = self._buf.decode('utf-8', 'surrogateescape') + * cdef int idx1, idx2 + * if not self._buf: # <<<<<<<<<<<<<< + * return + * self._path = self._buf.decode('utf-8', 'surrogateescape') */ } - /* "aiohttp/_http_parser.pyx":578 - * if not self._buf: - * return - * self._path = self._buf.decode('utf-8', 'surrogateescape') # <<<<<<<<<<<<<< - * if self._cparser.method == 5: # CONNECT - * self._url = URL(self._path) + /* "aiohttp/_http_parser.pyx":592 + * if not self._buf: + * return + * self._path = self._buf.decode('utf-8', 'surrogateescape') # <<<<<<<<<<<<<< + * try: + * idx3 = len(self._path) */ if (unlikely(__pyx_v_self->__pyx_base._buf == Py_None)) { PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "decode"); - __PYX_ERR(0, 578, __pyx_L1_error) + __PYX_ERR(0, 592, __pyx_L1_error) } - __pyx_t_3 = __Pyx_decode_bytearray(__pyx_v_self->__pyx_base._buf, 0, PY_SSIZE_T_MAX, NULL, ((char const *)"surrogateescape"), PyUnicode_DecodeUTF8); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 578, __pyx_L1_error) + __pyx_t_3 = __Pyx_decode_bytearray(__pyx_v_self->__pyx_base._buf, 0, PY_SSIZE_T_MAX, NULL, ((char const *)"surrogateescape"), PyUnicode_DecodeUTF8); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 592, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __Pyx_GIVEREF(__pyx_t_3); __Pyx_GOTREF(__pyx_v_self->__pyx_base._path); @@ -10223,174 +10556,548 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_17HttpRequestParser__on_status_ __pyx_v_self->__pyx_base._path = ((PyObject*)__pyx_t_3); __pyx_t_3 = 0; - /* "aiohttp/_http_parser.pyx":579 - * return - * self._path = self._buf.decode('utf-8', 'surrogateescape') - * if self._cparser.method == 5: # CONNECT # <<<<<<<<<<<<<< - * self._url = URL(self._path) - * else: - */ - __pyx_t_2 = ((__pyx_v_self->__pyx_base._cparser->method == 5) != 0); - if (__pyx_t_2) { - - /* "aiohttp/_http_parser.pyx":580 - * self._path = self._buf.decode('utf-8', 'surrogateescape') - * if self._cparser.method == 5: # CONNECT - * self._url = URL(self._path) # <<<<<<<<<<<<<< - * else: - * PyObject_GetBuffer(self._buf, &py_buf, PyBUF_SIMPLE) - */ - __Pyx_INCREF(__pyx_v_7aiohttp_12_http_parser_URL); - __pyx_t_4 = __pyx_v_7aiohttp_12_http_parser_URL; __pyx_t_5 = NULL; - if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) { - __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4); - if (likely(__pyx_t_5)) { - PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4); - __Pyx_INCREF(__pyx_t_5); - __Pyx_INCREF(function); - __Pyx_DECREF_SET(__pyx_t_4, function); - } - } - __pyx_t_3 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_5, __pyx_v_self->__pyx_base._path) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_v_self->__pyx_base._path); - __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; - if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 580, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - __Pyx_GIVEREF(__pyx_t_3); - __Pyx_GOTREF(__pyx_v_self->__pyx_base._url); - __Pyx_DECREF(__pyx_v_self->__pyx_base._url); - __pyx_v_self->__pyx_base._url = __pyx_t_3; - __pyx_t_3 = 0; - - /* "aiohttp/_http_parser.pyx":579 - * return - * self._path = self._buf.decode('utf-8', 'surrogateescape') - * if self._cparser.method == 5: # CONNECT # <<<<<<<<<<<<<< - * self._url = URL(self._path) - * else: + /* "aiohttp/_http_parser.pyx":593 + * return + * self._path = self._buf.decode('utf-8', 'surrogateescape') + * try: # <<<<<<<<<<<<<< + * idx3 = len(self._path) + * if self._cparser.method == cparser.HTTP_CONNECT: */ - goto __pyx_L4; - } + /*try:*/ { - /* "aiohttp/_http_parser.pyx":582 - * self._url = URL(self._path) - * else: - * PyObject_GetBuffer(self._buf, &py_buf, PyBUF_SIMPLE) # <<<<<<<<<<<<<< - * try: - * self._url = _parse_url(py_buf.buf, + /* "aiohttp/_http_parser.pyx":594 + * self._path = self._buf.decode('utf-8', 'surrogateescape') + * try: + * idx3 = len(self._path) # <<<<<<<<<<<<<< + * if self._cparser.method == cparser.HTTP_CONNECT: + * # authority-form, */ - /*else*/ { - __pyx_t_3 = __pyx_v_self->__pyx_base._buf; + __pyx_t_3 = __pyx_v_self->__pyx_base._path; __Pyx_INCREF(__pyx_t_3); - __pyx_t_6 = PyObject_GetBuffer(__pyx_t_3, (&__pyx_v_py_buf), PyBUF_SIMPLE); if (unlikely(__pyx_t_6 == ((int)-1))) __PYX_ERR(0, 582, __pyx_L1_error) + if (unlikely(__pyx_t_3 == Py_None)) { + PyErr_SetString(PyExc_TypeError, "object of type 'NoneType' has no len()"); + __PYX_ERR(0, 594, __pyx_L5_error) + } + __pyx_t_4 = __Pyx_PyUnicode_GET_LENGTH(__pyx_t_3); if (unlikely(__pyx_t_4 == ((Py_ssize_t)-1))) __PYX_ERR(0, 594, __pyx_L5_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_v_idx3 = __pyx_t_4; - /* "aiohttp/_http_parser.pyx":583 - * else: - * PyObject_GetBuffer(self._buf, &py_buf, PyBUF_SIMPLE) - * try: # <<<<<<<<<<<<<< - * self._url = _parse_url(py_buf.buf, - * py_buf.len) + /* "aiohttp/_http_parser.pyx":595 + * try: + * idx3 = len(self._path) + * if self._cparser.method == cparser.HTTP_CONNECT: # <<<<<<<<<<<<<< + * # authority-form, + * # https://datatracker.ietf.org/doc/html/rfc7230#section-5.3.3 */ - /*try:*/ { + __pyx_t_2 = ((__pyx_v_self->__pyx_base._cparser->method == HTTP_CONNECT) != 0); + if (__pyx_t_2) { - /* "aiohttp/_http_parser.pyx":584 - * PyObject_GetBuffer(self._buf, &py_buf, PyBUF_SIMPLE) - * try: - * self._url = _parse_url(py_buf.buf, # <<<<<<<<<<<<<< - * py_buf.len) - * finally: + /* "aiohttp/_http_parser.pyx":598 + * # authority-form, + * # https://datatracker.ietf.org/doc/html/rfc7230#section-5.3.3 + * self._url = URL.build(authority=self._path, encoded=True) # <<<<<<<<<<<<<< + * elif idx3 > 1 and self._path[0] == '/': + * # origin-form, */ - __pyx_t_3 = __pyx_f_7aiohttp_12_http_parser__parse_url(((char *)__pyx_v_py_buf.buf), __pyx_v_py_buf.len); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 584, __pyx_L6_error) + __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_7aiohttp_12_http_parser_URL, __pyx_n_s_build); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 598, __pyx_L5_error) __Pyx_GOTREF(__pyx_t_3); - __Pyx_GIVEREF(__pyx_t_3); + __pyx_t_5 = __Pyx_PyDict_NewPresized(2); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 598, __pyx_L5_error) + __Pyx_GOTREF(__pyx_t_5); + if (PyDict_SetItem(__pyx_t_5, __pyx_n_s_authority, __pyx_v_self->__pyx_base._path) < 0) __PYX_ERR(0, 598, __pyx_L5_error) + if (PyDict_SetItem(__pyx_t_5, __pyx_n_s_encoded, Py_True) < 0) __PYX_ERR(0, 598, __pyx_L5_error) + __pyx_t_6 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_empty_tuple, __pyx_t_5); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 598, __pyx_L5_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_GIVEREF(__pyx_t_6); __Pyx_GOTREF(__pyx_v_self->__pyx_base._url); __Pyx_DECREF(__pyx_v_self->__pyx_base._url); - __pyx_v_self->__pyx_base._url = __pyx_t_3; - __pyx_t_3 = 0; + __pyx_v_self->__pyx_base._url = __pyx_t_6; + __pyx_t_6 = 0; + + /* "aiohttp/_http_parser.pyx":595 + * try: + * idx3 = len(self._path) + * if self._cparser.method == cparser.HTTP_CONNECT: # <<<<<<<<<<<<<< + * # authority-form, + * # https://datatracker.ietf.org/doc/html/rfc7230#section-5.3.3 + */ + goto __pyx_L7; } - /* "aiohttp/_http_parser.pyx":587 - * py_buf.len) - * finally: - * PyBuffer_Release(&py_buf) # <<<<<<<<<<<<<< - * PyByteArray_Resize(self._buf, 0) - * + /* "aiohttp/_http_parser.pyx":599 + * # https://datatracker.ietf.org/doc/html/rfc7230#section-5.3.3 + * self._url = URL.build(authority=self._path, encoded=True) + * elif idx3 > 1 and self._path[0] == '/': # <<<<<<<<<<<<<< + * # origin-form, + * # https://datatracker.ietf.org/doc/html/rfc7230#section-5.3.1 + */ + __pyx_t_1 = ((__pyx_v_idx3 > 1) != 0); + if (__pyx_t_1) { + } else { + __pyx_t_2 = __pyx_t_1; + goto __pyx_L8_bool_binop_done; + } + __pyx_t_7 = __Pyx_GetItemInt_Unicode(__pyx_v_self->__pyx_base._path, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(__pyx_t_7 == (Py_UCS4)-1)) __PYX_ERR(0, 599, __pyx_L5_error) + __pyx_t_1 = ((__pyx_t_7 == 47) != 0); + __pyx_t_2 = __pyx_t_1; + __pyx_L8_bool_binop_done:; + if (__pyx_t_2) { + + /* "aiohttp/_http_parser.pyx":602 + * # origin-form, + * # https://datatracker.ietf.org/doc/html/rfc7230#section-5.3.1 + * idx1 = self._path.find("?") # <<<<<<<<<<<<<< + * if idx1 == -1: + * query = "" */ - /*finally:*/ { - /*normal exit:*/{ - PyBuffer_Release((&__pyx_v_py_buf)); - goto __pyx_L7; + if (unlikely(__pyx_v_self->__pyx_base._path == Py_None)) { + PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "find"); + __PYX_ERR(0, 602, __pyx_L5_error) } - __pyx_L6_error:; - /*exception exit:*/{ - __Pyx_PyThreadState_declare - __Pyx_PyThreadState_assign - __pyx_t_9 = 0; __pyx_t_10 = 0; __pyx_t_11 = 0; __pyx_t_12 = 0; __pyx_t_13 = 0; __pyx_t_14 = 0; - __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; - __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; - __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; - if (PY_MAJOR_VERSION >= 3) __Pyx_ExceptionSwap(&__pyx_t_12, &__pyx_t_13, &__pyx_t_14); - if ((PY_MAJOR_VERSION < 3) || unlikely(__Pyx_GetException(&__pyx_t_9, &__pyx_t_10, &__pyx_t_11) < 0)) __Pyx_ErrFetch(&__pyx_t_9, &__pyx_t_10, &__pyx_t_11); - __Pyx_XGOTREF(__pyx_t_9); - __Pyx_XGOTREF(__pyx_t_10); - __Pyx_XGOTREF(__pyx_t_11); - __Pyx_XGOTREF(__pyx_t_12); - __Pyx_XGOTREF(__pyx_t_13); - __Pyx_XGOTREF(__pyx_t_14); - __pyx_t_6 = __pyx_lineno; __pyx_t_7 = __pyx_clineno; __pyx_t_8 = __pyx_filename; - { - PyBuffer_Release((&__pyx_v_py_buf)); + __pyx_t_4 = PyUnicode_Find(__pyx_v_self->__pyx_base._path, __pyx_kp_u__11, 0, PY_SSIZE_T_MAX, 1); if (unlikely(__pyx_t_4 == ((Py_ssize_t)-2))) __PYX_ERR(0, 602, __pyx_L5_error) + __pyx_v_idx1 = __pyx_t_4; + + /* "aiohttp/_http_parser.pyx":603 + * # https://datatracker.ietf.org/doc/html/rfc7230#section-5.3.1 + * idx1 = self._path.find("?") + * if idx1 == -1: # <<<<<<<<<<<<<< + * query = "" + * idx2 = self._path.find("#") + */ + __pyx_t_2 = ((__pyx_v_idx1 == -1L) != 0); + if (__pyx_t_2) { + + /* "aiohttp/_http_parser.pyx":604 + * idx1 = self._path.find("?") + * if idx1 == -1: + * query = "" # <<<<<<<<<<<<<< + * idx2 = self._path.find("#") + * if idx2 == -1: + */ + __Pyx_INCREF(__pyx_kp_u__8); + __pyx_v_query = __pyx_kp_u__8; + + /* "aiohttp/_http_parser.pyx":605 + * if idx1 == -1: + * query = "" + * idx2 = self._path.find("#") # <<<<<<<<<<<<<< + * if idx2 == -1: + * path = self._path + */ + if (unlikely(__pyx_v_self->__pyx_base._path == Py_None)) { + PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "find"); + __PYX_ERR(0, 605, __pyx_L5_error) } - if (PY_MAJOR_VERSION >= 3) { - __Pyx_XGIVEREF(__pyx_t_12); - __Pyx_XGIVEREF(__pyx_t_13); - __Pyx_XGIVEREF(__pyx_t_14); - __Pyx_ExceptionReset(__pyx_t_12, __pyx_t_13, __pyx_t_14); + __pyx_t_4 = PyUnicode_Find(__pyx_v_self->__pyx_base._path, __pyx_kp_u__12, 0, PY_SSIZE_T_MAX, 1); if (unlikely(__pyx_t_4 == ((Py_ssize_t)-2))) __PYX_ERR(0, 605, __pyx_L5_error) + __pyx_v_idx2 = __pyx_t_4; + + /* "aiohttp/_http_parser.pyx":606 + * query = "" + * idx2 = self._path.find("#") + * if idx2 == -1: # <<<<<<<<<<<<<< + * path = self._path + * fragment = "" + */ + __pyx_t_2 = ((__pyx_v_idx2 == -1L) != 0); + if (__pyx_t_2) { + + /* "aiohttp/_http_parser.pyx":607 + * idx2 = self._path.find("#") + * if idx2 == -1: + * path = self._path # <<<<<<<<<<<<<< + * fragment = "" + * else: + */ + __pyx_t_6 = __pyx_v_self->__pyx_base._path; + __Pyx_INCREF(__pyx_t_6); + __pyx_v_path = ((PyObject*)__pyx_t_6); + __pyx_t_6 = 0; + + /* "aiohttp/_http_parser.pyx":608 + * if idx2 == -1: + * path = self._path + * fragment = "" # <<<<<<<<<<<<<< + * else: + * path = self._path[0: idx2] + */ + __Pyx_INCREF(__pyx_kp_u__8); + __pyx_v_fragment = __pyx_kp_u__8; + + /* "aiohttp/_http_parser.pyx":606 + * query = "" + * idx2 = self._path.find("#") + * if idx2 == -1: # <<<<<<<<<<<<<< + * path = self._path + * fragment = "" + */ + goto __pyx_L11; } - __Pyx_XGIVEREF(__pyx_t_9); - __Pyx_XGIVEREF(__pyx_t_10); - __Pyx_XGIVEREF(__pyx_t_11); - __Pyx_ErrRestore(__pyx_t_9, __pyx_t_10, __pyx_t_11); - __pyx_t_9 = 0; __pyx_t_10 = 0; __pyx_t_11 = 0; __pyx_t_12 = 0; __pyx_t_13 = 0; __pyx_t_14 = 0; - __pyx_lineno = __pyx_t_6; __pyx_clineno = __pyx_t_7; __pyx_filename = __pyx_t_8; - goto __pyx_L1_error; - } - __pyx_L7:; - } - } - __pyx_L4:; - /* "aiohttp/_http_parser.pyx":588 - * finally: - * PyBuffer_Release(&py_buf) - * PyByteArray_Resize(self._buf, 0) # <<<<<<<<<<<<<< - * + /* "aiohttp/_http_parser.pyx":610 + * fragment = "" + * else: + * path = self._path[0: idx2] # <<<<<<<<<<<<<< + * fragment = self._path[idx2+1:] * */ - __pyx_t_3 = __pyx_v_self->__pyx_base._buf; - __Pyx_INCREF(__pyx_t_3); - __pyx_t_7 = PyByteArray_Resize(__pyx_t_3, 0); if (unlikely(__pyx_t_7 == ((int)-1))) __PYX_ERR(0, 588, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + /*else*/ { + if (unlikely(__pyx_v_self->__pyx_base._path == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(0, 610, __pyx_L5_error) + } + __pyx_t_6 = __Pyx_PyUnicode_Substring(__pyx_v_self->__pyx_base._path, 0, __pyx_v_idx2); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 610, __pyx_L5_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_v_path = ((PyObject*)__pyx_t_6); + __pyx_t_6 = 0; - /* "aiohttp/_http_parser.pyx":574 - * payload_exception, response_with_body, read_until_eof) + /* "aiohttp/_http_parser.pyx":611 + * else: + * path = self._path[0: idx2] + * fragment = self._path[idx2+1:] # <<<<<<<<<<<<<< * - * cdef object _on_status_complete(self): # <<<<<<<<<<<<<< - * cdef Py_buffer py_buf - * if not self._buf: + * else: */ + if (unlikely(__pyx_v_self->__pyx_base._path == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(0, 611, __pyx_L5_error) + } + __pyx_t_6 = __Pyx_PyUnicode_Substring(__pyx_v_self->__pyx_base._path, (__pyx_v_idx2 + 1), PY_SSIZE_T_MAX); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 611, __pyx_L5_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_v_fragment = ((PyObject*)__pyx_t_6); + __pyx_t_6 = 0; + } + __pyx_L11:; - /* function exit code */ - __pyx_r = Py_None; __Pyx_INCREF(Py_None); - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_3); - __Pyx_XDECREF(__pyx_t_4); + /* "aiohttp/_http_parser.pyx":603 + * # https://datatracker.ietf.org/doc/html/rfc7230#section-5.3.1 + * idx1 = self._path.find("?") + * if idx1 == -1: # <<<<<<<<<<<<<< + * query = "" + * idx2 = self._path.find("#") + */ + goto __pyx_L10; + } + + /* "aiohttp/_http_parser.pyx":614 + * + * else: + * path = self._path[0:idx1] # <<<<<<<<<<<<<< + * idx1 += 1 + * idx2 = self._path.find("#", idx1+1) + */ + /*else*/ { + if (unlikely(__pyx_v_self->__pyx_base._path == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(0, 614, __pyx_L5_error) + } + __pyx_t_6 = __Pyx_PyUnicode_Substring(__pyx_v_self->__pyx_base._path, 0, __pyx_v_idx1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 614, __pyx_L5_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_v_path = ((PyObject*)__pyx_t_6); + __pyx_t_6 = 0; + + /* "aiohttp/_http_parser.pyx":615 + * else: + * path = self._path[0:idx1] + * idx1 += 1 # <<<<<<<<<<<<<< + * idx2 = self._path.find("#", idx1+1) + * if idx2 == -1: + */ + __pyx_v_idx1 = (__pyx_v_idx1 + 1); + + /* "aiohttp/_http_parser.pyx":616 + * path = self._path[0:idx1] + * idx1 += 1 + * idx2 = self._path.find("#", idx1+1) # <<<<<<<<<<<<<< + * if idx2 == -1: + * query = self._path[idx1:] + */ + if (unlikely(__pyx_v_self->__pyx_base._path == Py_None)) { + PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "find"); + __PYX_ERR(0, 616, __pyx_L5_error) + } + __pyx_t_6 = __Pyx_PyInt_From_long((__pyx_v_idx1 + 1)); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 616, __pyx_L5_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_4 = __Pyx_PyIndex_AsSsize_t(__pyx_t_6); if (unlikely((__pyx_t_4 == (Py_ssize_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 616, __pyx_L5_error) + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __pyx_t_8 = PyUnicode_Find(__pyx_v_self->__pyx_base._path, __pyx_kp_u__12, __pyx_t_4, PY_SSIZE_T_MAX, 1); if (unlikely(__pyx_t_8 == ((Py_ssize_t)-2))) __PYX_ERR(0, 616, __pyx_L5_error) + __pyx_v_idx2 = __pyx_t_8; + + /* "aiohttp/_http_parser.pyx":617 + * idx1 += 1 + * idx2 = self._path.find("#", idx1+1) + * if idx2 == -1: # <<<<<<<<<<<<<< + * query = self._path[idx1:] + * fragment = "" + */ + __pyx_t_2 = ((__pyx_v_idx2 == -1L) != 0); + if (__pyx_t_2) { + + /* "aiohttp/_http_parser.pyx":618 + * idx2 = self._path.find("#", idx1+1) + * if idx2 == -1: + * query = self._path[idx1:] # <<<<<<<<<<<<<< + * fragment = "" + * else: + */ + if (unlikely(__pyx_v_self->__pyx_base._path == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(0, 618, __pyx_L5_error) + } + __pyx_t_6 = __Pyx_PyUnicode_Substring(__pyx_v_self->__pyx_base._path, __pyx_v_idx1, PY_SSIZE_T_MAX); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 618, __pyx_L5_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_v_query = ((PyObject*)__pyx_t_6); + __pyx_t_6 = 0; + + /* "aiohttp/_http_parser.pyx":619 + * if idx2 == -1: + * query = self._path[idx1:] + * fragment = "" # <<<<<<<<<<<<<< + * else: + * query = self._path[idx1: idx2] + */ + __Pyx_INCREF(__pyx_kp_u__8); + __pyx_v_fragment = __pyx_kp_u__8; + + /* "aiohttp/_http_parser.pyx":617 + * idx1 += 1 + * idx2 = self._path.find("#", idx1+1) + * if idx2 == -1: # <<<<<<<<<<<<<< + * query = self._path[idx1:] + * fragment = "" + */ + goto __pyx_L12; + } + + /* "aiohttp/_http_parser.pyx":621 + * fragment = "" + * else: + * query = self._path[idx1: idx2] # <<<<<<<<<<<<<< + * fragment = self._path[idx2+1:] + * + */ + /*else*/ { + if (unlikely(__pyx_v_self->__pyx_base._path == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(0, 621, __pyx_L5_error) + } + __pyx_t_6 = __Pyx_PyUnicode_Substring(__pyx_v_self->__pyx_base._path, __pyx_v_idx1, __pyx_v_idx2); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 621, __pyx_L5_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_v_query = ((PyObject*)__pyx_t_6); + __pyx_t_6 = 0; + + /* "aiohttp/_http_parser.pyx":622 + * else: + * query = self._path[idx1: idx2] + * fragment = self._path[idx2+1:] # <<<<<<<<<<<<<< + * + * self._url = URL.build( + */ + if (unlikely(__pyx_v_self->__pyx_base._path == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(0, 622, __pyx_L5_error) + } + __pyx_t_6 = __Pyx_PyUnicode_Substring(__pyx_v_self->__pyx_base._path, (__pyx_v_idx2 + 1), PY_SSIZE_T_MAX); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 622, __pyx_L5_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_v_fragment = ((PyObject*)__pyx_t_6); + __pyx_t_6 = 0; + } + __pyx_L12:; + } + __pyx_L10:; + + /* "aiohttp/_http_parser.pyx":624 + * fragment = self._path[idx2+1:] + * + * self._url = URL.build( # <<<<<<<<<<<<<< + * path=path, + * query_string=query, + */ + __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_v_7aiohttp_12_http_parser_URL, __pyx_n_s_build); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 624, __pyx_L5_error) + __Pyx_GOTREF(__pyx_t_6); + + /* "aiohttp/_http_parser.pyx":625 + * + * self._url = URL.build( + * path=path, # <<<<<<<<<<<<<< + * query_string=query, + * fragment=fragment, + */ + __pyx_t_5 = __Pyx_PyDict_NewPresized(4); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 625, __pyx_L5_error) + __Pyx_GOTREF(__pyx_t_5); + if (PyDict_SetItem(__pyx_t_5, __pyx_n_s_path, __pyx_v_path) < 0) __PYX_ERR(0, 625, __pyx_L5_error) + + /* "aiohttp/_http_parser.pyx":626 + * self._url = URL.build( + * path=path, + * query_string=query, # <<<<<<<<<<<<<< + * fragment=fragment, + * encoded=True, + */ + if (PyDict_SetItem(__pyx_t_5, __pyx_n_s_query_string, __pyx_v_query) < 0) __PYX_ERR(0, 625, __pyx_L5_error) + + /* "aiohttp/_http_parser.pyx":627 + * path=path, + * query_string=query, + * fragment=fragment, # <<<<<<<<<<<<<< + * encoded=True, + * ) + */ + if (PyDict_SetItem(__pyx_t_5, __pyx_n_s_fragment, __pyx_v_fragment) < 0) __PYX_ERR(0, 625, __pyx_L5_error) + + /* "aiohttp/_http_parser.pyx":628 + * query_string=query, + * fragment=fragment, + * encoded=True, # <<<<<<<<<<<<<< + * ) + * else: + */ + if (PyDict_SetItem(__pyx_t_5, __pyx_n_s_encoded, Py_True) < 0) __PYX_ERR(0, 625, __pyx_L5_error) + + /* "aiohttp/_http_parser.pyx":624 + * fragment = self._path[idx2+1:] + * + * self._url = URL.build( # <<<<<<<<<<<<<< + * path=path, + * query_string=query, + */ + __pyx_t_3 = __Pyx_PyObject_Call(__pyx_t_6, __pyx_empty_tuple, __pyx_t_5); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 624, __pyx_L5_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_GIVEREF(__pyx_t_3); + __Pyx_GOTREF(__pyx_v_self->__pyx_base._url); + __Pyx_DECREF(__pyx_v_self->__pyx_base._url); + __pyx_v_self->__pyx_base._url = __pyx_t_3; + __pyx_t_3 = 0; + + /* "aiohttp/_http_parser.pyx":599 + * # https://datatracker.ietf.org/doc/html/rfc7230#section-5.3.3 + * self._url = URL.build(authority=self._path, encoded=True) + * elif idx3 > 1 and self._path[0] == '/': # <<<<<<<<<<<<<< + * # origin-form, + * # https://datatracker.ietf.org/doc/html/rfc7230#section-5.3.1 + */ + goto __pyx_L7; + } + + /* "aiohttp/_http_parser.pyx":633 + * # absolute-form for proxy maybe, + * # https://datatracker.ietf.org/doc/html/rfc7230#section-5.3.2 + * self._url = URL(self._path, encoded=True) # <<<<<<<<<<<<<< + * finally: + * PyByteArray_Resize(self._buf, 0) + */ + /*else*/ { + __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 633, __pyx_L5_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_INCREF(__pyx_v_self->__pyx_base._path); + __Pyx_GIVEREF(__pyx_v_self->__pyx_base._path); + PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_self->__pyx_base._path); + __pyx_t_5 = __Pyx_PyDict_NewPresized(1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 633, __pyx_L5_error) + __Pyx_GOTREF(__pyx_t_5); + if (PyDict_SetItem(__pyx_t_5, __pyx_n_s_encoded, Py_True) < 0) __PYX_ERR(0, 633, __pyx_L5_error) + __pyx_t_6 = __Pyx_PyObject_Call(__pyx_v_7aiohttp_12_http_parser_URL, __pyx_t_3, __pyx_t_5); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 633, __pyx_L5_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_GIVEREF(__pyx_t_6); + __Pyx_GOTREF(__pyx_v_self->__pyx_base._url); + __Pyx_DECREF(__pyx_v_self->__pyx_base._url); + __pyx_v_self->__pyx_base._url = __pyx_t_6; + __pyx_t_6 = 0; + } + __pyx_L7:; + } + + /* "aiohttp/_http_parser.pyx":635 + * self._url = URL(self._path, encoded=True) + * finally: + * PyByteArray_Resize(self._buf, 0) # <<<<<<<<<<<<<< + * + * + */ + /*finally:*/ { + /*normal exit:*/{ + __pyx_t_6 = __pyx_v_self->__pyx_base._buf; + __Pyx_INCREF(__pyx_t_6); + __pyx_t_9 = PyByteArray_Resize(__pyx_t_6, 0); if (unlikely(__pyx_t_9 == ((int)-1))) __PYX_ERR(0, 635, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + goto __pyx_L6; + } + __pyx_L5_error:; + /*exception exit:*/{ + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __pyx_t_12 = 0; __pyx_t_13 = 0; __pyx_t_14 = 0; __pyx_t_15 = 0; __pyx_t_16 = 0; __pyx_t_17 = 0; + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + if (PY_MAJOR_VERSION >= 3) __Pyx_ExceptionSwap(&__pyx_t_15, &__pyx_t_16, &__pyx_t_17); + if ((PY_MAJOR_VERSION < 3) || unlikely(__Pyx_GetException(&__pyx_t_12, &__pyx_t_13, &__pyx_t_14) < 0)) __Pyx_ErrFetch(&__pyx_t_12, &__pyx_t_13, &__pyx_t_14); + __Pyx_XGOTREF(__pyx_t_12); + __Pyx_XGOTREF(__pyx_t_13); + __Pyx_XGOTREF(__pyx_t_14); + __Pyx_XGOTREF(__pyx_t_15); + __Pyx_XGOTREF(__pyx_t_16); + __Pyx_XGOTREF(__pyx_t_17); + __pyx_t_9 = __pyx_lineno; __pyx_t_10 = __pyx_clineno; __pyx_t_11 = __pyx_filename; + { + __pyx_t_6 = __pyx_v_self->__pyx_base._buf; + __Pyx_INCREF(__pyx_t_6); + __pyx_t_18 = PyByteArray_Resize(__pyx_t_6, 0); if (unlikely(__pyx_t_18 == ((int)-1))) __PYX_ERR(0, 635, __pyx_L14_error) + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + } + if (PY_MAJOR_VERSION >= 3) { + __Pyx_XGIVEREF(__pyx_t_15); + __Pyx_XGIVEREF(__pyx_t_16); + __Pyx_XGIVEREF(__pyx_t_17); + __Pyx_ExceptionReset(__pyx_t_15, __pyx_t_16, __pyx_t_17); + } + __Pyx_XGIVEREF(__pyx_t_12); + __Pyx_XGIVEREF(__pyx_t_13); + __Pyx_XGIVEREF(__pyx_t_14); + __Pyx_ErrRestore(__pyx_t_12, __pyx_t_13, __pyx_t_14); + __pyx_t_12 = 0; __pyx_t_13 = 0; __pyx_t_14 = 0; __pyx_t_15 = 0; __pyx_t_16 = 0; __pyx_t_17 = 0; + __pyx_lineno = __pyx_t_9; __pyx_clineno = __pyx_t_10; __pyx_filename = __pyx_t_11; + goto __pyx_L1_error; + __pyx_L14_error:; + if (PY_MAJOR_VERSION >= 3) { + __Pyx_XGIVEREF(__pyx_t_15); + __Pyx_XGIVEREF(__pyx_t_16); + __Pyx_XGIVEREF(__pyx_t_17); + __Pyx_ExceptionReset(__pyx_t_15, __pyx_t_16, __pyx_t_17); + } + __Pyx_XDECREF(__pyx_t_12); __pyx_t_12 = 0; + __Pyx_XDECREF(__pyx_t_13); __pyx_t_13 = 0; + __Pyx_XDECREF(__pyx_t_14); __pyx_t_14 = 0; + __pyx_t_15 = 0; __pyx_t_16 = 0; __pyx_t_17 = 0; + goto __pyx_L1_error; + } + __pyx_L6:; + } + + /* "aiohttp/_http_parser.pyx":588 + * auto_decompress) + * + * cdef object _on_status_complete(self): # <<<<<<<<<<<<<< + * cdef int idx1, idx2 + * if not self._buf: + */ + + /* function exit code */ + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_3); __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); __Pyx_AddTraceback("aiohttp._http_parser.HttpRequestParser._on_status_complete", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = 0; __pyx_L0:; + __Pyx_XDECREF(__pyx_v_query); + __Pyx_XDECREF(__pyx_v_path); + __Pyx_XDECREF(__pyx_v_fragment); __Pyx_XGIVEREF(__pyx_r); __Pyx_RefNannyFinishContext(); return __pyx_r; @@ -10430,7 +11137,7 @@ static PyObject *__pyx_pf_7aiohttp_12_http_parser_17HttpRequestParser_2__reduce_ * def __setstate_cython__(self, __pyx_state): * raise TypeError("no default __reduce__ due to non-trivial __cinit__") */ - __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__7, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 2, __pyx_L1_error) + __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__13, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 2, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_Raise(__pyx_t_1, 0, 0, 0); __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; @@ -10486,7 +11193,7 @@ static PyObject *__pyx_pf_7aiohttp_12_http_parser_17HttpRequestParser_4__setstat * def __setstate_cython__(self, __pyx_state): * raise TypeError("no default __reduce__ due to non-trivial __cinit__") # <<<<<<<<<<<<<< */ - __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__8, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 4, __pyx_L1_error) + __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__14, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 4, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_Raise(__pyx_t_1, 0, 0, 0); __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; @@ -10509,12 +11216,12 @@ static PyObject *__pyx_pf_7aiohttp_12_http_parser_17HttpRequestParser_4__setstat return __pyx_r; } -/* "aiohttp/_http_parser.pyx":593 +/* "aiohttp/_http_parser.pyx":640 * cdef class HttpResponseParser(HttpParser): * - * def __init__(self, protocol, loop, int limit, timer=None, # <<<<<<<<<<<<<< - * size_t max_line_size=8190, size_t max_headers=32768, - * size_t max_field_size=8190, payload_exception=None, + * def __init__( # <<<<<<<<<<<<<< + * self, protocol, loop, int limit, timer=None, + * size_t max_line_size=8190, size_t max_headers=32768, */ /* Python wrapper */ @@ -10540,14 +11247,22 @@ static int __pyx_pw_7aiohttp_12_http_parser_18HttpResponseParser_1__init__(PyObj { static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_protocol,&__pyx_n_s_loop,&__pyx_n_s_limit,&__pyx_n_s_timer,&__pyx_n_s_max_line_size,&__pyx_n_s_max_headers,&__pyx_n_s_max_field_size,&__pyx_n_s_payload_exception,&__pyx_n_s_response_with_body,&__pyx_n_s_read_until_eof,&__pyx_n_s_auto_decompress,0}; PyObject* values[11] = {0,0,0,0,0,0,0,0,0,0,0}; + + /* "aiohttp/_http_parser.pyx":641 + * + * def __init__( + * self, protocol, loop, int limit, timer=None, # <<<<<<<<<<<<<< + * size_t max_line_size=8190, size_t max_headers=32768, + * size_t max_field_size=8190, payload_exception=None, + */ values[3] = ((PyObject *)Py_None); - /* "aiohttp/_http_parser.pyx":595 - * def __init__(self, protocol, loop, int limit, timer=None, - * size_t max_line_size=8190, size_t max_headers=32768, - * size_t max_field_size=8190, payload_exception=None, # <<<<<<<<<<<<<< - * bint response_with_body=True, bint read_until_eof=False, - * bint auto_decompress=True + /* "aiohttp/_http_parser.pyx":643 + * self, protocol, loop, int limit, timer=None, + * size_t max_line_size=8190, size_t max_headers=32768, + * size_t max_field_size=8190, payload_exception=None, # <<<<<<<<<<<<<< + * bint response_with_body=True, bint read_until_eof=False, + * bint auto_decompress=True */ values[7] = ((PyObject *)Py_None); if (unlikely(__pyx_kwds)) { @@ -10588,13 +11303,13 @@ static int __pyx_pw_7aiohttp_12_http_parser_18HttpResponseParser_1__init__(PyObj case 1: if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_loop)) != 0)) kw_args--; else { - __Pyx_RaiseArgtupleInvalid("__init__", 0, 3, 11, 1); __PYX_ERR(0, 593, __pyx_L3_error) + __Pyx_RaiseArgtupleInvalid("__init__", 0, 3, 11, 1); __PYX_ERR(0, 640, __pyx_L3_error) } CYTHON_FALLTHROUGH; case 2: if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_limit)) != 0)) kw_args--; else { - __Pyx_RaiseArgtupleInvalid("__init__", 0, 3, 11, 2); __PYX_ERR(0, 593, __pyx_L3_error) + __Pyx_RaiseArgtupleInvalid("__init__", 0, 3, 11, 2); __PYX_ERR(0, 640, __pyx_L3_error) } CYTHON_FALLTHROUGH; case 3: @@ -10646,7 +11361,7 @@ static int __pyx_pw_7aiohttp_12_http_parser_18HttpResponseParser_1__init__(PyObj } } if (unlikely(kw_args > 0)) { - if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__init__") < 0)) __PYX_ERR(0, 593, __pyx_L3_error) + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__init__") < 0)) __PYX_ERR(0, 640, __pyx_L3_error) } } else { switch (PyTuple_GET_SIZE(__pyx_args)) { @@ -10675,50 +11390,50 @@ static int __pyx_pw_7aiohttp_12_http_parser_18HttpResponseParser_1__init__(PyObj } __pyx_v_protocol = values[0]; __pyx_v_loop = values[1]; - __pyx_v_limit = __Pyx_PyInt_As_int(values[2]); if (unlikely((__pyx_v_limit == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 593, __pyx_L3_error) + __pyx_v_limit = __Pyx_PyInt_As_int(values[2]); if (unlikely((__pyx_v_limit == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 641, __pyx_L3_error) __pyx_v_timer = values[3]; if (values[4]) { - __pyx_v_max_line_size = __Pyx_PyInt_As_size_t(values[4]); if (unlikely((__pyx_v_max_line_size == (size_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 594, __pyx_L3_error) + __pyx_v_max_line_size = __Pyx_PyInt_As_size_t(values[4]); if (unlikely((__pyx_v_max_line_size == (size_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 642, __pyx_L3_error) } else { __pyx_v_max_line_size = ((size_t)0x1FFE); } if (values[5]) { - __pyx_v_max_headers = __Pyx_PyInt_As_size_t(values[5]); if (unlikely((__pyx_v_max_headers == (size_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 594, __pyx_L3_error) + __pyx_v_max_headers = __Pyx_PyInt_As_size_t(values[5]); if (unlikely((__pyx_v_max_headers == (size_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 642, __pyx_L3_error) } else { __pyx_v_max_headers = ((size_t)0x8000); } if (values[6]) { - __pyx_v_max_field_size = __Pyx_PyInt_As_size_t(values[6]); if (unlikely((__pyx_v_max_field_size == (size_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 595, __pyx_L3_error) + __pyx_v_max_field_size = __Pyx_PyInt_As_size_t(values[6]); if (unlikely((__pyx_v_max_field_size == (size_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 643, __pyx_L3_error) } else { __pyx_v_max_field_size = ((size_t)0x1FFE); } __pyx_v_payload_exception = values[7]; if (values[8]) { - __pyx_v_response_with_body = __Pyx_PyObject_IsTrue(values[8]); if (unlikely((__pyx_v_response_with_body == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 596, __pyx_L3_error) + __pyx_v_response_with_body = __Pyx_PyObject_IsTrue(values[8]); if (unlikely((__pyx_v_response_with_body == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 644, __pyx_L3_error) } else { - /* "aiohttp/_http_parser.pyx":596 - * size_t max_line_size=8190, size_t max_headers=32768, - * size_t max_field_size=8190, payload_exception=None, - * bint response_with_body=True, bint read_until_eof=False, # <<<<<<<<<<<<<< - * bint auto_decompress=True + /* "aiohttp/_http_parser.pyx":644 + * size_t max_line_size=8190, size_t max_headers=32768, + * size_t max_field_size=8190, payload_exception=None, + * bint response_with_body=True, bint read_until_eof=False, # <<<<<<<<<<<<<< + * bint auto_decompress=True * ): */ __pyx_v_response_with_body = ((int)1); } if (values[9]) { - __pyx_v_read_until_eof = __Pyx_PyObject_IsTrue(values[9]); if (unlikely((__pyx_v_read_until_eof == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 596, __pyx_L3_error) + __pyx_v_read_until_eof = __Pyx_PyObject_IsTrue(values[9]); if (unlikely((__pyx_v_read_until_eof == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 644, __pyx_L3_error) } else { __pyx_v_read_until_eof = ((int)0); } if (values[10]) { - __pyx_v_auto_decompress = __Pyx_PyObject_IsTrue(values[10]); if (unlikely((__pyx_v_auto_decompress == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 597, __pyx_L3_error) + __pyx_v_auto_decompress = __Pyx_PyObject_IsTrue(values[10]); if (unlikely((__pyx_v_auto_decompress == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 645, __pyx_L3_error) } else { - /* "aiohttp/_http_parser.pyx":597 - * size_t max_field_size=8190, payload_exception=None, - * bint response_with_body=True, bint read_until_eof=False, - * bint auto_decompress=True # <<<<<<<<<<<<<< + /* "aiohttp/_http_parser.pyx":645 + * size_t max_field_size=8190, payload_exception=None, + * bint response_with_body=True, bint read_until_eof=False, + * bint auto_decompress=True # <<<<<<<<<<<<<< * ): * self._init(cparser.HTTP_RESPONSE, protocol, loop, limit, timer, */ @@ -10727,7 +11442,7 @@ static int __pyx_pw_7aiohttp_12_http_parser_18HttpResponseParser_1__init__(PyObj } goto __pyx_L4_argument_unpacking_done; __pyx_L5_argtuple_error:; - __Pyx_RaiseArgtupleInvalid("__init__", 0, 3, 11, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 593, __pyx_L3_error) + __Pyx_RaiseArgtupleInvalid("__init__", 0, 3, 11, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 640, __pyx_L3_error) __pyx_L3_error:; __Pyx_AddTraceback("aiohttp._http_parser.HttpResponseParser.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename); __Pyx_RefNannyFinishContext(); @@ -10735,12 +11450,12 @@ static int __pyx_pw_7aiohttp_12_http_parser_18HttpResponseParser_1__init__(PyObj __pyx_L4_argument_unpacking_done:; __pyx_r = __pyx_pf_7aiohttp_12_http_parser_18HttpResponseParser___init__(((struct __pyx_obj_7aiohttp_12_http_parser_HttpResponseParser *)__pyx_v_self), __pyx_v_protocol, __pyx_v_loop, __pyx_v_limit, __pyx_v_timer, __pyx_v_max_line_size, __pyx_v_max_headers, __pyx_v_max_field_size, __pyx_v_payload_exception, __pyx_v_response_with_body, __pyx_v_read_until_eof, __pyx_v_auto_decompress); - /* "aiohttp/_http_parser.pyx":593 + /* "aiohttp/_http_parser.pyx":640 * cdef class HttpResponseParser(HttpParser): * - * def __init__(self, protocol, loop, int limit, timer=None, # <<<<<<<<<<<<<< - * size_t max_line_size=8190, size_t max_headers=32768, - * size_t max_field_size=8190, payload_exception=None, + * def __init__( # <<<<<<<<<<<<<< + * self, protocol, loop, int limit, timer=None, + * size_t max_line_size=8190, size_t max_headers=32768, */ /* function exit code */ @@ -10753,13 +11468,15 @@ static int __pyx_pf_7aiohttp_12_http_parser_18HttpResponseParser___init__(struct __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; struct __pyx_opt_args_7aiohttp_12_http_parser_10HttpParser__init __pyx_t_2; + int __pyx_t_3; + int __pyx_t_4; int __pyx_lineno = 0; const char *__pyx_filename = NULL; int __pyx_clineno = 0; __Pyx_RefNannySetupContext("__init__", 0); - /* "aiohttp/_http_parser.pyx":599 - * bint auto_decompress=True + /* "aiohttp/_http_parser.pyx":647 + * bint auto_decompress=True * ): * self._init(cparser.HTTP_RESPONSE, protocol, loop, limit, timer, # <<<<<<<<<<<<<< * max_line_size, max_headers, max_field_size, @@ -10774,16 +11491,66 @@ static int __pyx_pf_7aiohttp_12_http_parser_18HttpResponseParser___init__(struct __pyx_t_2.response_with_body = __pyx_v_response_with_body; __pyx_t_2.read_until_eof = __pyx_v_read_until_eof; __pyx_t_2.auto_decompress = __pyx_v_auto_decompress; - __pyx_t_1 = ((struct __pyx_vtabstruct_7aiohttp_12_http_parser_HttpResponseParser *)__pyx_v_self->__pyx_base.__pyx_vtab)->__pyx_base._init(((struct __pyx_obj_7aiohttp_12_http_parser_HttpParser *)__pyx_v_self), HTTP_RESPONSE, __pyx_v_protocol, __pyx_v_loop, __pyx_v_limit, &__pyx_t_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 599, __pyx_L1_error) + __pyx_t_1 = ((struct __pyx_vtabstruct_7aiohttp_12_http_parser_HttpResponseParser *)__pyx_v_self->__pyx_base.__pyx_vtab)->__pyx_base._init(((struct __pyx_obj_7aiohttp_12_http_parser_HttpParser *)__pyx_v_self), HTTP_RESPONSE, __pyx_v_protocol, __pyx_v_loop, __pyx_v_limit, &__pyx_t_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 647, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - /* "aiohttp/_http_parser.pyx":593 + /* "aiohttp/_http_parser.pyx":652 + * auto_decompress) + * # Use strict parsing on dev mode, so users are warned about broken servers. + * if not DEBUG: # <<<<<<<<<<<<<< + * cparser.llhttp_set_lenient_headers(self._cparser, 1) + * cparser.llhttp_set_lenient_optional_cr_before_lf(self._cparser, 1) + */ + __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_DEBUG); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 652, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_3 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_3 < 0)) __PYX_ERR(0, 652, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_4 = ((!__pyx_t_3) != 0); + if (__pyx_t_4) { + + /* "aiohttp/_http_parser.pyx":653 + * # Use strict parsing on dev mode, so users are warned about broken servers. + * if not DEBUG: + * cparser.llhttp_set_lenient_headers(self._cparser, 1) # <<<<<<<<<<<<<< + * cparser.llhttp_set_lenient_optional_cr_before_lf(self._cparser, 1) + * cparser.llhttp_set_lenient_spaces_after_chunk_size(self._cparser, 1) + */ + llhttp_set_lenient_headers(__pyx_v_self->__pyx_base._cparser, 1); + + /* "aiohttp/_http_parser.pyx":654 + * if not DEBUG: + * cparser.llhttp_set_lenient_headers(self._cparser, 1) + * cparser.llhttp_set_lenient_optional_cr_before_lf(self._cparser, 1) # <<<<<<<<<<<<<< + * cparser.llhttp_set_lenient_spaces_after_chunk_size(self._cparser, 1) + * + */ + llhttp_set_lenient_optional_cr_before_lf(__pyx_v_self->__pyx_base._cparser, 1); + + /* "aiohttp/_http_parser.pyx":655 + * cparser.llhttp_set_lenient_headers(self._cparser, 1) + * cparser.llhttp_set_lenient_optional_cr_before_lf(self._cparser, 1) + * cparser.llhttp_set_lenient_spaces_after_chunk_size(self._cparser, 1) # <<<<<<<<<<<<<< + * + * cdef object _on_status_complete(self): + */ + llhttp_set_lenient_spaces_after_chunk_size(__pyx_v_self->__pyx_base._cparser, 1); + + /* "aiohttp/_http_parser.pyx":652 + * auto_decompress) + * # Use strict parsing on dev mode, so users are warned about broken servers. + * if not DEBUG: # <<<<<<<<<<<<<< + * cparser.llhttp_set_lenient_headers(self._cparser, 1) + * cparser.llhttp_set_lenient_optional_cr_before_lf(self._cparser, 1) + */ + } + + /* "aiohttp/_http_parser.pyx":640 * cdef class HttpResponseParser(HttpParser): * - * def __init__(self, protocol, loop, int limit, timer=None, # <<<<<<<<<<<<<< - * size_t max_line_size=8190, size_t max_headers=32768, - * size_t max_field_size=8190, payload_exception=None, + * def __init__( # <<<<<<<<<<<<<< + * self, protocol, loop, int limit, timer=None, + * size_t max_line_size=8190, size_t max_headers=32768, */ /* function exit code */ @@ -10798,8 +11565,8 @@ static int __pyx_pf_7aiohttp_12_http_parser_18HttpResponseParser___init__(struct return __pyx_r; } -/* "aiohttp/_http_parser.pyx":604 - * auto_decompress) +/* "aiohttp/_http_parser.pyx":657 + * cparser.llhttp_set_lenient_spaces_after_chunk_size(self._cparser, 1) * * cdef object _on_status_complete(self): # <<<<<<<<<<<<<< * if self._buf: @@ -10817,7 +11584,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_18HttpResponseParser__on_status int __pyx_clineno = 0; __Pyx_RefNannySetupContext("_on_status_complete", 0); - /* "aiohttp/_http_parser.pyx":605 + /* "aiohttp/_http_parser.pyx":658 * * cdef object _on_status_complete(self): * if self._buf: # <<<<<<<<<<<<<< @@ -10827,7 +11594,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_18HttpResponseParser__on_status __pyx_t_1 = (__pyx_v_self->__pyx_base._buf != Py_None)&&(PyByteArray_GET_SIZE(__pyx_v_self->__pyx_base._buf) != 0); if (__pyx_t_1) { - /* "aiohttp/_http_parser.pyx":606 + /* "aiohttp/_http_parser.pyx":659 * cdef object _on_status_complete(self): * if self._buf: * self._reason = self._buf.decode('utf-8', 'surrogateescape') # <<<<<<<<<<<<<< @@ -10836,9 +11603,9 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_18HttpResponseParser__on_status */ if (unlikely(__pyx_v_self->__pyx_base._buf == Py_None)) { PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "decode"); - __PYX_ERR(0, 606, __pyx_L1_error) + __PYX_ERR(0, 659, __pyx_L1_error) } - __pyx_t_2 = __Pyx_decode_bytearray(__pyx_v_self->__pyx_base._buf, 0, PY_SSIZE_T_MAX, NULL, ((char const *)"surrogateescape"), PyUnicode_DecodeUTF8); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 606, __pyx_L1_error) + __pyx_t_2 = __Pyx_decode_bytearray(__pyx_v_self->__pyx_base._buf, 0, PY_SSIZE_T_MAX, NULL, ((char const *)"surrogateescape"), PyUnicode_DecodeUTF8); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 659, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); __Pyx_GIVEREF(__pyx_t_2); __Pyx_GOTREF(__pyx_v_self->__pyx_base._reason); @@ -10846,7 +11613,7 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_18HttpResponseParser__on_status __pyx_v_self->__pyx_base._reason = ((PyObject*)__pyx_t_2); __pyx_t_2 = 0; - /* "aiohttp/_http_parser.pyx":607 + /* "aiohttp/_http_parser.pyx":660 * if self._buf: * self._reason = self._buf.decode('utf-8', 'surrogateescape') * PyByteArray_Resize(self._buf, 0) # <<<<<<<<<<<<<< @@ -10855,10 +11622,10 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_18HttpResponseParser__on_status */ __pyx_t_2 = __pyx_v_self->__pyx_base._buf; __Pyx_INCREF(__pyx_t_2); - __pyx_t_3 = PyByteArray_Resize(__pyx_t_2, 0); if (unlikely(__pyx_t_3 == ((int)-1))) __PYX_ERR(0, 607, __pyx_L1_error) + __pyx_t_3 = PyByteArray_Resize(__pyx_t_2, 0); if (unlikely(__pyx_t_3 == ((int)-1))) __PYX_ERR(0, 660, __pyx_L1_error) __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - /* "aiohttp/_http_parser.pyx":605 + /* "aiohttp/_http_parser.pyx":658 * * cdef object _on_status_complete(self): * if self._buf: # <<<<<<<<<<<<<< @@ -10868,23 +11635,23 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_18HttpResponseParser__on_status goto __pyx_L3; } - /* "aiohttp/_http_parser.pyx":609 + /* "aiohttp/_http_parser.pyx":662 * PyByteArray_Resize(self._buf, 0) * else: * self._reason = self._reason or '' # <<<<<<<<<<<<<< * - * cdef int cb_on_message_begin(cparser.http_parser* parser) except -1: + * cdef int cb_on_message_begin(cparser.llhttp_t* parser) except -1: */ /*else*/ { - __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_v_self->__pyx_base._reason); if (unlikely(__pyx_t_1 < 0)) __PYX_ERR(0, 609, __pyx_L1_error) + __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_v_self->__pyx_base._reason); if (unlikely(__pyx_t_1 < 0)) __PYX_ERR(0, 662, __pyx_L1_error) if (!__pyx_t_1) { } else { __Pyx_INCREF(__pyx_v_self->__pyx_base._reason); __pyx_t_2 = __pyx_v_self->__pyx_base._reason; goto __pyx_L4_bool_binop_done; } - __Pyx_INCREF(__pyx_kp_u__4); - __pyx_t_2 = __pyx_kp_u__4; + __Pyx_INCREF(__pyx_kp_u__8); + __pyx_t_2 = __pyx_kp_u__8; __pyx_L4_bool_binop_done:; __Pyx_GIVEREF(__pyx_t_2); __Pyx_GOTREF(__pyx_v_self->__pyx_base._reason); @@ -10894,8 +11661,8 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser_18HttpResponseParser__on_status } __pyx_L3:; - /* "aiohttp/_http_parser.pyx":604 - * auto_decompress) + /* "aiohttp/_http_parser.pyx":657 + * cparser.llhttp_set_lenient_spaces_after_chunk_size(self._cparser, 1) * * cdef object _on_status_complete(self): # <<<<<<<<<<<<<< * if self._buf: @@ -10949,7 +11716,7 @@ static PyObject *__pyx_pf_7aiohttp_12_http_parser_18HttpResponseParser_2__reduce * def __setstate_cython__(self, __pyx_state): * raise TypeError("no default __reduce__ due to non-trivial __cinit__") */ - __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__9, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 2, __pyx_L1_error) + __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__15, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 2, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_Raise(__pyx_t_1, 0, 0, 0); __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; @@ -11005,7 +11772,7 @@ static PyObject *__pyx_pf_7aiohttp_12_http_parser_18HttpResponseParser_4__setsta * def __setstate_cython__(self, __pyx_state): * raise TypeError("no default __reduce__ due to non-trivial __cinit__") # <<<<<<<<<<<<<< */ - __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__10, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 4, __pyx_L1_error) + __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__16, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 4, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_Raise(__pyx_t_1, 0, 0, 0); __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; @@ -11028,15 +11795,15 @@ static PyObject *__pyx_pf_7aiohttp_12_http_parser_18HttpResponseParser_4__setsta return __pyx_r; } -/* "aiohttp/_http_parser.pyx":611 +/* "aiohttp/_http_parser.pyx":664 * self._reason = self._reason or '' * - * cdef int cb_on_message_begin(cparser.http_parser* parser) except -1: # <<<<<<<<<<<<<< + * cdef int cb_on_message_begin(cparser.llhttp_t* parser) except -1: # <<<<<<<<<<<<<< * cdef HttpParser pyparser = parser.data * */ -static int __pyx_f_7aiohttp_12_http_parser_cb_on_message_begin(struct http_parser *__pyx_v_parser) { +static int __pyx_f_7aiohttp_12_http_parser_cb_on_message_begin(llhttp_t *__pyx_v_parser) { struct __pyx_obj_7aiohttp_12_http_parser_HttpParser *__pyx_v_pyparser = 0; int __pyx_r; __Pyx_RefNannyDeclarations @@ -11049,9 +11816,9 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_message_begin(struct http_parse int __pyx_clineno = 0; __Pyx_RefNannySetupContext("cb_on_message_begin", 0); - /* "aiohttp/_http_parser.pyx":612 + /* "aiohttp/_http_parser.pyx":665 * - * cdef int cb_on_message_begin(cparser.http_parser* parser) except -1: + * cdef int cb_on_message_begin(cparser.llhttp_t* parser) except -1: * cdef HttpParser pyparser = parser.data # <<<<<<<<<<<<<< * * pyparser._started = True @@ -11061,7 +11828,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_message_begin(struct http_parse __pyx_v_pyparser = ((struct __pyx_obj_7aiohttp_12_http_parser_HttpParser *)__pyx_t_1); __pyx_t_1 = 0; - /* "aiohttp/_http_parser.pyx":614 + /* "aiohttp/_http_parser.pyx":667 * cdef HttpParser pyparser = parser.data * * pyparser._started = True # <<<<<<<<<<<<<< @@ -11070,7 +11837,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_message_begin(struct http_parse */ __pyx_v_pyparser->_started = 1; - /* "aiohttp/_http_parser.pyx":615 + /* "aiohttp/_http_parser.pyx":668 * * pyparser._started = True * pyparser._headers = CIMultiDict() # <<<<<<<<<<<<<< @@ -11090,7 +11857,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_message_begin(struct http_parse } __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3) : __Pyx_PyObject_CallNoArg(__pyx_t_2); __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; - if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 615, __pyx_L1_error) + if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 668, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; __Pyx_GIVEREF(__pyx_t_1); @@ -11099,14 +11866,14 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_message_begin(struct http_parse __pyx_v_pyparser->_headers = __pyx_t_1; __pyx_t_1 = 0; - /* "aiohttp/_http_parser.pyx":616 + /* "aiohttp/_http_parser.pyx":669 * pyparser._started = True * pyparser._headers = CIMultiDict() * pyparser._raw_headers = [] # <<<<<<<<<<<<<< * PyByteArray_Resize(pyparser._buf, 0) * pyparser._path = None */ - __pyx_t_1 = PyList_New(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 616, __pyx_L1_error) + __pyx_t_1 = PyList_New(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 669, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_GIVEREF(__pyx_t_1); __Pyx_GOTREF(__pyx_v_pyparser->_raw_headers); @@ -11114,7 +11881,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_message_begin(struct http_parse __pyx_v_pyparser->_raw_headers = ((PyObject*)__pyx_t_1); __pyx_t_1 = 0; - /* "aiohttp/_http_parser.pyx":617 + /* "aiohttp/_http_parser.pyx":670 * pyparser._headers = CIMultiDict() * pyparser._raw_headers = [] * PyByteArray_Resize(pyparser._buf, 0) # <<<<<<<<<<<<<< @@ -11123,10 +11890,10 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_message_begin(struct http_parse */ __pyx_t_1 = __pyx_v_pyparser->_buf; __Pyx_INCREF(__pyx_t_1); - __pyx_t_4 = PyByteArray_Resize(__pyx_t_1, 0); if (unlikely(__pyx_t_4 == ((int)-1))) __PYX_ERR(0, 617, __pyx_L1_error) + __pyx_t_4 = PyByteArray_Resize(__pyx_t_1, 0); if (unlikely(__pyx_t_4 == ((int)-1))) __PYX_ERR(0, 670, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - /* "aiohttp/_http_parser.pyx":618 + /* "aiohttp/_http_parser.pyx":671 * pyparser._raw_headers = [] * PyByteArray_Resize(pyparser._buf, 0) * pyparser._path = None # <<<<<<<<<<<<<< @@ -11139,7 +11906,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_message_begin(struct http_parse __Pyx_DECREF(__pyx_v_pyparser->_path); __pyx_v_pyparser->_path = ((PyObject*)Py_None); - /* "aiohttp/_http_parser.pyx":619 + /* "aiohttp/_http_parser.pyx":672 * PyByteArray_Resize(pyparser._buf, 0) * pyparser._path = None * pyparser._reason = None # <<<<<<<<<<<<<< @@ -11152,7 +11919,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_message_begin(struct http_parse __Pyx_DECREF(__pyx_v_pyparser->_reason); __pyx_v_pyparser->_reason = ((PyObject*)Py_None); - /* "aiohttp/_http_parser.pyx":620 + /* "aiohttp/_http_parser.pyx":673 * pyparser._path = None * pyparser._reason = None * return 0 # <<<<<<<<<<<<<< @@ -11162,10 +11929,10 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_message_begin(struct http_parse __pyx_r = 0; goto __pyx_L0; - /* "aiohttp/_http_parser.pyx":611 + /* "aiohttp/_http_parser.pyx":664 * self._reason = self._reason or '' * - * cdef int cb_on_message_begin(cparser.http_parser* parser) except -1: # <<<<<<<<<<<<<< + * cdef int cb_on_message_begin(cparser.llhttp_t* parser) except -1: # <<<<<<<<<<<<<< * cdef HttpParser pyparser = parser.data * */ @@ -11183,15 +11950,15 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_message_begin(struct http_parse return __pyx_r; } -/* "aiohttp/_http_parser.pyx":623 +/* "aiohttp/_http_parser.pyx":676 * * - * cdef int cb_on_url(cparser.http_parser* parser, # <<<<<<<<<<<<<< + * cdef int cb_on_url(cparser.llhttp_t* parser, # <<<<<<<<<<<<<< * const char *at, size_t length) except -1: * cdef HttpParser pyparser = parser.data */ -static int __pyx_f_7aiohttp_12_http_parser_cb_on_url(struct http_parser *__pyx_v_parser, char const *__pyx_v_at, size_t __pyx_v_length) { +static int __pyx_f_7aiohttp_12_http_parser_cb_on_url(llhttp_t *__pyx_v_parser, char const *__pyx_v_at, size_t __pyx_v_length) { struct __pyx_obj_7aiohttp_12_http_parser_HttpParser *__pyx_v_pyparser = 0; PyObject *__pyx_v_ex = NULL; int __pyx_r; @@ -11212,8 +11979,8 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_url(struct http_parser *__pyx_v int __pyx_clineno = 0; __Pyx_RefNannySetupContext("cb_on_url", 0); - /* "aiohttp/_http_parser.pyx":625 - * cdef int cb_on_url(cparser.http_parser* parser, + /* "aiohttp/_http_parser.pyx":678 + * cdef int cb_on_url(cparser.llhttp_t* parser, * const char *at, size_t length) except -1: * cdef HttpParser pyparser = parser.data # <<<<<<<<<<<<<< * try: @@ -11224,7 +11991,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_url(struct http_parser *__pyx_v __pyx_v_pyparser = ((struct __pyx_obj_7aiohttp_12_http_parser_HttpParser *)__pyx_t_1); __pyx_t_1 = 0; - /* "aiohttp/_http_parser.pyx":626 + /* "aiohttp/_http_parser.pyx":679 * const char *at, size_t length) except -1: * cdef HttpParser pyparser = parser.data * try: # <<<<<<<<<<<<<< @@ -11240,7 +12007,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_url(struct http_parser *__pyx_v __Pyx_XGOTREF(__pyx_t_4); /*try:*/ { - /* "aiohttp/_http_parser.pyx":627 + /* "aiohttp/_http_parser.pyx":680 * cdef HttpParser pyparser = parser.data * try: * if length > pyparser._max_line_size: # <<<<<<<<<<<<<< @@ -11250,26 +12017,26 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_url(struct http_parser *__pyx_v __pyx_t_5 = ((__pyx_v_length > __pyx_v_pyparser->_max_line_size) != 0); if (unlikely(__pyx_t_5)) { - /* "aiohttp/_http_parser.pyx":628 + /* "aiohttp/_http_parser.pyx":681 * try: * if length > pyparser._max_line_size: * raise LineTooLong( # <<<<<<<<<<<<<< * 'Status line is too long', pyparser._max_line_size, length) * extend(pyparser._buf, at, length) */ - __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_n_s_LineTooLong); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 628, __pyx_L3_error) + __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_n_s_LineTooLong); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 681, __pyx_L3_error) __Pyx_GOTREF(__pyx_t_6); - /* "aiohttp/_http_parser.pyx":629 + /* "aiohttp/_http_parser.pyx":682 * if length > pyparser._max_line_size: * raise LineTooLong( * 'Status line is too long', pyparser._max_line_size, length) # <<<<<<<<<<<<<< * extend(pyparser._buf, at, length) * except BaseException as ex: */ - __pyx_t_7 = __Pyx_PyInt_FromSize_t(__pyx_v_pyparser->_max_line_size); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 629, __pyx_L3_error) + __pyx_t_7 = __Pyx_PyInt_FromSize_t(__pyx_v_pyparser->_max_line_size); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 682, __pyx_L3_error) __Pyx_GOTREF(__pyx_t_7); - __pyx_t_8 = __Pyx_PyInt_FromSize_t(__pyx_v_length); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 629, __pyx_L3_error) + __pyx_t_8 = __Pyx_PyInt_FromSize_t(__pyx_v_length); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 682, __pyx_L3_error) __Pyx_GOTREF(__pyx_t_8); __pyx_t_9 = NULL; __pyx_t_10 = 0; @@ -11286,7 +12053,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_url(struct http_parser *__pyx_v #if CYTHON_FAST_PYCALL if (PyFunction_Check(__pyx_t_6)) { PyObject *__pyx_temp[4] = {__pyx_t_9, __pyx_kp_u_Status_line_is_too_long, __pyx_t_7, __pyx_t_8}; - __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_6, __pyx_temp+1-__pyx_t_10, 3+__pyx_t_10); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 628, __pyx_L3_error) + __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_6, __pyx_temp+1-__pyx_t_10, 3+__pyx_t_10); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 681, __pyx_L3_error) __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; __Pyx_GOTREF(__pyx_t_1); __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; @@ -11296,7 +12063,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_url(struct http_parser *__pyx_v #if CYTHON_FAST_PYCCALL if (__Pyx_PyFastCFunction_Check(__pyx_t_6)) { PyObject *__pyx_temp[4] = {__pyx_t_9, __pyx_kp_u_Status_line_is_too_long, __pyx_t_7, __pyx_t_8}; - __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_6, __pyx_temp+1-__pyx_t_10, 3+__pyx_t_10); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 628, __pyx_L3_error) + __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_6, __pyx_temp+1-__pyx_t_10, 3+__pyx_t_10); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 681, __pyx_L3_error) __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; __Pyx_GOTREF(__pyx_t_1); __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; @@ -11304,7 +12071,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_url(struct http_parser *__pyx_v } else #endif { - __pyx_t_11 = PyTuple_New(3+__pyx_t_10); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 628, __pyx_L3_error) + __pyx_t_11 = PyTuple_New(3+__pyx_t_10); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 681, __pyx_L3_error) __Pyx_GOTREF(__pyx_t_11); if (__pyx_t_9) { __Pyx_GIVEREF(__pyx_t_9); PyTuple_SET_ITEM(__pyx_t_11, 0, __pyx_t_9); __pyx_t_9 = NULL; @@ -11318,16 +12085,16 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_url(struct http_parser *__pyx_v PyTuple_SET_ITEM(__pyx_t_11, 2+__pyx_t_10, __pyx_t_8); __pyx_t_7 = 0; __pyx_t_8 = 0; - __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_6, __pyx_t_11, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 628, __pyx_L3_error) + __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_6, __pyx_t_11, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 681, __pyx_L3_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0; } __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; __Pyx_Raise(__pyx_t_1, 0, 0, 0); __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __PYX_ERR(0, 628, __pyx_L3_error) + __PYX_ERR(0, 681, __pyx_L3_error) - /* "aiohttp/_http_parser.pyx":627 + /* "aiohttp/_http_parser.pyx":680 * cdef HttpParser pyparser = parser.data * try: * if length > pyparser._max_line_size: # <<<<<<<<<<<<<< @@ -11336,7 +12103,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_url(struct http_parser *__pyx_v */ } - /* "aiohttp/_http_parser.pyx":630 + /* "aiohttp/_http_parser.pyx":683 * raise LineTooLong( * 'Status line is too long', pyparser._max_line_size, length) * extend(pyparser._buf, at, length) # <<<<<<<<<<<<<< @@ -11345,12 +12112,12 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_url(struct http_parser *__pyx_v */ __pyx_t_1 = __pyx_v_pyparser->_buf; __Pyx_INCREF(__pyx_t_1); - __pyx_t_6 = __pyx_f_7aiohttp_12_http_parser_extend(__pyx_t_1, __pyx_v_at, __pyx_v_length); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 630, __pyx_L3_error) + __pyx_t_6 = __pyx_f_7aiohttp_12_http_parser_extend(__pyx_t_1, __pyx_v_at, __pyx_v_length); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 683, __pyx_L3_error) __Pyx_GOTREF(__pyx_t_6); __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; - /* "aiohttp/_http_parser.pyx":626 + /* "aiohttp/_http_parser.pyx":679 * const char *at, size_t length) except -1: * cdef HttpParser pyparser = parser.data * try: # <<<<<<<<<<<<<< @@ -11359,7 +12126,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_url(struct http_parser *__pyx_v */ } - /* "aiohttp/_http_parser.pyx":635 + /* "aiohttp/_http_parser.pyx":688 * return -1 * else: * return 0 # <<<<<<<<<<<<<< @@ -11378,7 +12145,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_url(struct http_parser *__pyx_v __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; - /* "aiohttp/_http_parser.pyx":631 + /* "aiohttp/_http_parser.pyx":684 * 'Status line is too long', pyparser._max_line_size, length) * extend(pyparser._buf, at, length) * except BaseException as ex: # <<<<<<<<<<<<<< @@ -11388,7 +12155,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_url(struct http_parser *__pyx_v __pyx_t_10 = __Pyx_PyErr_ExceptionMatches(__pyx_builtin_BaseException); if (__pyx_t_10) { __Pyx_AddTraceback("aiohttp._http_parser.cb_on_url", __pyx_clineno, __pyx_lineno, __pyx_filename); - if (__Pyx_GetException(&__pyx_t_6, &__pyx_t_1, &__pyx_t_11) < 0) __PYX_ERR(0, 631, __pyx_L5_except_error) + if (__Pyx_GetException(&__pyx_t_6, &__pyx_t_1, &__pyx_t_11) < 0) __PYX_ERR(0, 684, __pyx_L5_except_error) __Pyx_GOTREF(__pyx_t_6); __Pyx_GOTREF(__pyx_t_1); __Pyx_GOTREF(__pyx_t_11); @@ -11396,7 +12163,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_url(struct http_parser *__pyx_v __pyx_v_ex = __pyx_t_1; /*try:*/ { - /* "aiohttp/_http_parser.pyx":632 + /* "aiohttp/_http_parser.pyx":685 * extend(pyparser._buf, at, length) * except BaseException as ex: * pyparser._last_error = ex # <<<<<<<<<<<<<< @@ -11409,7 +12176,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_url(struct http_parser *__pyx_v __Pyx_DECREF(__pyx_v_pyparser->_last_error); __pyx_v_pyparser->_last_error = __pyx_v_ex; - /* "aiohttp/_http_parser.pyx":633 + /* "aiohttp/_http_parser.pyx":686 * except BaseException as ex: * pyparser._last_error = ex * return -1 # <<<<<<<<<<<<<< @@ -11423,7 +12190,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_url(struct http_parser *__pyx_v goto __pyx_L14_return; } - /* "aiohttp/_http_parser.pyx":631 + /* "aiohttp/_http_parser.pyx":684 * 'Status line is too long', pyparser._max_line_size, length) * extend(pyparser._buf, at, length) * except BaseException as ex: # <<<<<<<<<<<<<< @@ -11443,7 +12210,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_url(struct http_parser *__pyx_v goto __pyx_L5_except_error; __pyx_L5_except_error:; - /* "aiohttp/_http_parser.pyx":626 + /* "aiohttp/_http_parser.pyx":679 * const char *at, size_t length) except -1: * cdef HttpParser pyparser = parser.data * try: # <<<<<<<<<<<<<< @@ -11463,10 +12230,10 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_url(struct http_parser *__pyx_v goto __pyx_L0; } - /* "aiohttp/_http_parser.pyx":623 + /* "aiohttp/_http_parser.pyx":676 * * - * cdef int cb_on_url(cparser.http_parser* parser, # <<<<<<<<<<<<<< + * cdef int cb_on_url(cparser.llhttp_t* parser, # <<<<<<<<<<<<<< * const char *at, size_t length) except -1: * cdef HttpParser pyparser = parser.data */ @@ -11488,15 +12255,15 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_url(struct http_parser *__pyx_v return __pyx_r; } -/* "aiohttp/_http_parser.pyx":638 +/* "aiohttp/_http_parser.pyx":691 * * - * cdef int cb_on_status(cparser.http_parser* parser, # <<<<<<<<<<<<<< + * cdef int cb_on_status(cparser.llhttp_t* parser, # <<<<<<<<<<<<<< * const char *at, size_t length) except -1: * cdef HttpParser pyparser = parser.data */ -static int __pyx_f_7aiohttp_12_http_parser_cb_on_status(struct http_parser *__pyx_v_parser, char const *__pyx_v_at, size_t __pyx_v_length) { +static int __pyx_f_7aiohttp_12_http_parser_cb_on_status(llhttp_t *__pyx_v_parser, char const *__pyx_v_at, size_t __pyx_v_length) { struct __pyx_obj_7aiohttp_12_http_parser_HttpParser *__pyx_v_pyparser = 0; PyObject *__pyx_v_ex = NULL; int __pyx_r; @@ -11517,8 +12284,8 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_status(struct http_parser *__py int __pyx_clineno = 0; __Pyx_RefNannySetupContext("cb_on_status", 0); - /* "aiohttp/_http_parser.pyx":640 - * cdef int cb_on_status(cparser.http_parser* parser, + /* "aiohttp/_http_parser.pyx":693 + * cdef int cb_on_status(cparser.llhttp_t* parser, * const char *at, size_t length) except -1: * cdef HttpParser pyparser = parser.data # <<<<<<<<<<<<<< * cdef str reason @@ -11529,7 +12296,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_status(struct http_parser *__py __pyx_v_pyparser = ((struct __pyx_obj_7aiohttp_12_http_parser_HttpParser *)__pyx_t_1); __pyx_t_1 = 0; - /* "aiohttp/_http_parser.pyx":642 + /* "aiohttp/_http_parser.pyx":695 * cdef HttpParser pyparser = parser.data * cdef str reason * try: # <<<<<<<<<<<<<< @@ -11545,7 +12312,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_status(struct http_parser *__py __Pyx_XGOTREF(__pyx_t_4); /*try:*/ { - /* "aiohttp/_http_parser.pyx":643 + /* "aiohttp/_http_parser.pyx":696 * cdef str reason * try: * if length > pyparser._max_line_size: # <<<<<<<<<<<<<< @@ -11555,26 +12322,26 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_status(struct http_parser *__py __pyx_t_5 = ((__pyx_v_length > __pyx_v_pyparser->_max_line_size) != 0); if (unlikely(__pyx_t_5)) { - /* "aiohttp/_http_parser.pyx":644 + /* "aiohttp/_http_parser.pyx":697 * try: * if length > pyparser._max_line_size: * raise LineTooLong( # <<<<<<<<<<<<<< * 'Status line is too long', pyparser._max_line_size, length) * extend(pyparser._buf, at, length) */ - __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_n_s_LineTooLong); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 644, __pyx_L3_error) + __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_n_s_LineTooLong); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 697, __pyx_L3_error) __Pyx_GOTREF(__pyx_t_6); - /* "aiohttp/_http_parser.pyx":645 + /* "aiohttp/_http_parser.pyx":698 * if length > pyparser._max_line_size: * raise LineTooLong( * 'Status line is too long', pyparser._max_line_size, length) # <<<<<<<<<<<<<< * extend(pyparser._buf, at, length) * except BaseException as ex: */ - __pyx_t_7 = __Pyx_PyInt_FromSize_t(__pyx_v_pyparser->_max_line_size); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 645, __pyx_L3_error) + __pyx_t_7 = __Pyx_PyInt_FromSize_t(__pyx_v_pyparser->_max_line_size); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 698, __pyx_L3_error) __Pyx_GOTREF(__pyx_t_7); - __pyx_t_8 = __Pyx_PyInt_FromSize_t(__pyx_v_length); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 645, __pyx_L3_error) + __pyx_t_8 = __Pyx_PyInt_FromSize_t(__pyx_v_length); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 698, __pyx_L3_error) __Pyx_GOTREF(__pyx_t_8); __pyx_t_9 = NULL; __pyx_t_10 = 0; @@ -11591,7 +12358,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_status(struct http_parser *__py #if CYTHON_FAST_PYCALL if (PyFunction_Check(__pyx_t_6)) { PyObject *__pyx_temp[4] = {__pyx_t_9, __pyx_kp_u_Status_line_is_too_long, __pyx_t_7, __pyx_t_8}; - __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_6, __pyx_temp+1-__pyx_t_10, 3+__pyx_t_10); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 644, __pyx_L3_error) + __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_6, __pyx_temp+1-__pyx_t_10, 3+__pyx_t_10); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 697, __pyx_L3_error) __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; __Pyx_GOTREF(__pyx_t_1); __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; @@ -11601,7 +12368,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_status(struct http_parser *__py #if CYTHON_FAST_PYCCALL if (__Pyx_PyFastCFunction_Check(__pyx_t_6)) { PyObject *__pyx_temp[4] = {__pyx_t_9, __pyx_kp_u_Status_line_is_too_long, __pyx_t_7, __pyx_t_8}; - __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_6, __pyx_temp+1-__pyx_t_10, 3+__pyx_t_10); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 644, __pyx_L3_error) + __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_6, __pyx_temp+1-__pyx_t_10, 3+__pyx_t_10); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 697, __pyx_L3_error) __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; __Pyx_GOTREF(__pyx_t_1); __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; @@ -11609,7 +12376,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_status(struct http_parser *__py } else #endif { - __pyx_t_11 = PyTuple_New(3+__pyx_t_10); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 644, __pyx_L3_error) + __pyx_t_11 = PyTuple_New(3+__pyx_t_10); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 697, __pyx_L3_error) __Pyx_GOTREF(__pyx_t_11); if (__pyx_t_9) { __Pyx_GIVEREF(__pyx_t_9); PyTuple_SET_ITEM(__pyx_t_11, 0, __pyx_t_9); __pyx_t_9 = NULL; @@ -11623,16 +12390,16 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_status(struct http_parser *__py PyTuple_SET_ITEM(__pyx_t_11, 2+__pyx_t_10, __pyx_t_8); __pyx_t_7 = 0; __pyx_t_8 = 0; - __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_6, __pyx_t_11, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 644, __pyx_L3_error) + __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_6, __pyx_t_11, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 697, __pyx_L3_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0; } __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; __Pyx_Raise(__pyx_t_1, 0, 0, 0); __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __PYX_ERR(0, 644, __pyx_L3_error) + __PYX_ERR(0, 697, __pyx_L3_error) - /* "aiohttp/_http_parser.pyx":643 + /* "aiohttp/_http_parser.pyx":696 * cdef str reason * try: * if length > pyparser._max_line_size: # <<<<<<<<<<<<<< @@ -11641,7 +12408,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_status(struct http_parser *__py */ } - /* "aiohttp/_http_parser.pyx":646 + /* "aiohttp/_http_parser.pyx":699 * raise LineTooLong( * 'Status line is too long', pyparser._max_line_size, length) * extend(pyparser._buf, at, length) # <<<<<<<<<<<<<< @@ -11650,12 +12417,12 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_status(struct http_parser *__py */ __pyx_t_1 = __pyx_v_pyparser->_buf; __Pyx_INCREF(__pyx_t_1); - __pyx_t_6 = __pyx_f_7aiohttp_12_http_parser_extend(__pyx_t_1, __pyx_v_at, __pyx_v_length); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 646, __pyx_L3_error) + __pyx_t_6 = __pyx_f_7aiohttp_12_http_parser_extend(__pyx_t_1, __pyx_v_at, __pyx_v_length); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 699, __pyx_L3_error) __Pyx_GOTREF(__pyx_t_6); __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; - /* "aiohttp/_http_parser.pyx":642 + /* "aiohttp/_http_parser.pyx":695 * cdef HttpParser pyparser = parser.data * cdef str reason * try: # <<<<<<<<<<<<<< @@ -11664,7 +12431,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_status(struct http_parser *__py */ } - /* "aiohttp/_http_parser.pyx":651 + /* "aiohttp/_http_parser.pyx":704 * return -1 * else: * return 0 # <<<<<<<<<<<<<< @@ -11683,7 +12450,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_status(struct http_parser *__py __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; - /* "aiohttp/_http_parser.pyx":647 + /* "aiohttp/_http_parser.pyx":700 * 'Status line is too long', pyparser._max_line_size, length) * extend(pyparser._buf, at, length) * except BaseException as ex: # <<<<<<<<<<<<<< @@ -11693,7 +12460,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_status(struct http_parser *__py __pyx_t_10 = __Pyx_PyErr_ExceptionMatches(__pyx_builtin_BaseException); if (__pyx_t_10) { __Pyx_AddTraceback("aiohttp._http_parser.cb_on_status", __pyx_clineno, __pyx_lineno, __pyx_filename); - if (__Pyx_GetException(&__pyx_t_6, &__pyx_t_1, &__pyx_t_11) < 0) __PYX_ERR(0, 647, __pyx_L5_except_error) + if (__Pyx_GetException(&__pyx_t_6, &__pyx_t_1, &__pyx_t_11) < 0) __PYX_ERR(0, 700, __pyx_L5_except_error) __Pyx_GOTREF(__pyx_t_6); __Pyx_GOTREF(__pyx_t_1); __Pyx_GOTREF(__pyx_t_11); @@ -11701,7 +12468,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_status(struct http_parser *__py __pyx_v_ex = __pyx_t_1; /*try:*/ { - /* "aiohttp/_http_parser.pyx":648 + /* "aiohttp/_http_parser.pyx":701 * extend(pyparser._buf, at, length) * except BaseException as ex: * pyparser._last_error = ex # <<<<<<<<<<<<<< @@ -11714,7 +12481,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_status(struct http_parser *__py __Pyx_DECREF(__pyx_v_pyparser->_last_error); __pyx_v_pyparser->_last_error = __pyx_v_ex; - /* "aiohttp/_http_parser.pyx":649 + /* "aiohttp/_http_parser.pyx":702 * except BaseException as ex: * pyparser._last_error = ex * return -1 # <<<<<<<<<<<<<< @@ -11728,7 +12495,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_status(struct http_parser *__py goto __pyx_L14_return; } - /* "aiohttp/_http_parser.pyx":647 + /* "aiohttp/_http_parser.pyx":700 * 'Status line is too long', pyparser._max_line_size, length) * extend(pyparser._buf, at, length) * except BaseException as ex: # <<<<<<<<<<<<<< @@ -11748,7 +12515,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_status(struct http_parser *__py goto __pyx_L5_except_error; __pyx_L5_except_error:; - /* "aiohttp/_http_parser.pyx":642 + /* "aiohttp/_http_parser.pyx":695 * cdef HttpParser pyparser = parser.data * cdef str reason * try: # <<<<<<<<<<<<<< @@ -11768,10 +12535,10 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_status(struct http_parser *__py goto __pyx_L0; } - /* "aiohttp/_http_parser.pyx":638 + /* "aiohttp/_http_parser.pyx":691 * * - * cdef int cb_on_status(cparser.http_parser* parser, # <<<<<<<<<<<<<< + * cdef int cb_on_status(cparser.llhttp_t* parser, # <<<<<<<<<<<<<< * const char *at, size_t length) except -1: * cdef HttpParser pyparser = parser.data */ @@ -11793,15 +12560,15 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_status(struct http_parser *__py return __pyx_r; } -/* "aiohttp/_http_parser.pyx":654 +/* "aiohttp/_http_parser.pyx":707 * * - * cdef int cb_on_header_field(cparser.http_parser* parser, # <<<<<<<<<<<<<< + * cdef int cb_on_header_field(cparser.llhttp_t* parser, # <<<<<<<<<<<<<< * const char *at, size_t length) except -1: * cdef HttpParser pyparser = parser.data */ -static int __pyx_f_7aiohttp_12_http_parser_cb_on_header_field(struct http_parser *__pyx_v_parser, char const *__pyx_v_at, size_t __pyx_v_length) { +static int __pyx_f_7aiohttp_12_http_parser_cb_on_header_field(llhttp_t *__pyx_v_parser, char const *__pyx_v_at, size_t __pyx_v_length) { struct __pyx_obj_7aiohttp_12_http_parser_HttpParser *__pyx_v_pyparser = 0; Py_ssize_t __pyx_v_size; PyObject *__pyx_v_ex = NULL; @@ -11824,8 +12591,8 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_header_field(struct http_parser int __pyx_clineno = 0; __Pyx_RefNannySetupContext("cb_on_header_field", 0); - /* "aiohttp/_http_parser.pyx":656 - * cdef int cb_on_header_field(cparser.http_parser* parser, + /* "aiohttp/_http_parser.pyx":709 + * cdef int cb_on_header_field(cparser.llhttp_t* parser, * const char *at, size_t length) except -1: * cdef HttpParser pyparser = parser.data # <<<<<<<<<<<<<< * cdef Py_ssize_t size @@ -11836,7 +12603,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_header_field(struct http_parser __pyx_v_pyparser = ((struct __pyx_obj_7aiohttp_12_http_parser_HttpParser *)__pyx_t_1); __pyx_t_1 = 0; - /* "aiohttp/_http_parser.pyx":658 + /* "aiohttp/_http_parser.pyx":711 * cdef HttpParser pyparser = parser.data * cdef Py_ssize_t size * try: # <<<<<<<<<<<<<< @@ -11852,18 +12619,18 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_header_field(struct http_parser __Pyx_XGOTREF(__pyx_t_4); /*try:*/ { - /* "aiohttp/_http_parser.pyx":659 + /* "aiohttp/_http_parser.pyx":712 * cdef Py_ssize_t size * try: * pyparser._on_status_complete() # <<<<<<<<<<<<<< * size = len(pyparser._raw_name) + length * if size > pyparser._max_field_size: */ - __pyx_t_1 = ((struct __pyx_vtabstruct_7aiohttp_12_http_parser_HttpParser *)__pyx_v_pyparser->__pyx_vtab)->_on_status_complete(__pyx_v_pyparser); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 659, __pyx_L3_error) + __pyx_t_1 = ((struct __pyx_vtabstruct_7aiohttp_12_http_parser_HttpParser *)__pyx_v_pyparser->__pyx_vtab)->_on_status_complete(__pyx_v_pyparser); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 712, __pyx_L3_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - /* "aiohttp/_http_parser.pyx":660 + /* "aiohttp/_http_parser.pyx":713 * try: * pyparser._on_status_complete() * size = len(pyparser._raw_name) + length # <<<<<<<<<<<<<< @@ -11874,13 +12641,13 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_header_field(struct http_parser __Pyx_INCREF(__pyx_t_1); if (unlikely(__pyx_t_1 == Py_None)) { PyErr_SetString(PyExc_TypeError, "object of type 'NoneType' has no len()"); - __PYX_ERR(0, 660, __pyx_L3_error) + __PYX_ERR(0, 713, __pyx_L3_error) } - __pyx_t_5 = PyByteArray_GET_SIZE(__pyx_t_1); if (unlikely(__pyx_t_5 == ((Py_ssize_t)-1))) __PYX_ERR(0, 660, __pyx_L3_error) + __pyx_t_5 = PyByteArray_GET_SIZE(__pyx_t_1); if (unlikely(__pyx_t_5 == ((Py_ssize_t)-1))) __PYX_ERR(0, 713, __pyx_L3_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __pyx_v_size = (__pyx_t_5 + __pyx_v_length); - /* "aiohttp/_http_parser.pyx":661 + /* "aiohttp/_http_parser.pyx":714 * pyparser._on_status_complete() * size = len(pyparser._raw_name) + length * if size > pyparser._max_field_size: # <<<<<<<<<<<<<< @@ -11890,26 +12657,26 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_header_field(struct http_parser __pyx_t_6 = ((__pyx_v_size > __pyx_v_pyparser->_max_field_size) != 0); if (unlikely(__pyx_t_6)) { - /* "aiohttp/_http_parser.pyx":662 + /* "aiohttp/_http_parser.pyx":715 * size = len(pyparser._raw_name) + length * if size > pyparser._max_field_size: * raise LineTooLong( # <<<<<<<<<<<<<< * 'Header name is too long', pyparser._max_field_size, size) * pyparser._on_header_field(at, length) */ - __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_n_s_LineTooLong); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 662, __pyx_L3_error) + __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_n_s_LineTooLong); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 715, __pyx_L3_error) __Pyx_GOTREF(__pyx_t_7); - /* "aiohttp/_http_parser.pyx":663 + /* "aiohttp/_http_parser.pyx":716 * if size > pyparser._max_field_size: * raise LineTooLong( * 'Header name is too long', pyparser._max_field_size, size) # <<<<<<<<<<<<<< * pyparser._on_header_field(at, length) * except BaseException as ex: */ - __pyx_t_8 = __Pyx_PyInt_FromSize_t(__pyx_v_pyparser->_max_field_size); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 663, __pyx_L3_error) + __pyx_t_8 = __Pyx_PyInt_FromSize_t(__pyx_v_pyparser->_max_field_size); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 716, __pyx_L3_error) __Pyx_GOTREF(__pyx_t_8); - __pyx_t_9 = PyInt_FromSsize_t(__pyx_v_size); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 663, __pyx_L3_error) + __pyx_t_9 = PyInt_FromSsize_t(__pyx_v_size); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 716, __pyx_L3_error) __Pyx_GOTREF(__pyx_t_9); __pyx_t_10 = NULL; __pyx_t_11 = 0; @@ -11926,7 +12693,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_header_field(struct http_parser #if CYTHON_FAST_PYCALL if (PyFunction_Check(__pyx_t_7)) { PyObject *__pyx_temp[4] = {__pyx_t_10, __pyx_kp_u_Header_name_is_too_long, __pyx_t_8, __pyx_t_9}; - __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_7, __pyx_temp+1-__pyx_t_11, 3+__pyx_t_11); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 662, __pyx_L3_error) + __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_7, __pyx_temp+1-__pyx_t_11, 3+__pyx_t_11); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 715, __pyx_L3_error) __Pyx_XDECREF(__pyx_t_10); __pyx_t_10 = 0; __Pyx_GOTREF(__pyx_t_1); __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; @@ -11936,7 +12703,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_header_field(struct http_parser #if CYTHON_FAST_PYCCALL if (__Pyx_PyFastCFunction_Check(__pyx_t_7)) { PyObject *__pyx_temp[4] = {__pyx_t_10, __pyx_kp_u_Header_name_is_too_long, __pyx_t_8, __pyx_t_9}; - __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_7, __pyx_temp+1-__pyx_t_11, 3+__pyx_t_11); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 662, __pyx_L3_error) + __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_7, __pyx_temp+1-__pyx_t_11, 3+__pyx_t_11); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 715, __pyx_L3_error) __Pyx_XDECREF(__pyx_t_10); __pyx_t_10 = 0; __Pyx_GOTREF(__pyx_t_1); __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; @@ -11944,7 +12711,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_header_field(struct http_parser } else #endif { - __pyx_t_12 = PyTuple_New(3+__pyx_t_11); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 662, __pyx_L3_error) + __pyx_t_12 = PyTuple_New(3+__pyx_t_11); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 715, __pyx_L3_error) __Pyx_GOTREF(__pyx_t_12); if (__pyx_t_10) { __Pyx_GIVEREF(__pyx_t_10); PyTuple_SET_ITEM(__pyx_t_12, 0, __pyx_t_10); __pyx_t_10 = NULL; @@ -11958,16 +12725,16 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_header_field(struct http_parser PyTuple_SET_ITEM(__pyx_t_12, 2+__pyx_t_11, __pyx_t_9); __pyx_t_8 = 0; __pyx_t_9 = 0; - __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_7, __pyx_t_12, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 662, __pyx_L3_error) + __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_7, __pyx_t_12, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 715, __pyx_L3_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0; } __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; __Pyx_Raise(__pyx_t_1, 0, 0, 0); __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __PYX_ERR(0, 662, __pyx_L3_error) + __PYX_ERR(0, 715, __pyx_L3_error) - /* "aiohttp/_http_parser.pyx":661 + /* "aiohttp/_http_parser.pyx":714 * pyparser._on_status_complete() * size = len(pyparser._raw_name) + length * if size > pyparser._max_field_size: # <<<<<<<<<<<<<< @@ -11976,18 +12743,18 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_header_field(struct http_parser */ } - /* "aiohttp/_http_parser.pyx":664 + /* "aiohttp/_http_parser.pyx":717 * raise LineTooLong( * 'Header name is too long', pyparser._max_field_size, size) * pyparser._on_header_field(at, length) # <<<<<<<<<<<<<< * except BaseException as ex: * pyparser._last_error = ex */ - __pyx_t_1 = ((struct __pyx_vtabstruct_7aiohttp_12_http_parser_HttpParser *)__pyx_v_pyparser->__pyx_vtab)->_on_header_field(__pyx_v_pyparser, __pyx_v_at, __pyx_v_length); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 664, __pyx_L3_error) + __pyx_t_1 = ((struct __pyx_vtabstruct_7aiohttp_12_http_parser_HttpParser *)__pyx_v_pyparser->__pyx_vtab)->_on_header_field(__pyx_v_pyparser, __pyx_v_at, __pyx_v_length); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 717, __pyx_L3_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - /* "aiohttp/_http_parser.pyx":658 + /* "aiohttp/_http_parser.pyx":711 * cdef HttpParser pyparser = parser.data * cdef Py_ssize_t size * try: # <<<<<<<<<<<<<< @@ -11996,7 +12763,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_header_field(struct http_parser */ } - /* "aiohttp/_http_parser.pyx":669 + /* "aiohttp/_http_parser.pyx":722 * return -1 * else: * return 0 # <<<<<<<<<<<<<< @@ -12015,7 +12782,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_header_field(struct http_parser __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; - /* "aiohttp/_http_parser.pyx":665 + /* "aiohttp/_http_parser.pyx":718 * 'Header name is too long', pyparser._max_field_size, size) * pyparser._on_header_field(at, length) * except BaseException as ex: # <<<<<<<<<<<<<< @@ -12025,7 +12792,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_header_field(struct http_parser __pyx_t_11 = __Pyx_PyErr_ExceptionMatches(__pyx_builtin_BaseException); if (__pyx_t_11) { __Pyx_AddTraceback("aiohttp._http_parser.cb_on_header_field", __pyx_clineno, __pyx_lineno, __pyx_filename); - if (__Pyx_GetException(&__pyx_t_1, &__pyx_t_7, &__pyx_t_12) < 0) __PYX_ERR(0, 665, __pyx_L5_except_error) + if (__Pyx_GetException(&__pyx_t_1, &__pyx_t_7, &__pyx_t_12) < 0) __PYX_ERR(0, 718, __pyx_L5_except_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_GOTREF(__pyx_t_7); __Pyx_GOTREF(__pyx_t_12); @@ -12033,7 +12800,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_header_field(struct http_parser __pyx_v_ex = __pyx_t_7; /*try:*/ { - /* "aiohttp/_http_parser.pyx":666 + /* "aiohttp/_http_parser.pyx":719 * pyparser._on_header_field(at, length) * except BaseException as ex: * pyparser._last_error = ex # <<<<<<<<<<<<<< @@ -12046,7 +12813,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_header_field(struct http_parser __Pyx_DECREF(__pyx_v_pyparser->_last_error); __pyx_v_pyparser->_last_error = __pyx_v_ex; - /* "aiohttp/_http_parser.pyx":667 + /* "aiohttp/_http_parser.pyx":720 * except BaseException as ex: * pyparser._last_error = ex * return -1 # <<<<<<<<<<<<<< @@ -12060,7 +12827,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_header_field(struct http_parser goto __pyx_L14_return; } - /* "aiohttp/_http_parser.pyx":665 + /* "aiohttp/_http_parser.pyx":718 * 'Header name is too long', pyparser._max_field_size, size) * pyparser._on_header_field(at, length) * except BaseException as ex: # <<<<<<<<<<<<<< @@ -12080,7 +12847,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_header_field(struct http_parser goto __pyx_L5_except_error; __pyx_L5_except_error:; - /* "aiohttp/_http_parser.pyx":658 + /* "aiohttp/_http_parser.pyx":711 * cdef HttpParser pyparser = parser.data * cdef Py_ssize_t size * try: # <<<<<<<<<<<<<< @@ -12100,10 +12867,10 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_header_field(struct http_parser goto __pyx_L0; } - /* "aiohttp/_http_parser.pyx":654 + /* "aiohttp/_http_parser.pyx":707 * * - * cdef int cb_on_header_field(cparser.http_parser* parser, # <<<<<<<<<<<<<< + * cdef int cb_on_header_field(cparser.llhttp_t* parser, # <<<<<<<<<<<<<< * const char *at, size_t length) except -1: * cdef HttpParser pyparser = parser.data */ @@ -12125,15 +12892,15 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_header_field(struct http_parser return __pyx_r; } -/* "aiohttp/_http_parser.pyx":672 +/* "aiohttp/_http_parser.pyx":725 * * - * cdef int cb_on_header_value(cparser.http_parser* parser, # <<<<<<<<<<<<<< + * cdef int cb_on_header_value(cparser.llhttp_t* parser, # <<<<<<<<<<<<<< * const char *at, size_t length) except -1: * cdef HttpParser pyparser = parser.data */ -static int __pyx_f_7aiohttp_12_http_parser_cb_on_header_value(struct http_parser *__pyx_v_parser, char const *__pyx_v_at, size_t __pyx_v_length) { +static int __pyx_f_7aiohttp_12_http_parser_cb_on_header_value(llhttp_t *__pyx_v_parser, char const *__pyx_v_at, size_t __pyx_v_length) { struct __pyx_obj_7aiohttp_12_http_parser_HttpParser *__pyx_v_pyparser = 0; Py_ssize_t __pyx_v_size; PyObject *__pyx_v_ex = NULL; @@ -12156,8 +12923,8 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_header_value(struct http_parser int __pyx_clineno = 0; __Pyx_RefNannySetupContext("cb_on_header_value", 0); - /* "aiohttp/_http_parser.pyx":674 - * cdef int cb_on_header_value(cparser.http_parser* parser, + /* "aiohttp/_http_parser.pyx":727 + * cdef int cb_on_header_value(cparser.llhttp_t* parser, * const char *at, size_t length) except -1: * cdef HttpParser pyparser = parser.data # <<<<<<<<<<<<<< * cdef Py_ssize_t size @@ -12168,7 +12935,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_header_value(struct http_parser __pyx_v_pyparser = ((struct __pyx_obj_7aiohttp_12_http_parser_HttpParser *)__pyx_t_1); __pyx_t_1 = 0; - /* "aiohttp/_http_parser.pyx":676 + /* "aiohttp/_http_parser.pyx":729 * cdef HttpParser pyparser = parser.data * cdef Py_ssize_t size * try: # <<<<<<<<<<<<<< @@ -12184,7 +12951,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_header_value(struct http_parser __Pyx_XGOTREF(__pyx_t_4); /*try:*/ { - /* "aiohttp/_http_parser.pyx":677 + /* "aiohttp/_http_parser.pyx":730 * cdef Py_ssize_t size * try: * size = len(pyparser._raw_value) + length # <<<<<<<<<<<<<< @@ -12195,13 +12962,13 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_header_value(struct http_parser __Pyx_INCREF(__pyx_t_1); if (unlikely(__pyx_t_1 == Py_None)) { PyErr_SetString(PyExc_TypeError, "object of type 'NoneType' has no len()"); - __PYX_ERR(0, 677, __pyx_L3_error) + __PYX_ERR(0, 730, __pyx_L3_error) } - __pyx_t_5 = PyByteArray_GET_SIZE(__pyx_t_1); if (unlikely(__pyx_t_5 == ((Py_ssize_t)-1))) __PYX_ERR(0, 677, __pyx_L3_error) + __pyx_t_5 = PyByteArray_GET_SIZE(__pyx_t_1); if (unlikely(__pyx_t_5 == ((Py_ssize_t)-1))) __PYX_ERR(0, 730, __pyx_L3_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __pyx_v_size = (__pyx_t_5 + __pyx_v_length); - /* "aiohttp/_http_parser.pyx":678 + /* "aiohttp/_http_parser.pyx":731 * try: * size = len(pyparser._raw_value) + length * if size > pyparser._max_field_size: # <<<<<<<<<<<<<< @@ -12211,26 +12978,26 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_header_value(struct http_parser __pyx_t_6 = ((__pyx_v_size > __pyx_v_pyparser->_max_field_size) != 0); if (unlikely(__pyx_t_6)) { - /* "aiohttp/_http_parser.pyx":679 + /* "aiohttp/_http_parser.pyx":732 * size = len(pyparser._raw_value) + length * if size > pyparser._max_field_size: * raise LineTooLong( # <<<<<<<<<<<<<< * 'Header value is too long', pyparser._max_field_size, size) * pyparser._on_header_value(at, length) */ - __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_n_s_LineTooLong); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 679, __pyx_L3_error) + __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_n_s_LineTooLong); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 732, __pyx_L3_error) __Pyx_GOTREF(__pyx_t_7); - /* "aiohttp/_http_parser.pyx":680 + /* "aiohttp/_http_parser.pyx":733 * if size > pyparser._max_field_size: * raise LineTooLong( * 'Header value is too long', pyparser._max_field_size, size) # <<<<<<<<<<<<<< * pyparser._on_header_value(at, length) * except BaseException as ex: */ - __pyx_t_8 = __Pyx_PyInt_FromSize_t(__pyx_v_pyparser->_max_field_size); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 680, __pyx_L3_error) + __pyx_t_8 = __Pyx_PyInt_FromSize_t(__pyx_v_pyparser->_max_field_size); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 733, __pyx_L3_error) __Pyx_GOTREF(__pyx_t_8); - __pyx_t_9 = PyInt_FromSsize_t(__pyx_v_size); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 680, __pyx_L3_error) + __pyx_t_9 = PyInt_FromSsize_t(__pyx_v_size); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 733, __pyx_L3_error) __Pyx_GOTREF(__pyx_t_9); __pyx_t_10 = NULL; __pyx_t_11 = 0; @@ -12247,7 +13014,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_header_value(struct http_parser #if CYTHON_FAST_PYCALL if (PyFunction_Check(__pyx_t_7)) { PyObject *__pyx_temp[4] = {__pyx_t_10, __pyx_kp_u_Header_value_is_too_long, __pyx_t_8, __pyx_t_9}; - __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_7, __pyx_temp+1-__pyx_t_11, 3+__pyx_t_11); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 679, __pyx_L3_error) + __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_7, __pyx_temp+1-__pyx_t_11, 3+__pyx_t_11); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 732, __pyx_L3_error) __Pyx_XDECREF(__pyx_t_10); __pyx_t_10 = 0; __Pyx_GOTREF(__pyx_t_1); __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; @@ -12257,7 +13024,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_header_value(struct http_parser #if CYTHON_FAST_PYCCALL if (__Pyx_PyFastCFunction_Check(__pyx_t_7)) { PyObject *__pyx_temp[4] = {__pyx_t_10, __pyx_kp_u_Header_value_is_too_long, __pyx_t_8, __pyx_t_9}; - __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_7, __pyx_temp+1-__pyx_t_11, 3+__pyx_t_11); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 679, __pyx_L3_error) + __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_7, __pyx_temp+1-__pyx_t_11, 3+__pyx_t_11); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 732, __pyx_L3_error) __Pyx_XDECREF(__pyx_t_10); __pyx_t_10 = 0; __Pyx_GOTREF(__pyx_t_1); __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; @@ -12265,7 +13032,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_header_value(struct http_parser } else #endif { - __pyx_t_12 = PyTuple_New(3+__pyx_t_11); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 679, __pyx_L3_error) + __pyx_t_12 = PyTuple_New(3+__pyx_t_11); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 732, __pyx_L3_error) __Pyx_GOTREF(__pyx_t_12); if (__pyx_t_10) { __Pyx_GIVEREF(__pyx_t_10); PyTuple_SET_ITEM(__pyx_t_12, 0, __pyx_t_10); __pyx_t_10 = NULL; @@ -12279,16 +13046,16 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_header_value(struct http_parser PyTuple_SET_ITEM(__pyx_t_12, 2+__pyx_t_11, __pyx_t_9); __pyx_t_8 = 0; __pyx_t_9 = 0; - __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_7, __pyx_t_12, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 679, __pyx_L3_error) + __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_7, __pyx_t_12, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 732, __pyx_L3_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0; } __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; __Pyx_Raise(__pyx_t_1, 0, 0, 0); __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __PYX_ERR(0, 679, __pyx_L3_error) + __PYX_ERR(0, 732, __pyx_L3_error) - /* "aiohttp/_http_parser.pyx":678 + /* "aiohttp/_http_parser.pyx":731 * try: * size = len(pyparser._raw_value) + length * if size > pyparser._max_field_size: # <<<<<<<<<<<<<< @@ -12297,18 +13064,18 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_header_value(struct http_parser */ } - /* "aiohttp/_http_parser.pyx":681 + /* "aiohttp/_http_parser.pyx":734 * raise LineTooLong( * 'Header value is too long', pyparser._max_field_size, size) * pyparser._on_header_value(at, length) # <<<<<<<<<<<<<< * except BaseException as ex: * pyparser._last_error = ex */ - __pyx_t_1 = ((struct __pyx_vtabstruct_7aiohttp_12_http_parser_HttpParser *)__pyx_v_pyparser->__pyx_vtab)->_on_header_value(__pyx_v_pyparser, __pyx_v_at, __pyx_v_length); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 681, __pyx_L3_error) + __pyx_t_1 = ((struct __pyx_vtabstruct_7aiohttp_12_http_parser_HttpParser *)__pyx_v_pyparser->__pyx_vtab)->_on_header_value(__pyx_v_pyparser, __pyx_v_at, __pyx_v_length); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 734, __pyx_L3_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - /* "aiohttp/_http_parser.pyx":676 + /* "aiohttp/_http_parser.pyx":729 * cdef HttpParser pyparser = parser.data * cdef Py_ssize_t size * try: # <<<<<<<<<<<<<< @@ -12317,7 +13084,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_header_value(struct http_parser */ } - /* "aiohttp/_http_parser.pyx":686 + /* "aiohttp/_http_parser.pyx":739 * return -1 * else: * return 0 # <<<<<<<<<<<<<< @@ -12336,7 +13103,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_header_value(struct http_parser __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; - /* "aiohttp/_http_parser.pyx":682 + /* "aiohttp/_http_parser.pyx":735 * 'Header value is too long', pyparser._max_field_size, size) * pyparser._on_header_value(at, length) * except BaseException as ex: # <<<<<<<<<<<<<< @@ -12346,7 +13113,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_header_value(struct http_parser __pyx_t_11 = __Pyx_PyErr_ExceptionMatches(__pyx_builtin_BaseException); if (__pyx_t_11) { __Pyx_AddTraceback("aiohttp._http_parser.cb_on_header_value", __pyx_clineno, __pyx_lineno, __pyx_filename); - if (__Pyx_GetException(&__pyx_t_1, &__pyx_t_7, &__pyx_t_12) < 0) __PYX_ERR(0, 682, __pyx_L5_except_error) + if (__Pyx_GetException(&__pyx_t_1, &__pyx_t_7, &__pyx_t_12) < 0) __PYX_ERR(0, 735, __pyx_L5_except_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_GOTREF(__pyx_t_7); __Pyx_GOTREF(__pyx_t_12); @@ -12354,7 +13121,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_header_value(struct http_parser __pyx_v_ex = __pyx_t_7; /*try:*/ { - /* "aiohttp/_http_parser.pyx":683 + /* "aiohttp/_http_parser.pyx":736 * pyparser._on_header_value(at, length) * except BaseException as ex: * pyparser._last_error = ex # <<<<<<<<<<<<<< @@ -12367,7 +13134,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_header_value(struct http_parser __Pyx_DECREF(__pyx_v_pyparser->_last_error); __pyx_v_pyparser->_last_error = __pyx_v_ex; - /* "aiohttp/_http_parser.pyx":684 + /* "aiohttp/_http_parser.pyx":737 * except BaseException as ex: * pyparser._last_error = ex * return -1 # <<<<<<<<<<<<<< @@ -12381,7 +13148,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_header_value(struct http_parser goto __pyx_L14_return; } - /* "aiohttp/_http_parser.pyx":682 + /* "aiohttp/_http_parser.pyx":735 * 'Header value is too long', pyparser._max_field_size, size) * pyparser._on_header_value(at, length) * except BaseException as ex: # <<<<<<<<<<<<<< @@ -12401,7 +13168,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_header_value(struct http_parser goto __pyx_L5_except_error; __pyx_L5_except_error:; - /* "aiohttp/_http_parser.pyx":676 + /* "aiohttp/_http_parser.pyx":729 * cdef HttpParser pyparser = parser.data * cdef Py_ssize_t size * try: # <<<<<<<<<<<<<< @@ -12421,10 +13188,10 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_header_value(struct http_parser goto __pyx_L0; } - /* "aiohttp/_http_parser.pyx":672 + /* "aiohttp/_http_parser.pyx":725 * * - * cdef int cb_on_header_value(cparser.http_parser* parser, # <<<<<<<<<<<<<< + * cdef int cb_on_header_value(cparser.llhttp_t* parser, # <<<<<<<<<<<<<< * const char *at, size_t length) except -1: * cdef HttpParser pyparser = parser.data */ @@ -12446,15 +13213,15 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_header_value(struct http_parser return __pyx_r; } -/* "aiohttp/_http_parser.pyx":689 +/* "aiohttp/_http_parser.pyx":742 * * - * cdef int cb_on_headers_complete(cparser.http_parser* parser) except -1: # <<<<<<<<<<<<<< + * cdef int cb_on_headers_complete(cparser.llhttp_t* parser) except -1: # <<<<<<<<<<<<<< * cdef HttpParser pyparser = parser.data * try: */ -static int __pyx_f_7aiohttp_12_http_parser_cb_on_headers_complete(struct http_parser *__pyx_v_parser) { +static int __pyx_f_7aiohttp_12_http_parser_cb_on_headers_complete(llhttp_t *__pyx_v_parser) { struct __pyx_obj_7aiohttp_12_http_parser_HttpParser *__pyx_v_pyparser = 0; PyObject *__pyx_v_exc = NULL; int __pyx_r; @@ -12473,9 +13240,9 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_headers_complete(struct http_pa int __pyx_clineno = 0; __Pyx_RefNannySetupContext("cb_on_headers_complete", 0); - /* "aiohttp/_http_parser.pyx":690 + /* "aiohttp/_http_parser.pyx":743 * - * cdef int cb_on_headers_complete(cparser.http_parser* parser) except -1: + * cdef int cb_on_headers_complete(cparser.llhttp_t* parser) except -1: * cdef HttpParser pyparser = parser.data # <<<<<<<<<<<<<< * try: * pyparser._on_status_complete() @@ -12485,8 +13252,8 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_headers_complete(struct http_pa __pyx_v_pyparser = ((struct __pyx_obj_7aiohttp_12_http_parser_HttpParser *)__pyx_t_1); __pyx_t_1 = 0; - /* "aiohttp/_http_parser.pyx":691 - * cdef int cb_on_headers_complete(cparser.http_parser* parser) except -1: + /* "aiohttp/_http_parser.pyx":744 + * cdef int cb_on_headers_complete(cparser.llhttp_t* parser) except -1: * cdef HttpParser pyparser = parser.data * try: # <<<<<<<<<<<<<< * pyparser._on_status_complete() @@ -12501,30 +13268,30 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_headers_complete(struct http_pa __Pyx_XGOTREF(__pyx_t_4); /*try:*/ { - /* "aiohttp/_http_parser.pyx":692 + /* "aiohttp/_http_parser.pyx":745 * cdef HttpParser pyparser = parser.data * try: * pyparser._on_status_complete() # <<<<<<<<<<<<<< * pyparser._on_headers_complete() * except BaseException as exc: */ - __pyx_t_1 = ((struct __pyx_vtabstruct_7aiohttp_12_http_parser_HttpParser *)__pyx_v_pyparser->__pyx_vtab)->_on_status_complete(__pyx_v_pyparser); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 692, __pyx_L3_error) + __pyx_t_1 = ((struct __pyx_vtabstruct_7aiohttp_12_http_parser_HttpParser *)__pyx_v_pyparser->__pyx_vtab)->_on_status_complete(__pyx_v_pyparser); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 745, __pyx_L3_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - /* "aiohttp/_http_parser.pyx":693 + /* "aiohttp/_http_parser.pyx":746 * try: * pyparser._on_status_complete() * pyparser._on_headers_complete() # <<<<<<<<<<<<<< * except BaseException as exc: * pyparser._last_error = exc */ - __pyx_t_1 = ((struct __pyx_vtabstruct_7aiohttp_12_http_parser_HttpParser *)__pyx_v_pyparser->__pyx_vtab)->_on_headers_complete(__pyx_v_pyparser); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 693, __pyx_L3_error) + __pyx_t_1 = ((struct __pyx_vtabstruct_7aiohttp_12_http_parser_HttpParser *)__pyx_v_pyparser->__pyx_vtab)->_on_headers_complete(__pyx_v_pyparser); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 746, __pyx_L3_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - /* "aiohttp/_http_parser.pyx":691 - * cdef int cb_on_headers_complete(cparser.http_parser* parser) except -1: + /* "aiohttp/_http_parser.pyx":744 + * cdef int cb_on_headers_complete(cparser.llhttp_t* parser) except -1: * cdef HttpParser pyparser = parser.data * try: # <<<<<<<<<<<<<< * pyparser._on_status_complete() @@ -12532,28 +13299,52 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_headers_complete(struct http_pa */ } - /* "aiohttp/_http_parser.pyx":698 + /* "aiohttp/_http_parser.pyx":751 * return -1 * else: - * if pyparser._cparser.upgrade or pyparser._cparser.method == 5: # CONNECT # <<<<<<<<<<<<<< - * return 2 - * else: + * if ( # <<<<<<<<<<<<<< + * pyparser._cparser.upgrade or + * pyparser._cparser.method == cparser.HTTP_CONNECT */ /*else:*/ { + + /* "aiohttp/_http_parser.pyx":752 + * else: + * if ( + * pyparser._cparser.upgrade or # <<<<<<<<<<<<<< + * pyparser._cparser.method == cparser.HTTP_CONNECT + * ): + */ __pyx_t_6 = (__pyx_v_pyparser->_cparser->upgrade != 0); if (!__pyx_t_6) { } else { __pyx_t_5 = __pyx_t_6; goto __pyx_L10_bool_binop_done; } - __pyx_t_6 = ((__pyx_v_pyparser->_cparser->method == 5) != 0); + + /* "aiohttp/_http_parser.pyx":753 + * if ( + * pyparser._cparser.upgrade or + * pyparser._cparser.method == cparser.HTTP_CONNECT # <<<<<<<<<<<<<< + * ): + * return 2 + */ + __pyx_t_6 = ((__pyx_v_pyparser->_cparser->method == HTTP_CONNECT) != 0); __pyx_t_5 = __pyx_t_6; __pyx_L10_bool_binop_done:; - if (__pyx_t_5) { - /* "aiohttp/_http_parser.pyx":699 + /* "aiohttp/_http_parser.pyx":751 + * return -1 * else: - * if pyparser._cparser.upgrade or pyparser._cparser.method == 5: # CONNECT + * if ( # <<<<<<<<<<<<<< + * pyparser._cparser.upgrade or + * pyparser._cparser.method == cparser.HTTP_CONNECT + */ + if (__pyx_t_5) { + + /* "aiohttp/_http_parser.pyx":755 + * pyparser._cparser.method == cparser.HTTP_CONNECT + * ): * return 2 # <<<<<<<<<<<<<< * else: * return 0 @@ -12561,16 +13352,16 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_headers_complete(struct http_pa __pyx_r = 2; goto __pyx_L6_except_return; - /* "aiohttp/_http_parser.pyx":698 + /* "aiohttp/_http_parser.pyx":751 * return -1 * else: - * if pyparser._cparser.upgrade or pyparser._cparser.method == 5: # CONNECT # <<<<<<<<<<<<<< - * return 2 - * else: + * if ( # <<<<<<<<<<<<<< + * pyparser._cparser.upgrade or + * pyparser._cparser.method == cparser.HTTP_CONNECT */ } - /* "aiohttp/_http_parser.pyx":701 + /* "aiohttp/_http_parser.pyx":757 * return 2 * else: * return 0 # <<<<<<<<<<<<<< @@ -12585,7 +13376,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_headers_complete(struct http_pa __pyx_L3_error:; __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; - /* "aiohttp/_http_parser.pyx":694 + /* "aiohttp/_http_parser.pyx":747 * pyparser._on_status_complete() * pyparser._on_headers_complete() * except BaseException as exc: # <<<<<<<<<<<<<< @@ -12595,7 +13386,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_headers_complete(struct http_pa __pyx_t_7 = __Pyx_PyErr_ExceptionMatches(__pyx_builtin_BaseException); if (__pyx_t_7) { __Pyx_AddTraceback("aiohttp._http_parser.cb_on_headers_complete", __pyx_clineno, __pyx_lineno, __pyx_filename); - if (__Pyx_GetException(&__pyx_t_1, &__pyx_t_8, &__pyx_t_9) < 0) __PYX_ERR(0, 694, __pyx_L5_except_error) + if (__Pyx_GetException(&__pyx_t_1, &__pyx_t_8, &__pyx_t_9) < 0) __PYX_ERR(0, 747, __pyx_L5_except_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_GOTREF(__pyx_t_8); __Pyx_GOTREF(__pyx_t_9); @@ -12603,7 +13394,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_headers_complete(struct http_pa __pyx_v_exc = __pyx_t_8; /*try:*/ { - /* "aiohttp/_http_parser.pyx":695 + /* "aiohttp/_http_parser.pyx":748 * pyparser._on_headers_complete() * except BaseException as exc: * pyparser._last_error = exc # <<<<<<<<<<<<<< @@ -12616,12 +13407,12 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_headers_complete(struct http_pa __Pyx_DECREF(__pyx_v_pyparser->_last_error); __pyx_v_pyparser->_last_error = __pyx_v_exc; - /* "aiohttp/_http_parser.pyx":696 + /* "aiohttp/_http_parser.pyx":749 * except BaseException as exc: * pyparser._last_error = exc * return -1 # <<<<<<<<<<<<<< * else: - * if pyparser._cparser.upgrade or pyparser._cparser.method == 5: # CONNECT + * if ( */ __pyx_r = -1; __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; @@ -12630,7 +13421,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_headers_complete(struct http_pa goto __pyx_L16_return; } - /* "aiohttp/_http_parser.pyx":694 + /* "aiohttp/_http_parser.pyx":747 * pyparser._on_status_complete() * pyparser._on_headers_complete() * except BaseException as exc: # <<<<<<<<<<<<<< @@ -12650,8 +13441,8 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_headers_complete(struct http_pa goto __pyx_L5_except_error; __pyx_L5_except_error:; - /* "aiohttp/_http_parser.pyx":691 - * cdef int cb_on_headers_complete(cparser.http_parser* parser) except -1: + /* "aiohttp/_http_parser.pyx":744 + * cdef int cb_on_headers_complete(cparser.llhttp_t* parser) except -1: * cdef HttpParser pyparser = parser.data * try: # <<<<<<<<<<<<<< * pyparser._on_status_complete() @@ -12670,10 +13461,10 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_headers_complete(struct http_pa goto __pyx_L0; } - /* "aiohttp/_http_parser.pyx":689 + /* "aiohttp/_http_parser.pyx":742 * * - * cdef int cb_on_headers_complete(cparser.http_parser* parser) except -1: # <<<<<<<<<<<<<< + * cdef int cb_on_headers_complete(cparser.llhttp_t* parser) except -1: # <<<<<<<<<<<<<< * cdef HttpParser pyparser = parser.data * try: */ @@ -12692,15 +13483,15 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_headers_complete(struct http_pa return __pyx_r; } -/* "aiohttp/_http_parser.pyx":704 +/* "aiohttp/_http_parser.pyx":760 * * - * cdef int cb_on_body(cparser.http_parser* parser, # <<<<<<<<<<<<<< + * cdef int cb_on_body(cparser.llhttp_t* parser, # <<<<<<<<<<<<<< * const char *at, size_t length) except -1: * cdef HttpParser pyparser = parser.data */ -static int __pyx_f_7aiohttp_12_http_parser_cb_on_body(struct http_parser *__pyx_v_parser, char const *__pyx_v_at, size_t __pyx_v_length) { +static int __pyx_f_7aiohttp_12_http_parser_cb_on_body(llhttp_t *__pyx_v_parser, char const *__pyx_v_at, size_t __pyx_v_length) { struct __pyx_obj_7aiohttp_12_http_parser_HttpParser *__pyx_v_pyparser = 0; PyObject *__pyx_v_body = 0; PyObject *__pyx_v_exc = NULL; @@ -12734,8 +13525,8 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_body(struct http_parser *__pyx_ int __pyx_clineno = 0; __Pyx_RefNannySetupContext("cb_on_body", 0); - /* "aiohttp/_http_parser.pyx":706 - * cdef int cb_on_body(cparser.http_parser* parser, + /* "aiohttp/_http_parser.pyx":762 + * cdef int cb_on_body(cparser.llhttp_t* parser, * const char *at, size_t length) except -1: * cdef HttpParser pyparser = parser.data # <<<<<<<<<<<<<< * cdef bytes body = at[:length] @@ -12746,19 +13537,19 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_body(struct http_parser *__pyx_ __pyx_v_pyparser = ((struct __pyx_obj_7aiohttp_12_http_parser_HttpParser *)__pyx_t_1); __pyx_t_1 = 0; - /* "aiohttp/_http_parser.pyx":707 + /* "aiohttp/_http_parser.pyx":763 * const char *at, size_t length) except -1: * cdef HttpParser pyparser = parser.data * cdef bytes body = at[:length] # <<<<<<<<<<<<<< * try: * pyparser._payload.feed_data(body, length) */ - __pyx_t_1 = __Pyx_PyBytes_FromStringAndSize(__pyx_v_at + 0, __pyx_v_length - 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 707, __pyx_L1_error) + __pyx_t_1 = __Pyx_PyBytes_FromStringAndSize(__pyx_v_at + 0, __pyx_v_length - 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 763, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_v_body = ((PyObject*)__pyx_t_1); __pyx_t_1 = 0; - /* "aiohttp/_http_parser.pyx":708 + /* "aiohttp/_http_parser.pyx":764 * cdef HttpParser pyparser = parser.data * cdef bytes body = at[:length] * try: # <<<<<<<<<<<<<< @@ -12774,16 +13565,16 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_body(struct http_parser *__pyx_ __Pyx_XGOTREF(__pyx_t_4); /*try:*/ { - /* "aiohttp/_http_parser.pyx":709 + /* "aiohttp/_http_parser.pyx":765 * cdef bytes body = at[:length] * try: * pyparser._payload.feed_data(body, length) # <<<<<<<<<<<<<< * except BaseException as exc: * if pyparser._payload_exception is not None: */ - __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_pyparser->_payload, __pyx_n_s_feed_data); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 709, __pyx_L3_error) + __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_pyparser->_payload, __pyx_n_s_feed_data); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 765, __pyx_L3_error) __Pyx_GOTREF(__pyx_t_5); - __pyx_t_6 = __Pyx_PyInt_FromSize_t(__pyx_v_length); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 709, __pyx_L3_error) + __pyx_t_6 = __Pyx_PyInt_FromSize_t(__pyx_v_length); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 765, __pyx_L3_error) __Pyx_GOTREF(__pyx_t_6); __pyx_t_7 = NULL; __pyx_t_8 = 0; @@ -12800,7 +13591,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_body(struct http_parser *__pyx_ #if CYTHON_FAST_PYCALL if (PyFunction_Check(__pyx_t_5)) { PyObject *__pyx_temp[3] = {__pyx_t_7, __pyx_v_body, __pyx_t_6}; - __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_5, __pyx_temp+1-__pyx_t_8, 2+__pyx_t_8); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 709, __pyx_L3_error) + __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_5, __pyx_temp+1-__pyx_t_8, 2+__pyx_t_8); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 765, __pyx_L3_error) __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; __Pyx_GOTREF(__pyx_t_1); __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; @@ -12809,14 +13600,14 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_body(struct http_parser *__pyx_ #if CYTHON_FAST_PYCCALL if (__Pyx_PyFastCFunction_Check(__pyx_t_5)) { PyObject *__pyx_temp[3] = {__pyx_t_7, __pyx_v_body, __pyx_t_6}; - __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_5, __pyx_temp+1-__pyx_t_8, 2+__pyx_t_8); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 709, __pyx_L3_error) + __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_5, __pyx_temp+1-__pyx_t_8, 2+__pyx_t_8); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 765, __pyx_L3_error) __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; __Pyx_GOTREF(__pyx_t_1); __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; } else #endif { - __pyx_t_9 = PyTuple_New(2+__pyx_t_8); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 709, __pyx_L3_error) + __pyx_t_9 = PyTuple_New(2+__pyx_t_8); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 765, __pyx_L3_error) __Pyx_GOTREF(__pyx_t_9); if (__pyx_t_7) { __Pyx_GIVEREF(__pyx_t_7); PyTuple_SET_ITEM(__pyx_t_9, 0, __pyx_t_7); __pyx_t_7 = NULL; @@ -12827,14 +13618,14 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_body(struct http_parser *__pyx_ __Pyx_GIVEREF(__pyx_t_6); PyTuple_SET_ITEM(__pyx_t_9, 1+__pyx_t_8, __pyx_t_6); __pyx_t_6 = 0; - __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_5, __pyx_t_9, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 709, __pyx_L3_error) + __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_5, __pyx_t_9, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 765, __pyx_L3_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; } __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - /* "aiohttp/_http_parser.pyx":708 + /* "aiohttp/_http_parser.pyx":764 * cdef HttpParser pyparser = parser.data * cdef bytes body = at[:length] * try: # <<<<<<<<<<<<<< @@ -12843,7 +13634,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_body(struct http_parser *__pyx_ */ } - /* "aiohttp/_http_parser.pyx":718 + /* "aiohttp/_http_parser.pyx":774 * return -1 * else: * return 0 # <<<<<<<<<<<<<< @@ -12861,7 +13652,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_body(struct http_parser *__pyx_ __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; - /* "aiohttp/_http_parser.pyx":710 + /* "aiohttp/_http_parser.pyx":766 * try: * pyparser._payload.feed_data(body, length) * except BaseException as exc: # <<<<<<<<<<<<<< @@ -12871,7 +13662,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_body(struct http_parser *__pyx_ __pyx_t_8 = __Pyx_PyErr_ExceptionMatches(__pyx_builtin_BaseException); if (__pyx_t_8) { __Pyx_AddTraceback("aiohttp._http_parser.cb_on_body", __pyx_clineno, __pyx_lineno, __pyx_filename); - if (__Pyx_GetException(&__pyx_t_1, &__pyx_t_5, &__pyx_t_9) < 0) __PYX_ERR(0, 710, __pyx_L5_except_error) + if (__Pyx_GetException(&__pyx_t_1, &__pyx_t_5, &__pyx_t_9) < 0) __PYX_ERR(0, 766, __pyx_L5_except_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_GOTREF(__pyx_t_5); __Pyx_GOTREF(__pyx_t_9); @@ -12879,7 +13670,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_body(struct http_parser *__pyx_ __pyx_v_exc = __pyx_t_5; /*try:*/ { - /* "aiohttp/_http_parser.pyx":711 + /* "aiohttp/_http_parser.pyx":767 * pyparser._payload.feed_data(body, length) * except BaseException as exc: * if pyparser._payload_exception is not None: # <<<<<<<<<<<<<< @@ -12890,16 +13681,16 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_body(struct http_parser *__pyx_ __pyx_t_11 = (__pyx_t_10 != 0); if (__pyx_t_11) { - /* "aiohttp/_http_parser.pyx":712 + /* "aiohttp/_http_parser.pyx":768 * except BaseException as exc: * if pyparser._payload_exception is not None: * pyparser._payload.set_exception(pyparser._payload_exception(str(exc))) # <<<<<<<<<<<<<< * else: * pyparser._payload.set_exception(exc) */ - __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_v_pyparser->_payload, __pyx_n_s_set_exception); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 712, __pyx_L14_error) + __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_v_pyparser->_payload, __pyx_n_s_set_exception); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 768, __pyx_L14_error) __Pyx_GOTREF(__pyx_t_7); - __pyx_t_13 = __Pyx_PyObject_CallOneArg(((PyObject *)(&PyUnicode_Type)), __pyx_v_exc); if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 712, __pyx_L14_error) + __pyx_t_13 = __Pyx_PyObject_CallOneArg(((PyObject *)(&PyUnicode_Type)), __pyx_v_exc); if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 768, __pyx_L14_error) __Pyx_GOTREF(__pyx_t_13); __Pyx_INCREF(__pyx_v_pyparser->_payload_exception); __pyx_t_14 = __pyx_v_pyparser->_payload_exception; __pyx_t_15 = NULL; @@ -12915,7 +13706,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_body(struct http_parser *__pyx_ __pyx_t_12 = (__pyx_t_15) ? __Pyx_PyObject_Call2Args(__pyx_t_14, __pyx_t_15, __pyx_t_13) : __Pyx_PyObject_CallOneArg(__pyx_t_14, __pyx_t_13); __Pyx_XDECREF(__pyx_t_15); __pyx_t_15 = 0; __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0; - if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 712, __pyx_L14_error) + if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 768, __pyx_L14_error) __Pyx_GOTREF(__pyx_t_12); __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0; __pyx_t_14 = NULL; @@ -12931,12 +13722,12 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_body(struct http_parser *__pyx_ __pyx_t_6 = (__pyx_t_14) ? __Pyx_PyObject_Call2Args(__pyx_t_7, __pyx_t_14, __pyx_t_12) : __Pyx_PyObject_CallOneArg(__pyx_t_7, __pyx_t_12); __Pyx_XDECREF(__pyx_t_14); __pyx_t_14 = 0; __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0; - if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 712, __pyx_L14_error) + if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 768, __pyx_L14_error) __Pyx_GOTREF(__pyx_t_6); __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; - /* "aiohttp/_http_parser.pyx":711 + /* "aiohttp/_http_parser.pyx":767 * pyparser._payload.feed_data(body, length) * except BaseException as exc: * if pyparser._payload_exception is not None: # <<<<<<<<<<<<<< @@ -12946,7 +13737,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_body(struct http_parser *__pyx_ goto __pyx_L16; } - /* "aiohttp/_http_parser.pyx":714 + /* "aiohttp/_http_parser.pyx":770 * pyparser._payload.set_exception(pyparser._payload_exception(str(exc))) * else: * pyparser._payload.set_exception(exc) # <<<<<<<<<<<<<< @@ -12954,7 +13745,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_body(struct http_parser *__pyx_ * return -1 */ /*else*/ { - __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_v_pyparser->_payload, __pyx_n_s_set_exception); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 714, __pyx_L14_error) + __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_v_pyparser->_payload, __pyx_n_s_set_exception); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 770, __pyx_L14_error) __Pyx_GOTREF(__pyx_t_7); __pyx_t_12 = NULL; if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_7))) { @@ -12968,14 +13759,14 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_body(struct http_parser *__pyx_ } __pyx_t_6 = (__pyx_t_12) ? __Pyx_PyObject_Call2Args(__pyx_t_7, __pyx_t_12, __pyx_v_exc) : __Pyx_PyObject_CallOneArg(__pyx_t_7, __pyx_v_exc); __Pyx_XDECREF(__pyx_t_12); __pyx_t_12 = 0; - if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 714, __pyx_L14_error) + if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 770, __pyx_L14_error) __Pyx_GOTREF(__pyx_t_6); __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; } __pyx_L16:; - /* "aiohttp/_http_parser.pyx":715 + /* "aiohttp/_http_parser.pyx":771 * else: * pyparser._payload.set_exception(exc) * pyparser._payload_error = 1 # <<<<<<<<<<<<<< @@ -12984,7 +13775,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_body(struct http_parser *__pyx_ */ __pyx_v_pyparser->_payload_error = 1; - /* "aiohttp/_http_parser.pyx":716 + /* "aiohttp/_http_parser.pyx":772 * pyparser._payload.set_exception(exc) * pyparser._payload_error = 1 * return -1 # <<<<<<<<<<<<<< @@ -12998,7 +13789,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_body(struct http_parser *__pyx_ goto __pyx_L13_return; } - /* "aiohttp/_http_parser.pyx":710 + /* "aiohttp/_http_parser.pyx":766 * try: * pyparser._payload.feed_data(body, length) * except BaseException as exc: # <<<<<<<<<<<<<< @@ -13056,7 +13847,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_body(struct http_parser *__pyx_ goto __pyx_L5_except_error; __pyx_L5_except_error:; - /* "aiohttp/_http_parser.pyx":708 + /* "aiohttp/_http_parser.pyx":764 * cdef HttpParser pyparser = parser.data * cdef bytes body = at[:length] * try: # <<<<<<<<<<<<<< @@ -13076,10 +13867,10 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_body(struct http_parser *__pyx_ goto __pyx_L0; } - /* "aiohttp/_http_parser.pyx":704 + /* "aiohttp/_http_parser.pyx":760 * * - * cdef int cb_on_body(cparser.http_parser* parser, # <<<<<<<<<<<<<< + * cdef int cb_on_body(cparser.llhttp_t* parser, # <<<<<<<<<<<<<< * const char *at, size_t length) except -1: * cdef HttpParser pyparser = parser.data */ @@ -13105,15 +13896,15 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_body(struct http_parser *__pyx_ return __pyx_r; } -/* "aiohttp/_http_parser.pyx":721 +/* "aiohttp/_http_parser.pyx":777 * * - * cdef int cb_on_message_complete(cparser.http_parser* parser) except -1: # <<<<<<<<<<<<<< + * cdef int cb_on_message_complete(cparser.llhttp_t* parser) except -1: # <<<<<<<<<<<<<< * cdef HttpParser pyparser = parser.data * try: */ -static int __pyx_f_7aiohttp_12_http_parser_cb_on_message_complete(struct http_parser *__pyx_v_parser) { +static int __pyx_f_7aiohttp_12_http_parser_cb_on_message_complete(llhttp_t *__pyx_v_parser) { struct __pyx_obj_7aiohttp_12_http_parser_HttpParser *__pyx_v_pyparser = 0; PyObject *__pyx_v_exc = NULL; int __pyx_r; @@ -13130,9 +13921,9 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_message_complete(struct http_pa int __pyx_clineno = 0; __Pyx_RefNannySetupContext("cb_on_message_complete", 0); - /* "aiohttp/_http_parser.pyx":722 + /* "aiohttp/_http_parser.pyx":778 * - * cdef int cb_on_message_complete(cparser.http_parser* parser) except -1: + * cdef int cb_on_message_complete(cparser.llhttp_t* parser) except -1: * cdef HttpParser pyparser = parser.data # <<<<<<<<<<<<<< * try: * pyparser._started = False @@ -13142,8 +13933,8 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_message_complete(struct http_pa __pyx_v_pyparser = ((struct __pyx_obj_7aiohttp_12_http_parser_HttpParser *)__pyx_t_1); __pyx_t_1 = 0; - /* "aiohttp/_http_parser.pyx":723 - * cdef int cb_on_message_complete(cparser.http_parser* parser) except -1: + /* "aiohttp/_http_parser.pyx":779 + * cdef int cb_on_message_complete(cparser.llhttp_t* parser) except -1: * cdef HttpParser pyparser = parser.data * try: # <<<<<<<<<<<<<< * pyparser._started = False @@ -13158,7 +13949,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_message_complete(struct http_pa __Pyx_XGOTREF(__pyx_t_4); /*try:*/ { - /* "aiohttp/_http_parser.pyx":724 + /* "aiohttp/_http_parser.pyx":780 * cdef HttpParser pyparser = parser.data * try: * pyparser._started = False # <<<<<<<<<<<<<< @@ -13167,19 +13958,19 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_message_complete(struct http_pa */ __pyx_v_pyparser->_started = 0; - /* "aiohttp/_http_parser.pyx":725 + /* "aiohttp/_http_parser.pyx":781 * try: * pyparser._started = False * pyparser._on_message_complete() # <<<<<<<<<<<<<< * except BaseException as exc: * pyparser._last_error = exc */ - __pyx_t_1 = ((struct __pyx_vtabstruct_7aiohttp_12_http_parser_HttpParser *)__pyx_v_pyparser->__pyx_vtab)->_on_message_complete(__pyx_v_pyparser); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 725, __pyx_L3_error) + __pyx_t_1 = ((struct __pyx_vtabstruct_7aiohttp_12_http_parser_HttpParser *)__pyx_v_pyparser->__pyx_vtab)->_on_message_complete(__pyx_v_pyparser); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 781, __pyx_L3_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - /* "aiohttp/_http_parser.pyx":723 - * cdef int cb_on_message_complete(cparser.http_parser* parser) except -1: + /* "aiohttp/_http_parser.pyx":779 + * cdef int cb_on_message_complete(cparser.llhttp_t* parser) except -1: * cdef HttpParser pyparser = parser.data * try: # <<<<<<<<<<<<<< * pyparser._started = False @@ -13187,7 +13978,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_message_complete(struct http_pa */ } - /* "aiohttp/_http_parser.pyx":730 + /* "aiohttp/_http_parser.pyx":786 * return -1 * else: * return 0 # <<<<<<<<<<<<<< @@ -13201,7 +13992,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_message_complete(struct http_pa __pyx_L3_error:; __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; - /* "aiohttp/_http_parser.pyx":726 + /* "aiohttp/_http_parser.pyx":782 * pyparser._started = False * pyparser._on_message_complete() * except BaseException as exc: # <<<<<<<<<<<<<< @@ -13211,7 +14002,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_message_complete(struct http_pa __pyx_t_5 = __Pyx_PyErr_ExceptionMatches(__pyx_builtin_BaseException); if (__pyx_t_5) { __Pyx_AddTraceback("aiohttp._http_parser.cb_on_message_complete", __pyx_clineno, __pyx_lineno, __pyx_filename); - if (__Pyx_GetException(&__pyx_t_1, &__pyx_t_6, &__pyx_t_7) < 0) __PYX_ERR(0, 726, __pyx_L5_except_error) + if (__Pyx_GetException(&__pyx_t_1, &__pyx_t_6, &__pyx_t_7) < 0) __PYX_ERR(0, 782, __pyx_L5_except_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_GOTREF(__pyx_t_6); __Pyx_GOTREF(__pyx_t_7); @@ -13219,7 +14010,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_message_complete(struct http_pa __pyx_v_exc = __pyx_t_6; /*try:*/ { - /* "aiohttp/_http_parser.pyx":727 + /* "aiohttp/_http_parser.pyx":783 * pyparser._on_message_complete() * except BaseException as exc: * pyparser._last_error = exc # <<<<<<<<<<<<<< @@ -13232,7 +14023,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_message_complete(struct http_pa __Pyx_DECREF(__pyx_v_pyparser->_last_error); __pyx_v_pyparser->_last_error = __pyx_v_exc; - /* "aiohttp/_http_parser.pyx":728 + /* "aiohttp/_http_parser.pyx":784 * except BaseException as exc: * pyparser._last_error = exc * return -1 # <<<<<<<<<<<<<< @@ -13246,7 +14037,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_message_complete(struct http_pa goto __pyx_L13_return; } - /* "aiohttp/_http_parser.pyx":726 + /* "aiohttp/_http_parser.pyx":782 * pyparser._started = False * pyparser._on_message_complete() * except BaseException as exc: # <<<<<<<<<<<<<< @@ -13266,8 +14057,8 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_message_complete(struct http_pa goto __pyx_L5_except_error; __pyx_L5_except_error:; - /* "aiohttp/_http_parser.pyx":723 - * cdef int cb_on_message_complete(cparser.http_parser* parser) except -1: + /* "aiohttp/_http_parser.pyx":779 + * cdef int cb_on_message_complete(cparser.llhttp_t* parser) except -1: * cdef HttpParser pyparser = parser.data * try: # <<<<<<<<<<<<<< * pyparser._started = False @@ -13286,10 +14077,10 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_message_complete(struct http_pa goto __pyx_L0; } - /* "aiohttp/_http_parser.pyx":721 + /* "aiohttp/_http_parser.pyx":777 * * - * cdef int cb_on_message_complete(cparser.http_parser* parser) except -1: # <<<<<<<<<<<<<< + * cdef int cb_on_message_complete(cparser.llhttp_t* parser) except -1: # <<<<<<<<<<<<<< * cdef HttpParser pyparser = parser.data * try: */ @@ -13308,15 +14099,15 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_message_complete(struct http_pa return __pyx_r; } -/* "aiohttp/_http_parser.pyx":733 +/* "aiohttp/_http_parser.pyx":789 * * - * cdef int cb_on_chunk_header(cparser.http_parser* parser) except -1: # <<<<<<<<<<<<<< + * cdef int cb_on_chunk_header(cparser.llhttp_t* parser) except -1: # <<<<<<<<<<<<<< * cdef HttpParser pyparser = parser.data * try: */ -static int __pyx_f_7aiohttp_12_http_parser_cb_on_chunk_header(struct http_parser *__pyx_v_parser) { +static int __pyx_f_7aiohttp_12_http_parser_cb_on_chunk_header(llhttp_t *__pyx_v_parser) { struct __pyx_obj_7aiohttp_12_http_parser_HttpParser *__pyx_v_pyparser = 0; PyObject *__pyx_v_exc = NULL; int __pyx_r; @@ -13333,9 +14124,9 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_chunk_header(struct http_parser int __pyx_clineno = 0; __Pyx_RefNannySetupContext("cb_on_chunk_header", 0); - /* "aiohttp/_http_parser.pyx":734 + /* "aiohttp/_http_parser.pyx":790 * - * cdef int cb_on_chunk_header(cparser.http_parser* parser) except -1: + * cdef int cb_on_chunk_header(cparser.llhttp_t* parser) except -1: * cdef HttpParser pyparser = parser.data # <<<<<<<<<<<<<< * try: * pyparser._on_chunk_header() @@ -13345,8 +14136,8 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_chunk_header(struct http_parser __pyx_v_pyparser = ((struct __pyx_obj_7aiohttp_12_http_parser_HttpParser *)__pyx_t_1); __pyx_t_1 = 0; - /* "aiohttp/_http_parser.pyx":735 - * cdef int cb_on_chunk_header(cparser.http_parser* parser) except -1: + /* "aiohttp/_http_parser.pyx":791 + * cdef int cb_on_chunk_header(cparser.llhttp_t* parser) except -1: * cdef HttpParser pyparser = parser.data * try: # <<<<<<<<<<<<<< * pyparser._on_chunk_header() @@ -13361,19 +14152,19 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_chunk_header(struct http_parser __Pyx_XGOTREF(__pyx_t_4); /*try:*/ { - /* "aiohttp/_http_parser.pyx":736 + /* "aiohttp/_http_parser.pyx":792 * cdef HttpParser pyparser = parser.data * try: * pyparser._on_chunk_header() # <<<<<<<<<<<<<< * except BaseException as exc: * pyparser._last_error = exc */ - __pyx_t_1 = ((struct __pyx_vtabstruct_7aiohttp_12_http_parser_HttpParser *)__pyx_v_pyparser->__pyx_vtab)->_on_chunk_header(__pyx_v_pyparser); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 736, __pyx_L3_error) + __pyx_t_1 = ((struct __pyx_vtabstruct_7aiohttp_12_http_parser_HttpParser *)__pyx_v_pyparser->__pyx_vtab)->_on_chunk_header(__pyx_v_pyparser); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 792, __pyx_L3_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - /* "aiohttp/_http_parser.pyx":735 - * cdef int cb_on_chunk_header(cparser.http_parser* parser) except -1: + /* "aiohttp/_http_parser.pyx":791 + * cdef int cb_on_chunk_header(cparser.llhttp_t* parser) except -1: * cdef HttpParser pyparser = parser.data * try: # <<<<<<<<<<<<<< * pyparser._on_chunk_header() @@ -13381,7 +14172,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_chunk_header(struct http_parser */ } - /* "aiohttp/_http_parser.pyx":741 + /* "aiohttp/_http_parser.pyx":797 * return -1 * else: * return 0 # <<<<<<<<<<<<<< @@ -13395,7 +14186,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_chunk_header(struct http_parser __pyx_L3_error:; __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; - /* "aiohttp/_http_parser.pyx":737 + /* "aiohttp/_http_parser.pyx":793 * try: * pyparser._on_chunk_header() * except BaseException as exc: # <<<<<<<<<<<<<< @@ -13405,7 +14196,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_chunk_header(struct http_parser __pyx_t_5 = __Pyx_PyErr_ExceptionMatches(__pyx_builtin_BaseException); if (__pyx_t_5) { __Pyx_AddTraceback("aiohttp._http_parser.cb_on_chunk_header", __pyx_clineno, __pyx_lineno, __pyx_filename); - if (__Pyx_GetException(&__pyx_t_1, &__pyx_t_6, &__pyx_t_7) < 0) __PYX_ERR(0, 737, __pyx_L5_except_error) + if (__Pyx_GetException(&__pyx_t_1, &__pyx_t_6, &__pyx_t_7) < 0) __PYX_ERR(0, 793, __pyx_L5_except_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_GOTREF(__pyx_t_6); __Pyx_GOTREF(__pyx_t_7); @@ -13413,7 +14204,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_chunk_header(struct http_parser __pyx_v_exc = __pyx_t_6; /*try:*/ { - /* "aiohttp/_http_parser.pyx":738 + /* "aiohttp/_http_parser.pyx":794 * pyparser._on_chunk_header() * except BaseException as exc: * pyparser._last_error = exc # <<<<<<<<<<<<<< @@ -13426,7 +14217,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_chunk_header(struct http_parser __Pyx_DECREF(__pyx_v_pyparser->_last_error); __pyx_v_pyparser->_last_error = __pyx_v_exc; - /* "aiohttp/_http_parser.pyx":739 + /* "aiohttp/_http_parser.pyx":795 * except BaseException as exc: * pyparser._last_error = exc * return -1 # <<<<<<<<<<<<<< @@ -13440,7 +14231,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_chunk_header(struct http_parser goto __pyx_L13_return; } - /* "aiohttp/_http_parser.pyx":737 + /* "aiohttp/_http_parser.pyx":793 * try: * pyparser._on_chunk_header() * except BaseException as exc: # <<<<<<<<<<<<<< @@ -13460,8 +14251,8 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_chunk_header(struct http_parser goto __pyx_L5_except_error; __pyx_L5_except_error:; - /* "aiohttp/_http_parser.pyx":735 - * cdef int cb_on_chunk_header(cparser.http_parser* parser) except -1: + /* "aiohttp/_http_parser.pyx":791 + * cdef int cb_on_chunk_header(cparser.llhttp_t* parser) except -1: * cdef HttpParser pyparser = parser.data * try: # <<<<<<<<<<<<<< * pyparser._on_chunk_header() @@ -13480,10 +14271,10 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_chunk_header(struct http_parser goto __pyx_L0; } - /* "aiohttp/_http_parser.pyx":733 + /* "aiohttp/_http_parser.pyx":789 * * - * cdef int cb_on_chunk_header(cparser.http_parser* parser) except -1: # <<<<<<<<<<<<<< + * cdef int cb_on_chunk_header(cparser.llhttp_t* parser) except -1: # <<<<<<<<<<<<<< * cdef HttpParser pyparser = parser.data * try: */ @@ -13502,15 +14293,15 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_chunk_header(struct http_parser return __pyx_r; } -/* "aiohttp/_http_parser.pyx":744 +/* "aiohttp/_http_parser.pyx":800 * * - * cdef int cb_on_chunk_complete(cparser.http_parser* parser) except -1: # <<<<<<<<<<<<<< + * cdef int cb_on_chunk_complete(cparser.llhttp_t* parser) except -1: # <<<<<<<<<<<<<< * cdef HttpParser pyparser = parser.data * try: */ -static int __pyx_f_7aiohttp_12_http_parser_cb_on_chunk_complete(struct http_parser *__pyx_v_parser) { +static int __pyx_f_7aiohttp_12_http_parser_cb_on_chunk_complete(llhttp_t *__pyx_v_parser) { struct __pyx_obj_7aiohttp_12_http_parser_HttpParser *__pyx_v_pyparser = 0; PyObject *__pyx_v_exc = NULL; int __pyx_r; @@ -13527,9 +14318,9 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_chunk_complete(struct http_pars int __pyx_clineno = 0; __Pyx_RefNannySetupContext("cb_on_chunk_complete", 0); - /* "aiohttp/_http_parser.pyx":745 + /* "aiohttp/_http_parser.pyx":801 * - * cdef int cb_on_chunk_complete(cparser.http_parser* parser) except -1: + * cdef int cb_on_chunk_complete(cparser.llhttp_t* parser) except -1: * cdef HttpParser pyparser = parser.data # <<<<<<<<<<<<<< * try: * pyparser._on_chunk_complete() @@ -13539,8 +14330,8 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_chunk_complete(struct http_pars __pyx_v_pyparser = ((struct __pyx_obj_7aiohttp_12_http_parser_HttpParser *)__pyx_t_1); __pyx_t_1 = 0; - /* "aiohttp/_http_parser.pyx":746 - * cdef int cb_on_chunk_complete(cparser.http_parser* parser) except -1: + /* "aiohttp/_http_parser.pyx":802 + * cdef int cb_on_chunk_complete(cparser.llhttp_t* parser) except -1: * cdef HttpParser pyparser = parser.data * try: # <<<<<<<<<<<<<< * pyparser._on_chunk_complete() @@ -13555,19 +14346,19 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_chunk_complete(struct http_pars __Pyx_XGOTREF(__pyx_t_4); /*try:*/ { - /* "aiohttp/_http_parser.pyx":747 + /* "aiohttp/_http_parser.pyx":803 * cdef HttpParser pyparser = parser.data * try: * pyparser._on_chunk_complete() # <<<<<<<<<<<<<< * except BaseException as exc: * pyparser._last_error = exc */ - __pyx_t_1 = ((struct __pyx_vtabstruct_7aiohttp_12_http_parser_HttpParser *)__pyx_v_pyparser->__pyx_vtab)->_on_chunk_complete(__pyx_v_pyparser); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 747, __pyx_L3_error) + __pyx_t_1 = ((struct __pyx_vtabstruct_7aiohttp_12_http_parser_HttpParser *)__pyx_v_pyparser->__pyx_vtab)->_on_chunk_complete(__pyx_v_pyparser); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 803, __pyx_L3_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - /* "aiohttp/_http_parser.pyx":746 - * cdef int cb_on_chunk_complete(cparser.http_parser* parser) except -1: + /* "aiohttp/_http_parser.pyx":802 + * cdef int cb_on_chunk_complete(cparser.llhttp_t* parser) except -1: * cdef HttpParser pyparser = parser.data * try: # <<<<<<<<<<<<<< * pyparser._on_chunk_complete() @@ -13575,7 +14366,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_chunk_complete(struct http_pars */ } - /* "aiohttp/_http_parser.pyx":752 + /* "aiohttp/_http_parser.pyx":808 * return -1 * else: * return 0 # <<<<<<<<<<<<<< @@ -13589,7 +14380,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_chunk_complete(struct http_pars __pyx_L3_error:; __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; - /* "aiohttp/_http_parser.pyx":748 + /* "aiohttp/_http_parser.pyx":804 * try: * pyparser._on_chunk_complete() * except BaseException as exc: # <<<<<<<<<<<<<< @@ -13599,7 +14390,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_chunk_complete(struct http_pars __pyx_t_5 = __Pyx_PyErr_ExceptionMatches(__pyx_builtin_BaseException); if (__pyx_t_5) { __Pyx_AddTraceback("aiohttp._http_parser.cb_on_chunk_complete", __pyx_clineno, __pyx_lineno, __pyx_filename); - if (__Pyx_GetException(&__pyx_t_1, &__pyx_t_6, &__pyx_t_7) < 0) __PYX_ERR(0, 748, __pyx_L5_except_error) + if (__Pyx_GetException(&__pyx_t_1, &__pyx_t_6, &__pyx_t_7) < 0) __PYX_ERR(0, 804, __pyx_L5_except_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_GOTREF(__pyx_t_6); __Pyx_GOTREF(__pyx_t_7); @@ -13607,7 +14398,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_chunk_complete(struct http_pars __pyx_v_exc = __pyx_t_6; /*try:*/ { - /* "aiohttp/_http_parser.pyx":749 + /* "aiohttp/_http_parser.pyx":805 * pyparser._on_chunk_complete() * except BaseException as exc: * pyparser._last_error = exc # <<<<<<<<<<<<<< @@ -13620,7 +14411,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_chunk_complete(struct http_pars __Pyx_DECREF(__pyx_v_pyparser->_last_error); __pyx_v_pyparser->_last_error = __pyx_v_exc; - /* "aiohttp/_http_parser.pyx":750 + /* "aiohttp/_http_parser.pyx":806 * except BaseException as exc: * pyparser._last_error = exc * return -1 # <<<<<<<<<<<<<< @@ -13634,7 +14425,7 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_chunk_complete(struct http_pars goto __pyx_L13_return; } - /* "aiohttp/_http_parser.pyx":748 + /* "aiohttp/_http_parser.pyx":804 * try: * pyparser._on_chunk_complete() * except BaseException as exc: # <<<<<<<<<<<<<< @@ -13654,8 +14445,8 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_chunk_complete(struct http_pars goto __pyx_L5_except_error; __pyx_L5_except_error:; - /* "aiohttp/_http_parser.pyx":746 - * cdef int cb_on_chunk_complete(cparser.http_parser* parser) except -1: + /* "aiohttp/_http_parser.pyx":802 + * cdef int cb_on_chunk_complete(cparser.llhttp_t* parser) except -1: * cdef HttpParser pyparser = parser.data * try: # <<<<<<<<<<<<<< * pyparser._on_chunk_complete() @@ -13674,10 +14465,10 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_chunk_complete(struct http_pars goto __pyx_L0; } - /* "aiohttp/_http_parser.pyx":744 + /* "aiohttp/_http_parser.pyx":800 * * - * cdef int cb_on_chunk_complete(cparser.http_parser* parser) except -1: # <<<<<<<<<<<<<< + * cdef int cb_on_chunk_complete(cparser.llhttp_t* parser) except -1: # <<<<<<<<<<<<<< * cdef HttpParser pyparser = parser.data * try: */ @@ -13696,1328 +14487,383 @@ static int __pyx_f_7aiohttp_12_http_parser_cb_on_chunk_complete(struct http_pars return __pyx_r; } -/* "aiohttp/_http_parser.pyx":755 +/* "aiohttp/_http_parser.pyx":811 * * - * cdef parser_error_from_errno(cparser.http_errno errno): # <<<<<<<<<<<<<< - * cdef bytes desc = cparser.http_errno_description(errno) - * + * cdef parser_error_from_errno(cparser.llhttp_t* parser, data, pointer): # <<<<<<<<<<<<<< + * cdef cparser.llhttp_errno_t errno = cparser.llhttp_get_errno(parser) + * cdef bytes desc = cparser.llhttp_get_error_reason(parser) */ -static PyObject *__pyx_f_7aiohttp_12_http_parser_parser_error_from_errno(enum http_errno __pyx_v_errno) { +static PyObject *__pyx_f_7aiohttp_12_http_parser_parser_error_from_errno(llhttp_t *__pyx_v_parser, PyObject *__pyx_v_data, PyObject *__pyx_v_pointer) { + llhttp_errno_t __pyx_v_errno; PyObject *__pyx_v_desc = 0; - PyObject *__pyx_v_cls = NULL; + PyObject *__pyx_v_err_msg = NULL; PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; PyObject *__pyx_t_2 = NULL; PyObject *__pyx_t_3 = NULL; PyObject *__pyx_t_4 = NULL; + int __pyx_t_5; + PyObject *__pyx_t_6 = NULL; int __pyx_lineno = 0; const char *__pyx_filename = NULL; int __pyx_clineno = 0; __Pyx_RefNannySetupContext("parser_error_from_errno", 0); - /* "aiohttp/_http_parser.pyx":756 + /* "aiohttp/_http_parser.pyx":812 + * + * cdef parser_error_from_errno(cparser.llhttp_t* parser, data, pointer): + * cdef cparser.llhttp_errno_t errno = cparser.llhttp_get_errno(parser) # <<<<<<<<<<<<<< + * cdef bytes desc = cparser.llhttp_get_error_reason(parser) * - * cdef parser_error_from_errno(cparser.http_errno errno): - * cdef bytes desc = cparser.http_errno_description(errno) # <<<<<<<<<<<<<< + */ + __pyx_v_errno = llhttp_get_errno(__pyx_v_parser); + + /* "aiohttp/_http_parser.pyx":813 + * cdef parser_error_from_errno(cparser.llhttp_t* parser, data, pointer): + * cdef cparser.llhttp_errno_t errno = cparser.llhttp_get_errno(parser) + * cdef bytes desc = cparser.llhttp_get_error_reason(parser) # <<<<<<<<<<<<<< * - * if errno in (cparser.HPE_CB_message_begin, + * err_msg = "{}:\n\n {!r}\n {}".format(desc.decode("latin-1"), data, pointer) */ - __pyx_t_1 = __Pyx_PyBytes_FromString(http_errno_description(__pyx_v_errno)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 756, __pyx_L1_error) + __pyx_t_1 = __Pyx_PyBytes_FromString(llhttp_get_error_reason(__pyx_v_parser)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 813, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_v_desc = ((PyObject*)__pyx_t_1); __pyx_t_1 = 0; - /* "aiohttp/_http_parser.pyx":758 - * cdef bytes desc = cparser.http_errno_description(errno) + /* "aiohttp/_http_parser.pyx":815 + * cdef bytes desc = cparser.llhttp_get_error_reason(parser) * - * if errno in (cparser.HPE_CB_message_begin, # <<<<<<<<<<<<<< - * cparser.HPE_CB_url, - * cparser.HPE_CB_header_field, - */ - switch (__pyx_v_errno) { - case HPE_CB_message_begin: - case HPE_CB_url: - - /* "aiohttp/_http_parser.pyx":759 + * err_msg = "{}:\n\n {!r}\n {}".format(desc.decode("latin-1"), data, pointer) # <<<<<<<<<<<<<< * - * if errno in (cparser.HPE_CB_message_begin, - * cparser.HPE_CB_url, # <<<<<<<<<<<<<< - * cparser.HPE_CB_header_field, - * cparser.HPE_CB_header_value, - */ - case HPE_CB_header_field: - - /* "aiohttp/_http_parser.pyx":760 - * if errno in (cparser.HPE_CB_message_begin, - * cparser.HPE_CB_url, - * cparser.HPE_CB_header_field, # <<<<<<<<<<<<<< - * cparser.HPE_CB_header_value, - * cparser.HPE_CB_headers_complete, + * if errno in {cparser.HPE_CB_MESSAGE_BEGIN, */ - case HPE_CB_header_value: - - /* "aiohttp/_http_parser.pyx":761 - * cparser.HPE_CB_url, - * cparser.HPE_CB_header_field, - * cparser.HPE_CB_header_value, # <<<<<<<<<<<<<< - * cparser.HPE_CB_headers_complete, - * cparser.HPE_CB_body, - */ - case HPE_CB_headers_complete: - - /* "aiohttp/_http_parser.pyx":762 - * cparser.HPE_CB_header_field, - * cparser.HPE_CB_header_value, - * cparser.HPE_CB_headers_complete, # <<<<<<<<<<<<<< - * cparser.HPE_CB_body, - * cparser.HPE_CB_message_complete, - */ - case HPE_CB_body: - - /* "aiohttp/_http_parser.pyx":763 - * cparser.HPE_CB_header_value, - * cparser.HPE_CB_headers_complete, - * cparser.HPE_CB_body, # <<<<<<<<<<<<<< - * cparser.HPE_CB_message_complete, - * cparser.HPE_CB_status, - */ - case HPE_CB_message_complete: - - /* "aiohttp/_http_parser.pyx":764 - * cparser.HPE_CB_headers_complete, - * cparser.HPE_CB_body, - * cparser.HPE_CB_message_complete, # <<<<<<<<<<<<<< - * cparser.HPE_CB_status, - * cparser.HPE_CB_chunk_header, - */ - case HPE_CB_status: - - /* "aiohttp/_http_parser.pyx":765 - * cparser.HPE_CB_body, - * cparser.HPE_CB_message_complete, - * cparser.HPE_CB_status, # <<<<<<<<<<<<<< - * cparser.HPE_CB_chunk_header, - * cparser.HPE_CB_chunk_complete): - */ - case HPE_CB_chunk_header: - - /* "aiohttp/_http_parser.pyx":766 - * cparser.HPE_CB_message_complete, - * cparser.HPE_CB_status, - * cparser.HPE_CB_chunk_header, # <<<<<<<<<<<<<< - * cparser.HPE_CB_chunk_complete): - * cls = BadHttpMessage - */ - case HPE_CB_chunk_complete: - - /* "aiohttp/_http_parser.pyx":768 - * cparser.HPE_CB_chunk_header, - * cparser.HPE_CB_chunk_complete): - * cls = BadHttpMessage # <<<<<<<<<<<<<< - * - * elif errno == cparser.HPE_INVALID_STATUS: - */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_BadHttpMessage); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 768, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_v_cls = __pyx_t_1; - __pyx_t_1 = 0; - - /* "aiohttp/_http_parser.pyx":758 - * cdef bytes desc = cparser.http_errno_description(errno) - * - * if errno in (cparser.HPE_CB_message_begin, # <<<<<<<<<<<<<< - * cparser.HPE_CB_url, - * cparser.HPE_CB_header_field, - */ - break; - case HPE_INVALID_STATUS: - - /* "aiohttp/_http_parser.pyx":771 - * - * elif errno == cparser.HPE_INVALID_STATUS: - * cls = BadStatusLine # <<<<<<<<<<<<<< - * - * elif errno == cparser.HPE_INVALID_METHOD: - */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_BadStatusLine); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 771, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_v_cls = __pyx_t_1; - __pyx_t_1 = 0; - - /* "aiohttp/_http_parser.pyx":770 - * cls = BadHttpMessage - * - * elif errno == cparser.HPE_INVALID_STATUS: # <<<<<<<<<<<<<< - * cls = BadStatusLine - * - */ - break; - case HPE_INVALID_METHOD: - - /* "aiohttp/_http_parser.pyx":774 - * - * elif errno == cparser.HPE_INVALID_METHOD: - * cls = BadStatusLine # <<<<<<<<<<<<<< - * - * elif errno == cparser.HPE_INVALID_URL: - */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_BadStatusLine); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 774, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_v_cls = __pyx_t_1; - __pyx_t_1 = 0; - - /* "aiohttp/_http_parser.pyx":773 - * cls = BadStatusLine - * - * elif errno == cparser.HPE_INVALID_METHOD: # <<<<<<<<<<<<<< - * cls = BadStatusLine - * - */ - break; - case HPE_INVALID_URL: - - /* "aiohttp/_http_parser.pyx":777 - * - * elif errno == cparser.HPE_INVALID_URL: - * cls = InvalidURLError # <<<<<<<<<<<<<< - * - * else: - */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_InvalidURLError); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 777, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_v_cls = __pyx_t_1; - __pyx_t_1 = 0; - - /* "aiohttp/_http_parser.pyx":776 - * cls = BadStatusLine - * - * elif errno == cparser.HPE_INVALID_URL: # <<<<<<<<<<<<<< - * cls = InvalidURLError - * - */ - break; - default: - - /* "aiohttp/_http_parser.pyx":780 - * - * else: - * cls = BadHttpMessage # <<<<<<<<<<<<<< - * - * return cls(desc.decode('latin-1')) - */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_BadHttpMessage); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 780, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_v_cls = __pyx_t_1; - __pyx_t_1 = 0; - break; - } - - /* "aiohttp/_http_parser.pyx":782 - * cls = BadHttpMessage - * - * return cls(desc.decode('latin-1')) # <<<<<<<<<<<<<< - * - * - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_2 = __Pyx_decode_bytes(__pyx_v_desc, 0, PY_SSIZE_T_MAX, NULL, NULL, PyUnicode_DecodeLatin1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 782, __pyx_L1_error) + __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_kp_u_r, __pyx_n_s_format); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 815, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); - __Pyx_INCREF(__pyx_v_cls); - __pyx_t_3 = __pyx_v_cls; __pyx_t_4 = NULL; - if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) { - __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3); + __pyx_t_3 = __Pyx_decode_bytes(__pyx_v_desc, 0, PY_SSIZE_T_MAX, NULL, NULL, PyUnicode_DecodeLatin1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 815, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_4 = NULL; + __pyx_t_5 = 0; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) { + __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_2); if (likely(__pyx_t_4)) { - PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3); + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2); __Pyx_INCREF(__pyx_t_4); __Pyx_INCREF(function); - __Pyx_DECREF_SET(__pyx_t_3, function); - } - } - __pyx_t_1 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_4, __pyx_t_2) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_2); - __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 782, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __pyx_r = __pyx_t_1; - __pyx_t_1 = 0; - goto __pyx_L0; - - /* "aiohttp/_http_parser.pyx":755 - * - * - * cdef parser_error_from_errno(cparser.http_errno errno): # <<<<<<<<<<<<<< - * cdef bytes desc = cparser.http_errno_description(errno) - * - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_XDECREF(__pyx_t_2); - __Pyx_XDECREF(__pyx_t_3); - __Pyx_XDECREF(__pyx_t_4); - __Pyx_AddTraceback("aiohttp._http_parser.parser_error_from_errno", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = 0; - __pyx_L0:; - __Pyx_XDECREF(__pyx_v_desc); - __Pyx_XDECREF(__pyx_v_cls); - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "aiohttp/_http_parser.pyx":785 - * - * - * def parse_url(url): # <<<<<<<<<<<<<< - * cdef: - * Py_buffer py_buf - */ - -/* Python wrapper */ -static PyObject *__pyx_pw_7aiohttp_12_http_parser_1parse_url(PyObject *__pyx_self, PyObject *__pyx_v_url); /*proto*/ -static PyMethodDef __pyx_mdef_7aiohttp_12_http_parser_1parse_url = {"parse_url", (PyCFunction)__pyx_pw_7aiohttp_12_http_parser_1parse_url, METH_O, 0}; -static PyObject *__pyx_pw_7aiohttp_12_http_parser_1parse_url(PyObject *__pyx_self, PyObject *__pyx_v_url) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("parse_url (wrapper)", 0); - __pyx_r = __pyx_pf_7aiohttp_12_http_parser_parse_url(__pyx_self, ((PyObject *)__pyx_v_url)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf_7aiohttp_12_http_parser_parse_url(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_url) { - Py_buffer __pyx_v_py_buf; - char *__pyx_v_buf_data; - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - int __pyx_t_1; - PyObject *__pyx_t_2 = NULL; - int __pyx_t_3; - char const *__pyx_t_4; - PyObject *__pyx_t_5 = NULL; - PyObject *__pyx_t_6 = NULL; - PyObject *__pyx_t_7 = NULL; - PyObject *__pyx_t_8 = NULL; - PyObject *__pyx_t_9 = NULL; - PyObject *__pyx_t_10 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("parse_url", 0); - - /* "aiohttp/_http_parser.pyx":790 - * char* buf_data - * - * PyObject_GetBuffer(url, &py_buf, PyBUF_SIMPLE) # <<<<<<<<<<<<<< - * try: - * buf_data = py_buf.buf - */ - __pyx_t_1 = PyObject_GetBuffer(__pyx_v_url, (&__pyx_v_py_buf), PyBUF_SIMPLE); if (unlikely(__pyx_t_1 == ((int)-1))) __PYX_ERR(0, 790, __pyx_L1_error) - - /* "aiohttp/_http_parser.pyx":791 - * - * PyObject_GetBuffer(url, &py_buf, PyBUF_SIMPLE) - * try: # <<<<<<<<<<<<<< - * buf_data = py_buf.buf - * return _parse_url(buf_data, py_buf.len) - */ - /*try:*/ { - - /* "aiohttp/_http_parser.pyx":792 - * PyObject_GetBuffer(url, &py_buf, PyBUF_SIMPLE) - * try: - * buf_data = py_buf.buf # <<<<<<<<<<<<<< - * return _parse_url(buf_data, py_buf.len) - * finally: - */ - __pyx_v_buf_data = ((char *)__pyx_v_py_buf.buf); - - /* "aiohttp/_http_parser.pyx":793 - * try: - * buf_data = py_buf.buf - * return _parse_url(buf_data, py_buf.len) # <<<<<<<<<<<<<< - * finally: - * PyBuffer_Release(&py_buf) - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_2 = __pyx_f_7aiohttp_12_http_parser__parse_url(__pyx_v_buf_data, __pyx_v_py_buf.len); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 793, __pyx_L4_error) - __Pyx_GOTREF(__pyx_t_2); - __pyx_r = __pyx_t_2; - __pyx_t_2 = 0; - goto __pyx_L3_return; - } - - /* "aiohttp/_http_parser.pyx":795 - * return _parse_url(buf_data, py_buf.len) - * finally: - * PyBuffer_Release(&py_buf) # <<<<<<<<<<<<<< - * - * - */ - /*finally:*/ { - __pyx_L4_error:; - /*exception exit:*/{ - __Pyx_PyThreadState_declare - __Pyx_PyThreadState_assign - __pyx_t_5 = 0; __pyx_t_6 = 0; __pyx_t_7 = 0; __pyx_t_8 = 0; __pyx_t_9 = 0; __pyx_t_10 = 0; - __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; - if (PY_MAJOR_VERSION >= 3) __Pyx_ExceptionSwap(&__pyx_t_8, &__pyx_t_9, &__pyx_t_10); - if ((PY_MAJOR_VERSION < 3) || unlikely(__Pyx_GetException(&__pyx_t_5, &__pyx_t_6, &__pyx_t_7) < 0)) __Pyx_ErrFetch(&__pyx_t_5, &__pyx_t_6, &__pyx_t_7); - __Pyx_XGOTREF(__pyx_t_5); - __Pyx_XGOTREF(__pyx_t_6); - __Pyx_XGOTREF(__pyx_t_7); - __Pyx_XGOTREF(__pyx_t_8); - __Pyx_XGOTREF(__pyx_t_9); - __Pyx_XGOTREF(__pyx_t_10); - __pyx_t_1 = __pyx_lineno; __pyx_t_3 = __pyx_clineno; __pyx_t_4 = __pyx_filename; - { - PyBuffer_Release((&__pyx_v_py_buf)); - } - if (PY_MAJOR_VERSION >= 3) { - __Pyx_XGIVEREF(__pyx_t_8); - __Pyx_XGIVEREF(__pyx_t_9); - __Pyx_XGIVEREF(__pyx_t_10); - __Pyx_ExceptionReset(__pyx_t_8, __pyx_t_9, __pyx_t_10); - } - __Pyx_XGIVEREF(__pyx_t_5); - __Pyx_XGIVEREF(__pyx_t_6); - __Pyx_XGIVEREF(__pyx_t_7); - __Pyx_ErrRestore(__pyx_t_5, __pyx_t_6, __pyx_t_7); - __pyx_t_5 = 0; __pyx_t_6 = 0; __pyx_t_7 = 0; __pyx_t_8 = 0; __pyx_t_9 = 0; __pyx_t_10 = 0; - __pyx_lineno = __pyx_t_1; __pyx_clineno = __pyx_t_3; __pyx_filename = __pyx_t_4; - goto __pyx_L1_error; - } - __pyx_L3_return: { - __pyx_t_10 = __pyx_r; - __pyx_r = 0; - PyBuffer_Release((&__pyx_v_py_buf)); - __pyx_r = __pyx_t_10; - __pyx_t_10 = 0; - goto __pyx_L0; + __Pyx_DECREF_SET(__pyx_t_2, function); + __pyx_t_5 = 1; } - } - - /* "aiohttp/_http_parser.pyx":785 - * - * - * def parse_url(url): # <<<<<<<<<<<<<< - * cdef: - * Py_buffer py_buf - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_2); - __Pyx_AddTraceback("aiohttp._http_parser.parse_url", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "aiohttp/_http_parser.pyx":798 - * - * - * cdef _parse_url(char* buf_data, size_t length): # <<<<<<<<<<<<<< - * cdef: - * cparser.http_parser_url* parsed - */ - -static PyObject *__pyx_f_7aiohttp_12_http_parser__parse_url(char *__pyx_v_buf_data, size_t __pyx_v_length) { - struct http_parser_url *__pyx_v_parsed; - int __pyx_v_res; - PyObject *__pyx_v_schema = 0; - PyObject *__pyx_v_host = 0; - PyObject *__pyx_v_port = 0; - PyObject *__pyx_v_path = 0; - PyObject *__pyx_v_query = 0; - PyObject *__pyx_v_fragment = 0; - PyObject *__pyx_v_user = 0; - PyObject *__pyx_v_password = 0; - PyObject *__pyx_v_userinfo = 0; - CYTHON_UNUSED PyObject *__pyx_v_result = 0; - int __pyx_v_off; - int __pyx_v_ln; - CYTHON_UNUSED PyObject *__pyx_v_sep = NULL; - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - int __pyx_t_1; - uint16_t __pyx_t_2; - PyObject *__pyx_t_3 = NULL; - PyObject *__pyx_t_4 = NULL; - PyObject *__pyx_t_5 = NULL; - PyObject *__pyx_t_6 = NULL; - PyObject *__pyx_t_7 = NULL; - PyObject *(*__pyx_t_8)(PyObject *); - PyObject *__pyx_t_9 = NULL; - int __pyx_t_10; - int __pyx_t_11; - char const *__pyx_t_12; - PyObject *__pyx_t_13 = NULL; - PyObject *__pyx_t_14 = NULL; - PyObject *__pyx_t_15 = NULL; - PyObject *__pyx_t_16 = NULL; - PyObject *__pyx_t_17 = NULL; - PyObject *__pyx_t_18 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("_parse_url", 0); - - /* "aiohttp/_http_parser.pyx":802 - * cparser.http_parser_url* parsed - * int res - * str schema = None # <<<<<<<<<<<<<< - * str host = None - * object port = None - */ - __Pyx_INCREF(Py_None); - __pyx_v_schema = ((PyObject*)Py_None); - - /* "aiohttp/_http_parser.pyx":803 - * int res - * str schema = None - * str host = None # <<<<<<<<<<<<<< - * object port = None - * str path = None - */ - __Pyx_INCREF(Py_None); - __pyx_v_host = ((PyObject*)Py_None); - - /* "aiohttp/_http_parser.pyx":804 - * str schema = None - * str host = None - * object port = None # <<<<<<<<<<<<<< - * str path = None - * str query = None - */ - __Pyx_INCREF(Py_None); - __pyx_v_port = Py_None; - - /* "aiohttp/_http_parser.pyx":805 - * str host = None - * object port = None - * str path = None # <<<<<<<<<<<<<< - * str query = None - * str fragment = None - */ - __Pyx_INCREF(Py_None); - __pyx_v_path = ((PyObject*)Py_None); - - /* "aiohttp/_http_parser.pyx":806 - * object port = None - * str path = None - * str query = None # <<<<<<<<<<<<<< - * str fragment = None - * str user = None - */ - __Pyx_INCREF(Py_None); - __pyx_v_query = ((PyObject*)Py_None); - - /* "aiohttp/_http_parser.pyx":807 - * str path = None - * str query = None - * str fragment = None # <<<<<<<<<<<<<< - * str user = None - * str password = None - */ - __Pyx_INCREF(Py_None); - __pyx_v_fragment = ((PyObject*)Py_None); - - /* "aiohttp/_http_parser.pyx":808 - * str query = None - * str fragment = None - * str user = None # <<<<<<<<<<<<<< - * str password = None - * str userinfo = None - */ - __Pyx_INCREF(Py_None); - __pyx_v_user = ((PyObject*)Py_None); - - /* "aiohttp/_http_parser.pyx":809 - * str fragment = None - * str user = None - * str password = None # <<<<<<<<<<<<<< - * str userinfo = None - * object result = None - */ - __Pyx_INCREF(Py_None); - __pyx_v_password = ((PyObject*)Py_None); - - /* "aiohttp/_http_parser.pyx":810 - * str user = None - * str password = None - * str userinfo = None # <<<<<<<<<<<<<< - * object result = None - * int off - */ - __Pyx_INCREF(Py_None); - __pyx_v_userinfo = ((PyObject*)Py_None); - - /* "aiohttp/_http_parser.pyx":811 - * str password = None - * str userinfo = None - * object result = None # <<<<<<<<<<<<<< - * int off - * int ln - */ - __Pyx_INCREF(Py_None); - __pyx_v_result = Py_None; - - /* "aiohttp/_http_parser.pyx":815 - * int ln - * - * parsed = \ # <<<<<<<<<<<<<< - * PyMem_Malloc(sizeof(cparser.http_parser_url)) - * if parsed is NULL: - */ - __pyx_v_parsed = ((struct http_parser_url *)PyMem_Malloc((sizeof(struct http_parser_url)))); - - /* "aiohttp/_http_parser.pyx":817 - * parsed = \ - * PyMem_Malloc(sizeof(cparser.http_parser_url)) - * if parsed is NULL: # <<<<<<<<<<<<<< - * raise MemoryError() - * cparser.http_parser_url_init(parsed) - */ - __pyx_t_1 = ((__pyx_v_parsed == NULL) != 0); - if (unlikely(__pyx_t_1)) { - - /* "aiohttp/_http_parser.pyx":818 - * PyMem_Malloc(sizeof(cparser.http_parser_url)) - * if parsed is NULL: - * raise MemoryError() # <<<<<<<<<<<<<< - * cparser.http_parser_url_init(parsed) - * try: - */ - PyErr_NoMemory(); __PYX_ERR(0, 818, __pyx_L1_error) - - /* "aiohttp/_http_parser.pyx":817 - * parsed = \ - * PyMem_Malloc(sizeof(cparser.http_parser_url)) - * if parsed is NULL: # <<<<<<<<<<<<<< - * raise MemoryError() - * cparser.http_parser_url_init(parsed) - */ - } - - /* "aiohttp/_http_parser.pyx":819 - * if parsed is NULL: - * raise MemoryError() - * cparser.http_parser_url_init(parsed) # <<<<<<<<<<<<<< - * try: - * res = cparser.http_parser_parse_url(buf_data, length, 0, parsed) - */ - http_parser_url_init(__pyx_v_parsed); - - /* "aiohttp/_http_parser.pyx":820 - * raise MemoryError() - * cparser.http_parser_url_init(parsed) - * try: # <<<<<<<<<<<<<< - * res = cparser.http_parser_parse_url(buf_data, length, 0, parsed) - * - */ - /*try:*/ { - - /* "aiohttp/_http_parser.pyx":821 - * cparser.http_parser_url_init(parsed) - * try: - * res = cparser.http_parser_parse_url(buf_data, length, 0, parsed) # <<<<<<<<<<<<<< - * - * if res == 0: - */ - __pyx_v_res = http_parser_parse_url(__pyx_v_buf_data, __pyx_v_length, 0, __pyx_v_parsed); - - /* "aiohttp/_http_parser.pyx":823 - * res = cparser.http_parser_parse_url(buf_data, length, 0, parsed) - * - * if res == 0: # <<<<<<<<<<<<<< - * if parsed.field_set & (1 << cparser.UF_SCHEMA): - * off = parsed.field_data[cparser.UF_SCHEMA].off - */ - __pyx_t_1 = ((__pyx_v_res == 0) != 0); - if (likely(__pyx_t_1)) { - - /* "aiohttp/_http_parser.pyx":824 - * - * if res == 0: - * if parsed.field_set & (1 << cparser.UF_SCHEMA): # <<<<<<<<<<<<<< - * off = parsed.field_data[cparser.UF_SCHEMA].off - * ln = parsed.field_data[cparser.UF_SCHEMA].len - */ - __pyx_t_1 = ((__pyx_v_parsed->field_set & (1 << UF_SCHEMA)) != 0); - if (__pyx_t_1) { - - /* "aiohttp/_http_parser.pyx":825 - * if res == 0: - * if parsed.field_set & (1 << cparser.UF_SCHEMA): - * off = parsed.field_data[cparser.UF_SCHEMA].off # <<<<<<<<<<<<<< - * ln = parsed.field_data[cparser.UF_SCHEMA].len - * schema = buf_data[off:off+ln].decode('utf-8', 'surrogateescape') - */ - __pyx_t_2 = (__pyx_v_parsed->field_data[((int)UF_SCHEMA)]).off; - __pyx_v_off = __pyx_t_2; - - /* "aiohttp/_http_parser.pyx":826 - * if parsed.field_set & (1 << cparser.UF_SCHEMA): - * off = parsed.field_data[cparser.UF_SCHEMA].off - * ln = parsed.field_data[cparser.UF_SCHEMA].len # <<<<<<<<<<<<<< - * schema = buf_data[off:off+ln].decode('utf-8', 'surrogateescape') - * else: - */ - __pyx_t_2 = (__pyx_v_parsed->field_data[((int)UF_SCHEMA)]).len; - __pyx_v_ln = __pyx_t_2; - - /* "aiohttp/_http_parser.pyx":827 - * off = parsed.field_data[cparser.UF_SCHEMA].off - * ln = parsed.field_data[cparser.UF_SCHEMA].len - * schema = buf_data[off:off+ln].decode('utf-8', 'surrogateescape') # <<<<<<<<<<<<<< - * else: - * schema = '' - */ - __pyx_t_3 = __Pyx_decode_c_string(__pyx_v_buf_data, __pyx_v_off, (__pyx_v_off + __pyx_v_ln), NULL, ((char const *)"surrogateescape"), PyUnicode_DecodeUTF8); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 827, __pyx_L5_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF_SET(__pyx_v_schema, ((PyObject*)__pyx_t_3)); - __pyx_t_3 = 0; - - /* "aiohttp/_http_parser.pyx":824 - * - * if res == 0: - * if parsed.field_set & (1 << cparser.UF_SCHEMA): # <<<<<<<<<<<<<< - * off = parsed.field_data[cparser.UF_SCHEMA].off - * ln = parsed.field_data[cparser.UF_SCHEMA].len - */ - goto __pyx_L8; - } - - /* "aiohttp/_http_parser.pyx":829 - * schema = buf_data[off:off+ln].decode('utf-8', 'surrogateescape') - * else: - * schema = '' # <<<<<<<<<<<<<< - * - * if parsed.field_set & (1 << cparser.UF_HOST): - */ - /*else*/ { - __Pyx_INCREF(__pyx_kp_u__4); - __Pyx_DECREF_SET(__pyx_v_schema, __pyx_kp_u__4); - } - __pyx_L8:; - - /* "aiohttp/_http_parser.pyx":831 - * schema = '' - * - * if parsed.field_set & (1 << cparser.UF_HOST): # <<<<<<<<<<<<<< - * off = parsed.field_data[cparser.UF_HOST].off - * ln = parsed.field_data[cparser.UF_HOST].len - */ - __pyx_t_1 = ((__pyx_v_parsed->field_set & (1 << UF_HOST)) != 0); - if (__pyx_t_1) { - - /* "aiohttp/_http_parser.pyx":832 - * - * if parsed.field_set & (1 << cparser.UF_HOST): - * off = parsed.field_data[cparser.UF_HOST].off # <<<<<<<<<<<<<< - * ln = parsed.field_data[cparser.UF_HOST].len - * host = buf_data[off:off+ln].decode('utf-8', 'surrogateescape') - */ - __pyx_t_2 = (__pyx_v_parsed->field_data[((int)UF_HOST)]).off; - __pyx_v_off = __pyx_t_2; - - /* "aiohttp/_http_parser.pyx":833 - * if parsed.field_set & (1 << cparser.UF_HOST): - * off = parsed.field_data[cparser.UF_HOST].off - * ln = parsed.field_data[cparser.UF_HOST].len # <<<<<<<<<<<<<< - * host = buf_data[off:off+ln].decode('utf-8', 'surrogateescape') - * else: - */ - __pyx_t_2 = (__pyx_v_parsed->field_data[((int)UF_HOST)]).len; - __pyx_v_ln = __pyx_t_2; - - /* "aiohttp/_http_parser.pyx":834 - * off = parsed.field_data[cparser.UF_HOST].off - * ln = parsed.field_data[cparser.UF_HOST].len - * host = buf_data[off:off+ln].decode('utf-8', 'surrogateescape') # <<<<<<<<<<<<<< - * else: - * host = '' - */ - __pyx_t_3 = __Pyx_decode_c_string(__pyx_v_buf_data, __pyx_v_off, (__pyx_v_off + __pyx_v_ln), NULL, ((char const *)"surrogateescape"), PyUnicode_DecodeUTF8); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 834, __pyx_L5_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF_SET(__pyx_v_host, ((PyObject*)__pyx_t_3)); - __pyx_t_3 = 0; - - /* "aiohttp/_http_parser.pyx":831 - * schema = '' - * - * if parsed.field_set & (1 << cparser.UF_HOST): # <<<<<<<<<<<<<< - * off = parsed.field_data[cparser.UF_HOST].off - * ln = parsed.field_data[cparser.UF_HOST].len - */ - goto __pyx_L9; - } - - /* "aiohttp/_http_parser.pyx":836 - * host = buf_data[off:off+ln].decode('utf-8', 'surrogateescape') - * else: - * host = '' # <<<<<<<<<<<<<< - * - * if parsed.field_set & (1 << cparser.UF_PORT): - */ - /*else*/ { - __Pyx_INCREF(__pyx_kp_u__4); - __Pyx_DECREF_SET(__pyx_v_host, __pyx_kp_u__4); - } - __pyx_L9:; - - /* "aiohttp/_http_parser.pyx":838 - * host = '' - * - * if parsed.field_set & (1 << cparser.UF_PORT): # <<<<<<<<<<<<<< - * port = parsed.port - * - */ - __pyx_t_1 = ((__pyx_v_parsed->field_set & (1 << UF_PORT)) != 0); - if (__pyx_t_1) { - - /* "aiohttp/_http_parser.pyx":839 - * - * if parsed.field_set & (1 << cparser.UF_PORT): - * port = parsed.port # <<<<<<<<<<<<<< - * - * if parsed.field_set & (1 << cparser.UF_PATH): - */ - __pyx_t_3 = __Pyx_PyInt_From_uint16_t(__pyx_v_parsed->port); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 839, __pyx_L5_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF_SET(__pyx_v_port, __pyx_t_3); - __pyx_t_3 = 0; - - /* "aiohttp/_http_parser.pyx":838 - * host = '' - * - * if parsed.field_set & (1 << cparser.UF_PORT): # <<<<<<<<<<<<<< - * port = parsed.port - * - */ - } - - /* "aiohttp/_http_parser.pyx":841 - * port = parsed.port - * - * if parsed.field_set & (1 << cparser.UF_PATH): # <<<<<<<<<<<<<< - * off = parsed.field_data[cparser.UF_PATH].off - * ln = parsed.field_data[cparser.UF_PATH].len - */ - __pyx_t_1 = ((__pyx_v_parsed->field_set & (1 << UF_PATH)) != 0); - if (__pyx_t_1) { - - /* "aiohttp/_http_parser.pyx":842 - * - * if parsed.field_set & (1 << cparser.UF_PATH): - * off = parsed.field_data[cparser.UF_PATH].off # <<<<<<<<<<<<<< - * ln = parsed.field_data[cparser.UF_PATH].len - * path = buf_data[off:off+ln].decode('utf-8', 'surrogateescape') - */ - __pyx_t_2 = (__pyx_v_parsed->field_data[((int)UF_PATH)]).off; - __pyx_v_off = __pyx_t_2; - - /* "aiohttp/_http_parser.pyx":843 - * if parsed.field_set & (1 << cparser.UF_PATH): - * off = parsed.field_data[cparser.UF_PATH].off - * ln = parsed.field_data[cparser.UF_PATH].len # <<<<<<<<<<<<<< - * path = buf_data[off:off+ln].decode('utf-8', 'surrogateescape') - * else: - */ - __pyx_t_2 = (__pyx_v_parsed->field_data[((int)UF_PATH)]).len; - __pyx_v_ln = __pyx_t_2; - - /* "aiohttp/_http_parser.pyx":844 - * off = parsed.field_data[cparser.UF_PATH].off - * ln = parsed.field_data[cparser.UF_PATH].len - * path = buf_data[off:off+ln].decode('utf-8', 'surrogateescape') # <<<<<<<<<<<<<< - * else: - * path = '' - */ - __pyx_t_3 = __Pyx_decode_c_string(__pyx_v_buf_data, __pyx_v_off, (__pyx_v_off + __pyx_v_ln), NULL, ((char const *)"surrogateescape"), PyUnicode_DecodeUTF8); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 844, __pyx_L5_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF_SET(__pyx_v_path, ((PyObject*)__pyx_t_3)); - __pyx_t_3 = 0; - - /* "aiohttp/_http_parser.pyx":841 - * port = parsed.port - * - * if parsed.field_set & (1 << cparser.UF_PATH): # <<<<<<<<<<<<<< - * off = parsed.field_data[cparser.UF_PATH].off - * ln = parsed.field_data[cparser.UF_PATH].len - */ - goto __pyx_L11; - } - - /* "aiohttp/_http_parser.pyx":846 - * path = buf_data[off:off+ln].decode('utf-8', 'surrogateescape') - * else: - * path = '' # <<<<<<<<<<<<<< - * - * if parsed.field_set & (1 << cparser.UF_QUERY): - */ - /*else*/ { - __Pyx_INCREF(__pyx_kp_u__4); - __Pyx_DECREF_SET(__pyx_v_path, __pyx_kp_u__4); - } - __pyx_L11:; - - /* "aiohttp/_http_parser.pyx":848 - * path = '' - * - * if parsed.field_set & (1 << cparser.UF_QUERY): # <<<<<<<<<<<<<< - * off = parsed.field_data[cparser.UF_QUERY].off - * ln = parsed.field_data[cparser.UF_QUERY].len - */ - __pyx_t_1 = ((__pyx_v_parsed->field_set & (1 << UF_QUERY)) != 0); - if (__pyx_t_1) { - - /* "aiohttp/_http_parser.pyx":849 - * - * if parsed.field_set & (1 << cparser.UF_QUERY): - * off = parsed.field_data[cparser.UF_QUERY].off # <<<<<<<<<<<<<< - * ln = parsed.field_data[cparser.UF_QUERY].len - * query = buf_data[off:off+ln].decode('utf-8', 'surrogateescape') - */ - __pyx_t_2 = (__pyx_v_parsed->field_data[((int)UF_QUERY)]).off; - __pyx_v_off = __pyx_t_2; - - /* "aiohttp/_http_parser.pyx":850 - * if parsed.field_set & (1 << cparser.UF_QUERY): - * off = parsed.field_data[cparser.UF_QUERY].off - * ln = parsed.field_data[cparser.UF_QUERY].len # <<<<<<<<<<<<<< - * query = buf_data[off:off+ln].decode('utf-8', 'surrogateescape') - * else: - */ - __pyx_t_2 = (__pyx_v_parsed->field_data[((int)UF_QUERY)]).len; - __pyx_v_ln = __pyx_t_2; - - /* "aiohttp/_http_parser.pyx":851 - * off = parsed.field_data[cparser.UF_QUERY].off - * ln = parsed.field_data[cparser.UF_QUERY].len - * query = buf_data[off:off+ln].decode('utf-8', 'surrogateescape') # <<<<<<<<<<<<<< - * else: - * query = '' - */ - __pyx_t_3 = __Pyx_decode_c_string(__pyx_v_buf_data, __pyx_v_off, (__pyx_v_off + __pyx_v_ln), NULL, ((char const *)"surrogateescape"), PyUnicode_DecodeUTF8); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 851, __pyx_L5_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF_SET(__pyx_v_query, ((PyObject*)__pyx_t_3)); - __pyx_t_3 = 0; - - /* "aiohttp/_http_parser.pyx":848 - * path = '' - * - * if parsed.field_set & (1 << cparser.UF_QUERY): # <<<<<<<<<<<<<< - * off = parsed.field_data[cparser.UF_QUERY].off - * ln = parsed.field_data[cparser.UF_QUERY].len - */ - goto __pyx_L12; - } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_2)) { + PyObject *__pyx_temp[4] = {__pyx_t_4, __pyx_t_3, __pyx_v_data, __pyx_v_pointer}; + __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_2, __pyx_temp+1-__pyx_t_5, 3+__pyx_t_5); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 815, __pyx_L1_error) + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_2)) { + PyObject *__pyx_temp[4] = {__pyx_t_4, __pyx_t_3, __pyx_v_data, __pyx_v_pointer}; + __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_2, __pyx_temp+1-__pyx_t_5, 3+__pyx_t_5); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 815, __pyx_L1_error) + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + } else + #endif + { + __pyx_t_6 = PyTuple_New(3+__pyx_t_5); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 815, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_6); + if (__pyx_t_4) { + __Pyx_GIVEREF(__pyx_t_4); PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_t_4); __pyx_t_4 = NULL; + } + __Pyx_GIVEREF(__pyx_t_3); + PyTuple_SET_ITEM(__pyx_t_6, 0+__pyx_t_5, __pyx_t_3); + __Pyx_INCREF(__pyx_v_data); + __Pyx_GIVEREF(__pyx_v_data); + PyTuple_SET_ITEM(__pyx_t_6, 1+__pyx_t_5, __pyx_v_data); + __Pyx_INCREF(__pyx_v_pointer); + __Pyx_GIVEREF(__pyx_v_pointer); + PyTuple_SET_ITEM(__pyx_t_6, 2+__pyx_t_5, __pyx_v_pointer); + __pyx_t_3 = 0; + __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_6, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 815, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + } + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_v_err_msg = __pyx_t_1; + __pyx_t_1 = 0; - /* "aiohttp/_http_parser.pyx":853 - * query = buf_data[off:off+ln].decode('utf-8', 'surrogateescape') - * else: - * query = '' # <<<<<<<<<<<<<< + /* "aiohttp/_http_parser.pyx":817 + * err_msg = "{}:\n\n {!r}\n {}".format(desc.decode("latin-1"), data, pointer) * - * if parsed.field_set & (1 << cparser.UF_FRAGMENT): + * if errno in {cparser.HPE_CB_MESSAGE_BEGIN, # <<<<<<<<<<<<<< + * cparser.HPE_CB_HEADERS_COMPLETE, + * cparser.HPE_CB_MESSAGE_COMPLETE, */ - /*else*/ { - __Pyx_INCREF(__pyx_kp_u__4); - __Pyx_DECREF_SET(__pyx_v_query, __pyx_kp_u__4); - } - __pyx_L12:; + switch (__pyx_v_errno) { + case HPE_CB_MESSAGE_BEGIN: + case HPE_CB_HEADERS_COMPLETE: - /* "aiohttp/_http_parser.pyx":855 - * query = '' + /* "aiohttp/_http_parser.pyx":818 * - * if parsed.field_set & (1 << cparser.UF_FRAGMENT): # <<<<<<<<<<<<<< - * off = parsed.field_data[cparser.UF_FRAGMENT].off - * ln = parsed.field_data[cparser.UF_FRAGMENT].len + * if errno in {cparser.HPE_CB_MESSAGE_BEGIN, + * cparser.HPE_CB_HEADERS_COMPLETE, # <<<<<<<<<<<<<< + * cparser.HPE_CB_MESSAGE_COMPLETE, + * cparser.HPE_CB_CHUNK_HEADER, */ - __pyx_t_1 = ((__pyx_v_parsed->field_set & (1 << UF_FRAGMENT)) != 0); - if (__pyx_t_1) { + case HPE_CB_MESSAGE_COMPLETE: - /* "aiohttp/_http_parser.pyx":856 - * - * if parsed.field_set & (1 << cparser.UF_FRAGMENT): - * off = parsed.field_data[cparser.UF_FRAGMENT].off # <<<<<<<<<<<<<< - * ln = parsed.field_data[cparser.UF_FRAGMENT].len - * fragment = buf_data[off:off+ln].decode('utf-8', 'surrogateescape') + /* "aiohttp/_http_parser.pyx":819 + * if errno in {cparser.HPE_CB_MESSAGE_BEGIN, + * cparser.HPE_CB_HEADERS_COMPLETE, + * cparser.HPE_CB_MESSAGE_COMPLETE, # <<<<<<<<<<<<<< + * cparser.HPE_CB_CHUNK_HEADER, + * cparser.HPE_CB_CHUNK_COMPLETE, */ - __pyx_t_2 = (__pyx_v_parsed->field_data[((int)UF_FRAGMENT)]).off; - __pyx_v_off = __pyx_t_2; + case HPE_CB_CHUNK_HEADER: - /* "aiohttp/_http_parser.pyx":857 - * if parsed.field_set & (1 << cparser.UF_FRAGMENT): - * off = parsed.field_data[cparser.UF_FRAGMENT].off - * ln = parsed.field_data[cparser.UF_FRAGMENT].len # <<<<<<<<<<<<<< - * fragment = buf_data[off:off+ln].decode('utf-8', 'surrogateescape') - * else: + /* "aiohttp/_http_parser.pyx":820 + * cparser.HPE_CB_HEADERS_COMPLETE, + * cparser.HPE_CB_MESSAGE_COMPLETE, + * cparser.HPE_CB_CHUNK_HEADER, # <<<<<<<<<<<<<< + * cparser.HPE_CB_CHUNK_COMPLETE, + * cparser.HPE_INVALID_CONSTANT, */ - __pyx_t_2 = (__pyx_v_parsed->field_data[((int)UF_FRAGMENT)]).len; - __pyx_v_ln = __pyx_t_2; + case HPE_CB_CHUNK_COMPLETE: - /* "aiohttp/_http_parser.pyx":858 - * off = parsed.field_data[cparser.UF_FRAGMENT].off - * ln = parsed.field_data[cparser.UF_FRAGMENT].len - * fragment = buf_data[off:off+ln].decode('utf-8', 'surrogateescape') # <<<<<<<<<<<<<< - * else: - * fragment = '' + /* "aiohttp/_http_parser.pyx":821 + * cparser.HPE_CB_MESSAGE_COMPLETE, + * cparser.HPE_CB_CHUNK_HEADER, + * cparser.HPE_CB_CHUNK_COMPLETE, # <<<<<<<<<<<<<< + * cparser.HPE_INVALID_CONSTANT, + * cparser.HPE_INVALID_HEADER_TOKEN, */ - __pyx_t_3 = __Pyx_decode_c_string(__pyx_v_buf_data, __pyx_v_off, (__pyx_v_off + __pyx_v_ln), NULL, ((char const *)"surrogateescape"), PyUnicode_DecodeUTF8); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 858, __pyx_L5_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF_SET(__pyx_v_fragment, ((PyObject*)__pyx_t_3)); - __pyx_t_3 = 0; + case HPE_INVALID_CONSTANT: - /* "aiohttp/_http_parser.pyx":855 - * query = '' - * - * if parsed.field_set & (1 << cparser.UF_FRAGMENT): # <<<<<<<<<<<<<< - * off = parsed.field_data[cparser.UF_FRAGMENT].off - * ln = parsed.field_data[cparser.UF_FRAGMENT].len + /* "aiohttp/_http_parser.pyx":822 + * cparser.HPE_CB_CHUNK_HEADER, + * cparser.HPE_CB_CHUNK_COMPLETE, + * cparser.HPE_INVALID_CONSTANT, # <<<<<<<<<<<<<< + * cparser.HPE_INVALID_HEADER_TOKEN, + * cparser.HPE_INVALID_CONTENT_LENGTH, */ - goto __pyx_L13; - } + case HPE_INVALID_HEADER_TOKEN: - /* "aiohttp/_http_parser.pyx":860 - * fragment = buf_data[off:off+ln].decode('utf-8', 'surrogateescape') - * else: - * fragment = '' # <<<<<<<<<<<<<< - * - * if parsed.field_set & (1 << cparser.UF_USERINFO): + /* "aiohttp/_http_parser.pyx":823 + * cparser.HPE_CB_CHUNK_COMPLETE, + * cparser.HPE_INVALID_CONSTANT, + * cparser.HPE_INVALID_HEADER_TOKEN, # <<<<<<<<<<<<<< + * cparser.HPE_INVALID_CONTENT_LENGTH, + * cparser.HPE_INVALID_CHUNK_SIZE, + */ + case HPE_INVALID_CONTENT_LENGTH: + + /* "aiohttp/_http_parser.pyx":824 + * cparser.HPE_INVALID_CONSTANT, + * cparser.HPE_INVALID_HEADER_TOKEN, + * cparser.HPE_INVALID_CONTENT_LENGTH, # <<<<<<<<<<<<<< + * cparser.HPE_INVALID_CHUNK_SIZE, + * cparser.HPE_INVALID_EOF_STATE, + */ + case HPE_INVALID_CHUNK_SIZE: + + /* "aiohttp/_http_parser.pyx":825 + * cparser.HPE_INVALID_HEADER_TOKEN, + * cparser.HPE_INVALID_CONTENT_LENGTH, + * cparser.HPE_INVALID_CHUNK_SIZE, # <<<<<<<<<<<<<< + * cparser.HPE_INVALID_EOF_STATE, + * cparser.HPE_INVALID_TRANSFER_ENCODING}: + */ + case HPE_INVALID_EOF_STATE: + + /* "aiohttp/_http_parser.pyx":826 + * cparser.HPE_INVALID_CONTENT_LENGTH, + * cparser.HPE_INVALID_CHUNK_SIZE, + * cparser.HPE_INVALID_EOF_STATE, # <<<<<<<<<<<<<< + * cparser.HPE_INVALID_TRANSFER_ENCODING}: + * return BadHttpMessage(err_msg) + */ + case HPE_INVALID_TRANSFER_ENCODING: + + /* "aiohttp/_http_parser.pyx":828 + * cparser.HPE_INVALID_EOF_STATE, + * cparser.HPE_INVALID_TRANSFER_ENCODING}: + * return BadHttpMessage(err_msg) # <<<<<<<<<<<<<< + * elif errno in {cparser.HPE_INVALID_STATUS, + * cparser.HPE_INVALID_METHOD, */ - /*else*/ { - __Pyx_INCREF(__pyx_kp_u__4); - __Pyx_DECREF_SET(__pyx_v_fragment, __pyx_kp_u__4); + __Pyx_XDECREF(__pyx_r); + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_BadHttpMessage); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 828, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_6 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) { + __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_2); + if (likely(__pyx_t_6)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2); + __Pyx_INCREF(__pyx_t_6); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_2, function); } - __pyx_L13:; + } + __pyx_t_1 = (__pyx_t_6) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_6, __pyx_v_err_msg) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_v_err_msg); + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 828, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; - /* "aiohttp/_http_parser.pyx":862 - * fragment = '' + /* "aiohttp/_http_parser.pyx":817 + * err_msg = "{}:\n\n {!r}\n {}".format(desc.decode("latin-1"), data, pointer) * - * if parsed.field_set & (1 << cparser.UF_USERINFO): # <<<<<<<<<<<<<< - * off = parsed.field_data[cparser.UF_USERINFO].off - * ln = parsed.field_data[cparser.UF_USERINFO].len + * if errno in {cparser.HPE_CB_MESSAGE_BEGIN, # <<<<<<<<<<<<<< + * cparser.HPE_CB_HEADERS_COMPLETE, + * cparser.HPE_CB_MESSAGE_COMPLETE, */ - __pyx_t_1 = ((__pyx_v_parsed->field_set & (1 << UF_USERINFO)) != 0); - if (__pyx_t_1) { + break; + case HPE_INVALID_STATUS: - /* "aiohttp/_http_parser.pyx":863 - * - * if parsed.field_set & (1 << cparser.UF_USERINFO): - * off = parsed.field_data[cparser.UF_USERINFO].off # <<<<<<<<<<<<<< - * ln = parsed.field_data[cparser.UF_USERINFO].len - * userinfo = buf_data[off:off+ln].decode('utf-8', 'surrogateescape') + /* "aiohttp/_http_parser.pyx":829 + * cparser.HPE_INVALID_TRANSFER_ENCODING}: + * return BadHttpMessage(err_msg) + * elif errno in {cparser.HPE_INVALID_STATUS, # <<<<<<<<<<<<<< + * cparser.HPE_INVALID_METHOD, + * cparser.HPE_INVALID_VERSION}: */ - __pyx_t_2 = (__pyx_v_parsed->field_data[((int)UF_USERINFO)]).off; - __pyx_v_off = __pyx_t_2; + case HPE_INVALID_METHOD: - /* "aiohttp/_http_parser.pyx":864 - * if parsed.field_set & (1 << cparser.UF_USERINFO): - * off = parsed.field_data[cparser.UF_USERINFO].off - * ln = parsed.field_data[cparser.UF_USERINFO].len # <<<<<<<<<<<<<< - * userinfo = buf_data[off:off+ln].decode('utf-8', 'surrogateescape') - * + /* "aiohttp/_http_parser.pyx":830 + * return BadHttpMessage(err_msg) + * elif errno in {cparser.HPE_INVALID_STATUS, + * cparser.HPE_INVALID_METHOD, # <<<<<<<<<<<<<< + * cparser.HPE_INVALID_VERSION}: + * return BadStatusLine(error=err_msg) */ - __pyx_t_2 = (__pyx_v_parsed->field_data[((int)UF_USERINFO)]).len; - __pyx_v_ln = __pyx_t_2; + case HPE_INVALID_VERSION: - /* "aiohttp/_http_parser.pyx":865 - * off = parsed.field_data[cparser.UF_USERINFO].off - * ln = parsed.field_data[cparser.UF_USERINFO].len - * userinfo = buf_data[off:off+ln].decode('utf-8', 'surrogateescape') # <<<<<<<<<<<<<< - * - * user, sep, password = userinfo.partition(':') + /* "aiohttp/_http_parser.pyx":832 + * cparser.HPE_INVALID_METHOD, + * cparser.HPE_INVALID_VERSION}: + * return BadStatusLine(error=err_msg) # <<<<<<<<<<<<<< + * elif errno == cparser.HPE_INVALID_URL: + * return InvalidURLError(err_msg) */ - __pyx_t_3 = __Pyx_decode_c_string(__pyx_v_buf_data, __pyx_v_off, (__pyx_v_off + __pyx_v_ln), NULL, ((char const *)"surrogateescape"), PyUnicode_DecodeUTF8); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 865, __pyx_L5_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF_SET(__pyx_v_userinfo, ((PyObject*)__pyx_t_3)); - __pyx_t_3 = 0; + __Pyx_XDECREF(__pyx_r); + __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_BadStatusLine); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 832, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = __Pyx_PyDict_NewPresized(1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 832, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + if (PyDict_SetItem(__pyx_t_2, __pyx_n_s_error, __pyx_v_err_msg) < 0) __PYX_ERR(0, 832, __pyx_L1_error) + __pyx_t_6 = __Pyx_PyObject_Call(__pyx_t_1, __pyx_empty_tuple, __pyx_t_2); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 832, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_r = __pyx_t_6; + __pyx_t_6 = 0; + goto __pyx_L0; - /* "aiohttp/_http_parser.pyx":867 - * userinfo = buf_data[off:off+ln].decode('utf-8', 'surrogateescape') - * - * user, sep, password = userinfo.partition(':') # <<<<<<<<<<<<<< - * - * return URL_build(scheme=schema, + /* "aiohttp/_http_parser.pyx":829 + * cparser.HPE_INVALID_TRANSFER_ENCODING}: + * return BadHttpMessage(err_msg) + * elif errno in {cparser.HPE_INVALID_STATUS, # <<<<<<<<<<<<<< + * cparser.HPE_INVALID_METHOD, + * cparser.HPE_INVALID_VERSION}: */ - __pyx_t_3 = __Pyx_CallUnboundCMethod1(&__pyx_umethod_PyUnicode_Type_partition, __pyx_v_userinfo, __pyx_kp_u__11); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 867, __pyx_L5_error) - __Pyx_GOTREF(__pyx_t_3); - if ((likely(PyTuple_CheckExact(__pyx_t_3))) || (PyList_CheckExact(__pyx_t_3))) { - PyObject* sequence = __pyx_t_3; - Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); - if (unlikely(size != 3)) { - if (size > 3) __Pyx_RaiseTooManyValuesError(3); - else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); - __PYX_ERR(0, 867, __pyx_L5_error) - } - #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS - if (likely(PyTuple_CheckExact(sequence))) { - __pyx_t_4 = PyTuple_GET_ITEM(sequence, 0); - __pyx_t_5 = PyTuple_GET_ITEM(sequence, 1); - __pyx_t_6 = PyTuple_GET_ITEM(sequence, 2); - } else { - __pyx_t_4 = PyList_GET_ITEM(sequence, 0); - __pyx_t_5 = PyList_GET_ITEM(sequence, 1); - __pyx_t_6 = PyList_GET_ITEM(sequence, 2); - } - __Pyx_INCREF(__pyx_t_4); - __Pyx_INCREF(__pyx_t_5); - __Pyx_INCREF(__pyx_t_6); - #else - __pyx_t_4 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 867, __pyx_L5_error) - __Pyx_GOTREF(__pyx_t_4); - __pyx_t_5 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 867, __pyx_L5_error) - __Pyx_GOTREF(__pyx_t_5); - __pyx_t_6 = PySequence_ITEM(sequence, 2); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 867, __pyx_L5_error) - __Pyx_GOTREF(__pyx_t_6); - #endif - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - } else { - Py_ssize_t index = -1; - __pyx_t_7 = PyObject_GetIter(__pyx_t_3); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 867, __pyx_L5_error) - __Pyx_GOTREF(__pyx_t_7); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __pyx_t_8 = Py_TYPE(__pyx_t_7)->tp_iternext; - index = 0; __pyx_t_4 = __pyx_t_8(__pyx_t_7); if (unlikely(!__pyx_t_4)) goto __pyx_L15_unpacking_failed; - __Pyx_GOTREF(__pyx_t_4); - index = 1; __pyx_t_5 = __pyx_t_8(__pyx_t_7); if (unlikely(!__pyx_t_5)) goto __pyx_L15_unpacking_failed; - __Pyx_GOTREF(__pyx_t_5); - index = 2; __pyx_t_6 = __pyx_t_8(__pyx_t_7); if (unlikely(!__pyx_t_6)) goto __pyx_L15_unpacking_failed; - __Pyx_GOTREF(__pyx_t_6); - if (__Pyx_IternextUnpackEndCheck(__pyx_t_8(__pyx_t_7), 3) < 0) __PYX_ERR(0, 867, __pyx_L5_error) - __pyx_t_8 = NULL; - __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; - goto __pyx_L16_unpacking_done; - __pyx_L15_unpacking_failed:; - __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; - __pyx_t_8 = NULL; - if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index); - __PYX_ERR(0, 867, __pyx_L5_error) - __pyx_L16_unpacking_done:; - } - if (!(likely(PyUnicode_CheckExact(__pyx_t_4))||((__pyx_t_4) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "unicode", Py_TYPE(__pyx_t_4)->tp_name), 0))) __PYX_ERR(0, 867, __pyx_L5_error) - if (!(likely(PyUnicode_CheckExact(__pyx_t_6))||((__pyx_t_6) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "unicode", Py_TYPE(__pyx_t_6)->tp_name), 0))) __PYX_ERR(0, 867, __pyx_L5_error) - __Pyx_DECREF_SET(__pyx_v_user, ((PyObject*)__pyx_t_4)); - __pyx_t_4 = 0; - __pyx_v_sep = __pyx_t_5; - __pyx_t_5 = 0; - __Pyx_DECREF_SET(__pyx_v_password, ((PyObject*)__pyx_t_6)); - __pyx_t_6 = 0; + break; + case HPE_INVALID_URL: - /* "aiohttp/_http_parser.pyx":862 - * fragment = '' + /* "aiohttp/_http_parser.pyx":834 + * return BadStatusLine(error=err_msg) + * elif errno == cparser.HPE_INVALID_URL: + * return InvalidURLError(err_msg) # <<<<<<<<<<<<<< * - * if parsed.field_set & (1 << cparser.UF_USERINFO): # <<<<<<<<<<<<<< - * off = parsed.field_data[cparser.UF_USERINFO].off - * ln = parsed.field_data[cparser.UF_USERINFO].len + * return BadHttpMessage(err_msg) */ + __Pyx_XDECREF(__pyx_r); + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_InvalidURLError); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 834, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_1 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) { + __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_2); + if (likely(__pyx_t_1)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2); + __Pyx_INCREF(__pyx_t_1); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_2, function); } - - /* "aiohttp/_http_parser.pyx":869 - * user, sep, password = userinfo.partition(':') - * - * return URL_build(scheme=schema, # <<<<<<<<<<<<<< - * user=user, password=password, host=host, port=port, - * path=path, query_string=query, fragment=fragment, encoded=True) - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_3 = __Pyx_PyDict_NewPresized(9); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 869, __pyx_L5_error) - __Pyx_GOTREF(__pyx_t_3); - if (PyDict_SetItem(__pyx_t_3, __pyx_n_s_scheme, __pyx_v_schema) < 0) __PYX_ERR(0, 869, __pyx_L5_error) - - /* "aiohttp/_http_parser.pyx":870 - * - * return URL_build(scheme=schema, - * user=user, password=password, host=host, port=port, # <<<<<<<<<<<<<< - * path=path, query_string=query, fragment=fragment, encoded=True) - * else: - */ - if (PyDict_SetItem(__pyx_t_3, __pyx_n_s_user, __pyx_v_user) < 0) __PYX_ERR(0, 869, __pyx_L5_error) - if (PyDict_SetItem(__pyx_t_3, __pyx_n_s_password, __pyx_v_password) < 0) __PYX_ERR(0, 869, __pyx_L5_error) - if (PyDict_SetItem(__pyx_t_3, __pyx_n_s_host, __pyx_v_host) < 0) __PYX_ERR(0, 869, __pyx_L5_error) - if (PyDict_SetItem(__pyx_t_3, __pyx_n_s_port, __pyx_v_port) < 0) __PYX_ERR(0, 869, __pyx_L5_error) - - /* "aiohttp/_http_parser.pyx":871 - * return URL_build(scheme=schema, - * user=user, password=password, host=host, port=port, - * path=path, query_string=query, fragment=fragment, encoded=True) # <<<<<<<<<<<<<< - * else: - * raise InvalidURLError("invalid url {!r}".format(buf_data)) - */ - if (PyDict_SetItem(__pyx_t_3, __pyx_n_s_path, __pyx_v_path) < 0) __PYX_ERR(0, 869, __pyx_L5_error) - if (PyDict_SetItem(__pyx_t_3, __pyx_n_s_query_string, __pyx_v_query) < 0) __PYX_ERR(0, 869, __pyx_L5_error) - if (PyDict_SetItem(__pyx_t_3, __pyx_n_s_fragment, __pyx_v_fragment) < 0) __PYX_ERR(0, 869, __pyx_L5_error) - if (PyDict_SetItem(__pyx_t_3, __pyx_n_s_encoded, Py_True) < 0) __PYX_ERR(0, 869, __pyx_L5_error) - - /* "aiohttp/_http_parser.pyx":869 - * user, sep, password = userinfo.partition(':') - * - * return URL_build(scheme=schema, # <<<<<<<<<<<<<< - * user=user, password=password, host=host, port=port, - * path=path, query_string=query, fragment=fragment, encoded=True) - */ - __pyx_t_6 = __Pyx_PyObject_Call(__pyx_v_7aiohttp_12_http_parser_URL_build, __pyx_empty_tuple, __pyx_t_3); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 869, __pyx_L5_error) - __Pyx_GOTREF(__pyx_t_6); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __pyx_r = __pyx_t_6; - __pyx_t_6 = 0; - goto __pyx_L4_return; - - /* "aiohttp/_http_parser.pyx":823 - * res = cparser.http_parser_parse_url(buf_data, length, 0, parsed) - * - * if res == 0: # <<<<<<<<<<<<<< - * if parsed.field_set & (1 << cparser.UF_SCHEMA): - * off = parsed.field_data[cparser.UF_SCHEMA].off - */ } + __pyx_t_6 = (__pyx_t_1) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_1, __pyx_v_err_msg) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_v_err_msg); + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 834, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_r = __pyx_t_6; + __pyx_t_6 = 0; + goto __pyx_L0; - /* "aiohttp/_http_parser.pyx":873 - * path=path, query_string=query, fragment=fragment, encoded=True) - * else: - * raise InvalidURLError("invalid url {!r}".format(buf_data)) # <<<<<<<<<<<<<< - * finally: - * PyMem_Free(parsed) + /* "aiohttp/_http_parser.pyx":833 + * cparser.HPE_INVALID_VERSION}: + * return BadStatusLine(error=err_msg) + * elif errno == cparser.HPE_INVALID_URL: # <<<<<<<<<<<<<< + * return InvalidURLError(err_msg) + * */ - /*else*/ { - __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_InvalidURLError); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 873, __pyx_L5_error) - __Pyx_GOTREF(__pyx_t_3); - __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_kp_u_invalid_url_r, __pyx_n_s_format); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 873, __pyx_L5_error) - __Pyx_GOTREF(__pyx_t_4); - __pyx_t_7 = __Pyx_PyBytes_FromString(__pyx_v_buf_data); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 873, __pyx_L5_error) - __Pyx_GOTREF(__pyx_t_7); - __pyx_t_9 = NULL; - if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_4))) { - __pyx_t_9 = PyMethod_GET_SELF(__pyx_t_4); - if (likely(__pyx_t_9)) { - PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4); - __Pyx_INCREF(__pyx_t_9); - __Pyx_INCREF(function); - __Pyx_DECREF_SET(__pyx_t_4, function); - } - } - __pyx_t_5 = (__pyx_t_9) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_9, __pyx_t_7) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_7); - __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; - __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; - if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 873, __pyx_L5_error) - __Pyx_GOTREF(__pyx_t_5); - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - __pyx_t_4 = NULL; - if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) { - __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3); - if (likely(__pyx_t_4)) { - PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3); - __Pyx_INCREF(__pyx_t_4); - __Pyx_INCREF(function); - __Pyx_DECREF_SET(__pyx_t_3, function); - } - } - __pyx_t_6 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_4, __pyx_t_5) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_5); - __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; - __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; - if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 873, __pyx_L5_error) - __Pyx_GOTREF(__pyx_t_6); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __Pyx_Raise(__pyx_t_6, 0, 0, 0); - __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; - __PYX_ERR(0, 873, __pyx_L5_error) - } + break; + default: break; } - /* "aiohttp/_http_parser.pyx":875 - * raise InvalidURLError("invalid url {!r}".format(buf_data)) - * finally: - * PyMem_Free(parsed) # <<<<<<<<<<<<<< + /* "aiohttp/_http_parser.pyx":836 + * return InvalidURLError(err_msg) + * + * return BadHttpMessage(err_msg) # <<<<<<<<<<<<<< */ - /*finally:*/ { - __pyx_L5_error:; - /*exception exit:*/{ - __Pyx_PyThreadState_declare - __Pyx_PyThreadState_assign - __pyx_t_13 = 0; __pyx_t_14 = 0; __pyx_t_15 = 0; __pyx_t_16 = 0; __pyx_t_17 = 0; __pyx_t_18 = 0; - __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; - __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; - __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; - __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; - __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; - __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; - if (PY_MAJOR_VERSION >= 3) __Pyx_ExceptionSwap(&__pyx_t_16, &__pyx_t_17, &__pyx_t_18); - if ((PY_MAJOR_VERSION < 3) || unlikely(__Pyx_GetException(&__pyx_t_13, &__pyx_t_14, &__pyx_t_15) < 0)) __Pyx_ErrFetch(&__pyx_t_13, &__pyx_t_14, &__pyx_t_15); - __Pyx_XGOTREF(__pyx_t_13); - __Pyx_XGOTREF(__pyx_t_14); - __Pyx_XGOTREF(__pyx_t_15); - __Pyx_XGOTREF(__pyx_t_16); - __Pyx_XGOTREF(__pyx_t_17); - __Pyx_XGOTREF(__pyx_t_18); - __pyx_t_10 = __pyx_lineno; __pyx_t_11 = __pyx_clineno; __pyx_t_12 = __pyx_filename; - { - PyMem_Free(__pyx_v_parsed); - } - if (PY_MAJOR_VERSION >= 3) { - __Pyx_XGIVEREF(__pyx_t_16); - __Pyx_XGIVEREF(__pyx_t_17); - __Pyx_XGIVEREF(__pyx_t_18); - __Pyx_ExceptionReset(__pyx_t_16, __pyx_t_17, __pyx_t_18); - } - __Pyx_XGIVEREF(__pyx_t_13); - __Pyx_XGIVEREF(__pyx_t_14); - __Pyx_XGIVEREF(__pyx_t_15); - __Pyx_ErrRestore(__pyx_t_13, __pyx_t_14, __pyx_t_15); - __pyx_t_13 = 0; __pyx_t_14 = 0; __pyx_t_15 = 0; __pyx_t_16 = 0; __pyx_t_17 = 0; __pyx_t_18 = 0; - __pyx_lineno = __pyx_t_10; __pyx_clineno = __pyx_t_11; __pyx_filename = __pyx_t_12; - goto __pyx_L1_error; - } - __pyx_L4_return: { - __pyx_t_18 = __pyx_r; - __pyx_r = 0; - PyMem_Free(__pyx_v_parsed); - __pyx_r = __pyx_t_18; - __pyx_t_18 = 0; - goto __pyx_L0; + __Pyx_XDECREF(__pyx_r); + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_BadHttpMessage); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 836, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_1 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) { + __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_2); + if (likely(__pyx_t_1)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2); + __Pyx_INCREF(__pyx_t_1); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_2, function); } } + __pyx_t_6 = (__pyx_t_1) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_1, __pyx_v_err_msg) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_v_err_msg); + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 836, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_r = __pyx_t_6; + __pyx_t_6 = 0; + goto __pyx_L0; - /* "aiohttp/_http_parser.pyx":798 + /* "aiohttp/_http_parser.pyx":811 * * - * cdef _parse_url(char* buf_data, size_t length): # <<<<<<<<<<<<<< - * cdef: - * cparser.http_parser_url* parsed + * cdef parser_error_from_errno(cparser.llhttp_t* parser, data, pointer): # <<<<<<<<<<<<<< + * cdef cparser.llhttp_errno_t errno = cparser.llhttp_get_errno(parser) + * cdef bytes desc = cparser.llhttp_get_error_reason(parser) */ /* function exit code */ __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); __Pyx_XDECREF(__pyx_t_3); __Pyx_XDECREF(__pyx_t_4); - __Pyx_XDECREF(__pyx_t_5); __Pyx_XDECREF(__pyx_t_6); - __Pyx_XDECREF(__pyx_t_7); - __Pyx_XDECREF(__pyx_t_9); - __Pyx_AddTraceback("aiohttp._http_parser._parse_url", __pyx_clineno, __pyx_lineno, __pyx_filename); + __Pyx_AddTraceback("aiohttp._http_parser.parser_error_from_errno", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = 0; __pyx_L0:; - __Pyx_XDECREF(__pyx_v_schema); - __Pyx_XDECREF(__pyx_v_host); - __Pyx_XDECREF(__pyx_v_port); - __Pyx_XDECREF(__pyx_v_path); - __Pyx_XDECREF(__pyx_v_query); - __Pyx_XDECREF(__pyx_v_fragment); - __Pyx_XDECREF(__pyx_v_user); - __Pyx_XDECREF(__pyx_v_password); - __Pyx_XDECREF(__pyx_v_userinfo); - __Pyx_XDECREF(__pyx_v_result); - __Pyx_XDECREF(__pyx_v_sep); + __Pyx_XDECREF(__pyx_v_desc); + __Pyx_XDECREF(__pyx_v_err_msg); __Pyx_XGIVEREF(__pyx_r); __Pyx_RefNannyFinishContext(); return __pyx_r; @@ -15030,9 +14876,9 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser__parse_url(char *__pyx_v_buf_da */ /* Python wrapper */ -static PyObject *__pyx_pw_7aiohttp_12_http_parser_3__pyx_unpickle_RawRequestMessage(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ -static PyMethodDef __pyx_mdef_7aiohttp_12_http_parser_3__pyx_unpickle_RawRequestMessage = {"__pyx_unpickle_RawRequestMessage", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_7aiohttp_12_http_parser_3__pyx_unpickle_RawRequestMessage, METH_VARARGS|METH_KEYWORDS, 0}; -static PyObject *__pyx_pw_7aiohttp_12_http_parser_3__pyx_unpickle_RawRequestMessage(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { +static PyObject *__pyx_pw_7aiohttp_12_http_parser_1__pyx_unpickle_RawRequestMessage(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static PyMethodDef __pyx_mdef_7aiohttp_12_http_parser_1__pyx_unpickle_RawRequestMessage = {"__pyx_unpickle_RawRequestMessage", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_7aiohttp_12_http_parser_1__pyx_unpickle_RawRequestMessage, METH_VARARGS|METH_KEYWORDS, 0}; +static PyObject *__pyx_pw_7aiohttp_12_http_parser_1__pyx_unpickle_RawRequestMessage(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { PyObject *__pyx_v___pyx_type = 0; long __pyx_v___pyx_checksum; PyObject *__pyx_v___pyx_state = 0; @@ -15098,24 +14944,24 @@ static PyObject *__pyx_pw_7aiohttp_12_http_parser_3__pyx_unpickle_RawRequestMess __Pyx_RefNannyFinishContext(); return NULL; __pyx_L4_argument_unpacking_done:; - __pyx_r = __pyx_pf_7aiohttp_12_http_parser_2__pyx_unpickle_RawRequestMessage(__pyx_self, __pyx_v___pyx_type, __pyx_v___pyx_checksum, __pyx_v___pyx_state); + __pyx_r = __pyx_pf_7aiohttp_12_http_parser___pyx_unpickle_RawRequestMessage(__pyx_self, __pyx_v___pyx_type, __pyx_v___pyx_checksum, __pyx_v___pyx_state); /* function exit code */ __Pyx_RefNannyFinishContext(); return __pyx_r; } -static PyObject *__pyx_pf_7aiohttp_12_http_parser_2__pyx_unpickle_RawRequestMessage(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v___pyx_type, long __pyx_v___pyx_checksum, PyObject *__pyx_v___pyx_state) { +static PyObject *__pyx_pf_7aiohttp_12_http_parser___pyx_unpickle_RawRequestMessage(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v___pyx_type, long __pyx_v___pyx_checksum, PyObject *__pyx_v___pyx_state) { PyObject *__pyx_v___pyx_PickleError = 0; PyObject *__pyx_v___pyx_result = 0; PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations - int __pyx_t_1; - PyObject *__pyx_t_2 = NULL; - PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_1 = NULL; + int __pyx_t_2; + int __pyx_t_3; PyObject *__pyx_t_4 = NULL; PyObject *__pyx_t_5 = NULL; - int __pyx_t_6; + PyObject *__pyx_t_6 = NULL; int __pyx_lineno = 0; const char *__pyx_filename = NULL; int __pyx_clineno = 0; @@ -15124,114 +14970,118 @@ static PyObject *__pyx_pf_7aiohttp_12_http_parser_2__pyx_unpickle_RawRequestMess /* "(tree fragment)":4 * cdef object __pyx_PickleError * cdef object __pyx_result - * if __pyx_checksum != 0x1408252: # <<<<<<<<<<<<<< + * if __pyx_checksum not in (0x1408252, 0xf602a9f, 0x03e51e3): # <<<<<<<<<<<<<< * from pickle import PickleError as __pyx_PickleError - * raise __pyx_PickleError("Incompatible checksums (%s vs 0x1408252 = (chunked, compression, headers, method, path, raw_headers, should_close, upgrade, url, version))" % __pyx_checksum) + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x1408252, 0xf602a9f, 0x03e51e3) = (chunked, compression, headers, method, path, raw_headers, should_close, upgrade, url, version))" % __pyx_checksum) */ - __pyx_t_1 = ((__pyx_v___pyx_checksum != 0x1408252) != 0); - if (__pyx_t_1) { + __pyx_t_1 = __Pyx_PyInt_From_long(__pyx_v___pyx_checksum); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 4, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = (__Pyx_PySequence_ContainsTF(__pyx_t_1, __pyx_tuple__17, Py_NE)); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(1, 4, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_3 = (__pyx_t_2 != 0); + if (__pyx_t_3) { /* "(tree fragment)":5 * cdef object __pyx_result - * if __pyx_checksum != 0x1408252: + * if __pyx_checksum not in (0x1408252, 0xf602a9f, 0x03e51e3): * from pickle import PickleError as __pyx_PickleError # <<<<<<<<<<<<<< - * raise __pyx_PickleError("Incompatible checksums (%s vs 0x1408252 = (chunked, compression, headers, method, path, raw_headers, should_close, upgrade, url, version))" % __pyx_checksum) + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x1408252, 0xf602a9f, 0x03e51e3) = (chunked, compression, headers, method, path, raw_headers, should_close, upgrade, url, version))" % __pyx_checksum) * __pyx_result = RawRequestMessage.__new__(__pyx_type) */ - __pyx_t_2 = PyList_New(1); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 5, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); + __pyx_t_1 = PyList_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); __Pyx_INCREF(__pyx_n_s_PickleError); __Pyx_GIVEREF(__pyx_n_s_PickleError); - PyList_SET_ITEM(__pyx_t_2, 0, __pyx_n_s_PickleError); - __pyx_t_3 = __Pyx_Import(__pyx_n_s_pickle, __pyx_t_2, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 5, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_2 = __Pyx_ImportFrom(__pyx_t_3, __pyx_n_s_PickleError); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 5, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __Pyx_INCREF(__pyx_t_2); - __pyx_v___pyx_PickleError = __pyx_t_2; - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + PyList_SET_ITEM(__pyx_t_1, 0, __pyx_n_s_PickleError); + __pyx_t_4 = __Pyx_Import(__pyx_n_s_pickle, __pyx_t_1, 0); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_4, __pyx_n_s_PickleError); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_t_1); + __pyx_v___pyx_PickleError = __pyx_t_1; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; /* "(tree fragment)":6 - * if __pyx_checksum != 0x1408252: + * if __pyx_checksum not in (0x1408252, 0xf602a9f, 0x03e51e3): * from pickle import PickleError as __pyx_PickleError - * raise __pyx_PickleError("Incompatible checksums (%s vs 0x1408252 = (chunked, compression, headers, method, path, raw_headers, should_close, upgrade, url, version))" % __pyx_checksum) # <<<<<<<<<<<<<< + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x1408252, 0xf602a9f, 0x03e51e3) = (chunked, compression, headers, method, path, raw_headers, should_close, upgrade, url, version))" % __pyx_checksum) # <<<<<<<<<<<<<< * __pyx_result = RawRequestMessage.__new__(__pyx_type) * if __pyx_state is not None: */ - __pyx_t_2 = __Pyx_PyInt_From_long(__pyx_v___pyx_checksum); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 6, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_4 = __Pyx_PyString_Format(__pyx_kp_s_Incompatible_checksums_s_vs_0x14, __pyx_t_2); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 6, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_1 = __Pyx_PyInt_From_long(__pyx_v___pyx_checksum); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_5 = __Pyx_PyString_Format(__pyx_kp_s_Incompatible_checksums_0x_x_vs_0, __pyx_t_1); if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __Pyx_INCREF(__pyx_v___pyx_PickleError); - __pyx_t_2 = __pyx_v___pyx_PickleError; __pyx_t_5 = NULL; - if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) { - __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_2); - if (likely(__pyx_t_5)) { - PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2); - __Pyx_INCREF(__pyx_t_5); + __pyx_t_1 = __pyx_v___pyx_PickleError; __pyx_t_6 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_1))) { + __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_1); + if (likely(__pyx_t_6)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1); + __Pyx_INCREF(__pyx_t_6); __Pyx_INCREF(function); - __Pyx_DECREF_SET(__pyx_t_2, function); + __Pyx_DECREF_SET(__pyx_t_1, function); } } - __pyx_t_3 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_5, __pyx_t_4) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_4); - __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_4 = (__pyx_t_6) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_6, __pyx_t_5) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_Raise(__pyx_t_4, 0, 0, 0); __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 6, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __Pyx_Raise(__pyx_t_3, 0, 0, 0); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __PYX_ERR(1, 6, __pyx_L1_error) /* "(tree fragment)":4 * cdef object __pyx_PickleError * cdef object __pyx_result - * if __pyx_checksum != 0x1408252: # <<<<<<<<<<<<<< + * if __pyx_checksum not in (0x1408252, 0xf602a9f, 0x03e51e3): # <<<<<<<<<<<<<< * from pickle import PickleError as __pyx_PickleError - * raise __pyx_PickleError("Incompatible checksums (%s vs 0x1408252 = (chunked, compression, headers, method, path, raw_headers, should_close, upgrade, url, version))" % __pyx_checksum) + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x1408252, 0xf602a9f, 0x03e51e3) = (chunked, compression, headers, method, path, raw_headers, should_close, upgrade, url, version))" % __pyx_checksum) */ } /* "(tree fragment)":7 * from pickle import PickleError as __pyx_PickleError - * raise __pyx_PickleError("Incompatible checksums (%s vs 0x1408252 = (chunked, compression, headers, method, path, raw_headers, should_close, upgrade, url, version))" % __pyx_checksum) + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x1408252, 0xf602a9f, 0x03e51e3) = (chunked, compression, headers, method, path, raw_headers, should_close, upgrade, url, version))" % __pyx_checksum) * __pyx_result = RawRequestMessage.__new__(__pyx_type) # <<<<<<<<<<<<<< * if __pyx_state is not None: * __pyx_unpickle_RawRequestMessage__set_state( __pyx_result, __pyx_state) */ - __pyx_t_2 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_ptype_7aiohttp_12_http_parser_RawRequestMessage), __pyx_n_s_new); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 7, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_4 = NULL; - if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) { - __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_2); - if (likely(__pyx_t_4)) { - PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2); - __Pyx_INCREF(__pyx_t_4); + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_ptype_7aiohttp_12_http_parser_RawRequestMessage), __pyx_n_s_new); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 7, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_5 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_1))) { + __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_1); + if (likely(__pyx_t_5)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1); + __Pyx_INCREF(__pyx_t_5); __Pyx_INCREF(function); - __Pyx_DECREF_SET(__pyx_t_2, function); + __Pyx_DECREF_SET(__pyx_t_1, function); } - } - __pyx_t_3 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_4, __pyx_v___pyx_type) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_v___pyx_type); - __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; - if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 7, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_v___pyx_result = __pyx_t_3; - __pyx_t_3 = 0; + } + __pyx_t_4 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_5, __pyx_v___pyx_type) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_v___pyx_type); + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 7, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v___pyx_result = __pyx_t_4; + __pyx_t_4 = 0; /* "(tree fragment)":8 - * raise __pyx_PickleError("Incompatible checksums (%s vs 0x1408252 = (chunked, compression, headers, method, path, raw_headers, should_close, upgrade, url, version))" % __pyx_checksum) + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x1408252, 0xf602a9f, 0x03e51e3) = (chunked, compression, headers, method, path, raw_headers, should_close, upgrade, url, version))" % __pyx_checksum) * __pyx_result = RawRequestMessage.__new__(__pyx_type) * if __pyx_state is not None: # <<<<<<<<<<<<<< * __pyx_unpickle_RawRequestMessage__set_state( __pyx_result, __pyx_state) * return __pyx_result */ - __pyx_t_1 = (__pyx_v___pyx_state != Py_None); - __pyx_t_6 = (__pyx_t_1 != 0); - if (__pyx_t_6) { + __pyx_t_3 = (__pyx_v___pyx_state != Py_None); + __pyx_t_2 = (__pyx_t_3 != 0); + if (__pyx_t_2) { /* "(tree fragment)":9 * __pyx_result = RawRequestMessage.__new__(__pyx_type) @@ -15241,12 +15091,12 @@ static PyObject *__pyx_pf_7aiohttp_12_http_parser_2__pyx_unpickle_RawRequestMess * cdef __pyx_unpickle_RawRequestMessage__set_state(RawRequestMessage __pyx_result, tuple __pyx_state): */ if (!(likely(PyTuple_CheckExact(__pyx_v___pyx_state))||((__pyx_v___pyx_state) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_v___pyx_state)->tp_name), 0))) __PYX_ERR(1, 9, __pyx_L1_error) - __pyx_t_3 = __pyx_f_7aiohttp_12_http_parser___pyx_unpickle_RawRequestMessage__set_state(((struct __pyx_obj_7aiohttp_12_http_parser_RawRequestMessage *)__pyx_v___pyx_result), ((PyObject*)__pyx_v___pyx_state)); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 9, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_4 = __pyx_f_7aiohttp_12_http_parser___pyx_unpickle_RawRequestMessage__set_state(((struct __pyx_obj_7aiohttp_12_http_parser_RawRequestMessage *)__pyx_v___pyx_result), ((PyObject*)__pyx_v___pyx_state)); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 9, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; /* "(tree fragment)":8 - * raise __pyx_PickleError("Incompatible checksums (%s vs 0x1408252 = (chunked, compression, headers, method, path, raw_headers, should_close, upgrade, url, version))" % __pyx_checksum) + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0x1408252, 0xf602a9f, 0x03e51e3) = (chunked, compression, headers, method, path, raw_headers, should_close, upgrade, url, version))" % __pyx_checksum) * __pyx_result = RawRequestMessage.__new__(__pyx_type) * if __pyx_state is not None: # <<<<<<<<<<<<<< * __pyx_unpickle_RawRequestMessage__set_state( __pyx_result, __pyx_state) @@ -15274,10 +15124,10 @@ static PyObject *__pyx_pf_7aiohttp_12_http_parser_2__pyx_unpickle_RawRequestMess /* function exit code */ __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_2); - __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_1); __Pyx_XDECREF(__pyx_t_4); __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); __Pyx_AddTraceback("aiohttp._http_parser.__pyx_unpickle_RawRequestMessage", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = NULL; __pyx_L0:; @@ -15528,9 +15378,9 @@ static PyObject *__pyx_f_7aiohttp_12_http_parser___pyx_unpickle_RawRequestMessag */ /* Python wrapper */ -static PyObject *__pyx_pw_7aiohttp_12_http_parser_5__pyx_unpickle_RawResponseMessage(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ -static PyMethodDef __pyx_mdef_7aiohttp_12_http_parser_5__pyx_unpickle_RawResponseMessage = {"__pyx_unpickle_RawResponseMessage", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_7aiohttp_12_http_parser_5__pyx_unpickle_RawResponseMessage, METH_VARARGS|METH_KEYWORDS, 0}; -static PyObject *__pyx_pw_7aiohttp_12_http_parser_5__pyx_unpickle_RawResponseMessage(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { +static PyObject *__pyx_pw_7aiohttp_12_http_parser_3__pyx_unpickle_RawResponseMessage(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static PyMethodDef __pyx_mdef_7aiohttp_12_http_parser_3__pyx_unpickle_RawResponseMessage = {"__pyx_unpickle_RawResponseMessage", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_7aiohttp_12_http_parser_3__pyx_unpickle_RawResponseMessage, METH_VARARGS|METH_KEYWORDS, 0}; +static PyObject *__pyx_pw_7aiohttp_12_http_parser_3__pyx_unpickle_RawResponseMessage(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { PyObject *__pyx_v___pyx_type = 0; long __pyx_v___pyx_checksum; PyObject *__pyx_v___pyx_state = 0; @@ -15596,24 +15446,24 @@ static PyObject *__pyx_pw_7aiohttp_12_http_parser_5__pyx_unpickle_RawResponseMes __Pyx_RefNannyFinishContext(); return NULL; __pyx_L4_argument_unpacking_done:; - __pyx_r = __pyx_pf_7aiohttp_12_http_parser_4__pyx_unpickle_RawResponseMessage(__pyx_self, __pyx_v___pyx_type, __pyx_v___pyx_checksum, __pyx_v___pyx_state); + __pyx_r = __pyx_pf_7aiohttp_12_http_parser_2__pyx_unpickle_RawResponseMessage(__pyx_self, __pyx_v___pyx_type, __pyx_v___pyx_checksum, __pyx_v___pyx_state); /* function exit code */ __Pyx_RefNannyFinishContext(); return __pyx_r; } -static PyObject *__pyx_pf_7aiohttp_12_http_parser_4__pyx_unpickle_RawResponseMessage(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v___pyx_type, long __pyx_v___pyx_checksum, PyObject *__pyx_v___pyx_state) { +static PyObject *__pyx_pf_7aiohttp_12_http_parser_2__pyx_unpickle_RawResponseMessage(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v___pyx_type, long __pyx_v___pyx_checksum, PyObject *__pyx_v___pyx_state) { PyObject *__pyx_v___pyx_PickleError = 0; PyObject *__pyx_v___pyx_result = 0; PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations - int __pyx_t_1; - PyObject *__pyx_t_2 = NULL; - PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_1 = NULL; + int __pyx_t_2; + int __pyx_t_3; PyObject *__pyx_t_4 = NULL; PyObject *__pyx_t_5 = NULL; - int __pyx_t_6; + PyObject *__pyx_t_6 = NULL; int __pyx_lineno = 0; const char *__pyx_filename = NULL; int __pyx_clineno = 0; @@ -15622,114 +15472,118 @@ static PyObject *__pyx_pf_7aiohttp_12_http_parser_4__pyx_unpickle_RawResponseMes /* "(tree fragment)":4 * cdef object __pyx_PickleError * cdef object __pyx_result - * if __pyx_checksum != 0xc7706dc: # <<<<<<<<<<<<<< + * if __pyx_checksum not in (0xc7706dc, 0xcb2b2ba, 0x4febc0e): # <<<<<<<<<<<<<< * from pickle import PickleError as __pyx_PickleError - * raise __pyx_PickleError("Incompatible checksums (%s vs 0xc7706dc = (chunked, code, compression, headers, raw_headers, reason, should_close, upgrade, version))" % __pyx_checksum) + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0xc7706dc, 0xcb2b2ba, 0x4febc0e) = (chunked, code, compression, headers, raw_headers, reason, should_close, upgrade, version))" % __pyx_checksum) */ - __pyx_t_1 = ((__pyx_v___pyx_checksum != 0xc7706dc) != 0); - if (__pyx_t_1) { + __pyx_t_1 = __Pyx_PyInt_From_long(__pyx_v___pyx_checksum); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 4, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = (__Pyx_PySequence_ContainsTF(__pyx_t_1, __pyx_tuple__18, Py_NE)); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(1, 4, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_3 = (__pyx_t_2 != 0); + if (__pyx_t_3) { /* "(tree fragment)":5 * cdef object __pyx_result - * if __pyx_checksum != 0xc7706dc: + * if __pyx_checksum not in (0xc7706dc, 0xcb2b2ba, 0x4febc0e): * from pickle import PickleError as __pyx_PickleError # <<<<<<<<<<<<<< - * raise __pyx_PickleError("Incompatible checksums (%s vs 0xc7706dc = (chunked, code, compression, headers, raw_headers, reason, should_close, upgrade, version))" % __pyx_checksum) + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0xc7706dc, 0xcb2b2ba, 0x4febc0e) = (chunked, code, compression, headers, raw_headers, reason, should_close, upgrade, version))" % __pyx_checksum) * __pyx_result = RawResponseMessage.__new__(__pyx_type) */ - __pyx_t_2 = PyList_New(1); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 5, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); + __pyx_t_1 = PyList_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); __Pyx_INCREF(__pyx_n_s_PickleError); __Pyx_GIVEREF(__pyx_n_s_PickleError); - PyList_SET_ITEM(__pyx_t_2, 0, __pyx_n_s_PickleError); - __pyx_t_3 = __Pyx_Import(__pyx_n_s_pickle, __pyx_t_2, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 5, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_2 = __Pyx_ImportFrom(__pyx_t_3, __pyx_n_s_PickleError); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 5, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __Pyx_INCREF(__pyx_t_2); - __pyx_v___pyx_PickleError = __pyx_t_2; - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + PyList_SET_ITEM(__pyx_t_1, 0, __pyx_n_s_PickleError); + __pyx_t_4 = __Pyx_Import(__pyx_n_s_pickle, __pyx_t_1, 0); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_4, __pyx_n_s_PickleError); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_t_1); + __pyx_v___pyx_PickleError = __pyx_t_1; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; /* "(tree fragment)":6 - * if __pyx_checksum != 0xc7706dc: + * if __pyx_checksum not in (0xc7706dc, 0xcb2b2ba, 0x4febc0e): * from pickle import PickleError as __pyx_PickleError - * raise __pyx_PickleError("Incompatible checksums (%s vs 0xc7706dc = (chunked, code, compression, headers, raw_headers, reason, should_close, upgrade, version))" % __pyx_checksum) # <<<<<<<<<<<<<< + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0xc7706dc, 0xcb2b2ba, 0x4febc0e) = (chunked, code, compression, headers, raw_headers, reason, should_close, upgrade, version))" % __pyx_checksum) # <<<<<<<<<<<<<< * __pyx_result = RawResponseMessage.__new__(__pyx_type) * if __pyx_state is not None: */ - __pyx_t_2 = __Pyx_PyInt_From_long(__pyx_v___pyx_checksum); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 6, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_4 = __Pyx_PyString_Format(__pyx_kp_s_Incompatible_checksums_s_vs_0xc7, __pyx_t_2); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 6, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_1 = __Pyx_PyInt_From_long(__pyx_v___pyx_checksum); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_5 = __Pyx_PyString_Format(__pyx_kp_s_Incompatible_checksums_0x_x_vs_0_2, __pyx_t_1); if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __Pyx_INCREF(__pyx_v___pyx_PickleError); - __pyx_t_2 = __pyx_v___pyx_PickleError; __pyx_t_5 = NULL; - if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) { - __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_2); - if (likely(__pyx_t_5)) { - PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2); - __Pyx_INCREF(__pyx_t_5); + __pyx_t_1 = __pyx_v___pyx_PickleError; __pyx_t_6 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_1))) { + __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_1); + if (likely(__pyx_t_6)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1); + __Pyx_INCREF(__pyx_t_6); __Pyx_INCREF(function); - __Pyx_DECREF_SET(__pyx_t_2, function); + __Pyx_DECREF_SET(__pyx_t_1, function); } } - __pyx_t_3 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_5, __pyx_t_4) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_4); - __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_4 = (__pyx_t_6) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_6, __pyx_t_5) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_Raise(__pyx_t_4, 0, 0, 0); __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 6, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __Pyx_Raise(__pyx_t_3, 0, 0, 0); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __PYX_ERR(1, 6, __pyx_L1_error) /* "(tree fragment)":4 * cdef object __pyx_PickleError * cdef object __pyx_result - * if __pyx_checksum != 0xc7706dc: # <<<<<<<<<<<<<< + * if __pyx_checksum not in (0xc7706dc, 0xcb2b2ba, 0x4febc0e): # <<<<<<<<<<<<<< * from pickle import PickleError as __pyx_PickleError - * raise __pyx_PickleError("Incompatible checksums (%s vs 0xc7706dc = (chunked, code, compression, headers, raw_headers, reason, should_close, upgrade, version))" % __pyx_checksum) + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0xc7706dc, 0xcb2b2ba, 0x4febc0e) = (chunked, code, compression, headers, raw_headers, reason, should_close, upgrade, version))" % __pyx_checksum) */ } /* "(tree fragment)":7 * from pickle import PickleError as __pyx_PickleError - * raise __pyx_PickleError("Incompatible checksums (%s vs 0xc7706dc = (chunked, code, compression, headers, raw_headers, reason, should_close, upgrade, version))" % __pyx_checksum) + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0xc7706dc, 0xcb2b2ba, 0x4febc0e) = (chunked, code, compression, headers, raw_headers, reason, should_close, upgrade, version))" % __pyx_checksum) * __pyx_result = RawResponseMessage.__new__(__pyx_type) # <<<<<<<<<<<<<< * if __pyx_state is not None: * __pyx_unpickle_RawResponseMessage__set_state( __pyx_result, __pyx_state) */ - __pyx_t_2 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_ptype_7aiohttp_12_http_parser_RawResponseMessage), __pyx_n_s_new); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 7, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_4 = NULL; - if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) { - __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_2); - if (likely(__pyx_t_4)) { - PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2); - __Pyx_INCREF(__pyx_t_4); + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_ptype_7aiohttp_12_http_parser_RawResponseMessage), __pyx_n_s_new); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 7, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_5 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_1))) { + __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_1); + if (likely(__pyx_t_5)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1); + __Pyx_INCREF(__pyx_t_5); __Pyx_INCREF(function); - __Pyx_DECREF_SET(__pyx_t_2, function); + __Pyx_DECREF_SET(__pyx_t_1, function); } } - __pyx_t_3 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_4, __pyx_v___pyx_type) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_v___pyx_type); - __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; - if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 7, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_v___pyx_result = __pyx_t_3; - __pyx_t_3 = 0; + __pyx_t_4 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_5, __pyx_v___pyx_type) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_v___pyx_type); + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 7, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v___pyx_result = __pyx_t_4; + __pyx_t_4 = 0; /* "(tree fragment)":8 - * raise __pyx_PickleError("Incompatible checksums (%s vs 0xc7706dc = (chunked, code, compression, headers, raw_headers, reason, should_close, upgrade, version))" % __pyx_checksum) + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0xc7706dc, 0xcb2b2ba, 0x4febc0e) = (chunked, code, compression, headers, raw_headers, reason, should_close, upgrade, version))" % __pyx_checksum) * __pyx_result = RawResponseMessage.__new__(__pyx_type) * if __pyx_state is not None: # <<<<<<<<<<<<<< * __pyx_unpickle_RawResponseMessage__set_state( __pyx_result, __pyx_state) * return __pyx_result */ - __pyx_t_1 = (__pyx_v___pyx_state != Py_None); - __pyx_t_6 = (__pyx_t_1 != 0); - if (__pyx_t_6) { + __pyx_t_3 = (__pyx_v___pyx_state != Py_None); + __pyx_t_2 = (__pyx_t_3 != 0); + if (__pyx_t_2) { /* "(tree fragment)":9 * __pyx_result = RawResponseMessage.__new__(__pyx_type) @@ -15739,12 +15593,12 @@ static PyObject *__pyx_pf_7aiohttp_12_http_parser_4__pyx_unpickle_RawResponseMes * cdef __pyx_unpickle_RawResponseMessage__set_state(RawResponseMessage __pyx_result, tuple __pyx_state): */ if (!(likely(PyTuple_CheckExact(__pyx_v___pyx_state))||((__pyx_v___pyx_state) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_v___pyx_state)->tp_name), 0))) __PYX_ERR(1, 9, __pyx_L1_error) - __pyx_t_3 = __pyx_f_7aiohttp_12_http_parser___pyx_unpickle_RawResponseMessage__set_state(((struct __pyx_obj_7aiohttp_12_http_parser_RawResponseMessage *)__pyx_v___pyx_result), ((PyObject*)__pyx_v___pyx_state)); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 9, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_4 = __pyx_f_7aiohttp_12_http_parser___pyx_unpickle_RawResponseMessage__set_state(((struct __pyx_obj_7aiohttp_12_http_parser_RawResponseMessage *)__pyx_v___pyx_result), ((PyObject*)__pyx_v___pyx_state)); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 9, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; /* "(tree fragment)":8 - * raise __pyx_PickleError("Incompatible checksums (%s vs 0xc7706dc = (chunked, code, compression, headers, raw_headers, reason, should_close, upgrade, version))" % __pyx_checksum) + * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0xc7706dc, 0xcb2b2ba, 0x4febc0e) = (chunked, code, compression, headers, raw_headers, reason, should_close, upgrade, version))" % __pyx_checksum) * __pyx_result = RawResponseMessage.__new__(__pyx_type) * if __pyx_state is not None: # <<<<<<<<<<<<<< * __pyx_unpickle_RawResponseMessage__set_state( __pyx_result, __pyx_state) @@ -15772,10 +15626,10 @@ static PyObject *__pyx_pf_7aiohttp_12_http_parser_4__pyx_unpickle_RawResponseMes /* function exit code */ __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_2); - __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_1); __Pyx_XDECREF(__pyx_t_4); __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); __Pyx_AddTraceback("aiohttp._http_parser.__pyx_unpickle_RawResponseMessage", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = NULL; __pyx_L0:; @@ -16246,12 +16100,15 @@ static PyTypeObject __pyx_type_7aiohttp_12_http_parser_RawRequestMessage = { #if PY_VERSION_HEX >= 0x030400a1 0, /*tp_finalize*/ #endif - #if PY_VERSION_HEX >= 0x030800b1 + #if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800) 0, /*tp_vectorcall*/ #endif #if PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x03090000 0, /*tp_print*/ #endif + #if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 + 0, /*tp_pypy_flags*/ + #endif }; static struct __pyx_obj_7aiohttp_12_http_parser_RawResponseMessage *__pyx_freelist_7aiohttp_12_http_parser_RawResponseMessage[250]; @@ -16478,12 +16335,15 @@ static PyTypeObject __pyx_type_7aiohttp_12_http_parser_RawResponseMessage = { #if PY_VERSION_HEX >= 0x030400a1 0, /*tp_finalize*/ #endif - #if PY_VERSION_HEX >= 0x030800b1 + #if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800) 0, /*tp_vectorcall*/ #endif #if PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x03090000 0, /*tp_print*/ #endif + #if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 + 0, /*tp_pypy_flags*/ + #endif }; static struct __pyx_vtabstruct_7aiohttp_12_http_parser_HttpParser __pyx_vtable_7aiohttp_12_http_parser_HttpParser; @@ -16703,12 +16563,15 @@ static PyTypeObject __pyx_type_7aiohttp_12_http_parser_HttpParser = { #if PY_VERSION_HEX >= 0x030400a1 0, /*tp_finalize*/ #endif - #if PY_VERSION_HEX >= 0x030800b1 + #if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800) 0, /*tp_vectorcall*/ #endif #if PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x03090000 0, /*tp_print*/ #endif + #if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 + 0, /*tp_pypy_flags*/ + #endif }; static struct __pyx_vtabstruct_7aiohttp_12_http_parser_HttpRequestParser __pyx_vtable_7aiohttp_12_http_parser_HttpRequestParser; @@ -16788,12 +16651,15 @@ static PyTypeObject __pyx_type_7aiohttp_12_http_parser_HttpRequestParser = { #if PY_VERSION_HEX >= 0x030400a1 0, /*tp_finalize*/ #endif - #if PY_VERSION_HEX >= 0x030800b1 + #if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800) 0, /*tp_vectorcall*/ #endif #if PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x03090000 0, /*tp_print*/ #endif + #if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 + 0, /*tp_pypy_flags*/ + #endif }; static struct __pyx_vtabstruct_7aiohttp_12_http_parser_HttpResponseParser __pyx_vtable_7aiohttp_12_http_parser_HttpResponseParser; @@ -16873,12 +16739,15 @@ static PyTypeObject __pyx_type_7aiohttp_12_http_parser_HttpResponseParser = { #if PY_VERSION_HEX >= 0x030400a1 0, /*tp_finalize*/ #endif - #if PY_VERSION_HEX >= 0x030800b1 + #if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800) 0, /*tp_vectorcall*/ #endif #if PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x03090000 0, /*tp_print*/ #endif + #if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 + 0, /*tp_pypy_flags*/ + #endif }; static struct __pyx_obj_7aiohttp_12_http_parser___pyx_scope_struct____repr__ *__pyx_freelist_7aiohttp_12_http_parser___pyx_scope_struct____repr__[8]; @@ -16988,12 +16857,15 @@ static PyTypeObject __pyx_type_7aiohttp_12_http_parser___pyx_scope_struct____rep #if PY_VERSION_HEX >= 0x030400a1 0, /*tp_finalize*/ #endif - #if PY_VERSION_HEX >= 0x030800b1 + #if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800) 0, /*tp_vectorcall*/ #endif #if PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x03090000 0, /*tp_print*/ #endif + #if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 + 0, /*tp_pypy_flags*/ + #endif }; static struct __pyx_obj_7aiohttp_12_http_parser___pyx_scope_struct_1_genexpr *__pyx_freelist_7aiohttp_12_http_parser___pyx_scope_struct_1_genexpr[8]; @@ -17102,12 +16974,15 @@ static PyTypeObject __pyx_type_7aiohttp_12_http_parser___pyx_scope_struct_1_gene #if PY_VERSION_HEX >= 0x030400a1 0, /*tp_finalize*/ #endif - #if PY_VERSION_HEX >= 0x030800b1 + #if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800) 0, /*tp_vectorcall*/ #endif #if PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x03090000 0, /*tp_print*/ #endif + #if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 + 0, /*tp_pypy_flags*/ + #endif }; static struct __pyx_obj_7aiohttp_12_http_parser___pyx_scope_struct_2___repr__ *__pyx_freelist_7aiohttp_12_http_parser___pyx_scope_struct_2___repr__[8]; @@ -17217,12 +17092,15 @@ static PyTypeObject __pyx_type_7aiohttp_12_http_parser___pyx_scope_struct_2___re #if PY_VERSION_HEX >= 0x030400a1 0, /*tp_finalize*/ #endif - #if PY_VERSION_HEX >= 0x030800b1 + #if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800) 0, /*tp_vectorcall*/ #endif #if PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x03090000 0, /*tp_print*/ #endif + #if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 + 0, /*tp_pypy_flags*/ + #endif }; static struct __pyx_obj_7aiohttp_12_http_parser___pyx_scope_struct_3_genexpr *__pyx_freelist_7aiohttp_12_http_parser___pyx_scope_struct_3_genexpr[8]; @@ -17331,12 +17209,15 @@ static PyTypeObject __pyx_type_7aiohttp_12_http_parser___pyx_scope_struct_3_gene #if PY_VERSION_HEX >= 0x030400a1 0, /*tp_finalize*/ #endif - #if PY_VERSION_HEX >= 0x030800b1 + #if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800) 0, /*tp_vectorcall*/ #endif #if PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x03090000 0, /*tp_print*/ #endif + #if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 + 0, /*tp_pypy_flags*/ + #endif }; static PyMethodDef __pyx_methods[] = { @@ -17423,6 +17304,7 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = { {&__pyx_n_s_COOKIE, __pyx_k_COOKIE, sizeof(__pyx_k_COOKIE), 0, 0, 1, 1}, {&__pyx_n_s_ContentLengthError, __pyx_k_ContentLengthError, sizeof(__pyx_k_ContentLengthError), 0, 0, 1, 1}, {&__pyx_n_s_DATE, __pyx_k_DATE, sizeof(__pyx_k_DATE), 0, 0, 1, 1}, + {&__pyx_n_s_DEBUG, __pyx_k_DEBUG, sizeof(__pyx_k_DEBUG), 0, 0, 1, 1}, {&__pyx_n_s_DESTINATION, __pyx_k_DESTINATION, sizeof(__pyx_k_DESTINATION), 0, 0, 1, 1}, {&__pyx_n_s_DIGEST, __pyx_k_DIGEST, sizeof(__pyx_k_DIGEST), 0, 0, 1, 1}, {&__pyx_n_s_DeflateBuffer, __pyx_k_DeflateBuffer, sizeof(__pyx_k_DeflateBuffer), 0, 0, 1, 1}, @@ -17452,8 +17334,8 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = { {&__pyx_n_s_IF_NONE_MATCH, __pyx_k_IF_NONE_MATCH, sizeof(__pyx_k_IF_NONE_MATCH), 0, 0, 1, 1}, {&__pyx_n_s_IF_RANGE, __pyx_k_IF_RANGE, sizeof(__pyx_k_IF_RANGE), 0, 0, 1, 1}, {&__pyx_n_s_IF_UNMODIFIED_SINCE, __pyx_k_IF_UNMODIFIED_SINCE, sizeof(__pyx_k_IF_UNMODIFIED_SINCE), 0, 0, 1, 1}, - {&__pyx_kp_s_Incompatible_checksums_s_vs_0x14, __pyx_k_Incompatible_checksums_s_vs_0x14, sizeof(__pyx_k_Incompatible_checksums_s_vs_0x14), 0, 0, 1, 0}, - {&__pyx_kp_s_Incompatible_checksums_s_vs_0xc7, __pyx_k_Incompatible_checksums_s_vs_0xc7, sizeof(__pyx_k_Incompatible_checksums_s_vs_0xc7), 0, 0, 1, 0}, + {&__pyx_kp_s_Incompatible_checksums_0x_x_vs_0, __pyx_k_Incompatible_checksums_0x_x_vs_0, sizeof(__pyx_k_Incompatible_checksums_0x_x_vs_0), 0, 0, 1, 0}, + {&__pyx_kp_s_Incompatible_checksums_0x_x_vs_0_2, __pyx_k_Incompatible_checksums_0x_x_vs_0_2, sizeof(__pyx_k_Incompatible_checksums_0x_x_vs_0_2), 0, 0, 1, 0}, {&__pyx_n_s_InvalidHeader, __pyx_k_InvalidHeader, sizeof(__pyx_k_InvalidHeader), 0, 0, 1, 1}, {&__pyx_n_s_InvalidURLError, __pyx_k_InvalidURLError, sizeof(__pyx_k_InvalidURLError), 0, 0, 1, 1}, {&__pyx_n_s_KEEP_ALIVE, __pyx_k_KEEP_ALIVE, sizeof(__pyx_k_KEEP_ALIVE), 0, 0, 1, 1}, @@ -17511,21 +17393,25 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = { {&__pyx_n_s_X_FORWARDED_HOST, __pyx_k_X_FORWARDED_HOST, sizeof(__pyx_k_X_FORWARDED_HOST), 0, 0, 1, 1}, {&__pyx_n_s_X_FORWARDED_PROTO, __pyx_k_X_FORWARDED_PROTO, sizeof(__pyx_k_X_FORWARDED_PROTO), 0, 0, 1, 1}, {&__pyx_kp_u__11, __pyx_k__11, sizeof(__pyx_k__11), 0, 1, 0, 0}, + {&__pyx_kp_u__12, __pyx_k__12, sizeof(__pyx_k__12), 0, 1, 0, 0}, {&__pyx_kp_u__2, __pyx_k__2, sizeof(__pyx_k__2), 0, 1, 0, 0}, {&__pyx_kp_u__3, __pyx_k__3, sizeof(__pyx_k__3), 0, 1, 0, 0}, - {&__pyx_n_s__4, __pyx_k__4, sizeof(__pyx_k__4), 0, 0, 1, 1}, {&__pyx_kp_b__4, __pyx_k__4, sizeof(__pyx_k__4), 0, 0, 0, 0}, - {&__pyx_kp_u__4, __pyx_k__4, sizeof(__pyx_k__4), 0, 1, 0, 0}, + {&__pyx_kp_u__6, __pyx_k__6, sizeof(__pyx_k__6), 0, 1, 0, 0}, + {&__pyx_kp_u__7, __pyx_k__7, sizeof(__pyx_k__7), 0, 1, 0, 0}, + {&__pyx_n_s__8, __pyx_k__8, sizeof(__pyx_k__8), 0, 0, 1, 1}, + {&__pyx_kp_b__8, __pyx_k__8, sizeof(__pyx_k__8), 0, 0, 0, 0}, + {&__pyx_kp_u__8, __pyx_k__8, sizeof(__pyx_k__8), 0, 1, 0, 0}, {&__pyx_n_s_add, __pyx_k_add, sizeof(__pyx_k_add), 0, 0, 1, 1}, {&__pyx_n_s_aiohttp, __pyx_k_aiohttp, sizeof(__pyx_k_aiohttp), 0, 0, 1, 1}, {&__pyx_n_s_aiohttp__http_parser, __pyx_k_aiohttp__http_parser, sizeof(__pyx_k_aiohttp__http_parser), 0, 0, 1, 1}, - {&__pyx_kp_s_aiohttp__http_parser_pyx, __pyx_k_aiohttp__http_parser_pyx, sizeof(__pyx_k_aiohttp__http_parser_pyx), 0, 0, 1, 0}, + {&__pyx_n_s_aiohttp_helpers, __pyx_k_aiohttp_helpers, sizeof(__pyx_k_aiohttp_helpers), 0, 0, 1, 1}, {&__pyx_n_s_all, __pyx_k_all, sizeof(__pyx_k_all), 0, 0, 1, 1}, {&__pyx_n_s_args, __pyx_k_args, sizeof(__pyx_k_args), 0, 0, 1, 1}, + {&__pyx_n_s_authority, __pyx_k_authority, sizeof(__pyx_k_authority), 0, 0, 1, 1}, {&__pyx_n_s_auto_decompress, __pyx_k_auto_decompress, sizeof(__pyx_k_auto_decompress), 0, 0, 1, 1}, {&__pyx_n_s_begin_http_chunk_receiving, __pyx_k_begin_http_chunk_receiving, sizeof(__pyx_k_begin_http_chunk_receiving), 0, 0, 1, 1}, {&__pyx_n_u_br, __pyx_k_br, sizeof(__pyx_k_br), 0, 1, 0, 1}, - {&__pyx_n_s_buf_data, __pyx_k_buf_data, sizeof(__pyx_k_buf_data), 0, 0, 1, 1}, {&__pyx_n_s_build, __pyx_k_build, sizeof(__pyx_k_build), 0, 0, 1, 1}, {&__pyx_n_s_chunked, __pyx_k_chunked, sizeof(__pyx_k_chunked), 0, 0, 1, 1}, {&__pyx_n_u_chunked, __pyx_k_chunked, sizeof(__pyx_k_chunked), 0, 1, 0, 1}, @@ -17539,6 +17425,7 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = { {&__pyx_n_s_dict, __pyx_k_dict, sizeof(__pyx_k_dict), 0, 0, 1, 1}, {&__pyx_n_s_encoded, __pyx_k_encoded, sizeof(__pyx_k_encoded), 0, 0, 1, 1}, {&__pyx_n_s_end_http_chunk_receiving, __pyx_k_end_http_chunk_receiving, sizeof(__pyx_k_end_http_chunk_receiving), 0, 0, 1, 1}, + {&__pyx_n_s_error, __pyx_k_error, sizeof(__pyx_k_error), 0, 0, 1, 1}, {&__pyx_n_s_feed_data, __pyx_k_feed_data, sizeof(__pyx_k_feed_data), 0, 0, 1, 1}, {&__pyx_n_s_feed_eof, __pyx_k_feed_eof, sizeof(__pyx_k_feed_eof), 0, 0, 1, 1}, {&__pyx_n_s_format, __pyx_k_format, sizeof(__pyx_k_format), 0, 0, 1, 1}, @@ -17549,13 +17436,11 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = { {&__pyx_n_s_hdrs, __pyx_k_hdrs, sizeof(__pyx_k_hdrs), 0, 0, 1, 1}, {&__pyx_n_s_headers, __pyx_k_headers, sizeof(__pyx_k_headers), 0, 0, 1, 1}, {&__pyx_n_u_headers, __pyx_k_headers, sizeof(__pyx_k_headers), 0, 1, 0, 1}, - {&__pyx_n_s_host, __pyx_k_host, sizeof(__pyx_k_host), 0, 0, 1, 1}, {&__pyx_n_s_http_exceptions, __pyx_k_http_exceptions, sizeof(__pyx_k_http_exceptions), 0, 0, 1, 1}, {&__pyx_n_s_http_parser, __pyx_k_http_parser, sizeof(__pyx_k_http_parser), 0, 0, 1, 1}, {&__pyx_n_s_http_writer, __pyx_k_http_writer, sizeof(__pyx_k_http_writer), 0, 0, 1, 1}, {&__pyx_n_s_i, __pyx_k_i, sizeof(__pyx_k_i), 0, 0, 1, 1}, {&__pyx_n_s_import, __pyx_k_import, sizeof(__pyx_k_import), 0, 0, 1, 1}, - {&__pyx_kp_u_invalid_url_r, __pyx_k_invalid_url_r, sizeof(__pyx_k_invalid_url_r), 0, 1, 0, 0}, {&__pyx_n_s_limit, __pyx_k_limit, sizeof(__pyx_k_limit), 0, 0, 1, 1}, {&__pyx_n_s_loop, __pyx_k_loop, sizeof(__pyx_k_loop), 0, 0, 1, 1}, {&__pyx_n_s_lower, __pyx_k_lower, sizeof(__pyx_k_lower), 0, 0, 1, 1}, @@ -17569,16 +17454,11 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = { {&__pyx_n_s_name, __pyx_k_name, sizeof(__pyx_k_name), 0, 0, 1, 1}, {&__pyx_n_s_new, __pyx_k_new, sizeof(__pyx_k_new), 0, 0, 1, 1}, {&__pyx_kp_s_no_default___reduce___due_to_non, __pyx_k_no_default___reduce___due_to_non, sizeof(__pyx_k_no_default___reduce___due_to_non), 0, 0, 1, 0}, - {&__pyx_n_s_parse_url, __pyx_k_parse_url, sizeof(__pyx_k_parse_url), 0, 0, 1, 1}, - {&__pyx_n_s_partition, __pyx_k_partition, sizeof(__pyx_k_partition), 0, 0, 1, 1}, - {&__pyx_n_s_password, __pyx_k_password, sizeof(__pyx_k_password), 0, 0, 1, 1}, {&__pyx_n_s_path, __pyx_k_path, sizeof(__pyx_k_path), 0, 0, 1, 1}, {&__pyx_n_u_path, __pyx_k_path, sizeof(__pyx_k_path), 0, 1, 0, 1}, {&__pyx_n_s_payload_exception, __pyx_k_payload_exception, sizeof(__pyx_k_payload_exception), 0, 0, 1, 1}, {&__pyx_n_s_pickle, __pyx_k_pickle, sizeof(__pyx_k_pickle), 0, 0, 1, 1}, - {&__pyx_n_s_port, __pyx_k_port, sizeof(__pyx_k_port), 0, 0, 1, 1}, {&__pyx_n_s_protocol, __pyx_k_protocol, sizeof(__pyx_k_protocol), 0, 0, 1, 1}, - {&__pyx_n_s_py_buf, __pyx_k_py_buf, sizeof(__pyx_k_py_buf), 0, 0, 1, 1}, {&__pyx_n_s_pyx_PickleError, __pyx_k_pyx_PickleError, sizeof(__pyx_k_pyx_PickleError), 0, 0, 1, 1}, {&__pyx_n_s_pyx_checksum, __pyx_k_pyx_checksum, sizeof(__pyx_k_pyx_checksum), 0, 0, 1, 1}, {&__pyx_n_s_pyx_result, __pyx_k_pyx_result, sizeof(__pyx_k_pyx_result), 0, 0, 1, 1}, @@ -17588,6 +17468,7 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = { {&__pyx_n_s_pyx_unpickle_RawResponseMessag, __pyx_k_pyx_unpickle_RawResponseMessag, sizeof(__pyx_k_pyx_unpickle_RawResponseMessag), 0, 0, 1, 1}, {&__pyx_n_s_pyx_vtable, __pyx_k_pyx_vtable, sizeof(__pyx_k_pyx_vtable), 0, 0, 1, 1}, {&__pyx_n_s_query_string, __pyx_k_query_string, sizeof(__pyx_k_query_string), 0, 0, 1, 1}, + {&__pyx_kp_u_r, __pyx_k_r, sizeof(__pyx_k_r), 0, 1, 0, 0}, {&__pyx_n_s_range, __pyx_k_range, sizeof(__pyx_k_range), 0, 0, 1, 1}, {&__pyx_n_s_raw_headers, __pyx_k_raw_headers, sizeof(__pyx_k_raw_headers), 0, 0, 1, 1}, {&__pyx_n_u_raw_headers, __pyx_k_raw_headers, sizeof(__pyx_k_raw_headers), 0, 1, 0, 1}, @@ -17599,13 +17480,14 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = { {&__pyx_n_s_reduce_ex, __pyx_k_reduce_ex, sizeof(__pyx_k_reduce_ex), 0, 0, 1, 1}, {&__pyx_n_s_repr___locals_genexpr, __pyx_k_repr___locals_genexpr, sizeof(__pyx_k_repr___locals_genexpr), 0, 0, 1, 1}, {&__pyx_n_s_response_with_body, __pyx_k_response_with_body, sizeof(__pyx_k_response_with_body), 0, 0, 1, 1}, - {&__pyx_n_s_scheme, __pyx_k_scheme, sizeof(__pyx_k_scheme), 0, 0, 1, 1}, + {&__pyx_n_s_rsplit, __pyx_k_rsplit, sizeof(__pyx_k_rsplit), 0, 0, 1, 1}, {&__pyx_n_s_send, __pyx_k_send, sizeof(__pyx_k_send), 0, 0, 1, 1}, {&__pyx_n_s_set_exception, __pyx_k_set_exception, sizeof(__pyx_k_set_exception), 0, 0, 1, 1}, {&__pyx_n_s_setstate, __pyx_k_setstate, sizeof(__pyx_k_setstate), 0, 0, 1, 1}, {&__pyx_n_s_setstate_cython, __pyx_k_setstate_cython, sizeof(__pyx_k_setstate_cython), 0, 0, 1, 1}, {&__pyx_n_s_should_close, __pyx_k_should_close, sizeof(__pyx_k_should_close), 0, 0, 1, 1}, {&__pyx_n_u_should_close, __pyx_k_should_close, sizeof(__pyx_k_should_close), 0, 1, 0, 1}, + {&__pyx_n_s_split, __pyx_k_split, sizeof(__pyx_k_split), 0, 0, 1, 1}, {&__pyx_n_s_streams, __pyx_k_streams, sizeof(__pyx_k_streams), 0, 0, 1, 1}, {&__pyx_kp_s_stringsource, __pyx_k_stringsource, sizeof(__pyx_k_stringsource), 0, 0, 1, 0}, {&__pyx_n_s_test, __pyx_k_test, sizeof(__pyx_k_test), 0, 0, 1, 1}, @@ -17617,7 +17499,6 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = { {&__pyx_n_u_upgrade, __pyx_k_upgrade, sizeof(__pyx_k_upgrade), 0, 1, 0, 1}, {&__pyx_n_s_url, __pyx_k_url, sizeof(__pyx_k_url), 0, 0, 1, 1}, {&__pyx_n_u_url, __pyx_k_url, sizeof(__pyx_k_url), 0, 1, 0, 1}, - {&__pyx_n_s_user, __pyx_k_user, sizeof(__pyx_k_user), 0, 0, 1, 1}, {&__pyx_n_s_version, __pyx_k_version, sizeof(__pyx_k_version), 0, 0, 1, 1}, {&__pyx_n_u_version, __pyx_k_version, sizeof(__pyx_k_version), 0, 1, 0, 1}, {&__pyx_n_s_yarl, __pyx_k_yarl, sizeof(__pyx_k_yarl), 0, 0, 1, 1}, @@ -17627,7 +17508,7 @@ static CYTHON_SMALL_CODE int __Pyx_InitCachedBuiltins(void) { __pyx_builtin_range = __Pyx_GetBuiltinName(__pyx_n_s_range); if (!__pyx_builtin_range) __PYX_ERR(0, 87, __pyx_L1_error) __pyx_builtin_MemoryError = __Pyx_GetBuiltinName(__pyx_n_s_MemoryError); if (!__pyx_builtin_MemoryError) __PYX_ERR(0, 316, __pyx_L1_error) __pyx_builtin_TypeError = __Pyx_GetBuiltinName(__pyx_n_s_TypeError); if (!__pyx_builtin_TypeError) __PYX_ERR(1, 2, __pyx_L1_error) - __pyx_builtin_BaseException = __Pyx_GetBuiltinName(__pyx_n_s_BaseException); if (!__pyx_builtin_BaseException) __PYX_ERR(0, 631, __pyx_L1_error) + __pyx_builtin_BaseException = __Pyx_GetBuiltinName(__pyx_n_s_BaseException); if (!__pyx_builtin_BaseException) __PYX_ERR(0, 684, __pyx_L1_error) return 0; __pyx_L1_error:; return -1; @@ -17637,24 +17518,35 @@ static CYTHON_SMALL_CODE int __Pyx_InitCachedConstants(void) { __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("__Pyx_InitCachedConstants", 0); + /* "aiohttp/_http_parser.pyx":551 + * after = cparser.llhttp_get_error_pos(self._cparser) + * before = data[:after - self.py_buf.buf] + * after_b = after.split(b"\r\n", 1)[0] # <<<<<<<<<<<<<< + * before = before.rsplit(b"\r\n", 1)[-1] + * data = before + after_b + */ + __pyx_tuple__5 = PyTuple_Pack(2, __pyx_kp_b__4, __pyx_int_1); if (unlikely(!__pyx_tuple__5)) __PYX_ERR(0, 551, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__5); + __Pyx_GIVEREF(__pyx_tuple__5); + /* "(tree fragment)":2 * def __reduce_cython__(self): * raise TypeError("no default __reduce__ due to non-trivial __cinit__") # <<<<<<<<<<<<<< * def __setstate_cython__(self, __pyx_state): * raise TypeError("no default __reduce__ due to non-trivial __cinit__") */ - __pyx_tuple__5 = PyTuple_Pack(1, __pyx_kp_s_no_default___reduce___due_to_non); if (unlikely(!__pyx_tuple__5)) __PYX_ERR(1, 2, __pyx_L1_error) - __Pyx_GOTREF(__pyx_tuple__5); - __Pyx_GIVEREF(__pyx_tuple__5); + __pyx_tuple__9 = PyTuple_Pack(1, __pyx_kp_s_no_default___reduce___due_to_non); if (unlikely(!__pyx_tuple__9)) __PYX_ERR(1, 2, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__9); + __Pyx_GIVEREF(__pyx_tuple__9); /* "(tree fragment)":4 * raise TypeError("no default __reduce__ due to non-trivial __cinit__") * def __setstate_cython__(self, __pyx_state): * raise TypeError("no default __reduce__ due to non-trivial __cinit__") # <<<<<<<<<<<<<< */ - __pyx_tuple__6 = PyTuple_Pack(1, __pyx_kp_s_no_default___reduce___due_to_non); if (unlikely(!__pyx_tuple__6)) __PYX_ERR(1, 4, __pyx_L1_error) - __Pyx_GOTREF(__pyx_tuple__6); - __Pyx_GIVEREF(__pyx_tuple__6); + __pyx_tuple__10 = PyTuple_Pack(1, __pyx_kp_s_no_default___reduce___due_to_non); if (unlikely(!__pyx_tuple__10)) __PYX_ERR(1, 4, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__10); + __Pyx_GIVEREF(__pyx_tuple__10); /* "(tree fragment)":2 * def __reduce_cython__(self): @@ -17662,18 +17554,18 @@ static CYTHON_SMALL_CODE int __Pyx_InitCachedConstants(void) { * def __setstate_cython__(self, __pyx_state): * raise TypeError("no default __reduce__ due to non-trivial __cinit__") */ - __pyx_tuple__7 = PyTuple_Pack(1, __pyx_kp_s_no_default___reduce___due_to_non); if (unlikely(!__pyx_tuple__7)) __PYX_ERR(1, 2, __pyx_L1_error) - __Pyx_GOTREF(__pyx_tuple__7); - __Pyx_GIVEREF(__pyx_tuple__7); + __pyx_tuple__13 = PyTuple_Pack(1, __pyx_kp_s_no_default___reduce___due_to_non); if (unlikely(!__pyx_tuple__13)) __PYX_ERR(1, 2, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__13); + __Pyx_GIVEREF(__pyx_tuple__13); /* "(tree fragment)":4 * raise TypeError("no default __reduce__ due to non-trivial __cinit__") * def __setstate_cython__(self, __pyx_state): * raise TypeError("no default __reduce__ due to non-trivial __cinit__") # <<<<<<<<<<<<<< */ - __pyx_tuple__8 = PyTuple_Pack(1, __pyx_kp_s_no_default___reduce___due_to_non); if (unlikely(!__pyx_tuple__8)) __PYX_ERR(1, 4, __pyx_L1_error) - __Pyx_GOTREF(__pyx_tuple__8); - __Pyx_GIVEREF(__pyx_tuple__8); + __pyx_tuple__14 = PyTuple_Pack(1, __pyx_kp_s_no_default___reduce___due_to_non); if (unlikely(!__pyx_tuple__14)) __PYX_ERR(1, 4, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__14); + __Pyx_GIVEREF(__pyx_tuple__14); /* "(tree fragment)":2 * def __reduce_cython__(self): @@ -17681,18 +17573,24 @@ static CYTHON_SMALL_CODE int __Pyx_InitCachedConstants(void) { * def __setstate_cython__(self, __pyx_state): * raise TypeError("no default __reduce__ due to non-trivial __cinit__") */ - __pyx_tuple__9 = PyTuple_Pack(1, __pyx_kp_s_no_default___reduce___due_to_non); if (unlikely(!__pyx_tuple__9)) __PYX_ERR(1, 2, __pyx_L1_error) - __Pyx_GOTREF(__pyx_tuple__9); - __Pyx_GIVEREF(__pyx_tuple__9); + __pyx_tuple__15 = PyTuple_Pack(1, __pyx_kp_s_no_default___reduce___due_to_non); if (unlikely(!__pyx_tuple__15)) __PYX_ERR(1, 2, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__15); + __Pyx_GIVEREF(__pyx_tuple__15); /* "(tree fragment)":4 * raise TypeError("no default __reduce__ due to non-trivial __cinit__") * def __setstate_cython__(self, __pyx_state): * raise TypeError("no default __reduce__ due to non-trivial __cinit__") # <<<<<<<<<<<<<< */ - __pyx_tuple__10 = PyTuple_Pack(1, __pyx_kp_s_no_default___reduce___due_to_non); if (unlikely(!__pyx_tuple__10)) __PYX_ERR(1, 4, __pyx_L1_error) - __Pyx_GOTREF(__pyx_tuple__10); - __Pyx_GIVEREF(__pyx_tuple__10); + __pyx_tuple__16 = PyTuple_Pack(1, __pyx_kp_s_no_default___reduce___due_to_non); if (unlikely(!__pyx_tuple__16)) __PYX_ERR(1, 4, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__16); + __Pyx_GIVEREF(__pyx_tuple__16); + __pyx_tuple__17 = PyTuple_Pack(3, __pyx_int_21004882, __pyx_int_257960607, __pyx_int_4084195); if (unlikely(!__pyx_tuple__17)) __PYX_ERR(1, 4, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__17); + __Pyx_GIVEREF(__pyx_tuple__17); + __pyx_tuple__18 = PyTuple_Pack(3, __pyx_int_209127132, __pyx_int_213037754, __pyx_int_83803150); if (unlikely(!__pyx_tuple__18)) __PYX_ERR(1, 4, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__18); + __Pyx_GIVEREF(__pyx_tuple__18); /* "aiohttp/_http_parser.pyx":57 * char* PyByteArray_AsString(object) @@ -17701,35 +17599,23 @@ static CYTHON_SMALL_CODE int __Pyx_InitCachedConstants(void) { * 'RawRequestMessage', 'RawResponseMessage') * */ - __pyx_tuple__12 = PyTuple_Pack(4, __pyx_n_u_HttpRequestParser, __pyx_n_u_HttpResponseParser, __pyx_n_u_RawRequestMessage_2, __pyx_n_u_RawResponseMessage_2); if (unlikely(!__pyx_tuple__12)) __PYX_ERR(0, 57, __pyx_L1_error) - __Pyx_GOTREF(__pyx_tuple__12); - __Pyx_GIVEREF(__pyx_tuple__12); - - /* "aiohttp/_http_parser.pyx":785 - * - * - * def parse_url(url): # <<<<<<<<<<<<<< - * cdef: - * Py_buffer py_buf - */ - __pyx_tuple__13 = PyTuple_Pack(3, __pyx_n_s_url, __pyx_n_s_py_buf, __pyx_n_s_buf_data); if (unlikely(!__pyx_tuple__13)) __PYX_ERR(0, 785, __pyx_L1_error) - __Pyx_GOTREF(__pyx_tuple__13); - __Pyx_GIVEREF(__pyx_tuple__13); - __pyx_codeobj__14 = (PyObject*)__Pyx_PyCode_New(1, 0, 3, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__13, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_aiohttp__http_parser_pyx, __pyx_n_s_parse_url, 785, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__14)) __PYX_ERR(0, 785, __pyx_L1_error) + __pyx_tuple__19 = PyTuple_Pack(4, __pyx_n_u_HttpRequestParser, __pyx_n_u_HttpResponseParser, __pyx_n_u_RawRequestMessage_2, __pyx_n_u_RawResponseMessage_2); if (unlikely(!__pyx_tuple__19)) __PYX_ERR(0, 57, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__19); + __Pyx_GIVEREF(__pyx_tuple__19); /* "(tree fragment)":1 * def __pyx_unpickle_RawRequestMessage(__pyx_type, long __pyx_checksum, __pyx_state): # <<<<<<<<<<<<<< * cdef object __pyx_PickleError * cdef object __pyx_result */ - __pyx_tuple__15 = PyTuple_Pack(5, __pyx_n_s_pyx_type, __pyx_n_s_pyx_checksum, __pyx_n_s_pyx_state, __pyx_n_s_pyx_PickleError, __pyx_n_s_pyx_result); if (unlikely(!__pyx_tuple__15)) __PYX_ERR(1, 1, __pyx_L1_error) - __Pyx_GOTREF(__pyx_tuple__15); - __Pyx_GIVEREF(__pyx_tuple__15); - __pyx_codeobj__16 = (PyObject*)__Pyx_PyCode_New(3, 0, 5, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__15, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_stringsource, __pyx_n_s_pyx_unpickle_RawRequestMessage, 1, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__16)) __PYX_ERR(1, 1, __pyx_L1_error) - __pyx_tuple__17 = PyTuple_Pack(5, __pyx_n_s_pyx_type, __pyx_n_s_pyx_checksum, __pyx_n_s_pyx_state, __pyx_n_s_pyx_PickleError, __pyx_n_s_pyx_result); if (unlikely(!__pyx_tuple__17)) __PYX_ERR(1, 1, __pyx_L1_error) - __Pyx_GOTREF(__pyx_tuple__17); - __Pyx_GIVEREF(__pyx_tuple__17); - __pyx_codeobj__18 = (PyObject*)__Pyx_PyCode_New(3, 0, 5, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__17, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_stringsource, __pyx_n_s_pyx_unpickle_RawResponseMessag, 1, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__18)) __PYX_ERR(1, 1, __pyx_L1_error) + __pyx_tuple__20 = PyTuple_Pack(5, __pyx_n_s_pyx_type, __pyx_n_s_pyx_checksum, __pyx_n_s_pyx_state, __pyx_n_s_pyx_PickleError, __pyx_n_s_pyx_result); if (unlikely(!__pyx_tuple__20)) __PYX_ERR(1, 1, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__20); + __Pyx_GIVEREF(__pyx_tuple__20); + __pyx_codeobj__21 = (PyObject*)__Pyx_PyCode_New(3, 0, 5, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__20, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_stringsource, __pyx_n_s_pyx_unpickle_RawRequestMessage, 1, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__21)) __PYX_ERR(1, 1, __pyx_L1_error) + __pyx_tuple__22 = PyTuple_Pack(5, __pyx_n_s_pyx_type, __pyx_n_s_pyx_checksum, __pyx_n_s_pyx_state, __pyx_n_s_pyx_PickleError, __pyx_n_s_pyx_result); if (unlikely(!__pyx_tuple__22)) __PYX_ERR(1, 1, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__22); + __Pyx_GIVEREF(__pyx_tuple__22); + __pyx_codeobj__23 = (PyObject*)__Pyx_PyCode_New(3, 0, 5, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__22, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_stringsource, __pyx_n_s_pyx_unpickle_RawResponseMessag, 1, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__23)) __PYX_ERR(1, 1, __pyx_L1_error) __Pyx_RefNannyFinishContext(); return 0; __pyx_L1_error:; @@ -17738,10 +17624,14 @@ static CYTHON_SMALL_CODE int __Pyx_InitCachedConstants(void) { } static CYTHON_SMALL_CODE int __Pyx_InitGlobals(void) { - __pyx_umethod_PyUnicode_Type_partition.type = (PyObject*)&PyUnicode_Type; if (__Pyx_InitStrings(__pyx_string_tab) < 0) __PYX_ERR(0, 1, __pyx_L1_error); + __pyx_int_1 = PyInt_FromLong(1); if (unlikely(!__pyx_int_1)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_int_4084195 = PyInt_FromLong(4084195L); if (unlikely(!__pyx_int_4084195)) __PYX_ERR(0, 1, __pyx_L1_error) __pyx_int_21004882 = PyInt_FromLong(21004882L); if (unlikely(!__pyx_int_21004882)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_int_83803150 = PyInt_FromLong(83803150L); if (unlikely(!__pyx_int_83803150)) __PYX_ERR(0, 1, __pyx_L1_error) __pyx_int_209127132 = PyInt_FromLong(209127132L); if (unlikely(!__pyx_int_209127132)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_int_213037754 = PyInt_FromLong(213037754L); if (unlikely(!__pyx_int_213037754)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_int_257960607 = PyInt_FromLong(257960607L); if (unlikely(!__pyx_int_257960607)) __PYX_ERR(0, 1, __pyx_L1_error) return 0; __pyx_L1_error:; return -1; @@ -17821,7 +17711,7 @@ static int __Pyx_modinit_type_init_code(void) { if (__Pyx_setup_reduce((PyObject*)&__pyx_type_7aiohttp_12_http_parser_RawResponseMessage) < 0) __PYX_ERR(0, 210, __pyx_L1_error) __pyx_ptype_7aiohttp_12_http_parser_RawResponseMessage = &__pyx_type_7aiohttp_12_http_parser_RawResponseMessage; __pyx_vtabptr_7aiohttp_12_http_parser_HttpParser = &__pyx_vtable_7aiohttp_12_http_parser_HttpParser; - __pyx_vtable_7aiohttp_12_http_parser_HttpParser._init = (PyObject *(*)(struct __pyx_obj_7aiohttp_12_http_parser_HttpParser *, enum http_parser_type, PyObject *, PyObject *, int, struct __pyx_opt_args_7aiohttp_12_http_parser_10HttpParser__init *__pyx_optional_args))__pyx_f_7aiohttp_12_http_parser_10HttpParser__init; + __pyx_vtable_7aiohttp_12_http_parser_HttpParser._init = (PyObject *(*)(struct __pyx_obj_7aiohttp_12_http_parser_HttpParser *, enum llhttp_type, PyObject *, PyObject *, int, struct __pyx_opt_args_7aiohttp_12_http_parser_10HttpParser__init *__pyx_optional_args))__pyx_f_7aiohttp_12_http_parser_10HttpParser__init; __pyx_vtable_7aiohttp_12_http_parser_HttpParser._process_header = (PyObject *(*)(struct __pyx_obj_7aiohttp_12_http_parser_HttpParser *))__pyx_f_7aiohttp_12_http_parser_10HttpParser__process_header; __pyx_vtable_7aiohttp_12_http_parser_HttpParser._on_header_field = (PyObject *(*)(struct __pyx_obj_7aiohttp_12_http_parser_HttpParser *, char *, size_t))__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_header_field; __pyx_vtable_7aiohttp_12_http_parser_HttpParser._on_header_value = (PyObject *(*)(struct __pyx_obj_7aiohttp_12_http_parser_HttpParser *, char *, size_t))__pyx_f_7aiohttp_12_http_parser_10HttpParser__on_header_value; @@ -17845,31 +17735,31 @@ static int __Pyx_modinit_type_init_code(void) { __pyx_vtable_7aiohttp_12_http_parser_HttpRequestParser.__pyx_base = *__pyx_vtabptr_7aiohttp_12_http_parser_HttpParser; __pyx_vtable_7aiohttp_12_http_parser_HttpRequestParser.__pyx_base._on_status_complete = (PyObject *(*)(struct __pyx_obj_7aiohttp_12_http_parser_HttpParser *))__pyx_f_7aiohttp_12_http_parser_17HttpRequestParser__on_status_complete; __pyx_type_7aiohttp_12_http_parser_HttpRequestParser.tp_base = __pyx_ptype_7aiohttp_12_http_parser_HttpParser; - if (PyType_Ready(&__pyx_type_7aiohttp_12_http_parser_HttpRequestParser) < 0) __PYX_ERR(0, 563, __pyx_L1_error) + if (PyType_Ready(&__pyx_type_7aiohttp_12_http_parser_HttpRequestParser) < 0) __PYX_ERR(0, 574, __pyx_L1_error) #if PY_VERSION_HEX < 0x030800B1 __pyx_type_7aiohttp_12_http_parser_HttpRequestParser.tp_print = 0; #endif if ((CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP) && likely(!__pyx_type_7aiohttp_12_http_parser_HttpRequestParser.tp_dictoffset && __pyx_type_7aiohttp_12_http_parser_HttpRequestParser.tp_getattro == PyObject_GenericGetAttr)) { __pyx_type_7aiohttp_12_http_parser_HttpRequestParser.tp_getattro = __Pyx_PyObject_GenericGetAttr; } - if (__Pyx_SetVtable(__pyx_type_7aiohttp_12_http_parser_HttpRequestParser.tp_dict, __pyx_vtabptr_7aiohttp_12_http_parser_HttpRequestParser) < 0) __PYX_ERR(0, 563, __pyx_L1_error) - if (PyObject_SetAttr(__pyx_m, __pyx_n_s_HttpRequestParser, (PyObject *)&__pyx_type_7aiohttp_12_http_parser_HttpRequestParser) < 0) __PYX_ERR(0, 563, __pyx_L1_error) - if (__Pyx_setup_reduce((PyObject*)&__pyx_type_7aiohttp_12_http_parser_HttpRequestParser) < 0) __PYX_ERR(0, 563, __pyx_L1_error) + if (__Pyx_SetVtable(__pyx_type_7aiohttp_12_http_parser_HttpRequestParser.tp_dict, __pyx_vtabptr_7aiohttp_12_http_parser_HttpRequestParser) < 0) __PYX_ERR(0, 574, __pyx_L1_error) + if (PyObject_SetAttr(__pyx_m, __pyx_n_s_HttpRequestParser, (PyObject *)&__pyx_type_7aiohttp_12_http_parser_HttpRequestParser) < 0) __PYX_ERR(0, 574, __pyx_L1_error) + if (__Pyx_setup_reduce((PyObject*)&__pyx_type_7aiohttp_12_http_parser_HttpRequestParser) < 0) __PYX_ERR(0, 574, __pyx_L1_error) __pyx_ptype_7aiohttp_12_http_parser_HttpRequestParser = &__pyx_type_7aiohttp_12_http_parser_HttpRequestParser; __pyx_vtabptr_7aiohttp_12_http_parser_HttpResponseParser = &__pyx_vtable_7aiohttp_12_http_parser_HttpResponseParser; __pyx_vtable_7aiohttp_12_http_parser_HttpResponseParser.__pyx_base = *__pyx_vtabptr_7aiohttp_12_http_parser_HttpParser; __pyx_vtable_7aiohttp_12_http_parser_HttpResponseParser.__pyx_base._on_status_complete = (PyObject *(*)(struct __pyx_obj_7aiohttp_12_http_parser_HttpParser *))__pyx_f_7aiohttp_12_http_parser_18HttpResponseParser__on_status_complete; __pyx_type_7aiohttp_12_http_parser_HttpResponseParser.tp_base = __pyx_ptype_7aiohttp_12_http_parser_HttpParser; - if (PyType_Ready(&__pyx_type_7aiohttp_12_http_parser_HttpResponseParser) < 0) __PYX_ERR(0, 591, __pyx_L1_error) + if (PyType_Ready(&__pyx_type_7aiohttp_12_http_parser_HttpResponseParser) < 0) __PYX_ERR(0, 638, __pyx_L1_error) #if PY_VERSION_HEX < 0x030800B1 __pyx_type_7aiohttp_12_http_parser_HttpResponseParser.tp_print = 0; #endif if ((CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP) && likely(!__pyx_type_7aiohttp_12_http_parser_HttpResponseParser.tp_dictoffset && __pyx_type_7aiohttp_12_http_parser_HttpResponseParser.tp_getattro == PyObject_GenericGetAttr)) { __pyx_type_7aiohttp_12_http_parser_HttpResponseParser.tp_getattro = __Pyx_PyObject_GenericGetAttr; } - if (__Pyx_SetVtable(__pyx_type_7aiohttp_12_http_parser_HttpResponseParser.tp_dict, __pyx_vtabptr_7aiohttp_12_http_parser_HttpResponseParser) < 0) __PYX_ERR(0, 591, __pyx_L1_error) - if (PyObject_SetAttr(__pyx_m, __pyx_n_s_HttpResponseParser, (PyObject *)&__pyx_type_7aiohttp_12_http_parser_HttpResponseParser) < 0) __PYX_ERR(0, 591, __pyx_L1_error) - if (__Pyx_setup_reduce((PyObject*)&__pyx_type_7aiohttp_12_http_parser_HttpResponseParser) < 0) __PYX_ERR(0, 591, __pyx_L1_error) + if (__Pyx_SetVtable(__pyx_type_7aiohttp_12_http_parser_HttpResponseParser.tp_dict, __pyx_vtabptr_7aiohttp_12_http_parser_HttpResponseParser) < 0) __PYX_ERR(0, 638, __pyx_L1_error) + if (PyObject_SetAttr(__pyx_m, __pyx_n_s_HttpResponseParser, (PyObject *)&__pyx_type_7aiohttp_12_http_parser_HttpResponseParser) < 0) __PYX_ERR(0, 638, __pyx_L1_error) + if (__Pyx_setup_reduce((PyObject*)&__pyx_type_7aiohttp_12_http_parser_HttpResponseParser) < 0) __PYX_ERR(0, 638, __pyx_L1_error) __pyx_ptype_7aiohttp_12_http_parser_HttpResponseParser = &__pyx_type_7aiohttp_12_http_parser_HttpResponseParser; if (PyType_Ready(&__pyx_type_7aiohttp_12_http_parser___pyx_scope_struct____repr__) < 0) __PYX_ERR(0, 135, __pyx_L1_error) #if PY_VERSION_HEX < 0x030800B1 @@ -18136,7 +18026,7 @@ static CYTHON_SMALL_CODE int __pyx_pymod_exec__http_parser(PyObject *__pyx_pyini PyObject *__pyx_t_77 = NULL; PyObject *__pyx_t_78 = NULL; long __pyx_t_79; - enum http_method __pyx_t_80; + llhttp_method_t __pyx_t_80; char const *__pyx_t_81; int __pyx_t_82; int __pyx_lineno = 0; @@ -18189,11 +18079,9 @@ if (!__Pyx_RefNanny) { #endif /*--- Library function declarations ---*/ /*--- Threads initialization code ---*/ - #if defined(__PYX_FORCE_INIT_THREADS) && __PYX_FORCE_INIT_THREADS - #ifdef WITH_THREAD /* Python build with threading support? */ + #if defined(WITH_THREAD) && PY_VERSION_HEX < 0x030700F0 && defined(__PYX_FORCE_INIT_THREADS) && __PYX_FORCE_INIT_THREADS PyEval_InitThreads(); #endif - #endif /*--- Module creation code ---*/ #if CYTHON_PEP489_MULTI_PHASE_INIT __pyx_m = __pyx_pyinit_module; @@ -18246,14 +18134,14 @@ if (!__Pyx_RefNanny) { if (__Pyx_patch_abc() < 0) __PYX_ERR(0, 1, __pyx_L1_error) #endif - /* "aiohttp/_http_parser.pyx":19 + /* "aiohttp/_http_parser.pyx":18 * from libc.string cimport memcpy * * from multidict import CIMultiDict as _CIMultiDict, CIMultiDictProxy as _CIMultiDictProxy # <<<<<<<<<<<<<< * from yarl import URL as _URL * */ - __pyx_t_1 = PyList_New(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 19, __pyx_L1_error) + __pyx_t_1 = PyList_New(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 18, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_INCREF(__pyx_n_s_CIMultiDict); __Pyx_GIVEREF(__pyx_n_s_CIMultiDict); @@ -18261,61 +18149,82 @@ if (!__Pyx_RefNanny) { __Pyx_INCREF(__pyx_n_s_CIMultiDictProxy); __Pyx_GIVEREF(__pyx_n_s_CIMultiDictProxy); PyList_SET_ITEM(__pyx_t_1, 1, __pyx_n_s_CIMultiDictProxy); - __pyx_t_2 = __Pyx_Import(__pyx_n_s_multidict, __pyx_t_1, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 19, __pyx_L1_error) + __pyx_t_2 = __Pyx_Import(__pyx_n_s_multidict, __pyx_t_1, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 18, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_CIMultiDict); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 19, __pyx_L1_error) + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_CIMultiDict); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 18, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); - if (PyDict_SetItem(__pyx_d, __pyx_n_s_CIMultiDict_2, __pyx_t_1) < 0) __PYX_ERR(0, 19, __pyx_L1_error) + if (PyDict_SetItem(__pyx_d, __pyx_n_s_CIMultiDict_2, __pyx_t_1) < 0) __PYX_ERR(0, 18, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_CIMultiDictProxy); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 19, __pyx_L1_error) + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_CIMultiDictProxy); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 18, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); - if (PyDict_SetItem(__pyx_d, __pyx_n_s_CIMultiDictProxy_2, __pyx_t_1) < 0) __PYX_ERR(0, 19, __pyx_L1_error) + if (PyDict_SetItem(__pyx_d, __pyx_n_s_CIMultiDictProxy_2, __pyx_t_1) < 0) __PYX_ERR(0, 18, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - /* "aiohttp/_http_parser.pyx":20 + /* "aiohttp/_http_parser.pyx":19 * * from multidict import CIMultiDict as _CIMultiDict, CIMultiDictProxy as _CIMultiDictProxy * from yarl import URL as _URL # <<<<<<<<<<<<<< * * from aiohttp import hdrs */ - __pyx_t_2 = PyList_New(1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 20, __pyx_L1_error) + __pyx_t_2 = PyList_New(1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 19, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); __Pyx_INCREF(__pyx_n_s_URL); __Pyx_GIVEREF(__pyx_n_s_URL); PyList_SET_ITEM(__pyx_t_2, 0, __pyx_n_s_URL); - __pyx_t_1 = __Pyx_Import(__pyx_n_s_yarl, __pyx_t_2, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 20, __pyx_L1_error) + __pyx_t_1 = __Pyx_Import(__pyx_n_s_yarl, __pyx_t_2, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 19, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_2 = __Pyx_ImportFrom(__pyx_t_1, __pyx_n_s_URL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 20, __pyx_L1_error) + __pyx_t_2 = __Pyx_ImportFrom(__pyx_t_1, __pyx_n_s_URL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 19, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); - if (PyDict_SetItem(__pyx_d, __pyx_n_s_URL_2, __pyx_t_2) < 0) __PYX_ERR(0, 20, __pyx_L1_error) + if (PyDict_SetItem(__pyx_d, __pyx_n_s_URL_2, __pyx_t_2) < 0) __PYX_ERR(0, 19, __pyx_L1_error) __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - /* "aiohttp/_http_parser.pyx":22 + /* "aiohttp/_http_parser.pyx":21 * from yarl import URL as _URL * * from aiohttp import hdrs # <<<<<<<<<<<<<< + * from aiohttp.helpers import DEBUG * - * from .http_exceptions import ( */ - __pyx_t_1 = PyList_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 22, __pyx_L1_error) + __pyx_t_1 = PyList_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 21, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_INCREF(__pyx_n_s_hdrs); __Pyx_GIVEREF(__pyx_n_s_hdrs); PyList_SET_ITEM(__pyx_t_1, 0, __pyx_n_s_hdrs); - __pyx_t_2 = __Pyx_Import(__pyx_n_s_aiohttp, __pyx_t_1, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 22, __pyx_L1_error) + __pyx_t_2 = __Pyx_Import(__pyx_n_s_aiohttp, __pyx_t_1, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 21, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 22, __pyx_L1_error) + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 21, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); - if (PyDict_SetItem(__pyx_d, __pyx_n_s_hdrs, __pyx_t_1) < 0) __PYX_ERR(0, 22, __pyx_L1_error) + if (PyDict_SetItem(__pyx_d, __pyx_n_s_hdrs, __pyx_t_1) < 0) __PYX_ERR(0, 21, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + /* "aiohttp/_http_parser.pyx":22 + * + * from aiohttp import hdrs + * from aiohttp.helpers import DEBUG # <<<<<<<<<<<<<< + * + * from .http_exceptions import ( + */ + __pyx_t_2 = PyList_New(1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 22, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_INCREF(__pyx_n_s_DEBUG); + __Pyx_GIVEREF(__pyx_n_s_DEBUG); + PyList_SET_ITEM(__pyx_t_2, 0, __pyx_n_s_DEBUG); + __pyx_t_1 = __Pyx_Import(__pyx_n_s_aiohttp_helpers, __pyx_t_2, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 22, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_2 = __Pyx_ImportFrom(__pyx_t_1, __pyx_n_s_DEBUG); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 22, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_DEBUG, __pyx_t_2) < 0) __PYX_ERR(0, 22, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + /* "aiohttp/_http_parser.pyx":25 * * from .http_exceptions import ( @@ -18323,76 +18232,76 @@ if (!__Pyx_RefNanny) { * BadStatusLine, * ContentLengthError, */ - __pyx_t_2 = PyList_New(8); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 25, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); + __pyx_t_1 = PyList_New(8); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 25, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); __Pyx_INCREF(__pyx_n_s_BadHttpMessage); __Pyx_GIVEREF(__pyx_n_s_BadHttpMessage); - PyList_SET_ITEM(__pyx_t_2, 0, __pyx_n_s_BadHttpMessage); + PyList_SET_ITEM(__pyx_t_1, 0, __pyx_n_s_BadHttpMessage); __Pyx_INCREF(__pyx_n_s_BadStatusLine); __Pyx_GIVEREF(__pyx_n_s_BadStatusLine); - PyList_SET_ITEM(__pyx_t_2, 1, __pyx_n_s_BadStatusLine); + PyList_SET_ITEM(__pyx_t_1, 1, __pyx_n_s_BadStatusLine); __Pyx_INCREF(__pyx_n_s_ContentLengthError); __Pyx_GIVEREF(__pyx_n_s_ContentLengthError); - PyList_SET_ITEM(__pyx_t_2, 2, __pyx_n_s_ContentLengthError); + PyList_SET_ITEM(__pyx_t_1, 2, __pyx_n_s_ContentLengthError); __Pyx_INCREF(__pyx_n_s_InvalidHeader); __Pyx_GIVEREF(__pyx_n_s_InvalidHeader); - PyList_SET_ITEM(__pyx_t_2, 3, __pyx_n_s_InvalidHeader); + PyList_SET_ITEM(__pyx_t_1, 3, __pyx_n_s_InvalidHeader); __Pyx_INCREF(__pyx_n_s_InvalidURLError); __Pyx_GIVEREF(__pyx_n_s_InvalidURLError); - PyList_SET_ITEM(__pyx_t_2, 4, __pyx_n_s_InvalidURLError); + PyList_SET_ITEM(__pyx_t_1, 4, __pyx_n_s_InvalidURLError); __Pyx_INCREF(__pyx_n_s_LineTooLong); __Pyx_GIVEREF(__pyx_n_s_LineTooLong); - PyList_SET_ITEM(__pyx_t_2, 5, __pyx_n_s_LineTooLong); + PyList_SET_ITEM(__pyx_t_1, 5, __pyx_n_s_LineTooLong); __Pyx_INCREF(__pyx_n_s_PayloadEncodingError); __Pyx_GIVEREF(__pyx_n_s_PayloadEncodingError); - PyList_SET_ITEM(__pyx_t_2, 6, __pyx_n_s_PayloadEncodingError); + PyList_SET_ITEM(__pyx_t_1, 6, __pyx_n_s_PayloadEncodingError); __Pyx_INCREF(__pyx_n_s_TransferEncodingError); __Pyx_GIVEREF(__pyx_n_s_TransferEncodingError); - PyList_SET_ITEM(__pyx_t_2, 7, __pyx_n_s_TransferEncodingError); + PyList_SET_ITEM(__pyx_t_1, 7, __pyx_n_s_TransferEncodingError); /* "aiohttp/_http_parser.pyx":24 - * from aiohttp import hdrs + * from aiohttp.helpers import DEBUG * * from .http_exceptions import ( # <<<<<<<<<<<<<< * BadHttpMessage, * BadStatusLine, */ - __pyx_t_1 = __Pyx_Import(__pyx_n_s_http_exceptions, __pyx_t_2, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 24, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_2 = __Pyx_ImportFrom(__pyx_t_1, __pyx_n_s_BadHttpMessage); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 24, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - if (PyDict_SetItem(__pyx_d, __pyx_n_s_BadHttpMessage, __pyx_t_2) < 0) __PYX_ERR(0, 25, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_2 = __Pyx_ImportFrom(__pyx_t_1, __pyx_n_s_BadStatusLine); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 24, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - if (PyDict_SetItem(__pyx_d, __pyx_n_s_BadStatusLine, __pyx_t_2) < 0) __PYX_ERR(0, 26, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_2 = __Pyx_ImportFrom(__pyx_t_1, __pyx_n_s_ContentLengthError); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 24, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - if (PyDict_SetItem(__pyx_d, __pyx_n_s_ContentLengthError, __pyx_t_2) < 0) __PYX_ERR(0, 27, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_2 = __Pyx_ImportFrom(__pyx_t_1, __pyx_n_s_InvalidHeader); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 24, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - if (PyDict_SetItem(__pyx_d, __pyx_n_s_InvalidHeader, __pyx_t_2) < 0) __PYX_ERR(0, 28, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_2 = __Pyx_ImportFrom(__pyx_t_1, __pyx_n_s_InvalidURLError); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 24, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - if (PyDict_SetItem(__pyx_d, __pyx_n_s_InvalidURLError, __pyx_t_2) < 0) __PYX_ERR(0, 29, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_2 = __Pyx_ImportFrom(__pyx_t_1, __pyx_n_s_LineTooLong); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 24, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - if (PyDict_SetItem(__pyx_d, __pyx_n_s_LineTooLong, __pyx_t_2) < 0) __PYX_ERR(0, 30, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_2 = __Pyx_ImportFrom(__pyx_t_1, __pyx_n_s_PayloadEncodingError); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 24, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - if (PyDict_SetItem(__pyx_d, __pyx_n_s_PayloadEncodingError, __pyx_t_2) < 0) __PYX_ERR(0, 31, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_2 = __Pyx_ImportFrom(__pyx_t_1, __pyx_n_s_TransferEncodingError); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 24, __pyx_L1_error) + __pyx_t_2 = __Pyx_Import(__pyx_n_s_http_exceptions, __pyx_t_1, 1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 24, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); - if (PyDict_SetItem(__pyx_d, __pyx_n_s_TransferEncodingError, __pyx_t_2) < 0) __PYX_ERR(0, 32, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_BadHttpMessage); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 24, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_BadHttpMessage, __pyx_t_1) < 0) __PYX_ERR(0, 25, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_BadStatusLine); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 24, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_BadStatusLine, __pyx_t_1) < 0) __PYX_ERR(0, 26, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_ContentLengthError); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 24, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_ContentLengthError, __pyx_t_1) < 0) __PYX_ERR(0, 27, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_InvalidHeader); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 24, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_InvalidHeader, __pyx_t_1) < 0) __PYX_ERR(0, 28, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_InvalidURLError); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 24, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_InvalidURLError, __pyx_t_1) < 0) __PYX_ERR(0, 29, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_LineTooLong); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 24, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_LineTooLong, __pyx_t_1) < 0) __PYX_ERR(0, 30, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_PayloadEncodingError); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 24, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_PayloadEncodingError, __pyx_t_1) < 0) __PYX_ERR(0, 31, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_TransferEncodingError); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 24, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_TransferEncodingError, __pyx_t_1) < 0) __PYX_ERR(0, 32, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_http_parser.pyx":34 * TransferEncodingError, @@ -18401,19 +18310,19 @@ if (!__Pyx_RefNanny) { * from .http_writer import ( * HttpVersion as _HttpVersion, */ - __pyx_t_1 = PyList_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 34, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = PyList_New(1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 34, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); __Pyx_INCREF(__pyx_n_s_DeflateBuffer); __Pyx_GIVEREF(__pyx_n_s_DeflateBuffer); - PyList_SET_ITEM(__pyx_t_1, 0, __pyx_n_s_DeflateBuffer); - __pyx_t_2 = __Pyx_Import(__pyx_n_s_http_parser, __pyx_t_1, 1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 34, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_DeflateBuffer); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 34, __pyx_L1_error) + PyList_SET_ITEM(__pyx_t_2, 0, __pyx_n_s_DeflateBuffer); + __pyx_t_1 = __Pyx_Import(__pyx_n_s_http_parser, __pyx_t_2, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 34, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); - if (PyDict_SetItem(__pyx_d, __pyx_n_s_DeflateBuffer_2, __pyx_t_1) < 0) __PYX_ERR(0, 34, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_2 = __Pyx_ImportFrom(__pyx_t_1, __pyx_n_s_DeflateBuffer); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 34, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_DeflateBuffer_2, __pyx_t_2) < 0) __PYX_ERR(0, 34, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; /* "aiohttp/_http_parser.pyx":36 * from .http_parser import DeflateBuffer as _DeflateBuffer @@ -18422,17 +18331,17 @@ if (!__Pyx_RefNanny) { * HttpVersion10 as _HttpVersion10, * HttpVersion11 as _HttpVersion11, */ - __pyx_t_2 = PyList_New(3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 36, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); + __pyx_t_1 = PyList_New(3); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 36, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); __Pyx_INCREF(__pyx_n_s_HttpVersion); __Pyx_GIVEREF(__pyx_n_s_HttpVersion); - PyList_SET_ITEM(__pyx_t_2, 0, __pyx_n_s_HttpVersion); + PyList_SET_ITEM(__pyx_t_1, 0, __pyx_n_s_HttpVersion); __Pyx_INCREF(__pyx_n_s_HttpVersion10); __Pyx_GIVEREF(__pyx_n_s_HttpVersion10); - PyList_SET_ITEM(__pyx_t_2, 1, __pyx_n_s_HttpVersion10); + PyList_SET_ITEM(__pyx_t_1, 1, __pyx_n_s_HttpVersion10); __Pyx_INCREF(__pyx_n_s_HttpVersion11); __Pyx_GIVEREF(__pyx_n_s_HttpVersion11); - PyList_SET_ITEM(__pyx_t_2, 2, __pyx_n_s_HttpVersion11); + PyList_SET_ITEM(__pyx_t_1, 2, __pyx_n_s_HttpVersion11); /* "aiohttp/_http_parser.pyx":35 * ) @@ -18441,22 +18350,22 @@ if (!__Pyx_RefNanny) { * HttpVersion as _HttpVersion, * HttpVersion10 as _HttpVersion10, */ - __pyx_t_1 = __Pyx_Import(__pyx_n_s_http_writer, __pyx_t_2, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 35, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_2 = __Pyx_ImportFrom(__pyx_t_1, __pyx_n_s_HttpVersion); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 35, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - if (PyDict_SetItem(__pyx_d, __pyx_n_s_HttpVersion_2, __pyx_t_2) < 0) __PYX_ERR(0, 36, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_2 = __Pyx_ImportFrom(__pyx_t_1, __pyx_n_s_HttpVersion10); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 35, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - if (PyDict_SetItem(__pyx_d, __pyx_n_s_HttpVersion10_2, __pyx_t_2) < 0) __PYX_ERR(0, 37, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_2 = __Pyx_ImportFrom(__pyx_t_1, __pyx_n_s_HttpVersion11); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 35, __pyx_L1_error) + __pyx_t_2 = __Pyx_Import(__pyx_n_s_http_writer, __pyx_t_1, 1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 35, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); - if (PyDict_SetItem(__pyx_d, __pyx_n_s_HttpVersion11_2, __pyx_t_2) < 0) __PYX_ERR(0, 38, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_HttpVersion); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 35, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_HttpVersion_2, __pyx_t_1) < 0) __PYX_ERR(0, 36, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_HttpVersion10); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 35, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_HttpVersion10_2, __pyx_t_1) < 0) __PYX_ERR(0, 37, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_HttpVersion11); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 35, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_HttpVersion11_2, __pyx_t_1) < 0) __PYX_ERR(0, 38, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_http_parser.pyx":40 * HttpVersion11 as _HttpVersion11, @@ -18465,26 +18374,26 @@ if (!__Pyx_RefNanny) { * * cimport cython */ - __pyx_t_1 = PyList_New(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 40, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = PyList_New(2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 40, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); __Pyx_INCREF(__pyx_n_s_EMPTY_PAYLOAD); __Pyx_GIVEREF(__pyx_n_s_EMPTY_PAYLOAD); - PyList_SET_ITEM(__pyx_t_1, 0, __pyx_n_s_EMPTY_PAYLOAD); + PyList_SET_ITEM(__pyx_t_2, 0, __pyx_n_s_EMPTY_PAYLOAD); __Pyx_INCREF(__pyx_n_s_StreamReader); __Pyx_GIVEREF(__pyx_n_s_StreamReader); - PyList_SET_ITEM(__pyx_t_1, 1, __pyx_n_s_StreamReader); - __pyx_t_2 = __Pyx_Import(__pyx_n_s_streams, __pyx_t_1, 1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 40, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_EMPTY_PAYLOAD); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 40, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - if (PyDict_SetItem(__pyx_d, __pyx_n_s_EMPTY_PAYLOAD_2, __pyx_t_1) < 0) __PYX_ERR(0, 40, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_StreamReader); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 40, __pyx_L1_error) + PyList_SET_ITEM(__pyx_t_2, 1, __pyx_n_s_StreamReader); + __pyx_t_1 = __Pyx_Import(__pyx_n_s_streams, __pyx_t_2, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 40, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); - if (PyDict_SetItem(__pyx_d, __pyx_n_s_StreamReader_2, __pyx_t_1) < 0) __PYX_ERR(0, 40, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_2 = __Pyx_ImportFrom(__pyx_t_1, __pyx_n_s_EMPTY_PAYLOAD); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 40, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_EMPTY_PAYLOAD_2, __pyx_t_2) < 0) __PYX_ERR(0, 40, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_2 = __Pyx_ImportFrom(__pyx_t_1, __pyx_n_s_StreamReader); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 40, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_StreamReader_2, __pyx_t_2) < 0) __PYX_ERR(0, 40, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; /* "aiohttp/_headers.pxi":4 * # Run ./tools/gen.py to update it after the origin changing. @@ -18493,19 +18402,19 @@ if (!__Pyx_RefNanny) { * cdef tuple headers = ( * hdrs.ACCEPT, */ - __pyx_t_2 = PyList_New(1); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 4, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); + __pyx_t_1 = PyList_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 4, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); __Pyx_INCREF(__pyx_n_s_hdrs); __Pyx_GIVEREF(__pyx_n_s_hdrs); - PyList_SET_ITEM(__pyx_t_2, 0, __pyx_n_s_hdrs); - __pyx_t_1 = __Pyx_Import(__pyx_n_s__4, __pyx_t_2, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 4, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_2 = __Pyx_ImportFrom(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 4, __pyx_L1_error) + PyList_SET_ITEM(__pyx_t_1, 0, __pyx_n_s_hdrs); + __pyx_t_2 = __Pyx_Import(__pyx_n_s__8, __pyx_t_1, 1); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 4, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); - if (PyDict_SetItem(__pyx_d, __pyx_n_s_hdrs, __pyx_t_2) < 0) __PYX_ERR(5, 4, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 4, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_hdrs, __pyx_t_1) < 0) __PYX_ERR(5, 4, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":6 * from . import hdrs @@ -18514,11 +18423,11 @@ if (!__Pyx_RefNanny) { * hdrs.ACCEPT_CHARSET, * hdrs.ACCEPT_ENCODING, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 6, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_ACCEPT); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 6, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 6, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_ACCEPT); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":7 * cdef tuple headers = ( @@ -18527,11 +18436,11 @@ if (!__Pyx_RefNanny) { * hdrs.ACCEPT_ENCODING, * hdrs.ACCEPT_LANGUAGE, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 7, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_ACCEPT_CHARSET); if (unlikely(!__pyx_t_3)) __PYX_ERR(5, 7, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 7, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_ACCEPT_CHARSET); if (unlikely(!__pyx_t_3)) __PYX_ERR(5, 7, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":8 * hdrs.ACCEPT, @@ -18540,11 +18449,11 @@ if (!__Pyx_RefNanny) { * hdrs.ACCEPT_LANGUAGE, * hdrs.ACCEPT_RANGES, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 8, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_ACCEPT_ENCODING); if (unlikely(!__pyx_t_4)) __PYX_ERR(5, 8, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 8, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_ACCEPT_ENCODING); if (unlikely(!__pyx_t_4)) __PYX_ERR(5, 8, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":9 * hdrs.ACCEPT_CHARSET, @@ -18553,11 +18462,11 @@ if (!__Pyx_RefNanny) { * hdrs.ACCEPT_RANGES, * hdrs.ACCESS_CONTROL_ALLOW_CREDENTIALS, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 9, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_ACCEPT_LANGUAGE); if (unlikely(!__pyx_t_5)) __PYX_ERR(5, 9, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 9, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_ACCEPT_LANGUAGE); if (unlikely(!__pyx_t_5)) __PYX_ERR(5, 9, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_5); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":10 * hdrs.ACCEPT_ENCODING, @@ -18566,11 +18475,11 @@ if (!__Pyx_RefNanny) { * hdrs.ACCESS_CONTROL_ALLOW_CREDENTIALS, * hdrs.ACCESS_CONTROL_ALLOW_HEADERS, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 10, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_ACCEPT_RANGES); if (unlikely(!__pyx_t_6)) __PYX_ERR(5, 10, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 10, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_ACCEPT_RANGES); if (unlikely(!__pyx_t_6)) __PYX_ERR(5, 10, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_6); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":11 * hdrs.ACCEPT_LANGUAGE, @@ -18579,11 +18488,11 @@ if (!__Pyx_RefNanny) { * hdrs.ACCESS_CONTROL_ALLOW_HEADERS, * hdrs.ACCESS_CONTROL_ALLOW_METHODS, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 11, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_ACCESS_CONTROL_ALLOW_CREDENTIALS); if (unlikely(!__pyx_t_7)) __PYX_ERR(5, 11, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 11, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_ACCESS_CONTROL_ALLOW_CREDENTIALS); if (unlikely(!__pyx_t_7)) __PYX_ERR(5, 11, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_7); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":12 * hdrs.ACCEPT_RANGES, @@ -18592,11 +18501,11 @@ if (!__Pyx_RefNanny) { * hdrs.ACCESS_CONTROL_ALLOW_METHODS, * hdrs.ACCESS_CONTROL_ALLOW_ORIGIN, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 12, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_ACCESS_CONTROL_ALLOW_HEADERS); if (unlikely(!__pyx_t_8)) __PYX_ERR(5, 12, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_ACCESS_CONTROL_ALLOW_HEADERS); if (unlikely(!__pyx_t_8)) __PYX_ERR(5, 12, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_8); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":13 * hdrs.ACCESS_CONTROL_ALLOW_CREDENTIALS, @@ -18605,11 +18514,11 @@ if (!__Pyx_RefNanny) { * hdrs.ACCESS_CONTROL_ALLOW_ORIGIN, * hdrs.ACCESS_CONTROL_EXPOSE_HEADERS, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 13, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_ACCESS_CONTROL_ALLOW_METHODS); if (unlikely(!__pyx_t_9)) __PYX_ERR(5, 13, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 13, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_ACCESS_CONTROL_ALLOW_METHODS); if (unlikely(!__pyx_t_9)) __PYX_ERR(5, 13, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_9); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":14 * hdrs.ACCESS_CONTROL_ALLOW_HEADERS, @@ -18618,11 +18527,11 @@ if (!__Pyx_RefNanny) { * hdrs.ACCESS_CONTROL_EXPOSE_HEADERS, * hdrs.ACCESS_CONTROL_MAX_AGE, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 14, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_10 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_ACCESS_CONTROL_ALLOW_ORIGIN); if (unlikely(!__pyx_t_10)) __PYX_ERR(5, 14, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 14, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_10 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_ACCESS_CONTROL_ALLOW_ORIGIN); if (unlikely(!__pyx_t_10)) __PYX_ERR(5, 14, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_10); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":15 * hdrs.ACCESS_CONTROL_ALLOW_METHODS, @@ -18631,11 +18540,11 @@ if (!__Pyx_RefNanny) { * hdrs.ACCESS_CONTROL_MAX_AGE, * hdrs.ACCESS_CONTROL_REQUEST_HEADERS, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 15, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_11 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_ACCESS_CONTROL_EXPOSE_HEADERS); if (unlikely(!__pyx_t_11)) __PYX_ERR(5, 15, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 15, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_11 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_ACCESS_CONTROL_EXPOSE_HEADERS); if (unlikely(!__pyx_t_11)) __PYX_ERR(5, 15, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_11); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":16 * hdrs.ACCESS_CONTROL_ALLOW_ORIGIN, @@ -18644,11 +18553,11 @@ if (!__Pyx_RefNanny) { * hdrs.ACCESS_CONTROL_REQUEST_HEADERS, * hdrs.ACCESS_CONTROL_REQUEST_METHOD, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 16, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_12 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_ACCESS_CONTROL_MAX_AGE); if (unlikely(!__pyx_t_12)) __PYX_ERR(5, 16, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 16, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_12 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_ACCESS_CONTROL_MAX_AGE); if (unlikely(!__pyx_t_12)) __PYX_ERR(5, 16, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_12); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":17 * hdrs.ACCESS_CONTROL_EXPOSE_HEADERS, @@ -18657,11 +18566,11 @@ if (!__Pyx_RefNanny) { * hdrs.ACCESS_CONTROL_REQUEST_METHOD, * hdrs.AGE, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 17, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_13 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_ACCESS_CONTROL_REQUEST_HEADERS); if (unlikely(!__pyx_t_13)) __PYX_ERR(5, 17, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 17, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_13 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_ACCESS_CONTROL_REQUEST_HEADERS); if (unlikely(!__pyx_t_13)) __PYX_ERR(5, 17, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_13); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":18 * hdrs.ACCESS_CONTROL_MAX_AGE, @@ -18670,11 +18579,11 @@ if (!__Pyx_RefNanny) { * hdrs.AGE, * hdrs.ALLOW, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 18, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_14 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_ACCESS_CONTROL_REQUEST_METHOD); if (unlikely(!__pyx_t_14)) __PYX_ERR(5, 18, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 18, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_14 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_ACCESS_CONTROL_REQUEST_METHOD); if (unlikely(!__pyx_t_14)) __PYX_ERR(5, 18, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_14); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":19 * hdrs.ACCESS_CONTROL_REQUEST_HEADERS, @@ -18683,11 +18592,11 @@ if (!__Pyx_RefNanny) { * hdrs.ALLOW, * hdrs.AUTHORIZATION, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 19, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_15 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_AGE); if (unlikely(!__pyx_t_15)) __PYX_ERR(5, 19, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 19, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_15 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_AGE); if (unlikely(!__pyx_t_15)) __PYX_ERR(5, 19, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_15); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":20 * hdrs.ACCESS_CONTROL_REQUEST_METHOD, @@ -18696,11 +18605,11 @@ if (!__Pyx_RefNanny) { * hdrs.AUTHORIZATION, * hdrs.CACHE_CONTROL, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 20, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_16 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_ALLOW); if (unlikely(!__pyx_t_16)) __PYX_ERR(5, 20, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 20, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_16 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_ALLOW); if (unlikely(!__pyx_t_16)) __PYX_ERR(5, 20, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_16); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":21 * hdrs.AGE, @@ -18709,11 +18618,11 @@ if (!__Pyx_RefNanny) { * hdrs.CACHE_CONTROL, * hdrs.CONNECTION, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 21, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_17 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_AUTHORIZATION); if (unlikely(!__pyx_t_17)) __PYX_ERR(5, 21, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 21, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_17 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_AUTHORIZATION); if (unlikely(!__pyx_t_17)) __PYX_ERR(5, 21, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_17); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":22 * hdrs.ALLOW, @@ -18722,11 +18631,11 @@ if (!__Pyx_RefNanny) { * hdrs.CONNECTION, * hdrs.CONTENT_DISPOSITION, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 22, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_18 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_CACHE_CONTROL); if (unlikely(!__pyx_t_18)) __PYX_ERR(5, 22, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 22, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_18 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_CACHE_CONTROL); if (unlikely(!__pyx_t_18)) __PYX_ERR(5, 22, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_18); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":23 * hdrs.AUTHORIZATION, @@ -18735,11 +18644,11 @@ if (!__Pyx_RefNanny) { * hdrs.CONTENT_DISPOSITION, * hdrs.CONTENT_ENCODING, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 23, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_19 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_CONNECTION); if (unlikely(!__pyx_t_19)) __PYX_ERR(5, 23, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 23, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_19 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_CONNECTION); if (unlikely(!__pyx_t_19)) __PYX_ERR(5, 23, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_19); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":24 * hdrs.CACHE_CONTROL, @@ -18748,11 +18657,11 @@ if (!__Pyx_RefNanny) { * hdrs.CONTENT_ENCODING, * hdrs.CONTENT_LANGUAGE, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 24, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_20 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_CONTENT_DISPOSITION); if (unlikely(!__pyx_t_20)) __PYX_ERR(5, 24, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 24, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_20 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_CONTENT_DISPOSITION); if (unlikely(!__pyx_t_20)) __PYX_ERR(5, 24, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_20); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":25 * hdrs.CONNECTION, @@ -18761,11 +18670,11 @@ if (!__Pyx_RefNanny) { * hdrs.CONTENT_LANGUAGE, * hdrs.CONTENT_LENGTH, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 25, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_21 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_CONTENT_ENCODING); if (unlikely(!__pyx_t_21)) __PYX_ERR(5, 25, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 25, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_21 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_CONTENT_ENCODING); if (unlikely(!__pyx_t_21)) __PYX_ERR(5, 25, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_21); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":26 * hdrs.CONTENT_DISPOSITION, @@ -18774,11 +18683,11 @@ if (!__Pyx_RefNanny) { * hdrs.CONTENT_LENGTH, * hdrs.CONTENT_LOCATION, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 26, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_22 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_CONTENT_LANGUAGE); if (unlikely(!__pyx_t_22)) __PYX_ERR(5, 26, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 26, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_22 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_CONTENT_LANGUAGE); if (unlikely(!__pyx_t_22)) __PYX_ERR(5, 26, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_22); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":27 * hdrs.CONTENT_ENCODING, @@ -18787,11 +18696,11 @@ if (!__Pyx_RefNanny) { * hdrs.CONTENT_LOCATION, * hdrs.CONTENT_MD5, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 27, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_23 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_CONTENT_LENGTH); if (unlikely(!__pyx_t_23)) __PYX_ERR(5, 27, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 27, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_23 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_CONTENT_LENGTH); if (unlikely(!__pyx_t_23)) __PYX_ERR(5, 27, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_23); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":28 * hdrs.CONTENT_LANGUAGE, @@ -18800,11 +18709,11 @@ if (!__Pyx_RefNanny) { * hdrs.CONTENT_MD5, * hdrs.CONTENT_RANGE, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 28, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_24 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_CONTENT_LOCATION); if (unlikely(!__pyx_t_24)) __PYX_ERR(5, 28, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 28, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_24 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_CONTENT_LOCATION); if (unlikely(!__pyx_t_24)) __PYX_ERR(5, 28, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_24); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":29 * hdrs.CONTENT_LENGTH, @@ -18813,11 +18722,11 @@ if (!__Pyx_RefNanny) { * hdrs.CONTENT_RANGE, * hdrs.CONTENT_TRANSFER_ENCODING, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 29, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_25 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_CONTENT_MD5); if (unlikely(!__pyx_t_25)) __PYX_ERR(5, 29, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 29, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_25 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_CONTENT_MD5); if (unlikely(!__pyx_t_25)) __PYX_ERR(5, 29, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_25); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":30 * hdrs.CONTENT_LOCATION, @@ -18826,11 +18735,11 @@ if (!__Pyx_RefNanny) { * hdrs.CONTENT_TRANSFER_ENCODING, * hdrs.CONTENT_TYPE, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 30, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_26 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_CONTENT_RANGE); if (unlikely(!__pyx_t_26)) __PYX_ERR(5, 30, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 30, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_26 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_CONTENT_RANGE); if (unlikely(!__pyx_t_26)) __PYX_ERR(5, 30, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_26); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":31 * hdrs.CONTENT_MD5, @@ -18839,11 +18748,11 @@ if (!__Pyx_RefNanny) { * hdrs.CONTENT_TYPE, * hdrs.COOKIE, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 31, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_27 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_CONTENT_TRANSFER_ENCODING); if (unlikely(!__pyx_t_27)) __PYX_ERR(5, 31, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 31, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_27 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_CONTENT_TRANSFER_ENCODING); if (unlikely(!__pyx_t_27)) __PYX_ERR(5, 31, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_27); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":32 * hdrs.CONTENT_RANGE, @@ -18852,11 +18761,11 @@ if (!__Pyx_RefNanny) { * hdrs.COOKIE, * hdrs.DATE, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 32, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_28 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_CONTENT_TYPE); if (unlikely(!__pyx_t_28)) __PYX_ERR(5, 32, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 32, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_28 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_CONTENT_TYPE); if (unlikely(!__pyx_t_28)) __PYX_ERR(5, 32, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_28); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":33 * hdrs.CONTENT_TRANSFER_ENCODING, @@ -18865,11 +18774,11 @@ if (!__Pyx_RefNanny) { * hdrs.DATE, * hdrs.DESTINATION, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 33, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_29 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_COOKIE); if (unlikely(!__pyx_t_29)) __PYX_ERR(5, 33, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 33, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_29 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_COOKIE); if (unlikely(!__pyx_t_29)) __PYX_ERR(5, 33, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_29); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":34 * hdrs.CONTENT_TYPE, @@ -18878,11 +18787,11 @@ if (!__Pyx_RefNanny) { * hdrs.DESTINATION, * hdrs.DIGEST, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 34, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_30 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_DATE); if (unlikely(!__pyx_t_30)) __PYX_ERR(5, 34, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 34, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_30 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_DATE); if (unlikely(!__pyx_t_30)) __PYX_ERR(5, 34, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_30); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":35 * hdrs.COOKIE, @@ -18891,11 +18800,11 @@ if (!__Pyx_RefNanny) { * hdrs.DIGEST, * hdrs.ETAG, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 35, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_31 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_DESTINATION); if (unlikely(!__pyx_t_31)) __PYX_ERR(5, 35, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 35, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_31 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_DESTINATION); if (unlikely(!__pyx_t_31)) __PYX_ERR(5, 35, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_31); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":36 * hdrs.DATE, @@ -18904,11 +18813,11 @@ if (!__Pyx_RefNanny) { * hdrs.ETAG, * hdrs.EXPECT, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 36, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_32 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_DIGEST); if (unlikely(!__pyx_t_32)) __PYX_ERR(5, 36, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 36, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_32 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_DIGEST); if (unlikely(!__pyx_t_32)) __PYX_ERR(5, 36, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_32); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":37 * hdrs.DESTINATION, @@ -18917,11 +18826,11 @@ if (!__Pyx_RefNanny) { * hdrs.EXPECT, * hdrs.EXPIRES, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 37, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_33 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_ETAG); if (unlikely(!__pyx_t_33)) __PYX_ERR(5, 37, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 37, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_33 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_ETAG); if (unlikely(!__pyx_t_33)) __PYX_ERR(5, 37, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_33); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":38 * hdrs.DIGEST, @@ -18930,11 +18839,11 @@ if (!__Pyx_RefNanny) { * hdrs.EXPIRES, * hdrs.FORWARDED, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 38, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_34 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_EXPECT); if (unlikely(!__pyx_t_34)) __PYX_ERR(5, 38, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 38, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_34 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_EXPECT); if (unlikely(!__pyx_t_34)) __PYX_ERR(5, 38, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_34); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":39 * hdrs.ETAG, @@ -18943,11 +18852,11 @@ if (!__Pyx_RefNanny) { * hdrs.FORWARDED, * hdrs.FROM, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 39, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_35 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_EXPIRES); if (unlikely(!__pyx_t_35)) __PYX_ERR(5, 39, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 39, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_35 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_EXPIRES); if (unlikely(!__pyx_t_35)) __PYX_ERR(5, 39, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_35); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":40 * hdrs.EXPECT, @@ -18956,11 +18865,11 @@ if (!__Pyx_RefNanny) { * hdrs.FROM, * hdrs.HOST, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 40, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_36 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_FORWARDED); if (unlikely(!__pyx_t_36)) __PYX_ERR(5, 40, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 40, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_36 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_FORWARDED); if (unlikely(!__pyx_t_36)) __PYX_ERR(5, 40, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_36); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":41 * hdrs.EXPIRES, @@ -18969,11 +18878,11 @@ if (!__Pyx_RefNanny) { * hdrs.HOST, * hdrs.IF_MATCH, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 41, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_37 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_FROM); if (unlikely(!__pyx_t_37)) __PYX_ERR(5, 41, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 41, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_37 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_FROM); if (unlikely(!__pyx_t_37)) __PYX_ERR(5, 41, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_37); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":42 * hdrs.FORWARDED, @@ -18982,11 +18891,11 @@ if (!__Pyx_RefNanny) { * hdrs.IF_MATCH, * hdrs.IF_MODIFIED_SINCE, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 42, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_38 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_HOST); if (unlikely(!__pyx_t_38)) __PYX_ERR(5, 42, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 42, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_38 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_HOST); if (unlikely(!__pyx_t_38)) __PYX_ERR(5, 42, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_38); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":43 * hdrs.FROM, @@ -18995,11 +18904,11 @@ if (!__Pyx_RefNanny) { * hdrs.IF_MODIFIED_SINCE, * hdrs.IF_NONE_MATCH, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 43, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_39 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_IF_MATCH); if (unlikely(!__pyx_t_39)) __PYX_ERR(5, 43, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 43, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_39 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_IF_MATCH); if (unlikely(!__pyx_t_39)) __PYX_ERR(5, 43, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_39); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":44 * hdrs.HOST, @@ -19008,11 +18917,11 @@ if (!__Pyx_RefNanny) { * hdrs.IF_NONE_MATCH, * hdrs.IF_RANGE, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 44, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_40 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_IF_MODIFIED_SINCE); if (unlikely(!__pyx_t_40)) __PYX_ERR(5, 44, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 44, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_40 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_IF_MODIFIED_SINCE); if (unlikely(!__pyx_t_40)) __PYX_ERR(5, 44, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_40); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":45 * hdrs.IF_MATCH, @@ -19021,11 +18930,11 @@ if (!__Pyx_RefNanny) { * hdrs.IF_RANGE, * hdrs.IF_UNMODIFIED_SINCE, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 45, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_41 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_IF_NONE_MATCH); if (unlikely(!__pyx_t_41)) __PYX_ERR(5, 45, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 45, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_41 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_IF_NONE_MATCH); if (unlikely(!__pyx_t_41)) __PYX_ERR(5, 45, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_41); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":46 * hdrs.IF_MODIFIED_SINCE, @@ -19034,11 +18943,11 @@ if (!__Pyx_RefNanny) { * hdrs.IF_UNMODIFIED_SINCE, * hdrs.KEEP_ALIVE, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 46, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_42 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_IF_RANGE); if (unlikely(!__pyx_t_42)) __PYX_ERR(5, 46, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 46, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_42 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_IF_RANGE); if (unlikely(!__pyx_t_42)) __PYX_ERR(5, 46, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_42); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":47 * hdrs.IF_NONE_MATCH, @@ -19047,11 +18956,11 @@ if (!__Pyx_RefNanny) { * hdrs.KEEP_ALIVE, * hdrs.LAST_EVENT_ID, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 47, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_43 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_IF_UNMODIFIED_SINCE); if (unlikely(!__pyx_t_43)) __PYX_ERR(5, 47, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 47, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_43 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_IF_UNMODIFIED_SINCE); if (unlikely(!__pyx_t_43)) __PYX_ERR(5, 47, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_43); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":48 * hdrs.IF_RANGE, @@ -19060,11 +18969,11 @@ if (!__Pyx_RefNanny) { * hdrs.LAST_EVENT_ID, * hdrs.LAST_MODIFIED, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 48, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_44 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_KEEP_ALIVE); if (unlikely(!__pyx_t_44)) __PYX_ERR(5, 48, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 48, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_44 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_KEEP_ALIVE); if (unlikely(!__pyx_t_44)) __PYX_ERR(5, 48, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_44); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":49 * hdrs.IF_UNMODIFIED_SINCE, @@ -19073,11 +18982,11 @@ if (!__Pyx_RefNanny) { * hdrs.LAST_MODIFIED, * hdrs.LINK, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 49, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_45 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_LAST_EVENT_ID); if (unlikely(!__pyx_t_45)) __PYX_ERR(5, 49, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 49, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_45 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_LAST_EVENT_ID); if (unlikely(!__pyx_t_45)) __PYX_ERR(5, 49, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_45); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":50 * hdrs.KEEP_ALIVE, @@ -19086,11 +18995,11 @@ if (!__Pyx_RefNanny) { * hdrs.LINK, * hdrs.LOCATION, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 50, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_46 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_LAST_MODIFIED); if (unlikely(!__pyx_t_46)) __PYX_ERR(5, 50, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 50, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_46 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_LAST_MODIFIED); if (unlikely(!__pyx_t_46)) __PYX_ERR(5, 50, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_46); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":51 * hdrs.LAST_EVENT_ID, @@ -19099,11 +19008,11 @@ if (!__Pyx_RefNanny) { * hdrs.LOCATION, * hdrs.MAX_FORWARDS, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 51, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_47 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_LINK); if (unlikely(!__pyx_t_47)) __PYX_ERR(5, 51, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 51, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_47 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_LINK); if (unlikely(!__pyx_t_47)) __PYX_ERR(5, 51, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_47); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":52 * hdrs.LAST_MODIFIED, @@ -19112,11 +19021,11 @@ if (!__Pyx_RefNanny) { * hdrs.MAX_FORWARDS, * hdrs.ORIGIN, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 52, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_48 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_LOCATION); if (unlikely(!__pyx_t_48)) __PYX_ERR(5, 52, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 52, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_48 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_LOCATION); if (unlikely(!__pyx_t_48)) __PYX_ERR(5, 52, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_48); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":53 * hdrs.LINK, @@ -19125,11 +19034,11 @@ if (!__Pyx_RefNanny) { * hdrs.ORIGIN, * hdrs.PRAGMA, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 53, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_49 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_MAX_FORWARDS); if (unlikely(!__pyx_t_49)) __PYX_ERR(5, 53, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 53, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_49 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_MAX_FORWARDS); if (unlikely(!__pyx_t_49)) __PYX_ERR(5, 53, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_49); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":54 * hdrs.LOCATION, @@ -19138,11 +19047,11 @@ if (!__Pyx_RefNanny) { * hdrs.PRAGMA, * hdrs.PROXY_AUTHENTICATE, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 54, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_50 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_ORIGIN); if (unlikely(!__pyx_t_50)) __PYX_ERR(5, 54, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 54, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_50 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_ORIGIN); if (unlikely(!__pyx_t_50)) __PYX_ERR(5, 54, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_50); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":55 * hdrs.MAX_FORWARDS, @@ -19151,11 +19060,11 @@ if (!__Pyx_RefNanny) { * hdrs.PROXY_AUTHENTICATE, * hdrs.PROXY_AUTHORIZATION, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 55, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_51 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_PRAGMA); if (unlikely(!__pyx_t_51)) __PYX_ERR(5, 55, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 55, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_51 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_PRAGMA); if (unlikely(!__pyx_t_51)) __PYX_ERR(5, 55, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_51); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":56 * hdrs.ORIGIN, @@ -19164,11 +19073,11 @@ if (!__Pyx_RefNanny) { * hdrs.PROXY_AUTHORIZATION, * hdrs.RANGE, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 56, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_52 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_PROXY_AUTHENTICATE); if (unlikely(!__pyx_t_52)) __PYX_ERR(5, 56, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 56, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_52 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_PROXY_AUTHENTICATE); if (unlikely(!__pyx_t_52)) __PYX_ERR(5, 56, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_52); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":57 * hdrs.PRAGMA, @@ -19177,11 +19086,11 @@ if (!__Pyx_RefNanny) { * hdrs.RANGE, * hdrs.REFERER, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 57, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_53 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_PROXY_AUTHORIZATION); if (unlikely(!__pyx_t_53)) __PYX_ERR(5, 57, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 57, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_53 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_PROXY_AUTHORIZATION); if (unlikely(!__pyx_t_53)) __PYX_ERR(5, 57, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_53); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":58 * hdrs.PROXY_AUTHENTICATE, @@ -19190,11 +19099,11 @@ if (!__Pyx_RefNanny) { * hdrs.REFERER, * hdrs.RETRY_AFTER, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 58, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_54 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_RANGE); if (unlikely(!__pyx_t_54)) __PYX_ERR(5, 58, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 58, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_54 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_RANGE); if (unlikely(!__pyx_t_54)) __PYX_ERR(5, 58, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_54); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":59 * hdrs.PROXY_AUTHORIZATION, @@ -19203,11 +19112,11 @@ if (!__Pyx_RefNanny) { * hdrs.RETRY_AFTER, * hdrs.SEC_WEBSOCKET_ACCEPT, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 59, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_55 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_REFERER); if (unlikely(!__pyx_t_55)) __PYX_ERR(5, 59, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 59, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_55 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_REFERER); if (unlikely(!__pyx_t_55)) __PYX_ERR(5, 59, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_55); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":60 * hdrs.RANGE, @@ -19216,11 +19125,11 @@ if (!__Pyx_RefNanny) { * hdrs.SEC_WEBSOCKET_ACCEPT, * hdrs.SEC_WEBSOCKET_EXTENSIONS, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 60, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_56 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_RETRY_AFTER); if (unlikely(!__pyx_t_56)) __PYX_ERR(5, 60, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 60, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_56 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_RETRY_AFTER); if (unlikely(!__pyx_t_56)) __PYX_ERR(5, 60, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_56); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":61 * hdrs.REFERER, @@ -19229,11 +19138,11 @@ if (!__Pyx_RefNanny) { * hdrs.SEC_WEBSOCKET_EXTENSIONS, * hdrs.SEC_WEBSOCKET_KEY, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 61, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_57 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_SEC_WEBSOCKET_ACCEPT); if (unlikely(!__pyx_t_57)) __PYX_ERR(5, 61, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 61, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_57 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_SEC_WEBSOCKET_ACCEPT); if (unlikely(!__pyx_t_57)) __PYX_ERR(5, 61, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_57); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":62 * hdrs.RETRY_AFTER, @@ -19242,11 +19151,11 @@ if (!__Pyx_RefNanny) { * hdrs.SEC_WEBSOCKET_KEY, * hdrs.SEC_WEBSOCKET_KEY1, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 62, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_58 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_SEC_WEBSOCKET_EXTENSIONS); if (unlikely(!__pyx_t_58)) __PYX_ERR(5, 62, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 62, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_58 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_SEC_WEBSOCKET_EXTENSIONS); if (unlikely(!__pyx_t_58)) __PYX_ERR(5, 62, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_58); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":63 * hdrs.SEC_WEBSOCKET_ACCEPT, @@ -19255,11 +19164,11 @@ if (!__Pyx_RefNanny) { * hdrs.SEC_WEBSOCKET_KEY1, * hdrs.SEC_WEBSOCKET_PROTOCOL, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 63, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_59 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_SEC_WEBSOCKET_KEY); if (unlikely(!__pyx_t_59)) __PYX_ERR(5, 63, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 63, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_59 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_SEC_WEBSOCKET_KEY); if (unlikely(!__pyx_t_59)) __PYX_ERR(5, 63, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_59); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":64 * hdrs.SEC_WEBSOCKET_EXTENSIONS, @@ -19268,11 +19177,11 @@ if (!__Pyx_RefNanny) { * hdrs.SEC_WEBSOCKET_PROTOCOL, * hdrs.SEC_WEBSOCKET_VERSION, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 64, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_60 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_SEC_WEBSOCKET_KEY1); if (unlikely(!__pyx_t_60)) __PYX_ERR(5, 64, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 64, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_60 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_SEC_WEBSOCKET_KEY1); if (unlikely(!__pyx_t_60)) __PYX_ERR(5, 64, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_60); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":65 * hdrs.SEC_WEBSOCKET_KEY, @@ -19281,11 +19190,11 @@ if (!__Pyx_RefNanny) { * hdrs.SEC_WEBSOCKET_VERSION, * hdrs.SERVER, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 65, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_61 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_SEC_WEBSOCKET_PROTOCOL); if (unlikely(!__pyx_t_61)) __PYX_ERR(5, 65, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 65, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_61 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_SEC_WEBSOCKET_PROTOCOL); if (unlikely(!__pyx_t_61)) __PYX_ERR(5, 65, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_61); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":66 * hdrs.SEC_WEBSOCKET_KEY1, @@ -19294,11 +19203,11 @@ if (!__Pyx_RefNanny) { * hdrs.SERVER, * hdrs.SET_COOKIE, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 66, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_62 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_SEC_WEBSOCKET_VERSION); if (unlikely(!__pyx_t_62)) __PYX_ERR(5, 66, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 66, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_62 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_SEC_WEBSOCKET_VERSION); if (unlikely(!__pyx_t_62)) __PYX_ERR(5, 66, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_62); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":67 * hdrs.SEC_WEBSOCKET_PROTOCOL, @@ -19307,11 +19216,11 @@ if (!__Pyx_RefNanny) { * hdrs.SET_COOKIE, * hdrs.TE, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 67, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_63 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_SERVER); if (unlikely(!__pyx_t_63)) __PYX_ERR(5, 67, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 67, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_63 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_SERVER); if (unlikely(!__pyx_t_63)) __PYX_ERR(5, 67, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_63); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":68 * hdrs.SEC_WEBSOCKET_VERSION, @@ -19320,11 +19229,11 @@ if (!__Pyx_RefNanny) { * hdrs.TE, * hdrs.TRAILER, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 68, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_64 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_SET_COOKIE); if (unlikely(!__pyx_t_64)) __PYX_ERR(5, 68, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 68, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_64 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_SET_COOKIE); if (unlikely(!__pyx_t_64)) __PYX_ERR(5, 68, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_64); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":69 * hdrs.SERVER, @@ -19333,11 +19242,11 @@ if (!__Pyx_RefNanny) { * hdrs.TRAILER, * hdrs.TRANSFER_ENCODING, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 69, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_65 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_TE); if (unlikely(!__pyx_t_65)) __PYX_ERR(5, 69, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 69, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_65 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_TE); if (unlikely(!__pyx_t_65)) __PYX_ERR(5, 69, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_65); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":70 * hdrs.SET_COOKIE, @@ -19346,11 +19255,11 @@ if (!__Pyx_RefNanny) { * hdrs.TRANSFER_ENCODING, * hdrs.URI, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 70, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_66 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_TRAILER); if (unlikely(!__pyx_t_66)) __PYX_ERR(5, 70, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 70, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_66 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_TRAILER); if (unlikely(!__pyx_t_66)) __PYX_ERR(5, 70, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_66); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":71 * hdrs.TE, @@ -19359,11 +19268,11 @@ if (!__Pyx_RefNanny) { * hdrs.URI, * hdrs.UPGRADE, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 71, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_67 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_TRANSFER_ENCODING); if (unlikely(!__pyx_t_67)) __PYX_ERR(5, 71, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 71, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_67 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_TRANSFER_ENCODING); if (unlikely(!__pyx_t_67)) __PYX_ERR(5, 71, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_67); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":72 * hdrs.TRAILER, @@ -19372,11 +19281,11 @@ if (!__Pyx_RefNanny) { * hdrs.UPGRADE, * hdrs.USER_AGENT, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 72, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_68 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_URI); if (unlikely(!__pyx_t_68)) __PYX_ERR(5, 72, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 72, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_68 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_URI); if (unlikely(!__pyx_t_68)) __PYX_ERR(5, 72, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_68); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":73 * hdrs.TRANSFER_ENCODING, @@ -19385,11 +19294,11 @@ if (!__Pyx_RefNanny) { * hdrs.USER_AGENT, * hdrs.VARY, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 73, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_69 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_UPGRADE); if (unlikely(!__pyx_t_69)) __PYX_ERR(5, 73, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 73, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_69 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_UPGRADE); if (unlikely(!__pyx_t_69)) __PYX_ERR(5, 73, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_69); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":74 * hdrs.URI, @@ -19398,11 +19307,11 @@ if (!__Pyx_RefNanny) { * hdrs.VARY, * hdrs.VIA, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 74, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_70 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_USER_AGENT); if (unlikely(!__pyx_t_70)) __PYX_ERR(5, 74, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 74, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_70 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_USER_AGENT); if (unlikely(!__pyx_t_70)) __PYX_ERR(5, 74, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_70); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":75 * hdrs.UPGRADE, @@ -19411,11 +19320,11 @@ if (!__Pyx_RefNanny) { * hdrs.VIA, * hdrs.WWW_AUTHENTICATE, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 75, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_71 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_VARY); if (unlikely(!__pyx_t_71)) __PYX_ERR(5, 75, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 75, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_71 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_VARY); if (unlikely(!__pyx_t_71)) __PYX_ERR(5, 75, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_71); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":76 * hdrs.USER_AGENT, @@ -19424,11 +19333,11 @@ if (!__Pyx_RefNanny) { * hdrs.WWW_AUTHENTICATE, * hdrs.WANT_DIGEST, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 76, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_72 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_VIA); if (unlikely(!__pyx_t_72)) __PYX_ERR(5, 76, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 76, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_72 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_VIA); if (unlikely(!__pyx_t_72)) __PYX_ERR(5, 76, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_72); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":77 * hdrs.VARY, @@ -19437,11 +19346,11 @@ if (!__Pyx_RefNanny) { * hdrs.WANT_DIGEST, * hdrs.WARNING, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 77, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_73 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_WWW_AUTHENTICATE); if (unlikely(!__pyx_t_73)) __PYX_ERR(5, 77, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 77, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_73 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_WWW_AUTHENTICATE); if (unlikely(!__pyx_t_73)) __PYX_ERR(5, 77, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_73); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":78 * hdrs.VIA, @@ -19450,11 +19359,11 @@ if (!__Pyx_RefNanny) { * hdrs.WARNING, * hdrs.X_FORWARDED_FOR, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 78, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_74 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_WANT_DIGEST); if (unlikely(!__pyx_t_74)) __PYX_ERR(5, 78, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 78, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_74 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_WANT_DIGEST); if (unlikely(!__pyx_t_74)) __PYX_ERR(5, 78, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_74); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":79 * hdrs.WWW_AUTHENTICATE, @@ -19463,11 +19372,11 @@ if (!__Pyx_RefNanny) { * hdrs.X_FORWARDED_FOR, * hdrs.X_FORWARDED_HOST, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 79, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_75 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_WARNING); if (unlikely(!__pyx_t_75)) __PYX_ERR(5, 79, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 79, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_75 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_WARNING); if (unlikely(!__pyx_t_75)) __PYX_ERR(5, 79, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_75); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":80 * hdrs.WANT_DIGEST, @@ -19476,11 +19385,11 @@ if (!__Pyx_RefNanny) { * hdrs.X_FORWARDED_HOST, * hdrs.X_FORWARDED_PROTO, */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 80, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_76 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_X_FORWARDED_FOR); if (unlikely(!__pyx_t_76)) __PYX_ERR(5, 80, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 80, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_76 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_X_FORWARDED_FOR); if (unlikely(!__pyx_t_76)) __PYX_ERR(5, 80, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_76); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":81 * hdrs.WARNING, @@ -19489,11 +19398,11 @@ if (!__Pyx_RefNanny) { * hdrs.X_FORWARDED_PROTO, * ) */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 81, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_77 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_X_FORWARDED_HOST); if (unlikely(!__pyx_t_77)) __PYX_ERR(5, 81, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 81, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_77 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_X_FORWARDED_HOST); if (unlikely(!__pyx_t_77)) __PYX_ERR(5, 81, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_77); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":82 * hdrs.X_FORWARDED_FOR, @@ -19501,11 +19410,11 @@ if (!__Pyx_RefNanny) { * hdrs.X_FORWARDED_PROTO, # <<<<<<<<<<<<<< * ) */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 82, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_78 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_X_FORWARDED_PROTO); if (unlikely(!__pyx_t_78)) __PYX_ERR(5, 82, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 82, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_78 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_X_FORWARDED_PROTO); if (unlikely(!__pyx_t_78)) __PYX_ERR(5, 82, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_78); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_headers.pxi":6 * from . import hdrs @@ -19514,163 +19423,163 @@ if (!__Pyx_RefNanny) { * hdrs.ACCEPT_CHARSET, * hdrs.ACCEPT_ENCODING, */ - __pyx_t_1 = PyTuple_New(77); if (unlikely(!__pyx_t_1)) __PYX_ERR(5, 6, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_GIVEREF(__pyx_t_2); - PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_2); + __pyx_t_2 = PyTuple_New(77); if (unlikely(!__pyx_t_2)) __PYX_ERR(5, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_GIVEREF(__pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_1); __Pyx_GIVEREF(__pyx_t_3); - PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_t_3); + PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_t_3); __Pyx_GIVEREF(__pyx_t_4); - PyTuple_SET_ITEM(__pyx_t_1, 2, __pyx_t_4); + PyTuple_SET_ITEM(__pyx_t_2, 2, __pyx_t_4); __Pyx_GIVEREF(__pyx_t_5); - PyTuple_SET_ITEM(__pyx_t_1, 3, __pyx_t_5); + PyTuple_SET_ITEM(__pyx_t_2, 3, __pyx_t_5); __Pyx_GIVEREF(__pyx_t_6); - PyTuple_SET_ITEM(__pyx_t_1, 4, __pyx_t_6); + PyTuple_SET_ITEM(__pyx_t_2, 4, __pyx_t_6); __Pyx_GIVEREF(__pyx_t_7); - PyTuple_SET_ITEM(__pyx_t_1, 5, __pyx_t_7); + PyTuple_SET_ITEM(__pyx_t_2, 5, __pyx_t_7); __Pyx_GIVEREF(__pyx_t_8); - PyTuple_SET_ITEM(__pyx_t_1, 6, __pyx_t_8); + PyTuple_SET_ITEM(__pyx_t_2, 6, __pyx_t_8); __Pyx_GIVEREF(__pyx_t_9); - PyTuple_SET_ITEM(__pyx_t_1, 7, __pyx_t_9); + PyTuple_SET_ITEM(__pyx_t_2, 7, __pyx_t_9); __Pyx_GIVEREF(__pyx_t_10); - PyTuple_SET_ITEM(__pyx_t_1, 8, __pyx_t_10); + PyTuple_SET_ITEM(__pyx_t_2, 8, __pyx_t_10); __Pyx_GIVEREF(__pyx_t_11); - PyTuple_SET_ITEM(__pyx_t_1, 9, __pyx_t_11); + PyTuple_SET_ITEM(__pyx_t_2, 9, __pyx_t_11); __Pyx_GIVEREF(__pyx_t_12); - PyTuple_SET_ITEM(__pyx_t_1, 10, __pyx_t_12); + PyTuple_SET_ITEM(__pyx_t_2, 10, __pyx_t_12); __Pyx_GIVEREF(__pyx_t_13); - PyTuple_SET_ITEM(__pyx_t_1, 11, __pyx_t_13); + PyTuple_SET_ITEM(__pyx_t_2, 11, __pyx_t_13); __Pyx_GIVEREF(__pyx_t_14); - PyTuple_SET_ITEM(__pyx_t_1, 12, __pyx_t_14); + PyTuple_SET_ITEM(__pyx_t_2, 12, __pyx_t_14); __Pyx_GIVEREF(__pyx_t_15); - PyTuple_SET_ITEM(__pyx_t_1, 13, __pyx_t_15); + PyTuple_SET_ITEM(__pyx_t_2, 13, __pyx_t_15); __Pyx_GIVEREF(__pyx_t_16); - PyTuple_SET_ITEM(__pyx_t_1, 14, __pyx_t_16); + PyTuple_SET_ITEM(__pyx_t_2, 14, __pyx_t_16); __Pyx_GIVEREF(__pyx_t_17); - PyTuple_SET_ITEM(__pyx_t_1, 15, __pyx_t_17); + PyTuple_SET_ITEM(__pyx_t_2, 15, __pyx_t_17); __Pyx_GIVEREF(__pyx_t_18); - PyTuple_SET_ITEM(__pyx_t_1, 16, __pyx_t_18); + PyTuple_SET_ITEM(__pyx_t_2, 16, __pyx_t_18); __Pyx_GIVEREF(__pyx_t_19); - PyTuple_SET_ITEM(__pyx_t_1, 17, __pyx_t_19); + PyTuple_SET_ITEM(__pyx_t_2, 17, __pyx_t_19); __Pyx_GIVEREF(__pyx_t_20); - PyTuple_SET_ITEM(__pyx_t_1, 18, __pyx_t_20); + PyTuple_SET_ITEM(__pyx_t_2, 18, __pyx_t_20); __Pyx_GIVEREF(__pyx_t_21); - PyTuple_SET_ITEM(__pyx_t_1, 19, __pyx_t_21); + PyTuple_SET_ITEM(__pyx_t_2, 19, __pyx_t_21); __Pyx_GIVEREF(__pyx_t_22); - PyTuple_SET_ITEM(__pyx_t_1, 20, __pyx_t_22); + PyTuple_SET_ITEM(__pyx_t_2, 20, __pyx_t_22); __Pyx_GIVEREF(__pyx_t_23); - PyTuple_SET_ITEM(__pyx_t_1, 21, __pyx_t_23); + PyTuple_SET_ITEM(__pyx_t_2, 21, __pyx_t_23); __Pyx_GIVEREF(__pyx_t_24); - PyTuple_SET_ITEM(__pyx_t_1, 22, __pyx_t_24); + PyTuple_SET_ITEM(__pyx_t_2, 22, __pyx_t_24); __Pyx_GIVEREF(__pyx_t_25); - PyTuple_SET_ITEM(__pyx_t_1, 23, __pyx_t_25); + PyTuple_SET_ITEM(__pyx_t_2, 23, __pyx_t_25); __Pyx_GIVEREF(__pyx_t_26); - PyTuple_SET_ITEM(__pyx_t_1, 24, __pyx_t_26); + PyTuple_SET_ITEM(__pyx_t_2, 24, __pyx_t_26); __Pyx_GIVEREF(__pyx_t_27); - PyTuple_SET_ITEM(__pyx_t_1, 25, __pyx_t_27); + PyTuple_SET_ITEM(__pyx_t_2, 25, __pyx_t_27); __Pyx_GIVEREF(__pyx_t_28); - PyTuple_SET_ITEM(__pyx_t_1, 26, __pyx_t_28); + PyTuple_SET_ITEM(__pyx_t_2, 26, __pyx_t_28); __Pyx_GIVEREF(__pyx_t_29); - PyTuple_SET_ITEM(__pyx_t_1, 27, __pyx_t_29); + PyTuple_SET_ITEM(__pyx_t_2, 27, __pyx_t_29); __Pyx_GIVEREF(__pyx_t_30); - PyTuple_SET_ITEM(__pyx_t_1, 28, __pyx_t_30); + PyTuple_SET_ITEM(__pyx_t_2, 28, __pyx_t_30); __Pyx_GIVEREF(__pyx_t_31); - PyTuple_SET_ITEM(__pyx_t_1, 29, __pyx_t_31); + PyTuple_SET_ITEM(__pyx_t_2, 29, __pyx_t_31); __Pyx_GIVEREF(__pyx_t_32); - PyTuple_SET_ITEM(__pyx_t_1, 30, __pyx_t_32); + PyTuple_SET_ITEM(__pyx_t_2, 30, __pyx_t_32); __Pyx_GIVEREF(__pyx_t_33); - PyTuple_SET_ITEM(__pyx_t_1, 31, __pyx_t_33); + PyTuple_SET_ITEM(__pyx_t_2, 31, __pyx_t_33); __Pyx_GIVEREF(__pyx_t_34); - PyTuple_SET_ITEM(__pyx_t_1, 32, __pyx_t_34); + PyTuple_SET_ITEM(__pyx_t_2, 32, __pyx_t_34); __Pyx_GIVEREF(__pyx_t_35); - PyTuple_SET_ITEM(__pyx_t_1, 33, __pyx_t_35); + PyTuple_SET_ITEM(__pyx_t_2, 33, __pyx_t_35); __Pyx_GIVEREF(__pyx_t_36); - PyTuple_SET_ITEM(__pyx_t_1, 34, __pyx_t_36); + PyTuple_SET_ITEM(__pyx_t_2, 34, __pyx_t_36); __Pyx_GIVEREF(__pyx_t_37); - PyTuple_SET_ITEM(__pyx_t_1, 35, __pyx_t_37); + PyTuple_SET_ITEM(__pyx_t_2, 35, __pyx_t_37); __Pyx_GIVEREF(__pyx_t_38); - PyTuple_SET_ITEM(__pyx_t_1, 36, __pyx_t_38); + PyTuple_SET_ITEM(__pyx_t_2, 36, __pyx_t_38); __Pyx_GIVEREF(__pyx_t_39); - PyTuple_SET_ITEM(__pyx_t_1, 37, __pyx_t_39); + PyTuple_SET_ITEM(__pyx_t_2, 37, __pyx_t_39); __Pyx_GIVEREF(__pyx_t_40); - PyTuple_SET_ITEM(__pyx_t_1, 38, __pyx_t_40); + PyTuple_SET_ITEM(__pyx_t_2, 38, __pyx_t_40); __Pyx_GIVEREF(__pyx_t_41); - PyTuple_SET_ITEM(__pyx_t_1, 39, __pyx_t_41); + PyTuple_SET_ITEM(__pyx_t_2, 39, __pyx_t_41); __Pyx_GIVEREF(__pyx_t_42); - PyTuple_SET_ITEM(__pyx_t_1, 40, __pyx_t_42); + PyTuple_SET_ITEM(__pyx_t_2, 40, __pyx_t_42); __Pyx_GIVEREF(__pyx_t_43); - PyTuple_SET_ITEM(__pyx_t_1, 41, __pyx_t_43); + PyTuple_SET_ITEM(__pyx_t_2, 41, __pyx_t_43); __Pyx_GIVEREF(__pyx_t_44); - PyTuple_SET_ITEM(__pyx_t_1, 42, __pyx_t_44); + PyTuple_SET_ITEM(__pyx_t_2, 42, __pyx_t_44); __Pyx_GIVEREF(__pyx_t_45); - PyTuple_SET_ITEM(__pyx_t_1, 43, __pyx_t_45); + PyTuple_SET_ITEM(__pyx_t_2, 43, __pyx_t_45); __Pyx_GIVEREF(__pyx_t_46); - PyTuple_SET_ITEM(__pyx_t_1, 44, __pyx_t_46); + PyTuple_SET_ITEM(__pyx_t_2, 44, __pyx_t_46); __Pyx_GIVEREF(__pyx_t_47); - PyTuple_SET_ITEM(__pyx_t_1, 45, __pyx_t_47); + PyTuple_SET_ITEM(__pyx_t_2, 45, __pyx_t_47); __Pyx_GIVEREF(__pyx_t_48); - PyTuple_SET_ITEM(__pyx_t_1, 46, __pyx_t_48); + PyTuple_SET_ITEM(__pyx_t_2, 46, __pyx_t_48); __Pyx_GIVEREF(__pyx_t_49); - PyTuple_SET_ITEM(__pyx_t_1, 47, __pyx_t_49); + PyTuple_SET_ITEM(__pyx_t_2, 47, __pyx_t_49); __Pyx_GIVEREF(__pyx_t_50); - PyTuple_SET_ITEM(__pyx_t_1, 48, __pyx_t_50); + PyTuple_SET_ITEM(__pyx_t_2, 48, __pyx_t_50); __Pyx_GIVEREF(__pyx_t_51); - PyTuple_SET_ITEM(__pyx_t_1, 49, __pyx_t_51); + PyTuple_SET_ITEM(__pyx_t_2, 49, __pyx_t_51); __Pyx_GIVEREF(__pyx_t_52); - PyTuple_SET_ITEM(__pyx_t_1, 50, __pyx_t_52); + PyTuple_SET_ITEM(__pyx_t_2, 50, __pyx_t_52); __Pyx_GIVEREF(__pyx_t_53); - PyTuple_SET_ITEM(__pyx_t_1, 51, __pyx_t_53); + PyTuple_SET_ITEM(__pyx_t_2, 51, __pyx_t_53); __Pyx_GIVEREF(__pyx_t_54); - PyTuple_SET_ITEM(__pyx_t_1, 52, __pyx_t_54); + PyTuple_SET_ITEM(__pyx_t_2, 52, __pyx_t_54); __Pyx_GIVEREF(__pyx_t_55); - PyTuple_SET_ITEM(__pyx_t_1, 53, __pyx_t_55); + PyTuple_SET_ITEM(__pyx_t_2, 53, __pyx_t_55); __Pyx_GIVEREF(__pyx_t_56); - PyTuple_SET_ITEM(__pyx_t_1, 54, __pyx_t_56); + PyTuple_SET_ITEM(__pyx_t_2, 54, __pyx_t_56); __Pyx_GIVEREF(__pyx_t_57); - PyTuple_SET_ITEM(__pyx_t_1, 55, __pyx_t_57); + PyTuple_SET_ITEM(__pyx_t_2, 55, __pyx_t_57); __Pyx_GIVEREF(__pyx_t_58); - PyTuple_SET_ITEM(__pyx_t_1, 56, __pyx_t_58); + PyTuple_SET_ITEM(__pyx_t_2, 56, __pyx_t_58); __Pyx_GIVEREF(__pyx_t_59); - PyTuple_SET_ITEM(__pyx_t_1, 57, __pyx_t_59); + PyTuple_SET_ITEM(__pyx_t_2, 57, __pyx_t_59); __Pyx_GIVEREF(__pyx_t_60); - PyTuple_SET_ITEM(__pyx_t_1, 58, __pyx_t_60); + PyTuple_SET_ITEM(__pyx_t_2, 58, __pyx_t_60); __Pyx_GIVEREF(__pyx_t_61); - PyTuple_SET_ITEM(__pyx_t_1, 59, __pyx_t_61); + PyTuple_SET_ITEM(__pyx_t_2, 59, __pyx_t_61); __Pyx_GIVEREF(__pyx_t_62); - PyTuple_SET_ITEM(__pyx_t_1, 60, __pyx_t_62); + PyTuple_SET_ITEM(__pyx_t_2, 60, __pyx_t_62); __Pyx_GIVEREF(__pyx_t_63); - PyTuple_SET_ITEM(__pyx_t_1, 61, __pyx_t_63); + PyTuple_SET_ITEM(__pyx_t_2, 61, __pyx_t_63); __Pyx_GIVEREF(__pyx_t_64); - PyTuple_SET_ITEM(__pyx_t_1, 62, __pyx_t_64); + PyTuple_SET_ITEM(__pyx_t_2, 62, __pyx_t_64); __Pyx_GIVEREF(__pyx_t_65); - PyTuple_SET_ITEM(__pyx_t_1, 63, __pyx_t_65); + PyTuple_SET_ITEM(__pyx_t_2, 63, __pyx_t_65); __Pyx_GIVEREF(__pyx_t_66); - PyTuple_SET_ITEM(__pyx_t_1, 64, __pyx_t_66); + PyTuple_SET_ITEM(__pyx_t_2, 64, __pyx_t_66); __Pyx_GIVEREF(__pyx_t_67); - PyTuple_SET_ITEM(__pyx_t_1, 65, __pyx_t_67); + PyTuple_SET_ITEM(__pyx_t_2, 65, __pyx_t_67); __Pyx_GIVEREF(__pyx_t_68); - PyTuple_SET_ITEM(__pyx_t_1, 66, __pyx_t_68); + PyTuple_SET_ITEM(__pyx_t_2, 66, __pyx_t_68); __Pyx_GIVEREF(__pyx_t_69); - PyTuple_SET_ITEM(__pyx_t_1, 67, __pyx_t_69); + PyTuple_SET_ITEM(__pyx_t_2, 67, __pyx_t_69); __Pyx_GIVEREF(__pyx_t_70); - PyTuple_SET_ITEM(__pyx_t_1, 68, __pyx_t_70); + PyTuple_SET_ITEM(__pyx_t_2, 68, __pyx_t_70); __Pyx_GIVEREF(__pyx_t_71); - PyTuple_SET_ITEM(__pyx_t_1, 69, __pyx_t_71); + PyTuple_SET_ITEM(__pyx_t_2, 69, __pyx_t_71); __Pyx_GIVEREF(__pyx_t_72); - PyTuple_SET_ITEM(__pyx_t_1, 70, __pyx_t_72); + PyTuple_SET_ITEM(__pyx_t_2, 70, __pyx_t_72); __Pyx_GIVEREF(__pyx_t_73); - PyTuple_SET_ITEM(__pyx_t_1, 71, __pyx_t_73); + PyTuple_SET_ITEM(__pyx_t_2, 71, __pyx_t_73); __Pyx_GIVEREF(__pyx_t_74); - PyTuple_SET_ITEM(__pyx_t_1, 72, __pyx_t_74); + PyTuple_SET_ITEM(__pyx_t_2, 72, __pyx_t_74); __Pyx_GIVEREF(__pyx_t_75); - PyTuple_SET_ITEM(__pyx_t_1, 73, __pyx_t_75); + PyTuple_SET_ITEM(__pyx_t_2, 73, __pyx_t_75); __Pyx_GIVEREF(__pyx_t_76); - PyTuple_SET_ITEM(__pyx_t_1, 74, __pyx_t_76); + PyTuple_SET_ITEM(__pyx_t_2, 74, __pyx_t_76); __Pyx_GIVEREF(__pyx_t_77); - PyTuple_SET_ITEM(__pyx_t_1, 75, __pyx_t_77); + PyTuple_SET_ITEM(__pyx_t_2, 75, __pyx_t_77); __Pyx_GIVEREF(__pyx_t_78); - PyTuple_SET_ITEM(__pyx_t_1, 76, __pyx_t_78); - __pyx_t_2 = 0; + PyTuple_SET_ITEM(__pyx_t_2, 76, __pyx_t_78); + __pyx_t_1 = 0; __pyx_t_3 = 0; __pyx_t_4 = 0; __pyx_t_5 = 0; @@ -19748,9 +19657,9 @@ if (!__Pyx_RefNanny) { __pyx_t_77 = 0; __pyx_t_78 = 0; __Pyx_XGOTREF(__pyx_v_7aiohttp_12_http_parser_headers); - __Pyx_DECREF_SET(__pyx_v_7aiohttp_12_http_parser_headers, ((PyObject*)__pyx_t_1)); - __Pyx_GIVEREF(__pyx_t_1); - __pyx_t_1 = 0; + __Pyx_DECREF_SET(__pyx_v_7aiohttp_12_http_parser_headers, ((PyObject*)__pyx_t_2)); + __Pyx_GIVEREF(__pyx_t_2); + __pyx_t_2 = 0; /* "aiohttp/_http_parser.pyx":57 * char* PyByteArray_AsString(object) @@ -19759,7 +19668,7 @@ if (!__Pyx_RefNanny) { * 'RawRequestMessage', 'RawResponseMessage') * */ - if (PyDict_SetItem(__pyx_d, __pyx_n_s_all, __pyx_tuple__12) < 0) __PYX_ERR(0, 57, __pyx_L1_error) + if (PyDict_SetItem(__pyx_d, __pyx_n_s_all, __pyx_tuple__19) < 0) __PYX_ERR(0, 57, __pyx_L1_error) /* "aiohttp/_http_parser.pyx":60 * 'RawRequestMessage', 'RawResponseMessage') @@ -19768,12 +19677,12 @@ if (!__Pyx_RefNanny) { * cdef object URL_build = URL.build * cdef object CIMultiDict = _CIMultiDict */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_URL_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 60, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_URL_2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 60, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); __Pyx_XGOTREF(__pyx_v_7aiohttp_12_http_parser_URL); - __Pyx_DECREF_SET(__pyx_v_7aiohttp_12_http_parser_URL, __pyx_t_1); - __Pyx_GIVEREF(__pyx_t_1); - __pyx_t_1 = 0; + __Pyx_DECREF_SET(__pyx_v_7aiohttp_12_http_parser_URL, __pyx_t_2); + __Pyx_GIVEREF(__pyx_t_2); + __pyx_t_2 = 0; /* "aiohttp/_http_parser.pyx":61 * @@ -19782,12 +19691,12 @@ if (!__Pyx_RefNanny) { * cdef object CIMultiDict = _CIMultiDict * cdef object CIMultiDictProxy = _CIMultiDictProxy */ - __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_7aiohttp_12_http_parser_URL, __pyx_n_s_build); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 61, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_7aiohttp_12_http_parser_URL, __pyx_n_s_build); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 61, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); __Pyx_XGOTREF(__pyx_v_7aiohttp_12_http_parser_URL_build); - __Pyx_DECREF_SET(__pyx_v_7aiohttp_12_http_parser_URL_build, __pyx_t_1); - __Pyx_GIVEREF(__pyx_t_1); - __pyx_t_1 = 0; + __Pyx_DECREF_SET(__pyx_v_7aiohttp_12_http_parser_URL_build, __pyx_t_2); + __Pyx_GIVEREF(__pyx_t_2); + __pyx_t_2 = 0; /* "aiohttp/_http_parser.pyx":62 * cdef object URL = _URL @@ -19796,12 +19705,12 @@ if (!__Pyx_RefNanny) { * cdef object CIMultiDictProxy = _CIMultiDictProxy * cdef object HttpVersion = _HttpVersion */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_CIMultiDict_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 62, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_CIMultiDict_2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 62, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); __Pyx_XGOTREF(__pyx_v_7aiohttp_12_http_parser_CIMultiDict); - __Pyx_DECREF_SET(__pyx_v_7aiohttp_12_http_parser_CIMultiDict, __pyx_t_1); - __Pyx_GIVEREF(__pyx_t_1); - __pyx_t_1 = 0; + __Pyx_DECREF_SET(__pyx_v_7aiohttp_12_http_parser_CIMultiDict, __pyx_t_2); + __Pyx_GIVEREF(__pyx_t_2); + __pyx_t_2 = 0; /* "aiohttp/_http_parser.pyx":63 * cdef object URL_build = URL.build @@ -19810,12 +19719,12 @@ if (!__Pyx_RefNanny) { * cdef object HttpVersion = _HttpVersion * cdef object HttpVersion10 = _HttpVersion10 */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_CIMultiDictProxy_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 63, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_CIMultiDictProxy_2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 63, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); __Pyx_XGOTREF(__pyx_v_7aiohttp_12_http_parser_CIMultiDictProxy); - __Pyx_DECREF_SET(__pyx_v_7aiohttp_12_http_parser_CIMultiDictProxy, __pyx_t_1); - __Pyx_GIVEREF(__pyx_t_1); - __pyx_t_1 = 0; + __Pyx_DECREF_SET(__pyx_v_7aiohttp_12_http_parser_CIMultiDictProxy, __pyx_t_2); + __Pyx_GIVEREF(__pyx_t_2); + __pyx_t_2 = 0; /* "aiohttp/_http_parser.pyx":64 * cdef object CIMultiDict = _CIMultiDict @@ -19824,12 +19733,12 @@ if (!__Pyx_RefNanny) { * cdef object HttpVersion10 = _HttpVersion10 * cdef object HttpVersion11 = _HttpVersion11 */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_HttpVersion_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 64, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_HttpVersion_2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 64, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); __Pyx_XGOTREF(__pyx_v_7aiohttp_12_http_parser_HttpVersion); - __Pyx_DECREF_SET(__pyx_v_7aiohttp_12_http_parser_HttpVersion, __pyx_t_1); - __Pyx_GIVEREF(__pyx_t_1); - __pyx_t_1 = 0; + __Pyx_DECREF_SET(__pyx_v_7aiohttp_12_http_parser_HttpVersion, __pyx_t_2); + __Pyx_GIVEREF(__pyx_t_2); + __pyx_t_2 = 0; /* "aiohttp/_http_parser.pyx":65 * cdef object CIMultiDictProxy = _CIMultiDictProxy @@ -19838,12 +19747,12 @@ if (!__Pyx_RefNanny) { * cdef object HttpVersion11 = _HttpVersion11 * cdef object SEC_WEBSOCKET_KEY1 = hdrs.SEC_WEBSOCKET_KEY1 */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_HttpVersion10_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 65, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_HttpVersion10_2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 65, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); __Pyx_XGOTREF(__pyx_v_7aiohttp_12_http_parser_HttpVersion10); - __Pyx_DECREF_SET(__pyx_v_7aiohttp_12_http_parser_HttpVersion10, __pyx_t_1); - __Pyx_GIVEREF(__pyx_t_1); - __pyx_t_1 = 0; + __Pyx_DECREF_SET(__pyx_v_7aiohttp_12_http_parser_HttpVersion10, __pyx_t_2); + __Pyx_GIVEREF(__pyx_t_2); + __pyx_t_2 = 0; /* "aiohttp/_http_parser.pyx":66 * cdef object HttpVersion = _HttpVersion @@ -19852,12 +19761,12 @@ if (!__Pyx_RefNanny) { * cdef object SEC_WEBSOCKET_KEY1 = hdrs.SEC_WEBSOCKET_KEY1 * cdef object CONTENT_ENCODING = hdrs.CONTENT_ENCODING */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_HttpVersion11_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 66, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_HttpVersion11_2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 66, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); __Pyx_XGOTREF(__pyx_v_7aiohttp_12_http_parser_HttpVersion11); - __Pyx_DECREF_SET(__pyx_v_7aiohttp_12_http_parser_HttpVersion11, __pyx_t_1); - __Pyx_GIVEREF(__pyx_t_1); - __pyx_t_1 = 0; + __Pyx_DECREF_SET(__pyx_v_7aiohttp_12_http_parser_HttpVersion11, __pyx_t_2); + __Pyx_GIVEREF(__pyx_t_2); + __pyx_t_2 = 0; /* "aiohttp/_http_parser.pyx":67 * cdef object HttpVersion10 = _HttpVersion10 @@ -19866,11 +19775,11 @@ if (!__Pyx_RefNanny) { * cdef object CONTENT_ENCODING = hdrs.CONTENT_ENCODING * cdef object EMPTY_PAYLOAD = _EMPTY_PAYLOAD */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 67, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_78 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_SEC_WEBSOCKET_KEY1); if (unlikely(!__pyx_t_78)) __PYX_ERR(0, 67, __pyx_L1_error) + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 67, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_78 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_SEC_WEBSOCKET_KEY1); if (unlikely(!__pyx_t_78)) __PYX_ERR(0, 67, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_78); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; __Pyx_XGOTREF(__pyx_v_7aiohttp_12_http_parser_SEC_WEBSOCKET_KEY1); __Pyx_DECREF_SET(__pyx_v_7aiohttp_12_http_parser_SEC_WEBSOCKET_KEY1, __pyx_t_78); __Pyx_GIVEREF(__pyx_t_78); @@ -19885,13 +19794,13 @@ if (!__Pyx_RefNanny) { */ __Pyx_GetModuleGlobalName(__pyx_t_78, __pyx_n_s_hdrs); if (unlikely(!__pyx_t_78)) __PYX_ERR(0, 68, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_78); - __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_78, __pyx_n_s_CONTENT_ENCODING); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 68, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_78, __pyx_n_s_CONTENT_ENCODING); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 68, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); __Pyx_DECREF(__pyx_t_78); __pyx_t_78 = 0; __Pyx_XGOTREF(__pyx_v_7aiohttp_12_http_parser_CONTENT_ENCODING); - __Pyx_DECREF_SET(__pyx_v_7aiohttp_12_http_parser_CONTENT_ENCODING, __pyx_t_1); - __Pyx_GIVEREF(__pyx_t_1); - __pyx_t_1 = 0; + __Pyx_DECREF_SET(__pyx_v_7aiohttp_12_http_parser_CONTENT_ENCODING, __pyx_t_2); + __Pyx_GIVEREF(__pyx_t_2); + __pyx_t_2 = 0; /* "aiohttp/_http_parser.pyx":69 * cdef object SEC_WEBSOCKET_KEY1 = hdrs.SEC_WEBSOCKET_KEY1 @@ -19900,12 +19809,12 @@ if (!__Pyx_RefNanny) { * cdef object StreamReader = _StreamReader * cdef object DeflateBuffer = _DeflateBuffer */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_EMPTY_PAYLOAD_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 69, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_EMPTY_PAYLOAD_2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 69, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); __Pyx_XGOTREF(__pyx_v_7aiohttp_12_http_parser_EMPTY_PAYLOAD); - __Pyx_DECREF_SET(__pyx_v_7aiohttp_12_http_parser_EMPTY_PAYLOAD, __pyx_t_1); - __Pyx_GIVEREF(__pyx_t_1); - __pyx_t_1 = 0; + __Pyx_DECREF_SET(__pyx_v_7aiohttp_12_http_parser_EMPTY_PAYLOAD, __pyx_t_2); + __Pyx_GIVEREF(__pyx_t_2); + __pyx_t_2 = 0; /* "aiohttp/_http_parser.pyx":70 * cdef object CONTENT_ENCODING = hdrs.CONTENT_ENCODING @@ -19914,12 +19823,12 @@ if (!__Pyx_RefNanny) { * cdef object DeflateBuffer = _DeflateBuffer * */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_StreamReader_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 70, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_StreamReader_2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 70, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); __Pyx_XGOTREF(__pyx_v_7aiohttp_12_http_parser_StreamReader); - __Pyx_DECREF_SET(__pyx_v_7aiohttp_12_http_parser_StreamReader, __pyx_t_1); - __Pyx_GIVEREF(__pyx_t_1); - __pyx_t_1 = 0; + __Pyx_DECREF_SET(__pyx_v_7aiohttp_12_http_parser_StreamReader, __pyx_t_2); + __Pyx_GIVEREF(__pyx_t_2); + __pyx_t_2 = 0; /* "aiohttp/_http_parser.pyx":71 * cdef object EMPTY_PAYLOAD = _EMPTY_PAYLOAD @@ -19928,45 +19837,45 @@ if (!__Pyx_RefNanny) { * * */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_DeflateBuffer_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 71, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_DeflateBuffer_2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 71, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); __Pyx_XGOTREF(__pyx_v_7aiohttp_12_http_parser_DeflateBuffer); - __Pyx_DECREF_SET(__pyx_v_7aiohttp_12_http_parser_DeflateBuffer, __pyx_t_1); - __Pyx_GIVEREF(__pyx_t_1); - __pyx_t_1 = 0; + __Pyx_DECREF_SET(__pyx_v_7aiohttp_12_http_parser_DeflateBuffer, __pyx_t_2); + __Pyx_GIVEREF(__pyx_t_2); + __pyx_t_2 = 0; /* "aiohttp/_http_parser.pyx":85 - * DEF METHODS_COUNT = 34; + * DEF METHODS_COUNT = 46; * * cdef list _http_method = [] # <<<<<<<<<<<<<< * * for i in range(METHODS_COUNT): */ - __pyx_t_1 = PyList_New(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 85, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = PyList_New(0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 85, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); __Pyx_XGOTREF(__pyx_v_7aiohttp_12_http_parser__http_method); - __Pyx_DECREF_SET(__pyx_v_7aiohttp_12_http_parser__http_method, ((PyObject*)__pyx_t_1)); - __Pyx_GIVEREF(__pyx_t_1); - __pyx_t_1 = 0; + __Pyx_DECREF_SET(__pyx_v_7aiohttp_12_http_parser__http_method, ((PyObject*)__pyx_t_2)); + __Pyx_GIVEREF(__pyx_t_2); + __pyx_t_2 = 0; /* "aiohttp/_http_parser.pyx":87 * cdef list _http_method = [] * * for i in range(METHODS_COUNT): # <<<<<<<<<<<<<< * _http_method.append( - * cparser.http_method_str( i).decode('ascii')) + * cparser.llhttp_method_name( i).decode('ascii')) */ - for (__pyx_t_79 = 0; __pyx_t_79 < 34; __pyx_t_79+=1) { - __pyx_t_1 = __Pyx_PyInt_From_long(__pyx_t_79); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 87, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - if (PyDict_SetItem(__pyx_d, __pyx_n_s_i, __pyx_t_1) < 0) __PYX_ERR(0, 87, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + for (__pyx_t_79 = 0; __pyx_t_79 < 46; __pyx_t_79+=1) { + __pyx_t_2 = __Pyx_PyInt_From_long(__pyx_t_79); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 87, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_i, __pyx_t_2) < 0) __PYX_ERR(0, 87, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_http_parser.pyx":88 * * for i in range(METHODS_COUNT): * _http_method.append( # <<<<<<<<<<<<<< - * cparser.http_method_str( i).decode('ascii')) + * cparser.llhttp_method_name( i).decode('ascii')) * */ if (unlikely(__pyx_v_7aiohttp_12_http_parser__http_method == Py_None)) { @@ -19977,50 +19886,38 @@ if (!__Pyx_RefNanny) { /* "aiohttp/_http_parser.pyx":89 * for i in range(METHODS_COUNT): * _http_method.append( - * cparser.http_method_str( i).decode('ascii')) # <<<<<<<<<<<<<< + * cparser.llhttp_method_name( i).decode('ascii')) # <<<<<<<<<<<<<< * * */ - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_i); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 89, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_80 = ((enum http_method)__Pyx_PyInt_As_enum__http_method(__pyx_t_1)); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 89, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __pyx_t_81 = http_method_str(((enum http_method)__pyx_t_80)); - __pyx_t_1 = __Pyx_decode_c_string(__pyx_t_81, 0, strlen(__pyx_t_81), NULL, NULL, PyUnicode_DecodeASCII); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 89, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); + __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_i); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 89, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_80 = ((enum llhttp_method)__Pyx_PyInt_As_enum__llhttp_method(__pyx_t_2)); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 89, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_81 = llhttp_method_name(((llhttp_method_t)__pyx_t_80)); + __pyx_t_2 = __Pyx_decode_c_string(__pyx_t_81, 0, strlen(__pyx_t_81), NULL, NULL, PyUnicode_DecodeASCII); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 89, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); /* "aiohttp/_http_parser.pyx":88 * * for i in range(METHODS_COUNT): * _http_method.append( # <<<<<<<<<<<<<< - * cparser.http_method_str( i).decode('ascii')) + * cparser.llhttp_method_name( i).decode('ascii')) * */ - __pyx_t_82 = __Pyx_PyList_Append(__pyx_v_7aiohttp_12_http_parser__http_method, __pyx_t_1); if (unlikely(__pyx_t_82 == ((int)-1))) __PYX_ERR(0, 88, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_82 = __Pyx_PyList_Append(__pyx_v_7aiohttp_12_http_parser__http_method, __pyx_t_2); if (unlikely(__pyx_t_82 == ((int)-1))) __PYX_ERR(0, 88, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; } - /* "aiohttp/_http_parser.pyx":785 - * - * - * def parse_url(url): # <<<<<<<<<<<<<< - * cdef: - * Py_buffer py_buf - */ - __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_7aiohttp_12_http_parser_1parse_url, NULL, __pyx_n_s_aiohttp__http_parser); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 785, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - if (PyDict_SetItem(__pyx_d, __pyx_n_s_parse_url, __pyx_t_1) < 0) __PYX_ERR(0, 785, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - /* "(tree fragment)":1 * def __pyx_unpickle_RawRequestMessage(__pyx_type, long __pyx_checksum, __pyx_state): # <<<<<<<<<<<<<< * cdef object __pyx_PickleError * cdef object __pyx_result */ - __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_7aiohttp_12_http_parser_3__pyx_unpickle_RawRequestMessage, NULL, __pyx_n_s_aiohttp__http_parser); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 1, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - if (PyDict_SetItem(__pyx_d, __pyx_n_s_pyx_unpickle_RawRequestMessage, __pyx_t_1) < 0) __PYX_ERR(1, 1, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_7aiohttp_12_http_parser_1__pyx_unpickle_RawRequestMessage, NULL, __pyx_n_s_aiohttp__http_parser); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 1, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_pyx_unpickle_RawRequestMessage, __pyx_t_2) < 0) __PYX_ERR(1, 1, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "(tree fragment)":11 * __pyx_unpickle_RawRequestMessage__set_state( __pyx_result, __pyx_state) @@ -20029,20 +19926,20 @@ if (!__Pyx_RefNanny) { * __pyx_result.chunked = __pyx_state[0]; __pyx_result.compression = __pyx_state[1]; __pyx_result.headers = __pyx_state[2]; __pyx_result.method = __pyx_state[3]; __pyx_result.path = __pyx_state[4]; __pyx_result.raw_headers = __pyx_state[5]; __pyx_result.should_close = __pyx_state[6]; __pyx_result.upgrade = __pyx_state[7]; __pyx_result.url = __pyx_state[8]; __pyx_result.version = __pyx_state[9] * if len(__pyx_state) > 10 and hasattr(__pyx_result, '__dict__'): */ - __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_7aiohttp_12_http_parser_5__pyx_unpickle_RawResponseMessage, NULL, __pyx_n_s_aiohttp__http_parser); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 1, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - if (PyDict_SetItem(__pyx_d, __pyx_n_s_pyx_unpickle_RawResponseMessag, __pyx_t_1) < 0) __PYX_ERR(1, 1, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_7aiohttp_12_http_parser_3__pyx_unpickle_RawResponseMessage, NULL, __pyx_n_s_aiohttp__http_parser); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 1, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_pyx_unpickle_RawResponseMessag, __pyx_t_2) < 0) __PYX_ERR(1, 1, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_http_parser.pyx":1 * #cython: language_level=3 # <<<<<<<<<<<<<< * # * # Based on https://github.com/MagicStack/httptools */ - __pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - if (PyDict_SetItem(__pyx_d, __pyx_n_s_test, __pyx_t_1) < 0) __PYX_ERR(0, 1, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_2 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_test, __pyx_t_2) < 0) __PYX_ERR(0, 1, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /*--- Wrapped vars code ---*/ @@ -20850,7 +20747,7 @@ static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, #if CYTHON_COMPILING_IN_CPYTHON static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw) { PyObject *result; - ternaryfunc call = func->ob_type->tp_call; + ternaryfunc call = Py_TYPE(func)->tp_call; if (unlikely(!call)) return PyObject_Call(func, arg, kw); if (unlikely(Py_EnterRecursiveCall((char*)" while calling a Python object"))) @@ -20953,7 +20850,7 @@ static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObjec if (likely(PyCFunction_GET_FLAGS(func) & METH_O)) { return __Pyx_PyObject_CallMethO(func, arg); #if CYTHON_FAST_PYCCALL - } else if (PyCFunction_GET_FLAGS(func) & METH_FASTCALL) { + } else if (__Pyx_PyFastCFunction_Check(func)) { return __Pyx_PyCFunction_FastCall(func, &arg, 1); #endif } @@ -21179,7 +21076,7 @@ static CYTHON_INLINE int __Pyx_PyBytes_Equals(PyObject* s1, PyObject* s2, int eq return (equals == Py_EQ); } else { int result; -#if CYTHON_USE_UNICODE_INTERNALS +#if CYTHON_USE_UNICODE_INTERNALS && (PY_VERSION_HEX < 0x030B0000) Py_hash_t hash1, hash2; hash1 = ((PyBytesObject*)s1)->ob_shash; hash2 = ((PyBytesObject*)s2)->ob_shash; @@ -21405,6 +21302,50 @@ static CYTHON_INLINE PyObject* __Pyx_PyObject_GetSlice(PyObject* obj, return NULL; } +/* GetItemIntUnicode */ +static CYTHON_INLINE Py_UCS4 __Pyx_GetItemInt_Unicode_Fast(PyObject* ustring, Py_ssize_t i, + int wraparound, int boundscheck) { + Py_ssize_t length; + if (unlikely(__Pyx_PyUnicode_READY(ustring) < 0)) return (Py_UCS4)-1; + if (wraparound | boundscheck) { + length = __Pyx_PyUnicode_GET_LENGTH(ustring); + if (wraparound & unlikely(i < 0)) i += length; + if ((!boundscheck) || likely(__Pyx_is_valid_index(i, length))) { + return __Pyx_PyUnicode_READ_CHAR(ustring, i); + } else { + PyErr_SetString(PyExc_IndexError, "string index out of range"); + return (Py_UCS4)-1; + } + } else { + return __Pyx_PyUnicode_READ_CHAR(ustring, i); + } +} + +/* PyUnicode_Substring */ +static CYTHON_INLINE PyObject* __Pyx_PyUnicode_Substring( + PyObject* text, Py_ssize_t start, Py_ssize_t stop) { + Py_ssize_t length; + if (unlikely(__Pyx_PyUnicode_READY(text) == -1)) return NULL; + length = __Pyx_PyUnicode_GET_LENGTH(text); + if (start < 0) { + start += length; + if (start < 0) + start = 0; + } + if (stop < 0) + stop += length; + else if (stop > length) + stop = length; + if (stop <= start) + return __Pyx_NewRef(__pyx_empty_unicode); +#if CYTHON_PEP393_ENABLED + return PyUnicode_FromKindAndData(PyUnicode_KIND(text), + PyUnicode_1BYTE_DATA(text) + start*PyUnicode_KIND(text), stop-start); +#else + return PyUnicode_FromUnicode(PyUnicode_AS_UNICODE(text)+start, stop-start); +#endif +} + /* GetException */ #if CYTHON_FAST_THREAD_STATE static int __Pyx__GetException(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) @@ -21570,111 +21511,6 @@ static CYTHON_INLINE void __Pyx__ExceptionReset(PyThreadState *tstate, PyObject } #endif -/* decode_c_string */ -static CYTHON_INLINE PyObject* __Pyx_decode_c_string( - const char* cstring, Py_ssize_t start, Py_ssize_t stop, - const char* encoding, const char* errors, - PyObject* (*decode_func)(const char *s, Py_ssize_t size, const char *errors)) { - Py_ssize_t length; - if (unlikely((start < 0) | (stop < 0))) { - size_t slen = strlen(cstring); - if (unlikely(slen > (size_t) PY_SSIZE_T_MAX)) { - PyErr_SetString(PyExc_OverflowError, - "c-string too long to convert to Python"); - return NULL; - } - length = (Py_ssize_t) slen; - if (start < 0) { - start += length; - if (start < 0) - start = 0; - } - if (stop < 0) - stop += length; - } - if (unlikely(stop <= start)) - return __Pyx_NewRef(__pyx_empty_unicode); - length = stop - start; - cstring += start; - if (decode_func) { - return decode_func(cstring, length, errors); - } else { - return PyUnicode_Decode(cstring, length, encoding, errors); - } -} - -/* UnpackUnboundCMethod */ -static int __Pyx_TryUnpackUnboundCMethod(__Pyx_CachedCFunction* target) { - PyObject *method; - method = __Pyx_PyObject_GetAttrStr(target->type, *target->method_name); - if (unlikely(!method)) - return -1; - target->method = method; -#if CYTHON_COMPILING_IN_CPYTHON - #if PY_MAJOR_VERSION >= 3 - if (likely(__Pyx_TypeCheck(method, &PyMethodDescr_Type))) - #endif - { - PyMethodDescrObject *descr = (PyMethodDescrObject*) method; - target->func = descr->d_method->ml_meth; - target->flag = descr->d_method->ml_flags & ~(METH_CLASS | METH_STATIC | METH_COEXIST | METH_STACKLESS); - } -#endif - return 0; -} - -/* CallUnboundCMethod1 */ -#if CYTHON_COMPILING_IN_CPYTHON -static CYTHON_INLINE PyObject* __Pyx_CallUnboundCMethod1(__Pyx_CachedCFunction* cfunc, PyObject* self, PyObject* arg) { - if (likely(cfunc->func)) { - int flag = cfunc->flag; - if (flag == METH_O) { - return (*(cfunc->func))(self, arg); - } else if (PY_VERSION_HEX >= 0x030600B1 && flag == METH_FASTCALL) { - if (PY_VERSION_HEX >= 0x030700A0) { - return (*(__Pyx_PyCFunctionFast)(void*)(PyCFunction)cfunc->func)(self, &arg, 1); - } else { - return (*(__Pyx_PyCFunctionFastWithKeywords)(void*)(PyCFunction)cfunc->func)(self, &arg, 1, NULL); - } - } else if (PY_VERSION_HEX >= 0x030700A0 && flag == (METH_FASTCALL | METH_KEYWORDS)) { - return (*(__Pyx_PyCFunctionFastWithKeywords)(void*)(PyCFunction)cfunc->func)(self, &arg, 1, NULL); - } - } - return __Pyx__CallUnboundCMethod1(cfunc, self, arg); -} -#endif -static PyObject* __Pyx__CallUnboundCMethod1(__Pyx_CachedCFunction* cfunc, PyObject* self, PyObject* arg){ - PyObject *args, *result = NULL; - if (unlikely(!cfunc->func && !cfunc->method) && unlikely(__Pyx_TryUnpackUnboundCMethod(cfunc) < 0)) return NULL; -#if CYTHON_COMPILING_IN_CPYTHON - if (cfunc->func && (cfunc->flag & METH_VARARGS)) { - args = PyTuple_New(1); - if (unlikely(!args)) goto bad; - Py_INCREF(arg); - PyTuple_SET_ITEM(args, 0, arg); - if (cfunc->flag & METH_KEYWORDS) - result = (*(PyCFunctionWithKeywords)(void*)(PyCFunction)cfunc->func)(self, args, NULL); - else - result = (*cfunc->func)(self, args); - } else { - args = PyTuple_New(2); - if (unlikely(!args)) goto bad; - Py_INCREF(self); - PyTuple_SET_ITEM(args, 0, self); - Py_INCREF(arg); - PyTuple_SET_ITEM(args, 1, arg); - result = __Pyx_PyObject_Call(cfunc->method, args, NULL); - } -#else - args = PyTuple_Pack(2, self, arg); - if (unlikely(!args)) goto bad; - result = __Pyx_PyObject_Call(cfunc->method, args, NULL); -#endif -bad: - Py_XDECREF(args); - return result; -} - /* Import */ static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, int level) { PyObject *empty_list = 0; @@ -21864,17 +21700,35 @@ static int __Pyx_setup_reduce_is_named(PyObject* meth, PyObject* name) { static int __Pyx_setup_reduce(PyObject* type_obj) { int ret = 0; PyObject *object_reduce = NULL; + PyObject *object_getstate = NULL; PyObject *object_reduce_ex = NULL; PyObject *reduce = NULL; PyObject *reduce_ex = NULL; PyObject *reduce_cython = NULL; PyObject *setstate = NULL; PyObject *setstate_cython = NULL; + PyObject *getstate = NULL; +#if CYTHON_USE_PYTYPE_LOOKUP + getstate = _PyType_Lookup((PyTypeObject*)type_obj, __pyx_n_s_getstate); +#else + getstate = __Pyx_PyObject_GetAttrStrNoError(type_obj, __pyx_n_s_getstate); + if (!getstate && PyErr_Occurred()) { + goto __PYX_BAD; + } +#endif + if (getstate) { #if CYTHON_USE_PYTYPE_LOOKUP - if (_PyType_Lookup((PyTypeObject*)type_obj, __pyx_n_s_getstate)) goto __PYX_GOOD; + object_getstate = _PyType_Lookup(&PyBaseObject_Type, __pyx_n_s_getstate); #else - if (PyObject_HasAttr(type_obj, __pyx_n_s_getstate)) goto __PYX_GOOD; + object_getstate = __Pyx_PyObject_GetAttrStrNoError((PyObject*)&PyBaseObject_Type, __pyx_n_s_getstate); + if (!object_getstate && PyErr_Occurred()) { + goto __PYX_BAD; + } #endif + if (object_getstate != getstate) { + goto __PYX_GOOD; + } + } #if CYTHON_USE_PYTYPE_LOOKUP object_reduce_ex = _PyType_Lookup(&PyBaseObject_Type, __pyx_n_s_reduce_ex); if (!object_reduce_ex) goto __PYX_BAD; #else @@ -21919,6 +21773,8 @@ static int __Pyx_setup_reduce(PyObject* type_obj) { #if !CYTHON_USE_PYTYPE_LOOKUP Py_XDECREF(object_reduce); Py_XDECREF(object_reduce_ex); + Py_XDECREF(object_getstate); + Py_XDECREF(getstate); #endif Py_XDECREF(reduce); Py_XDECREF(reduce_ex); @@ -21993,19 +21849,52 @@ static PyTypeObject *__Pyx_ImportType(PyObject *module, const char *module_name, module_name, class_name, size, basicsize); goto bad; } - else if (check_size == __Pyx_ImportType_CheckSize_Warn && (size_t)basicsize > size) { - PyOS_snprintf(warning, sizeof(warning), - "%s.%s size changed, may indicate binary incompatibility. " - "Expected %zd from C header, got %zd from PyObject", - module_name, class_name, size, basicsize); - if (PyErr_WarnEx(NULL, warning, 0) < 0) goto bad; + else if (check_size == __Pyx_ImportType_CheckSize_Warn && (size_t)basicsize > size) { + PyOS_snprintf(warning, sizeof(warning), + "%s.%s size changed, may indicate binary incompatibility. " + "Expected %zd from C header, got %zd from PyObject", + module_name, class_name, size, basicsize); + if (PyErr_WarnEx(NULL, warning, 0) < 0) goto bad; + } + return (PyTypeObject *)result; +bad: + Py_XDECREF(result); + return NULL; +} +#endif + +/* decode_c_string */ +static CYTHON_INLINE PyObject* __Pyx_decode_c_string( + const char* cstring, Py_ssize_t start, Py_ssize_t stop, + const char* encoding, const char* errors, + PyObject* (*decode_func)(const char *s, Py_ssize_t size, const char *errors)) { + Py_ssize_t length; + if (unlikely((start < 0) | (stop < 0))) { + size_t slen = strlen(cstring); + if (unlikely(slen > (size_t) PY_SSIZE_T_MAX)) { + PyErr_SetString(PyExc_OverflowError, + "c-string too long to convert to Python"); + return NULL; + } + length = (Py_ssize_t) slen; + if (start < 0) { + start += length; + if (start < 0) + start = 0; + } + if (stop < 0) + stop += length; + } + if (unlikely(stop <= start)) + return __Pyx_NewRef(__pyx_empty_unicode); + length = stop - start; + cstring += start; + if (decode_func) { + return decode_func(cstring, length, errors); + } else { + return PyUnicode_Decode(cstring, length, encoding, errors); } - return (PyTypeObject *)result; -bad: - Py_XDECREF(result); - return NULL; } -#endif /* CLineInTraceback */ #ifndef CYTHON_CLINE_IN_TRACEBACK @@ -22039,7 +21928,7 @@ static int __Pyx_CLineForTraceback(CYTHON_NCP_UNUSED PyThreadState *tstate, int } if (!use_cline) { c_line = 0; - PyObject_SetAttr(__pyx_cython_runtime, __pyx_n_s_cline_in_traceback, Py_False); + (void) PyObject_SetAttr(__pyx_cython_runtime, __pyx_n_s_cline_in_traceback, Py_False); } else if (use_cline == Py_False || (use_cline != Py_True && PyObject_Not(use_cline) != 0)) { c_line = 0; @@ -22133,33 +22022,40 @@ static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object) { #include "compile.h" #include "frameobject.h" #include "traceback.h" +#if PY_VERSION_HEX >= 0x030b00a6 + #ifndef Py_BUILD_CORE + #define Py_BUILD_CORE 1 + #endif + #include "internal/pycore_frame.h" +#endif static PyCodeObject* __Pyx_CreateCodeObjectForTraceback( const char *funcname, int c_line, int py_line, const char *filename) { - PyCodeObject *py_code = 0; - PyObject *py_srcfile = 0; - PyObject *py_funcname = 0; + PyCodeObject *py_code = NULL; + PyObject *py_funcname = NULL; #if PY_MAJOR_VERSION < 3 + PyObject *py_srcfile = NULL; py_srcfile = PyString_FromString(filename); - #else - py_srcfile = PyUnicode_FromString(filename); - #endif if (!py_srcfile) goto bad; + #endif if (c_line) { #if PY_MAJOR_VERSION < 3 py_funcname = PyString_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line); + if (!py_funcname) goto bad; #else py_funcname = PyUnicode_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line); + if (!py_funcname) goto bad; + funcname = PyUnicode_AsUTF8(py_funcname); + if (!funcname) goto bad; #endif } else { #if PY_MAJOR_VERSION < 3 py_funcname = PyString_FromString(funcname); - #else - py_funcname = PyUnicode_FromString(funcname); + if (!py_funcname) goto bad; #endif } - if (!py_funcname) goto bad; + #if PY_MAJOR_VERSION < 3 py_code = __Pyx_PyCode_New( 0, 0, @@ -22178,11 +22074,16 @@ static PyCodeObject* __Pyx_CreateCodeObjectForTraceback( __pyx_empty_bytes /*PyObject *lnotab*/ ); Py_DECREF(py_srcfile); - Py_DECREF(py_funcname); + #else + py_code = PyCode_NewEmpty(filename, funcname, py_line); + #endif + Py_XDECREF(py_funcname); // XDECREF since it's only set on Py3 if cline return py_code; bad: - Py_XDECREF(py_srcfile); Py_XDECREF(py_funcname); + #if PY_MAJOR_VERSION < 3 + Py_XDECREF(py_srcfile); + #endif return NULL; } static void __Pyx_AddTraceback(const char *funcname, int c_line, @@ -22190,14 +22091,24 @@ static void __Pyx_AddTraceback(const char *funcname, int c_line, PyCodeObject *py_code = 0; PyFrameObject *py_frame = 0; PyThreadState *tstate = __Pyx_PyThreadState_Current; + PyObject *ptype, *pvalue, *ptraceback; if (c_line) { c_line = __Pyx_CLineForTraceback(tstate, c_line); } py_code = __pyx_find_code_object(c_line ? -c_line : py_line); if (!py_code) { + __Pyx_ErrFetchInState(tstate, &ptype, &pvalue, &ptraceback); py_code = __Pyx_CreateCodeObjectForTraceback( funcname, c_line, py_line, filename); - if (!py_code) goto bad; + if (!py_code) { + /* If the code object creation fails, then we should clear the + fetched exception references and propagate the new exception */ + Py_XDECREF(ptype); + Py_XDECREF(pvalue); + Py_XDECREF(ptraceback); + goto bad; + } + __Pyx_ErrRestoreInState(tstate, ptype, pvalue, ptraceback); __pyx_insert_code_object(c_line ? -c_line : py_line, py_code); } py_frame = PyFrame_New( @@ -22214,37 +22125,6 @@ static void __Pyx_AddTraceback(const char *funcname, int c_line, Py_XDECREF(py_frame); } -/* CIntToPy */ -static CYTHON_INLINE PyObject* __Pyx_PyInt_From_int(int value) { - const int neg_one = (int) ((int) 0 - (int) 1), const_zero = (int) 0; - const int is_unsigned = neg_one > const_zero; - if (is_unsigned) { - if (sizeof(int) < sizeof(long)) { - return PyInt_FromLong((long) value); - } else if (sizeof(int) <= sizeof(unsigned long)) { - return PyLong_FromUnsignedLong((unsigned long) value); -#ifdef HAVE_LONG_LONG - } else if (sizeof(int) <= sizeof(unsigned PY_LONG_LONG)) { - return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value); -#endif - } - } else { - if (sizeof(int) <= sizeof(long)) { - return PyInt_FromLong((long) value); -#ifdef HAVE_LONG_LONG - } else if (sizeof(int) <= sizeof(PY_LONG_LONG)) { - return PyLong_FromLongLong((PY_LONG_LONG) value); -#endif - } - } - { - int one = 1; int little = (int)*(unsigned char *)&one; - unsigned char *bytes = (unsigned char *)&value; - return _PyLong_FromByteArray(bytes, sizeof(int), - little, !is_unsigned); - } -} - /* CIntFromPyVerify */ #define __PYX_VERIFY_RETURN_INT(target_type, func_type, func_value)\ __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, 0) @@ -22268,117 +22148,31 @@ static CYTHON_INLINE PyObject* __Pyx_PyInt_From_int(int value) { } /* CIntToPy */ -static CYTHON_INLINE PyObject* __Pyx_PyInt_From_unsigned_int(unsigned int value) { - const unsigned int neg_one = (unsigned int) ((unsigned int) 0 - (unsigned int) 1), const_zero = (unsigned int) 0; - const int is_unsigned = neg_one > const_zero; - if (is_unsigned) { - if (sizeof(unsigned int) < sizeof(long)) { - return PyInt_FromLong((long) value); - } else if (sizeof(unsigned int) <= sizeof(unsigned long)) { - return PyLong_FromUnsignedLong((unsigned long) value); -#ifdef HAVE_LONG_LONG - } else if (sizeof(unsigned int) <= sizeof(unsigned PY_LONG_LONG)) { - return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value); -#endif - } - } else { - if (sizeof(unsigned int) <= sizeof(long)) { - return PyInt_FromLong((long) value); -#ifdef HAVE_LONG_LONG - } else if (sizeof(unsigned int) <= sizeof(PY_LONG_LONG)) { - return PyLong_FromLongLong((PY_LONG_LONG) value); -#endif - } - } - { - int one = 1; int little = (int)*(unsigned char *)&one; - unsigned char *bytes = (unsigned char *)&value; - return _PyLong_FromByteArray(bytes, sizeof(unsigned int), - little, !is_unsigned); - } -} - -/* CIntToPy */ -static CYTHON_INLINE PyObject* __Pyx_PyInt_From_unsigned_short(unsigned short value) { - const unsigned short neg_one = (unsigned short) ((unsigned short) 0 - (unsigned short) 1), const_zero = (unsigned short) 0; - const int is_unsigned = neg_one > const_zero; - if (is_unsigned) { - if (sizeof(unsigned short) < sizeof(long)) { - return PyInt_FromLong((long) value); - } else if (sizeof(unsigned short) <= sizeof(unsigned long)) { - return PyLong_FromUnsignedLong((unsigned long) value); -#ifdef HAVE_LONG_LONG - } else if (sizeof(unsigned short) <= sizeof(unsigned PY_LONG_LONG)) { - return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value); -#endif - } - } else { - if (sizeof(unsigned short) <= sizeof(long)) { - return PyInt_FromLong((long) value); -#ifdef HAVE_LONG_LONG - } else if (sizeof(unsigned short) <= sizeof(PY_LONG_LONG)) { - return PyLong_FromLongLong((PY_LONG_LONG) value); -#endif - } - } - { - int one = 1; int little = (int)*(unsigned char *)&one; - unsigned char *bytes = (unsigned char *)&value; - return _PyLong_FromByteArray(bytes, sizeof(unsigned short), - little, !is_unsigned); - } -} - -/* CIntToPy */ -static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value) { - const long neg_one = (long) ((long) 0 - (long) 1), const_zero = (long) 0; - const int is_unsigned = neg_one > const_zero; - if (is_unsigned) { - if (sizeof(long) < sizeof(long)) { - return PyInt_FromLong((long) value); - } else if (sizeof(long) <= sizeof(unsigned long)) { - return PyLong_FromUnsignedLong((unsigned long) value); -#ifdef HAVE_LONG_LONG - } else if (sizeof(long) <= sizeof(unsigned PY_LONG_LONG)) { - return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value); +static CYTHON_INLINE PyObject* __Pyx_PyInt_From_int(int value) { +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" #endif - } - } else { - if (sizeof(long) <= sizeof(long)) { - return PyInt_FromLong((long) value); -#ifdef HAVE_LONG_LONG - } else if (sizeof(long) <= sizeof(PY_LONG_LONG)) { - return PyLong_FromLongLong((PY_LONG_LONG) value); + const int neg_one = (int) -1, const_zero = (int) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic pop #endif - } - } - { - int one = 1; int little = (int)*(unsigned char *)&one; - unsigned char *bytes = (unsigned char *)&value; - return _PyLong_FromByteArray(bytes, sizeof(long), - little, !is_unsigned); - } -} - -/* CIntToPy */ -static CYTHON_INLINE PyObject* __Pyx_PyInt_From_uint16_t(uint16_t value) { - const uint16_t neg_one = (uint16_t) ((uint16_t) 0 - (uint16_t) 1), const_zero = (uint16_t) 0; const int is_unsigned = neg_one > const_zero; if (is_unsigned) { - if (sizeof(uint16_t) < sizeof(long)) { + if (sizeof(int) < sizeof(long)) { return PyInt_FromLong((long) value); - } else if (sizeof(uint16_t) <= sizeof(unsigned long)) { + } else if (sizeof(int) <= sizeof(unsigned long)) { return PyLong_FromUnsignedLong((unsigned long) value); #ifdef HAVE_LONG_LONG - } else if (sizeof(uint16_t) <= sizeof(unsigned PY_LONG_LONG)) { + } else if (sizeof(int) <= sizeof(unsigned PY_LONG_LONG)) { return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value); #endif } } else { - if (sizeof(uint16_t) <= sizeof(long)) { + if (sizeof(int) <= sizeof(long)) { return PyInt_FromLong((long) value); #ifdef HAVE_LONG_LONG - } else if (sizeof(uint16_t) <= sizeof(PY_LONG_LONG)) { + } else if (sizeof(int) <= sizeof(PY_LONG_LONG)) { return PyLong_FromLongLong((PY_LONG_LONG) value); #endif } @@ -22386,14 +22180,21 @@ static CYTHON_INLINE PyObject* __Pyx_PyInt_From_uint16_t(uint16_t value) { { int one = 1; int little = (int)*(unsigned char *)&one; unsigned char *bytes = (unsigned char *)&value; - return _PyLong_FromByteArray(bytes, sizeof(uint16_t), + return _PyLong_FromByteArray(bytes, sizeof(int), little, !is_unsigned); } } /* CIntFromPy */ static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *x) { - const int neg_one = (int) ((int) 0 - (int) 1), const_zero = (int) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +#endif + const int neg_one = (int) -1, const_zero = (int) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic pop +#endif const int is_unsigned = neg_one > const_zero; #if PY_MAJOR_VERSION < 3 if (likely(PyInt_Check(x))) { @@ -22581,19 +22382,26 @@ static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *x) { } /* CIntFromPy */ -static CYTHON_INLINE enum http_method __Pyx_PyInt_As_enum__http_method(PyObject *x) { - const enum http_method neg_one = (enum http_method) ((enum http_method) 0 - (enum http_method) 1), const_zero = (enum http_method) 0; +static CYTHON_INLINE enum llhttp_method __Pyx_PyInt_As_enum__llhttp_method(PyObject *x) { +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +#endif + const enum llhttp_method neg_one = (enum llhttp_method) -1, const_zero = (enum llhttp_method) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic pop +#endif const int is_unsigned = neg_one > const_zero; #if PY_MAJOR_VERSION < 3 if (likely(PyInt_Check(x))) { - if (sizeof(enum http_method) < sizeof(long)) { - __PYX_VERIFY_RETURN_INT(enum http_method, long, PyInt_AS_LONG(x)) + if (sizeof(enum llhttp_method) < sizeof(long)) { + __PYX_VERIFY_RETURN_INT(enum llhttp_method, long, PyInt_AS_LONG(x)) } else { long val = PyInt_AS_LONG(x); if (is_unsigned && unlikely(val < 0)) { goto raise_neg_overflow; } - return (enum http_method) val; + return (enum llhttp_method) val; } } else #endif @@ -22602,32 +22410,32 @@ static CYTHON_INLINE enum http_method __Pyx_PyInt_As_enum__http_method(PyObject #if CYTHON_USE_PYLONG_INTERNALS const digit* digits = ((PyLongObject*)x)->ob_digit; switch (Py_SIZE(x)) { - case 0: return (enum http_method) 0; - case 1: __PYX_VERIFY_RETURN_INT(enum http_method, digit, digits[0]) + case 0: return (enum llhttp_method) 0; + case 1: __PYX_VERIFY_RETURN_INT(enum llhttp_method, digit, digits[0]) case 2: - if (8 * sizeof(enum http_method) > 1 * PyLong_SHIFT) { + if (8 * sizeof(enum llhttp_method) > 1 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(enum http_method, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(enum http_method) >= 2 * PyLong_SHIFT) { - return (enum http_method) (((((enum http_method)digits[1]) << PyLong_SHIFT) | (enum http_method)digits[0])); + __PYX_VERIFY_RETURN_INT(enum llhttp_method, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(enum llhttp_method) >= 2 * PyLong_SHIFT) { + return (enum llhttp_method) (((((enum llhttp_method)digits[1]) << PyLong_SHIFT) | (enum llhttp_method)digits[0])); } } break; case 3: - if (8 * sizeof(enum http_method) > 2 * PyLong_SHIFT) { + if (8 * sizeof(enum llhttp_method) > 2 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(enum http_method, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(enum http_method) >= 3 * PyLong_SHIFT) { - return (enum http_method) (((((((enum http_method)digits[2]) << PyLong_SHIFT) | (enum http_method)digits[1]) << PyLong_SHIFT) | (enum http_method)digits[0])); + __PYX_VERIFY_RETURN_INT(enum llhttp_method, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(enum llhttp_method) >= 3 * PyLong_SHIFT) { + return (enum llhttp_method) (((((((enum llhttp_method)digits[2]) << PyLong_SHIFT) | (enum llhttp_method)digits[1]) << PyLong_SHIFT) | (enum llhttp_method)digits[0])); } } break; case 4: - if (8 * sizeof(enum http_method) > 3 * PyLong_SHIFT) { + if (8 * sizeof(enum llhttp_method) > 3 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(enum http_method, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(enum http_method) >= 4 * PyLong_SHIFT) { - return (enum http_method) (((((((((enum http_method)digits[3]) << PyLong_SHIFT) | (enum http_method)digits[2]) << PyLong_SHIFT) | (enum http_method)digits[1]) << PyLong_SHIFT) | (enum http_method)digits[0])); + __PYX_VERIFY_RETURN_INT(enum llhttp_method, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(enum llhttp_method) >= 4 * PyLong_SHIFT) { + return (enum llhttp_method) (((((((((enum llhttp_method)digits[3]) << PyLong_SHIFT) | (enum llhttp_method)digits[2]) << PyLong_SHIFT) | (enum llhttp_method)digits[1]) << PyLong_SHIFT) | (enum llhttp_method)digits[0])); } } break; @@ -22641,86 +22449,86 @@ static CYTHON_INLINE enum http_method __Pyx_PyInt_As_enum__http_method(PyObject { int result = PyObject_RichCompareBool(x, Py_False, Py_LT); if (unlikely(result < 0)) - return (enum http_method) -1; + return (enum llhttp_method) -1; if (unlikely(result == 1)) goto raise_neg_overflow; } #endif - if (sizeof(enum http_method) <= sizeof(unsigned long)) { - __PYX_VERIFY_RETURN_INT_EXC(enum http_method, unsigned long, PyLong_AsUnsignedLong(x)) + if (sizeof(enum llhttp_method) <= sizeof(unsigned long)) { + __PYX_VERIFY_RETURN_INT_EXC(enum llhttp_method, unsigned long, PyLong_AsUnsignedLong(x)) #ifdef HAVE_LONG_LONG - } else if (sizeof(enum http_method) <= sizeof(unsigned PY_LONG_LONG)) { - __PYX_VERIFY_RETURN_INT_EXC(enum http_method, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x)) + } else if (sizeof(enum llhttp_method) <= sizeof(unsigned PY_LONG_LONG)) { + __PYX_VERIFY_RETURN_INT_EXC(enum llhttp_method, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x)) #endif } } else { #if CYTHON_USE_PYLONG_INTERNALS const digit* digits = ((PyLongObject*)x)->ob_digit; switch (Py_SIZE(x)) { - case 0: return (enum http_method) 0; - case -1: __PYX_VERIFY_RETURN_INT(enum http_method, sdigit, (sdigit) (-(sdigit)digits[0])) - case 1: __PYX_VERIFY_RETURN_INT(enum http_method, digit, +digits[0]) + case 0: return (enum llhttp_method) 0; + case -1: __PYX_VERIFY_RETURN_INT(enum llhttp_method, sdigit, (sdigit) (-(sdigit)digits[0])) + case 1: __PYX_VERIFY_RETURN_INT(enum llhttp_method, digit, +digits[0]) case -2: - if (8 * sizeof(enum http_method) - 1 > 1 * PyLong_SHIFT) { + if (8 * sizeof(enum llhttp_method) - 1 > 1 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(enum http_method, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(enum http_method) - 1 > 2 * PyLong_SHIFT) { - return (enum http_method) (((enum http_method)-1)*(((((enum http_method)digits[1]) << PyLong_SHIFT) | (enum http_method)digits[0]))); + __PYX_VERIFY_RETURN_INT(enum llhttp_method, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(enum llhttp_method) - 1 > 2 * PyLong_SHIFT) { + return (enum llhttp_method) (((enum llhttp_method)-1)*(((((enum llhttp_method)digits[1]) << PyLong_SHIFT) | (enum llhttp_method)digits[0]))); } } break; case 2: - if (8 * sizeof(enum http_method) > 1 * PyLong_SHIFT) { + if (8 * sizeof(enum llhttp_method) > 1 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(enum http_method, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(enum http_method) - 1 > 2 * PyLong_SHIFT) { - return (enum http_method) ((((((enum http_method)digits[1]) << PyLong_SHIFT) | (enum http_method)digits[0]))); + __PYX_VERIFY_RETURN_INT(enum llhttp_method, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(enum llhttp_method) - 1 > 2 * PyLong_SHIFT) { + return (enum llhttp_method) ((((((enum llhttp_method)digits[1]) << PyLong_SHIFT) | (enum llhttp_method)digits[0]))); } } break; case -3: - if (8 * sizeof(enum http_method) - 1 > 2 * PyLong_SHIFT) { + if (8 * sizeof(enum llhttp_method) - 1 > 2 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(enum http_method, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(enum http_method) - 1 > 3 * PyLong_SHIFT) { - return (enum http_method) (((enum http_method)-1)*(((((((enum http_method)digits[2]) << PyLong_SHIFT) | (enum http_method)digits[1]) << PyLong_SHIFT) | (enum http_method)digits[0]))); + __PYX_VERIFY_RETURN_INT(enum llhttp_method, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(enum llhttp_method) - 1 > 3 * PyLong_SHIFT) { + return (enum llhttp_method) (((enum llhttp_method)-1)*(((((((enum llhttp_method)digits[2]) << PyLong_SHIFT) | (enum llhttp_method)digits[1]) << PyLong_SHIFT) | (enum llhttp_method)digits[0]))); } } break; case 3: - if (8 * sizeof(enum http_method) > 2 * PyLong_SHIFT) { + if (8 * sizeof(enum llhttp_method) > 2 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(enum http_method, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(enum http_method) - 1 > 3 * PyLong_SHIFT) { - return (enum http_method) ((((((((enum http_method)digits[2]) << PyLong_SHIFT) | (enum http_method)digits[1]) << PyLong_SHIFT) | (enum http_method)digits[0]))); + __PYX_VERIFY_RETURN_INT(enum llhttp_method, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(enum llhttp_method) - 1 > 3 * PyLong_SHIFT) { + return (enum llhttp_method) ((((((((enum llhttp_method)digits[2]) << PyLong_SHIFT) | (enum llhttp_method)digits[1]) << PyLong_SHIFT) | (enum llhttp_method)digits[0]))); } } break; case -4: - if (8 * sizeof(enum http_method) - 1 > 3 * PyLong_SHIFT) { + if (8 * sizeof(enum llhttp_method) - 1 > 3 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(enum http_method, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(enum http_method) - 1 > 4 * PyLong_SHIFT) { - return (enum http_method) (((enum http_method)-1)*(((((((((enum http_method)digits[3]) << PyLong_SHIFT) | (enum http_method)digits[2]) << PyLong_SHIFT) | (enum http_method)digits[1]) << PyLong_SHIFT) | (enum http_method)digits[0]))); + __PYX_VERIFY_RETURN_INT(enum llhttp_method, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(enum llhttp_method) - 1 > 4 * PyLong_SHIFT) { + return (enum llhttp_method) (((enum llhttp_method)-1)*(((((((((enum llhttp_method)digits[3]) << PyLong_SHIFT) | (enum llhttp_method)digits[2]) << PyLong_SHIFT) | (enum llhttp_method)digits[1]) << PyLong_SHIFT) | (enum llhttp_method)digits[0]))); } } break; case 4: - if (8 * sizeof(enum http_method) > 3 * PyLong_SHIFT) { + if (8 * sizeof(enum llhttp_method) > 3 * PyLong_SHIFT) { if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(enum http_method, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(enum http_method) - 1 > 4 * PyLong_SHIFT) { - return (enum http_method) ((((((((((enum http_method)digits[3]) << PyLong_SHIFT) | (enum http_method)digits[2]) << PyLong_SHIFT) | (enum http_method)digits[1]) << PyLong_SHIFT) | (enum http_method)digits[0]))); + __PYX_VERIFY_RETURN_INT(enum llhttp_method, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(enum llhttp_method) - 1 > 4 * PyLong_SHIFT) { + return (enum llhttp_method) ((((((((((enum llhttp_method)digits[3]) << PyLong_SHIFT) | (enum llhttp_method)digits[2]) << PyLong_SHIFT) | (enum llhttp_method)digits[1]) << PyLong_SHIFT) | (enum llhttp_method)digits[0]))); } } break; } #endif - if (sizeof(enum http_method) <= sizeof(long)) { - __PYX_VERIFY_RETURN_INT_EXC(enum http_method, long, PyLong_AsLong(x)) + if (sizeof(enum llhttp_method) <= sizeof(long)) { + __PYX_VERIFY_RETURN_INT_EXC(enum llhttp_method, long, PyLong_AsLong(x)) #ifdef HAVE_LONG_LONG - } else if (sizeof(enum http_method) <= sizeof(PY_LONG_LONG)) { - __PYX_VERIFY_RETURN_INT_EXC(enum http_method, PY_LONG_LONG, PyLong_AsLongLong(x)) + } else if (sizeof(enum llhttp_method) <= sizeof(PY_LONG_LONG)) { + __PYX_VERIFY_RETURN_INT_EXC(enum llhttp_method, PY_LONG_LONG, PyLong_AsLongLong(x)) #endif } } @@ -22729,7 +22537,7 @@ static CYTHON_INLINE enum http_method __Pyx_PyInt_As_enum__http_method(PyObject PyErr_SetString(PyExc_RuntimeError, "_PyLong_AsByteArray() not available in PyPy, cannot convert large numbers"); #else - enum http_method val; + enum llhttp_method val; PyObject *v = __Pyx_PyNumber_IntOrLong(x); #if PY_MAJOR_VERSION < 3 if (likely(v) && !PyLong_Check(v)) { @@ -22749,29 +22557,36 @@ static CYTHON_INLINE enum http_method __Pyx_PyInt_As_enum__http_method(PyObject return val; } #endif - return (enum http_method) -1; + return (enum llhttp_method) -1; } } else { - enum http_method val; + enum llhttp_method val; PyObject *tmp = __Pyx_PyNumber_IntOrLong(x); - if (!tmp) return (enum http_method) -1; - val = __Pyx_PyInt_As_enum__http_method(tmp); + if (!tmp) return (enum llhttp_method) -1; + val = __Pyx_PyInt_As_enum__llhttp_method(tmp); Py_DECREF(tmp); return val; } raise_overflow: PyErr_SetString(PyExc_OverflowError, - "value too large to convert to enum http_method"); - return (enum http_method) -1; + "value too large to convert to enum llhttp_method"); + return (enum llhttp_method) -1; raise_neg_overflow: PyErr_SetString(PyExc_OverflowError, - "can't convert negative value to enum http_method"); - return (enum http_method) -1; + "can't convert negative value to enum llhttp_method"); + return (enum llhttp_method) -1; } /* CIntFromPy */ static CYTHON_INLINE size_t __Pyx_PyInt_As_size_t(PyObject *x) { - const size_t neg_one = (size_t) ((size_t) 0 - (size_t) 1), const_zero = (size_t) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +#endif + const size_t neg_one = (size_t) -1, const_zero = (size_t) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic pop +#endif const int is_unsigned = neg_one > const_zero; #if PY_MAJOR_VERSION < 3 if (likely(PyInt_Check(x))) { @@ -22960,7 +22775,14 @@ static CYTHON_INLINE size_t __Pyx_PyInt_As_size_t(PyObject *x) { /* CIntFromPy */ static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *x) { - const long neg_one = (long) ((long) 0 - (long) 1), const_zero = (long) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +#endif + const long neg_one = (long) -1, const_zero = (long) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic pop +#endif const int is_unsigned = neg_one > const_zero; #if PY_MAJOR_VERSION < 3 if (likely(PyInt_Check(x))) { @@ -23147,6 +22969,82 @@ static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *x) { return (long) -1; } +/* CIntToPy */ +static CYTHON_INLINE PyObject* __Pyx_PyInt_From_uint8_t(uint8_t value) { +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +#endif + const uint8_t neg_one = (uint8_t) -1, const_zero = (uint8_t) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic pop +#endif + const int is_unsigned = neg_one > const_zero; + if (is_unsigned) { + if (sizeof(uint8_t) < sizeof(long)) { + return PyInt_FromLong((long) value); + } else if (sizeof(uint8_t) <= sizeof(unsigned long)) { + return PyLong_FromUnsignedLong((unsigned long) value); +#ifdef HAVE_LONG_LONG + } else if (sizeof(uint8_t) <= sizeof(unsigned PY_LONG_LONG)) { + return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value); +#endif + } + } else { + if (sizeof(uint8_t) <= sizeof(long)) { + return PyInt_FromLong((long) value); +#ifdef HAVE_LONG_LONG + } else if (sizeof(uint8_t) <= sizeof(PY_LONG_LONG)) { + return PyLong_FromLongLong((PY_LONG_LONG) value); +#endif + } + } + { + int one = 1; int little = (int)*(unsigned char *)&one; + unsigned char *bytes = (unsigned char *)&value; + return _PyLong_FromByteArray(bytes, sizeof(uint8_t), + little, !is_unsigned); + } +} + +/* CIntToPy */ +static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value) { +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +#endif + const long neg_one = (long) -1, const_zero = (long) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic pop +#endif + const int is_unsigned = neg_one > const_zero; + if (is_unsigned) { + if (sizeof(long) < sizeof(long)) { + return PyInt_FromLong((long) value); + } else if (sizeof(long) <= sizeof(unsigned long)) { + return PyLong_FromUnsignedLong((unsigned long) value); +#ifdef HAVE_LONG_LONG + } else if (sizeof(long) <= sizeof(unsigned PY_LONG_LONG)) { + return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value); +#endif + } + } else { + if (sizeof(long) <= sizeof(long)) { + return PyInt_FromLong((long) value); +#ifdef HAVE_LONG_LONG + } else if (sizeof(long) <= sizeof(PY_LONG_LONG)) { + return PyLong_FromLongLong((PY_LONG_LONG) value); +#endif + } + } + { + int one = 1; int little = (int)*(unsigned char *)&one; + unsigned char *bytes = (unsigned char *)&value; + return _PyLong_FromByteArray(bytes, sizeof(long), + little, !is_unsigned); + } +} + /* FastTypeChecks */ #if CYTHON_COMPILING_IN_CPYTHON static int __Pyx_InBases(PyTypeObject *a, PyTypeObject *b) { @@ -23403,6 +23301,12 @@ static PyObject* __Pyx_PyObject_CallMethod1(PyObject* obj, PyObject* method_name /* CoroutineBase */ #include #include +#if PY_VERSION_HEX >= 0x030b00a6 + #ifndef Py_BUILD_CORE + #define Py_BUILD_CORE 1 + #endif + #include "internal/pycore_frame.h" +#endif #define __Pyx_Coroutine_Undelegate(gen) Py_CLEAR((gen)->yieldfrom) static int __Pyx_PyGen__FetchStopIterationValue(CYTHON_UNUSED PyThreadState *__pyx_tstate, PyObject **pvalue) { PyObject *et, *ev, *tb; @@ -23574,9 +23478,13 @@ PyObject *__Pyx_Coroutine_SendEx(__pyx_CoroutineObject *self, PyObject *value, i if (exc_state->exc_traceback) { PyTracebackObject *tb = (PyTracebackObject *) exc_state->exc_traceback; PyFrameObject *f = tb->tb_frame; - Py_XINCREF(tstate->frame); assert(f->f_back == NULL); + #if PY_VERSION_HEX >= 0x030B00A1 + f->f_back = PyThreadState_GetFrame(tstate); + #else + Py_XINCREF(tstate->frame); f->f_back = tstate->frame; + #endif } #endif } @@ -23629,6 +23537,30 @@ PyObject *__Pyx_Coroutine_MethodReturn(CYTHON_UNUSED PyObject* gen, PyObject *re } return retval; } +#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x03030000 && (defined(__linux__) || PY_VERSION_HEX >= 0x030600B3) +static CYTHON_INLINE +PyObject *__Pyx_PyGen_Send(PyGenObject *gen, PyObject *arg) { +#if PY_VERSION_HEX <= 0x030A00A1 + return _PyGen_Send(gen, arg); +#else + PyObject *result; + if (PyIter_Send((PyObject*)gen, arg ? arg : Py_None, &result) == PYGEN_RETURN) { + if (PyAsyncGen_CheckExact(gen)) { + assert(result == Py_None); + PyErr_SetNone(PyExc_StopAsyncIteration); + } + else if (result == Py_None) { + PyErr_SetNone(PyExc_StopIteration); + } + else { + _PyGen_SetStopIterationValue(result); + } + Py_CLEAR(result); + } + return result; +#endif +} +#endif static CYTHON_INLINE PyObject *__Pyx_Coroutine_FinishDelegation(__pyx_CoroutineObject *gen) { PyObject *ret; @@ -23665,12 +23597,12 @@ static PyObject *__Pyx_Coroutine_Send(PyObject *self, PyObject *value) { #endif #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x03030000 && (defined(__linux__) || PY_VERSION_HEX >= 0x030600B3) if (PyGen_CheckExact(yf)) { - ret = _PyGen_Send((PyGenObject*)yf, value == Py_None ? NULL : value); + ret = __Pyx_PyGen_Send((PyGenObject*)yf, value == Py_None ? NULL : value); } else #endif #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x03050000 && defined(PyCoro_CheckExact) && (defined(__linux__) || PY_VERSION_HEX >= 0x030600B3) if (PyCoro_CheckExact(yf)) { - ret = _PyGen_Send((PyGenObject*)yf, value == Py_None ? NULL : value); + ret = __Pyx_PyGen_Send((PyGenObject*)yf, value == Py_None ? NULL : value); } else #endif { @@ -23754,7 +23686,7 @@ static PyObject *__Pyx_Generator_Next(PyObject *self) { #endif #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x03030000 && (defined(__linux__) || PY_VERSION_HEX >= 0x030600B3) if (PyGen_CheckExact(yf)) { - ret = _PyGen_Send((PyGenObject*)yf, NULL); + ret = __Pyx_PyGen_Send((PyGenObject*)yf, NULL); } else #endif #ifdef __Pyx_Coroutine_USED @@ -23914,6 +23846,7 @@ static int __Pyx_Coroutine_clear(PyObject *self) { } #endif Py_CLEAR(gen->gi_code); + Py_CLEAR(gen->gi_frame); Py_CLEAR(gen->gi_name); Py_CLEAR(gen->gi_qualname); Py_CLEAR(gen->gi_modulename); @@ -23930,7 +23863,7 @@ static void __Pyx_Coroutine_dealloc(PyObject *self) { if (PyObject_CallFinalizerFromDealloc(self)) #else Py_TYPE(gen)->tp_del(self); - if (self->ob_refcnt > 0) + if (Py_REFCNT(self) > 0) #endif { return; @@ -23957,7 +23890,7 @@ static void __Pyx_Coroutine_del(PyObject *self) { } #if !CYTHON_USE_TP_FINALIZE assert(self->ob_refcnt == 0); - self->ob_refcnt = 1; + __Pyx_SET_REFCNT(self, 1); #endif __Pyx_PyThreadState_assign __Pyx_ErrFetch(&error_type, &error_value, &error_traceback); @@ -24024,17 +23957,17 @@ static void __Pyx_Coroutine_del(PyObject *self) { } __Pyx_ErrRestore(error_type, error_value, error_traceback); #if !CYTHON_USE_TP_FINALIZE - assert(self->ob_refcnt > 0); + assert(Py_REFCNT(self) > 0); if (--self->ob_refcnt == 0) { return; } { - Py_ssize_t refcnt = self->ob_refcnt; + Py_ssize_t refcnt = Py_REFCNT(self); _Py_NewReference(self); - self->ob_refcnt = refcnt; + __Pyx_SET_REFCNT(self, refcnt); } #if CYTHON_COMPILING_IN_CPYTHON - assert(PyType_IS_GC(self->ob_type) && + assert(PyType_IS_GC(Py_TYPE(self)) && _Py_AS_GC(self)->gc.gc_refs != _PyGC_REFS_UNTRACKED); _Py_DEC_REFTOTAL; #endif @@ -24100,6 +24033,27 @@ __Pyx_Coroutine_set_qualname(__pyx_CoroutineObject *self, PyObject *value, CYTHO Py_XDECREF(tmp); return 0; } +static PyObject * +__Pyx_Coroutine_get_frame(__pyx_CoroutineObject *self, CYTHON_UNUSED void *context) +{ + PyObject *frame = self->gi_frame; + if (!frame) { + if (unlikely(!self->gi_code)) { + Py_RETURN_NONE; + } + frame = (PyObject *) PyFrame_New( + PyThreadState_Get(), /*PyThreadState *tstate,*/ + (PyCodeObject*) self->gi_code, /*PyCodeObject *code,*/ + __pyx_d, /*PyObject *globals,*/ + 0 /*PyObject *locals*/ + ); + if (unlikely(!frame)) + return NULL; + self->gi_frame = frame; + } + Py_INCREF(frame); + return frame; +} static __pyx_CoroutineObject *__Pyx__Coroutine_New( PyTypeObject* type, __pyx_coroutine_body_t body, PyObject *code, PyObject *closure, PyObject *name, PyObject *qualname, PyObject *module_name) { @@ -24133,6 +24087,7 @@ static __pyx_CoroutineObject *__Pyx__Coroutine_NewInit( gen->gi_modulename = module_name; Py_XINCREF(code); gen->gi_code = code; + gen->gi_frame = NULL; PyObject_GC_Track(gen); return gen; } @@ -24256,6 +24211,8 @@ static PyGetSetDef __pyx_Generator_getsets[] = { (char*) PyDoc_STR("name of the generator"), 0}, {(char *) "__qualname__", (getter)__Pyx_Coroutine_get_qualname, (setter)__Pyx_Coroutine_set_qualname, (char*) PyDoc_STR("qualified name of the generator"), 0}, + {(char *) "gi_frame", (getter)__Pyx_Coroutine_get_frame, NULL, + (char*) PyDoc_STR("Frame of the generator"), 0}, {0, 0, 0, 0, 0} }; static PyTypeObject __pyx_GeneratorType_type = { @@ -24315,12 +24272,15 @@ static PyTypeObject __pyx_GeneratorType_type = { #elif PY_VERSION_HEX >= 0x030400a1 0, #endif -#if PY_VERSION_HEX >= 0x030800b1 +#if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800) 0, #endif #if PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x03090000 0, #endif +#if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 + 0, +#endif }; static int __pyx_Generator_init(void) { __pyx_GeneratorType_type.tp_getattro = __Pyx_PyObject_GenericGetAttrNoDict; @@ -24334,11 +24294,33 @@ static int __pyx_Generator_init(void) { /* CheckBinaryVersion */ static int __Pyx_check_binary_version(void) { - char ctversion[4], rtversion[4]; - PyOS_snprintf(ctversion, 4, "%d.%d", PY_MAJOR_VERSION, PY_MINOR_VERSION); - PyOS_snprintf(rtversion, 4, "%s", Py_GetVersion()); - if (ctversion[0] != rtversion[0] || ctversion[2] != rtversion[2]) { + char ctversion[5]; + int same=1, i, found_dot; + const char* rt_from_call = Py_GetVersion(); + PyOS_snprintf(ctversion, 5, "%d.%d", PY_MAJOR_VERSION, PY_MINOR_VERSION); + found_dot = 0; + for (i = 0; i < 4; i++) { + if (!ctversion[i]) { + same = (rt_from_call[i] < '0' || rt_from_call[i] > '9'); + break; + } + if (rt_from_call[i] != ctversion[i]) { + same = 0; + break; + } + } + if (!same) { + char rtversion[5] = {'\0'}; char message[200]; + for (i=0; i<4; ++i) { + if (rt_from_call[i] == '.') { + if (found_dot) break; + found_dot = 1; + } else if (rt_from_call[i] < '0' || rt_from_call[i] > '9') { + break; + } + rtversion[i] = rt_from_call[i]; + } PyOS_snprintf(message, sizeof(message), "compiletime version %s of module '%.100s' " "does not match runtime version %s", @@ -24596,6 +24578,23 @@ static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) { Py_DECREF(x); return ival; } +static CYTHON_INLINE Py_hash_t __Pyx_PyIndex_AsHash_t(PyObject* o) { + if (sizeof(Py_hash_t) == sizeof(Py_ssize_t)) { + return (Py_hash_t) __Pyx_PyIndex_AsSsize_t(o); +#if PY_MAJOR_VERSION < 3 + } else if (likely(PyInt_CheckExact(o))) { + return PyInt_AS_LONG(o); +#endif + } else { + Py_ssize_t ival; + PyObject *x; + x = PyNumber_Index(o); + if (!x) return -1; + ival = PyInt_AsLong(x); + Py_DECREF(x); + return ival; + } +} static CYTHON_INLINE PyObject * __Pyx_PyBool_FromLong(long b) { return b ? __Pyx_NewRef(Py_True) : __Pyx_NewRef(Py_False); } diff --git a/aiohttp/_http_parser.pyx b/aiohttp/_http_parser.pyx index c24e310..3f28fbd 100644 --- a/aiohttp/_http_parser.pyx +++ b/aiohttp/_http_parser.pyx @@ -2,7 +2,6 @@ # # Based on https://github.com/MagicStack/httptools # -from __future__ import absolute_import, print_function from cpython cimport ( Py_buffer, @@ -20,6 +19,7 @@ from multidict import CIMultiDict as _CIMultiDict, CIMultiDictProxy as _CIMultiD from yarl import URL as _URL from aiohttp import hdrs +from aiohttp.helpers import DEBUG from .http_exceptions import ( BadHttpMessage, @@ -80,13 +80,13 @@ cdef inline object extend(object buf, const char* at, size_t length): memcpy(ptr + s, at, length) -DEF METHODS_COUNT = 34; +DEF METHODS_COUNT = 46; cdef list _http_method = [] for i in range(METHODS_COUNT): _http_method.append( - cparser.http_method_str( i).decode('ascii')) + cparser.llhttp_method_name( i).decode('ascii')) cdef inline str http_method_str(int i): @@ -272,8 +272,8 @@ cdef _new_response_message(object version, cdef class HttpParser: cdef: - cparser.http_parser* _cparser - cparser.http_parser_settings* _csettings + cparser.llhttp_t* _cparser + cparser.llhttp_settings_t* _csettings bytearray _raw_name bytearray _raw_value @@ -310,13 +310,13 @@ cdef class HttpParser: Py_buffer py_buf def __cinit__(self): - self._cparser = \ - PyMem_Malloc(sizeof(cparser.http_parser)) + self._cparser = \ + PyMem_Malloc(sizeof(cparser.llhttp_t)) if self._cparser is NULL: raise MemoryError() - self._csettings = \ - PyMem_Malloc(sizeof(cparser.http_parser_settings)) + self._csettings = \ + PyMem_Malloc(sizeof(cparser.llhttp_settings_t)) if self._csettings is NULL: raise MemoryError() @@ -324,19 +324,20 @@ cdef class HttpParser: PyMem_Free(self._cparser) PyMem_Free(self._csettings) - cdef _init(self, cparser.http_parser_type mode, - object protocol, object loop, int limit, - object timer=None, - size_t max_line_size=8190, size_t max_headers=32768, - size_t max_field_size=8190, payload_exception=None, - bint response_with_body=True, bint read_until_eof=False, - bint auto_decompress=True): - cparser.http_parser_init(self._cparser, mode) + cdef _init( + self, cparser.llhttp_type mode, + object protocol, object loop, int limit, + object timer=None, + size_t max_line_size=8190, size_t max_headers=32768, + size_t max_field_size=8190, payload_exception=None, + bint response_with_body=True, bint read_until_eof=False, + bint auto_decompress=True, + ): + cparser.llhttp_settings_init(self._csettings) + cparser.llhttp_init(self._cparser, mode, self._csettings) self._cparser.data = self self._cparser.content_length = 0 - cparser.http_parser_settings_init(self._csettings) - self._protocol = protocol self._loop = loop self._timer = timer @@ -417,14 +418,14 @@ cdef class HttpParser: self._process_header() method = http_method_str(self._cparser.method) - should_close = not cparser.http_should_keep_alive(self._cparser) + should_close = not cparser.llhttp_should_keep_alive(self._cparser) upgrade = self._cparser.upgrade chunked = self._cparser.flags & cparser.F_CHUNKED raw_headers = tuple(self._raw_headers) headers = CIMultiDictProxy(self._headers) - if upgrade or self._cparser.method == 5: # cparser.CONNECT: + if upgrade or self._cparser.method == cparser.HTTP_CONNECT: self._upgraded = True # do not support old websocket spec @@ -450,11 +451,12 @@ cdef class HttpParser: headers, raw_headers, should_close, encoding, upgrade, chunked) - if (ULLONG_MAX > self._cparser.content_length > 0 or chunked or - self._cparser.method == 5 or # CONNECT: 5 - (self._cparser.status_code >= 199 and - self._cparser.content_length == ULLONG_MAX and - self._read_until_eof) + if ( + ULLONG_MAX > self._cparser.content_length > 0 or chunked or + self._cparser.method == cparser.HTTP_CONNECT or + (self._cparser.status_code >= 199 and + self._cparser.content_length == 0 and + self._read_until_eof) ): payload = StreamReader( self._protocol, timer=self._timer, loop=self._loop, @@ -485,7 +487,7 @@ cdef class HttpParser: pass cdef inline http_version(self): - cdef cparser.http_parser* parser = self._cparser + cdef cparser.llhttp_t* parser = self._cparser if parser.http_major == 1: if parser.http_minor == 0: @@ -504,12 +506,11 @@ cdef class HttpParser: if self._cparser.flags & cparser.F_CHUNKED: raise TransferEncodingError( "Not enough data for satisfy transfer length header.") - elif self._cparser.flags & cparser.F_CONTENTLENGTH: + elif self._cparser.flags & cparser.F_CONTENT_LENGTH: raise ContentLengthError( "Not enough data for satisfy content length header.") - elif self._cparser.http_errno != cparser.HPE_OK: - desc = cparser.http_errno_description( - self._cparser.http_errno) + elif cparser.llhttp_get_errno(self._cparser) != cparser.HPE_OK: + desc = cparser.llhttp_get_error_reason(self._cparser) raise PayloadEncodingError(desc.decode('latin-1')) else: self._payload.feed_eof() @@ -522,26 +523,36 @@ cdef class HttpParser: cdef: size_t data_len size_t nb + cdef cparser.llhttp_errno_t errno PyObject_GetBuffer(data, &self.py_buf, PyBUF_SIMPLE) data_len = self.py_buf.len - nb = cparser.http_parser_execute( + errno = cparser.llhttp_execute( self._cparser, - self._csettings, self.py_buf.buf, data_len) + if errno is cparser.HPE_PAUSED_UPGRADE: + cparser.llhttp_resume_after_upgrade(self._cparser) + + nb = cparser.llhttp_get_error_pos(self._cparser) - self.py_buf.buf + PyBuffer_Release(&self.py_buf) - if (self._cparser.http_errno != cparser.HPE_OK): + if errno not in (cparser.HPE_OK, cparser.HPE_PAUSED_UPGRADE): if self._payload_error == 0: if self._last_error is not None: ex = self._last_error self._last_error = None else: - ex = parser_error_from_errno( - self._cparser.http_errno) + after = cparser.llhttp_get_error_pos(self._cparser) + before = data[:after - self.py_buf.buf] + after_b = after.split(b"\r\n", 1)[0] + before = before.rsplit(b"\r\n", 1)[-1] + data = before + after_b + pointer = " " * (len(repr(before))-1) + "^" + ex = parser_error_from_errno(self._cparser, data, pointer) self._payload = None raise ex @@ -562,44 +573,86 @@ cdef class HttpParser: cdef class HttpRequestParser(HttpParser): - def __init__(self, protocol, loop, int limit, timer=None, - size_t max_line_size=8190, size_t max_headers=32768, - size_t max_field_size=8190, payload_exception=None, - bint response_with_body=True, bint read_until_eof=False, + def __init__( + self, protocol, loop, int limit, timer=None, + size_t max_line_size=8190, size_t max_headers=32768, + size_t max_field_size=8190, payload_exception=None, + bint response_with_body=True, bint read_until_eof=False, + bint auto_decompress=True, ): - self._init(cparser.HTTP_REQUEST, protocol, loop, limit, timer, - max_line_size, max_headers, max_field_size, - payload_exception, response_with_body, read_until_eof) + self._init(cparser.HTTP_REQUEST, protocol, loop, limit, timer, + max_line_size, max_headers, max_field_size, + payload_exception, response_with_body, read_until_eof, + auto_decompress) cdef object _on_status_complete(self): - cdef Py_buffer py_buf - if not self._buf: - return - self._path = self._buf.decode('utf-8', 'surrogateescape') - if self._cparser.method == 5: # CONNECT - self._url = URL(self._path) - else: - PyObject_GetBuffer(self._buf, &py_buf, PyBUF_SIMPLE) - try: - self._url = _parse_url(py_buf.buf, - py_buf.len) - finally: - PyBuffer_Release(&py_buf) - PyByteArray_Resize(self._buf, 0) + cdef int idx1, idx2 + if not self._buf: + return + self._path = self._buf.decode('utf-8', 'surrogateescape') + try: + idx3 = len(self._path) + if self._cparser.method == cparser.HTTP_CONNECT: + # authority-form, + # https://datatracker.ietf.org/doc/html/rfc7230#section-5.3.3 + self._url = URL.build(authority=self._path, encoded=True) + elif idx3 > 1 and self._path[0] == '/': + # origin-form, + # https://datatracker.ietf.org/doc/html/rfc7230#section-5.3.1 + idx1 = self._path.find("?") + if idx1 == -1: + query = "" + idx2 = self._path.find("#") + if idx2 == -1: + path = self._path + fragment = "" + else: + path = self._path[0: idx2] + fragment = self._path[idx2+1:] + + else: + path = self._path[0:idx1] + idx1 += 1 + idx2 = self._path.find("#", idx1+1) + if idx2 == -1: + query = self._path[idx1:] + fragment = "" + else: + query = self._path[idx1: idx2] + fragment = self._path[idx2+1:] + + self._url = URL.build( + path=path, + query_string=query, + fragment=fragment, + encoded=True, + ) + else: + # absolute-form for proxy maybe, + # https://datatracker.ietf.org/doc/html/rfc7230#section-5.3.2 + self._url = URL(self._path, encoded=True) + finally: + PyByteArray_Resize(self._buf, 0) cdef class HttpResponseParser(HttpParser): - def __init__(self, protocol, loop, int limit, timer=None, - size_t max_line_size=8190, size_t max_headers=32768, - size_t max_field_size=8190, payload_exception=None, - bint response_with_body=True, bint read_until_eof=False, - bint auto_decompress=True + def __init__( + self, protocol, loop, int limit, timer=None, + size_t max_line_size=8190, size_t max_headers=32768, + size_t max_field_size=8190, payload_exception=None, + bint response_with_body=True, bint read_until_eof=False, + bint auto_decompress=True ): self._init(cparser.HTTP_RESPONSE, protocol, loop, limit, timer, max_line_size, max_headers, max_field_size, payload_exception, response_with_body, read_until_eof, auto_decompress) + # Use strict parsing on dev mode, so users are warned about broken servers. + if not DEBUG: + cparser.llhttp_set_lenient_headers(self._cparser, 1) + cparser.llhttp_set_lenient_optional_cr_before_lf(self._cparser, 1) + cparser.llhttp_set_lenient_spaces_after_chunk_size(self._cparser, 1) cdef object _on_status_complete(self): if self._buf: @@ -608,7 +661,7 @@ cdef class HttpResponseParser(HttpParser): else: self._reason = self._reason or '' -cdef int cb_on_message_begin(cparser.http_parser* parser) except -1: +cdef int cb_on_message_begin(cparser.llhttp_t* parser) except -1: cdef HttpParser pyparser = parser.data pyparser._started = True @@ -620,7 +673,7 @@ cdef int cb_on_message_begin(cparser.http_parser* parser) except -1: return 0 -cdef int cb_on_url(cparser.http_parser* parser, +cdef int cb_on_url(cparser.llhttp_t* parser, const char *at, size_t length) except -1: cdef HttpParser pyparser = parser.data try: @@ -635,7 +688,7 @@ cdef int cb_on_url(cparser.http_parser* parser, return 0 -cdef int cb_on_status(cparser.http_parser* parser, +cdef int cb_on_status(cparser.llhttp_t* parser, const char *at, size_t length) except -1: cdef HttpParser pyparser = parser.data cdef str reason @@ -651,7 +704,7 @@ cdef int cb_on_status(cparser.http_parser* parser, return 0 -cdef int cb_on_header_field(cparser.http_parser* parser, +cdef int cb_on_header_field(cparser.llhttp_t* parser, const char *at, size_t length) except -1: cdef HttpParser pyparser = parser.data cdef Py_ssize_t size @@ -669,7 +722,7 @@ cdef int cb_on_header_field(cparser.http_parser* parser, return 0 -cdef int cb_on_header_value(cparser.http_parser* parser, +cdef int cb_on_header_value(cparser.llhttp_t* parser, const char *at, size_t length) except -1: cdef HttpParser pyparser = parser.data cdef Py_ssize_t size @@ -686,7 +739,7 @@ cdef int cb_on_header_value(cparser.http_parser* parser, return 0 -cdef int cb_on_headers_complete(cparser.http_parser* parser) except -1: +cdef int cb_on_headers_complete(cparser.llhttp_t* parser) except -1: cdef HttpParser pyparser = parser.data try: pyparser._on_status_complete() @@ -695,13 +748,16 @@ cdef int cb_on_headers_complete(cparser.http_parser* parser) except -1: pyparser._last_error = exc return -1 else: - if pyparser._cparser.upgrade or pyparser._cparser.method == 5: # CONNECT + if ( + pyparser._cparser.upgrade or + pyparser._cparser.method == cparser.HTTP_CONNECT + ): return 2 else: return 0 -cdef int cb_on_body(cparser.http_parser* parser, +cdef int cb_on_body(cparser.llhttp_t* parser, const char *at, size_t length) except -1: cdef HttpParser pyparser = parser.data cdef bytes body = at[:length] @@ -718,7 +774,7 @@ cdef int cb_on_body(cparser.http_parser* parser, return 0 -cdef int cb_on_message_complete(cparser.http_parser* parser) except -1: +cdef int cb_on_message_complete(cparser.llhttp_t* parser) except -1: cdef HttpParser pyparser = parser.data try: pyparser._started = False @@ -730,7 +786,7 @@ cdef int cb_on_message_complete(cparser.http_parser* parser) except -1: return 0 -cdef int cb_on_chunk_header(cparser.http_parser* parser) except -1: +cdef int cb_on_chunk_header(cparser.llhttp_t* parser) except -1: cdef HttpParser pyparser = parser.data try: pyparser._on_chunk_header() @@ -741,7 +797,7 @@ cdef int cb_on_chunk_header(cparser.http_parser* parser) except -1: return 0 -cdef int cb_on_chunk_complete(cparser.http_parser* parser) except -1: +cdef int cb_on_chunk_complete(cparser.llhttp_t* parser) except -1: cdef HttpParser pyparser = parser.data try: pyparser._on_chunk_complete() @@ -752,124 +808,29 @@ cdef int cb_on_chunk_complete(cparser.http_parser* parser) except -1: return 0 -cdef parser_error_from_errno(cparser.http_errno errno): - cdef bytes desc = cparser.http_errno_description(errno) - - if errno in (cparser.HPE_CB_message_begin, - cparser.HPE_CB_url, - cparser.HPE_CB_header_field, - cparser.HPE_CB_header_value, - cparser.HPE_CB_headers_complete, - cparser.HPE_CB_body, - cparser.HPE_CB_message_complete, - cparser.HPE_CB_status, - cparser.HPE_CB_chunk_header, - cparser.HPE_CB_chunk_complete): - cls = BadHttpMessage - - elif errno == cparser.HPE_INVALID_STATUS: - cls = BadStatusLine - - elif errno == cparser.HPE_INVALID_METHOD: - cls = BadStatusLine - +cdef parser_error_from_errno(cparser.llhttp_t* parser, data, pointer): + cdef cparser.llhttp_errno_t errno = cparser.llhttp_get_errno(parser) + cdef bytes desc = cparser.llhttp_get_error_reason(parser) + + err_msg = "{}:\n\n {!r}\n {}".format(desc.decode("latin-1"), data, pointer) + + if errno in {cparser.HPE_CB_MESSAGE_BEGIN, + cparser.HPE_CB_HEADERS_COMPLETE, + cparser.HPE_CB_MESSAGE_COMPLETE, + cparser.HPE_CB_CHUNK_HEADER, + cparser.HPE_CB_CHUNK_COMPLETE, + cparser.HPE_INVALID_CONSTANT, + cparser.HPE_INVALID_HEADER_TOKEN, + cparser.HPE_INVALID_CONTENT_LENGTH, + cparser.HPE_INVALID_CHUNK_SIZE, + cparser.HPE_INVALID_EOF_STATE, + cparser.HPE_INVALID_TRANSFER_ENCODING}: + return BadHttpMessage(err_msg) + elif errno in {cparser.HPE_INVALID_STATUS, + cparser.HPE_INVALID_METHOD, + cparser.HPE_INVALID_VERSION}: + return BadStatusLine(error=err_msg) elif errno == cparser.HPE_INVALID_URL: - cls = InvalidURLError + return InvalidURLError(err_msg) - else: - cls = BadHttpMessage - - return cls(desc.decode('latin-1')) - - -def parse_url(url): - cdef: - Py_buffer py_buf - char* buf_data - - PyObject_GetBuffer(url, &py_buf, PyBUF_SIMPLE) - try: - buf_data = py_buf.buf - return _parse_url(buf_data, py_buf.len) - finally: - PyBuffer_Release(&py_buf) - - -cdef _parse_url(char* buf_data, size_t length): - cdef: - cparser.http_parser_url* parsed - int res - str schema = None - str host = None - object port = None - str path = None - str query = None - str fragment = None - str user = None - str password = None - str userinfo = None - object result = None - int off - int ln - - parsed = \ - PyMem_Malloc(sizeof(cparser.http_parser_url)) - if parsed is NULL: - raise MemoryError() - cparser.http_parser_url_init(parsed) - try: - res = cparser.http_parser_parse_url(buf_data, length, 0, parsed) - - if res == 0: - if parsed.field_set & (1 << cparser.UF_SCHEMA): - off = parsed.field_data[cparser.UF_SCHEMA].off - ln = parsed.field_data[cparser.UF_SCHEMA].len - schema = buf_data[off:off+ln].decode('utf-8', 'surrogateescape') - else: - schema = '' - - if parsed.field_set & (1 << cparser.UF_HOST): - off = parsed.field_data[cparser.UF_HOST].off - ln = parsed.field_data[cparser.UF_HOST].len - host = buf_data[off:off+ln].decode('utf-8', 'surrogateescape') - else: - host = '' - - if parsed.field_set & (1 << cparser.UF_PORT): - port = parsed.port - - if parsed.field_set & (1 << cparser.UF_PATH): - off = parsed.field_data[cparser.UF_PATH].off - ln = parsed.field_data[cparser.UF_PATH].len - path = buf_data[off:off+ln].decode('utf-8', 'surrogateescape') - else: - path = '' - - if parsed.field_set & (1 << cparser.UF_QUERY): - off = parsed.field_data[cparser.UF_QUERY].off - ln = parsed.field_data[cparser.UF_QUERY].len - query = buf_data[off:off+ln].decode('utf-8', 'surrogateescape') - else: - query = '' - - if parsed.field_set & (1 << cparser.UF_FRAGMENT): - off = parsed.field_data[cparser.UF_FRAGMENT].off - ln = parsed.field_data[cparser.UF_FRAGMENT].len - fragment = buf_data[off:off+ln].decode('utf-8', 'surrogateescape') - else: - fragment = '' - - if parsed.field_set & (1 << cparser.UF_USERINFO): - off = parsed.field_data[cparser.UF_USERINFO].off - ln = parsed.field_data[cparser.UF_USERINFO].len - userinfo = buf_data[off:off+ln].decode('utf-8', 'surrogateescape') - - user, sep, password = userinfo.partition(':') - - return URL_build(scheme=schema, - user=user, password=password, host=host, port=port, - path=path, query_string=query, fragment=fragment, encoded=True) - else: - raise InvalidURLError("invalid url {!r}".format(buf_data)) - finally: - PyMem_Free(parsed) + return BadHttpMessage(err_msg) diff --git a/aiohttp/_http_writer.c b/aiohttp/_http_writer.c index 09e3efa..42c099a 100644 --- a/aiohttp/_http_writer.c +++ b/aiohttp/_http_writer.c @@ -1,14 +1,16 @@ -/* Generated by Cython 0.29.21 */ +/* Generated by Cython 0.29.32 */ +#ifndef PY_SSIZE_T_CLEAN #define PY_SSIZE_T_CLEAN +#endif /* PY_SSIZE_T_CLEAN */ #include "Python.h" #ifndef Py_PYTHON_H #error Python headers needed to compile C extensions, please install development version of Python. #elif PY_VERSION_HEX < 0x02060000 || (0x03000000 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x03030000) #error Cython requires Python 2.6+ or Python 3.3+. #else -#define CYTHON_ABI "0_29_21" -#define CYTHON_HEX_VERSION 0x001D15F0 +#define CYTHON_ABI "0_29_32" +#define CYTHON_HEX_VERSION 0x001D20F0 #define CYTHON_FUTURE_DIVISION 1 #include #ifndef offsetof @@ -47,6 +49,7 @@ #define CYTHON_COMPILING_IN_PYPY 1 #define CYTHON_COMPILING_IN_PYSTON 0 #define CYTHON_COMPILING_IN_CPYTHON 0 + #define CYTHON_COMPILING_IN_NOGIL 0 #undef CYTHON_USE_TYPE_SLOTS #define CYTHON_USE_TYPE_SLOTS 0 #undef CYTHON_USE_PYTYPE_LOOKUP @@ -83,10 +86,14 @@ #define CYTHON_USE_DICT_VERSIONS 0 #undef CYTHON_USE_EXC_INFO_STACK #define CYTHON_USE_EXC_INFO_STACK 0 + #ifndef CYTHON_UPDATE_DESCRIPTOR_DOC + #define CYTHON_UPDATE_DESCRIPTOR_DOC (PYPY_VERSION_HEX >= 0x07030900) + #endif #elif defined(PYSTON_VERSION) #define CYTHON_COMPILING_IN_PYPY 0 #define CYTHON_COMPILING_IN_PYSTON 1 #define CYTHON_COMPILING_IN_CPYTHON 0 + #define CYTHON_COMPILING_IN_NOGIL 0 #ifndef CYTHON_USE_TYPE_SLOTS #define CYTHON_USE_TYPE_SLOTS 1 #endif @@ -124,10 +131,59 @@ #define CYTHON_USE_DICT_VERSIONS 0 #undef CYTHON_USE_EXC_INFO_STACK #define CYTHON_USE_EXC_INFO_STACK 0 + #ifndef CYTHON_UPDATE_DESCRIPTOR_DOC + #define CYTHON_UPDATE_DESCRIPTOR_DOC 0 + #endif +#elif defined(PY_NOGIL) + #define CYTHON_COMPILING_IN_PYPY 0 + #define CYTHON_COMPILING_IN_PYSTON 0 + #define CYTHON_COMPILING_IN_CPYTHON 0 + #define CYTHON_COMPILING_IN_NOGIL 1 + #ifndef CYTHON_USE_TYPE_SLOTS + #define CYTHON_USE_TYPE_SLOTS 1 + #endif + #undef CYTHON_USE_PYTYPE_LOOKUP + #define CYTHON_USE_PYTYPE_LOOKUP 0 + #ifndef CYTHON_USE_ASYNC_SLOTS + #define CYTHON_USE_ASYNC_SLOTS 1 + #endif + #undef CYTHON_USE_PYLIST_INTERNALS + #define CYTHON_USE_PYLIST_INTERNALS 0 + #ifndef CYTHON_USE_UNICODE_INTERNALS + #define CYTHON_USE_UNICODE_INTERNALS 1 + #endif + #undef CYTHON_USE_UNICODE_WRITER + #define CYTHON_USE_UNICODE_WRITER 0 + #undef CYTHON_USE_PYLONG_INTERNALS + #define CYTHON_USE_PYLONG_INTERNALS 0 + #ifndef CYTHON_AVOID_BORROWED_REFS + #define CYTHON_AVOID_BORROWED_REFS 0 + #endif + #ifndef CYTHON_ASSUME_SAFE_MACROS + #define CYTHON_ASSUME_SAFE_MACROS 1 + #endif + #ifndef CYTHON_UNPACK_METHODS + #define CYTHON_UNPACK_METHODS 1 + #endif + #undef CYTHON_FAST_THREAD_STATE + #define CYTHON_FAST_THREAD_STATE 0 + #undef CYTHON_FAST_PYCALL + #define CYTHON_FAST_PYCALL 0 + #ifndef CYTHON_PEP489_MULTI_PHASE_INIT + #define CYTHON_PEP489_MULTI_PHASE_INIT 1 + #endif + #ifndef CYTHON_USE_TP_FINALIZE + #define CYTHON_USE_TP_FINALIZE 1 + #endif + #undef CYTHON_USE_DICT_VERSIONS + #define CYTHON_USE_DICT_VERSIONS 0 + #undef CYTHON_USE_EXC_INFO_STACK + #define CYTHON_USE_EXC_INFO_STACK 0 #else #define CYTHON_COMPILING_IN_PYPY 0 #define CYTHON_COMPILING_IN_PYSTON 0 #define CYTHON_COMPILING_IN_CPYTHON 1 + #define CYTHON_COMPILING_IN_NOGIL 0 #ifndef CYTHON_USE_TYPE_SLOTS #define CYTHON_USE_TYPE_SLOTS 1 #endif @@ -155,7 +211,7 @@ #ifndef CYTHON_USE_UNICODE_INTERNALS #define CYTHON_USE_UNICODE_INTERNALS 1 #endif - #if PY_VERSION_HEX < 0x030300F0 + #if PY_VERSION_HEX < 0x030300F0 || PY_VERSION_HEX >= 0x030B00A2 #undef CYTHON_USE_UNICODE_WRITER #define CYTHON_USE_UNICODE_WRITER 0 #elif !defined(CYTHON_USE_UNICODE_WRITER) @@ -170,11 +226,14 @@ #ifndef CYTHON_UNPACK_METHODS #define CYTHON_UNPACK_METHODS 1 #endif - #ifndef CYTHON_FAST_THREAD_STATE + #if PY_VERSION_HEX >= 0x030B00A4 + #undef CYTHON_FAST_THREAD_STATE + #define CYTHON_FAST_THREAD_STATE 0 + #elif !defined(CYTHON_FAST_THREAD_STATE) #define CYTHON_FAST_THREAD_STATE 1 #endif #ifndef CYTHON_FAST_PYCALL - #define CYTHON_FAST_PYCALL 1 + #define CYTHON_FAST_PYCALL (PY_VERSION_HEX < 0x030A0000) #endif #ifndef CYTHON_PEP489_MULTI_PHASE_INIT #define CYTHON_PEP489_MULTI_PHASE_INIT (PY_VERSION_HEX >= 0x03050000) @@ -185,15 +244,23 @@ #ifndef CYTHON_USE_DICT_VERSIONS #define CYTHON_USE_DICT_VERSIONS (PY_VERSION_HEX >= 0x030600B1) #endif - #ifndef CYTHON_USE_EXC_INFO_STACK + #if PY_VERSION_HEX >= 0x030B00A4 + #undef CYTHON_USE_EXC_INFO_STACK + #define CYTHON_USE_EXC_INFO_STACK 0 + #elif !defined(CYTHON_USE_EXC_INFO_STACK) #define CYTHON_USE_EXC_INFO_STACK (PY_VERSION_HEX >= 0x030700A3) #endif + #ifndef CYTHON_UPDATE_DESCRIPTOR_DOC + #define CYTHON_UPDATE_DESCRIPTOR_DOC 1 + #endif #endif #if !defined(CYTHON_FAST_PYCCALL) #define CYTHON_FAST_PYCCALL (CYTHON_FAST_PYCALL && PY_VERSION_HEX >= 0x030600B1) #endif #if CYTHON_USE_PYLONG_INTERNALS - #include "longintrepr.h" + #if PY_MAJOR_VERSION < 3 + #include "longintrepr.h" + #endif #undef SHIFT #undef BASE #undef MASK @@ -310,9 +377,68 @@ #define __Pyx_DefaultClassType PyClass_Type #else #define __Pyx_BUILTIN_MODULE_NAME "builtins" -#if PY_VERSION_HEX >= 0x030800A4 && PY_VERSION_HEX < 0x030800B2 - #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ - PyCode_New(a, 0, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) + #define __Pyx_DefaultClassType PyType_Type +#if PY_VERSION_HEX >= 0x030B00A1 + static CYTHON_INLINE PyCodeObject* __Pyx_PyCode_New(int a, int k, int l, int s, int f, + PyObject *code, PyObject *c, PyObject* n, PyObject *v, + PyObject *fv, PyObject *cell, PyObject* fn, + PyObject *name, int fline, PyObject *lnos) { + PyObject *kwds=NULL, *argcount=NULL, *posonlyargcount=NULL, *kwonlyargcount=NULL; + PyObject *nlocals=NULL, *stacksize=NULL, *flags=NULL, *replace=NULL, *call_result=NULL, *empty=NULL; + const char *fn_cstr=NULL; + const char *name_cstr=NULL; + PyCodeObject* co=NULL; + PyObject *type, *value, *traceback; + PyErr_Fetch(&type, &value, &traceback); + if (!(kwds=PyDict_New())) goto end; + if (!(argcount=PyLong_FromLong(a))) goto end; + if (PyDict_SetItemString(kwds, "co_argcount", argcount) != 0) goto end; + if (!(posonlyargcount=PyLong_FromLong(0))) goto end; + if (PyDict_SetItemString(kwds, "co_posonlyargcount", posonlyargcount) != 0) goto end; + if (!(kwonlyargcount=PyLong_FromLong(k))) goto end; + if (PyDict_SetItemString(kwds, "co_kwonlyargcount", kwonlyargcount) != 0) goto end; + if (!(nlocals=PyLong_FromLong(l))) goto end; + if (PyDict_SetItemString(kwds, "co_nlocals", nlocals) != 0) goto end; + if (!(stacksize=PyLong_FromLong(s))) goto end; + if (PyDict_SetItemString(kwds, "co_stacksize", stacksize) != 0) goto end; + if (!(flags=PyLong_FromLong(f))) goto end; + if (PyDict_SetItemString(kwds, "co_flags", flags) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_code", code) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_consts", c) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_names", n) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_varnames", v) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_freevars", fv) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_cellvars", cell) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_linetable", lnos) != 0) goto end; + if (!(fn_cstr=PyUnicode_AsUTF8AndSize(fn, NULL))) goto end; + if (!(name_cstr=PyUnicode_AsUTF8AndSize(name, NULL))) goto end; + if (!(co = PyCode_NewEmpty(fn_cstr, name_cstr, fline))) goto end; + if (!(replace = PyObject_GetAttrString((PyObject*)co, "replace"))) goto cleanup_code_too; + if (!(empty = PyTuple_New(0))) goto cleanup_code_too; // unfortunately __pyx_empty_tuple isn't available here + if (!(call_result = PyObject_Call(replace, empty, kwds))) goto cleanup_code_too; + Py_XDECREF((PyObject*)co); + co = (PyCodeObject*)call_result; + call_result = NULL; + if (0) { + cleanup_code_too: + Py_XDECREF((PyObject*)co); + co = NULL; + } + end: + Py_XDECREF(kwds); + Py_XDECREF(argcount); + Py_XDECREF(posonlyargcount); + Py_XDECREF(kwonlyargcount); + Py_XDECREF(nlocals); + Py_XDECREF(stacksize); + Py_XDECREF(replace); + Py_XDECREF(call_result); + Py_XDECREF(empty); + if (type) { + PyErr_Restore(type, value, traceback); + } + return co; + } #else #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) @@ -426,8 +552,12 @@ static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) { #endif #if PY_VERSION_HEX > 0x03030000 && defined(PyUnicode_KIND) #define CYTHON_PEP393_ENABLED 1 + #if defined(PyUnicode_IS_READY) #define __Pyx_PyUnicode_READY(op) (likely(PyUnicode_IS_READY(op)) ?\ 0 : _PyUnicode_Ready((PyObject *)(op))) + #else + #define __Pyx_PyUnicode_READY(op) (0) + #endif #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_LENGTH(u) #define __Pyx_PyUnicode_READ_CHAR(u, i) PyUnicode_READ_CHAR(u, i) #define __Pyx_PyUnicode_MAX_CHAR_VALUE(u) PyUnicode_MAX_CHAR_VALUE(u) @@ -436,7 +566,11 @@ static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) { #define __Pyx_PyUnicode_READ(k, d, i) PyUnicode_READ(k, d, i) #define __Pyx_PyUnicode_WRITE(k, d, i, ch) PyUnicode_WRITE(k, d, i, ch) #if defined(PyUnicode_IS_READY) && defined(PyUnicode_GET_SIZE) + #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x03090000 + #define __Pyx_PyUnicode_IS_TRUE(u) (0 != (likely(PyUnicode_IS_READY(u)) ? PyUnicode_GET_LENGTH(u) : ((PyCompactUnicodeObject *)(u))->wstr_length)) + #else #define __Pyx_PyUnicode_IS_TRUE(u) (0 != (likely(PyUnicode_IS_READY(u)) ? PyUnicode_GET_LENGTH(u) : PyUnicode_GET_SIZE(u))) + #endif #else #define __Pyx_PyUnicode_IS_TRUE(u) (0 != PyUnicode_GET_LENGTH(u)) #endif @@ -542,10 +676,10 @@ static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) { #if PY_VERSION_HEX < 0x030200A4 typedef long Py_hash_t; #define __Pyx_PyInt_FromHash_t PyInt_FromLong - #define __Pyx_PyInt_AsHash_t PyInt_AsLong + #define __Pyx_PyInt_AsHash_t __Pyx_PyIndex_AsHash_t #else #define __Pyx_PyInt_FromHash_t PyInt_FromSsize_t - #define __Pyx_PyInt_AsHash_t PyInt_AsSsize_t + #define __Pyx_PyInt_AsHash_t __Pyx_PyIndex_AsSsize_t #endif #if PY_MAJOR_VERSION >= 3 #define __Pyx_PyMethod_New(func, self, klass) ((self) ? ((void)(klass), PyMethod_New(func, self)) : __Pyx_NewRef(func)) @@ -570,8 +704,10 @@ static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) { } __Pyx_PyAsyncMethodsStruct; #endif -#if defined(WIN32) || defined(MS_WINDOWS) - #define _USE_MATH_DEFINES +#if defined(_WIN32) || defined(WIN32) || defined(MS_WINDOWS) + #if !defined(_USE_MATH_DEFINES) + #define _USE_MATH_DEFINES + #endif #endif #include #ifdef NAN @@ -704,6 +840,7 @@ static CYTHON_INLINE PyObject* __Pyx_PyNumber_IntOrLong(PyObject* x); (likely(PyTuple_CheckExact(obj)) ? __Pyx_NewRef(obj) : PySequence_Tuple(obj)) static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject*); static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t); +static CYTHON_INLINE Py_hash_t __Pyx_PyIndex_AsHash_t(PyObject*); #if CYTHON_ASSUME_SAFE_MACROS #define __pyx_PyFloat_AsDouble(x) (PyFloat_CheckExact(x) ? PyFloat_AS_DOUBLE(x) : PyFloat_AsDouble(x)) #else @@ -976,13 +1113,21 @@ static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, #ifndef Py_MEMBER_SIZE #define Py_MEMBER_SIZE(type, member) sizeof(((type *)0)->member) #endif +#if CYTHON_FAST_PYCALL static size_t __pyx_pyframe_localsplus_offset = 0; #include "frameobject.h" +#if PY_VERSION_HEX >= 0x030b00a6 + #ifndef Py_BUILD_CORE + #define Py_BUILD_CORE 1 + #endif + #include "internal/pycore_frame.h" +#endif #define __Pxy_PyFrame_Initialize_Offsets()\ ((void)__Pyx_BUILD_ASSERT_EXPR(sizeof(PyFrameObject) == offsetof(PyFrameObject, f_localsplus) + Py_MEMBER_SIZE(PyFrameObject, f_localsplus)),\ (void)(__pyx_pyframe_localsplus_offset = ((size_t)PyFrame_Type.tp_basicsize) - Py_MEMBER_SIZE(PyFrameObject, f_localsplus))) #define __Pyx_PyFrame_GetLocalsplus(frame)\ (assert(__pyx_pyframe_localsplus_offset), (PyObject **)(((char *)(frame)) + __pyx_pyframe_localsplus_offset)) +#endif // CYTHON_FAST_PYCALL #endif /* PyObjectCall.proto */ @@ -1006,6 +1151,12 @@ static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObjec /* RaiseException.proto */ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause); +/* PyUnicodeContains.proto */ +static CYTHON_INLINE int __Pyx_PyUnicode_ContainsTF(PyObject* substring, PyObject* text, int eq) { + int result = PyUnicode_Contains(text, substring); + return unlikely(result < 0) ? result : (result == (eq == Py_EQ)); +} + /* RaiseArgTupleInvalid.proto */ static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact, Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); @@ -1024,14 +1175,6 @@ static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[],\ __Pyx__ArgTypeTest(obj, type, name, exact)) static int __Pyx__ArgTypeTest(PyObject *obj, PyTypeObject *type, const char *name, int exact); -/* GetTopmostException.proto */ -#if CYTHON_USE_EXC_INFO_STACK -static _PyErr_StackItem * __Pyx_PyErr_GetTopmostException(PyThreadState *tstate); -#endif - -/* ReRaiseException.proto */ -static CYTHON_INLINE void __Pyx_ReraiseException(void); - /* IterFinish.proto */ static CYTHON_INLINE int __Pyx_IterFinish(void); @@ -1081,6 +1224,14 @@ static CYTHON_INLINE PyObject* __Pyx_dict_iterator(PyObject* dict, int is_dict, static CYTHON_INLINE int __Pyx_dict_iter_next(PyObject* dict_or_iter, Py_ssize_t orig_length, Py_ssize_t* ppos, PyObject** pkey, PyObject** pvalue, PyObject** pitem, int is_dict); +/* GetTopmostException.proto */ +#if CYTHON_USE_EXC_INFO_STACK +static _PyErr_StackItem * __Pyx_PyErr_GetTopmostException(PyThreadState *tstate); +#endif + +/* ReRaiseException.proto */ +static CYTHON_INLINE void __Pyx_ReraiseException(void); + /* GetException.proto */ #if CYTHON_FAST_THREAD_STATE #define __Pyx_GetException(type, value, tb) __Pyx__GetException(__pyx_tstate, type, value, tb) @@ -1198,6 +1349,11 @@ static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object); static void __Pyx_AddTraceback(const char *funcname, int c_line, int py_line, const char *filename); +/* GCCDiagnostics.proto */ +#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) +#define __Pyx_HAS_GCC_DIAGNOSTIC +#endif + /* CIntToPy.proto */ static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value); @@ -1257,12 +1413,16 @@ static CYTHON_INLINE int __pyx_f_7aiohttp_12_http_writer__write_byte(struct __py static CYTHON_INLINE int __pyx_f_7aiohttp_12_http_writer__write_utf8(struct __pyx_t_7aiohttp_12_http_writer_Writer *, Py_UCS4); /*proto*/ static CYTHON_INLINE int __pyx_f_7aiohttp_12_http_writer__write_str(struct __pyx_t_7aiohttp_12_http_writer_Writer *, PyObject *); /*proto*/ static PyObject *__pyx_f_7aiohttp_12_http_writer_to_str(PyObject *); /*proto*/ +static void __pyx_f_7aiohttp_12_http_writer__safe_header(PyObject *); /*proto*/ #define __Pyx_MODULE_NAME "aiohttp._http_writer" extern int __pyx_module_is_main_aiohttp___http_writer; int __pyx_module_is_main_aiohttp___http_writer = 0; /* Implementation of 'aiohttp._http_writer' */ static PyObject *__pyx_builtin_TypeError; +static PyObject *__pyx_builtin_ValueError; +static const char __pyx_k_[] = "\r"; +static const char __pyx_k__2[] = "\n"; static const char __pyx_k_key[] = "key"; static const char __pyx_k_ret[] = "ret"; static const char __pyx_k_val[] = "val"; @@ -1277,14 +1437,20 @@ static const char __pyx_k_writer[] = "writer"; static const char __pyx_k_headers[] = "headers"; static const char __pyx_k_TypeError[] = "TypeError"; static const char __pyx_k_multidict[] = "multidict"; +static const char __pyx_k_ValueError[] = "ValueError"; static const char __pyx_k_status_line[] = "status_line"; static const char __pyx_k_serialize_headers[] = "_serialize_headers"; static const char __pyx_k_cline_in_traceback[] = "cline_in_traceback"; static const char __pyx_k_aiohttp__http_writer[] = "aiohttp._http_writer"; static const char __pyx_k_aiohttp__http_writer_pyx[] = "aiohttp/_http_writer.pyx"; static const char __pyx_k_Cannot_serialize_non_str_key_r[] = "Cannot serialize non-str key {!r}"; +static const char __pyx_k_Newline_or_carriage_return_chara[] = "Newline or carriage return character detected in HTTP status message or header. This is a potential security issue."; +static PyObject *__pyx_kp_u_; static PyObject *__pyx_kp_u_Cannot_serialize_non_str_key_r; +static PyObject *__pyx_kp_u_Newline_or_carriage_return_chara; static PyObject *__pyx_n_s_TypeError; +static PyObject *__pyx_n_s_ValueError; +static PyObject *__pyx_kp_u__2; static PyObject *__pyx_n_s_aiohttp__http_writer; static PyObject *__pyx_kp_s_aiohttp__http_writer_pyx; static PyObject *__pyx_n_s_cline_in_traceback; @@ -1304,8 +1470,9 @@ static PyObject *__pyx_n_s_test; static PyObject *__pyx_n_s_val; static PyObject *__pyx_n_s_writer; static PyObject *__pyx_pf_7aiohttp_12_http_writer__serialize_headers(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_status_line, PyObject *__pyx_v_headers); /* proto */ -static PyObject *__pyx_tuple_; -static PyObject *__pyx_codeobj__2; +static PyObject *__pyx_tuple__3; +static PyObject *__pyx_tuple__4; +static PyObject *__pyx_codeobj__5; /* Late includes */ /* "aiohttp/_http_writer.pyx":24 @@ -2323,6 +2490,92 @@ static PyObject *__pyx_f_7aiohttp_12_http_writer_to_str(PyObject *__pyx_v_s) { } /* "aiohttp/_http_writer.pyx":114 + * + * + * cdef void _safe_header(str string) except *: # <<<<<<<<<<<<<< + * if "\r" in string or "\n" in string: + * raise ValueError( + */ + +static void __pyx_f_7aiohttp_12_http_writer__safe_header(PyObject *__pyx_v_string) { + __Pyx_RefNannyDeclarations + int __pyx_t_1; + int __pyx_t_2; + int __pyx_t_3; + PyObject *__pyx_t_4 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("_safe_header", 0); + + /* "aiohttp/_http_writer.pyx":115 + * + * cdef void _safe_header(str string) except *: + * if "\r" in string or "\n" in string: # <<<<<<<<<<<<<< + * raise ValueError( + * "Newline or carriage return character detected in HTTP status message or " + */ + if (unlikely(__pyx_v_string == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable"); + __PYX_ERR(0, 115, __pyx_L1_error) + } + __pyx_t_2 = (__Pyx_PyUnicode_ContainsTF(__pyx_kp_u_, __pyx_v_string, Py_EQ)); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 115, __pyx_L1_error) + __pyx_t_3 = (__pyx_t_2 != 0); + if (!__pyx_t_3) { + } else { + __pyx_t_1 = __pyx_t_3; + goto __pyx_L4_bool_binop_done; + } + if (unlikely(__pyx_v_string == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable"); + __PYX_ERR(0, 115, __pyx_L1_error) + } + __pyx_t_3 = (__Pyx_PyUnicode_ContainsTF(__pyx_kp_u__2, __pyx_v_string, Py_EQ)); if (unlikely(__pyx_t_3 < 0)) __PYX_ERR(0, 115, __pyx_L1_error) + __pyx_t_2 = (__pyx_t_3 != 0); + __pyx_t_1 = __pyx_t_2; + __pyx_L4_bool_binop_done:; + if (unlikely(__pyx_t_1)) { + + /* "aiohttp/_http_writer.pyx":116 + * cdef void _safe_header(str string) except *: + * if "\r" in string or "\n" in string: + * raise ValueError( # <<<<<<<<<<<<<< + * "Newline or carriage return character detected in HTTP status message or " + * "header. This is a potential security issue." + */ + __pyx_t_4 = __Pyx_PyObject_Call(__pyx_builtin_ValueError, __pyx_tuple__3, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 116, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_Raise(__pyx_t_4, 0, 0, 0); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __PYX_ERR(0, 116, __pyx_L1_error) + + /* "aiohttp/_http_writer.pyx":115 + * + * cdef void _safe_header(str string) except *: + * if "\r" in string or "\n" in string: # <<<<<<<<<<<<<< + * raise ValueError( + * "Newline or carriage return character detected in HTTP status message or " + */ + } + + /* "aiohttp/_http_writer.pyx":114 + * + * + * cdef void _safe_header(str string) except *: # <<<<<<<<<<<<<< + * if "\r" in string or "\n" in string: + * raise ValueError( + */ + + /* function exit code */ + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_4); + __Pyx_AddTraceback("aiohttp._http_writer._safe_header", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_L0:; + __Pyx_RefNannyFinishContext(); +} + +/* "aiohttp/_http_writer.pyx":122 * * * def _serialize_headers(str status_line, headers): # <<<<<<<<<<<<<< @@ -2365,11 +2618,11 @@ static PyObject *__pyx_pw_7aiohttp_12_http_writer_1_serialize_headers(PyObject * case 1: if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_headers)) != 0)) kw_args--; else { - __Pyx_RaiseArgtupleInvalid("_serialize_headers", 1, 2, 2, 1); __PYX_ERR(0, 114, __pyx_L3_error) + __Pyx_RaiseArgtupleInvalid("_serialize_headers", 1, 2, 2, 1); __PYX_ERR(0, 122, __pyx_L3_error) } } if (unlikely(kw_args > 0)) { - if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "_serialize_headers") < 0)) __PYX_ERR(0, 114, __pyx_L3_error) + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "_serialize_headers") < 0)) __PYX_ERR(0, 122, __pyx_L3_error) } } else if (PyTuple_GET_SIZE(__pyx_args) != 2) { goto __pyx_L5_argtuple_error; @@ -2382,13 +2635,13 @@ static PyObject *__pyx_pw_7aiohttp_12_http_writer_1_serialize_headers(PyObject * } goto __pyx_L4_argument_unpacking_done; __pyx_L5_argtuple_error:; - __Pyx_RaiseArgtupleInvalid("_serialize_headers", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 114, __pyx_L3_error) + __Pyx_RaiseArgtupleInvalid("_serialize_headers", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 122, __pyx_L3_error) __pyx_L3_error:; __Pyx_AddTraceback("aiohttp._http_writer._serialize_headers", __pyx_clineno, __pyx_lineno, __pyx_filename); __Pyx_RefNannyFinishContext(); return NULL; __pyx_L4_argument_unpacking_done:; - if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_status_line), (&PyUnicode_Type), 1, "status_line", 1))) __PYX_ERR(0, 114, __pyx_L1_error) + if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_status_line), (&PyUnicode_Type), 1, "status_line", 1))) __PYX_ERR(0, 122, __pyx_L1_error) __pyx_r = __pyx_pf_7aiohttp_12_http_writer__serialize_headers(__pyx_self, __pyx_v_status_line, __pyx_v_headers); /* function exit code */ @@ -2406,13 +2659,13 @@ static PyObject *__pyx_pf_7aiohttp_12_http_writer__serialize_headers(CYTHON_UNUS PyObject *__pyx_v_val = 0; PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations - int __pyx_t_1; - PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_1 = NULL; + Py_ssize_t __pyx_t_2; Py_ssize_t __pyx_t_3; - Py_ssize_t __pyx_t_4; - int __pyx_t_5; + int __pyx_t_4; + PyObject *__pyx_t_5 = NULL; PyObject *__pyx_t_6 = NULL; - PyObject *__pyx_t_7 = NULL; + int __pyx_t_7; int __pyx_t_8; char const *__pyx_t_9; PyObject *__pyx_t_10 = NULL; @@ -2426,44 +2679,98 @@ static PyObject *__pyx_pf_7aiohttp_12_http_writer__serialize_headers(CYTHON_UNUS int __pyx_clineno = 0; __Pyx_RefNannySetupContext("_serialize_headers", 0); - /* "aiohttp/_http_writer.pyx":120 + /* "aiohttp/_http_writer.pyx":128 * cdef bytes ret * * _init_writer(&writer) # <<<<<<<<<<<<<< * - * try: + * for key, val in headers.items(): */ __pyx_f_7aiohttp_12_http_writer__init_writer((&__pyx_v_writer)); - /* "aiohttp/_http_writer.pyx":122 + /* "aiohttp/_http_writer.pyx":130 * _init_writer(&writer) * + * for key, val in headers.items(): # <<<<<<<<<<<<<< + * _safe_header(to_str(key)) + * _safe_header(to_str(val)) + */ + __pyx_t_2 = 0; + if (unlikely(__pyx_v_headers == Py_None)) { + PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "items"); + __PYX_ERR(0, 130, __pyx_L1_error) + } + __pyx_t_5 = __Pyx_dict_iterator(__pyx_v_headers, 0, __pyx_n_s_items, (&__pyx_t_3), (&__pyx_t_4)); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 130, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_1); + __pyx_t_1 = __pyx_t_5; + __pyx_t_5 = 0; + while (1) { + __pyx_t_7 = __Pyx_dict_iter_next(__pyx_t_1, __pyx_t_3, &__pyx_t_2, &__pyx_t_5, &__pyx_t_6, NULL, __pyx_t_4); + if (unlikely(__pyx_t_7 == 0)) break; + if (unlikely(__pyx_t_7 == -1)) __PYX_ERR(0, 130, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_GOTREF(__pyx_t_6); + __Pyx_XDECREF_SET(__pyx_v_key, __pyx_t_5); + __pyx_t_5 = 0; + __Pyx_XDECREF_SET(__pyx_v_val, __pyx_t_6); + __pyx_t_6 = 0; + + /* "aiohttp/_http_writer.pyx":131 + * + * for key, val in headers.items(): + * _safe_header(to_str(key)) # <<<<<<<<<<<<<< + * _safe_header(to_str(val)) + * + */ + __pyx_t_6 = __pyx_f_7aiohttp_12_http_writer_to_str(__pyx_v_key); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 131, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_f_7aiohttp_12_http_writer__safe_header(((PyObject*)__pyx_t_6)); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 131, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + + /* "aiohttp/_http_writer.pyx":132 + * for key, val in headers.items(): + * _safe_header(to_str(key)) + * _safe_header(to_str(val)) # <<<<<<<<<<<<<< + * + * try: + */ + __pyx_t_6 = __pyx_f_7aiohttp_12_http_writer_to_str(__pyx_v_val); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 132, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_f_7aiohttp_12_http_writer__safe_header(((PyObject*)__pyx_t_6)); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 132, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + } + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "aiohttp/_http_writer.pyx":134 + * _safe_header(to_str(val)) + * * try: # <<<<<<<<<<<<<< * if _write_str(&writer, status_line) < 0: * raise */ /*try:*/ { - /* "aiohttp/_http_writer.pyx":123 + /* "aiohttp/_http_writer.pyx":135 * * try: * if _write_str(&writer, status_line) < 0: # <<<<<<<<<<<<<< * raise * if _write_byte(&writer, b'\r') < 0: */ - __pyx_t_1 = ((__pyx_f_7aiohttp_12_http_writer__write_str((&__pyx_v_writer), __pyx_v_status_line) < 0) != 0); - if (unlikely(__pyx_t_1)) { + __pyx_t_8 = ((__pyx_f_7aiohttp_12_http_writer__write_str((&__pyx_v_writer), __pyx_v_status_line) < 0) != 0); + if (unlikely(__pyx_t_8)) { - /* "aiohttp/_http_writer.pyx":124 + /* "aiohttp/_http_writer.pyx":136 * try: * if _write_str(&writer, status_line) < 0: * raise # <<<<<<<<<<<<<< * if _write_byte(&writer, b'\r') < 0: * raise */ - __Pyx_ReraiseException(); __PYX_ERR(0, 124, __pyx_L4_error) + __Pyx_ReraiseException(); __PYX_ERR(0, 136, __pyx_L6_error) - /* "aiohttp/_http_writer.pyx":123 + /* "aiohttp/_http_writer.pyx":135 * * try: * if _write_str(&writer, status_line) < 0: # <<<<<<<<<<<<<< @@ -2472,26 +2779,26 @@ static PyObject *__pyx_pf_7aiohttp_12_http_writer__serialize_headers(CYTHON_UNUS */ } - /* "aiohttp/_http_writer.pyx":125 + /* "aiohttp/_http_writer.pyx":137 * if _write_str(&writer, status_line) < 0: * raise * if _write_byte(&writer, b'\r') < 0: # <<<<<<<<<<<<<< * raise * if _write_byte(&writer, b'\n') < 0: */ - __pyx_t_1 = ((__pyx_f_7aiohttp_12_http_writer__write_byte((&__pyx_v_writer), '\r') < 0) != 0); - if (unlikely(__pyx_t_1)) { + __pyx_t_8 = ((__pyx_f_7aiohttp_12_http_writer__write_byte((&__pyx_v_writer), '\r') < 0) != 0); + if (unlikely(__pyx_t_8)) { - /* "aiohttp/_http_writer.pyx":126 + /* "aiohttp/_http_writer.pyx":138 * raise * if _write_byte(&writer, b'\r') < 0: * raise # <<<<<<<<<<<<<< * if _write_byte(&writer, b'\n') < 0: * raise */ - __Pyx_ReraiseException(); __PYX_ERR(0, 126, __pyx_L4_error) + __Pyx_ReraiseException(); __PYX_ERR(0, 138, __pyx_L6_error) - /* "aiohttp/_http_writer.pyx":125 + /* "aiohttp/_http_writer.pyx":137 * if _write_str(&writer, status_line) < 0: * raise * if _write_byte(&writer, b'\r') < 0: # <<<<<<<<<<<<<< @@ -2500,26 +2807,26 @@ static PyObject *__pyx_pf_7aiohttp_12_http_writer__serialize_headers(CYTHON_UNUS */ } - /* "aiohttp/_http_writer.pyx":127 + /* "aiohttp/_http_writer.pyx":139 * if _write_byte(&writer, b'\r') < 0: * raise * if _write_byte(&writer, b'\n') < 0: # <<<<<<<<<<<<<< * raise * */ - __pyx_t_1 = ((__pyx_f_7aiohttp_12_http_writer__write_byte((&__pyx_v_writer), '\n') < 0) != 0); - if (unlikely(__pyx_t_1)) { + __pyx_t_8 = ((__pyx_f_7aiohttp_12_http_writer__write_byte((&__pyx_v_writer), '\n') < 0) != 0); + if (unlikely(__pyx_t_8)) { - /* "aiohttp/_http_writer.pyx":128 + /* "aiohttp/_http_writer.pyx":140 * raise * if _write_byte(&writer, b'\n') < 0: * raise # <<<<<<<<<<<<<< * * for key, val in headers.items(): */ - __Pyx_ReraiseException(); __PYX_ERR(0, 128, __pyx_L4_error) + __Pyx_ReraiseException(); __PYX_ERR(0, 140, __pyx_L6_error) - /* "aiohttp/_http_writer.pyx":127 + /* "aiohttp/_http_writer.pyx":139 * if _write_byte(&writer, b'\r') < 0: * raise * if _write_byte(&writer, b'\n') < 0: # <<<<<<<<<<<<<< @@ -2528,7 +2835,7 @@ static PyObject *__pyx_pf_7aiohttp_12_http_writer__serialize_headers(CYTHON_UNUS */ } - /* "aiohttp/_http_writer.pyx":130 + /* "aiohttp/_http_writer.pyx":142 * raise * * for key, val in headers.items(): # <<<<<<<<<<<<<< @@ -2538,47 +2845,47 @@ static PyObject *__pyx_pf_7aiohttp_12_http_writer__serialize_headers(CYTHON_UNUS __pyx_t_3 = 0; if (unlikely(__pyx_v_headers == Py_None)) { PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "items"); - __PYX_ERR(0, 130, __pyx_L4_error) + __PYX_ERR(0, 142, __pyx_L6_error) } - __pyx_t_6 = __Pyx_dict_iterator(__pyx_v_headers, 0, __pyx_n_s_items, (&__pyx_t_4), (&__pyx_t_5)); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 130, __pyx_L4_error) + __pyx_t_6 = __Pyx_dict_iterator(__pyx_v_headers, 0, __pyx_n_s_items, (&__pyx_t_2), (&__pyx_t_4)); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 142, __pyx_L6_error) __Pyx_GOTREF(__pyx_t_6); - __Pyx_XDECREF(__pyx_t_2); - __pyx_t_2 = __pyx_t_6; + __Pyx_XDECREF(__pyx_t_1); + __pyx_t_1 = __pyx_t_6; __pyx_t_6 = 0; while (1) { - __pyx_t_8 = __Pyx_dict_iter_next(__pyx_t_2, __pyx_t_4, &__pyx_t_3, &__pyx_t_6, &__pyx_t_7, NULL, __pyx_t_5); - if (unlikely(__pyx_t_8 == 0)) break; - if (unlikely(__pyx_t_8 == -1)) __PYX_ERR(0, 130, __pyx_L4_error) + __pyx_t_7 = __Pyx_dict_iter_next(__pyx_t_1, __pyx_t_2, &__pyx_t_3, &__pyx_t_6, &__pyx_t_5, NULL, __pyx_t_4); + if (unlikely(__pyx_t_7 == 0)) break; + if (unlikely(__pyx_t_7 == -1)) __PYX_ERR(0, 142, __pyx_L6_error) __Pyx_GOTREF(__pyx_t_6); - __Pyx_GOTREF(__pyx_t_7); + __Pyx_GOTREF(__pyx_t_5); __Pyx_XDECREF_SET(__pyx_v_key, __pyx_t_6); __pyx_t_6 = 0; - __Pyx_XDECREF_SET(__pyx_v_val, __pyx_t_7); - __pyx_t_7 = 0; + __Pyx_XDECREF_SET(__pyx_v_val, __pyx_t_5); + __pyx_t_5 = 0; - /* "aiohttp/_http_writer.pyx":131 + /* "aiohttp/_http_writer.pyx":143 * * for key, val in headers.items(): * if _write_str(&writer, to_str(key)) < 0: # <<<<<<<<<<<<<< * raise * if _write_byte(&writer, b':') < 0: */ - __pyx_t_7 = __pyx_f_7aiohttp_12_http_writer_to_str(__pyx_v_key); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 131, __pyx_L4_error) - __Pyx_GOTREF(__pyx_t_7); - __pyx_t_1 = ((__pyx_f_7aiohttp_12_http_writer__write_str((&__pyx_v_writer), ((PyObject*)__pyx_t_7)) < 0) != 0); - __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; - if (unlikely(__pyx_t_1)) { + __pyx_t_5 = __pyx_f_7aiohttp_12_http_writer_to_str(__pyx_v_key); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 143, __pyx_L6_error) + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_8 = ((__pyx_f_7aiohttp_12_http_writer__write_str((&__pyx_v_writer), ((PyObject*)__pyx_t_5)) < 0) != 0); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (unlikely(__pyx_t_8)) { - /* "aiohttp/_http_writer.pyx":132 + /* "aiohttp/_http_writer.pyx":144 * for key, val in headers.items(): * if _write_str(&writer, to_str(key)) < 0: * raise # <<<<<<<<<<<<<< * if _write_byte(&writer, b':') < 0: * raise */ - __Pyx_ReraiseException(); __PYX_ERR(0, 132, __pyx_L4_error) + __Pyx_ReraiseException(); __PYX_ERR(0, 144, __pyx_L6_error) - /* "aiohttp/_http_writer.pyx":131 + /* "aiohttp/_http_writer.pyx":143 * * for key, val in headers.items(): * if _write_str(&writer, to_str(key)) < 0: # <<<<<<<<<<<<<< @@ -2587,26 +2894,26 @@ static PyObject *__pyx_pf_7aiohttp_12_http_writer__serialize_headers(CYTHON_UNUS */ } - /* "aiohttp/_http_writer.pyx":133 + /* "aiohttp/_http_writer.pyx":145 * if _write_str(&writer, to_str(key)) < 0: * raise * if _write_byte(&writer, b':') < 0: # <<<<<<<<<<<<<< * raise * if _write_byte(&writer, b' ') < 0: */ - __pyx_t_1 = ((__pyx_f_7aiohttp_12_http_writer__write_byte((&__pyx_v_writer), ':') < 0) != 0); - if (unlikely(__pyx_t_1)) { + __pyx_t_8 = ((__pyx_f_7aiohttp_12_http_writer__write_byte((&__pyx_v_writer), ':') < 0) != 0); + if (unlikely(__pyx_t_8)) { - /* "aiohttp/_http_writer.pyx":134 + /* "aiohttp/_http_writer.pyx":146 * raise * if _write_byte(&writer, b':') < 0: * raise # <<<<<<<<<<<<<< * if _write_byte(&writer, b' ') < 0: * raise */ - __Pyx_ReraiseException(); __PYX_ERR(0, 134, __pyx_L4_error) + __Pyx_ReraiseException(); __PYX_ERR(0, 146, __pyx_L6_error) - /* "aiohttp/_http_writer.pyx":133 + /* "aiohttp/_http_writer.pyx":145 * if _write_str(&writer, to_str(key)) < 0: * raise * if _write_byte(&writer, b':') < 0: # <<<<<<<<<<<<<< @@ -2615,26 +2922,26 @@ static PyObject *__pyx_pf_7aiohttp_12_http_writer__serialize_headers(CYTHON_UNUS */ } - /* "aiohttp/_http_writer.pyx":135 + /* "aiohttp/_http_writer.pyx":147 * if _write_byte(&writer, b':') < 0: * raise * if _write_byte(&writer, b' ') < 0: # <<<<<<<<<<<<<< * raise * if _write_str(&writer, to_str(val)) < 0: */ - __pyx_t_1 = ((__pyx_f_7aiohttp_12_http_writer__write_byte((&__pyx_v_writer), ' ') < 0) != 0); - if (unlikely(__pyx_t_1)) { + __pyx_t_8 = ((__pyx_f_7aiohttp_12_http_writer__write_byte((&__pyx_v_writer), ' ') < 0) != 0); + if (unlikely(__pyx_t_8)) { - /* "aiohttp/_http_writer.pyx":136 + /* "aiohttp/_http_writer.pyx":148 * raise * if _write_byte(&writer, b' ') < 0: * raise # <<<<<<<<<<<<<< * if _write_str(&writer, to_str(val)) < 0: * raise */ - __Pyx_ReraiseException(); __PYX_ERR(0, 136, __pyx_L4_error) + __Pyx_ReraiseException(); __PYX_ERR(0, 148, __pyx_L6_error) - /* "aiohttp/_http_writer.pyx":135 + /* "aiohttp/_http_writer.pyx":147 * if _write_byte(&writer, b':') < 0: * raise * if _write_byte(&writer, b' ') < 0: # <<<<<<<<<<<<<< @@ -2643,29 +2950,29 @@ static PyObject *__pyx_pf_7aiohttp_12_http_writer__serialize_headers(CYTHON_UNUS */ } - /* "aiohttp/_http_writer.pyx":137 + /* "aiohttp/_http_writer.pyx":149 * if _write_byte(&writer, b' ') < 0: * raise * if _write_str(&writer, to_str(val)) < 0: # <<<<<<<<<<<<<< * raise * if _write_byte(&writer, b'\r') < 0: */ - __pyx_t_7 = __pyx_f_7aiohttp_12_http_writer_to_str(__pyx_v_val); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 137, __pyx_L4_error) - __Pyx_GOTREF(__pyx_t_7); - __pyx_t_1 = ((__pyx_f_7aiohttp_12_http_writer__write_str((&__pyx_v_writer), ((PyObject*)__pyx_t_7)) < 0) != 0); - __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; - if (unlikely(__pyx_t_1)) { + __pyx_t_5 = __pyx_f_7aiohttp_12_http_writer_to_str(__pyx_v_val); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 149, __pyx_L6_error) + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_8 = ((__pyx_f_7aiohttp_12_http_writer__write_str((&__pyx_v_writer), ((PyObject*)__pyx_t_5)) < 0) != 0); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (unlikely(__pyx_t_8)) { - /* "aiohttp/_http_writer.pyx":138 + /* "aiohttp/_http_writer.pyx":150 * raise * if _write_str(&writer, to_str(val)) < 0: * raise # <<<<<<<<<<<<<< * if _write_byte(&writer, b'\r') < 0: * raise */ - __Pyx_ReraiseException(); __PYX_ERR(0, 138, __pyx_L4_error) + __Pyx_ReraiseException(); __PYX_ERR(0, 150, __pyx_L6_error) - /* "aiohttp/_http_writer.pyx":137 + /* "aiohttp/_http_writer.pyx":149 * if _write_byte(&writer, b' ') < 0: * raise * if _write_str(&writer, to_str(val)) < 0: # <<<<<<<<<<<<<< @@ -2674,26 +2981,26 @@ static PyObject *__pyx_pf_7aiohttp_12_http_writer__serialize_headers(CYTHON_UNUS */ } - /* "aiohttp/_http_writer.pyx":139 + /* "aiohttp/_http_writer.pyx":151 * if _write_str(&writer, to_str(val)) < 0: * raise * if _write_byte(&writer, b'\r') < 0: # <<<<<<<<<<<<<< * raise * if _write_byte(&writer, b'\n') < 0: */ - __pyx_t_1 = ((__pyx_f_7aiohttp_12_http_writer__write_byte((&__pyx_v_writer), '\r') < 0) != 0); - if (unlikely(__pyx_t_1)) { + __pyx_t_8 = ((__pyx_f_7aiohttp_12_http_writer__write_byte((&__pyx_v_writer), '\r') < 0) != 0); + if (unlikely(__pyx_t_8)) { - /* "aiohttp/_http_writer.pyx":140 + /* "aiohttp/_http_writer.pyx":152 * raise * if _write_byte(&writer, b'\r') < 0: * raise # <<<<<<<<<<<<<< * if _write_byte(&writer, b'\n') < 0: * raise */ - __Pyx_ReraiseException(); __PYX_ERR(0, 140, __pyx_L4_error) + __Pyx_ReraiseException(); __PYX_ERR(0, 152, __pyx_L6_error) - /* "aiohttp/_http_writer.pyx":139 + /* "aiohttp/_http_writer.pyx":151 * if _write_str(&writer, to_str(val)) < 0: * raise * if _write_byte(&writer, b'\r') < 0: # <<<<<<<<<<<<<< @@ -2702,26 +3009,26 @@ static PyObject *__pyx_pf_7aiohttp_12_http_writer__serialize_headers(CYTHON_UNUS */ } - /* "aiohttp/_http_writer.pyx":141 + /* "aiohttp/_http_writer.pyx":153 * if _write_byte(&writer, b'\r') < 0: * raise * if _write_byte(&writer, b'\n') < 0: # <<<<<<<<<<<<<< * raise * */ - __pyx_t_1 = ((__pyx_f_7aiohttp_12_http_writer__write_byte((&__pyx_v_writer), '\n') < 0) != 0); - if (unlikely(__pyx_t_1)) { + __pyx_t_8 = ((__pyx_f_7aiohttp_12_http_writer__write_byte((&__pyx_v_writer), '\n') < 0) != 0); + if (unlikely(__pyx_t_8)) { - /* "aiohttp/_http_writer.pyx":142 + /* "aiohttp/_http_writer.pyx":154 * raise * if _write_byte(&writer, b'\n') < 0: * raise # <<<<<<<<<<<<<< * * if _write_byte(&writer, b'\r') < 0: */ - __Pyx_ReraiseException(); __PYX_ERR(0, 142, __pyx_L4_error) + __Pyx_ReraiseException(); __PYX_ERR(0, 154, __pyx_L6_error) - /* "aiohttp/_http_writer.pyx":141 + /* "aiohttp/_http_writer.pyx":153 * if _write_byte(&writer, b'\r') < 0: * raise * if _write_byte(&writer, b'\n') < 0: # <<<<<<<<<<<<<< @@ -2730,28 +3037,28 @@ static PyObject *__pyx_pf_7aiohttp_12_http_writer__serialize_headers(CYTHON_UNUS */ } } - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - /* "aiohttp/_http_writer.pyx":144 + /* "aiohttp/_http_writer.pyx":156 * raise * * if _write_byte(&writer, b'\r') < 0: # <<<<<<<<<<<<<< * raise * if _write_byte(&writer, b'\n') < 0: */ - __pyx_t_1 = ((__pyx_f_7aiohttp_12_http_writer__write_byte((&__pyx_v_writer), '\r') < 0) != 0); - if (unlikely(__pyx_t_1)) { + __pyx_t_8 = ((__pyx_f_7aiohttp_12_http_writer__write_byte((&__pyx_v_writer), '\r') < 0) != 0); + if (unlikely(__pyx_t_8)) { - /* "aiohttp/_http_writer.pyx":145 + /* "aiohttp/_http_writer.pyx":157 * * if _write_byte(&writer, b'\r') < 0: * raise # <<<<<<<<<<<<<< * if _write_byte(&writer, b'\n') < 0: * raise */ - __Pyx_ReraiseException(); __PYX_ERR(0, 145, __pyx_L4_error) + __Pyx_ReraiseException(); __PYX_ERR(0, 157, __pyx_L6_error) - /* "aiohttp/_http_writer.pyx":144 + /* "aiohttp/_http_writer.pyx":156 * raise * * if _write_byte(&writer, b'\r') < 0: # <<<<<<<<<<<<<< @@ -2760,26 +3067,26 @@ static PyObject *__pyx_pf_7aiohttp_12_http_writer__serialize_headers(CYTHON_UNUS */ } - /* "aiohttp/_http_writer.pyx":146 + /* "aiohttp/_http_writer.pyx":158 * if _write_byte(&writer, b'\r') < 0: * raise * if _write_byte(&writer, b'\n') < 0: # <<<<<<<<<<<<<< * raise * */ - __pyx_t_1 = ((__pyx_f_7aiohttp_12_http_writer__write_byte((&__pyx_v_writer), '\n') < 0) != 0); - if (unlikely(__pyx_t_1)) { + __pyx_t_8 = ((__pyx_f_7aiohttp_12_http_writer__write_byte((&__pyx_v_writer), '\n') < 0) != 0); + if (unlikely(__pyx_t_8)) { - /* "aiohttp/_http_writer.pyx":147 + /* "aiohttp/_http_writer.pyx":159 * raise * if _write_byte(&writer, b'\n') < 0: * raise # <<<<<<<<<<<<<< * * return PyBytes_FromStringAndSize(writer.buf, writer.pos) */ - __Pyx_ReraiseException(); __PYX_ERR(0, 147, __pyx_L4_error) + __Pyx_ReraiseException(); __PYX_ERR(0, 159, __pyx_L6_error) - /* "aiohttp/_http_writer.pyx":146 + /* "aiohttp/_http_writer.pyx":158 * if _write_byte(&writer, b'\r') < 0: * raise * if _write_byte(&writer, b'\n') < 0: # <<<<<<<<<<<<<< @@ -2788,7 +3095,7 @@ static PyObject *__pyx_pf_7aiohttp_12_http_writer__serialize_headers(CYTHON_UNUS */ } - /* "aiohttp/_http_writer.pyx":149 + /* "aiohttp/_http_writer.pyx":161 * raise * * return PyBytes_FromStringAndSize(writer.buf, writer.pos) # <<<<<<<<<<<<<< @@ -2796,27 +3103,27 @@ static PyObject *__pyx_pf_7aiohttp_12_http_writer__serialize_headers(CYTHON_UNUS * _release_writer(&writer) */ __Pyx_XDECREF(__pyx_r); - __pyx_t_2 = PyBytes_FromStringAndSize(__pyx_v_writer.buf, __pyx_v_writer.pos); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 149, __pyx_L4_error) - __Pyx_GOTREF(__pyx_t_2); - __pyx_r = __pyx_t_2; - __pyx_t_2 = 0; - goto __pyx_L3_return; + __pyx_t_1 = PyBytes_FromStringAndSize(__pyx_v_writer.buf, __pyx_v_writer.pos); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 161, __pyx_L6_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L5_return; } - /* "aiohttp/_http_writer.pyx":151 + /* "aiohttp/_http_writer.pyx":163 * return PyBytes_FromStringAndSize(writer.buf, writer.pos) * finally: * _release_writer(&writer) # <<<<<<<<<<<<<< */ /*finally:*/ { - __pyx_L4_error:; + __pyx_L6_error:; /*exception exit:*/{ __Pyx_PyThreadState_declare __Pyx_PyThreadState_assign __pyx_t_10 = 0; __pyx_t_11 = 0; __pyx_t_12 = 0; __pyx_t_13 = 0; __pyx_t_14 = 0; __pyx_t_15 = 0; - __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; - __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; if (PY_MAJOR_VERSION >= 3) __Pyx_ExceptionSwap(&__pyx_t_13, &__pyx_t_14, &__pyx_t_15); if ((PY_MAJOR_VERSION < 3) || unlikely(__Pyx_GetException(&__pyx_t_10, &__pyx_t_11, &__pyx_t_12) < 0)) __Pyx_ErrFetch(&__pyx_t_10, &__pyx_t_11, &__pyx_t_12); __Pyx_XGOTREF(__pyx_t_10); @@ -2825,7 +3132,7 @@ static PyObject *__pyx_pf_7aiohttp_12_http_writer__serialize_headers(CYTHON_UNUS __Pyx_XGOTREF(__pyx_t_13); __Pyx_XGOTREF(__pyx_t_14); __Pyx_XGOTREF(__pyx_t_15); - __pyx_t_5 = __pyx_lineno; __pyx_t_8 = __pyx_clineno; __pyx_t_9 = __pyx_filename; + __pyx_t_4 = __pyx_lineno; __pyx_t_7 = __pyx_clineno; __pyx_t_9 = __pyx_filename; { __pyx_f_7aiohttp_12_http_writer__release_writer((&__pyx_v_writer)); } @@ -2840,10 +3147,10 @@ static PyObject *__pyx_pf_7aiohttp_12_http_writer__serialize_headers(CYTHON_UNUS __Pyx_XGIVEREF(__pyx_t_12); __Pyx_ErrRestore(__pyx_t_10, __pyx_t_11, __pyx_t_12); __pyx_t_10 = 0; __pyx_t_11 = 0; __pyx_t_12 = 0; __pyx_t_13 = 0; __pyx_t_14 = 0; __pyx_t_15 = 0; - __pyx_lineno = __pyx_t_5; __pyx_clineno = __pyx_t_8; __pyx_filename = __pyx_t_9; + __pyx_lineno = __pyx_t_4; __pyx_clineno = __pyx_t_7; __pyx_filename = __pyx_t_9; goto __pyx_L1_error; } - __pyx_L3_return: { + __pyx_L5_return: { __pyx_t_15 = __pyx_r; __pyx_r = 0; __pyx_f_7aiohttp_12_http_writer__release_writer((&__pyx_v_writer)); @@ -2853,7 +3160,7 @@ static PyObject *__pyx_pf_7aiohttp_12_http_writer__serialize_headers(CYTHON_UNUS } } - /* "aiohttp/_http_writer.pyx":114 + /* "aiohttp/_http_writer.pyx":122 * * * def _serialize_headers(str status_line, headers): # <<<<<<<<<<<<<< @@ -2863,9 +3170,9 @@ static PyObject *__pyx_pf_7aiohttp_12_http_writer__serialize_headers(CYTHON_UNUS /* function exit code */ __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_5); __Pyx_XDECREF(__pyx_t_6); - __Pyx_XDECREF(__pyx_t_7); __Pyx_AddTraceback("aiohttp._http_writer._serialize_headers", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = NULL; __pyx_L0:; @@ -2922,8 +3229,12 @@ static struct PyModuleDef __pyx_moduledef = { #endif static __Pyx_StringTabEntry __pyx_string_tab[] = { + {&__pyx_kp_u_, __pyx_k_, sizeof(__pyx_k_), 0, 1, 0, 0}, {&__pyx_kp_u_Cannot_serialize_non_str_key_r, __pyx_k_Cannot_serialize_non_str_key_r, sizeof(__pyx_k_Cannot_serialize_non_str_key_r), 0, 1, 0, 0}, + {&__pyx_kp_u_Newline_or_carriage_return_chara, __pyx_k_Newline_or_carriage_return_chara, sizeof(__pyx_k_Newline_or_carriage_return_chara), 0, 1, 0, 0}, {&__pyx_n_s_TypeError, __pyx_k_TypeError, sizeof(__pyx_k_TypeError), 0, 0, 1, 1}, + {&__pyx_n_s_ValueError, __pyx_k_ValueError, sizeof(__pyx_k_ValueError), 0, 0, 1, 1}, + {&__pyx_kp_u__2, __pyx_k__2, sizeof(__pyx_k__2), 0, 1, 0, 0}, {&__pyx_n_s_aiohttp__http_writer, __pyx_k_aiohttp__http_writer, sizeof(__pyx_k_aiohttp__http_writer), 0, 0, 1, 1}, {&__pyx_kp_s_aiohttp__http_writer_pyx, __pyx_k_aiohttp__http_writer_pyx, sizeof(__pyx_k_aiohttp__http_writer_pyx), 0, 0, 1, 0}, {&__pyx_n_s_cline_in_traceback, __pyx_k_cline_in_traceback, sizeof(__pyx_k_cline_in_traceback), 0, 0, 1, 1}, @@ -2946,6 +3257,7 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = { }; static CYTHON_SMALL_CODE int __Pyx_InitCachedBuiltins(void) { __pyx_builtin_TypeError = __Pyx_GetBuiltinName(__pyx_n_s_TypeError); if (!__pyx_builtin_TypeError) __PYX_ERR(0, 109, __pyx_L1_error) + __pyx_builtin_ValueError = __Pyx_GetBuiltinName(__pyx_n_s_ValueError); if (!__pyx_builtin_ValueError) __PYX_ERR(0, 116, __pyx_L1_error) return 0; __pyx_L1_error:; return -1; @@ -2955,17 +3267,28 @@ static CYTHON_SMALL_CODE int __Pyx_InitCachedConstants(void) { __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("__Pyx_InitCachedConstants", 0); - /* "aiohttp/_http_writer.pyx":114 + /* "aiohttp/_http_writer.pyx":116 + * cdef void _safe_header(str string) except *: + * if "\r" in string or "\n" in string: + * raise ValueError( # <<<<<<<<<<<<<< + * "Newline or carriage return character detected in HTTP status message or " + * "header. This is a potential security issue." + */ + __pyx_tuple__3 = PyTuple_Pack(1, __pyx_kp_u_Newline_or_carriage_return_chara); if (unlikely(!__pyx_tuple__3)) __PYX_ERR(0, 116, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__3); + __Pyx_GIVEREF(__pyx_tuple__3); + + /* "aiohttp/_http_writer.pyx":122 * * * def _serialize_headers(str status_line, headers): # <<<<<<<<<<<<<< * cdef Writer writer * cdef object key */ - __pyx_tuple_ = PyTuple_Pack(6, __pyx_n_s_status_line, __pyx_n_s_headers, __pyx_n_s_writer, __pyx_n_s_key, __pyx_n_s_val, __pyx_n_s_ret); if (unlikely(!__pyx_tuple_)) __PYX_ERR(0, 114, __pyx_L1_error) - __Pyx_GOTREF(__pyx_tuple_); - __Pyx_GIVEREF(__pyx_tuple_); - __pyx_codeobj__2 = (PyObject*)__Pyx_PyCode_New(2, 0, 6, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple_, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_aiohttp__http_writer_pyx, __pyx_n_s_serialize_headers, 114, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__2)) __PYX_ERR(0, 114, __pyx_L1_error) + __pyx_tuple__4 = PyTuple_Pack(6, __pyx_n_s_status_line, __pyx_n_s_headers, __pyx_n_s_writer, __pyx_n_s_key, __pyx_n_s_val, __pyx_n_s_ret); if (unlikely(!__pyx_tuple__4)) __PYX_ERR(0, 122, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__4); + __Pyx_GIVEREF(__pyx_tuple__4); + __pyx_codeobj__5 = (PyObject*)__Pyx_PyCode_New(2, 0, 6, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__4, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_aiohttp__http_writer_pyx, __pyx_n_s_serialize_headers, 122, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__5)) __PYX_ERR(0, 122, __pyx_L1_error) __Pyx_RefNannyFinishContext(); return 0; __pyx_L1_error:; @@ -3210,11 +3533,9 @@ if (!__Pyx_RefNanny) { #endif /*--- Library function declarations ---*/ /*--- Threads initialization code ---*/ - #if defined(__PYX_FORCE_INIT_THREADS) && __PYX_FORCE_INIT_THREADS - #ifdef WITH_THREAD /* Python build with threading support? */ + #if defined(WITH_THREAD) && PY_VERSION_HEX < 0x030700F0 && defined(__PYX_FORCE_INIT_THREADS) && __PYX_FORCE_INIT_THREADS PyEval_InitThreads(); #endif - #endif /*--- Module creation code ---*/ #if CYTHON_PEP489_MULTI_PHASE_INIT __pyx_m = __pyx_pyinit_module; @@ -3302,16 +3623,16 @@ if (!__Pyx_RefNanny) { __Pyx_GIVEREF(__pyx_t_2); __pyx_t_2 = 0; - /* "aiohttp/_http_writer.pyx":114 + /* "aiohttp/_http_writer.pyx":122 * * * def _serialize_headers(str status_line, headers): # <<<<<<<<<<<<<< * cdef Writer writer * cdef object key */ - __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_7aiohttp_12_http_writer_1_serialize_headers, NULL, __pyx_n_s_aiohttp__http_writer); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 114, __pyx_L1_error) + __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_7aiohttp_12_http_writer_1_serialize_headers, NULL, __pyx_n_s_aiohttp__http_writer); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 122, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); - if (PyDict_SetItem(__pyx_d, __pyx_n_s_serialize_headers, __pyx_t_2) < 0) __PYX_ERR(0, 114, __pyx_L1_error) + if (PyDict_SetItem(__pyx_d, __pyx_n_s_serialize_headers, __pyx_t_2) < 0) __PYX_ERR(0, 122, __pyx_L1_error) __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "aiohttp/_http_writer.pyx":1 @@ -3623,7 +3944,7 @@ static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, #if CYTHON_COMPILING_IN_CPYTHON static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw) { PyObject *result; - ternaryfunc call = func->ob_type->tp_call; + ternaryfunc call = Py_TYPE(func)->tp_call; if (unlikely(!call)) return PyObject_Call(func, arg, kw); if (unlikely(Py_EnterRecursiveCall((char*)" while calling a Python object"))) @@ -3710,7 +4031,7 @@ static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObjec if (likely(PyCFunction_GET_FLAGS(func) & METH_O)) { return __Pyx_PyObject_CallMethO(func, arg); #if CYTHON_FAST_PYCCALL - } else if (PyCFunction_GET_FLAGS(func) & METH_FASTCALL) { + } else if (__Pyx_PyFastCFunction_Check(func)) { return __Pyx_PyCFunction_FastCall(func, &arg, 1); #endif } @@ -4050,57 +4371,6 @@ static int __Pyx__ArgTypeTest(PyObject *obj, PyTypeObject *type, const char *nam return 0; } -/* GetTopmostException */ -#if CYTHON_USE_EXC_INFO_STACK -static _PyErr_StackItem * -__Pyx_PyErr_GetTopmostException(PyThreadState *tstate) -{ - _PyErr_StackItem *exc_info = tstate->exc_info; - while ((exc_info->exc_type == NULL || exc_info->exc_type == Py_None) && - exc_info->previous_item != NULL) - { - exc_info = exc_info->previous_item; - } - return exc_info; -} -#endif - -/* ReRaiseException */ -static CYTHON_INLINE void __Pyx_ReraiseException(void) { - PyObject *type = NULL, *value = NULL, *tb = NULL; -#if CYTHON_FAST_THREAD_STATE - PyThreadState *tstate = PyThreadState_GET(); - #if CYTHON_USE_EXC_INFO_STACK - _PyErr_StackItem *exc_info = __Pyx_PyErr_GetTopmostException(tstate); - type = exc_info->exc_type; - value = exc_info->exc_value; - tb = exc_info->exc_traceback; - #else - type = tstate->exc_type; - value = tstate->exc_value; - tb = tstate->exc_traceback; - #endif -#else - PyErr_GetExcInfo(&type, &value, &tb); -#endif - if (!type || type == Py_None) { -#if !CYTHON_FAST_THREAD_STATE - Py_XDECREF(type); - Py_XDECREF(value); - Py_XDECREF(tb); -#endif - PyErr_SetString(PyExc_RuntimeError, - "No active exception to reraise"); - } else { -#if CYTHON_FAST_THREAD_STATE - Py_INCREF(type); - Py_XINCREF(value); - Py_XINCREF(tb); -#endif - PyErr_Restore(type, value, tb); - } -} - /* IterFinish */ static CYTHON_INLINE int __Pyx_IterFinish(void) { #if CYTHON_FAST_THREAD_STATE @@ -4476,6 +4746,57 @@ static CYTHON_INLINE int __Pyx_dict_iter_next( return 1; } +/* GetTopmostException */ +#if CYTHON_USE_EXC_INFO_STACK +static _PyErr_StackItem * +__Pyx_PyErr_GetTopmostException(PyThreadState *tstate) +{ + _PyErr_StackItem *exc_info = tstate->exc_info; + while ((exc_info->exc_type == NULL || exc_info->exc_type == Py_None) && + exc_info->previous_item != NULL) + { + exc_info = exc_info->previous_item; + } + return exc_info; +} +#endif + +/* ReRaiseException */ +static CYTHON_INLINE void __Pyx_ReraiseException(void) { + PyObject *type = NULL, *value = NULL, *tb = NULL; +#if CYTHON_FAST_THREAD_STATE + PyThreadState *tstate = PyThreadState_GET(); + #if CYTHON_USE_EXC_INFO_STACK + _PyErr_StackItem *exc_info = __Pyx_PyErr_GetTopmostException(tstate); + type = exc_info->exc_type; + value = exc_info->exc_value; + tb = exc_info->exc_traceback; + #else + type = tstate->exc_type; + value = tstate->exc_value; + tb = tstate->exc_traceback; + #endif +#else + PyErr_GetExcInfo(&type, &value, &tb); +#endif + if (!type || type == Py_None) { +#if !CYTHON_FAST_THREAD_STATE + Py_XDECREF(type); + Py_XDECREF(value); + Py_XDECREF(tb); +#endif + PyErr_SetString(PyExc_RuntimeError, + "No active exception to reraise"); + } else { +#if CYTHON_FAST_THREAD_STATE + Py_INCREF(type); + Py_XINCREF(value); + Py_XINCREF(tb); +#endif + PyErr_Restore(type, value, tb); + } +} + /* GetException */ #if CYTHON_FAST_THREAD_STATE static int __Pyx__GetException(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) @@ -4859,7 +5180,7 @@ static int __Pyx_CLineForTraceback(CYTHON_NCP_UNUSED PyThreadState *tstate, int } if (!use_cline) { c_line = 0; - PyObject_SetAttr(__pyx_cython_runtime, __pyx_n_s_cline_in_traceback, Py_False); + (void) PyObject_SetAttr(__pyx_cython_runtime, __pyx_n_s_cline_in_traceback, Py_False); } else if (use_cline == Py_False || (use_cline != Py_True && PyObject_Not(use_cline) != 0)) { c_line = 0; @@ -4953,33 +5274,40 @@ static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object) { #include "compile.h" #include "frameobject.h" #include "traceback.h" +#if PY_VERSION_HEX >= 0x030b00a6 + #ifndef Py_BUILD_CORE + #define Py_BUILD_CORE 1 + #endif + #include "internal/pycore_frame.h" +#endif static PyCodeObject* __Pyx_CreateCodeObjectForTraceback( const char *funcname, int c_line, int py_line, const char *filename) { - PyCodeObject *py_code = 0; - PyObject *py_srcfile = 0; - PyObject *py_funcname = 0; + PyCodeObject *py_code = NULL; + PyObject *py_funcname = NULL; #if PY_MAJOR_VERSION < 3 + PyObject *py_srcfile = NULL; py_srcfile = PyString_FromString(filename); - #else - py_srcfile = PyUnicode_FromString(filename); - #endif if (!py_srcfile) goto bad; + #endif if (c_line) { #if PY_MAJOR_VERSION < 3 py_funcname = PyString_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line); + if (!py_funcname) goto bad; #else py_funcname = PyUnicode_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line); + if (!py_funcname) goto bad; + funcname = PyUnicode_AsUTF8(py_funcname); + if (!funcname) goto bad; #endif } else { #if PY_MAJOR_VERSION < 3 py_funcname = PyString_FromString(funcname); - #else - py_funcname = PyUnicode_FromString(funcname); + if (!py_funcname) goto bad; #endif } - if (!py_funcname) goto bad; + #if PY_MAJOR_VERSION < 3 py_code = __Pyx_PyCode_New( 0, 0, @@ -4998,11 +5326,16 @@ static PyCodeObject* __Pyx_CreateCodeObjectForTraceback( __pyx_empty_bytes /*PyObject *lnotab*/ ); Py_DECREF(py_srcfile); - Py_DECREF(py_funcname); + #else + py_code = PyCode_NewEmpty(filename, funcname, py_line); + #endif + Py_XDECREF(py_funcname); // XDECREF since it's only set on Py3 if cline return py_code; bad: - Py_XDECREF(py_srcfile); Py_XDECREF(py_funcname); + #if PY_MAJOR_VERSION < 3 + Py_XDECREF(py_srcfile); + #endif return NULL; } static void __Pyx_AddTraceback(const char *funcname, int c_line, @@ -5010,14 +5343,24 @@ static void __Pyx_AddTraceback(const char *funcname, int c_line, PyCodeObject *py_code = 0; PyFrameObject *py_frame = 0; PyThreadState *tstate = __Pyx_PyThreadState_Current; + PyObject *ptype, *pvalue, *ptraceback; if (c_line) { c_line = __Pyx_CLineForTraceback(tstate, c_line); } py_code = __pyx_find_code_object(c_line ? -c_line : py_line); if (!py_code) { + __Pyx_ErrFetchInState(tstate, &ptype, &pvalue, &ptraceback); py_code = __Pyx_CreateCodeObjectForTraceback( funcname, c_line, py_line, filename); - if (!py_code) goto bad; + if (!py_code) { + /* If the code object creation fails, then we should clear the + fetched exception references and propagate the new exception */ + Py_XDECREF(ptype); + Py_XDECREF(pvalue); + Py_XDECREF(ptraceback); + goto bad; + } + __Pyx_ErrRestoreInState(tstate, ptype, pvalue, ptraceback); __pyx_insert_code_object(c_line ? -c_line : py_line, py_code); } py_frame = PyFrame_New( @@ -5036,7 +5379,14 @@ static void __Pyx_AddTraceback(const char *funcname, int c_line, /* CIntToPy */ static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value) { - const long neg_one = (long) ((long) 0 - (long) 1), const_zero = (long) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +#endif + const long neg_one = (long) -1, const_zero = (long) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic pop +#endif const int is_unsigned = neg_one > const_zero; if (is_unsigned) { if (sizeof(long) < sizeof(long)) { @@ -5089,7 +5439,14 @@ static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value) { /* CIntFromPy */ static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *x) { - const long neg_one = (long) ((long) 0 - (long) 1), const_zero = (long) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +#endif + const long neg_one = (long) -1, const_zero = (long) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic pop +#endif const int is_unsigned = neg_one > const_zero; #if PY_MAJOR_VERSION < 3 if (likely(PyInt_Check(x))) { @@ -5278,7 +5635,14 @@ static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *x) { /* CIntFromPy */ static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *x) { - const int neg_one = (int) ((int) 0 - (int) 1), const_zero = (int) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +#endif + const int neg_one = (int) -1, const_zero = (int) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic pop +#endif const int is_unsigned = neg_one > const_zero; #if PY_MAJOR_VERSION < 3 if (likely(PyInt_Check(x))) { @@ -5567,11 +5931,33 @@ static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches2(PyObject *err, PyObj /* CheckBinaryVersion */ static int __Pyx_check_binary_version(void) { - char ctversion[4], rtversion[4]; - PyOS_snprintf(ctversion, 4, "%d.%d", PY_MAJOR_VERSION, PY_MINOR_VERSION); - PyOS_snprintf(rtversion, 4, "%s", Py_GetVersion()); - if (ctversion[0] != rtversion[0] || ctversion[2] != rtversion[2]) { + char ctversion[5]; + int same=1, i, found_dot; + const char* rt_from_call = Py_GetVersion(); + PyOS_snprintf(ctversion, 5, "%d.%d", PY_MAJOR_VERSION, PY_MINOR_VERSION); + found_dot = 0; + for (i = 0; i < 4; i++) { + if (!ctversion[i]) { + same = (rt_from_call[i] < '0' || rt_from_call[i] > '9'); + break; + } + if (rt_from_call[i] != ctversion[i]) { + same = 0; + break; + } + } + if (!same) { + char rtversion[5] = {'\0'}; char message[200]; + for (i=0; i<4; ++i) { + if (rt_from_call[i] == '.') { + if (found_dot) break; + found_dot = 1; + } else if (rt_from_call[i] < '0' || rt_from_call[i] > '9') { + break; + } + rtversion[i] = rt_from_call[i]; + } PyOS_snprintf(message, sizeof(message), "compiletime version %s of module '%.100s' " "does not match runtime version %s", @@ -5829,6 +6215,23 @@ static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) { Py_DECREF(x); return ival; } +static CYTHON_INLINE Py_hash_t __Pyx_PyIndex_AsHash_t(PyObject* o) { + if (sizeof(Py_hash_t) == sizeof(Py_ssize_t)) { + return (Py_hash_t) __Pyx_PyIndex_AsSsize_t(o); +#if PY_MAJOR_VERSION < 3 + } else if (likely(PyInt_CheckExact(o))) { + return PyInt_AS_LONG(o); +#endif + } else { + Py_ssize_t ival; + PyObject *x; + x = PyNumber_Index(o); + if (!x) return -1; + ival = PyInt_AsLong(x); + Py_DECREF(x); + return ival; + } +} static CYTHON_INLINE PyObject * __Pyx_PyBool_FromLong(long b) { return b ? __Pyx_NewRef(Py_True) : __Pyx_NewRef(Py_False); } diff --git a/aiohttp/_http_writer.pyx b/aiohttp/_http_writer.pyx index 84b42fa..eff8521 100644 --- a/aiohttp/_http_writer.pyx +++ b/aiohttp/_http_writer.pyx @@ -111,6 +111,14 @@ cdef str to_str(object s): return str(s) +cdef void _safe_header(str string) except *: + if "\r" in string or "\n" in string: + raise ValueError( + "Newline or carriage return character detected in HTTP status message or " + "header. This is a potential security issue." + ) + + def _serialize_headers(str status_line, headers): cdef Writer writer cdef object key @@ -119,6 +127,10 @@ def _serialize_headers(str status_line, headers): _init_writer(&writer) + for key, val in headers.items(): + _safe_header(to_str(key)) + _safe_header(to_str(val)) + try: if _write_str(&writer, status_line) < 0: raise diff --git a/aiohttp/_websocket.c b/aiohttp/_websocket.c index 4891c24..de83e09 100644 --- a/aiohttp/_websocket.c +++ b/aiohttp/_websocket.c @@ -1,14 +1,16 @@ -/* Generated by Cython 0.29.21 */ +/* Generated by Cython 0.29.32 */ +#ifndef PY_SSIZE_T_CLEAN #define PY_SSIZE_T_CLEAN +#endif /* PY_SSIZE_T_CLEAN */ #include "Python.h" #ifndef Py_PYTHON_H #error Python headers needed to compile C extensions, please install development version of Python. #elif PY_VERSION_HEX < 0x02060000 || (0x03000000 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x03030000) #error Cython requires Python 2.6+ or Python 3.3+. #else -#define CYTHON_ABI "0_29_21" -#define CYTHON_HEX_VERSION 0x001D15F0 +#define CYTHON_ABI "0_29_32" +#define CYTHON_HEX_VERSION 0x001D20F0 #define CYTHON_FUTURE_DIVISION 1 #include #ifndef offsetof @@ -47,6 +49,7 @@ #define CYTHON_COMPILING_IN_PYPY 1 #define CYTHON_COMPILING_IN_PYSTON 0 #define CYTHON_COMPILING_IN_CPYTHON 0 + #define CYTHON_COMPILING_IN_NOGIL 0 #undef CYTHON_USE_TYPE_SLOTS #define CYTHON_USE_TYPE_SLOTS 0 #undef CYTHON_USE_PYTYPE_LOOKUP @@ -83,10 +86,14 @@ #define CYTHON_USE_DICT_VERSIONS 0 #undef CYTHON_USE_EXC_INFO_STACK #define CYTHON_USE_EXC_INFO_STACK 0 + #ifndef CYTHON_UPDATE_DESCRIPTOR_DOC + #define CYTHON_UPDATE_DESCRIPTOR_DOC (PYPY_VERSION_HEX >= 0x07030900) + #endif #elif defined(PYSTON_VERSION) #define CYTHON_COMPILING_IN_PYPY 0 #define CYTHON_COMPILING_IN_PYSTON 1 #define CYTHON_COMPILING_IN_CPYTHON 0 + #define CYTHON_COMPILING_IN_NOGIL 0 #ifndef CYTHON_USE_TYPE_SLOTS #define CYTHON_USE_TYPE_SLOTS 1 #endif @@ -124,10 +131,59 @@ #define CYTHON_USE_DICT_VERSIONS 0 #undef CYTHON_USE_EXC_INFO_STACK #define CYTHON_USE_EXC_INFO_STACK 0 + #ifndef CYTHON_UPDATE_DESCRIPTOR_DOC + #define CYTHON_UPDATE_DESCRIPTOR_DOC 0 + #endif +#elif defined(PY_NOGIL) + #define CYTHON_COMPILING_IN_PYPY 0 + #define CYTHON_COMPILING_IN_PYSTON 0 + #define CYTHON_COMPILING_IN_CPYTHON 0 + #define CYTHON_COMPILING_IN_NOGIL 1 + #ifndef CYTHON_USE_TYPE_SLOTS + #define CYTHON_USE_TYPE_SLOTS 1 + #endif + #undef CYTHON_USE_PYTYPE_LOOKUP + #define CYTHON_USE_PYTYPE_LOOKUP 0 + #ifndef CYTHON_USE_ASYNC_SLOTS + #define CYTHON_USE_ASYNC_SLOTS 1 + #endif + #undef CYTHON_USE_PYLIST_INTERNALS + #define CYTHON_USE_PYLIST_INTERNALS 0 + #ifndef CYTHON_USE_UNICODE_INTERNALS + #define CYTHON_USE_UNICODE_INTERNALS 1 + #endif + #undef CYTHON_USE_UNICODE_WRITER + #define CYTHON_USE_UNICODE_WRITER 0 + #undef CYTHON_USE_PYLONG_INTERNALS + #define CYTHON_USE_PYLONG_INTERNALS 0 + #ifndef CYTHON_AVOID_BORROWED_REFS + #define CYTHON_AVOID_BORROWED_REFS 0 + #endif + #ifndef CYTHON_ASSUME_SAFE_MACROS + #define CYTHON_ASSUME_SAFE_MACROS 1 + #endif + #ifndef CYTHON_UNPACK_METHODS + #define CYTHON_UNPACK_METHODS 1 + #endif + #undef CYTHON_FAST_THREAD_STATE + #define CYTHON_FAST_THREAD_STATE 0 + #undef CYTHON_FAST_PYCALL + #define CYTHON_FAST_PYCALL 0 + #ifndef CYTHON_PEP489_MULTI_PHASE_INIT + #define CYTHON_PEP489_MULTI_PHASE_INIT 1 + #endif + #ifndef CYTHON_USE_TP_FINALIZE + #define CYTHON_USE_TP_FINALIZE 1 + #endif + #undef CYTHON_USE_DICT_VERSIONS + #define CYTHON_USE_DICT_VERSIONS 0 + #undef CYTHON_USE_EXC_INFO_STACK + #define CYTHON_USE_EXC_INFO_STACK 0 #else #define CYTHON_COMPILING_IN_PYPY 0 #define CYTHON_COMPILING_IN_PYSTON 0 #define CYTHON_COMPILING_IN_CPYTHON 1 + #define CYTHON_COMPILING_IN_NOGIL 0 #ifndef CYTHON_USE_TYPE_SLOTS #define CYTHON_USE_TYPE_SLOTS 1 #endif @@ -155,7 +211,7 @@ #ifndef CYTHON_USE_UNICODE_INTERNALS #define CYTHON_USE_UNICODE_INTERNALS 1 #endif - #if PY_VERSION_HEX < 0x030300F0 + #if PY_VERSION_HEX < 0x030300F0 || PY_VERSION_HEX >= 0x030B00A2 #undef CYTHON_USE_UNICODE_WRITER #define CYTHON_USE_UNICODE_WRITER 0 #elif !defined(CYTHON_USE_UNICODE_WRITER) @@ -170,11 +226,14 @@ #ifndef CYTHON_UNPACK_METHODS #define CYTHON_UNPACK_METHODS 1 #endif - #ifndef CYTHON_FAST_THREAD_STATE + #if PY_VERSION_HEX >= 0x030B00A4 + #undef CYTHON_FAST_THREAD_STATE + #define CYTHON_FAST_THREAD_STATE 0 + #elif !defined(CYTHON_FAST_THREAD_STATE) #define CYTHON_FAST_THREAD_STATE 1 #endif #ifndef CYTHON_FAST_PYCALL - #define CYTHON_FAST_PYCALL 1 + #define CYTHON_FAST_PYCALL (PY_VERSION_HEX < 0x030A0000) #endif #ifndef CYTHON_PEP489_MULTI_PHASE_INIT #define CYTHON_PEP489_MULTI_PHASE_INIT (PY_VERSION_HEX >= 0x03050000) @@ -185,15 +244,23 @@ #ifndef CYTHON_USE_DICT_VERSIONS #define CYTHON_USE_DICT_VERSIONS (PY_VERSION_HEX >= 0x030600B1) #endif - #ifndef CYTHON_USE_EXC_INFO_STACK + #if PY_VERSION_HEX >= 0x030B00A4 + #undef CYTHON_USE_EXC_INFO_STACK + #define CYTHON_USE_EXC_INFO_STACK 0 + #elif !defined(CYTHON_USE_EXC_INFO_STACK) #define CYTHON_USE_EXC_INFO_STACK (PY_VERSION_HEX >= 0x030700A3) #endif + #ifndef CYTHON_UPDATE_DESCRIPTOR_DOC + #define CYTHON_UPDATE_DESCRIPTOR_DOC 1 + #endif #endif #if !defined(CYTHON_FAST_PYCCALL) #define CYTHON_FAST_PYCCALL (CYTHON_FAST_PYCALL && PY_VERSION_HEX >= 0x030600B1) #endif #if CYTHON_USE_PYLONG_INTERNALS - #include "longintrepr.h" + #if PY_MAJOR_VERSION < 3 + #include "longintrepr.h" + #endif #undef SHIFT #undef BASE #undef MASK @@ -310,9 +377,68 @@ #define __Pyx_DefaultClassType PyClass_Type #else #define __Pyx_BUILTIN_MODULE_NAME "builtins" -#if PY_VERSION_HEX >= 0x030800A4 && PY_VERSION_HEX < 0x030800B2 - #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ - PyCode_New(a, 0, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) + #define __Pyx_DefaultClassType PyType_Type +#if PY_VERSION_HEX >= 0x030B00A1 + static CYTHON_INLINE PyCodeObject* __Pyx_PyCode_New(int a, int k, int l, int s, int f, + PyObject *code, PyObject *c, PyObject* n, PyObject *v, + PyObject *fv, PyObject *cell, PyObject* fn, + PyObject *name, int fline, PyObject *lnos) { + PyObject *kwds=NULL, *argcount=NULL, *posonlyargcount=NULL, *kwonlyargcount=NULL; + PyObject *nlocals=NULL, *stacksize=NULL, *flags=NULL, *replace=NULL, *call_result=NULL, *empty=NULL; + const char *fn_cstr=NULL; + const char *name_cstr=NULL; + PyCodeObject* co=NULL; + PyObject *type, *value, *traceback; + PyErr_Fetch(&type, &value, &traceback); + if (!(kwds=PyDict_New())) goto end; + if (!(argcount=PyLong_FromLong(a))) goto end; + if (PyDict_SetItemString(kwds, "co_argcount", argcount) != 0) goto end; + if (!(posonlyargcount=PyLong_FromLong(0))) goto end; + if (PyDict_SetItemString(kwds, "co_posonlyargcount", posonlyargcount) != 0) goto end; + if (!(kwonlyargcount=PyLong_FromLong(k))) goto end; + if (PyDict_SetItemString(kwds, "co_kwonlyargcount", kwonlyargcount) != 0) goto end; + if (!(nlocals=PyLong_FromLong(l))) goto end; + if (PyDict_SetItemString(kwds, "co_nlocals", nlocals) != 0) goto end; + if (!(stacksize=PyLong_FromLong(s))) goto end; + if (PyDict_SetItemString(kwds, "co_stacksize", stacksize) != 0) goto end; + if (!(flags=PyLong_FromLong(f))) goto end; + if (PyDict_SetItemString(kwds, "co_flags", flags) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_code", code) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_consts", c) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_names", n) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_varnames", v) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_freevars", fv) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_cellvars", cell) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_linetable", lnos) != 0) goto end; + if (!(fn_cstr=PyUnicode_AsUTF8AndSize(fn, NULL))) goto end; + if (!(name_cstr=PyUnicode_AsUTF8AndSize(name, NULL))) goto end; + if (!(co = PyCode_NewEmpty(fn_cstr, name_cstr, fline))) goto end; + if (!(replace = PyObject_GetAttrString((PyObject*)co, "replace"))) goto cleanup_code_too; + if (!(empty = PyTuple_New(0))) goto cleanup_code_too; // unfortunately __pyx_empty_tuple isn't available here + if (!(call_result = PyObject_Call(replace, empty, kwds))) goto cleanup_code_too; + Py_XDECREF((PyObject*)co); + co = (PyCodeObject*)call_result; + call_result = NULL; + if (0) { + cleanup_code_too: + Py_XDECREF((PyObject*)co); + co = NULL; + } + end: + Py_XDECREF(kwds); + Py_XDECREF(argcount); + Py_XDECREF(posonlyargcount); + Py_XDECREF(kwonlyargcount); + Py_XDECREF(nlocals); + Py_XDECREF(stacksize); + Py_XDECREF(replace); + Py_XDECREF(call_result); + Py_XDECREF(empty); + if (type) { + PyErr_Restore(type, value, traceback); + } + return co; + } #else #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) @@ -426,8 +552,12 @@ static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) { #endif #if PY_VERSION_HEX > 0x03030000 && defined(PyUnicode_KIND) #define CYTHON_PEP393_ENABLED 1 + #if defined(PyUnicode_IS_READY) #define __Pyx_PyUnicode_READY(op) (likely(PyUnicode_IS_READY(op)) ?\ 0 : _PyUnicode_Ready((PyObject *)(op))) + #else + #define __Pyx_PyUnicode_READY(op) (0) + #endif #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_LENGTH(u) #define __Pyx_PyUnicode_READ_CHAR(u, i) PyUnicode_READ_CHAR(u, i) #define __Pyx_PyUnicode_MAX_CHAR_VALUE(u) PyUnicode_MAX_CHAR_VALUE(u) @@ -436,7 +566,11 @@ static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) { #define __Pyx_PyUnicode_READ(k, d, i) PyUnicode_READ(k, d, i) #define __Pyx_PyUnicode_WRITE(k, d, i, ch) PyUnicode_WRITE(k, d, i, ch) #if defined(PyUnicode_IS_READY) && defined(PyUnicode_GET_SIZE) + #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x03090000 + #define __Pyx_PyUnicode_IS_TRUE(u) (0 != (likely(PyUnicode_IS_READY(u)) ? PyUnicode_GET_LENGTH(u) : ((PyCompactUnicodeObject *)(u))->wstr_length)) + #else #define __Pyx_PyUnicode_IS_TRUE(u) (0 != (likely(PyUnicode_IS_READY(u)) ? PyUnicode_GET_LENGTH(u) : PyUnicode_GET_SIZE(u))) + #endif #else #define __Pyx_PyUnicode_IS_TRUE(u) (0 != PyUnicode_GET_LENGTH(u)) #endif @@ -542,10 +676,10 @@ static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) { #if PY_VERSION_HEX < 0x030200A4 typedef long Py_hash_t; #define __Pyx_PyInt_FromHash_t PyInt_FromLong - #define __Pyx_PyInt_AsHash_t PyInt_AsLong + #define __Pyx_PyInt_AsHash_t __Pyx_PyIndex_AsHash_t #else #define __Pyx_PyInt_FromHash_t PyInt_FromSsize_t - #define __Pyx_PyInt_AsHash_t PyInt_AsSsize_t + #define __Pyx_PyInt_AsHash_t __Pyx_PyIndex_AsSsize_t #endif #if PY_MAJOR_VERSION >= 3 #define __Pyx_PyMethod_New(func, self, klass) ((self) ? ((void)(klass), PyMethod_New(func, self)) : __Pyx_NewRef(func)) @@ -570,8 +704,10 @@ static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) { } __Pyx_PyAsyncMethodsStruct; #endif -#if defined(WIN32) || defined(MS_WINDOWS) - #define _USE_MATH_DEFINES +#if defined(_WIN32) || defined(WIN32) || defined(MS_WINDOWS) + #if !defined(_USE_MATH_DEFINES) + #define _USE_MATH_DEFINES + #endif #endif #include #ifdef NAN @@ -705,6 +841,7 @@ static CYTHON_INLINE PyObject* __Pyx_PyNumber_IntOrLong(PyObject* x); (likely(PyTuple_CheckExact(obj)) ? __Pyx_NewRef(obj) : PySequence_Tuple(obj)) static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject*); static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t); +static CYTHON_INLINE Py_hash_t __Pyx_PyIndex_AsHash_t(PyObject*); #if CYTHON_ASSUME_SAFE_MACROS #define __pyx_PyFloat_AsDouble(x) (PyFloat_CheckExact(x) ? PyFloat_AS_DOUBLE(x) : PyFloat_AsDouble(x)) #else @@ -932,13 +1069,21 @@ static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, #ifndef Py_MEMBER_SIZE #define Py_MEMBER_SIZE(type, member) sizeof(((type *)0)->member) #endif +#if CYTHON_FAST_PYCALL static size_t __pyx_pyframe_localsplus_offset = 0; #include "frameobject.h" +#if PY_VERSION_HEX >= 0x030b00a6 + #ifndef Py_BUILD_CORE + #define Py_BUILD_CORE 1 + #endif + #include "internal/pycore_frame.h" +#endif #define __Pxy_PyFrame_Initialize_Offsets()\ ((void)__Pyx_BUILD_ASSERT_EXPR(sizeof(PyFrameObject) == offsetof(PyFrameObject, f_localsplus) + Py_MEMBER_SIZE(PyFrameObject, f_localsplus)),\ (void)(__pyx_pyframe_localsplus_offset = ((size_t)PyFrame_Type.tp_basicsize) - Py_MEMBER_SIZE(PyFrameObject, f_localsplus))) #define __Pyx_PyFrame_GetLocalsplus(frame)\ (assert(__pyx_pyframe_localsplus_offset), (PyObject **)(((char *)(frame)) + __pyx_pyframe_localsplus_offset)) +#endif // CYTHON_FAST_PYCALL #endif /* PyObjectCall.proto */ @@ -1055,6 +1200,11 @@ static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object); static void __Pyx_AddTraceback(const char *funcname, int c_line, int py_line, const char *filename); +/* GCCDiagnostics.proto */ +#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) +#define __Pyx_HAS_GCC_DIAGNOSTIC +#endif + /* CIntToPy.proto */ static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value); @@ -1951,11 +2101,9 @@ if (!__Pyx_RefNanny) { #endif /*--- Library function declarations ---*/ /*--- Threads initialization code ---*/ - #if defined(__PYX_FORCE_INIT_THREADS) && __PYX_FORCE_INIT_THREADS - #ifdef WITH_THREAD /* Python build with threading support? */ + #if defined(WITH_THREAD) && PY_VERSION_HEX < 0x030700F0 && defined(__PYX_FORCE_INIT_THREADS) && __PYX_FORCE_INIT_THREADS PyEval_InitThreads(); #endif - #endif /*--- Module creation code ---*/ #if CYTHON_PEP489_MULTI_PHASE_INIT __pyx_m = __pyx_pyinit_module; @@ -2388,7 +2536,7 @@ static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, #if CYTHON_COMPILING_IN_CPYTHON static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw) { PyObject *result; - ternaryfunc call = func->ob_type->tp_call; + ternaryfunc call = Py_TYPE(func)->tp_call; if (unlikely(!call)) return PyObject_Call(func, arg, kw); if (unlikely(Py_EnterRecursiveCall((char*)" while calling a Python object"))) @@ -2446,7 +2594,7 @@ static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObjec if (likely(PyCFunction_GET_FLAGS(func) & METH_O)) { return __Pyx_PyObject_CallMethO(func, arg); #if CYTHON_FAST_PYCCALL - } else if (PyCFunction_GET_FLAGS(func) & METH_FASTCALL) { + } else if (__Pyx_PyFastCFunction_Check(func)) { return __Pyx_PyCFunction_FastCall(func, &arg, 1); #endif } @@ -2607,7 +2755,7 @@ static int __Pyx_CLineForTraceback(CYTHON_NCP_UNUSED PyThreadState *tstate, int } if (!use_cline) { c_line = 0; - PyObject_SetAttr(__pyx_cython_runtime, __pyx_n_s_cline_in_traceback, Py_False); + (void) PyObject_SetAttr(__pyx_cython_runtime, __pyx_n_s_cline_in_traceback, Py_False); } else if (use_cline == Py_False || (use_cline != Py_True && PyObject_Not(use_cline) != 0)) { c_line = 0; @@ -2701,33 +2849,40 @@ static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object) { #include "compile.h" #include "frameobject.h" #include "traceback.h" +#if PY_VERSION_HEX >= 0x030b00a6 + #ifndef Py_BUILD_CORE + #define Py_BUILD_CORE 1 + #endif + #include "internal/pycore_frame.h" +#endif static PyCodeObject* __Pyx_CreateCodeObjectForTraceback( const char *funcname, int c_line, int py_line, const char *filename) { - PyCodeObject *py_code = 0; - PyObject *py_srcfile = 0; - PyObject *py_funcname = 0; + PyCodeObject *py_code = NULL; + PyObject *py_funcname = NULL; #if PY_MAJOR_VERSION < 3 + PyObject *py_srcfile = NULL; py_srcfile = PyString_FromString(filename); - #else - py_srcfile = PyUnicode_FromString(filename); - #endif if (!py_srcfile) goto bad; + #endif if (c_line) { #if PY_MAJOR_VERSION < 3 py_funcname = PyString_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line); + if (!py_funcname) goto bad; #else py_funcname = PyUnicode_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line); + if (!py_funcname) goto bad; + funcname = PyUnicode_AsUTF8(py_funcname); + if (!funcname) goto bad; #endif } else { #if PY_MAJOR_VERSION < 3 py_funcname = PyString_FromString(funcname); - #else - py_funcname = PyUnicode_FromString(funcname); + if (!py_funcname) goto bad; #endif } - if (!py_funcname) goto bad; + #if PY_MAJOR_VERSION < 3 py_code = __Pyx_PyCode_New( 0, 0, @@ -2746,11 +2901,16 @@ static PyCodeObject* __Pyx_CreateCodeObjectForTraceback( __pyx_empty_bytes /*PyObject *lnotab*/ ); Py_DECREF(py_srcfile); - Py_DECREF(py_funcname); + #else + py_code = PyCode_NewEmpty(filename, funcname, py_line); + #endif + Py_XDECREF(py_funcname); // XDECREF since it's only set on Py3 if cline return py_code; bad: - Py_XDECREF(py_srcfile); Py_XDECREF(py_funcname); + #if PY_MAJOR_VERSION < 3 + Py_XDECREF(py_srcfile); + #endif return NULL; } static void __Pyx_AddTraceback(const char *funcname, int c_line, @@ -2758,14 +2918,24 @@ static void __Pyx_AddTraceback(const char *funcname, int c_line, PyCodeObject *py_code = 0; PyFrameObject *py_frame = 0; PyThreadState *tstate = __Pyx_PyThreadState_Current; + PyObject *ptype, *pvalue, *ptraceback; if (c_line) { c_line = __Pyx_CLineForTraceback(tstate, c_line); } py_code = __pyx_find_code_object(c_line ? -c_line : py_line); if (!py_code) { + __Pyx_ErrFetchInState(tstate, &ptype, &pvalue, &ptraceback); py_code = __Pyx_CreateCodeObjectForTraceback( funcname, c_line, py_line, filename); - if (!py_code) goto bad; + if (!py_code) { + /* If the code object creation fails, then we should clear the + fetched exception references and propagate the new exception */ + Py_XDECREF(ptype); + Py_XDECREF(pvalue); + Py_XDECREF(ptraceback); + goto bad; + } + __Pyx_ErrRestoreInState(tstate, ptype, pvalue, ptraceback); __pyx_insert_code_object(c_line ? -c_line : py_line, py_code); } py_frame = PyFrame_New( @@ -2784,7 +2954,14 @@ static void __Pyx_AddTraceback(const char *funcname, int c_line, /* CIntToPy */ static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value) { - const long neg_one = (long) ((long) 0 - (long) 1), const_zero = (long) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +#endif + const long neg_one = (long) -1, const_zero = (long) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic pop +#endif const int is_unsigned = neg_one > const_zero; if (is_unsigned) { if (sizeof(long) < sizeof(long)) { @@ -2837,7 +3014,14 @@ static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value) { /* CIntFromPy */ static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *x) { - const long neg_one = (long) ((long) 0 - (long) 1), const_zero = (long) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +#endif + const long neg_one = (long) -1, const_zero = (long) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic pop +#endif const int is_unsigned = neg_one > const_zero; #if PY_MAJOR_VERSION < 3 if (likely(PyInt_Check(x))) { @@ -3026,7 +3210,14 @@ static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *x) { /* CIntFromPy */ static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *x) { - const int neg_one = (int) ((int) 0 - (int) 1), const_zero = (int) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +#endif + const int neg_one = (int) -1, const_zero = (int) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic pop +#endif const int is_unsigned = neg_one > const_zero; #if PY_MAJOR_VERSION < 3 if (likely(PyInt_Check(x))) { @@ -3315,11 +3506,33 @@ static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches2(PyObject *err, PyObj /* CheckBinaryVersion */ static int __Pyx_check_binary_version(void) { - char ctversion[4], rtversion[4]; - PyOS_snprintf(ctversion, 4, "%d.%d", PY_MAJOR_VERSION, PY_MINOR_VERSION); - PyOS_snprintf(rtversion, 4, "%s", Py_GetVersion()); - if (ctversion[0] != rtversion[0] || ctversion[2] != rtversion[2]) { + char ctversion[5]; + int same=1, i, found_dot; + const char* rt_from_call = Py_GetVersion(); + PyOS_snprintf(ctversion, 5, "%d.%d", PY_MAJOR_VERSION, PY_MINOR_VERSION); + found_dot = 0; + for (i = 0; i < 4; i++) { + if (!ctversion[i]) { + same = (rt_from_call[i] < '0' || rt_from_call[i] > '9'); + break; + } + if (rt_from_call[i] != ctversion[i]) { + same = 0; + break; + } + } + if (!same) { + char rtversion[5] = {'\0'}; char message[200]; + for (i=0; i<4; ++i) { + if (rt_from_call[i] == '.') { + if (found_dot) break; + found_dot = 1; + } else if (rt_from_call[i] < '0' || rt_from_call[i] > '9') { + break; + } + rtversion[i] = rt_from_call[i]; + } PyOS_snprintf(message, sizeof(message), "compiletime version %s of module '%.100s' " "does not match runtime version %s", @@ -3577,6 +3790,23 @@ static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) { Py_DECREF(x); return ival; } +static CYTHON_INLINE Py_hash_t __Pyx_PyIndex_AsHash_t(PyObject* o) { + if (sizeof(Py_hash_t) == sizeof(Py_ssize_t)) { + return (Py_hash_t) __Pyx_PyIndex_AsSsize_t(o); +#if PY_MAJOR_VERSION < 3 + } else if (likely(PyInt_CheckExact(o))) { + return PyInt_AS_LONG(o); +#endif + } else { + Py_ssize_t ival; + PyObject *x; + x = PyNumber_Index(o); + if (!x) return -1; + ival = PyInt_AsLong(x); + Py_DECREF(x); + return ival; + } +} static CYTHON_INLINE PyObject * __Pyx_PyBool_FromLong(long b) { return b ? __Pyx_NewRef(Py_True) : __Pyx_NewRef(Py_False); } diff --git a/aiohttp/abc.py b/aiohttp/abc.py index 4abfd79..44a3bda 100644 --- a/aiohttp/abc.py +++ b/aiohttp/abc.py @@ -135,6 +135,9 @@ async def close(self) -> None: IterableBase = Iterable +ClearCookiePredicate = Callable[["Morsel[str]"], bool] + + class AbstractCookieJar(Sized, IterableBase): """Abstract Cookie Jar.""" @@ -142,8 +145,12 @@ def __init__(self, *, loop: Optional[asyncio.AbstractEventLoop] = None) -> None: self._loop = get_running_loop(loop) @abstractmethod - def clear(self) -> None: - """Clear all cookies.""" + def clear(self, predicate: Optional[ClearCookiePredicate] = None) -> None: + """Clear all cookies if no predicate is passed.""" + + @abstractmethod + def clear_domain(self, domain: str) -> None: + """Clear all cookies for domain and all subdomains.""" @abstractmethod def update_cookies(self, cookies: LooseCookies, response_url: URL = URL()) -> None: @@ -159,7 +166,7 @@ class AbstractStreamWriter(ABC): buffer_size = 0 output_size = 0 - length = 0 # type: Optional[int] + length: Optional[int] = 0 @abstractmethod async def write(self, chunk: bytes) -> None: diff --git a/aiohttp/base_protocol.py b/aiohttp/base_protocol.py index 01e1831..4c9f0a7 100644 --- a/aiohttp/base_protocol.py +++ b/aiohttp/base_protocol.py @@ -15,13 +15,17 @@ class BaseProtocol(asyncio.Protocol): ) def __init__(self, loop: asyncio.AbstractEventLoop) -> None: - self._loop = loop # type: asyncio.AbstractEventLoop + self._loop: asyncio.AbstractEventLoop = loop self._paused = False - self._drain_waiter = None # type: Optional[asyncio.Future[None]] - self._connection_lost = False + self._drain_waiter: Optional[asyncio.Future[None]] = None self._reading_paused = False - self.transport = None # type: Optional[asyncio.Transport] + self.transport: Optional[asyncio.Transport] = None + + @property + def connected(self) -> bool: + """Return True if the connection is open.""" + return self.transport is not None def pause_writing(self) -> None: assert not self._paused @@ -59,7 +63,6 @@ def connection_made(self, transport: asyncio.BaseTransport) -> None: self.transport = tr def connection_lost(self, exc: Optional[BaseException]) -> None: - self._connection_lost = True # Wake up the writer if currently paused. self.transport = None if not self._paused: @@ -76,12 +79,12 @@ def connection_lost(self, exc: Optional[BaseException]) -> None: waiter.set_exception(exc) async def _drain_helper(self) -> None: - if self._connection_lost: + if not self.connected: raise ConnectionResetError("Connection lost") if not self._paused: return waiter = self._drain_waiter - assert waiter is None or waiter.cancelled() - waiter = self._loop.create_future() - self._drain_waiter = waiter - await waiter + if waiter is None: + waiter = self._loop.create_future() + self._drain_waiter = waiter + await asyncio.shield(waiter) diff --git a/aiohttp/client.py b/aiohttp/client.py index a9da8e1..4f56f61 100644 --- a/aiohttp/client.py +++ b/aiohttp/client.py @@ -8,6 +8,7 @@ import sys import traceback import warnings +from contextlib import suppress from types import SimpleNamespace, TracebackType from typing import ( Any, @@ -74,10 +75,10 @@ DEBUG, PY_36, BasicAuth, - CeilTimeout, TimeoutHandle, + ceil_timeout, + get_env_proxy_for_url, get_running_loop, - proxies_from_env, sentinel, strip_auth_from_url, ) @@ -85,7 +86,12 @@ from .http_websocket import WSHandshakeError, WSMessage, ws_ext_gen, ws_ext_parse from .streams import FlowControlDataQueue from .tracing import Trace, TraceConfig -from .typedefs import JSONEncoder, LooseCookies, LooseHeaders, StrOrURL +from .typedefs import Final, JSONEncoder, LooseCookies, LooseHeaders, StrOrURL + +try: + import cchardet as chardet +except ImportError: # pragma: no cover + import charset_normalizer as chardet # type: ignore[no-redef] __all__ = ( # client_exceptions @@ -130,7 +136,7 @@ try: from ssl import SSLContext except ImportError: # pragma: no cover - SSLContext = object # type: ignore + SSLContext = object # type: ignore[misc,assignment] @attr.s(auto_attribs=True, frozen=True, slots=True) @@ -155,9 +161,25 @@ class ClientTimeout: # 5 Minute default read timeout -DEFAULT_TIMEOUT = ClientTimeout(total=5 * 60) +DEFAULT_TIMEOUT: Final[ClientTimeout] = ClientTimeout(total=5 * 60) _RetType = TypeVar("_RetType") +_CharsetResolver = Callable[[ClientResponse, bytes], str] + + +def _default_fallback_charset_resolver(response: ClientResponse, body: bytes) -> str: + + ret: str = chardet.detect(body)["encoding"] or "utf-8" + + if ret != "utf-8": + warnings.warn( + "Automatic charset detection will be removed in 3.9, see: " + "https://docs.aiohttp.org/en/stable/client_advanced.html#character-set-detection", # noqa: E501 + DeprecationWarning, + stacklevel=3, + ) + + return ret class ClientSession: @@ -165,6 +187,7 @@ class ClientSession: ATTRS = frozenset( [ + "_base_url", "_source_traceback", "_connector", "requote_redirect_url", @@ -189,10 +212,12 @@ class ClientSession: ] ) - _source_traceback = None + _source_traceback = None # type: Optional[traceback.StackSummary] + _connector = None # type: Optional[BaseConnector] def __init__( self, + base_url: Optional[StrOrURL] = None, *, connector: Optional[BaseConnector] = None, loop: Optional[asyncio.AbstractEventLoop] = None, @@ -215,15 +240,25 @@ def __init__( trust_env: bool = False, requote_redirect_url: bool = True, trace_configs: Optional[List[TraceConfig]] = None, - read_bufsize: int = 2 ** 16, + read_bufsize: int = 2**16, + fallback_charset_resolver: _CharsetResolver = ( + _default_fallback_charset_resolver + ), ) -> None: - if loop is None: if connector is not None: loop = connector._loop loop = get_running_loop(loop) + if base_url is None or isinstance(base_url, URL): + self._base_url: Optional[URL] = base_url + else: + self._base_url = URL(base_url) + assert ( + self._base_url.origin() == self._base_url + ), "Only absolute URLs without path part are supported" + if connector is None: connector = TCPConnector(loop=loop) @@ -242,7 +277,7 @@ def __init__( if cookies is not None: self._cookie_jar.update_cookies(cookies) - self._connector = connector # type: Optional[BaseConnector] + self._connector = connector self._connector_owner = connector_owner self._default_auth = auth self._version = version @@ -264,7 +299,7 @@ def __init__( stacklevel=2, ) else: - self._timeout = timeout # type: ignore + self._timeout = timeout # type: ignore[assignment] if read_timeout is not sentinel: raise ValueError( "read_timeout and timeout parameters " @@ -285,12 +320,12 @@ def __init__( # Convert to list of tuples if headers: - real_headers = CIMultiDict(headers) # type: CIMultiDict[str] + real_headers: CIMultiDict[str] = CIMultiDict(headers) else: real_headers = CIMultiDict() - self._default_headers = real_headers # type: CIMultiDict[str] + self._default_headers: CIMultiDict[str] = real_headers if skip_auto_headers is not None: - self._skip_auto_headers = frozenset([istr(i) for i in skip_auto_headers]) + self._skip_auto_headers = frozenset(istr(i) for i in skip_auto_headers) else: self._skip_auto_headers = frozenset() @@ -302,6 +337,8 @@ def __init__( for trace_config in self._trace_configs: trace_config.freeze() + self._resolve_charset = fallback_charset_resolver + def __init_subclass__(cls: Type["ClientSession"]) -> None: warnings.warn( "Inheritance class {} from ClientSession " @@ -342,6 +379,14 @@ def request( """Perform HTTP request.""" return _RequestContextManager(self._request(method, url, **kwargs)) + def _build_url(self, str_or_url: StrOrURL) -> URL: + url = URL(str_or_url) + if self._base_url is None: + return url + else: + assert not url.is_absolute() and url.path.startswith("/") + return self._base_url.join(url) + async def _request( self, method: str, @@ -401,7 +446,7 @@ async def _request( proxy_headers = self._prepare_headers(proxy_headers) try: - url = URL(str_or_url) + url = self._build_url(str_or_url) except ValueError as e: raise InvalidURL(str_or_url) from e @@ -417,10 +462,10 @@ async def _request( raise InvalidURL(proxy) from e if timeout is sentinel: - real_timeout = self._timeout # type: ClientTimeout + real_timeout: ClientTimeout = self._timeout else: if not isinstance(timeout, ClientTimeout): - real_timeout = ClientTimeout(total=timeout) # type: ignore + real_timeout = ClientTimeout(total=timeout) # type: ignore[arg-type] else: real_timeout = timeout # timeout is cumulative for all request operations @@ -441,7 +486,7 @@ async def _request( ] for trace in traces: - await trace.send_request_start(method, url, headers) + await trace.send_request_start(method, url.update_query(params), headers) timer = tm.timer() try: @@ -483,11 +528,8 @@ async def _request( if proxy is not None: proxy = URL(proxy) elif self._trust_env: - for scheme, proxy_info in proxies_from_env().items(): - if scheme == url.scheme: - proxy = proxy_info.proxy - proxy_auth = proxy_info.proxy_auth - break + with suppress(LookupError): + proxy, proxy_auth = get_env_proxy_for_url(url) req = self._request_class( method, @@ -515,7 +557,7 @@ async def _request( # connection timeout try: - with CeilTimeout(real_timeout.connect, loop=self._loop): + async with ceil_timeout(real_timeout.connect): assert self._connector is not None conn = await self._connector.connect( req, traces=traces, timeout=real_timeout @@ -551,6 +593,8 @@ async def _request( except ClientError: raise except OSError as exc: + if exc.errno is None and isinstance(exc, asyncio.TimeoutError): + raise raise ClientOSError(*exc.args) from exc self._cookie_jar.update_cookies(resp.cookies, resp.url) @@ -560,7 +604,7 @@ async def _request( for trace in traces: await trace.send_request_redirect( - method, url, headers, resp + method, url.update_query(params), headers, resp ) redirects += 1 @@ -634,7 +678,9 @@ async def _request( resp._history = tuple(history) for trace in traces: - await trace.send_request_end(method, url, headers, resp) + await trace.send_request_end( + method, url.update_query(params), headers, resp + ) return resp except BaseException as e: @@ -645,7 +691,9 @@ async def _request( handle = None for trace in traces: - await trace.send_request_exception(method, url, headers, e) + await trace.send_request_exception( + method, url.update_query(params), headers, e + ) raise def ws_connect( @@ -661,6 +709,7 @@ def ws_connect( heartbeat: Optional[float] = None, auth: Optional[BasicAuth] = None, origin: Optional[str] = None, + params: Optional[Mapping[str, str]] = None, headers: Optional[LooseHeaders] = None, proxy: Optional[StrOrURL] = None, proxy_auth: Optional[BasicAuth] = None, @@ -685,6 +734,7 @@ def ws_connect( heartbeat=heartbeat, auth=auth, origin=origin, + params=params, headers=headers, proxy=proxy, proxy_auth=proxy_auth, @@ -711,6 +761,7 @@ async def _ws_connect( heartbeat: Optional[float] = None, auth: Optional[BasicAuth] = None, origin: Optional[str] = None, + params: Optional[Mapping[str, str]] = None, headers: Optional[LooseHeaders] = None, proxy: Optional[StrOrURL] = None, proxy_auth: Optional[BasicAuth] = None, @@ -724,7 +775,7 @@ async def _ws_connect( ) -> ClientWebSocketResponse: if headers is None: - real_headers = CIMultiDict() # type: CIMultiDict[str] + real_headers: CIMultiDict[str] = CIMultiDict() else: real_headers = CIMultiDict(headers) @@ -754,6 +805,7 @@ async def _ws_connect( resp = await self.request( method, url, + params=params, headers=real_headers, read_until_eof=False, auth=auth, @@ -842,9 +894,9 @@ async def _ws_connect( assert conn_proto is not None transport = conn.transport assert transport is not None - reader = FlowControlDataQueue( - conn_proto, 2 ** 16, loop=self._loop - ) # type: FlowControlDataQueue[WSMessage] + reader: FlowControlDataQueue[WSMessage] = FlowControlDataQueue( + conn_proto, 2**16, loop=self._loop + ) conn_proto.set_parser(WebSocketReader(reader, max_msg_size), reader) writer = WebSocketWriter( conn_proto, @@ -879,7 +931,7 @@ def _prepare_headers(self, headers: Optional[LooseHeaders]) -> "CIMultiDict[str] if headers: if not isinstance(headers, (MultiDictProxy, MultiDict)): headers = CIMultiDict(headers) - added_names = set() # type: Set[str] + added_names: Set[str] = set() for key, value in headers.items(): if key in added_names: result.add(key, value) @@ -1001,7 +1053,7 @@ def loop(self) -> asyncio.AbstractEventLoop: return self._loop @property - def timeout(self) -> Union[object, ClientTimeout]: + def timeout(self) -> ClientTimeout: """Timeout for the session.""" return self._timeout @@ -1034,23 +1086,21 @@ def connector_owner(self) -> bool: def raise_for_status( self, ) -> Union[bool, Callable[[ClientResponse], Awaitable[None]]]: - """ - Should `ClientResponse.raise_for_status()` - be called for each response - """ + """Should `ClientResponse.raise_for_status()` be called for each response.""" return self._raise_for_status @property def auto_decompress(self) -> bool: - """Should the body response be automatically decompressed""" + """Should the body response be automatically decompressed.""" return self._auto_decompress @property def trust_env(self) -> bool: """ - Should get proxies information - from HTTP_PROXY / HTTPS_PROXY environment variables - or ~/.netrc file if present + Should proxies information from environment or netrc be trusted. + + Information is from HTTP_PROXY / HTTPS_PROXY environment variables + or ~/.netrc file if present. """ return self._trust_env @@ -1100,7 +1150,7 @@ def __init__(self, coro: Coroutine["asyncio.Future[Any]", None, _RetType]) -> No def send(self, arg: None) -> "asyncio.Future[Any]": return self._coro.send(arg) - def throw(self, arg: BaseException) -> None: # type: ignore + def throw(self, arg: BaseException) -> None: # type: ignore[arg-type,override] self._coro.throw(arg) def close(self) -> None: @@ -1119,6 +1169,8 @@ async def __aenter__(self) -> _RetType: class _RequestContextManager(_BaseRequestContextManager[ClientResponse]): + __slots__ = () + async def __aexit__( self, exc_type: Optional[Type[BaseException]], @@ -1134,6 +1186,8 @@ async def __aexit__( class _WSRequestContextManager(_BaseRequestContextManager[ClientWebSocketResponse]): + __slots__ = () + async def __aexit__( self, exc_type: Optional[Type[BaseException]], @@ -1153,7 +1207,7 @@ def __init__( session: ClientSession, ) -> None: self._coro = coro - self._resp = None # type: Optional[ClientResponse] + self._resp: Optional[ClientResponse] = None self._session = session async def __aenter__(self) -> ClientResponse: @@ -1202,7 +1256,9 @@ def request( read_bufsize: Optional[int] = None, loop: Optional[asyncio.AbstractEventLoop] = None, ) -> _SessionRequestContextManager: - """Constructs and sends a request. Returns response object. + """Constructs and sends a request. + + Returns response object. method - HTTP method url - request url params - (optional) Dictionary or bytes to be sent in the query diff --git a/aiohttp/client_exceptions.py b/aiohttp/client_exceptions.py index f4be3bf..c640e1e 100644 --- a/aiohttp/client_exceptions.py +++ b/aiohttp/client_exceptions.py @@ -4,6 +4,7 @@ import warnings from typing import TYPE_CHECKING, Any, Optional, Tuple, Union +from .http_parser import RawResponseMessage from .typedefs import LooseHeaders try: @@ -11,7 +12,7 @@ SSLContext = ssl.SSLContext except ImportError: # pragma: no cover - ssl = SSLContext = None # type: ignore + ssl = SSLContext = None # type: ignore[assignment] if TYPE_CHECKING: # pragma: no cover @@ -99,7 +100,7 @@ def __repr__(self) -> str: args += f", message={self.message!r}" if self.headers is not None: args += f", headers={self.headers!r}" - return "{}({})".format(type(self).__name__, args) + return f"{type(self).__name__}({args})" @property def code(self) -> int: @@ -153,7 +154,7 @@ class ClientConnectorError(ClientOSError): """Client connector error. Raised in :class:`aiohttp.connector.TCPConnector` if - connection to proxy can not be established. + a connection can not be established. """ def __init__(self, connection_key: ConnectionKey, os_error: OSError) -> None: @@ -195,6 +196,29 @@ class ClientProxyConnectionError(ClientConnectorError): """ +class UnixClientConnectorError(ClientConnectorError): + """Unix connector error. + + Raised in :py:class:`aiohttp.connector.UnixConnector` + if connection to unix socket can not be established. + """ + + def __init__( + self, path: str, connection_key: ConnectionKey, os_error: OSError + ) -> None: + self._path = path + super().__init__(connection_key, os_error) + + @property + def path(self) -> str: + return self._path + + def __str__(self) -> str: + return "Cannot connect to unix socket {0.path} ssl:{1} [{2}]".format( + self, self.ssl if self.ssl is not None else "default", self.strerror + ) + + class ServerConnectionError(ClientConnectionError): """Server connection errors.""" @@ -202,7 +226,7 @@ class ServerConnectionError(ClientConnectionError): class ServerDisconnectedError(ServerConnectionError): """Server disconnected.""" - def __init__(self, message: Optional[str] = None) -> None: + def __init__(self, message: Union[RawResponseMessage, str, None] = None) -> None: if message is None: message = "Server disconnected" @@ -238,7 +262,8 @@ class InvalidURL(ClientError, ValueError): """Invalid URL. URL used for fetching is malformed, e.g. it doesn't contains host - part.""" + part. + """ # Derive from ValueError for backward compatibility @@ -279,11 +304,11 @@ class ClientSSLError(ClientConnectorError): ssl_error_bases = (ClientSSLError,) -class ClientConnectorSSLError(*ssl_error_bases): # type: ignore +class ClientConnectorSSLError(*ssl_error_bases): # type: ignore[misc] """Response ssl error.""" -class ClientConnectorCertificateError(*cert_errors_bases): # type: ignore +class ClientConnectorCertificateError(*cert_errors_bases): # type: ignore[misc] """Response certificate error.""" def __init__( diff --git a/aiohttp/client_proto.py b/aiohttp/client_proto.py index 2973342..3041157 100644 --- a/aiohttp/client_proto.py +++ b/aiohttp/client_proto.py @@ -23,7 +23,7 @@ def __init__(self, loop: asyncio.AbstractEventLoop) -> None: self._should_close = False - self._payload = None + self._payload: Optional[StreamReader] = None self._skip_payload = False self._payload_parser = None @@ -31,10 +31,10 @@ def __init__(self, loop: asyncio.AbstractEventLoop) -> None: self._tail = b"" self._upgraded = False - self._parser = None # type: Optional[HttpResponseParser] + self._parser: Optional[HttpResponseParser] = None - self._read_timeout = None # type: Optional[float] - self._read_timeout_handle = None # type: Optional[asyncio.TimerHandle] + self._read_timeout: Optional[float] = None + self._read_timeout_handle: Optional[asyncio.TimerHandle] = None @property def upgraded(self) -> bool: @@ -142,7 +142,7 @@ def set_response_params( read_until_eof: bool = False, auto_decompress: bool = True, read_timeout: Optional[float] = None, - read_bufsize: int = 2 ** 16 + read_bufsize: int = 2**16, ) -> None: self._skip_payload = skip_payload @@ -223,7 +223,7 @@ def data_received(self, data: bytes) -> None: self._upgraded = upgraded - payload = None + payload: Optional[StreamReader] = None for message, payload in messages: if message.should_close: self._should_close = True @@ -231,7 +231,7 @@ def data_received(self, data: bytes) -> None: self._payload = payload if self._skip_payload or message.code in (204, 304): - self.feed_data((message, EMPTY_PAYLOAD), 0) # type: ignore + self.feed_data((message, EMPTY_PAYLOAD), 0) else: self.feed_data((message, payload), 0) if payload is not None: diff --git a/aiohttp/client_reqrep.py b/aiohttp/client_reqrep.py index d826bfe..987d68f 100644 --- a/aiohttp/client_reqrep.py +++ b/aiohttp/client_reqrep.py @@ -1,5 +1,6 @@ import asyncio import codecs +import contextlib import functools import io import re @@ -12,6 +13,7 @@ from typing import ( TYPE_CHECKING, Any, + Callable, Dict, Iterable, List, @@ -63,13 +65,8 @@ import ssl from ssl import SSLContext except ImportError: # pragma: no cover - ssl = None # type: ignore - SSLContext = object # type: ignore - -try: - import cchardet as chardet -except ImportError: # pragma: no cover - import chardet # type: ignore + ssl = None # type: ignore[assignment] + SSLContext = object # type: ignore[misc,assignment] __all__ = ("ClientRequest", "ClientResponse", "RequestInfo", "Fingerprint") @@ -294,7 +291,7 @@ def __init__( real_response_class = ClientResponse else: real_response_class = response_class - self.response_class = real_response_class # type: Type[ClientResponse] + self.response_class: Type[ClientResponse] = real_response_class self._timer = timer if timer is not None else TimerNoop() self._ssl = ssl @@ -311,7 +308,7 @@ def __init__( self.update_proxy(proxy, proxy_auth, proxy_headers) self.update_body_from_data(data) - if data or self.method not in self.GET_METHODS: + if data is not None or self.method not in self.GET_METHODS: self.update_transfer_encoding() self.update_expect_continue(expect100) if traces is None: @@ -329,9 +326,7 @@ def ssl(self) -> Union["SSLContext", None, bool, Fingerprint]: def connection_key(self) -> ConnectionKey: proxy_headers = self.proxy_headers if proxy_headers: - h = hash( - tuple((k, v) for k, v in proxy_headers.items()) - ) # type: Optional[int] + h: Optional[int] = hash(tuple((k, v) for k, v in proxy_headers.items())) else: h = None return ConnectionKey( @@ -356,7 +351,7 @@ def port(self) -> Optional[int]: @property def request_info(self) -> RequestInfo: - headers = CIMultiDictProxy(self.headers) # type: CIMultiDictProxy[str] + headers: CIMultiDictProxy[str] = CIMultiDictProxy(self.headers) return RequestInfo(self.url, self.method, headers, self.original_url) def update_host(self, url: URL) -> None: @@ -387,7 +382,7 @@ def update_version(self, version: Union[http.HttpVersion, str]) -> None: def update_headers(self, headers: Optional[LooseHeaders]) -> None: """Update request headers.""" - self.headers = CIMultiDict() # type: CIMultiDict[str] + self.headers: CIMultiDict[str] = CIMultiDict() # add host netloc = cast(str, self.url.raw_host) @@ -399,9 +394,9 @@ def update_headers(self, headers: Optional[LooseHeaders]) -> None: if headers: if isinstance(headers, (dict, MultiDictProxy, MultiDict)): - headers = headers.items() # type: ignore + headers = headers.items() # type: ignore[assignment] - for key, value in headers: # type: ignore + for key, value in headers: # type: ignore[misc] # A special case for Host header if key.lower() == "host": self.headers[key] = value @@ -413,7 +408,7 @@ def update_auto_headers(self, skip_auto_headers: Iterable[str]) -> None: (hdr, None) for hdr in sorted(skip_auto_headers) ) used_headers = self.headers.copy() - used_headers.extend(self.skip_auto_headers) # type: ignore + used_headers.extend(self.skip_auto_headers) # type: ignore[arg-type] for hdr, val in self.DEFAULT_HEADERS.items(): if hdr not in used_headers: @@ -427,7 +422,7 @@ def update_cookies(self, cookies: Optional[LooseCookies]) -> None: if not cookies: return - c = SimpleCookie() # type: SimpleCookie[str] + c: SimpleCookie[str] = SimpleCookie() if hdrs.COOKIE in self.headers: c.load(self.headers.get(hdrs.COOKIE, "")) del self.headers[hdrs.COOKIE] @@ -435,7 +430,7 @@ def update_cookies(self, cookies: Optional[LooseCookies]) -> None: if isinstance(cookies, Mapping): iter_cookies = cookies.items() else: - iter_cookies = cookies # type: ignore + iter_cookies = cookies # type: ignore[assignment] for name, value in iter_cookies: if isinstance(value, Morsel): # Preserve coded_value @@ -443,13 +438,13 @@ def update_cookies(self, cookies: Optional[LooseCookies]) -> None: mrsl_val.set(value.key, value.value, value.coded_value) c[name] = mrsl_val else: - c[name] = value # type: ignore + c[name] = value # type: ignore[assignment] self.headers[hdrs.COOKIE] = c.output(header="", sep=";").strip() def update_content_encoding(self, data: Any) -> None: """Set request content encoding.""" - if not data: + if data is None: return enc = self.headers.get(hdrs.CONTENT_ENCODING, "").lower() @@ -499,7 +494,7 @@ def update_auth(self, auth: Optional[BasicAuth]) -> None: self.headers[hdrs.AUTHORIZATION] = auth.encode() def update_body_from_data(self, body: Any) -> None: - if not body: + if body is None: return # FormData @@ -547,8 +542,6 @@ def update_proxy( proxy_auth: Optional[BasicAuth], proxy_headers: Optional[LooseHeaders], ) -> None: - if proxy and not proxy.scheme == "http": - raise ValueError("Only http proxies are supported") if proxy_auth and not isinstance(proxy_auth, helpers.BasicAuth): raise ValueError("proxy_auth must be None or BasicAuth() tuple") self.proxy = proxy @@ -585,19 +578,22 @@ async def write_bytes( await self.body.write(writer) else: if isinstance(self.body, (bytes, bytearray)): - self.body = (self.body,) # type: ignore + self.body = (self.body,) # type: ignore[assignment] for chunk in self.body: - await writer.write(chunk) # type: ignore + await writer.write(chunk) # type: ignore[arg-type] await writer.write_eof() except OSError as exc: - new_exc = ClientOSError( - exc.errno, "Can not write request body for %s" % self.url - ) - new_exc.__context__ = exc - new_exc.__cause__ = exc - protocol.set_exception(new_exc) + if exc.errno is None and isinstance(exc, asyncio.TimeoutError): + protocol.set_exception(exc) + else: + new_exc = ClientOSError( + exc.errno, "Can not write request body for %s" % self.url + ) + new_exc.__context__ = exc + new_exc.__cause__ = exc + protocol.set_exception(new_exc) except asyncio.CancelledError as exc: if not conn.closed: protocol.set_exception(exc) @@ -632,6 +628,9 @@ async def send(self, conn: "Connection") -> "ClientResponse": on_chunk_sent=functools.partial( self._on_chunk_request_sent, self.method, self.url ), + on_headers_sent=functools.partial( + self._on_headers_request_sent, self.method, self.url + ), ) if self.compress: @@ -701,21 +700,27 @@ async def _on_chunk_request_sent(self, method: str, url: URL, chunk: bytes) -> N for trace in self._traces: await trace.send_request_chunk_sent(method, url, chunk) + async def _on_headers_request_sent( + self, method: str, url: URL, headers: "CIMultiDict[str]" + ) -> None: + for trace in self._traces: + await trace.send_request_headers(method, url, headers) + class ClientResponse(HeadersMixin): # from the Status-Line of the response version = None # HTTP-Version - status = None # type: int # Status-Code + status: int = None # type: ignore[assignment] # Status-Code reason = None # Reason-Phrase - content = None # type: StreamReader # Payload stream - _headers = None # type: CIMultiDictProxy[str] # Response headers - _raw_headers = None # type: RawHeaders # Response raw headers + content: StreamReader = None # type: ignore[assignment] # Payload stream + _headers: "CIMultiDictProxy[str]" = None # type: ignore[assignment] + _raw_headers: RawHeaders = None # type: ignore[assignment] # Response raw headers _connection = None # current connection - _source_traceback = None - # setted up by ClientRequest after ClientResponse object creation + _source_traceback: Optional[traceback.StackSummary] = None + # set up by ClientRequest after ClientResponse object creation # post-init stage allows to not change ctor signature _closed = True # to allow __del__ for non-initialized properly response _released = False @@ -736,22 +741,31 @@ def __init__( assert isinstance(url, URL) self.method = method - self.cookies = SimpleCookie() # type: SimpleCookie[str] + self.cookies: SimpleCookie[str] = SimpleCookie() self._real_url = url self._url = url.with_fragment(None) - self._body = None # type: Any - self._writer = writer # type: Optional[asyncio.Task[None]] + self._body: Any = None + self._writer: Optional[asyncio.Task[None]] = writer self._continue = continue100 # None by default self._closed = True - self._history = () # type: Tuple[ClientResponse, ...] + self._history: Tuple[ClientResponse, ...] = () self._request_info = request_info self._timer = timer if timer is not None else TimerNoop() - self._cache = {} # type: Dict[str, Any] + self._cache: Dict[str, Any] = {} self._traces = traces self._loop = loop # store a reference to session #1985 - self._session = session # type: Optional[ClientSession] + self._session: Optional[ClientSession] = session + # Save reference to _resolve_charset, so that get_encoding() will still + # work after the response has finished reading the body. + if session is None: + # TODO: Fix session=None in tests (see ClientRequest.__init__). + self._resolve_charset: Callable[ + ["ClientResponse", bytes], str + ] = lambda *_: "utf-8" + else: + self._resolve_charset = session._resolve_charset if loop.get_debug(): self._source_traceback = traceback.extract_stack(sys._getframe(1)) @@ -848,7 +862,7 @@ def links(self) -> "MultiDictProxy[MultiDictProxy[Union[str, URL]]]": if not links_str: return MultiDictProxy(MultiDict()) - links = MultiDict() # type: MultiDict[MultiDictProxy[Union[str, URL]]] + links: MultiDict[MultiDictProxy[Union[str, URL]]] = MultiDict() for val in re.split(r",(?=\s*<)", links_str): match = re.match(r"\s*<(.*)>(.*)", val) @@ -858,7 +872,7 @@ def links(self) -> "MultiDictProxy[MultiDictProxy[Union[str, URL]]]": url, params_str = match.groups() params = params_str.split(";")[1:] - link = MultiDict() # type: MultiDict[Union[str, URL]] + link: MultiDict[Union[str, URL]] = MultiDict() for param in params: match = re.match(r"^\s*(\S*)\s*=\s*(['\"]?)(.*?)(\2)\s*$", param, re.M) @@ -869,7 +883,7 @@ def links(self) -> "MultiDictProxy[MultiDictProxy[Union[str, URL]]]": link.add(key, value) - key = link.get("rel", url) # type: ignore + key = link.get("rel", url) # type: ignore[assignment] link.add("url", self.url.join(URL(url))) @@ -887,7 +901,8 @@ async def start(self, connection: "Connection") -> "ClientResponse": while True: # read response try: - message, payload = await self._protocol.read() # type: ignore + protocol = self._protocol + message, payload = await protocol.read() # type: ignore[union-attr] except http.HttpProcessingError as exc: raise ClientResponseError( self.request_info, @@ -986,14 +1001,10 @@ def ok(self) -> bool: This is **not** a check for ``200 OK`` but a check that the response status is under 400. """ - try: - self.raise_for_status() - except ClientResponseError: - return False - return True + return 400 > self.status def raise_for_status(self) -> None: - if 400 <= self.status: + if not self.ok: # reason should always be not None for a started response assert self.reason is not None self.release() @@ -1040,7 +1051,7 @@ async def read(self) -> bytes: elif self._released: raise ClientConnectionError("Connection closed") - return self._body + return self._body # type: ignore[no-any-return] def get_encoding(self) -> str: ctype = self.headers.get(hdrs.CONTENT_TYPE, "").lower() @@ -1048,27 +1059,22 @@ def get_encoding(self) -> str: encoding = mimetype.parameters.get("charset") if encoding: - try: - codecs.lookup(encoding) - except LookupError: - encoding = None - if not encoding: - if mimetype.type == "application" and ( - mimetype.subtype == "json" or mimetype.subtype == "rdap" - ): - # RFC 7159 states that the default encoding is UTF-8. - # RFC 7483 defines application/rdap+json - encoding = "utf-8" - elif self._body is None: - raise RuntimeError( - "Cannot guess the encoding of " "a not yet read body" - ) - else: - encoding = chardet.detect(self._body)["encoding"] - if not encoding: - encoding = "utf-8" + with contextlib.suppress(LookupError): + return codecs.lookup(encoding).name - return encoding + if mimetype.type == "application" and ( + mimetype.subtype == "json" or mimetype.subtype == "rdap" + ): + # RFC 7159 states that the default encoding is UTF-8. + # RFC 7483 defines application/rdap+json + return "utf-8" + + if self._body is None: + raise RuntimeError( + "Cannot compute fallback encoding of a not yet read body" + ) + + return self._resolve_charset(self, self._body) async def text(self, encoding: Optional[str] = None, errors: str = "strict") -> str: """Read response payload and decode.""" @@ -1078,7 +1084,9 @@ async def text(self, encoding: Optional[str] = None, errors: str = "strict") -> if encoding is None: encoding = self.get_encoding() - return self._body.decode(encoding, errors=errors) # type: ignore + return self._body.decode( # type: ignore[no-any-return,union-attr] + encoding, errors=errors + ) async def json( self, @@ -1103,7 +1111,7 @@ async def json( headers=self.headers, ) - stripped = self._body.strip() # type: ignore + stripped = self._body.strip() # type: ignore[union-attr] if not stripped: return None diff --git a/aiohttp/client_ws.py b/aiohttp/client_ws.py index 28fa371..9a8ba84 100644 --- a/aiohttp/client_ws.py +++ b/aiohttp/client_ws.py @@ -1,7 +1,7 @@ """WebSocket client for asyncio.""" import asyncio -from typing import Any, Optional +from typing import Any, Optional, cast import async_timeout @@ -12,6 +12,7 @@ WS_CLOSED_MESSAGE, WS_CLOSING_MESSAGE, WebSocketError, + WSCloseCode, WSMessage, WSMsgType, ) @@ -50,19 +51,19 @@ def __init__( self._protocol = protocol self._closed = False self._closing = False - self._close_code = None # type: Optional[int] + self._close_code: Optional[int] = None self._timeout = timeout self._receive_timeout = receive_timeout self._autoclose = autoclose self._autoping = autoping self._heartbeat = heartbeat - self._heartbeat_cb = None + self._heartbeat_cb: Optional[asyncio.TimerHandle] = None if heartbeat is not None: self._pong_heartbeat = heartbeat / 2.0 - self._pong_response_cb = None + self._pong_response_cb: Optional[asyncio.TimerHandle] = None self._loop = loop - self._waiting = None # type: Optional[asyncio.Future[bool]] - self._exception = None # type: Optional[BaseException] + self._waiting: Optional[asyncio.Future[bool]] = None + self._exception: Optional[BaseException] = None self._compress = compress self._client_notakeover = client_notakeover @@ -101,7 +102,7 @@ def _send_heartbeat(self) -> None: def _pong_not_received(self) -> None: if not self._closed: self._closed = True - self._close_code = 1006 + self._close_code = WSCloseCode.ABNORMAL_CLOSURE self._exception = asyncio.TimeoutError() self._response.close() @@ -163,7 +164,7 @@ async def send_json( ) -> None: await self.send_str(dumps(data), compress=compress) - async def close(self, *, code: int = 1000, message: bytes = b"") -> bool: + async def close(self, *, code: int = WSCloseCode.OK, message: bytes = b"") -> bool: # we need to break `receive()` cycle first, # `close()` may be called from different task if self._waiting is not None and not self._closed: @@ -176,11 +177,11 @@ async def close(self, *, code: int = 1000, message: bytes = b"") -> bool: try: await self._writer.close(code, message) except asyncio.CancelledError: - self._close_code = 1006 + self._close_code = WSCloseCode.ABNORMAL_CLOSURE self._response.close() raise except Exception as exc: - self._close_code = 1006 + self._close_code = WSCloseCode.ABNORMAL_CLOSURE self._exception = exc self._response.close() return True @@ -191,14 +192,14 @@ async def close(self, *, code: int = 1000, message: bytes = b"") -> bool: while True: try: - with async_timeout.timeout(self._timeout, loop=self._loop): + async with async_timeout.timeout(self._timeout): msg = await self._reader.read() except asyncio.CancelledError: - self._close_code = 1006 + self._close_code = WSCloseCode.ABNORMAL_CLOSURE self._response.close() raise except Exception as exc: - self._close_code = 1006 + self._close_code = WSCloseCode.ABNORMAL_CLOSURE self._exception = exc self._response.close() return True @@ -224,9 +225,7 @@ async def receive(self, timeout: Optional[float] = None) -> WSMessage: try: self._waiting = self._loop.create_future() try: - with async_timeout.timeout( - timeout or self._receive_timeout, loop=self._loop - ): + async with async_timeout.timeout(timeout or self._receive_timeout): msg = await self._reader.read() self._reset_heartbeat() finally: @@ -234,15 +233,15 @@ async def receive(self, timeout: Optional[float] = None) -> WSMessage: self._waiting = None set_result(waiter, True) except (asyncio.CancelledError, asyncio.TimeoutError): - self._close_code = 1006 + self._close_code = WSCloseCode.ABNORMAL_CLOSURE raise except EofStream: - self._close_code = 1000 + self._close_code = WSCloseCode.OK await self.close() return WSMessage(WSMsgType.CLOSED, None, None) except ClientError: self._closed = True - self._close_code = 1006 + self._close_code = WSCloseCode.ABNORMAL_CLOSURE return WS_CLOSED_MESSAGE except WebSocketError as exc: self._close_code = exc.code @@ -251,7 +250,7 @@ async def receive(self, timeout: Optional[float] = None) -> WSMessage: except Exception as exc: self._exception = exc self._closing = True - self._close_code = 1006 + self._close_code = WSCloseCode.ABNORMAL_CLOSURE await self.close() return WSMessage(WSMsgType.ERROR, exc, None) @@ -274,13 +273,13 @@ async def receive_str(self, *, timeout: Optional[float] = None) -> str: msg = await self.receive(timeout) if msg.type != WSMsgType.TEXT: raise TypeError(f"Received message {msg.type}:{msg.data!r} is not str") - return msg.data + return cast(str, msg.data) async def receive_bytes(self, *, timeout: Optional[float] = None) -> bytes: msg = await self.receive(timeout) if msg.type != WSMsgType.BINARY: raise TypeError(f"Received message {msg.type}:{msg.data!r} is not bytes") - return msg.data + return cast(bytes, msg.data) async def receive_json( self, diff --git a/aiohttp/connector.py b/aiohttp/connector.py index 748b22a..2499a2d 100644 --- a/aiohttp/connector.py +++ b/aiohttp/connector.py @@ -39,12 +39,20 @@ ClientHttpProxyError, ClientProxyConnectionError, ServerFingerprintMismatch, + UnixClientConnectorError, cert_errors, ssl_errors, ) from .client_proto import ResponseHandler from .client_reqrep import ClientRequest, Fingerprint, _merge_ssl_params -from .helpers import PY_36, CeilTimeout, get_running_loop, is_ip_address, noop, sentinel +from .helpers import ( + PY_36, + ceil_timeout, + get_running_loop, + is_ip_address, + noop, + sentinel, +) from .http import RESPONSES from .locks import EventResultOrError from .resolver import DefaultResolver @@ -54,8 +62,8 @@ SSLContext = ssl.SSLContext except ImportError: # pragma: no cover - ssl = None # type: ignore - SSLContext = object # type: ignore + ssl = None # type: ignore[assignment] + SSLContext = object # type: ignore[misc,assignment] __all__ = ("BaseConnector", "TCPConnector", "UnixConnector", "NamedPipeConnector") @@ -102,8 +110,8 @@ def __init__( self._key = key self._connector = connector self._loop = loop - self._protocol = protocol # type: Optional[ResponseHandler] - self._callbacks = [] # type: List[Callable[[], None]] + self._protocol: Optional[ResponseHandler] = protocol + self._callbacks: List[Callable[[], None]] = [] if loop.get_debug(): self._source_traceback = traceback.extract_stack(sys._getframe(1)) @@ -178,7 +186,7 @@ def closed(self) -> bool: class _TransportPlaceholder: - """ placeholder for BaseConnector.connect function """ + """placeholder for BaseConnector.connect function""" def close(self) -> None: pass @@ -229,33 +237,31 @@ def __init__( if loop.get_debug(): self._source_traceback = traceback.extract_stack(sys._getframe(1)) - self._conns = ( - {} - ) # type: Dict[ConnectionKey, List[Tuple[ResponseHandler, float]]] + self._conns: Dict[ConnectionKey, List[Tuple[ResponseHandler, float]]] = {} self._limit = limit self._limit_per_host = limit_per_host - self._acquired = set() # type: Set[ResponseHandler] - self._acquired_per_host = defaultdict( - set - ) # type: DefaultDict[ConnectionKey, Set[ResponseHandler]] + self._acquired: Set[ResponseHandler] = set() + self._acquired_per_host: DefaultDict[ + ConnectionKey, Set[ResponseHandler] + ] = defaultdict(set) self._keepalive_timeout = cast(float, keepalive_timeout) self._force_close = force_close # {host_key: FIFO list of waiters} - self._waiters = defaultdict(deque) # type: ignore + self._waiters = defaultdict(deque) # type: ignore[var-annotated] self._loop = loop self._factory = functools.partial(ResponseHandler, loop=loop) - self.cookies = SimpleCookie() # type: SimpleCookie[str] + self.cookies: SimpleCookie[str] = SimpleCookie() # start keep-alive connection cleanup task - self._cleanup_handle = None + self._cleanup_handle: Optional[asyncio.TimerHandle] = None # start cleanup closed transports task - self._cleanup_closed_handle = None + self._cleanup_closed_handle: Optional[asyncio.TimerHandle] = None self._cleanup_closed_disabled = not enable_cleanup_closed - self._cleanup_closed_transports = [] # type: List[Optional[asyncio.Transport]] + self._cleanup_closed_transports: List[Optional[asyncio.Transport]] = [] self._cleanup_closed() def __del__(self, _warnings: Any = warnings) -> None: @@ -284,14 +290,14 @@ def __del__(self, _warnings: Any = warnings) -> None: def __enter__(self) -> "BaseConnector": warnings.warn( - '"witn Connector():" is deprecated, ' + '"with Connector():" is deprecated, ' 'use "async with Connector():" instead', DeprecationWarning, ) return self def __exit__(self, *exc: Any) -> None: - self.close() + self._close() async def __aenter__(self) -> "BaseConnector": return self @@ -320,12 +326,10 @@ def limit(self) -> int: @property def limit_per_host(self) -> int: - """The limit_per_host for simultaneous connections - to the same endpoint. + """The limit for simultaneous connections to the same endpoint. Endpoints are the same if they are have equal (host, port, is_ssl) triple. - """ return self._limit_per_host @@ -383,6 +387,7 @@ def _drop_acquired_per_host( def _cleanup_closed(self) -> None: """Double confirmation for transport close. + Some broken ssl servers may leave socket open without proper close. """ if self._cleanup_closed_handle: @@ -451,13 +456,13 @@ def closed(self) -> bool: def _available_connections(self, key: "ConnectionKey") -> int: """ - Return number of available connections taking into account - the limit, limit_per_host and the connection key. + Return number of available connections. - If it returns less than 1 means that there is no connections - availables. - """ + The limit, limit_per_host and the connection key are taken into account. + If it returns less than 1 means that there are no connections + available. + """ if self._limit: # total calc available connections available = self._limit - len(self._acquired) @@ -552,8 +557,14 @@ async def connect( await trace.send_connection_create_end() else: if traces: + # Acquire the connection to prevent race conditions with limits + placeholder = cast(ResponseHandler, _TransportPlaceholder()) + self._acquired.add(placeholder) + self._acquired_per_host[key].add(placeholder) for trace in traces: await trace.send_connection_reuseconn() + self._acquired.remove(placeholder) + self._drop_acquired_per_host(key, placeholder) self._acquired.add(proto) self._acquired_per_host[key].add(proto) @@ -592,7 +603,9 @@ def _get(self, key: "ConnectionKey") -> Optional[ResponseHandler]: def _release_waiter(self) -> None: """ - Iterates over all waiters till found one that is not finsihed and + Iterates over all waiters until one to be released is found. + + The one to be released is not finsihed and belongs to a host that has available connections. """ if not self._waiters: @@ -670,10 +683,8 @@ async def _create_connection( class _DNSCacheTable: def __init__(self, ttl: Optional[float] = None) -> None: - self._addrs_rr = ( - {} - ) # type: Dict[Tuple[str, int], Tuple[Iterator[Dict[str, Any]], int]] - self._timestamps = {} # type: Dict[Tuple[str, int], float] + self._addrs_rr: Dict[Tuple[str, int], Tuple[Iterator[Dict[str, Any]], int]] = {} + self._timestamps: Dict[Tuple[str, int], float] = {} self._ttl = ttl def __contains__(self, host: object) -> bool: @@ -769,9 +780,7 @@ def __init__( self._use_dns_cache = use_dns_cache self._cached_hosts = _DNSCacheTable(ttl=ttl_dns_cache) - self._throttle_dns_events = ( - {} - ) # type: Dict[Tuple[str, int], EventResultOrError] + self._throttle_dns_events: Dict[Tuple[str, int], EventResultOrError] = {} self._family = family self._local_addr = local_addr @@ -899,9 +908,11 @@ def _make_ssl_context(verified: bool) -> SSLContext: if verified: return ssl.create_default_context() else: - sslcontext = ssl.SSLContext(ssl.PROTOCOL_SSLv23) + sslcontext = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) sslcontext.options |= ssl.OP_NO_SSLv2 sslcontext.options |= ssl.OP_NO_SSLv3 + sslcontext.check_hostname = False + sslcontext.verify_mode = ssl.CERT_NONE try: sslcontext.options |= ssl.OP_NO_COMPRESSION except AttributeError as attr_err: @@ -965,15 +976,160 @@ async def _wrap_create_connection( **kwargs: Any, ) -> Tuple[asyncio.Transport, ResponseHandler]: try: - with CeilTimeout(timeout.sock_connect): - return await self._loop.create_connection(*args, **kwargs) # type: ignore # noqa + async with ceil_timeout(timeout.sock_connect): + return await self._loop.create_connection(*args, **kwargs) # type: ignore[return-value] # noqa except cert_errors as exc: raise ClientConnectorCertificateError(req.connection_key, exc) from exc except ssl_errors as exc: raise ClientConnectorSSLError(req.connection_key, exc) from exc except OSError as exc: + if exc.errno is None and isinstance(exc, asyncio.TimeoutError): + raise raise client_error(req.connection_key, exc) from exc + def _fail_on_no_start_tls(self, req: "ClientRequest") -> None: + """Raise a :py:exc:`RuntimeError` on missing ``start_tls()``. + + One case is that :py:meth:`asyncio.loop.start_tls` is not yet + implemented under Python 3.6. It is necessary for TLS-in-TLS so + that it is possible to send HTTPS queries through HTTPS proxies. + + This doesn't affect regular HTTP requests, though. + """ + if not req.is_ssl(): + return + + proxy_url = req.proxy + assert proxy_url is not None + if proxy_url.scheme != "https": + return + + self._check_loop_for_start_tls() + + def _check_loop_for_start_tls(self) -> None: + try: + self._loop.start_tls + except AttributeError as attr_exc: + raise RuntimeError( + "An HTTPS request is being sent through an HTTPS proxy. " + "This needs support for TLS in TLS but it is not implemented " + "in your runtime for the stdlib asyncio.\n\n" + "Please upgrade to Python 3.7 or higher. For more details, " + "please see:\n" + "* https://bugs.python.org/issue37179\n" + "* https://github.com/python/cpython/pull/28073\n" + "* https://docs.aiohttp.org/en/stable/" + "client_advanced.html#proxy-support\n" + "* https://github.com/aio-libs/aiohttp/discussions/6044\n", + ) from attr_exc + + def _loop_supports_start_tls(self) -> bool: + try: + self._check_loop_for_start_tls() + except RuntimeError: + return False + else: + return True + + def _warn_about_tls_in_tls( + self, + underlying_transport: asyncio.Transport, + req: "ClientRequest", + ) -> None: + """Issue a warning if the requested URL has HTTPS scheme.""" + if req.request_info.url.scheme != "https": + return + + asyncio_supports_tls_in_tls = getattr( + underlying_transport, + "_start_tls_compatible", + False, + ) + + if asyncio_supports_tls_in_tls: + return + + warnings.warn( + "An HTTPS request is being sent through an HTTPS proxy. " + "This support for TLS in TLS is known to be disabled " + "in the stdlib asyncio. This is why you'll probably see " + "an error in the log below.\n\n" + "It is possible to enable it via monkeypatching under " + "Python 3.7 or higher. For more details, see:\n" + "* https://bugs.python.org/issue37179\n" + "* https://github.com/python/cpython/pull/28073\n\n" + "You can temporarily patch this as follows:\n" + "* https://docs.aiohttp.org/en/stable/client_advanced.html#proxy-support\n" + "* https://github.com/aio-libs/aiohttp/discussions/6044\n", + RuntimeWarning, + source=self, + # Why `4`? At least 3 of the calls in the stack originate + # from the methods in this class. + stacklevel=3, + ) + + async def _start_tls_connection( + self, + underlying_transport: asyncio.Transport, + req: "ClientRequest", + timeout: "ClientTimeout", + client_error: Type[Exception] = ClientConnectorError, + ) -> Tuple[asyncio.BaseTransport, ResponseHandler]: + """Wrap the raw TCP transport with TLS.""" + tls_proto = self._factory() # Create a brand new proto for TLS + + # Safety of the `cast()` call here is based on the fact that + # internally `_get_ssl_context()` only returns `None` when + # `req.is_ssl()` evaluates to `False` which is never gonna happen + # in this code path. Of course, it's rather fragile + # maintainability-wise but this is to be solved separately. + sslcontext = cast(ssl.SSLContext, self._get_ssl_context(req)) + + try: + async with ceil_timeout(timeout.sock_connect): + try: + tls_transport = await self._loop.start_tls( + underlying_transport, + tls_proto, + sslcontext, + server_hostname=req.host, + ssl_handshake_timeout=timeout.total, + ) + except BaseException: + # We need to close the underlying transport since + # `start_tls()` probably failed before it had a + # chance to do this: + underlying_transport.close() + raise + except cert_errors as exc: + raise ClientConnectorCertificateError(req.connection_key, exc) from exc + except ssl_errors as exc: + raise ClientConnectorSSLError(req.connection_key, exc) from exc + except OSError as exc: + if exc.errno is None and isinstance(exc, asyncio.TimeoutError): + raise + raise client_error(req.connection_key, exc) from exc + except TypeError as type_err: + # Example cause looks like this: + # TypeError: transport is not supported by start_tls() + + raise ClientConnectionError( + "Cannot initialize a TLS-in-TLS connection to host " + f"{req.host!s}:{req.port:d} through an underlying connection " + f"to an HTTPS proxy {req.proxy!s} ssl:{req.ssl or 'default'} " + f"[{type_err!s}]" + ) from type_err + else: + if tls_transport is None: + msg = "Failed to start TLS (possibly caused by closing transport)" + raise client_error(req.connection_key, OSError(msg)) + tls_proto.connection_made( + tls_transport + ) # Kick the state machine of the new TLS protocol + + return tls_transport, tls_proto + async def _create_direct_connection( self, req: "ClientRequest", @@ -1006,11 +1162,13 @@ def drop_exception(fut: "asyncio.Future[List[Dict[str, Any]]]") -> None: host_resolved.add_done_callback(drop_exception) raise except OSError as exc: + if exc.errno is None and isinstance(exc, asyncio.TimeoutError): + raise # in case of proxy it is not ClientProxyConnectionError # it is problem of resolving proxy ip itself raise ClientConnectorError(req.connection_key, exc) from exc - last_exc = None # type: Optional[Exception] + last_exc: Optional[Exception] = None for hinfo in hosts: host = hinfo["host"] @@ -1052,10 +1210,13 @@ def drop_exception(fut: "asyncio.Future[List[Dict[str, Any]]]") -> None: async def _create_proxy_connection( self, req: "ClientRequest", traces: List["Trace"], timeout: "ClientTimeout" - ) -> Tuple[asyncio.Transport, ResponseHandler]: - headers = {} # type: Dict[str, str] + ) -> Tuple[asyncio.BaseTransport, ResponseHandler]: + self._fail_on_no_start_tls(req) + runtime_has_start_tls = self._loop_supports_start_tls() + + headers: Dict[str, str] = {} if req.proxy_headers is not None: - headers = req.proxy_headers # type: ignore + headers = req.proxy_headers # type: ignore[assignment] headers[hdrs.HOST] = req.headers[hdrs.HOST] url = req.proxy @@ -1087,7 +1248,9 @@ async def _create_proxy_connection( proxy_req.headers[hdrs.PROXY_AUTHORIZATION] = auth if req.is_ssl(): - sslcontext = self._get_ssl_context(req) + if runtime_has_start_tls: + self._warn_about_tls_in_tls(transport, req) + # For HTTPS requests over HTTP proxy # we must notify proxy to tunnel connection # so we send CONNECT command: @@ -1107,7 +1270,11 @@ async def _create_proxy_connection( try: protocol = conn._protocol assert protocol is not None - protocol.set_response_params() + + # read_until_eof=True will ensure the connection isn't closed + # once the response is received and processed allowing + # START_TLS to work on the connection below. + protocol.set_response_params(read_until_eof=runtime_has_start_tls) resp = await proxy_resp.start(conn) except BaseException: proxy_resp.close() @@ -1128,21 +1295,42 @@ async def _create_proxy_connection( message=message, headers=resp.headers, ) - rawsock = transport.get_extra_info("socket", default=None) - if rawsock is None: - raise RuntimeError("Transport does not expose socket instance") - # Duplicate the socket, so now we can close proxy transport - rawsock = rawsock.dup() - finally: + if not runtime_has_start_tls: + rawsock = transport.get_extra_info("socket", default=None) + if rawsock is None: + raise RuntimeError( + "Transport does not expose socket instance" + ) + # Duplicate the socket, so now we can close proxy transport + rawsock = rawsock.dup() + except BaseException: + # It shouldn't be closed in `finally` because it's fed to + # `loop.start_tls()` and the docs say not to touch it after + # passing there. transport.close() - - transport, proto = await self._wrap_create_connection( - self._factory, - timeout=timeout, - ssl=sslcontext, - sock=rawsock, - server_hostname=req.host, + raise + finally: + if not runtime_has_start_tls: + transport.close() + + if not runtime_has_start_tls: + # HTTP proxy with support for upgrade to HTTPS + sslcontext = self._get_ssl_context(req) + return await self._wrap_create_connection( + self._factory, + timeout=timeout, + ssl=sslcontext, + sock=rawsock, + server_hostname=req.host, + req=req, + ) + + return await self._start_tls_connection( + # Access the old transport for the last time before it's + # closed and forgotten forever: + transport, req=req, + timeout=timeout, ) finally: proxy_resp.close() @@ -1189,12 +1377,14 @@ async def _create_connection( self, req: "ClientRequest", traces: List["Trace"], timeout: "ClientTimeout" ) -> ResponseHandler: try: - with CeilTimeout(timeout.sock_connect): + async with ceil_timeout(timeout.sock_connect): _, proto = await self._loop.create_unix_connection( self._factory, self._path ) except OSError as exc: - raise ClientConnectorError(req.connection_key, exc) from exc + if exc.errno is None and isinstance(exc, asyncio.TimeoutError): + raise + raise UnixClientConnectorError(self.path, req.connection_key, exc) from exc return cast(ResponseHandler, proto) @@ -1230,7 +1420,9 @@ def __init__( limit_per_host=limit_per_host, loop=loop, ) - if not isinstance(self._loop, asyncio.ProactorEventLoop): # type: ignore + if not isinstance( + self._loop, asyncio.ProactorEventLoop # type: ignore[attr-defined] + ): raise RuntimeError( "Named Pipes only available in proactor " "loop under windows" ) @@ -1245,8 +1437,8 @@ async def _create_connection( self, req: "ClientRequest", traces: List["Trace"], timeout: "ClientTimeout" ) -> ResponseHandler: try: - with CeilTimeout(timeout.sock_connect): - _, proto = await self._loop.create_pipe_connection( # type: ignore + async with ceil_timeout(timeout.sock_connect): + _, proto = await self._loop.create_pipe_connection( # type: ignore[attr-defined] # noqa: E501 self._factory, self._path ) # the drain is required so that the connection_made is called @@ -1257,6 +1449,8 @@ async def _create_connection( # other option is to manually set transport like # `proto.transport = trans` except OSError as exc: + if exc.errno is None and isinstance(exc, asyncio.TimeoutError): + raise raise ClientConnectorError(req.connection_key, exc) from exc return cast(ResponseHandler, proto) diff --git a/aiohttp/cookiejar.py b/aiohttp/cookiejar.py index b6b59d6..e395b74 100644 --- a/aiohttp/cookiejar.py +++ b/aiohttp/cookiejar.py @@ -1,4 +1,5 @@ import asyncio +import contextlib import datetime import os # noqa import pathlib @@ -11,6 +12,7 @@ Dict, Iterable, Iterator, + List, Mapping, Optional, Set, @@ -21,9 +23,9 @@ from yarl import URL -from .abc import AbstractCookieJar +from .abc import AbstractCookieJar, ClearCookiePredicate from .helpers import is_ip_address, next_whole_second -from .typedefs import LooseCookies, PathLike +from .typedefs import LooseCookies, PathLike, StrOrURL __all__ = ("CookieJar", "DummyCookieJar") @@ -52,24 +54,37 @@ class CookieJar(AbstractCookieJar): MAX_TIME = datetime.datetime.max.replace(tzinfo=datetime.timezone.utc) - MAX_32BIT_TIME = datetime.datetime.utcfromtimestamp(2 ** 31 - 1) + MAX_32BIT_TIME = datetime.datetime.utcfromtimestamp(2**31 - 1) def __init__( self, *, unsafe: bool = False, quote_cookie: bool = True, - loop: Optional[asyncio.AbstractEventLoop] = None + treat_as_secure_origin: Union[StrOrURL, List[StrOrURL], None] = None, + loop: Optional[asyncio.AbstractEventLoop] = None, ) -> None: super().__init__(loop=loop) - self._cookies = defaultdict( + self._cookies: DefaultDict[Tuple[str, str], SimpleCookie[str]] = defaultdict( SimpleCookie - ) # type: DefaultDict[str, SimpleCookie[str]] - self._host_only_cookies = set() # type: Set[Tuple[str, str]] + ) + self._host_only_cookies: Set[Tuple[str, str]] = set() self._unsafe = unsafe self._quote_cookie = quote_cookie + if treat_as_secure_origin is None: + treat_as_secure_origin = [] + elif isinstance(treat_as_secure_origin, URL): + treat_as_secure_origin = [treat_as_secure_origin.origin()] + elif isinstance(treat_as_secure_origin, str): + treat_as_secure_origin = [URL(treat_as_secure_origin).origin()] + else: + treat_as_secure_origin = [ + URL(url).origin() if isinstance(url, str) else url.origin() + for url in treat_as_secure_origin + ] + self._treat_as_secure_origin = treat_as_secure_origin self._next_expiration = next_whole_second() - self._expirations = {} # type: Dict[Tuple[str, str], datetime.datetime] + self._expirations: Dict[Tuple[str, str, str], datetime.datetime] = {} # #4515: datetime.max may not be representable on 32-bit platforms self._max_time = self.MAX_TIME try: @@ -87,11 +102,41 @@ def load(self, file_path: PathLike) -> None: with file_path.open(mode="rb") as f: self._cookies = pickle.load(f) - def clear(self) -> None: - self._cookies.clear() - self._host_only_cookies.clear() - self._next_expiration = next_whole_second() - self._expirations.clear() + def clear(self, predicate: Optional[ClearCookiePredicate] = None) -> None: + if predicate is None: + self._next_expiration = next_whole_second() + self._cookies.clear() + self._host_only_cookies.clear() + self._expirations.clear() + return + + to_del = [] + now = datetime.datetime.now(datetime.timezone.utc) + for (domain, path), cookie in self._cookies.items(): + for name, morsel in cookie.items(): + key = (domain, path, name) + if ( + key in self._expirations and self._expirations[key] <= now + ) or predicate(morsel): + to_del.append(key) + + for domain, path, name in to_del: + self._host_only_cookies.discard((domain, name)) + key = (domain, path, name) + if key in self._expirations: + del self._expirations[(domain, path, name)] + self._cookies[(domain, path)].pop(name, None) + + next_expiration = min(self._expirations.values(), default=self._max_time) + try: + self._next_expiration = next_expiration.replace( + microsecond=0 + ) + datetime.timedelta(seconds=1) + except OverflowError: + self._next_expiration = self._max_time + + def clear_domain(self, domain: str) -> None: + self.clear(lambda x: self._is_domain_match(domain, x["domain"])) def __iter__(self) -> "Iterator[Morsel[str]]": self._do_expiration() @@ -102,35 +147,13 @@ def __len__(self) -> int: return sum(1 for i in self) def _do_expiration(self) -> None: - now = datetime.datetime.now(datetime.timezone.utc) - if self._next_expiration > now: - return - if not self._expirations: - return - next_expiration = self._max_time - to_del = [] - cookies = self._cookies - expirations = self._expirations - for (domain, name), when in expirations.items(): - if when <= now: - cookies[domain].pop(name, None) - to_del.append((domain, name)) - self._host_only_cookies.discard((domain, name)) - else: - next_expiration = min(next_expiration, when) - for key in to_del: - del expirations[key] + self.clear(lambda x: False) - try: - self._next_expiration = next_expiration.replace( - microsecond=0 - ) + datetime.timedelta(seconds=1) - except OverflowError: - self._next_expiration = self._max_time - - def _expire_cookie(self, when: datetime.datetime, domain: str, name: str) -> None: + def _expire_cookie( + self, when: datetime.datetime, domain: str, path: str, name: str + ) -> None: self._next_expiration = min(self._next_expiration, when) - self._expirations[(domain, name)] = when + self._expirations[(domain, path, name)] = when def update_cookies(self, cookies: LooseCookies, response_url: URL = URL()) -> None: """Update cookies.""" @@ -145,8 +168,8 @@ def update_cookies(self, cookies: LooseCookies, response_url: URL = URL()) -> No for name, cookie in cookies: if not isinstance(cookie, Morsel): - tmp = SimpleCookie() # type: SimpleCookie[str] - tmp[name] = cookie # type: ignore + tmp: SimpleCookie[str] = SimpleCookie() + tmp[name] = cookie # type: ignore[assignment] cookie = tmp[name] domain = cookie["domain"] @@ -192,7 +215,7 @@ def update_cookies(self, cookies: LooseCookies, response_url: URL = URL()) -> No ) + datetime.timedelta(seconds=delta_seconds) except OverflowError: max_age_expiration = self._max_time - self._expire_cookie(max_age_expiration, domain, name) + self._expire_cookie(max_age_expiration, domain, path, name) except ValueError: cookie["max-age"] = "" @@ -201,11 +224,11 @@ def update_cookies(self, cookies: LooseCookies, response_url: URL = URL()) -> No if expires: expire_time = self._parse_date(expires) if expire_time: - self._expire_cookie(expire_time, domain, name) + self._expire_cookie(expire_time, domain, path, name) else: cookie["expires"] = "" - self._cookies[domain][name] = cookie + self._cookies[(domain, path)][name] = cookie self._do_expiration() @@ -219,9 +242,17 @@ def filter_cookies( SimpleCookie() if self._quote_cookie else BaseCookie() ) hostname = request_url.raw_host or "" - is_not_secure = request_url.scheme not in ("https", "wss") + request_origin = URL() + with contextlib.suppress(ValueError): + request_origin = request_url.origin() - for cookie in self: + is_not_secure = ( + request_url.scheme not in ("https", "wss") + and request_origin not in self._treat_as_secure_origin + ) + + # Point 2: https://www.rfc-editor.org/rfc/rfc6265.html#section-5.4 + for cookie in sorted(self, key=lambda c: len(c["path"])): name = cookie.key domain = cookie["domain"] @@ -312,7 +343,7 @@ def _parse_date(cls, date_str: str) -> Optional[datetime.datetime]: time_match = cls.DATE_HMS_TIME_RE.match(token) if time_match: found_time = True - hour, minute, second = [int(s) for s in time_match.groups()] + hour, minute, second = (int(s) for s in time_match.groups()) continue if not found_day: @@ -372,7 +403,10 @@ def __iter__(self) -> "Iterator[Morsel[str]]": def __len__(self) -> int: return 0 - def clear(self) -> None: + def clear(self, predicate: Optional[ClearCookiePredicate] = None) -> None: + pass + + def clear_domain(self, domain: str) -> None: pass def update_cookies(self, cookies: LooseCookies, response_url: URL = URL()) -> None: diff --git a/aiohttp/formdata.py b/aiohttp/formdata.py index 900716b..e7cd24c 100644 --- a/aiohttp/formdata.py +++ b/aiohttp/formdata.py @@ -12,8 +12,10 @@ class FormData: - """Helper class for multipart/form-data and - application/x-www-form-urlencoded body generation.""" + """Helper class for form body generation. + + Supports multipart/form-data and application/x-www-form-urlencoded. + """ def __init__( self, @@ -22,7 +24,7 @@ def __init__( charset: Optional[str] = None, ) -> None: self._writer = multipart.MultipartWriter("form-data") - self._fields = [] # type: List[Any] + self._fields: List[Any] = [] self._is_multipart = False self._is_processed = False self._quote_fields = quote_fields @@ -45,7 +47,7 @@ def add_field( *, content_type: Optional[str] = None, filename: Optional[str] = None, - content_transfer_encoding: Optional[str] = None + content_transfer_encoding: Optional[str] = None, ) -> None: if isinstance(value, io.IOBase): @@ -54,7 +56,7 @@ def add_field( if filename is None and content_transfer_encoding is None: filename = name - type_options = MultiDict({"name": name}) # type: MultiDict[str] + type_options: MultiDict[str] = MultiDict({"name": name}) if filename is not None and not isinstance(filename, str): raise TypeError( "filename must be an instance of str. " "Got: %s" % filename @@ -92,14 +94,14 @@ def add_fields(self, *fields: Any) -> None: if isinstance(rec, io.IOBase): k = guess_filename(rec, "unknown") - self.add_field(k, rec) # type: ignore + self.add_field(k, rec) # type: ignore[arg-type] elif isinstance(rec, (MultiDictProxy, MultiDict)): to_add.extend(rec.items()) elif isinstance(rec, (list, tuple)) and len(rec) == 2: k, fp = rec - self.add_field(k, fp) # type: ignore + self.add_field(k, fp) # type: ignore[arg-type] else: raise TypeError( diff --git a/aiohttp/frozenlist.py b/aiohttp/frozenlist.py deleted file mode 100644 index 46b2610..0000000 --- a/aiohttp/frozenlist.py +++ /dev/null @@ -1,72 +0,0 @@ -from collections.abc import MutableSequence -from functools import total_ordering - -from .helpers import NO_EXTENSIONS - - -@total_ordering -class FrozenList(MutableSequence): - - __slots__ = ("_frozen", "_items") - - def __init__(self, items=None): - self._frozen = False - if items is not None: - items = list(items) - else: - items = [] - self._items = items - - @property - def frozen(self): - return self._frozen - - def freeze(self): - self._frozen = True - - def __getitem__(self, index): - return self._items[index] - - def __setitem__(self, index, value): - if self._frozen: - raise RuntimeError("Cannot modify frozen list.") - self._items[index] = value - - def __delitem__(self, index): - if self._frozen: - raise RuntimeError("Cannot modify frozen list.") - del self._items[index] - - def __len__(self): - return self._items.__len__() - - def __iter__(self): - return self._items.__iter__() - - def __reversed__(self): - return self._items.__reversed__() - - def __eq__(self, other): - return list(self) == other - - def __le__(self, other): - return list(self) <= other - - def insert(self, pos, item): - if self._frozen: - raise RuntimeError("Cannot modify frozen list.") - self._items.insert(pos, item) - - def __repr__(self): - return f"" - - -PyFrozenList = FrozenList - -try: - from aiohttp._frozenlist import FrozenList as CFrozenList # type: ignore - - if not NO_EXTENSIONS: - FrozenList = CFrozenList # type: ignore -except ImportError: # pragma: no cover - pass diff --git a/aiohttp/frozenlist.pyi b/aiohttp/frozenlist.pyi deleted file mode 100644 index 72ab086..0000000 --- a/aiohttp/frozenlist.pyi +++ /dev/null @@ -1,46 +0,0 @@ -from typing import ( - Generic, - Iterable, - Iterator, - List, - MutableSequence, - Optional, - TypeVar, - Union, - overload, -) - -_T = TypeVar("_T") -_Arg = Union[List[_T], Iterable[_T]] - -class FrozenList(MutableSequence[_T], Generic[_T]): - def __init__(self, items: Optional[_Arg[_T]] = ...) -> None: ... - @property - def frozen(self) -> bool: ... - def freeze(self) -> None: ... - @overload - def __getitem__(self, i: int) -> _T: ... - @overload - def __getitem__(self, s: slice) -> FrozenList[_T]: ... - @overload - def __setitem__(self, i: int, o: _T) -> None: ... - @overload - def __setitem__(self, s: slice, o: Iterable[_T]) -> None: ... - @overload - def __delitem__(self, i: int) -> None: ... - @overload - def __delitem__(self, i: slice) -> None: ... - def __len__(self) -> int: ... - def __iter__(self) -> Iterator[_T]: ... - def __reversed__(self) -> Iterator[_T]: ... - def __eq__(self, other: object) -> bool: ... - def __le__(self, other: FrozenList[_T]) -> bool: ... - def __ne__(self, other: object) -> bool: ... - def __lt__(self, other: FrozenList[_T]) -> bool: ... - def __ge__(self, other: FrozenList[_T]) -> bool: ... - def __gt__(self, other: FrozenList[_T]) -> bool: ... - def insert(self, pos: int, item: _T) -> None: ... - def __repr__(self) -> str: ... - -# types for C accelerators are the same -CFrozenList = PyFrozenList = FrozenList diff --git a/aiohttp/hdrs.py b/aiohttp/hdrs.py index f04a545..a619f25 100644 --- a/aiohttp/hdrs.py +++ b/aiohttp/hdrs.py @@ -2,21 +2,28 @@ # After changing the file content call ./tools/gen.py # to regenerate the headers parser +import sys +from typing import Set from multidict import istr -METH_ANY = "*" -METH_CONNECT = "CONNECT" -METH_HEAD = "HEAD" -METH_GET = "GET" -METH_DELETE = "DELETE" -METH_OPTIONS = "OPTIONS" -METH_PATCH = "PATCH" -METH_POST = "POST" -METH_PUT = "PUT" -METH_TRACE = "TRACE" +if sys.version_info >= (3, 8): + from typing import Final +else: + from typing_extensions import Final -METH_ALL = { +METH_ANY: Final[str] = "*" +METH_CONNECT: Final[str] = "CONNECT" +METH_HEAD: Final[str] = "HEAD" +METH_GET: Final[str] = "GET" +METH_DELETE: Final[str] = "DELETE" +METH_OPTIONS: Final[str] = "OPTIONS" +METH_PATCH: Final[str] = "PATCH" +METH_POST: Final[str] = "POST" +METH_PUT: Final[str] = "PUT" +METH_TRACE: Final[str] = "TRACE" + +METH_ALL: Final[Set[str]] = { METH_CONNECT, METH_HEAD, METH_GET, @@ -28,81 +35,80 @@ METH_TRACE, } - -ACCEPT = istr("Accept") -ACCEPT_CHARSET = istr("Accept-Charset") -ACCEPT_ENCODING = istr("Accept-Encoding") -ACCEPT_LANGUAGE = istr("Accept-Language") -ACCEPT_RANGES = istr("Accept-Ranges") -ACCESS_CONTROL_MAX_AGE = istr("Access-Control-Max-Age") -ACCESS_CONTROL_ALLOW_CREDENTIALS = istr("Access-Control-Allow-Credentials") -ACCESS_CONTROL_ALLOW_HEADERS = istr("Access-Control-Allow-Headers") -ACCESS_CONTROL_ALLOW_METHODS = istr("Access-Control-Allow-Methods") -ACCESS_CONTROL_ALLOW_ORIGIN = istr("Access-Control-Allow-Origin") -ACCESS_CONTROL_EXPOSE_HEADERS = istr("Access-Control-Expose-Headers") -ACCESS_CONTROL_REQUEST_HEADERS = istr("Access-Control-Request-Headers") -ACCESS_CONTROL_REQUEST_METHOD = istr("Access-Control-Request-Method") -AGE = istr("Age") -ALLOW = istr("Allow") -AUTHORIZATION = istr("Authorization") -CACHE_CONTROL = istr("Cache-Control") -CONNECTION = istr("Connection") -CONTENT_DISPOSITION = istr("Content-Disposition") -CONTENT_ENCODING = istr("Content-Encoding") -CONTENT_LANGUAGE = istr("Content-Language") -CONTENT_LENGTH = istr("Content-Length") -CONTENT_LOCATION = istr("Content-Location") -CONTENT_MD5 = istr("Content-MD5") -CONTENT_RANGE = istr("Content-Range") -CONTENT_TRANSFER_ENCODING = istr("Content-Transfer-Encoding") -CONTENT_TYPE = istr("Content-Type") -COOKIE = istr("Cookie") -DATE = istr("Date") -DESTINATION = istr("Destination") -DIGEST = istr("Digest") -ETAG = istr("Etag") -EXPECT = istr("Expect") -EXPIRES = istr("Expires") -FORWARDED = istr("Forwarded") -FROM = istr("From") -HOST = istr("Host") -IF_MATCH = istr("If-Match") -IF_MODIFIED_SINCE = istr("If-Modified-Since") -IF_NONE_MATCH = istr("If-None-Match") -IF_RANGE = istr("If-Range") -IF_UNMODIFIED_SINCE = istr("If-Unmodified-Since") -KEEP_ALIVE = istr("Keep-Alive") -LAST_EVENT_ID = istr("Last-Event-ID") -LAST_MODIFIED = istr("Last-Modified") -LINK = istr("Link") -LOCATION = istr("Location") -MAX_FORWARDS = istr("Max-Forwards") -ORIGIN = istr("Origin") -PRAGMA = istr("Pragma") -PROXY_AUTHENTICATE = istr("Proxy-Authenticate") -PROXY_AUTHORIZATION = istr("Proxy-Authorization") -RANGE = istr("Range") -REFERER = istr("Referer") -RETRY_AFTER = istr("Retry-After") -SEC_WEBSOCKET_ACCEPT = istr("Sec-WebSocket-Accept") -SEC_WEBSOCKET_VERSION = istr("Sec-WebSocket-Version") -SEC_WEBSOCKET_PROTOCOL = istr("Sec-WebSocket-Protocol") -SEC_WEBSOCKET_EXTENSIONS = istr("Sec-WebSocket-Extensions") -SEC_WEBSOCKET_KEY = istr("Sec-WebSocket-Key") -SEC_WEBSOCKET_KEY1 = istr("Sec-WebSocket-Key1") -SERVER = istr("Server") -SET_COOKIE = istr("Set-Cookie") -TE = istr("TE") -TRAILER = istr("Trailer") -TRANSFER_ENCODING = istr("Transfer-Encoding") -UPGRADE = istr("Upgrade") -URI = istr("URI") -USER_AGENT = istr("User-Agent") -VARY = istr("Vary") -VIA = istr("Via") -WANT_DIGEST = istr("Want-Digest") -WARNING = istr("Warning") -WWW_AUTHENTICATE = istr("WWW-Authenticate") -X_FORWARDED_FOR = istr("X-Forwarded-For") -X_FORWARDED_HOST = istr("X-Forwarded-Host") -X_FORWARDED_PROTO = istr("X-Forwarded-Proto") +ACCEPT: Final[istr] = istr("Accept") +ACCEPT_CHARSET: Final[istr] = istr("Accept-Charset") +ACCEPT_ENCODING: Final[istr] = istr("Accept-Encoding") +ACCEPT_LANGUAGE: Final[istr] = istr("Accept-Language") +ACCEPT_RANGES: Final[istr] = istr("Accept-Ranges") +ACCESS_CONTROL_MAX_AGE: Final[istr] = istr("Access-Control-Max-Age") +ACCESS_CONTROL_ALLOW_CREDENTIALS: Final[istr] = istr("Access-Control-Allow-Credentials") +ACCESS_CONTROL_ALLOW_HEADERS: Final[istr] = istr("Access-Control-Allow-Headers") +ACCESS_CONTROL_ALLOW_METHODS: Final[istr] = istr("Access-Control-Allow-Methods") +ACCESS_CONTROL_ALLOW_ORIGIN: Final[istr] = istr("Access-Control-Allow-Origin") +ACCESS_CONTROL_EXPOSE_HEADERS: Final[istr] = istr("Access-Control-Expose-Headers") +ACCESS_CONTROL_REQUEST_HEADERS: Final[istr] = istr("Access-Control-Request-Headers") +ACCESS_CONTROL_REQUEST_METHOD: Final[istr] = istr("Access-Control-Request-Method") +AGE: Final[istr] = istr("Age") +ALLOW: Final[istr] = istr("Allow") +AUTHORIZATION: Final[istr] = istr("Authorization") +CACHE_CONTROL: Final[istr] = istr("Cache-Control") +CONNECTION: Final[istr] = istr("Connection") +CONTENT_DISPOSITION: Final[istr] = istr("Content-Disposition") +CONTENT_ENCODING: Final[istr] = istr("Content-Encoding") +CONTENT_LANGUAGE: Final[istr] = istr("Content-Language") +CONTENT_LENGTH: Final[istr] = istr("Content-Length") +CONTENT_LOCATION: Final[istr] = istr("Content-Location") +CONTENT_MD5: Final[istr] = istr("Content-MD5") +CONTENT_RANGE: Final[istr] = istr("Content-Range") +CONTENT_TRANSFER_ENCODING: Final[istr] = istr("Content-Transfer-Encoding") +CONTENT_TYPE: Final[istr] = istr("Content-Type") +COOKIE: Final[istr] = istr("Cookie") +DATE: Final[istr] = istr("Date") +DESTINATION: Final[istr] = istr("Destination") +DIGEST: Final[istr] = istr("Digest") +ETAG: Final[istr] = istr("Etag") +EXPECT: Final[istr] = istr("Expect") +EXPIRES: Final[istr] = istr("Expires") +FORWARDED: Final[istr] = istr("Forwarded") +FROM: Final[istr] = istr("From") +HOST: Final[istr] = istr("Host") +IF_MATCH: Final[istr] = istr("If-Match") +IF_MODIFIED_SINCE: Final[istr] = istr("If-Modified-Since") +IF_NONE_MATCH: Final[istr] = istr("If-None-Match") +IF_RANGE: Final[istr] = istr("If-Range") +IF_UNMODIFIED_SINCE: Final[istr] = istr("If-Unmodified-Since") +KEEP_ALIVE: Final[istr] = istr("Keep-Alive") +LAST_EVENT_ID: Final[istr] = istr("Last-Event-ID") +LAST_MODIFIED: Final[istr] = istr("Last-Modified") +LINK: Final[istr] = istr("Link") +LOCATION: Final[istr] = istr("Location") +MAX_FORWARDS: Final[istr] = istr("Max-Forwards") +ORIGIN: Final[istr] = istr("Origin") +PRAGMA: Final[istr] = istr("Pragma") +PROXY_AUTHENTICATE: Final[istr] = istr("Proxy-Authenticate") +PROXY_AUTHORIZATION: Final[istr] = istr("Proxy-Authorization") +RANGE: Final[istr] = istr("Range") +REFERER: Final[istr] = istr("Referer") +RETRY_AFTER: Final[istr] = istr("Retry-After") +SEC_WEBSOCKET_ACCEPT: Final[istr] = istr("Sec-WebSocket-Accept") +SEC_WEBSOCKET_VERSION: Final[istr] = istr("Sec-WebSocket-Version") +SEC_WEBSOCKET_PROTOCOL: Final[istr] = istr("Sec-WebSocket-Protocol") +SEC_WEBSOCKET_EXTENSIONS: Final[istr] = istr("Sec-WebSocket-Extensions") +SEC_WEBSOCKET_KEY: Final[istr] = istr("Sec-WebSocket-Key") +SEC_WEBSOCKET_KEY1: Final[istr] = istr("Sec-WebSocket-Key1") +SERVER: Final[istr] = istr("Server") +SET_COOKIE: Final[istr] = istr("Set-Cookie") +TE: Final[istr] = istr("TE") +TRAILER: Final[istr] = istr("Trailer") +TRANSFER_ENCODING: Final[istr] = istr("Transfer-Encoding") +UPGRADE: Final[istr] = istr("Upgrade") +URI: Final[istr] = istr("URI") +USER_AGENT: Final[istr] = istr("User-Agent") +VARY: Final[istr] = istr("Vary") +VIA: Final[istr] = istr("Via") +WANT_DIGEST: Final[istr] = istr("Want-Digest") +WARNING: Final[istr] = istr("Warning") +WWW_AUTHENTICATE: Final[istr] = istr("WWW-Authenticate") +X_FORWARDED_FOR: Final[istr] = istr("X-Forwarded-For") +X_FORWARDED_HOST: Final[istr] = istr("X-Forwarded-Host") +X_FORWARDED_PROTO: Final[istr] = istr("X-Forwarded-Proto") diff --git a/aiohttp/helpers.py b/aiohttp/helpers.py index bbf5f12..eb0782f 100644 --- a/aiohttp/helpers.py +++ b/aiohttp/helpers.py @@ -3,7 +3,7 @@ import asyncio import base64 import binascii -import cgi +import contextlib import datetime import functools import inspect @@ -17,12 +17,15 @@ import weakref from collections import namedtuple from contextlib import suppress +from email.parser import HeaderParser +from email.utils import parsedate from math import ceil from pathlib import Path from types import TracebackType from typing import ( Any, Callable, + ContextManager, Dict, Generator, Generic, @@ -40,58 +43,55 @@ cast, ) from urllib.parse import quote -from urllib.request import getproxies +from urllib.request import getproxies, proxy_bypass import async_timeout import attr from multidict import MultiDict, MultiDictProxy -from typing_extensions import Protocol from yarl import URL from . import hdrs from .log import client_logger, internal_logger -from .typedefs import PathLike # noqa +from .typedefs import PathLike, Protocol # noqa -__all__ = ("BasicAuth", "ChainMapProxy") +__all__ = ("BasicAuth", "ChainMapProxy", "ETag") + +IS_MACOS = platform.system() == "Darwin" +IS_WINDOWS = platform.system() == "Windows" PY_36 = sys.version_info >= (3, 6) PY_37 = sys.version_info >= (3, 7) PY_38 = sys.version_info >= (3, 8) +PY_310 = sys.version_info >= (3, 10) +PY_311 = sys.version_info >= (3, 11) -if not PY_37: +if sys.version_info < (3, 7): import idna_ssl idna_ssl.patch_match_hostname() -try: - from typing import ContextManager -except ImportError: - from typing_extensions import ContextManager - - -def all_tasks( - loop: Optional[asyncio.AbstractEventLoop] = None, -) -> Set["asyncio.Task[Any]"]: - tasks = list(asyncio.Task.all_tasks(loop)) - return {t for t in tasks if not t.done()} - + def all_tasks( + loop: Optional[asyncio.AbstractEventLoop] = None, + ) -> Set["asyncio.Task[Any]"]: + tasks = list(asyncio.Task.all_tasks(loop)) + return {t for t in tasks if not t.done()} -if PY_37: - all_tasks = getattr(asyncio, "all_tasks") +else: + all_tasks = asyncio.all_tasks _T = TypeVar("_T") _S = TypeVar("_S") -sentinel = object() # type: Any -NO_EXTENSIONS = bool(os.environ.get("AIOHTTP_NO_EXTENSIONS")) # type: bool +sentinel: Any = object() +NO_EXTENSIONS: bool = bool(os.environ.get("AIOHTTP_NO_EXTENSIONS")) # N.B. sys.flags.dev_mode is available on Python 3.7+, use getattr # for compatibility with older versions -DEBUG = getattr(sys.flags, "dev_mode", False) or ( +DEBUG: bool = getattr(sys.flags, "dev_mode", False) or ( not sys.flags.ignore_environment and bool(os.environ.get("PYTHONASYNCIODEBUG")) -) # type: bool +) CHAR = {chr(i) for i in range(0, 128)} @@ -197,7 +197,9 @@ def strip_auth_from_url(url: URL) -> Tuple[URL, Optional[BasicAuth]]: def netrc_from_env() -> Optional[netrc.netrc]: - """Attempt to load the netrc file from the path specified by the env-var + """Load netrc from file. + + Attempt to load it from the path specified by the env-var NETRC or in the default location in the user's home directory. Returns None if it couldn't be found or fails to parse. @@ -218,17 +220,18 @@ def netrc_from_env() -> Optional[netrc.netrc]: ) return None - netrc_path = home_dir / ( - "_netrc" if platform.system() == "Windows" else ".netrc" - ) + netrc_path = home_dir / ("_netrc" if IS_WINDOWS else ".netrc") try: return netrc.netrc(str(netrc_path)) except netrc.NetrcParseError as e: client_logger.warning("Could not parse .netrc file: %s", e) except OSError as e: + netrc_exists = False + with contextlib.suppress(OSError): + netrc_exists = netrc_path.is_file() # we couldn't read the file (doesn't exist, permissions, etc.) - if netrc_env or netrc_path.is_file(): + if netrc_env or netrc_exists: # only warn if the environment wanted us to load it, # or it appears like the default file does actually exist client_logger.warning("Could not read .netrc file: %s", e) @@ -243,14 +246,20 @@ class ProxyInfo: def proxies_from_env() -> Dict[str, ProxyInfo]: - proxy_urls = {k: URL(v) for k, v in getproxies().items() if k in ("http", "https")} + proxy_urls = { + k: URL(v) + for k, v in getproxies().items() + if k in ("http", "https", "ws", "wss") + } netrc_obj = netrc_from_env() stripped = {k: strip_auth_from_url(v) for k, v in proxy_urls.items()} ret = {} for proto, val in stripped.items(): proxy, auth = val - if proxy.scheme == "https": - client_logger.warning("HTTPS proxies %s are not supported, ignoring", proxy) + if proxy.scheme in ("https", "wss"): + client_logger.warning( + "%s proxies %s are not supported, ignoring", proxy.scheme.upper(), proxy + ) continue if netrc_obj and auth is None: auth_from_netrc = None @@ -270,7 +279,7 @@ def proxies_from_env() -> Dict[str, ProxyInfo]: def current_task( loop: Optional[asyncio.AbstractEventLoop] = None, ) -> "Optional[asyncio.Task[Any]]": - if PY_37: + if sys.version_info >= (3, 7): return asyncio.current_task(loop=loop) else: return asyncio.Task.current_task(loop=loop) @@ -297,11 +306,25 @@ def get_running_loop( def isasyncgenfunction(obj: Any) -> bool: func = getattr(inspect, "isasyncgenfunction", None) if func is not None: - return func(obj) + return func(obj) # type: ignore[no-any-return] else: return False +def get_env_proxy_for_url(url: URL) -> Tuple[URL, Optional[BasicAuth]]: + """Get a permitted proxy for the given URL from the env.""" + if url.host is not None and proxy_bypass(url.host): + raise LookupError(f"Proxying is disallowed for `{url.host!r}`") + + proxies_in_env = proxies_from_env() + try: + proxy_info = proxies_in_env[url.scheme] + except KeyError: + raise LookupError(f"No proxies found for `{url!s}` in the env") + else: + return proxy_info.proxy, proxy_info.proxy_auth + + @attr.s(auto_attribs=True, frozen=True, slots=True) class MimeType: type: str @@ -331,7 +354,7 @@ def parse_mimetype(mimetype: str) -> MimeType: ) parts = mimetype.split(";") - params = MultiDict() # type: MultiDict[str] + params: MultiDict[str] = MultiDict() for item in parts[1:]: if not item: continue @@ -365,14 +388,41 @@ def guess_filename(obj: Any, default: Optional[str] = None) -> Optional[str]: return default +not_qtext_re = re.compile(r"[^\041\043-\133\135-\176]") +QCONTENT = {chr(i) for i in range(0x20, 0x7F)} | {"\t"} + + +def quoted_string(content: str) -> str: + """Return 7-bit content as quoted-string. + + Format content into a quoted-string as defined in RFC5322 for + Internet Message Format. Notice that this is not the 8-bit HTTP + format, but the 7-bit email format. Content must be in usascii or + a ValueError is raised. + """ + if not (QCONTENT > set(content)): + raise ValueError(f"bad content for quoted-string {content!r}") + return not_qtext_re.sub(lambda x: "\\" + x.group(0), content) + + def content_disposition_header( - disptype: str, quote_fields: bool = True, **params: str + disptype: str, quote_fields: bool = True, _charset: str = "utf-8", **params: str ) -> str: - """Sets ``Content-Disposition`` header. + """Sets ``Content-Disposition`` header for MIME. + + This is the MIME payload Content-Disposition header from RFC 2183 + and RFC 7579 section 4.2, not the HTTP Content-Disposition from + RFC 6266. disptype is a disposition type: inline, attachment, form-data. Should be valid extension token (see RFC 2183) + quote_fields performs value quoting to 7-bit MIME headers + according to RFC 7578. Set to quote_fields to False if recipient + can take 8-bit file names and field values. + + _charset specifies the charset to use when quote_fields is True. + params is a dict with disposition params. """ if not disptype or not (TOKEN > set(disptype)): @@ -386,26 +436,40 @@ def content_disposition_header( raise ValueError( "bad content disposition parameter" " {!r}={!r}".format(key, val) ) - qval = quote(val, "") if quote_fields else val - lparams.append((key, '"%s"' % qval)) - if key == "filename": - lparams.append(("filename*", "utf-8''" + qval)) + if quote_fields: + if key.lower() == "filename": + qval = quote(val, "", encoding=_charset) + lparams.append((key, '"%s"' % qval)) + else: + try: + qval = quoted_string(val) + except ValueError: + qval = "".join( + (_charset, "''", quote(val, "", encoding=_charset)) + ) + lparams.append((key + "*", qval)) + else: + lparams.append((key, '"%s"' % qval)) + else: + qval = val.replace("\\", "\\\\").replace('"', '\\"') + lparams.append((key, '"%s"' % qval)) sparams = "; ".join("=".join(pair) for pair in lparams) value = "; ".join((value, sparams)) return value -class _TSelf(Protocol): - _cache: Dict[str, Any] +class _TSelf(Protocol, Generic[_T]): + _cache: Dict[str, _T] class reify(Generic[_T]): - """Use as a class method decorator. It operates almost exactly like + """Use as a class method decorator. + + It operates almost exactly like the Python `@property` decorator, but it puts the result of the method it decorates into the instance dict after the first call, effectively replacing the function it decorates with an instance variable. It is, in Python parlance, a data descriptor. - """ def __init__(self, wrapped: Callable[..., _T]) -> None: @@ -413,7 +477,7 @@ def __init__(self, wrapped: Callable[..., _T]) -> None: self.__doc__ = wrapped.__doc__ self.name = wrapped.__name__ - def __get__(self, inst: _TSelf, owner: Optional[Type[Any]] = None) -> _T: + def __get__(self, inst: _TSelf[_T], owner: Optional[Type[Any]] = None) -> _T: try: try: return inst._cache[self.name] @@ -426,7 +490,7 @@ def __get__(self, inst: _TSelf, owner: Optional[Type[Any]] = None) -> _T: return self raise - def __set__(self, inst: _TSelf, value: _T) -> None: + def __set__(self, inst: _TSelf[_T], value: _T) -> None: raise AttributeError("reified property is read-only") @@ -436,7 +500,7 @@ def __set__(self, inst: _TSelf, value: _T) -> None: from ._helpers import reify as reify_c if not NO_EXTENSIONS: - reify = reify_c # type: ignore + reify = reify_c # type: ignore[misc,assignment] except ImportError: pass @@ -470,7 +534,7 @@ def _is_ip_address( elif isinstance(host, (bytes, bytearray, memoryview)): return bool(regexb.match(host)) else: - raise TypeError("{} [{}] is not a str or bytes".format(host, type(host))) + raise TypeError(f"{host} [{type(host)}] is not a str or bytes") is_ipv4_address = functools.partial(_is_ip_address, _ipv4_regex, _ipv4_regexb) @@ -488,7 +552,7 @@ def next_whole_second() -> datetime.datetime: ) + datetime.timedelta(seconds=0) -_cached_current_datetime = None # type: Optional[int] +_cached_current_datetime: Optional[int] = None _cached_formatted_datetime = "" @@ -532,7 +596,7 @@ def rfc822_formatted_time() -> str: return _cached_formatted_datetime -def _weakref_handle(info): # type: ignore +def _weakref_handle(info: "Tuple[weakref.ref[object], str]") -> None: ref, name = info ob = ref() if ob is not None: @@ -540,34 +604,40 @@ def _weakref_handle(info): # type: ignore getattr(ob, name)() -def weakref_handle(ob, name, timeout, loop): # type: ignore +def weakref_handle( + ob: object, name: str, timeout: float, loop: asyncio.AbstractEventLoop +) -> Optional[asyncio.TimerHandle]: if timeout is not None and timeout > 0: when = loop.time() + timeout if timeout >= 5: when = ceil(when) return loop.call_at(when, _weakref_handle, (weakref.ref(ob), name)) + return None -def call_later(cb, timeout, loop): # type: ignore +def call_later( + cb: Callable[[], Any], timeout: float, loop: asyncio.AbstractEventLoop +) -> Optional[asyncio.TimerHandle]: if timeout is not None and timeout > 0: when = loop.time() + timeout if timeout > 5: when = ceil(when) return loop.call_at(when, cb) + return None class TimeoutHandle: - """ Timeout handle """ + """Timeout handle""" def __init__( self, loop: asyncio.AbstractEventLoop, timeout: Optional[float] ) -> None: self._timeout = timeout self._loop = loop - self._callbacks = ( - [] - ) # type: List[Tuple[Callable[..., None], Tuple[Any, ...], Dict[str, Any]]] + self._callbacks: List[ + Tuple[Callable[..., None], Tuple[Any, ...], Dict[str, Any]] + ] = [] def register( self, callback: Callable[..., None], *args: Any, **kwargs: Any @@ -621,11 +691,11 @@ def __exit__( class TimerContext(BaseTimerContext): - """ Low resolution timeout context manager """ + """Low resolution timeout context manager""" def __init__(self, loop: asyncio.AbstractEventLoop) -> None: self._loop = loop - self._tasks = [] # type: List[asyncio.Task[Any]] + self._tasks: List[asyncio.Task[Any]] = [] self._cancelled = False def __enter__(self) -> BaseTimerContext: @@ -637,7 +707,6 @@ def __enter__(self) -> BaseTimerContext: ) if self._cancelled: - task.cancel() raise asyncio.TimeoutError from None self._tasks.append(task) @@ -664,29 +733,23 @@ def timeout(self) -> None: self._cancelled = True -class CeilTimeout(async_timeout.timeout): - def __enter__(self) -> async_timeout.timeout: - if self._timeout is not None: - self._task = current_task(loop=self._loop) - if self._task is None: - raise RuntimeError( - "Timeout context manager should be used inside a task" - ) - now = self._loop.time() - delay = self._timeout - when = now + delay - if delay > 5: - when = ceil(when) - self._cancel_handler = self._loop.call_at(when, self._cancel_task) - return self +def ceil_timeout(delay: Optional[float]) -> async_timeout.Timeout: + if delay is None or delay <= 0: + return async_timeout.timeout(None) + loop = get_running_loop() + now = loop.time() + when = now + delay + if delay > 5: + when = ceil(when) + return async_timeout.timeout_at(when) -class HeadersMixin: +class HeadersMixin: ATTRS = frozenset(["_content_type", "_content_dict", "_stored_content_type"]) - _content_type = None # type: Optional[str] - _content_dict = None # type: Optional[Dict[str, str]] + _content_type: Optional[str] = None + _content_dict: Optional[Dict[str, str]] = None _stored_content_type = sentinel def _parse_content_type(self, raw: str) -> None: @@ -696,28 +759,33 @@ def _parse_content_type(self, raw: str) -> None: self._content_type = "application/octet-stream" self._content_dict = {} else: - self._content_type, self._content_dict = cgi.parse_header(raw) + msg = HeaderParser().parsestr("Content-Type: " + raw) + self._content_type = msg.get_content_type() + params = msg.get_params() + self._content_dict = dict(params[1:]) # First element is content type again @property def content_type(self) -> str: """The value of content part for Content-Type HTTP header.""" - raw = self._headers.get(hdrs.CONTENT_TYPE) # type: ignore + raw = self._headers.get(hdrs.CONTENT_TYPE) # type: ignore[attr-defined] if self._stored_content_type != raw: self._parse_content_type(raw) - return self._content_type # type: ignore + return self._content_type # type: ignore[return-value] @property def charset(self) -> Optional[str]: """The value of charset part for Content-Type HTTP header.""" - raw = self._headers.get(hdrs.CONTENT_TYPE) # type: ignore + raw = self._headers.get(hdrs.CONTENT_TYPE) # type: ignore[attr-defined] if self._stored_content_type != raw: self._parse_content_type(raw) - return self._content_dict.get("charset") # type: ignore + return self._content_dict.get("charset") # type: ignore[union-attr] @property def content_length(self) -> Optional[int]: """The value of Content-Length HTTP header.""" - content_length = self._headers.get(hdrs.CONTENT_LENGTH) # type: ignore + content_length = self._headers.get( # type: ignore[attr-defined] + hdrs.CONTENT_LENGTH + ) if content_length is not None: return int(content_length) @@ -760,10 +828,10 @@ def get(self, key: str, default: Any = None) -> Any: def __len__(self) -> int: # reuses stored hash values if possible - return len(set().union(*self._maps)) # type: ignore + return len(set().union(*self._maps)) # type: ignore[arg-type] def __iter__(self) -> Iterator[str]: - d = {} # type: Dict[str, Any] + d: Dict[str, Any] = {} for mapping in reversed(self._maps): # reuses stored hash values if possible d.update(mapping) @@ -778,3 +846,36 @@ def __bool__(self) -> bool: def __repr__(self) -> str: content = ", ".join(map(repr, self._maps)) return f"ChainMapProxy({content})" + + +# https://tools.ietf.org/html/rfc7232#section-2.3 +_ETAGC = r"[!#-}\x80-\xff]+" +_ETAGC_RE = re.compile(_ETAGC) +_QUOTED_ETAG = rf'(W/)?"({_ETAGC})"' +QUOTED_ETAG_RE = re.compile(_QUOTED_ETAG) +LIST_QUOTED_ETAG_RE = re.compile(rf"({_QUOTED_ETAG})(?:\s*,\s*|$)|(.)") + +ETAG_ANY = "*" + + +@attr.s(auto_attribs=True, frozen=True, slots=True) +class ETag: + value: str + is_weak: bool = False + + +def validate_etag_value(value: str) -> None: + if value != ETAG_ANY and not _ETAGC_RE.fullmatch(value): + raise ValueError( + f"Value {value!r} is not a valid etag. Maybe it contains '\"'?" + ) + + +def parse_http_date(date_str: Optional[str]) -> Optional[datetime.datetime]: + """Process a date string, return a datetime object""" + if date_str is not None: + timetuple = parsedate(date_str) + if timetuple is not None: + with suppress(ValueError): + return datetime.datetime(*timetuple[:6], tzinfo=datetime.timezone.utc) + return None diff --git a/aiohttp/http.py b/aiohttp/http.py index 415ffbf..ca9dc54 100644 --- a/aiohttp/http.py +++ b/aiohttp/http.py @@ -63,10 +63,8 @@ ) -SERVER_SOFTWARE = "Python/{0[0]}.{0[1]} aiohttp/{1}".format( +SERVER_SOFTWARE: str = "Python/{0[0]}.{0[1]} aiohttp/{1}".format( sys.version_info, __version__ -) # type: str +) -RESPONSES = ( - http.server.BaseHTTPRequestHandler.responses -) # type: Mapping[int, Tuple[str, str]] +RESPONSES: Mapping[int, Tuple[str, str]] = http.server.BaseHTTPRequestHandler.responses diff --git a/aiohttp/http_exceptions.py b/aiohttp/http_exceptions.py index c885f80..63c20af 100644 --- a/aiohttp/http_exceptions.py +++ b/aiohttp/http_exceptions.py @@ -1,6 +1,7 @@ """Low-level http related exceptions.""" +from textwrap import indent from typing import Optional, Union from .typedefs import _CIMultiDict @@ -35,10 +36,11 @@ def __init__( self.message = message def __str__(self) -> str: - return f"{self.code}, message={self.message!r}" + msg = indent(self.message, " ") + return f"{self.code}, message:\n{msg}" def __repr__(self) -> str: - return f"<{self.__class__.__name__}: {self}>" + return f"<{self.__class__.__name__}: {self.code}, message={self.message!r}>" class BadHttpMessage(HttpProcessingError): @@ -93,10 +95,10 @@ def __init__(self, hdr: Union[bytes, str]) -> None: class BadStatusLine(BadHttpMessage): - def __init__(self, line: str = "") -> None: + def __init__(self, line: str = "", error: Optional[str] = None) -> None: if not isinstance(line, str): line = repr(line) - super().__init__(f"Bad status line {line!r}") + super().__init__(error or f"Bad status line {line!r}") self.args = (line,) self.line = line diff --git a/aiohttp/http_parser.py b/aiohttp/http_parser.py index 71ba815..91e01f4 100644 --- a/aiohttp/http_parser.py +++ b/aiohttp/http_parser.py @@ -3,17 +3,34 @@ import collections import re import string +import sys import zlib +from contextlib import suppress from enum import IntEnum -from typing import Any, List, Optional, Tuple, Type, Union +from typing import ( + Any, + ClassVar, + Generic, + List, + NamedTuple, + Optional, + Pattern, + Set, + Tuple, + Type, + TypeVar, + Union, + cast, +) from multidict import CIMultiDict, CIMultiDictProxy, istr from yarl import URL from . import hdrs from .base_protocol import BaseProtocol -from .helpers import NO_EXTENSIONS, BaseTimerContext +from .helpers import DEBUG, NO_EXTENSIONS, BaseTimerContext from .http_exceptions import ( + BadHttpMessage, BadStatusLine, ContentEncodingError, ContentLengthError, @@ -24,7 +41,12 @@ from .http_writer import HttpVersion, HttpVersion10 from .log import internal_logger from .streams import EMPTY_PAYLOAD, StreamReader -from .typedefs import RawHeaders +from .typedefs import Final, RawHeaders + +if sys.version_info >= (3, 8): + from typing import Literal +else: + from typing_extensions import Literal try: import brotli @@ -43,34 +65,35 @@ "RawResponseMessage", ) -ASCIISET = set(string.printable) +_SEP = Literal[b"\r\n", b"\n"] + +ASCIISET: Final[Set[str]] = set(string.printable) -# See https://tools.ietf.org/html/rfc7230#section-3.1.1 -# and https://tools.ietf.org/html/rfc7230#appendix-B +# See https://www.rfc-editor.org/rfc/rfc9110.html#name-overview +# and https://www.rfc-editor.org/rfc/rfc9110.html#name-tokens # # method = token # tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." / # "^" / "_" / "`" / "|" / "~" / DIGIT / ALPHA # token = 1*tchar -METHRE = re.compile(r"[!#$%&'*+\-.^_`|~0-9A-Za-z]+") -VERSRE = re.compile(r"HTTP/(\d+).(\d+)") -HDRRE = re.compile(rb"[\x00-\x1F\x7F()<>@,;:\[\]={} \t\\\\\"]") +METHRE: Final[Pattern[str]] = re.compile(r"[!#$%&'*+\-.^_`|~0-9A-Za-z]+") +VERSRE: Final[Pattern[str]] = re.compile(r"HTTP/(\d).(\d)") +HDRRE: Final[Pattern[bytes]] = re.compile(rb"[\x00-\x1F\x7F()<>@,;:\[\]={} \t\"\\]") +HEXDIGIT = re.compile(rb"[0-9a-fA-F]+") + + +class RawRequestMessage(NamedTuple): + method: str + path: str + version: HttpVersion + headers: "CIMultiDictProxy[str]" + raw_headers: RawHeaders + should_close: bool + compression: Optional[str] + upgrade: bool + chunked: bool + url: URL -RawRequestMessage = collections.namedtuple( - "RawRequestMessage", - [ - "method", - "path", - "version", - "headers", - "raw_headers", - "should_close", - "compression", - "upgrade", - "chunked", - "url", - ], -) RawResponseMessage = collections.namedtuple( "RawResponseMessage", @@ -88,6 +111,9 @@ ) +_MsgT = TypeVar("_MsgT", RawRequestMessage, RawResponseMessage) + + class ParseState(IntEnum): PARSE_NONE = 0 @@ -118,7 +144,7 @@ def __init__( def parse_headers( self, lines: List[bytes] ) -> Tuple["CIMultiDictProxy[str]", RawHeaders]: - headers = CIMultiDict() # type: CIMultiDict[str] + headers: CIMultiDict[str] = CIMultiDict() raw_headers = [] lines_idx = 1 @@ -132,8 +158,11 @@ def parse_headers( except ValueError: raise InvalidHeader(line) from None - bname = bname.strip(b" \t") - bvalue = bvalue.lstrip() + # https://www.rfc-editor.org/rfc/rfc9112.html#section-5.1-2 + if {bname[0], bname[-1]} & {32, 9}: # {" ", "\t"} + raise InvalidHeader(line) + + bvalue = bvalue.lstrip(b" \t") if HDRRE.search(bname): raise InvalidHeader(bname) if len(bname) > self.max_field_size: @@ -154,6 +183,8 @@ def parse_headers( # consume continuation lines continuation = line and line[0] in (32, 9) # (' ', '\t') + # Deprecated: + # https://www.rfc-editor.org/rfc/rfc9112.html#name-obsolete-line-folding if continuation: bvalue_lst = [bvalue] while continuation: @@ -188,22 +219,28 @@ def parse_headers( str(header_length), ) - bvalue = bvalue.strip() + bvalue = bvalue.strip(b" \t") name = bname.decode("utf-8", "surrogateescape") value = bvalue.decode("utf-8", "surrogateescape") + # https://www.rfc-editor.org/rfc/rfc9110.html#section-5.5-5 + if "\n" in value or "\r" in value or "\x00" in value: + raise InvalidHeader(bvalue) + headers.add(name, value) raw_headers.append((bname, bvalue)) return (CIMultiDictProxy(headers), tuple(raw_headers)) -class HttpParser(abc.ABC): +class HttpParser(abc.ABC, Generic[_MsgT]): + lax: ClassVar[bool] = False + def __init__( self, protocol: Optional[BaseProtocol] = None, loop: Optional[asyncio.AbstractEventLoop] = None, - limit: int = 2 ** 16, + limit: int = 2**16, max_line_size: int = 8190, max_headers: int = 32768, max_field_size: int = 8190, @@ -229,20 +266,20 @@ def __init__( self.response_with_body = response_with_body self.read_until_eof = read_until_eof - self._lines = [] # type: List[bytes] + self._lines: List[bytes] = [] self._tail = b"" self._upgraded = False self._payload = None - self._payload_parser = None # type: Optional[HttpPayloadParser] + self._payload_parser: Optional[HttpPayloadParser] = None self._auto_decompress = auto_decompress self._limit = limit self._headers_parser = HeadersParser(max_line_size, max_headers, max_field_size) @abc.abstractmethod - def parse_message(self, lines: List[bytes]) -> Any: + def parse_message(self, lines: List[bytes]) -> _MsgT: pass - def feed_eof(self) -> Any: + def feed_eof(self) -> Optional[_MsgT]: if self._payload_parser is not None: self._payload_parser.feed_eof() self._payload_parser = None @@ -254,20 +291,19 @@ def feed_eof(self) -> Any: if self._lines: if self._lines[-1] != "\r\n": self._lines.append(b"") - try: + with suppress(Exception): return self.parse_message(self._lines) - except Exception: - return None + return None def feed_data( self, data: bytes, - SEP: bytes = b"\r\n", + SEP: _SEP = b"\r\n", EMPTY: bytes = b"", CONTENT_LENGTH: istr = hdrs.CONTENT_LENGTH, METH_CONNECT: str = hdrs.METH_CONNECT, SEC_WEBSOCKET_KEY1: istr = hdrs.SEC_WEBSOCKET_KEY1, - ) -> Tuple[List[Any], bool, bytes]: + ) -> Tuple[List[Tuple[_MsgT, StreamReader]], bool, bytes]: messages = [] @@ -286,31 +322,38 @@ def feed_data( pos = data.find(SEP, start_pos) # consume \r\n if pos == start_pos and not self._lines: - start_pos = pos + 2 + start_pos = pos + len(SEP) continue if pos >= start_pos: # line found - self._lines.append(data[start_pos:pos]) - start_pos = pos + 2 + line = data[start_pos:pos] + if SEP == b"\n": # For lax response parsing + line = line.rstrip(b"\r") + self._lines.append(line) + start_pos = pos + len(SEP) # \r\n\r\n found if self._lines[-1] == EMPTY: try: - msg = self.parse_message(self._lines) + msg: _MsgT = self.parse_message(self._lines) finally: self._lines.clear() - # payload length - length = msg.headers.get(CONTENT_LENGTH) - if length is not None: - try: - length = int(length) - except ValueError: - raise InvalidHeader(CONTENT_LENGTH) - if length < 0: + def get_content_length() -> Optional[int]: + # payload length + length_hdr = msg.headers.get(CONTENT_LENGTH) + if length_hdr is None: + return None + + # Shouldn't allow +/- or other number formats. + # https://www.rfc-editor.org/rfc/rfc9110#section-8.6-2 + if not length_hdr.strip(" \t").isdecimal(): raise InvalidHeader(CONTENT_LENGTH) + return int(length_hdr) + + length = get_content_length() # do not support old websocket spec if SEC_WEBSOCKET_KEY1 in msg.headers: raise InvalidHeader(SEC_WEBSOCKET_KEY1) @@ -342,10 +385,12 @@ def feed_data( readall=self.readall, response_with_body=self.response_with_body, auto_decompress=self._auto_decompress, + lax=self.lax, ) if not payload_parser.done: self._payload_parser = payload_parser elif method == METH_CONNECT: + assert isinstance(msg, RawRequestMessage) payload = StreamReader( self.protocol, timer=self.timer, @@ -359,6 +404,7 @@ def feed_data( compression=msg.compression, readall=True, auto_decompress=self._auto_decompress, + lax=self.lax, ) else: if ( @@ -382,11 +428,12 @@ def feed_data( readall=True, response_with_body=self.response_with_body, auto_decompress=self._auto_decompress, + lax=self.lax, ) if not payload_parser.done: self._payload_parser = payload_parser else: - payload = EMPTY_PAYLOAD # type: ignore + payload = EMPTY_PAYLOAD messages.append((msg, payload)) else: @@ -404,7 +451,7 @@ def feed_data( assert not self._lines assert self._payload_parser is not None try: - eof, data = self._payload_parser.feed_data(data[start_pos:]) + eof, data = self._payload_parser.feed_data(data[start_pos:], SEP) except BaseException as exc: if self.payload_exception is not None: self._payload_parser.payload.set_exception( @@ -447,6 +494,24 @@ def parse_headers( upgrade = False chunked = False + # https://www.rfc-editor.org/rfc/rfc9110.html#section-5.5-6 + # https://www.rfc-editor.org/rfc/rfc9110.html#name-collected-abnf + singletons = ( + hdrs.CONTENT_LENGTH, + hdrs.CONTENT_LOCATION, + hdrs.CONTENT_RANGE, + hdrs.CONTENT_TYPE, + hdrs.ETAG, + hdrs.HOST, + hdrs.MAX_FORWARDS, + hdrs.SERVER, + hdrs.TRANSFER_ENCODING, + hdrs.USER_AGENT, + ) + bad_hdr = next((h for h in singletons if len(headers.getall(h, ())) > 1), None) + if bad_hdr is not None: + raise BadHttpMessage(f"Duplicate '{bad_hdr}' header found.") + # keep-alive conn = headers.get(hdrs.CONNECTION) if conn: @@ -467,29 +532,40 @@ def parse_headers( # chunking te = headers.get(hdrs.TRANSFER_ENCODING) - if te and "chunked" in te.lower(): - chunked = True + if te is not None: + if "chunked" == te.lower(): + chunked = True + else: + raise BadHttpMessage("Request has invalid `Transfer-Encoding`") + + if hdrs.CONTENT_LENGTH in headers: + raise BadHttpMessage( + "Transfer-Encoding can't be present with Content-Length", + ) return (headers, raw_headers, close_conn, encoding, upgrade, chunked) def set_upgraded(self, val: bool) -> None: """Set connection upgraded (to websocket) mode. + :param bool val: new state. """ self._upgraded = val -class HttpRequestParser(HttpParser): - """Read request status line. Exception .http_exceptions.BadStatusLine +class HttpRequestParser(HttpParser[RawRequestMessage]): + """Read request status line. + + Exception .http_exceptions.BadStatusLine could be raised in case of any errors in status line. Returns RawRequestMessage. """ - def parse_message(self, lines: List[bytes]) -> Any: + def parse_message(self, lines: List[bytes]) -> RawRequestMessage: # request line line = lines[0].decode("utf-8", "surrogateescape") try: - method, path, version = line.split(None, 2) + method, path, version = line.split(maxsplit=2) except ValueError: raise BadStatusLine(line) from None @@ -498,22 +574,40 @@ def parse_message(self, lines: List[bytes]) -> Any: "Status line is too long", str(self.max_line_size), str(len(path)) ) - path_part, _hash_separator, url_fragment = path.partition("#") - path_part, _question_mark_separator, qs_part = path_part.partition("?") - # method if not METHRE.match(method): raise BadStatusLine(method) # version - try: - if version.startswith("HTTP/"): - n1, n2 = version[5:].split(".", 1) - version_o = HttpVersion(int(n1), int(n2)) - else: - raise BadStatusLine(version) - except Exception: - raise BadStatusLine(version) + match = VERSRE.match(version) + if match is None: + raise BadStatusLine(line) + version_o = HttpVersion(int(match.group(1)), int(match.group(2))) + + if method == "CONNECT": + # authority-form, + # https://datatracker.ietf.org/doc/html/rfc7230#section-5.3.3 + url = URL.build(authority=path, encoded=True) + elif path.startswith("/"): + # origin-form, + # https://datatracker.ietf.org/doc/html/rfc7230#section-5.3.1 + path_part, _hash_separator, url_fragment = path.partition("#") + path_part, _question_mark_separator, qs_part = path_part.partition("?") + + # NOTE: `yarl.URL.build()` is used to mimic what the Cython-based + # NOTE: parser does, otherwise it results into the same + # NOTE: HTTP Request-Line input producing different + # NOTE: `yarl.URL()` objects + url = URL.build( + path=path_part, + query_string=qs_part, + fragment=url_fragment, + encoded=True, + ) + else: + # absolute-form for proxy maybe, + # https://datatracker.ietf.org/doc/html/rfc7230#section-5.3.2 + url = URL(path, encoded=True) # read headers ( @@ -541,34 +635,40 @@ def parse_message(self, lines: List[bytes]) -> Any: compression, upgrade, chunked, - # NOTE: `yarl.URL.build()` is used to mimic what the Cython-based - # NOTE: parser does, otherwise it results into the same - # NOTE: HTTP Request-Line input producing different - # NOTE: `yarl.URL()` objects - URL.build( - path=path_part, - query_string=qs_part, - fragment=url_fragment, - encoded=True, - ), + url, ) -class HttpResponseParser(HttpParser): +class HttpResponseParser(HttpParser[RawResponseMessage]): """Read response status line and headers. BadStatusLine could be raised in case of any errors in status line. - Returns RawResponseMessage""" + Returns RawResponseMessage. + """ - def parse_message(self, lines: List[bytes]) -> Any: + # Lax mode should only be enabled on response parser. + lax = not DEBUG + + def feed_data( + self, + data: bytes, + SEP: Optional[_SEP] = None, + *args: Any, + **kwargs: Any, + ) -> Tuple[List[Tuple[RawResponseMessage, StreamReader]], bool, bytes]: + if SEP is None: + SEP = b"\r\n" if DEBUG else b"\n" + return super().feed_data(data, SEP, *args, **kwargs) + + def parse_message(self, lines: List[bytes]) -> RawResponseMessage: line = lines[0].decode("utf-8", "surrogateescape") try: - version, status = line.split(None, 1) + version, status = line.split(maxsplit=1) except ValueError: raise BadStatusLine(line) from None try: - status, reason = status.split(None, 1) + status, reason = status.split(maxsplit=1) except ValueError: reason = "" @@ -584,13 +684,9 @@ def parse_message(self, lines: List[bytes]) -> Any: version_o = HttpVersion(int(match.group(1)), int(match.group(2))) # The status code is a three-digit number - try: - status_i = int(status) - except ValueError: - raise BadStatusLine(line) from None - - if status_i > 999: + if len(status) != 3 or not status.isdecimal(): raise BadStatusLine(line) + status_i = int(status) # read headers ( @@ -630,6 +726,7 @@ def __init__( readall: bool = False, response_with_body: bool = True, auto_decompress: bool = True, + lax: bool = False, ) -> None: self._length = 0 self._type = ParseState.PARSE_NONE @@ -637,13 +734,14 @@ def __init__( self._chunk_size = 0 self._chunk_tail = b"" self._auto_decompress = auto_decompress + self._lax = lax self.done = False # payload decompression wrapper if response_with_body and compression and self._auto_decompress: - real_payload = DeflateBuffer( + real_payload: Union[StreamReader, DeflateBuffer] = DeflateBuffer( payload, compression - ) # type: Union[StreamReader, DeflateBuffer] + ) else: real_payload = payload @@ -688,7 +786,7 @@ def feed_eof(self) -> None: ) def feed_data( - self, chunk: bytes, SEP: bytes = b"\r\n", CHUNK_EXT: bytes = b";" + self, chunk: bytes, SEP: _SEP = b"\r\n", CHUNK_EXT: bytes = b";" ) -> Tuple[bool, bytes]: # Read specified amount of bytes if self._type == ParseState.PARSE_LENGTH: @@ -725,18 +823,22 @@ def feed_data( else: size_b = chunk[:pos] - try: - size = int(bytes(size_b), 16) - except ValueError: + if self._lax: # Allow whitespace in lax mode. + size_b = size_b.strip() + + if not re.fullmatch(HEXDIGIT, size_b): exc = TransferEncodingError( chunk[:pos].decode("ascii", "surrogateescape") ) self.payload.set_exception(exc) - raise exc from None + raise exc + size = int(bytes(size_b), 16) - chunk = chunk[pos + 2 :] + chunk = chunk[pos + len(SEP) :] if size == 0: # eof marker self._chunk = ChunkState.PARSE_MAYBE_TRAILERS + if self._lax and chunk.startswith(b"\r"): + chunk = chunk[1:] else: self._chunk = ChunkState.PARSE_CHUNKED_CHUNK self._chunk_size = size @@ -758,13 +860,15 @@ def feed_data( self._chunk_size = 0 self.payload.feed_data(chunk[:required], required) chunk = chunk[required:] + if self._lax and chunk.startswith(b"\r"): + chunk = chunk[1:] self._chunk = ChunkState.PARSE_CHUNKED_CHUNK_EOF self.payload.end_http_chunk_receiving() # toss the CRLF at the end of the chunk if self._chunk == ChunkState.PARSE_CHUNKED_CHUNK_EOF: - if chunk[:2] == SEP: - chunk = chunk[2:] + if chunk[: len(SEP)] == SEP: + chunk = chunk[len(SEP) :] self._chunk = ChunkState.PARSE_CHUNKED_SIZE else: self._chunk_tail = chunk @@ -774,11 +878,11 @@ def feed_data( # we should get another \r\n otherwise # trailers needs to be skiped until \r\n\r\n if self._chunk == ChunkState.PARSE_MAYBE_TRAILERS: - head = chunk[:2] + head = chunk[: len(SEP)] if head == SEP: # end of stream self.payload.feed_eof() - return True, chunk[2:] + return True, chunk[len(SEP) :] # Both CR and LF, or only LF may not be received yet. It is # expected that CRLF or LF will be shown at the very first # byte next time, otherwise trailers should come. The last @@ -796,7 +900,7 @@ def feed_data( if self._chunk == ChunkState.PARSE_TRAILERS: pos = chunk.find(SEP) if pos >= 0: - chunk = chunk[pos + 2 :] + chunk = chunk[pos + len(SEP) :] self._chunk = ChunkState.PARSE_MAYBE_TRAILERS else: self._chunk_tail = chunk @@ -812,6 +916,8 @@ def feed_data( class DeflateBuffer: """DeflateStream decompress stream and feed data into specified stream.""" + decompressor: Any + def __init__(self, out: StreamReader, encoding: Optional[str]) -> None: self.out = out self.size = 0 @@ -822,9 +928,27 @@ def __init__(self, out: StreamReader, encoding: Optional[str]) -> None: if not HAS_BROTLI: # pragma: no cover raise ContentEncodingError( "Can not decode content-encoding: brotli (br). " - "Please install `brotlipy`" + "Please install `Brotli`" ) - self.decompressor = brotli.Decompressor() + + class BrotliDecoder: + # Supports both 'brotlipy' and 'Brotli' packages + # since they share an import name. The top branches + # are for 'brotlipy' and bottom branches for 'Brotli' + def __init__(self) -> None: + self._obj = brotli.Decompressor() + + def decompress(self, data: bytes) -> bytes: + if hasattr(self._obj, "decompress"): + return cast(bytes, self._obj.decompress(data)) + return cast(bytes, self._obj.process(data)) + + def flush(self) -> bytes: + if hasattr(self._obj, "flush"): + return cast(bytes, self._obj.flush()) + return b"" + + self.decompressor = BrotliDecoder() else: zlib_mode = 16 + zlib.MAX_WBITS if encoding == "gzip" else zlib.MAX_WBITS self.decompressor = zlib.decompressobj(wbits=zlib_mode) @@ -886,7 +1010,7 @@ def end_http_chunk_receiving(self) -> None: try: if not NO_EXTENSIONS: - from ._http_parser import ( # type: ignore + from ._http_parser import ( # type: ignore[import,no-redef] HttpRequestParser, HttpResponseParser, RawRequestMessage, diff --git a/aiohttp/http_websocket.py b/aiohttp/http_websocket.py index 5cdaeea..2cfc519 100644 --- a/aiohttp/http_websocket.py +++ b/aiohttp/http_websocket.py @@ -9,11 +9,12 @@ import zlib from enum import IntEnum from struct import Struct -from typing import Any, Callable, List, Optional, Tuple, Union +from typing import Any, Callable, List, Optional, Pattern, Set, Tuple, Union, cast from .base_protocol import BaseProtocol from .helpers import NO_EXTENSIONS from .streams import DataQueue +from .typedefs import Final __all__ = ( "WS_CLOSED_MESSAGE", @@ -33,6 +34,7 @@ class WSCloseCode(IntEnum): GOING_AWAY = 1001 PROTOCOL_ERROR = 1002 UNSUPPORTED_DATA = 1003 + ABNORMAL_CLOSURE = 1006 INVALID_TEXT = 1007 POLICY_VIOLATION = 1008 MESSAGE_TOO_BIG = 1009 @@ -40,9 +42,10 @@ class WSCloseCode(IntEnum): INTERNAL_ERROR = 1011 SERVICE_RESTART = 1012 TRY_AGAIN_LATER = 1013 + BAD_GATEWAY = 1014 -ALLOWED_CLOSE_CODES = {int(i) for i in WSCloseCode} +ALLOWED_CLOSE_CODES: Final[Set[int]] = {int(i) for i in WSCloseCode} class WSMsgType(IntEnum): @@ -69,7 +72,7 @@ class WSMsgType(IntEnum): error = ERROR -WS_KEY = b"258EAFA5-E914-47DA-95CA-C5AB0DC85B11" +WS_KEY: Final[bytes] = b"258EAFA5-E914-47DA-95CA-C5AB0DC85B11" UNPACK_LEN2 = Struct("!H").unpack_from @@ -79,8 +82,8 @@ class WSMsgType(IntEnum): PACK_LEN2 = Struct("!BBH").pack PACK_LEN3 = Struct("!BBQ").pack PACK_CLOSE_CODE = Struct("!H").pack -MSG_SIZE = 2 ** 14 -DEFAULT_LIMIT = 2 ** 16 +MSG_SIZE: Final[int] = 2**14 +DEFAULT_LIMIT: Final[int] = 2**16 _WSMessageBase = collections.namedtuple("_WSMessageBase", ["type", "data", "extra"]) @@ -107,18 +110,18 @@ def __init__(self, code: int, message: str) -> None: super().__init__(code, message) def __str__(self) -> str: - return self.args[1] + return cast(str, self.args[1]) class WSHandshakeError(Exception): """WebSocket protocol handshake error.""" -native_byteorder = sys.byteorder +native_byteorder: Final[str] = sys.byteorder # Used by _websocket_mask_python -_XOR_TABLE = [bytes(a ^ b for a in range(256)) for b in range(256)] +_XOR_TABLE: Final[List[bytes]] = [bytes(a ^ b for a in range(256)) for b in range(256)] def _websocket_mask_python(mask: bytes, data: bytearray) -> None: @@ -149,16 +152,16 @@ def _websocket_mask_python(mask: bytes, data: bytearray) -> None: _websocket_mask = _websocket_mask_python else: try: - from ._websocket import _websocket_mask_cython # type: ignore + from ._websocket import _websocket_mask_cython # type: ignore[import] _websocket_mask = _websocket_mask_cython except ImportError: # pragma: no cover _websocket_mask = _websocket_mask_python -_WS_DEFLATE_TRAILING = bytes([0x00, 0x00, 0xFF, 0xFF]) +_WS_DEFLATE_TRAILING: Final[bytes] = bytes([0x00, 0x00, 0xFF, 0xFF]) -_WS_EXT_RE = re.compile( +_WS_EXT_RE: Final[Pattern[str]] = re.compile( r"^(?:;\s*(?:" r"(server_no_context_takeover)|" r"(client_no_context_takeover)|" @@ -166,7 +169,7 @@ def _websocket_mask_python(mask: bytes, data: bytearray) -> None: r"(client_max_window_bits(?:=(\d+))?)))*$" ) -_WS_EXT_RE_SPLIT = re.compile(r"permessage-deflate([^,]+)?") +_WS_EXT_RE_SPLIT: Final[Pattern[str]] = re.compile(r"permessage-deflate([^,]+)?") def ws_ext_parse(extstr: Optional[str], isserver: bool = False) -> Tuple[int, bool]: @@ -256,22 +259,22 @@ def __init__( self.queue = queue self._max_msg_size = max_msg_size - self._exc = None # type: Optional[BaseException] + self._exc: Optional[BaseException] = None self._partial = bytearray() self._state = WSParserState.READ_HEADER - self._opcode = None # type: Optional[int] + self._opcode: Optional[int] = None self._frame_fin = False - self._frame_opcode = None # type: Optional[int] + self._frame_opcode: Optional[int] = None self._frame_payload = bytearray() self._tail = b"" self._has_mask = False - self._frame_mask = None # type: Optional[bytes] + self._frame_mask: Optional[bytes] = None self._payload_length = 0 self._payload_length_flag = 0 - self._compressed = None # type: Optional[bool] - self._decompressobj = None # type: Any # zlib.decompressobj actually + self._compressed: Optional[bool] = None + self._decompressobj: Any = None # zlib.decompressobj actually self._compress = compress def feed_eof(self) -> None: @@ -588,7 +591,7 @@ def __init__( self._closing = False self._limit = limit self._output_size = 0 - self._compressobj = None # type: Any # actually compressobj + self._compressobj: Any = None # actually compressobj async def _send_frame( self, message: bytes, opcode: int, compress: Optional[int] = None diff --git a/aiohttp/http_writer.py b/aiohttp/http_writer.py index d261fc4..73f0f96 100644 --- a/aiohttp/http_writer.py +++ b/aiohttp/http_writer.py @@ -1,9 +1,8 @@ """Http related parsers and protocol.""" import asyncio -import collections import zlib -from typing import Any, Awaitable, Callable, Optional, Union # noqa +from typing import Any, Awaitable, Callable, NamedTuple, Optional, Union # noqa from multidict import CIMultiDict @@ -13,12 +12,18 @@ __all__ = ("StreamWriter", "HttpVersion", "HttpVersion10", "HttpVersion11") -HttpVersion = collections.namedtuple("HttpVersion", ["major", "minor"]) + +class HttpVersion(NamedTuple): + major: int + minor: int + + HttpVersion10 = HttpVersion(1, 0) HttpVersion11 = HttpVersion(1, 1) _T_OnChunkSent = Optional[Callable[[bytes], Awaitable[None]]] +_T_OnHeadersSent = Optional[Callable[["CIMultiDict[str]"], Awaitable[None]]] class StreamWriter(AbstractStreamWriter): @@ -27,9 +32,9 @@ def __init__( protocol: BaseProtocol, loop: asyncio.AbstractEventLoop, on_chunk_sent: _T_OnChunkSent = None, + on_headers_sent: _T_OnHeadersSent = None, ) -> None: self._protocol = protocol - self._transport = protocol.transport self.loop = loop self.length = None @@ -38,14 +43,15 @@ def __init__( self.output_size = 0 self._eof = False - self._compress = None # type: Any + self._compress: Any = None self._drain_waiter = None - self._on_chunk_sent = on_chunk_sent # type: _T_OnChunkSent + self._on_chunk_sent: _T_OnChunkSent = on_chunk_sent + self._on_headers_sent: _T_OnHeadersSent = on_headers_sent @property def transport(self) -> Optional[asyncio.Transport]: - return self._transport + return self._protocol.transport @property def protocol(self) -> BaseProtocol: @@ -54,18 +60,20 @@ def protocol(self) -> BaseProtocol: def enable_chunking(self) -> None: self.chunked = True - def enable_compression(self, encoding: str = "deflate") -> None: + def enable_compression( + self, encoding: str = "deflate", strategy: int = zlib.Z_DEFAULT_STRATEGY + ) -> None: zlib_mode = 16 + zlib.MAX_WBITS if encoding == "gzip" else zlib.MAX_WBITS - self._compress = zlib.compressobj(wbits=zlib_mode) + self._compress = zlib.compressobj(wbits=zlib_mode, strategy=strategy) def _write(self, chunk: bytes) -> None: size = len(chunk) self.buffer_size += size self.output_size += size - - if self._transport is None or self._transport.is_closing(): + transport = self.transport + if not self._protocol.connected or transport is None or transport.is_closing(): raise ConnectionResetError("Cannot write to closing transport") - self._transport.write(chunk) + transport.write(chunk) async def write( self, chunk: bytes, *, drain: bool = True, LIMIT: int = 0x10000 @@ -114,6 +122,9 @@ async def write_headers( self, status_line: str, headers: "CIMultiDict[str]" ) -> None: """Write request/response status and headers.""" + if self._on_headers_sent is not None: + await self._on_headers_sent(headers) + # status + headers buf = _serialize_headers(status_line, headers) self._write(buf) @@ -147,7 +158,6 @@ async def write_eof(self, chunk: bytes = b"") -> None: await self.drain() self._eof = True - self._transport = None async def drain(self) -> None: """Flush the write buffer. @@ -161,19 +171,25 @@ async def drain(self) -> None: await self._protocol._drain_helper() +def _safe_header(string: str) -> str: + if "\r" in string or "\n" in string: + raise ValueError( + "Newline or carriage return detected in headers. " + "Potential header injection attack." + ) + return string + + def _py_serialize_headers(status_line: str, headers: "CIMultiDict[str]") -> bytes: - line = ( - status_line - + "\r\n" - + "".join([k + ": " + v + "\r\n" for k, v in headers.items()]) - ) - return line.encode("utf-8") + b"\r\n" + headers_gen = (_safe_header(k) + ": " + _safe_header(v) for k, v in headers.items()) + line = status_line + "\r\n" + "\r\n".join(headers_gen) + "\r\n\r\n" + return line.encode("utf-8") _serialize_headers = _py_serialize_headers try: - import aiohttp._http_writer as _http_writer # type: ignore + import aiohttp._http_writer as _http_writer # type: ignore[import] _c_serialize_headers = _http_writer._serialize_headers if not NO_EXTENSIONS: diff --git a/aiohttp/locks.py b/aiohttp/locks.py index ce5b9c6..de2dc83 100644 --- a/aiohttp/locks.py +++ b/aiohttp/locks.py @@ -1,16 +1,12 @@ import asyncio import collections -from typing import Any, Optional - -try: - from typing import Deque -except ImportError: - from typing_extensions import Deque +from typing import Any, Deque, Optional class EventResultOrError: - """ - This class wrappers the Event asyncio lock allowing either awake the + """Event asyncio lock helper class. + + Wraps the Event asyncio lock allowing either to awake the locked Tasks without any error or raising an exception. thanks to @vorpalsmith for the simple design. @@ -18,9 +14,9 @@ class EventResultOrError: def __init__(self, loop: asyncio.AbstractEventLoop) -> None: self._loop = loop - self._exc = None # type: Optional[BaseException] + self._exc: Optional[BaseException] = None self._event = asyncio.Event() - self._waiters = collections.deque() # type: Deque[asyncio.Future[Any]] + self._waiters: Deque[asyncio.Future[Any]] = collections.deque() def set(self, exc: Optional[BaseException] = None) -> None: self._exc = exc @@ -40,6 +36,6 @@ async def wait(self) -> Any: return val def cancel(self) -> None: - """ Cancel all waiters """ + """Cancel all waiters""" for waiter in self._waiters: waiter.cancel() diff --git a/aiohttp/multipart.py b/aiohttp/multipart.py index 9e1ca92..73801f4 100644 --- a/aiohttp/multipart.py +++ b/aiohttp/multipart.py @@ -11,6 +11,7 @@ TYPE_CHECKING, Any, AsyncIterator, + Deque, Dict, Iterator, List, @@ -20,6 +21,7 @@ Tuple, Type, Union, + cast, ) from urllib.parse import parse_qsl, unquote, urlencode @@ -101,7 +103,7 @@ def unescape(text: str, *, chars: str = "".join(map(re.escape, CHAR))) -> str: warnings.warn(BadContentDispositionHeader(header)) return None, {} - params = {} # type: Dict[str, str] + params: Dict[str, str] = {} while parts: item = parts.pop(0) @@ -152,7 +154,7 @@ def unescape(text: str, *, chars: str = "".join(map(re.escape, CHAR))) -> str: elif parts: # maybe just ; in filename, in any case this is just # one case fix, for proper fix we need to redesign parser - _value = "{};{}".format(value, parts[0]) + _value = f"{value};{parts[0]}" if is_quoted(_value): parts.pop(0) value = unescape(_value[1:-1].lstrip("\\/")) @@ -240,8 +242,10 @@ async def next( return item async def release(self) -> None: - """Releases the connection gracefully, reading all the content - to the void.""" + """Release the connection gracefully. + + All remaining content is read to the void. + """ await self.resp.release() @@ -261,13 +265,13 @@ def __init__( self._length = int(length) if length is not None else None self._read_bytes = 0 # TODO: typeing.Deque is not supported by Python 3.5 - self._unread = deque() # type: Any - self._prev_chunk = None # type: Optional[bytes] + self._unread: Deque[bytes] = deque() + self._prev_chunk: Optional[bytes] = None self._content_eof = 0 - self._cache = {} # type: Dict[str, Any] + self._cache: Dict[str, Any] = {} def __aiter__(self) -> AsyncIterator["BodyPartReader"]: - return self # type: ignore + return self # type: ignore[return-value] async def __anext__(self) -> bytes: part = await self.next() @@ -411,12 +415,10 @@ async def json(self, *, encoding: Optional[str] = None) -> Optional[Dict[str, An if not data: return None encoding = encoding or self.get_charset(default="utf-8") - return json.loads(data.decode(encoding)) + return cast(Dict[str, Any], json.loads(data.decode(encoding))) async def form(self, *, encoding: Optional[str] = None) -> List[Tuple[str, str]]: - """Like read(), but assumes that body parts contains form - urlencoded data. - """ + """Like read(), but assumes that body parts contain form urlencoded data.""" data = await self.read(decode=True) if not data: return [] @@ -435,7 +437,9 @@ def at_eof(self) -> bool: return self._at_eof def decode(self, data: bytes) -> bytes: - """Decodes data according the specified Content-Encoding + """Decodes data. + + Decoding is done according the specified Content-Encoding or Content-Transfer-Encoding headers value. """ if CONTENT_TRANSFER_ENCODING in self.headers: @@ -478,17 +482,18 @@ def get_charset(self, default: str) -> str: @reify def name(self) -> Optional[str]: - """Returns name specified in Content-Disposition header or None - if missed or header is malformed. - """ + """Returns name specified in Content-Disposition header. + If the header is missing or malformed, returns None. + """ _, params = parse_content_disposition(self.headers.get(CONTENT_DISPOSITION)) return content_disposition_filename(params, "name") @reify def filename(self) -> Optional[str]: - """Returns filename specified in Content-Disposition header or None - if missed or header is malformed. + """Returns filename specified in Content-Disposition header. + + Returns None if the header is missing or malformed. """ _, params = parse_content_disposition(self.headers.get(CONTENT_DISPOSITION)) return content_disposition_filename(params, "filename") @@ -499,7 +504,7 @@ class BodyPartReaderPayload(Payload): def __init__(self, value: BodyPartReader, *args: Any, **kwargs: Any) -> None: super().__init__(value, *args, **kwargs) - params = {} # type: Dict[str, str] + params: Dict[str, str] = {} if value.name is not None: params["name"] = value.name if value.filename is not None: @@ -510,10 +515,10 @@ def __init__(self, value: BodyPartReader, *args: Any, **kwargs: Any) -> None: async def write(self, writer: Any) -> None: field = self._value - chunk = await field.read_chunk(size=2 ** 16) + chunk = await field.read_chunk(size=2**16) while chunk: await writer.write(field.decode(chunk)) - chunk = await field.read_chunk(size=2 ** 16) + chunk = await field.read_chunk(size=2**16) class MultipartReader: @@ -531,17 +536,15 @@ def __init__(self, headers: Mapping[str, str], content: StreamReader) -> None: self.headers = headers self._boundary = ("--" + self._get_boundary()).encode() self._content = content - self._last_part = ( - None - ) # type: Optional[Union['MultipartReader', BodyPartReader]] + self._last_part: Optional[Union["MultipartReader", BodyPartReader]] = None self._at_eof = False self._at_bof = True - self._unread = [] # type: List[bytes] + self._unread: List[bytes] = [] def __aiter__( self, ) -> AsyncIterator["BodyPartReader"]: - return self # type: ignore + return self # type: ignore[return-value] async def __anext__( self, @@ -566,9 +569,7 @@ def from_response( return obj def at_eof(self) -> bool: - """Returns True if the final boundary was reached or - False otherwise. - """ + """Returns True if the final boundary was reached, false otherwise.""" return self._at_eof async def next( @@ -608,8 +609,9 @@ def _get_part_reader( self, headers: "CIMultiDictProxy[str]", ) -> Union["MultipartReader", BodyPartReader]: - """Dispatches the response by the `Content-Type` header, returning - suitable reader instance. + """Dispatches the response by the `Content-Type` header. + + Returns a suitable reader instance. :param dict headers: Response headers """ @@ -723,7 +725,7 @@ def __init__(self, subtype: str = "mixed", boundary: Optional[str] = None) -> No super().__init__(None, content_type=ctype) - self._parts = [] # type: List[_Part] + self._parts: List[_Part] = [] def __enter__(self) -> "MultipartWriter": return self @@ -745,8 +747,8 @@ def __len__(self) -> int: def __bool__(self) -> bool: return True - _valid_tchar_regex = re.compile(br"\A[!#$%&'*+\-.^_`|~\w]+\Z") - _invalid_qdtext_char_regex = re.compile(br"[\x00-\x08\x0A-\x1F\x7F]") + _valid_tchar_regex = re.compile(rb"\A[!#$%&'*+\-.^_`|~\w]+\Z") + _invalid_qdtext_char_regex = re.compile(rb"[\x00-\x08\x0A-\x1F\x7F]") @property def _boundary_value(self) -> str: @@ -802,20 +804,20 @@ def append(self, obj: Any, headers: Optional[MultiMapping[str]] = None) -> Paylo def append_payload(self, payload: Payload) -> Payload: """Adds a new body part to multipart writer.""" # compression - encoding = payload.headers.get( + encoding: Optional[str] = payload.headers.get( CONTENT_ENCODING, "", - ).lower() # type: Optional[str] + ).lower() if encoding and encoding not in ("deflate", "gzip", "identity"): raise RuntimeError(f"unknown content encoding: {encoding}") if encoding == "identity": encoding = None # te encoding - te_encoding = payload.headers.get( + te_encoding: Optional[str] = payload.headers.get( CONTENT_TRANSFER_ENCODING, "", - ).lower() # type: Optional[str] + ).lower() if te_encoding not in ("", "base64", "quoted-printable", "binary"): raise RuntimeError( "unknown content transfer encoding: {}" "".format(te_encoding) @@ -828,7 +830,7 @@ def append_payload(self, payload: Payload) -> Payload: if size is not None and not (encoding or te_encoding): payload.headers[CONTENT_LENGTH] = str(size) - self._parts.append((payload, encoding, te_encoding)) # type: ignore + self._parts.append((payload, encoding, te_encoding)) # type: ignore[arg-type] return payload def append_json( @@ -893,7 +895,7 @@ async def write(self, writer: Any, close_boundary: bool = True) -> None: w.enable_compression(encoding) if te_encoding: w.enable_encoding(te_encoding) - await part.write(w) # type: ignore + await part.write(w) # type: ignore[arg-type] await w.write_eof() else: await part.write(writer) @@ -907,9 +909,9 @@ async def write(self, writer: Any, close_boundary: bool = True) -> None: class MultipartPayloadWriter: def __init__(self, writer: Any) -> None: self._writer = writer - self._encoding = None # type: Optional[str] - self._compress = None # type: Any - self._encoding_buffer = None # type: Optional[bytearray] + self._encoding: Optional[str] = None + self._compress: Any = None + self._encoding_buffer: Optional[bytearray] = None def enable_encoding(self, encoding: str) -> None: if encoding == "base64": @@ -918,9 +920,11 @@ def enable_encoding(self, encoding: str) -> None: elif encoding == "quoted-printable": self._encoding = "quoted-printable" - def enable_compression(self, encoding: str = "deflate") -> None: + def enable_compression( + self, encoding: str = "deflate", strategy: int = zlib.Z_DEFAULT_STRATEGY + ) -> None: zlib_mode = 16 + zlib.MAX_WBITS if encoding == "gzip" else -zlib.MAX_WBITS - self._compress = zlib.compressobj(wbits=zlib_mode) + self._compress = zlib.compressobj(wbits=zlib_mode, strategy=strategy) async def write_eof(self) -> None: if self._compress is not None: diff --git a/aiohttp/payload.py b/aiohttp/payload.py index c63dd22..a2340e2 100644 --- a/aiohttp/payload.py +++ b/aiohttp/payload.py @@ -15,7 +15,6 @@ Dict, Iterable, Optional, - Text, TextIO, Tuple, Type, @@ -34,7 +33,7 @@ sentinel, ) from .streams import StreamReader -from .typedefs import JSONEncoder, _CIMultiDict +from .typedefs import Final, JSONEncoder, _CIMultiDict __all__ = ( "PAYLOAD_REGISTRY", @@ -52,8 +51,7 @@ "AsyncIterablePayload", ) -TOO_LARGE_BYTES_BODY = 2 ** 20 # 1 MB - +TOO_LARGE_BYTES_BODY: Final[int] = 2**20 # 1 MB if TYPE_CHECKING: # pragma: no cover from typing import List @@ -89,6 +87,10 @@ def __call__(self, factory: Type["Payload"]) -> Type["Payload"]: return factory +PayloadType = Type["Payload"] +_PayloadRegistryItem = Tuple[PayloadType, Any] + + class PayloadRegistry: """Payload registry. @@ -96,12 +98,16 @@ class PayloadRegistry: """ def __init__(self) -> None: - self._first = [] # type: List[Tuple[Type[Payload], Any]] - self._normal = [] # type: List[Tuple[Type[Payload], Any]] - self._last = [] # type: List[Tuple[Type[Payload], Any]] + self._first: List[_PayloadRegistryItem] = [] + self._normal: List[_PayloadRegistryItem] = [] + self._last: List[_PayloadRegistryItem] = [] def get( - self, data: Any, *args: Any, _CHAIN: Any = chain, **kwargs: Any + self, + data: Any, + *args: Any, + _CHAIN: "Type[chain[_PayloadRegistryItem]]" = chain, + **kwargs: Any, ) -> "Payload": if isinstance(data, Payload): return data @@ -112,7 +118,7 @@ def get( raise LookupError() def register( - self, factory: Type["Payload"], type: Any, *, order: Order = Order.normal + self, factory: PayloadType, type: Any, *, order: Order = Order.normal ) -> None: if order is Order.try_first: self._first.append((factory, type)) @@ -126,8 +132,8 @@ def register( class Payload(ABC): - _default_content_type = "application/octet-stream" # type: str - _size = None # type: Optional[int] + _default_content_type: str = "application/octet-stream" + _size: Optional[int] = None def __init__( self, @@ -142,7 +148,7 @@ def __init__( ) -> None: self._encoding = encoding self._filename = filename - self._headers = CIMultiDict() # type: _CIMultiDict + self._headers: _CIMultiDict = CIMultiDict() self._value = value if content_type is not sentinel and content_type is not None: self._headers[hdrs.CONTENT_TYPE] = content_type @@ -190,11 +196,15 @@ def content_type(self) -> str: return self._headers[hdrs.CONTENT_TYPE] def set_content_disposition( - self, disptype: str, quote_fields: bool = True, **params: Any + self, + disptype: str, + quote_fields: bool = True, + _charset: str = "utf-8", + **params: Any, ) -> None: """Sets ``Content-Disposition`` header.""" self._headers[hdrs.CONTENT_DISPOSITION] = content_disposition_header( - disptype, quote_fields=quote_fields, **params + disptype, quote_fields=quote_fields, _charset=_charset, **params ) @abstractmethod @@ -208,9 +218,7 @@ async def write(self, writer: AbstractStreamWriter) -> None: class BytesPayload(Payload): def __init__(self, value: ByteString, *args: Any, **kwargs: Any) -> None: if not isinstance(value, (bytes, bytearray, memoryview)): - raise TypeError( - "value argument must be byte-ish, not {!r}".format(type(value)) - ) + raise TypeError(f"value argument must be byte-ish, not {type(value)!r}") if "content_type" not in kwargs: kwargs["content_type"] = "application/octet-stream" @@ -242,7 +250,7 @@ async def write(self, writer: AbstractStreamWriter) -> None: class StringPayload(BytesPayload): def __init__( self, - value: Text, + value: str, *args: Any, encoding: Optional[str] = None, content_type: Optional[str] = None, @@ -276,6 +284,8 @@ def __init__(self, value: IO[str], *args: Any, **kwargs: Any) -> None: class IOBasePayload(Payload): + _value: IO[Any] + def __init__( self, value: IO[Any], disposition: str = "attachment", *args: Any, **kwargs: Any ) -> None: @@ -291,15 +301,17 @@ def __init__( async def write(self, writer: AbstractStreamWriter) -> None: loop = asyncio.get_event_loop() try: - chunk = await loop.run_in_executor(None, self._value.read, 2 ** 16) + chunk = await loop.run_in_executor(None, self._value.read, 2**16) while chunk: await writer.write(chunk) - chunk = await loop.run_in_executor(None, self._value.read, 2 ** 16) + chunk = await loop.run_in_executor(None, self._value.read, 2**16) finally: await loop.run_in_executor(None, self._value.close) class TextIOPayload(IOBasePayload): + _value: TextIO + def __init__( self, value: TextIO, @@ -338,10 +350,15 @@ def size(self) -> Optional[int]: async def write(self, writer: AbstractStreamWriter) -> None: loop = asyncio.get_event_loop() try: - chunk = await loop.run_in_executor(None, self._value.read, 2 ** 16) + chunk = await loop.run_in_executor(None, self._value.read, 2**16) while chunk: - await writer.write(chunk.encode(self._encoding)) - chunk = await loop.run_in_executor(None, self._value.read, 2 ** 16) + data = ( + chunk.encode(encoding=self._encoding) + if self._encoding + else chunk.encode() + ) + await writer.write(data) + chunk = await loop.run_in_executor(None, self._value.read, 2**16) finally: await loop.run_in_executor(None, self._value.close) @@ -400,13 +417,13 @@ def __init__( class AsyncIterablePayload(Payload): - _iter = None # type: Optional[_AsyncIterator] + _iter: Optional[_AsyncIterator] = None def __init__(self, value: _AsyncIterable, *args: Any, **kwargs: Any) -> None: if not isinstance(value, AsyncIterable): raise TypeError( "value argument must support " - "collections.abc.AsyncIterablebe interface, " + "collections.abc.AsyncIterable interface, " "got {!r}".format(type(value)) ) diff --git a/aiohttp/payload_streamer.py b/aiohttp/payload_streamer.py index 3b2de15..9f8b8bc 100644 --- a/aiohttp/payload_streamer.py +++ b/aiohttp/payload_streamer.py @@ -1,4 +1,5 @@ -""" Payload implemenation for coroutines as data provider. +""" +Payload implemenation for coroutines as data provider. As a simple case, you can upload data from file:: @@ -43,7 +44,7 @@ def __init__( self.kwargs = kwargs async def __call__(self, writer: AbstractStreamWriter) -> None: - await self.coro(writer, *self.args, **self.kwargs) # type: ignore + await self.coro(writer, *self.args, **self.kwargs) # type: ignore[operator] class streamer: diff --git a/aiohttp/pytest_plugin.py b/aiohttp/pytest_plugin.py index 5204293..dd9a9f6 100644 --- a/aiohttp/pytest_plugin.py +++ b/aiohttp/pytest_plugin.py @@ -2,6 +2,7 @@ import contextlib import warnings from collections.abc import Callable +from typing import Any, Awaitable, Callable, Dict, Generator, Optional, Union import pytest @@ -29,8 +30,10 @@ except ImportError: # pragma: no cover tokio = None +AiohttpClient = Callable[[Union[Application, BaseTestServer]], Awaitable[TestClient]] -def pytest_addoption(parser): # type: ignore + +def pytest_addoption(parser): # type: ignore[no-untyped-def] parser.addoption( "--aiohttp-fast", action="store_true", @@ -51,8 +54,9 @@ def pytest_addoption(parser): # type: ignore ) -def pytest_fixture_setup(fixturedef): # type: ignore - """ +def pytest_fixture_setup(fixturedef): # type: ignore[no-untyped-def] + """Set up pytest fixture. + Allow fixtures to be coroutines. Run coroutine fixtures in an event loop. """ func = fixturedef.func @@ -72,7 +76,7 @@ def pytest_fixture_setup(fixturedef): # type: ignore fixturedef.argnames += ("request",) strip_request = True - def wrapper(*args, **kwargs): # type: ignore + def wrapper(*args, **kwargs): # type: ignore[no-untyped-def] request = kwargs["request"] if strip_request: del kwargs["request"] @@ -93,7 +97,7 @@ def wrapper(*args, **kwargs): # type: ignore # then advance it again in a finalizer gen = func(*args, **kwargs) - def finalizer(): # type: ignore + def finalizer(): # type: ignore[no-untyped-def] try: return _loop.run_until_complete(gen.__anext__()) except StopAsyncIteration: @@ -108,21 +112,22 @@ def finalizer(): # type: ignore @pytest.fixture -def fast(request): # type: ignore +def fast(request): # type: ignore[no-untyped-def] """--fast config option""" return request.config.getoption("--aiohttp-fast") @pytest.fixture -def loop_debug(request): # type: ignore +def loop_debug(request): # type: ignore[no-untyped-def] """--enable-loop-debug config option""" return request.config.getoption("--aiohttp-enable-loop-debug") @contextlib.contextmanager -def _runtime_warning_context(): # type: ignore - """ - Context manager which checks for RuntimeWarnings, specifically to +def _runtime_warning_context(): # type: ignore[no-untyped-def] + """Context manager which checks for RuntimeWarnings. + + This exists specifically to avoid "coroutine 'X' was never awaited" warnings being missed. If RuntimeWarnings occur in the context a RuntimeError is raised. @@ -143,9 +148,10 @@ def _runtime_warning_context(): # type: ignore @contextlib.contextmanager -def _passthrough_loop_context(loop, fast=False): # type: ignore - """ - setups and tears down a loop unless one is passed in via the loop +def _passthrough_loop_context(loop, fast=False): # type: ignore[no-untyped-def] + """Passthrough loop context. + + Sets up and tears down a loop unless one is passed in via the loop argument when it's passed straight through. """ if loop: @@ -158,18 +164,14 @@ def _passthrough_loop_context(loop, fast=False): # type: ignore teardown_test_loop(loop, fast=fast) -def pytest_pycollect_makeitem(collector, name, obj): # type: ignore - """ - Fix pytest collecting for coroutines. - """ +def pytest_pycollect_makeitem(collector, name, obj): # type: ignore[no-untyped-def] + """Fix pytest collecting for coroutines.""" if collector.funcnamefilter(name) and asyncio.iscoroutinefunction(obj): return list(collector._genfunctions(name, obj)) -def pytest_pyfunc_call(pyfuncitem): # type: ignore - """ - Run coroutines in an event loop instead of a normal function call. - """ +def pytest_pyfunc_call(pyfuncitem): # type: ignore[no-untyped-def] + """Run coroutines in an event loop instead of a normal function call.""" fast = pyfuncitem.config.getoption("--aiohttp-fast") if asyncio.iscoroutinefunction(pyfuncitem.function): existing_loop = pyfuncitem.funcargs.get( @@ -186,7 +188,7 @@ def pytest_pyfunc_call(pyfuncitem): # type: ignore return True -def pytest_generate_tests(metafunc): # type: ignore +def pytest_generate_tests(metafunc): # type: ignore[no-untyped-def] if "loop_factory" not in metafunc.fixturenames: return @@ -202,7 +204,7 @@ def pytest_generate_tests(metafunc): # type: ignore if loops == "all": loops = "pyloop,uvloop?,tokio?" - factories = {} # type: ignore + factories = {} # type: ignore[var-annotated] for name in loops.split(","): required = not name.endswith("?") name = name.strip(" ?") @@ -221,7 +223,7 @@ def pytest_generate_tests(metafunc): # type: ignore @pytest.fixture -def loop(loop_factory, fast, loop_debug): # type: ignore +def loop(loop_factory, fast, loop_debug): # type: ignore[no-untyped-def] """Return an instance of the event loop.""" policy = loop_factory() asyncio.set_event_loop_policy(policy) @@ -233,12 +235,12 @@ def loop(loop_factory, fast, loop_debug): # type: ignore @pytest.fixture -def proactor_loop(): # type: ignore +def proactor_loop(): # type: ignore[no-untyped-def] if not PY_37: policy = asyncio.get_event_loop_policy() - policy._loop_factory = asyncio.ProactorEventLoop # type: ignore + policy._loop_factory = asyncio.ProactorEventLoop # type: ignore[attr-defined] else: - policy = asyncio.WindowsProactorEventLoopPolicy() # type: ignore + policy = asyncio.WindowsProactorEventLoopPolicy() # type: ignore[attr-defined] asyncio.set_event_loop_policy(policy) with loop_context(policy.new_event_loop) as _loop: @@ -247,7 +249,7 @@ def proactor_loop(): # type: ignore @pytest.fixture -def unused_port(aiohttp_unused_port): # type: ignore # pragma: no cover +def unused_port(aiohttp_unused_port): # type: ignore[no-untyped-def] # pragma: no cover warnings.warn( "Deprecated, use aiohttp_unused_port fixture instead", DeprecationWarning, @@ -257,20 +259,20 @@ def unused_port(aiohttp_unused_port): # type: ignore # pragma: no cover @pytest.fixture -def aiohttp_unused_port(): # type: ignore +def aiohttp_unused_port(): # type: ignore[no-untyped-def] """Return a port that is unused on the current host.""" return _unused_port @pytest.fixture -def aiohttp_server(loop): # type: ignore +def aiohttp_server(loop): # type: ignore[no-untyped-def] """Factory to create a TestServer instance, given an app. aiohttp_server(app, **kwargs) """ servers = [] - async def go(app, *, port=None, **kwargs): # type: ignore + async def go(app, *, port=None, **kwargs): # type: ignore[no-untyped-def] server = TestServer(app, port=port) await server.start_server(loop=loop, **kwargs) servers.append(server) @@ -278,7 +280,7 @@ async def go(app, *, port=None, **kwargs): # type: ignore yield go - async def finalize(): # type: ignore + async def finalize() -> None: while servers: await servers.pop().close() @@ -286,7 +288,7 @@ async def finalize(): # type: ignore @pytest.fixture -def test_server(aiohttp_server): # type: ignore # pragma: no cover +def test_server(aiohttp_server): # type: ignore[no-untyped-def] # pragma: no cover warnings.warn( "Deprecated, use aiohttp_server fixture instead", DeprecationWarning, @@ -296,14 +298,14 @@ def test_server(aiohttp_server): # type: ignore # pragma: no cover @pytest.fixture -def aiohttp_raw_server(loop): # type: ignore +def aiohttp_raw_server(loop): # type: ignore[no-untyped-def] """Factory to create a RawTestServer instance, given a web handler. aiohttp_raw_server(handler, **kwargs) """ servers = [] - async def go(handler, *, port=None, **kwargs): # type: ignore + async def go(handler, *, port=None, **kwargs): # type: ignore[no-untyped-def] server = RawTestServer(handler, port=port) await server.start_server(loop=loop, **kwargs) servers.append(server) @@ -311,7 +313,7 @@ async def go(handler, *, port=None, **kwargs): # type: ignore yield go - async def finalize(): # type: ignore + async def finalize() -> None: while servers: await servers.pop().close() @@ -319,7 +321,9 @@ async def finalize(): # type: ignore @pytest.fixture -def raw_test_server(aiohttp_raw_server): # type: ignore # pragma: no cover +def raw_test_server( # type: ignore[no-untyped-def] # pragma: no cover + aiohttp_raw_server, +): warnings.warn( "Deprecated, use aiohttp_raw_server fixture instead", DeprecationWarning, @@ -329,7 +333,9 @@ def raw_test_server(aiohttp_raw_server): # type: ignore # pragma: no cover @pytest.fixture -def aiohttp_client(loop): # type: ignore +def aiohttp_client( + loop: asyncio.AbstractEventLoop, +) -> Generator[AiohttpClient, None, None]: """Factory to create a TestClient instance. aiohttp_client(app, **kwargs) @@ -338,9 +344,14 @@ def aiohttp_client(loop): # type: ignore """ clients = [] - async def go(__param, *args, server_kwargs=None, **kwargs): # type: ignore + async def go( + __param: Union[Application, BaseTestServer], + *args: Any, + server_kwargs: Optional[Dict[str, Any]] = None, + **kwargs: Any + ) -> TestClient: - if isinstance(__param, Callable) and not isinstance( # type: ignore + if isinstance(__param, Callable) and not isinstance( # type: ignore[arg-type] __param, (Application, BaseTestServer) ): __param = __param(loop, *args, **kwargs) @@ -363,7 +374,7 @@ async def go(__param, *args, server_kwargs=None, **kwargs): # type: ignore yield go - async def finalize(): # type: ignore + async def finalize() -> None: while clients: await clients.pop().close() @@ -371,7 +382,7 @@ async def finalize(): # type: ignore @pytest.fixture -def test_client(aiohttp_client): # type: ignore # pragma: no cover +def test_client(aiohttp_client): # type: ignore[no-untyped-def] # pragma: no cover warnings.warn( "Deprecated, use aiohttp_client fixture instead", DeprecationWarning, diff --git a/aiohttp/resolver.py b/aiohttp/resolver.py index 2974bca..531ce93 100644 --- a/aiohttp/resolver.py +++ b/aiohttp/resolver.py @@ -1,6 +1,6 @@ import asyncio import socket -from typing import Any, Dict, List, Optional +from typing import Any, Dict, List, Optional, Type, Union from .abc import AbstractResolver from .helpers import get_running_loop @@ -18,8 +18,10 @@ class ThreadedResolver(AbstractResolver): - """Use Executor for synchronous getaddrinfo() calls, which defaults to - concurrent.futures.ThreadPoolExecutor. + """Threaded resolver. + + Uses an Executor for synchronous getaddrinfo() calls. + concurrent.futures.ThreadPoolExecutor is used by default. """ def __init__(self, loop: Optional[asyncio.AbstractEventLoop] = None) -> None: @@ -38,16 +40,24 @@ async def resolve( hosts = [] for family, _, proto, _, address in infos: - if family == socket.AF_INET6 and address[3]: # type: ignore - # This is essential for link-local IPv6 addresses. - # LL IPv6 is a VERY rare case. Strictly speaking, we should use - # getnameinfo() unconditionally, but performance makes sense. - host, _port = socket.getnameinfo( - address, socket.NI_NUMERICHOST | socket.NI_NUMERICSERV - ) - port = int(_port) - else: - host, port = address[:2] + if family == socket.AF_INET6: + if len(address) < 3: + # IPv6 is not supported by Python build, + # or IPv6 is not enabled in the host + continue + if address[3]: # type: ignore[misc] + # This is essential for link-local IPv6 addresses. + # LL IPv6 is a VERY rare case. Strictly speaking, we should use + # getnameinfo() unconditionally, but performance makes sense. + host, _port = socket.getnameinfo( + address, socket.NI_NUMERICHOST | socket.NI_NUMERICSERV + ) + port = int(_port) + else: + host, port = address[:2] + else: # IPv4 + assert family == socket.AF_INET + host, port = address # type: ignore[misc] hosts.append( { "hostname": hostname, @@ -143,7 +153,8 @@ async def _resolve_with_query( return hosts async def close(self) -> None: - return self._resolver.cancel() + self._resolver.cancel() -DefaultResolver = AsyncResolver if aiodns_default else ThreadedResolver +_DefaultType = Type[Union[AsyncResolver, ThreadedResolver]] +DefaultResolver: _DefaultType = AsyncResolver if aiodns_default else ThreadedResolver diff --git a/aiohttp/signals.py b/aiohttp/signals.py deleted file mode 100644 index d406c02..0000000 --- a/aiohttp/signals.py +++ /dev/null @@ -1,34 +0,0 @@ -from aiohttp.frozenlist import FrozenList - -__all__ = ("Signal",) - - -class Signal(FrozenList): - """Coroutine-based signal implementation. - - To connect a callback to a signal, use any list method. - - Signals are fired using the send() coroutine, which takes named - arguments. - """ - - __slots__ = ("_owner",) - - def __init__(self, owner): - super().__init__() - self._owner = owner - - def __repr__(self): - return "".format( - self._owner, self.frozen, list(self) - ) - - async def send(self, *args, **kwargs): - """ - Sends data to all registered receivers. - """ - if not self.frozen: - raise RuntimeError("Cannot send non-frozen signal.") - - for receiver in self: - await receiver(*args, **kwargs) # type: ignore diff --git a/aiohttp/signals.pyi b/aiohttp/signals.pyi deleted file mode 100644 index 455f8e2..0000000 --- a/aiohttp/signals.pyi +++ /dev/null @@ -1,12 +0,0 @@ -from typing import Any, Generic, TypeVar - -from aiohttp.frozenlist import FrozenList - -__all__ = ("Signal",) - -_T = TypeVar("_T") - -class Signal(FrozenList[_T], Generic[_T]): - def __init__(self, owner: Any) -> None: ... - def __repr__(self) -> str: ... - async def send(self, *args: Any, **kwargs: Any) -> None: ... diff --git a/aiohttp/streams.py b/aiohttp/streams.py index 42970b5..726b023 100644 --- a/aiohttp/streams.py +++ b/aiohttp/streams.py @@ -1,16 +1,12 @@ import asyncio import collections import warnings -from typing import Awaitable, Callable, Generic, List, Optional, Tuple, TypeVar +from typing import Awaitable, Callable, Deque, Generic, List, Optional, Tuple, TypeVar from .base_protocol import BaseProtocol from .helpers import BaseTimerContext, set_exception, set_result from .log import internal_logger - -try: # pragma: no cover - from typing import Deque -except ImportError: - from typing_extensions import Deque +from .typedefs import Final __all__ = ( "EMPTY_PAYLOAD", @@ -60,31 +56,33 @@ async def __anext__(self) -> Tuple[bytes, bool]: class AsyncStreamReaderMixin: def __aiter__(self) -> AsyncStreamIterator[bytes]: - return AsyncStreamIterator(self.readline) # type: ignore + return AsyncStreamIterator(self.readline) # type: ignore[attr-defined] def iter_chunked(self, n: int) -> AsyncStreamIterator[bytes]: """Returns an asynchronous iterator that yields chunks of size n. Python-3.5 available for Python 3.5+ only """ - return AsyncStreamIterator(lambda: self.read(n)) # type: ignore + return AsyncStreamIterator( + lambda: self.read(n) # type: ignore[attr-defined,no-any-return] + ) def iter_any(self) -> AsyncStreamIterator[bytes]: - """Returns an asynchronous iterator that yields all the available - data as soon as it is received + """Yield all available data as soon as it is received. Python-3.5 available for Python 3.5+ only """ - return AsyncStreamIterator(self.readany) # type: ignore + return AsyncStreamIterator(self.readany) # type: ignore[attr-defined] def iter_chunks(self) -> ChunkTupleAsyncStreamIterator: - """Returns an asynchronous iterator that yields chunks of data - as they are received by the server. The yielded objects are tuples + """Yield chunks of data as they are received by the server. + + The yielded objects are tuples of (bytes, bool) as returned by the StreamReader.readchunk method. Python-3.5 available for Python 3.5+ only """ - return ChunkTupleAsyncStreamIterator(self) # type: ignore + return ChunkTupleAsyncStreamIterator(self) # type: ignore[arg-type] class StreamReader(AsyncStreamReaderMixin): @@ -109,7 +107,7 @@ def __init__( limit: int, *, timer: Optional[BaseTimerContext] = None, - loop: Optional[asyncio.AbstractEventLoop] = None + loop: Optional[asyncio.AbstractEventLoop] = None, ) -> None: self._protocol = protocol self._low_water = limit @@ -119,15 +117,15 @@ def __init__( self._loop = loop self._size = 0 self._cursor = 0 - self._http_chunk_splits = None # type: Optional[List[int]] - self._buffer = collections.deque() # type: Deque[bytes] + self._http_chunk_splits: Optional[List[int]] = None + self._buffer: Deque[bytes] = collections.deque() self._buffer_offset = 0 self._eof = False - self._waiter = None # type: Optional[asyncio.Future[None]] - self._eof_waiter = None # type: Optional[asyncio.Future[None]] - self._exception = None # type: Optional[BaseException] + self._waiter: Optional[asyncio.Future[None]] = None + self._eof_waiter: Optional[asyncio.Future[None]] = None + self._exception: Optional[BaseException] = None self._timer = timer - self._eof_callbacks = [] # type: List[Callable[[], None]] + self._eof_callbacks: List[Callable[[], None]] = [] def __repr__(self) -> str: info = [self.__class__.__name__] @@ -135,7 +133,7 @@ def __repr__(self) -> str: info.append("%d bytes" % self._size) if self._eof: info.append("eof") - if self._low_water != 2 ** 16: # default limit + if self._low_water != 2**16: # default limit info.append("low=%d high=%d" % (self._low_water, self._high_water)) if self._waiter: info.append("w=%r" % self._waiter) @@ -310,34 +308,41 @@ async def _wait(self, func_name: str) -> None: self._waiter = None async def readline(self) -> bytes: + return await self.readuntil() + + async def readuntil(self, separator: bytes = b"\n") -> bytes: + seplen = len(separator) + if seplen == 0: + raise ValueError("Separator should be at least one-byte string") + if self._exception is not None: raise self._exception - line = [] - line_size = 0 + chunk = b"" + chunk_size = 0 not_enough = True while not_enough: while self._buffer and not_enough: offset = self._buffer_offset - ichar = self._buffer[0].find(b"\n", offset) + 1 - # Read from current offset to found b'\n' or to the end. + ichar = self._buffer[0].find(separator, offset) + 1 + # Read from current offset to found separator or to the end. data = self._read_nowait_chunk(ichar - offset if ichar else -1) - line.append(data) - line_size += len(data) + chunk += data + chunk_size += len(data) if ichar: not_enough = False - if line_size > self._high_water: - raise ValueError("Line is too long") + if chunk_size > self._high_water: + raise ValueError("Chunk too big") if self._eof: break if not_enough: - await self._wait("readline") + await self._wait("readuntil") - return b"".join(line) + return chunk async def read(self, n: int = -1) -> bytes: if self._exception is not None: @@ -394,7 +399,9 @@ async def readany(self) -> bytes: return self._read_nowait(-1) async def readchunk(self) -> Tuple[bytes, bool]: - """Returns a tuple of (data, end_of_http_chunk). When chunked transfer + """Returns a tuple of (data, end_of_http_chunk). + + When chunked transfer encoding is used, end_of_http_chunk is a boolean indicating if the end of the data corresponds to the end of a HTTP chunk , otherwise it is always False. @@ -429,7 +436,7 @@ async def readexactly(self, n: int) -> bytes: if self._exception is not None: raise self._exception - blocks = [] # type: List[bytes] + blocks: List[bytes] = [] while n > 0: block = await self.read(n) if not block: @@ -483,7 +490,7 @@ def _read_nowait_chunk(self, n: int) -> bytes: return data def _read_nowait(self, n: int) -> bytes: - """ Read not more than n bytes, or whole buffer if n == -1 """ + """Read not more than n bytes, or whole buffer if n == -1""" chunks = [] while self._buffer: @@ -497,7 +504,10 @@ def _read_nowait(self, n: int) -> bytes: return b"".join(chunks) if chunks else b"" -class EmptyStreamReader(AsyncStreamReaderMixin): +class EmptyStreamReader(StreamReader): # lgtm [py/missing-call-to-init] + def __init__(self) -> None: + pass + def exception(self) -> Optional[BaseException]: return None @@ -531,6 +541,8 @@ async def readline(self) -> bytes: async def read(self, n: int = -1) -> bytes: return b"" + # TODO add async def readuntil + async def readany(self) -> bytes: return b"" @@ -540,11 +552,11 @@ async def readchunk(self) -> Tuple[bytes, bool]: async def readexactly(self, n: int) -> bytes: raise asyncio.IncompleteReadError(b"", n) - def read_nowait(self) -> bytes: + def read_nowait(self, n: int = -1) -> bytes: return b"" -EMPTY_PAYLOAD = EmptyStreamReader() +EMPTY_PAYLOAD: Final[StreamReader] = EmptyStreamReader() class DataQueue(Generic[_T]): @@ -553,10 +565,10 @@ class DataQueue(Generic[_T]): def __init__(self, loop: asyncio.AbstractEventLoop) -> None: self._loop = loop self._eof = False - self._waiter = None # type: Optional[asyncio.Future[None]] - self._exception = None # type: Optional[BaseException] + self._waiter: Optional[asyncio.Future[None]] = None + self._exception: Optional[BaseException] = None self._size = 0 - self._buffer = collections.deque() # type: Deque[Tuple[_T, int]] + self._buffer: Deque[Tuple[_T, int]] = collections.deque() def __len__(self) -> int: return len(self._buffer) @@ -623,7 +635,8 @@ def __aiter__(self) -> AsyncStreamIterator[_T]: class FlowControlDataQueue(DataQueue[_T]): """FlowControlDataQueue resumes and pauses an underlying stream. - It is a destination for parsed data.""" + It is a destination for parsed data. + """ def __init__( self, protocol: BaseProtocol, limit: int, *, loop: asyncio.AbstractEventLoop diff --git a/aiohttp/tcp_helpers.py b/aiohttp/tcp_helpers.py index 0e1dbf1..88b2442 100644 --- a/aiohttp/tcp_helpers.py +++ b/aiohttp/tcp_helpers.py @@ -15,7 +15,6 @@ def tcp_keepalive(transport: asyncio.Transport) -> None: if sock is not None: sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1) - else: def tcp_keepalive(transport: asyncio.Transport) -> None: # pragma: no cover diff --git a/aiohttp/test_utils.py b/aiohttp/test_utils.py index 7a9ca7d..fcda2f3 100644 --- a/aiohttp/test_utils.py +++ b/aiohttp/test_utils.py @@ -2,35 +2,41 @@ import asyncio import contextlib -import functools import gc import inspect +import ipaddress import os import socket import sys -import unittest +import warnings from abc import ABC, abstractmethod from types import TracebackType -from typing import TYPE_CHECKING, Any, Callable, Iterator, List, Optional, Type, Union +from typing import ( + TYPE_CHECKING, + Any, + Callable, + Iterator, + List, + Optional, + Type, + Union, + cast, +) from unittest import mock +from aiosignal import Signal from multidict import CIMultiDict, CIMultiDictProxy from yarl import URL import aiohttp -from aiohttp.client import ( - ClientResponse, - _RequestContextManager, - _WSRequestContextManager, -) +from aiohttp.client import _RequestContextManager, _WSRequestContextManager from . import ClientSession, hdrs from .abc import AbstractCookieJar from .client_reqrep import ClientResponse from .client_ws import ClientWebSocketResponse -from .helpers import sentinel +from .helpers import PY_38, sentinel from .http import HttpVersion, RawRequestMessage -from .signals import Signal from .web import ( Application, AppRunner, @@ -48,16 +54,24 @@ else: SSLContext = None +if PY_38: + from unittest import IsolatedAsyncioTestCase as TestCase +else: + from asynctest import TestCase # type: ignore[no-redef] REUSE_ADDRESS = os.name == "posix" and sys.platform != "cygwin" -def get_unused_port_socket(host: str) -> socket.socket: - return get_port_socket(host, 0) +def get_unused_port_socket( + host: str, family: socket.AddressFamily = socket.AF_INET +) -> socket.socket: + return get_port_socket(host, 0, family) -def get_port_socket(host: str, port: int) -> socket.socket: - s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +def get_port_socket( + host: str, port: int, family: socket.AddressFamily +) -> socket.socket: + s = socket.socket(family, socket.SOCK_STREAM) if REUSE_ADDRESS: # Windows has different semantics for SO_REUSEADDR, # so don't set it. Ref: @@ -71,7 +85,7 @@ def unused_port() -> int: """Return a port that is unused on the current host.""" with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.bind(("127.0.0.1", 0)) - return s.getsockname()[1] + return cast(int, s.getsockname()[1]) class BaseTestServer(ABC): @@ -85,16 +99,20 @@ def __init__( host: str = "127.0.0.1", port: Optional[int] = None, skip_url_asserts: bool = False, + socket_factory: Callable[ + [str, int, socket.AddressFamily], socket.socket + ] = get_port_socket, **kwargs: Any, ) -> None: self._loop = loop - self.runner = None # type: Optional[BaseRunner] - self._root = None # type: Optional[URL] + self.runner: Optional[BaseRunner] = None + self._root: Optional[URL] = None self.host = host self.port = port self._closed = False self.scheme = scheme self.skip_url_asserts = skip_url_asserts + self.socket_factory = socket_factory async def start_server( self, loop: Optional[asyncio.AbstractEventLoop] = None, **kwargs: Any @@ -107,7 +125,12 @@ async def start_server( await self.runner.setup() if not self.port: self.port = 0 - _sock = get_port_socket(self.host, self.port) + try: + version = ipaddress.ip_address(self.host).version + except ValueError: + version = 4 + family = socket.AF_INET6 if version == 6 else socket.AF_INET + _sock = self.socket_factory(self.host, self.port, family) self.host, self.port = _sock.getsockname()[:2] site = SockSite(self.runner, sock=_sock, ssl_context=self._ssl) await site.start() @@ -261,8 +284,8 @@ def __init__( cookie_jar = aiohttp.CookieJar(unsafe=True, loop=loop) self._session = ClientSession(loop=loop, cookie_jar=cookie_jar, **kwargs) self._closed = False - self._responses = [] # type: List[ClientResponse] - self._websockets = [] # type: List[ClientWebSocketResponse] + self._responses: List[ClientResponse] = [] + self._websockets: List[ClientWebSocketResponse] = [] async def start_server(self) -> None: await self._server.start_server(loop=self._loop) @@ -280,8 +303,8 @@ def server(self) -> BaseTestServer: return self._server @property - def app(self) -> Application: - return getattr(self._server, "app", None) + def app(self) -> Optional[Application]: + return cast(Optional[Application], getattr(self._server, "app", None)) @property def session(self) -> ClientSession: @@ -400,9 +423,8 @@ async def __aexit__( await self.close() -class AioHTTPTestCase(unittest.TestCase): - """A base class to allow for unittest web applications using - aiohttp. +class AioHTTPTestCase(TestCase): + """A base class to allow for unittest web applications using aiohttp. Provides the following: @@ -417,43 +439,49 @@ class AioHTTPTestCase(unittest.TestCase): """ async def get_application(self) -> Application: - """ + """Get application. + This method should be overridden to return the aiohttp.web.Application object to test. - """ return self.get_app() def get_app(self) -> Application: """Obsolete method used to constructing web application. - Use .get_application() coroutine instead - + Use .get_application() coroutine instead. """ raise RuntimeError("Did you forget to define get_application()?") def setUp(self) -> None: - self.loop = setup_test_loop() - - self.app = self.loop.run_until_complete(self.get_application()) - self.server = self.loop.run_until_complete(self.get_server(self.app)) - self.client = self.loop.run_until_complete(self.get_client(self.server)) + if not PY_38: + asyncio.get_event_loop().run_until_complete(self.asyncSetUp()) - self.loop.run_until_complete(self.client.start_server()) + async def asyncSetUp(self) -> None: + try: + self.loop = asyncio.get_running_loop() + except (AttributeError, RuntimeError): # AttributeError->py36 + self.loop = asyncio.get_event_loop_policy().get_event_loop() - self.loop.run_until_complete(self.setUpAsync()) + return await self.setUpAsync() async def setUpAsync(self) -> None: - pass + self.app = await self.get_application() + self.server = await self.get_server(self.app) + self.client = await self.get_client(self.server) + + await self.client.start_server() def tearDown(self) -> None: - self.loop.run_until_complete(self.tearDownAsync()) - self.loop.run_until_complete(self.client.close()) - teardown_test_loop(self.loop) + if not PY_38: + self.loop.run_until_complete(self.asyncTearDown()) + + async def asyncTearDown(self) -> None: + return await self.tearDownAsync() async def tearDownAsync(self) -> None: - pass + await self.client.close() async def get_server(self, app: Application) -> TestServer: """Return a TestServer instance.""" @@ -465,18 +493,17 @@ async def get_client(self, server: TestServer) -> TestClient: def unittest_run_loop(func: Any, *args: Any, **kwargs: Any) -> Any: - """A decorator dedicated to use with asynchronous methods of an - AioHTTPTestCase. - - Handles executing an asynchronous function, using - the self.loop of the AioHTTPTestCase. """ + A decorator dedicated to use with asynchronous AioHTTPTestCase test methods. - @functools.wraps(func, *args, **kwargs) - def new_func(self: Any, *inner_args: Any, **inner_kwargs: Any) -> Any: - return self.loop.run_until_complete(func(self, *inner_args, **inner_kwargs)) - - return new_func + In 3.8+, this does nothing. + """ + warnings.warn( + "Decorator `@unittest_run_loop` is no longer needed in aiohttp 3.8+", + DeprecationWarning, + stacklevel=2, + ) + return func _LOOP_FACTORY = Callable[[], asyncio.AbstractEventLoop] @@ -498,8 +525,7 @@ def loop_context( def setup_test_loop( loop_factory: _LOOP_FACTORY = asyncio.new_event_loop, ) -> asyncio.AbstractEventLoop: - """Create and return an asyncio.BaseEventLoop - instance. + """Create and return an asyncio.BaseEventLoop instance. The caller should also call teardown_test_loop, once they are done with the loop. @@ -514,7 +540,16 @@ def setup_test_loop( asyncio.set_event_loop(loop) if sys.platform != "win32" and not skip_watcher: policy = asyncio.get_event_loop_policy() - watcher = asyncio.SafeChildWatcher() + watcher: asyncio.AbstractChildWatcher + try: # Python >= 3.8 + # Refs: + # * https://github.com/pytest-dev/pytest-xdist/issues/620 + # * https://stackoverflow.com/a/58614689/595220 + # * https://bugs.python.org/issue35621 + # * https://github.com/python/cpython/pull/14344 + watcher = asyncio.ThreadedChildWatcher() + except AttributeError: # Python < 3.8 + watcher = asyncio.SafeChildWatcher() watcher.attach_loop(loop) with contextlib.suppress(NotImplementedError): policy.set_child_watcher(watcher) @@ -522,10 +557,7 @@ def setup_test_loop( def teardown_test_loop(loop: asyncio.AbstractEventLoop, fast: bool = False) -> None: - """Teardown and cleanup an event_loop created - by setup_test_loop. - - """ + """Teardown and cleanup an event_loop created by setup_test_loop.""" closed = loop.is_closed() if not closed: loop.call_soon(loop.stop) @@ -545,7 +577,7 @@ def get_dict(app: Any, key: str) -> Any: def set_dict(app: Any, key: str, value: Any) -> None: app.__app_dict[key] = value - app = mock.MagicMock() + app = mock.MagicMock(spec=Application) app.__app_dict = {} app.__getitem__ = get_dict app.__setitem__ = set_dict @@ -583,16 +615,14 @@ def make_mocked_request( transport: Any = sentinel, payload: Any = sentinel, sslcontext: Optional[SSLContext] = None, - client_max_size: int = 1024 ** 2, + client_max_size: int = 1024**2, loop: Any = ..., ) -> Request: """Creates mocked web.Request testing purposes. Useful in unit tests, when spinning full web server is overkill or specific conditions and errors are hard to trigger. - """ - task = mock.Mock() if loop is ...: loop = mock.Mock() @@ -619,7 +649,7 @@ def make_mocked_request( headers, raw_hdrs, closing, - False, + None, False, chunked, URL(path), diff --git a/aiohttp/tracing.py b/aiohttp/tracing.py index 7ae7948..d5596a4 100644 --- a/aiohttp/tracing.py +++ b/aiohttp/tracing.py @@ -2,16 +2,15 @@ from typing import TYPE_CHECKING, Awaitable, Optional, Type, TypeVar import attr +from aiosignal import Signal from multidict import CIMultiDict from yarl import URL from .client_reqrep import ClientResponse -from .signals import Signal if TYPE_CHECKING: # pragma: no cover - from typing_extensions import Protocol - from .client import ClientSession + from .typedefs import Protocol _ParamT_contra = TypeVar("_ParamT_contra", contravariant=True) @@ -42,68 +41,71 @@ def __call__( "TraceRequestRedirectParams", "TraceRequestChunkSentParams", "TraceResponseChunkReceivedParams", + "TraceRequestHeadersSentParams", ) class TraceConfig: - """First-class used to trace requests launched via ClientSession - objects.""" + """First-class used to trace requests launched via ClientSession objects.""" def __init__( self, trace_config_ctx_factory: Type[SimpleNamespace] = SimpleNamespace ) -> None: - self._on_request_start = Signal( - self - ) # type: Signal[_SignalCallback[TraceRequestStartParams]] - self._on_request_chunk_sent = Signal( - self - ) # type: Signal[_SignalCallback[TraceRequestChunkSentParams]] - self._on_response_chunk_received = Signal( - self - ) # type: Signal[_SignalCallback[TraceResponseChunkReceivedParams]] - self._on_request_end = Signal( - self - ) # type: Signal[_SignalCallback[TraceRequestEndParams]] - self._on_request_exception = Signal( - self - ) # type: Signal[_SignalCallback[TraceRequestExceptionParams]] - self._on_request_redirect = Signal( - self - ) # type: Signal[_SignalCallback[TraceRequestRedirectParams]] - self._on_connection_queued_start = Signal( - self - ) # type: Signal[_SignalCallback[TraceConnectionQueuedStartParams]] - self._on_connection_queued_end = Signal( - self - ) # type: Signal[_SignalCallback[TraceConnectionQueuedEndParams]] - self._on_connection_create_start = Signal( + self._on_request_start: Signal[ + _SignalCallback[TraceRequestStartParams] + ] = Signal(self) + self._on_request_chunk_sent: Signal[ + _SignalCallback[TraceRequestChunkSentParams] + ] = Signal(self) + self._on_response_chunk_received: Signal[ + _SignalCallback[TraceResponseChunkReceivedParams] + ] = Signal(self) + self._on_request_end: Signal[_SignalCallback[TraceRequestEndParams]] = Signal( self - ) # type: Signal[_SignalCallback[TraceConnectionCreateStartParams]] - self._on_connection_create_end = Signal( - self - ) # type: Signal[_SignalCallback[TraceConnectionCreateEndParams]] - self._on_connection_reuseconn = Signal( - self - ) # type: Signal[_SignalCallback[TraceConnectionReuseconnParams]] - self._on_dns_resolvehost_start = Signal( - self - ) # type: Signal[_SignalCallback[TraceDnsResolveHostStartParams]] - self._on_dns_resolvehost_end = Signal( - self - ) # type: Signal[_SignalCallback[TraceDnsResolveHostEndParams]] - self._on_dns_cache_hit = Signal( - self - ) # type: Signal[_SignalCallback[TraceDnsCacheHitParams]] - self._on_dns_cache_miss = Signal( - self - ) # type: Signal[_SignalCallback[TraceDnsCacheMissParams]] + ) + self._on_request_exception: Signal[ + _SignalCallback[TraceRequestExceptionParams] + ] = Signal(self) + self._on_request_redirect: Signal[ + _SignalCallback[TraceRequestRedirectParams] + ] = Signal(self) + self._on_connection_queued_start: Signal[ + _SignalCallback[TraceConnectionQueuedStartParams] + ] = Signal(self) + self._on_connection_queued_end: Signal[ + _SignalCallback[TraceConnectionQueuedEndParams] + ] = Signal(self) + self._on_connection_create_start: Signal[ + _SignalCallback[TraceConnectionCreateStartParams] + ] = Signal(self) + self._on_connection_create_end: Signal[ + _SignalCallback[TraceConnectionCreateEndParams] + ] = Signal(self) + self._on_connection_reuseconn: Signal[ + _SignalCallback[TraceConnectionReuseconnParams] + ] = Signal(self) + self._on_dns_resolvehost_start: Signal[ + _SignalCallback[TraceDnsResolveHostStartParams] + ] = Signal(self) + self._on_dns_resolvehost_end: Signal[ + _SignalCallback[TraceDnsResolveHostEndParams] + ] = Signal(self) + self._on_dns_cache_hit: Signal[ + _SignalCallback[TraceDnsCacheHitParams] + ] = Signal(self) + self._on_dns_cache_miss: Signal[ + _SignalCallback[TraceDnsCacheMissParams] + ] = Signal(self) + self._on_request_headers_sent: Signal[ + _SignalCallback[TraceRequestHeadersSentParams] + ] = Signal(self) self._trace_config_ctx_factory = trace_config_ctx_factory def trace_config_ctx( self, trace_request_ctx: Optional[SimpleNamespace] = None ) -> SimpleNamespace: - """ Return a new trace_config_ctx instance """ + """Return a new trace_config_ctx instance""" return self._trace_config_ctx_factory(trace_request_ctx=trace_request_ctx) def freeze(self) -> None: @@ -122,6 +124,7 @@ def freeze(self) -> None: self._on_dns_resolvehost_end.freeze() self._on_dns_cache_hit.freeze() self._on_dns_cache_miss.freeze() + self._on_request_headers_sent.freeze() @property def on_request_start(self) -> "Signal[_SignalCallback[TraceRequestStartParams]]": @@ -205,10 +208,16 @@ def on_dns_cache_hit(self) -> "Signal[_SignalCallback[TraceDnsCacheHitParams]]": def on_dns_cache_miss(self) -> "Signal[_SignalCallback[TraceDnsCacheMissParams]]": return self._on_dns_cache_miss + @property + def on_request_headers_sent( + self, + ) -> "Signal[_SignalCallback[TraceRequestHeadersSentParams]]": + return self._on_request_headers_sent + @attr.s(auto_attribs=True, frozen=True, slots=True) class TraceRequestStartParams: - """ Parameters sent by the `on_request_start` signal""" + """Parameters sent by the `on_request_start` signal""" method: str url: URL @@ -217,7 +226,7 @@ class TraceRequestStartParams: @attr.s(auto_attribs=True, frozen=True, slots=True) class TraceRequestChunkSentParams: - """ Parameters sent by the `on_request_chunk_sent` signal""" + """Parameters sent by the `on_request_chunk_sent` signal""" method: str url: URL @@ -226,7 +235,7 @@ class TraceRequestChunkSentParams: @attr.s(auto_attribs=True, frozen=True, slots=True) class TraceResponseChunkReceivedParams: - """ Parameters sent by the `on_response_chunk_received` signal""" + """Parameters sent by the `on_response_chunk_received` signal""" method: str url: URL @@ -235,7 +244,7 @@ class TraceResponseChunkReceivedParams: @attr.s(auto_attribs=True, frozen=True, slots=True) class TraceRequestEndParams: - """ Parameters sent by the `on_request_end` signal""" + """Parameters sent by the `on_request_end` signal""" method: str url: URL @@ -245,7 +254,7 @@ class TraceRequestEndParams: @attr.s(auto_attribs=True, frozen=True, slots=True) class TraceRequestExceptionParams: - """ Parameters sent by the `on_request_exception` signal""" + """Parameters sent by the `on_request_exception` signal""" method: str url: URL @@ -255,7 +264,7 @@ class TraceRequestExceptionParams: @attr.s(auto_attribs=True, frozen=True, slots=True) class TraceRequestRedirectParams: - """ Parameters sent by the `on_request_redirect` signal""" + """Parameters sent by the `on_request_redirect` signal""" method: str url: URL @@ -265,60 +274,72 @@ class TraceRequestRedirectParams: @attr.s(auto_attribs=True, frozen=True, slots=True) class TraceConnectionQueuedStartParams: - """ Parameters sent by the `on_connection_queued_start` signal""" + """Parameters sent by the `on_connection_queued_start` signal""" @attr.s(auto_attribs=True, frozen=True, slots=True) class TraceConnectionQueuedEndParams: - """ Parameters sent by the `on_connection_queued_end` signal""" + """Parameters sent by the `on_connection_queued_end` signal""" @attr.s(auto_attribs=True, frozen=True, slots=True) class TraceConnectionCreateStartParams: - """ Parameters sent by the `on_connection_create_start` signal""" + """Parameters sent by the `on_connection_create_start` signal""" @attr.s(auto_attribs=True, frozen=True, slots=True) class TraceConnectionCreateEndParams: - """ Parameters sent by the `on_connection_create_end` signal""" + """Parameters sent by the `on_connection_create_end` signal""" @attr.s(auto_attribs=True, frozen=True, slots=True) class TraceConnectionReuseconnParams: - """ Parameters sent by the `on_connection_reuseconn` signal""" + """Parameters sent by the `on_connection_reuseconn` signal""" @attr.s(auto_attribs=True, frozen=True, slots=True) class TraceDnsResolveHostStartParams: - """ Parameters sent by the `on_dns_resolvehost_start` signal""" + """Parameters sent by the `on_dns_resolvehost_start` signal""" host: str @attr.s(auto_attribs=True, frozen=True, slots=True) class TraceDnsResolveHostEndParams: - """ Parameters sent by the `on_dns_resolvehost_end` signal""" + """Parameters sent by the `on_dns_resolvehost_end` signal""" host: str @attr.s(auto_attribs=True, frozen=True, slots=True) class TraceDnsCacheHitParams: - """ Parameters sent by the `on_dns_cache_hit` signal""" + """Parameters sent by the `on_dns_cache_hit` signal""" host: str @attr.s(auto_attribs=True, frozen=True, slots=True) class TraceDnsCacheMissParams: - """ Parameters sent by the `on_dns_cache_miss` signal""" + """Parameters sent by the `on_dns_cache_miss` signal""" host: str +@attr.s(auto_attribs=True, frozen=True, slots=True) +class TraceRequestHeadersSentParams: + """Parameters sent by the `on_request_headers_sent` signal""" + + method: str + url: URL + headers: "CIMultiDict[str]" + + class Trace: - """Internal class used to keep together the main dependencies used - at the moment of send a signal.""" + """Internal dependency holder class. + + Used to keep together the main dependencies used + at the moment of send a signal. + """ def __init__( self, @@ -440,3 +461,12 @@ async def send_dns_cache_miss(self, host: str) -> None: return await self._trace_config.on_dns_cache_miss.send( self._session, self._trace_config_ctx, TraceDnsCacheMissParams(host) ) + + async def send_request_headers( + self, method: str, url: URL, headers: "CIMultiDict[str]" + ) -> None: + return await self._trace_config._on_request_headers_sent.send( + self._session, + self._trace_config_ctx, + TraceRequestHeadersSentParams(method, url, headers), + ) diff --git a/aiohttp/typedefs.py b/aiohttp/typedefs.py index 1b68a24..84283d9 100644 --- a/aiohttp/typedefs.py +++ b/aiohttp/typedefs.py @@ -1,12 +1,30 @@ import json import os -import pathlib import sys -from typing import TYPE_CHECKING, Any, Callable, Iterable, Mapping, Tuple, Union +from typing import ( + TYPE_CHECKING, + Any, + Awaitable, + Callable, + Iterable, + Mapping, + Tuple, + Union, +) from multidict import CIMultiDict, CIMultiDictProxy, MultiDict, MultiDictProxy, istr from yarl import URL +# These are for other modules to use (to avoid repeating the conditional import). +if sys.version_info >= (3, 8): + from typing import Final as Final, Protocol as Protocol, TypedDict as TypedDict +else: + from typing_extensions import ( # noqa: F401 + Final, + Protocol as Protocol, + TypedDict as TypedDict, + ) + DEFAULT_JSON_ENCODER = json.dumps DEFAULT_JSON_DECODER = json.loads @@ -16,6 +34,8 @@ _MultiDict = MultiDict[str] _MultiDictProxy = MultiDictProxy[str] from http.cookies import BaseCookie, Morsel + + from .web import Request, StreamResponse else: _CIMultiDict = CIMultiDict _CIMultiDictProxy = CIMultiDictProxy @@ -39,8 +59,6 @@ "BaseCookie[str]", ] +Handler = Callable[["Request"], Awaitable["StreamResponse"]] -if sys.version_info >= (3, 6): - PathLike = Union[str, "os.PathLike[str]"] -else: - PathLike = Union[str, pathlib.PurePath] +PathLike = Union[str, "os.PathLike[str]"] diff --git a/aiohttp/web.py b/aiohttp/web.py index 557e3c3..cefae2b 100644 --- a/aiohttp/web.py +++ b/aiohttp/web.py @@ -6,16 +6,16 @@ from collections.abc import Iterable from importlib import import_module from typing import ( - Any as Any, - Awaitable as Awaitable, - Callable as Callable, + Any, + Awaitable, + Callable, Iterable as TypingIterable, - List as List, - Optional as Optional, - Set as Set, - Type as Type, - Union as Union, - cast as cast, + List, + Optional, + Set, + Type, + Union, + cast, ) from .abc import AbstractAccessLogger @@ -136,6 +136,7 @@ AbstractRoute as AbstractRoute, DynamicResource as DynamicResource, PlainResource as PlainResource, + PrefixedSubAppResource as PrefixedSubAppResource, Resource as Resource, ResourceRoute as ResourceRoute, StaticResource as StaticResource, @@ -261,6 +262,7 @@ "AbstractRoute", "DynamicResource", "PlainResource", + "PrefixedSubAppResource", "Resource", "ResourceRoute", "StaticResource", @@ -279,7 +281,7 @@ try: from ssl import SSLContext except ImportError: # pragma: no cover - SSLContext = Any # type: ignore + SSLContext = Any # type: ignore[misc,assignment] HostSequence = TypingIterable[str] @@ -290,8 +292,9 @@ async def _run_app( host: Optional[Union[str, HostSequence]] = None, port: Optional[int] = None, path: Optional[str] = None, - sock: Optional[socket.socket] = None, + sock: Optional[Union[socket.socket, TypingIterable[socket.socket]]] = None, shutdown_timeout: float = 60.0, + keepalive_timeout: float = 75.0, ssl_context: Optional[SSLContext] = None, print: Callable[..., None] = print, backlog: int = 128, @@ -304,7 +307,7 @@ async def _run_app( ) -> None: # A internal functio to actually do all dirty job for application running if asyncio.iscoroutine(app): - app = await app # type: ignore + app = await app # type: ignore[misc] app = cast(Application, app) @@ -314,11 +317,12 @@ async def _run_app( access_log_class=access_log_class, access_log_format=access_log_format, access_log=access_log, + keepalive_timeout=keepalive_timeout, ) await runner.setup() - sites = [] # type: List[BaseSite] + sites: List[BaseSite] = [] try: if host is not None: @@ -440,9 +444,7 @@ def _cancel_tasks( for task in to_cancel: task.cancel() - loop.run_until_complete( - asyncio.gather(*to_cancel, loop=loop, return_exceptions=True) - ) + loop.run_until_complete(asyncio.gather(*to_cancel, return_exceptions=True)) for task in to_cancel: if task.cancelled(): @@ -463,8 +465,9 @@ def run_app( host: Optional[Union[str, HostSequence]] = None, port: Optional[int] = None, path: Optional[str] = None, - sock: Optional[socket.socket] = None, + sock: Optional[Union[socket.socket, TypingIterable[socket.socket]]] = None, shutdown_timeout: float = 60.0, + keepalive_timeout: float = 75.0, ssl_context: Optional[SSLContext] = None, print: Callable[..., None] = print, backlog: int = 128, @@ -474,9 +477,11 @@ def run_app( handle_signals: bool = True, reuse_address: Optional[bool] = None, reuse_port: Optional[bool] = None, + loop: Optional[asyncio.AbstractEventLoop] = None, ) -> None: """Run an app locally""" - loop = asyncio.get_event_loop() + if loop is None: + loop = asyncio.new_event_loop() # Configure if and only if in debugging mode and using the default logger if loop.get_debug() and access_log and access_log.name == "aiohttp.access": @@ -485,34 +490,36 @@ def run_app( if not access_log.hasHandlers(): access_log.addHandler(logging.StreamHandler()) - try: - main_task = loop.create_task( - _run_app( - app, - host=host, - port=port, - path=path, - sock=sock, - shutdown_timeout=shutdown_timeout, - ssl_context=ssl_context, - print=print, - backlog=backlog, - access_log_class=access_log_class, - access_log_format=access_log_format, - access_log=access_log, - handle_signals=handle_signals, - reuse_address=reuse_address, - reuse_port=reuse_port, - ) + main_task = loop.create_task( + _run_app( + app, + host=host, + port=port, + path=path, + sock=sock, + shutdown_timeout=shutdown_timeout, + keepalive_timeout=keepalive_timeout, + ssl_context=ssl_context, + print=print, + backlog=backlog, + access_log_class=access_log_class, + access_log_format=access_log_format, + access_log=access_log, + handle_signals=handle_signals, + reuse_address=reuse_address, + reuse_port=reuse_port, ) + ) + + try: + asyncio.set_event_loop(loop) loop.run_until_complete(main_task) except (GracefulExit, KeyboardInterrupt): # pragma: no cover pass finally: _cancel_tasks({main_task}, loop) _cancel_tasks(all_tasks(loop), loop) - if sys.version_info >= (3, 6): # don't use PY_36 to pass mypy - loop.run_until_complete(loop.shutdown_asyncgens()) + loop.run_until_complete(loop.shutdown_asyncgens()) loop.close() diff --git a/aiohttp/web_app.py b/aiohttp/web_app.py index 14f2937..8fd4471 100644 --- a/aiohttp/web_app.py +++ b/aiohttp/web_app.py @@ -22,6 +22,9 @@ cast, ) +from aiosignal import Signal +from frozenlist import FrozenList + from . import hdrs from .abc import ( AbstractAccessLogger, @@ -29,11 +32,9 @@ AbstractRouter, AbstractStreamWriter, ) -from .frozenlist import FrozenList from .helpers import DEBUG from .http_parser import RawRequestMessage from .log import web_logger -from .signals import Signal from .streams import StreamReader from .web_log import AccessLogger from .web_middlewares import _fix_request_current_app @@ -56,12 +57,13 @@ if TYPE_CHECKING: # pragma: no cover + from .typedefs import Handler + _AppSignal = Signal[Callable[["Application"], Awaitable[None]]] _RespPrepareSignal = Signal[Callable[[Request, StreamResponse], Awaitable[None]]] - _Handler = Callable[[Request], Awaitable[StreamResponse]] _Middleware = Union[ - Callable[[Request, _Handler], Awaitable[StreamResponse]], - Callable[["Application", _Handler], Awaitable[_Handler]], # old-style + Callable[[Request, Handler], Awaitable[StreamResponse]], + Callable[["Application", Handler], Awaitable[Handler]], # old-style ] _Middlewares = FrozenList[_Middleware] _MiddlewaresHandlers = Optional[Sequence[Tuple[_Middleware, bool]]] @@ -70,7 +72,6 @@ # No type checker mode, skip types _AppSignal = Signal _RespPrepareSignal = Signal - _Handler = Callable _Middleware = Callable _Middlewares = FrozenList _MiddlewaresHandlers = Optional[Sequence] @@ -108,7 +109,7 @@ def __init__( router: Optional[UrlDispatcher] = None, middlewares: Iterable[_Middleware] = (), handler_args: Optional[Mapping[str, Any]] = None, - client_max_size: int = 1024 ** 2, + client_max_size: int = 1024**2, loop: Optional[asyncio.AbstractEventLoop] = None, debug: Any = ..., # mypy doesn't support ellipsis ) -> None: @@ -130,27 +131,27 @@ def __init__( "debug argument is deprecated", DeprecationWarning, stacklevel=2 ) self._debug = debug - self._router = router # type: UrlDispatcher + self._router: UrlDispatcher = router self._loop = loop self._handler_args = handler_args self.logger = logger - self._middlewares = FrozenList(middlewares) # type: _Middlewares + self._middlewares: _Middlewares = FrozenList(middlewares) # initialized on freezing - self._middlewares_handlers = None # type: _MiddlewaresHandlers + self._middlewares_handlers: _MiddlewaresHandlers = None # initialized on freezing - self._run_middlewares = None # type: Optional[bool] + self._run_middlewares: Optional[bool] = None - self._state = {} # type: Dict[str, Any] + self._state: Dict[str, Any] = {} self._frozen = False self._pre_frozen = False - self._subapps = [] # type: _Subapps + self._subapps: _Subapps = [] - self._on_response_prepare = Signal(self) # type: _RespPrepareSignal - self._on_startup = Signal(self) # type: _AppSignal - self._on_shutdown = Signal(self) # type: _AppSignal - self._on_cleanup = Signal(self) # type: _AppSignal + self._on_response_prepare: _RespPrepareSignal = Signal(self) + self._on_startup: _AppSignal = Signal(self) + self._on_shutdown: _AppSignal = Signal(self) + self._on_cleanup: _AppSignal = Signal(self) self._cleanup_ctx = CleanupContext() self._on_startup.append(self._cleanup_ctx._on_startup) self._on_cleanup.append(self._cleanup_ctx._on_cleanup) @@ -278,7 +279,7 @@ def freeze(self) -> None: @property def debug(self) -> bool: warnings.warn("debug property is deprecated", DeprecationWarning, stacklevel=2) - return self._debug + return self._debug # type: ignore[no-any-return] def _reg_subapp_signals(self, subapp: "Application") -> None: def reg_handler(signame: str) -> None: @@ -323,7 +324,7 @@ def add_domain(self, domain: str, subapp: "Application") -> AbstractResource: if not isinstance(domain, str): raise TypeError("Domain must be str") elif "*" in domain: - rule = MaskDomain(domain) # type: Domain + rule: Domain = MaskDomain(domain) else: rule = Domain(domain) factory = partial(MatchedSubAppResource, rule, subapp) @@ -384,7 +385,7 @@ def _make_handler( kwargs[k] = v return Server( - self._handle, # type: ignore + self._handle, # type: ignore[arg-type] request_factory=self._make_request, loop=self._loop, **kwargs, @@ -427,7 +428,11 @@ async def cleanup(self) -> None: Should be called after shutdown() """ - await self.on_cleanup.send(self) + if self.on_cleanup.frozen: + await self.on_cleanup.send(self) + else: + # If an exception occurs in startup, ensure cleanup contexts are completed. + await self._cleanup_ctx._on_cleanup(self) def _make_request( self, @@ -477,7 +482,7 @@ async def _handle(self, request: Request) -> StreamResponse: match_info.freeze() resp = None - request._match_info = match_info # type: ignore + request._match_info = match_info expect = request.headers.get(hdrs.EXPECT) if expect: resp = await match_info.expect_handler(request) @@ -488,13 +493,13 @@ async def _handle(self, request: Request) -> StreamResponse: if self._run_middlewares: for app in match_info.apps[::-1]: - for m, new_style in app._middlewares_handlers: # type: ignore + for m, new_style in app._middlewares_handlers: # type: ignore[union-attr] # noqa if new_style: handler = update_wrapper( partial(m, handler=handler), handler ) else: - handler = await m(app, handler) # type: ignore + handler = await m(app, handler) # type: ignore[arg-type] resp = await handler(request) @@ -505,7 +510,7 @@ def __call__(self) -> "Application": return self def __repr__(self) -> str: - return "".format(id(self)) + return f"" def __bool__(self) -> bool: return True @@ -514,7 +519,7 @@ def __bool__(self) -> bool: class CleanupError(RuntimeError): @property def exceptions(self) -> List[BaseException]: - return self.args[1] + return cast(List[BaseException], self.args[1]) if TYPE_CHECKING: # pragma: no cover @@ -526,7 +531,7 @@ def exceptions(self) -> List[BaseException]: class CleanupContext(_CleanupContextBase): def __init__(self) -> None: super().__init__() - self._exits = [] # type: List[AsyncIterator[None]] + self._exits: List[AsyncIterator[None]] = [] async def _on_startup(self, app: Application) -> None: for cb in self: diff --git a/aiohttp/web_exceptions.py b/aiohttp/web_exceptions.py index 2eadca0..ae706a1 100644 --- a/aiohttp/web_exceptions.py +++ b/aiohttp/web_exceptions.py @@ -273,7 +273,7 @@ def __init__( content_type=content_type, ) self.headers["Allow"] = allow - self.allowed_methods = set(allowed_methods) # type: Set[str] + self.allowed_methods: Set[str] = set(allowed_methods) self.method = method.upper() diff --git a/aiohttp/web_fileresponse.py b/aiohttp/web_fileresponse.py index 0737c4f..f41ed3f 100644 --- a/aiohttp/web_fileresponse.py +++ b/aiohttp/web_fileresponse.py @@ -9,15 +9,18 @@ Any, Awaitable, Callable, + Iterator, List, Optional, + Tuple, Union, cast, ) from . import hdrs from .abc import AbstractStreamWriter -from .typedefs import LooseHeaders +from .helpers import ETAG_ANY, ETag +from .typedefs import Final, LooseHeaders from .web_exceptions import ( HTTPNotModified, HTTPPartialContent, @@ -35,7 +38,7 @@ _T_OnChunkSent = Optional[Callable[[bytes], Awaitable[None]]] -NOSENDFILE = bool(os.environ.get("AIOHTTP_NOSENDFILE")) +NOSENDFILE: Final[bool] = bool(os.environ.get("AIOHTTP_NOSENDFILE")) class FileResponse(StreamResponse): @@ -100,6 +103,30 @@ async def _sendfile( await super().write_eof() return writer + @staticmethod + def _strong_etag_match(etag_value: str, etags: Tuple[ETag, ...]) -> bool: + if len(etags) == 1 and etags[0].value == ETAG_ANY: + return True + return any(etag.value == etag_value for etag in etags if not etag.is_weak) + + async def _not_modified( + self, request: "BaseRequest", etag_value: str, last_modified: float + ) -> Optional[AbstractStreamWriter]: + self.set_status(HTTPNotModified.status_code) + self._length_check = False + self.etag = etag_value # type: ignore[assignment] + self.last_modified = last_modified # type: ignore[assignment] + # Delete any Content-Length headers provided by user. HTTP 304 + # should always have empty response body + return await super().prepare(request) + + async def _precondition_failed( + self, request: "BaseRequest" + ) -> Optional[AbstractStreamWriter]: + self.set_status(HTTPPreconditionFailed.status_code) + self.content_length = 0 + return await super().prepare(request) + async def prepare(self, request: "BaseRequest") -> Optional[AbstractStreamWriter]: filepath = self._path @@ -112,20 +139,35 @@ async def prepare(self, request: "BaseRequest") -> Optional[AbstractStreamWriter gzip = True loop = asyncio.get_event_loop() - st = await loop.run_in_executor(None, filepath.stat) + st: os.stat_result = await loop.run_in_executor(None, filepath.stat) - modsince = request.if_modified_since - if modsince is not None and st.st_mtime <= modsince.timestamp(): - self.set_status(HTTPNotModified.status_code) - self._length_check = False - # Delete any Content-Length headers provided by user. HTTP 304 - # should always have empty response body - return await super().prepare(request) + etag_value = f"{st.st_mtime_ns:x}-{st.st_size:x}" + last_modified = st.st_mtime + + # https://tools.ietf.org/html/rfc7232#section-6 + ifmatch = request.if_match + if ifmatch is not None and not self._strong_etag_match(etag_value, ifmatch): + return await self._precondition_failed(request) unmodsince = request.if_unmodified_since - if unmodsince is not None and st.st_mtime > unmodsince.timestamp(): - self.set_status(HTTPPreconditionFailed.status_code) - return await super().prepare(request) + if ( + unmodsince is not None + and ifmatch is None + and st.st_mtime > unmodsince.timestamp() + ): + return await self._precondition_failed(request) + + ifnonematch = request.if_none_match + if ifnonematch is not None and self._strong_etag_match(etag_value, ifnonematch): + return await self._not_modified(request, etag_value, last_modified) + + modsince = request.if_modified_since + if ( + modsince is not None + and ifnonematch is None + and st.st_mtime <= modsince.timestamp() + ): + return await self._not_modified(request, etag_value, last_modified) if hdrs.CONTENT_TYPE not in self.headers: ct, encoding = mimetypes.guess_type(str(filepath)) @@ -211,12 +253,14 @@ async def prepare(self, request: "BaseRequest") -> Optional[AbstractStreamWriter self.set_status(status) if should_set_ct: - self.content_type = ct # type: ignore + self.content_type = ct # type: ignore[assignment] if encoding: self.headers[hdrs.CONTENT_ENCODING] = encoding if gzip: self.headers[hdrs.VARY] = hdrs.ACCEPT_ENCODING - self.last_modified = st.st_mtime # type: ignore + + self.etag = etag_value # type: ignore[assignment] + self.last_modified = st.st_mtime # type: ignore[assignment] self.content_length = count self.headers[hdrs.ACCEPT_RANGES] = "bytes" @@ -228,7 +272,8 @@ async def prepare(self, request: "BaseRequest") -> Optional[AbstractStreamWriter real_start, real_start + count - 1, file_size ) - if request.method == hdrs.METH_HEAD or self.status in [204, 304]: + # If we are sending 0 bytes calling sendfile() will throw a ValueError + if count == 0 or request.method == hdrs.METH_HEAD or self.status in [204, 304]: return await super().prepare(request) fobj = await loop.run_in_executor(None, filepath.open, "rb") diff --git a/aiohttp/web_log.py b/aiohttp/web_log.py index 4cfa579..bc6e3b5 100644 --- a/aiohttp/web_log.py +++ b/aiohttp/web_log.py @@ -57,7 +57,7 @@ class AccessLogger(AbstractAccessLogger): LOG_FORMAT = '%a %t "%r" %s %b "%{Referer}i" "%{User-Agent}i"' FORMAT_RE = re.compile(r"%(\{([A-Za-z0-9\-_]+)\}([ioe])|[atPrsbOD]|Tf?)") CLEANUP_RE = re.compile(r"(%[^s])") - _FORMAT_CACHE = {} # type: Dict[str, Tuple[str, List[KeyMethod]]] + _FORMAT_CACHE: Dict[str, Tuple[str, List[KeyMethod]]] = {} def __init__(self, logger: logging.Logger, log_format: str = LOG_FORMAT) -> None: """Initialise the logger. @@ -198,10 +198,10 @@ def log(self, request: BaseRequest, response: StreamResponse, time: float) -> No if key.__class__ is str: extra[key] = value else: - k1, k2 = key # type: ignore - dct = extra.get(k1, {}) # type: ignore - dct[k2] = value # type: ignore - extra[k1] = dct # type: ignore + k1, k2 = key # type: ignore[misc] + dct = extra.get(k1, {}) # type: ignore[var-annotated,has-type] + dct[k2] = value # type: ignore[index,has-type] + extra[k1] = dct # type: ignore[has-type,assignment] self.logger.info(self._log_format % tuple(values), extra=extra) except Exception: diff --git a/aiohttp/web_middlewares.py b/aiohttp/web_middlewares.py index 8a8967e..fabcc44 100644 --- a/aiohttp/web_middlewares.py +++ b/aiohttp/web_middlewares.py @@ -1,6 +1,7 @@ import re from typing import TYPE_CHECKING, Awaitable, Callable, Tuple, Type, TypeVar +from .typedefs import Handler from .web_exceptions import HTTPPermanentRedirect, _HTTPMove from .web_request import Request from .web_response import StreamResponse @@ -21,7 +22,7 @@ async def _check_request_resolves(request: Request, path: str) -> Tuple[bool, Re alt_request = request.clone(rel_url=path) match_info = await request.app.router.resolve(alt_request) - alt_request._match_info = match_info # type: ignore + alt_request._match_info = match_info if match_info.http_exception is None: return True, alt_request @@ -30,12 +31,11 @@ async def _check_request_resolves(request: Request, path: str) -> Tuple[bool, Re def middleware(f: _Func) -> _Func: - f.__middleware_version__ = 1 # type: ignore + f.__middleware_version__ = 1 # type: ignore[attr-defined] return f -_Handler = Callable[[Request], Awaitable[StreamResponse]] -_Middleware = Callable[[Request, _Handler], Awaitable[StreamResponse]] +_Middleware = Callable[[Request, Handler], Awaitable[StreamResponse]] def normalize_path_middleware( @@ -43,12 +43,11 @@ def normalize_path_middleware( append_slash: bool = True, remove_slash: bool = False, merge_slashes: bool = True, - redirect_class: Type[_HTTPMove] = HTTPPermanentRedirect + redirect_class: Type[_HTTPMove] = HTTPPermanentRedirect, ) -> _Middleware: - """ - Middleware factory which produces a middleware that normalizes - the path of a request. By normalizing it means: + """Factory for producing a middleware that normalizes the path of a request. + Normalizing means: - Add or remove a trailing slash to the path. - Double slashes are replaced by one. @@ -74,12 +73,11 @@ def normalize_path_middleware( If merge_slashes is True, merge multiple consecutive slashes in the path into one. """ - correct_configuration = not (append_slash and remove_slash) assert correct_configuration, "Cannot both remove and append slash" @middleware - async def impl(request: Request, handler: _Handler) -> StreamResponse: + async def impl(request: Request, handler: Handler) -> StreamResponse: if isinstance(request.match_info.route, SystemRoute): paths_to_check = [] if "?" in request.raw_path: @@ -114,7 +112,7 @@ async def impl(request: Request, handler: _Handler) -> StreamResponse: def _fix_request_current_app(app: "Application") -> _Middleware: @middleware - async def impl(request: Request, handler: _Handler) -> StreamResponse: + async def impl(request: Request, handler: Handler) -> StreamResponse: with request.match_info.set_current_app(app): return await handler(request) diff --git a/aiohttp/web_protocol.py b/aiohttp/web_protocol.py index 8e02bc4..10a9608 100644 --- a/aiohttp/web_protocol.py +++ b/aiohttp/web_protocol.py @@ -7,13 +7,26 @@ from html import escape as html_escape from http import HTTPStatus from logging import Logger -from typing import TYPE_CHECKING, Any, Awaitable, Callable, Optional, Tuple, Type, cast +from typing import ( + TYPE_CHECKING, + Any, + Awaitable, + Callable, + Deque, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import attr import yarl from .abc import AbstractAccessLogger, AbstractStreamWriter from .base_protocol import BaseProtocol -from .helpers import CeilTimeout, current_task +from .helpers import ceil_timeout from .http import ( HttpProcessingError, HttpRequestParser, @@ -48,9 +61,17 @@ _RequestHandler = Callable[[BaseRequest], Awaitable[StreamResponse]] - ERROR = RawRequestMessage( - "UNKNOWN", "/", HttpVersion10, {}, {}, True, False, False, False, yarl.URL("/") + "UNKNOWN", + "/", + HttpVersion10, + {}, # type: ignore[arg-type] + {}, # type: ignore[arg-type] + True, + None, + False, + False, + yarl.URL("/"), ) @@ -62,6 +83,16 @@ class PayloadAccessError(Exception): """Payload was accessed after response was sent.""" +@attr.s(auto_attribs=True, frozen=True, slots=True) +class _ErrInfo: + status: int + exc: BaseException + message: str + + +_MsgType = Tuple[Union[RawRequestMessage, _ErrInfo], StreamReader] + + class RequestHandler(BaseProtocol): """HTTP protocol implementation. @@ -73,32 +104,28 @@ class RequestHandler(BaseProtocol): status line, bad headers or incomplete payload. If any error occurs, connection gets closed. - :param keepalive_timeout: number of seconds before closing - keep-alive connection - :type keepalive_timeout: int or None + keepalive_timeout -- number of seconds before closing + keep-alive connection - :param bool tcp_keepalive: TCP keep-alive is on, default is on + tcp_keepalive -- TCP keep-alive is on, default is on - :param bool debug: enable debug mode + debug -- enable debug mode - :param logger: custom logger object - :type logger: aiohttp.log.server_logger + logger -- custom logger object - :param access_log_class: custom class for access_logger - :type access_log_class: aiohttp.abc.AbstractAccessLogger + access_log_class -- custom class for access_logger - :param access_log: custom logging object - :type access_log: aiohttp.log.server_logger + access_log -- custom logging object - :param str access_log_format: access log format string + access_log_format -- access log format string - :param loop: Optional event loop + loop -- Optional event loop - :param int max_line_size: Optional maximum header line size + max_line_size -- Optional maximum header line size - :param int max_field_size: Optional maximum header field size + max_field_size -- Optional maximum header field size - :param int max_headers: Optional maximum header size + max_headers -- Optional maximum header size """ @@ -118,7 +145,6 @@ class RequestHandler(BaseProtocol): "_messages", "_message_tail", "_waiter", - "_error_handler", "_task_handler", "_upgrade", "_payload_parser", @@ -149,39 +175,34 @@ def __init__( max_headers: int = 32768, max_field_size: int = 8190, lingering_time: float = 10.0, - read_bufsize: int = 2 ** 16, + read_bufsize: int = 2**16, + auto_decompress: bool = True, ): - super().__init__(loop) self._request_count = 0 self._keepalive = False - self._current_request = None # type: Optional[BaseRequest] - self._manager = manager # type: Optional[Server] - self._request_handler = ( - manager.request_handler - ) # type: Optional[_RequestHandler] - self._request_factory = ( - manager.request_factory - ) # type: Optional[_RequestFactory] + self._current_request: Optional[BaseRequest] = None + self._manager: Optional[Server] = manager + self._request_handler: Optional[_RequestHandler] = manager.request_handler + self._request_factory: Optional[_RequestFactory] = manager.request_factory self._tcp_keepalive = tcp_keepalive # placeholder to be replaced on keepalive timeout setup self._keepalive_time = 0.0 - self._keepalive_handle = None # type: Optional[asyncio.Handle] + self._keepalive_handle: Optional[asyncio.Handle] = None self._keepalive_timeout = keepalive_timeout self._lingering_time = float(lingering_time) - self._messages = deque() # type: Any # Python 3.5 has no typing.Deque + self._messages: Deque[_MsgType] = deque() self._message_tail = b"" - self._waiter = None # type: Optional[asyncio.Future[None]] - self._error_handler = None # type: Optional[asyncio.Task[None]] - self._task_handler = None # type: Optional[asyncio.Task[None]] + self._waiter: Optional[asyncio.Future[None]] = None + self._task_handler: Optional[asyncio.Task[None]] = None self._upgrade = False - self._payload_parser = None # type: Any - self._request_parser = HttpRequestParser( + self._payload_parser: Any = None + self._request_parser: Optional[HttpRequestParser] = HttpRequestParser( self, loop, read_bufsize, @@ -189,15 +210,16 @@ def __init__( max_field_size=max_field_size, max_headers=max_headers, payload_exception=RequestPayloadError, - ) # type: Optional[HttpRequestParser] + auto_decompress=auto_decompress, + ) self.logger = logger self.debug = debug self.access_log = access_log if access_log: - self.access_logger = access_log_class( + self.access_logger: Optional[AbstractAccessLogger] = access_log_class( access_log, access_log_format - ) # type: Optional[AbstractAccessLogger] + ) else: self.access_logger = None @@ -215,9 +237,11 @@ def keepalive_timeout(self) -> float: return self._keepalive_timeout async def shutdown(self, timeout: Optional[float] = 15.0) -> None: - """Worker process is about to exit, we need cleanup everything and - stop accepting requests. It is especially important for keep-alive - connections.""" + """Do worker process exit preparations. + + We need to clean up everything and stop accepting requests. + It is especially important for keep-alive connections. + """ self._force_close = True if self._keepalive_handle is not None: @@ -228,10 +252,7 @@ async def shutdown(self, timeout: Optional[float] = 15.0) -> None: # wait for handlers with suppress(asyncio.CancelledError, asyncio.TimeoutError): - with CeilTimeout(timeout, loop=self._loop): - if self._error_handler is not None and not self._error_handler.done(): - await self._error_handler - + async with ceil_timeout(timeout): if self._current_request is not None: self._current_request._cancel(asyncio.CancelledError()) @@ -278,10 +299,6 @@ def connection_lost(self, exc: Optional[BaseException]) -> None: exc = ConnectionResetError("Connection lost") self._current_request._cancel(exc) - if self._error_handler is not None: - self._error_handler.cancel() - if self._task_handler is not None: - self._task_handler.cancel() if self._waiter is not None: self._waiter.cancel() @@ -308,40 +325,30 @@ def data_received(self, data: bytes) -> None: if self._force_close or self._close: return # parse http messages + messages: Sequence[_MsgType] if self._payload_parser is None and not self._upgrade: assert self._request_parser is not None try: messages, upgraded, tail = self._request_parser.feed_data(data) except HttpProcessingError as exc: - # something happened during parsing - self._error_handler = self._loop.create_task( - self.handle_parse_error( - StreamWriter(self, self._loop), 400, exc, exc.message - ) - ) - self.close() - except Exception as exc: - # 500: internal error - self._error_handler = self._loop.create_task( - self.handle_parse_error(StreamWriter(self, self._loop), 500, exc) - ) - self.close() - else: - if messages: - # sometimes the parser returns no messages - for (msg, payload) in messages: - self._request_count += 1 - self._messages.append((msg, payload)) - - waiter = self._waiter - if waiter is not None: - if not waiter.done(): - # don't set result twice - waiter.set_result(None) - - self._upgrade = upgraded - if upgraded and tail: - self._message_tail = tail + messages = [ + (_ErrInfo(status=400, exc=exc, message=exc.message), EMPTY_PAYLOAD) + ] + upgraded = False + tail = b"" + + for msg, payload in messages or (): + self._request_count += 1 + self._messages.append((msg, payload)) + + waiter = self._waiter + if messages and waiter is not None and not waiter.done(): + # don't set result twice + waiter.set_result(None) + + self._upgrade = upgraded + if upgraded and tail: + self._message_tail = tail # no parser, just store elif self._payload_parser is None and self._upgrade and data: @@ -364,14 +371,17 @@ def keep_alive(self, val: bool) -> None: self._keepalive_handle = None def close(self) -> None: - """Stop accepting new pipelinig messages and close - connection when handlers done processing messages""" + """Close connection. + + Stop accepting new pipelining messages and close + connection when handlers done processing messages. + """ self._close = True if self._waiter: self._waiter.cancel() def force_close(self) -> None: - """Force close connection""" + """Forcefully close connection.""" self._force_close = True if self._waiter: self._waiter.cancel() @@ -414,18 +424,17 @@ async def _handle_request( self, request: BaseRequest, start_time: float, + request_handler: Callable[[BaseRequest], Awaitable[StreamResponse]], ) -> Tuple[StreamResponse, bool]: assert self._request_handler is not None try: try: self._current_request = request - resp = await self._request_handler(request) + resp = await request_handler(request) finally: self._current_request = None except HTTPException as exc: - resp = Response( - status=exc.status, reason=exc.reason, text=exc.text, headers=exc.headers - ) + resp = exc reset = await self.finish_response(request, resp, start_time) except asyncio.CancelledError: raise @@ -437,6 +446,15 @@ async def _handle_request( resp = self.handle_error(request, 500, exc) reset = await self.finish_response(request, resp, start_time) else: + # Deprecation warning (See #2415) + if getattr(resp, "__http_exception__", False): + warnings.warn( + "returning HTTPException object is deprecated " + "(#2415) and will be removed, " + "please raise the exception instead", + DeprecationWarning, + ) + reset = await self.finish_response(request, resp, start_time) return resp, reset @@ -477,23 +495,24 @@ async def start(self) -> None: manager.requests_count += 1 writer = StreamWriter(self, loop) + if isinstance(message, _ErrInfo): + # make request_factory work + request_handler = self._make_error_handler(message) + message = ERROR + else: + request_handler = self._request_handler + request = self._request_factory(message, payload, self, writer, handler) try: # a new task is used for copy context vars (#3406) - task = self._loop.create_task(self._handle_request(request, start)) + task = self._loop.create_task( + self._handle_request(request, start, request_handler) + ) try: resp, reset = await task except (asyncio.CancelledError, ConnectionError): self.log_debug("Ignored premature client disconnection") break - # Deprecation warning (See #2415) - if getattr(resp, "__http_exception__", False): - warnings.warn( - "returning HTTPException object is deprecated " - "(#2415) and will be removed, " - "please raise the exception instead", - DeprecationWarning, - ) # Drop the processed task from asyncio.Task.all_tasks() early del task @@ -517,7 +536,7 @@ async def start(self) -> None: with suppress(asyncio.TimeoutError, asyncio.CancelledError): while not payload.is_eof() and now < end_t: - with CeilTimeout(end_t - now, loop=loop): + async with ceil_timeout(end_t - now): # read and ignore await payload.readany() now = loop.time() @@ -558,14 +577,15 @@ async def start(self) -> None: # remove handler, close transport if no handlers left if not self._force_close: self._task_handler = None - if self.transport is not None and self._error_handler is None: + if self.transport is not None: self.transport.close() async def finish_response( self, request: BaseRequest, resp: StreamResponse, start_time: float ) -> bool: - """ - Prepare the response and write_eof, then log access. This has to + """Prepare the response and write_eof, then log access. + + This has to be called within the context of any exception so the access logger can get exception information. Returns True if the client disconnects prematurely. @@ -607,9 +627,17 @@ def handle_error( """Handle errors. Returns HTTP response with specific status code. Logs additional - information. It always closes current connection.""" + information. It always closes current connection. + """ self.log_exception("Error handling request", exc_info=exc) + # some data already got sent, connection is broken + if request.writer.output_size > 0: + raise ConnectionError( + "Response is sent already, cannot send another response " + "with the error message" + ) + ct = "text/plain" if status == HTTPStatus.INTERNAL_SERVER_ERROR: title = "{0.value} {0.phrase}".format(HTTPStatus.INTERNAL_SERVER_ERROR) @@ -638,30 +666,14 @@ def handle_error( resp = Response(status=status, text=message, content_type=ct) resp.force_close() - # some data already got sent, connection is broken - if request.writer.output_size > 0 or self.transport is None: - self.force_close() - return resp - async def handle_parse_error( - self, - writer: AbstractStreamWriter, - status: int, - exc: Optional[BaseException] = None, - message: Optional[str] = None, - ) -> None: - task = current_task() - assert task is not None - request = BaseRequest( - ERROR, EMPTY_PAYLOAD, self, writer, task, self._loop # type: ignore - ) - - resp = self.handle_error(request, status, exc, message) - await resp.prepare(request) - await resp.write_eof() - - if self.transport is not None: - self.transport.close() + def _make_error_handler( + self, err_info: _ErrInfo + ) -> Callable[[BaseRequest], Awaitable[StreamResponse]]: + async def handler(request: BaseRequest) -> StreamResponse: + return self.handle_error( + request, err_info.status, err_info.exc, err_info.message + ) - self._error_handler = None + return handler diff --git a/aiohttp/web_request.py b/aiohttp/web_request.py index f11e7be..c02ebfc 100644 --- a/aiohttp/web_request.py +++ b/aiohttp/web_request.py @@ -7,7 +7,6 @@ import tempfile import types import warnings -from email.utils import parsedate from http.cookies import SimpleCookie from types import MappingProxyType from typing import ( @@ -18,6 +17,7 @@ Mapping, MutableMapping, Optional, + Pattern, Tuple, Union, cast, @@ -30,13 +30,24 @@ from . import hdrs from .abc import AbstractStreamWriter -from .helpers import DEBUG, ChainMapProxy, HeadersMixin, reify, sentinel +from .helpers import ( + DEBUG, + ETAG_ANY, + LIST_QUOTED_ETAG_RE, + ChainMapProxy, + ETag, + HeadersMixin, + parse_http_date, + reify, + sentinel, +) from .http_parser import RawRequestMessage from .http_writer import HttpVersion from .multipart import BodyPartReader, MultipartReader from .streams import EmptyStreamReader, StreamReader from .typedefs import ( DEFAULT_JSON_DECODER, + Final, JSONDecoder, LooseHeaders, RawHeaders, @@ -63,31 +74,33 @@ class FileField: headers: "CIMultiDictProxy[str]" -_TCHAR = string.digits + string.ascii_letters + r"!#$%&'*+.^_`|~-" +_TCHAR: Final[str] = string.digits + string.ascii_letters + r"!#$%&'*+.^_`|~-" # '-' at the end to prevent interpretation as range in a char class -_TOKEN = fr"[{_TCHAR}]+" +_TOKEN: Final[str] = rf"[{_TCHAR}]+" -_QDTEXT = r"[{}]".format( +_QDTEXT: Final[str] = r"[{}]".format( r"".join(chr(c) for c in (0x09, 0x20, 0x21) + tuple(range(0x23, 0x7F))) ) # qdtext includes 0x5C to escape 0x5D ('\]') # qdtext excludes obs-text (because obsoleted, and encoding not specified) -_QUOTED_PAIR = r"\\[\t !-~]" +_QUOTED_PAIR: Final[str] = r"\\[\t !-~]" -_QUOTED_STRING = r'"(?:{quoted_pair}|{qdtext})*"'.format( +_QUOTED_STRING: Final[str] = r'"(?:{quoted_pair}|{qdtext})*"'.format( qdtext=_QDTEXT, quoted_pair=_QUOTED_PAIR ) -_FORWARDED_PAIR = r"({token})=({token}|{quoted_string})(:\d{{1,4}})?".format( +_FORWARDED_PAIR: Final[ + str +] = r"({token})=({token}|{quoted_string})(:\d{{1,4}})?".format( token=_TOKEN, quoted_string=_QUOTED_STRING ) -_QUOTED_PAIR_REPLACE_RE = re.compile(r"\\([\t !-~])") +_QUOTED_PAIR_REPLACE_RE: Final[Pattern[str]] = re.compile(r"\\([\t !-~])") # same pattern as _QUOTED_PAIR but contains a capture group -_FORWARDED_PAIR_RE = re.compile(_FORWARDED_PAIR) +_FORWARDED_PAIR_RE: Final[Pattern[str]] = re.compile(_FORWARDED_PAIR) ############################################################ # HTTP Request @@ -135,7 +148,7 @@ def __init__( task: "asyncio.Task[None]", loop: asyncio.AbstractEventLoop, *, - client_max_size: int = 1024 ** 2, + client_max_size: int = 1024**2, state: Optional[Dict[str, Any]] = None, scheme: Optional[str] = None, host: Optional[str] = None, @@ -151,14 +164,22 @@ def __init__( self._headers = message.headers self._method = message.method self._version = message.version - self._rel_url = message.url - self._post = ( - None - ) # type: Optional[MultiDictProxy[Union[str, bytes, FileField]]] - self._read_bytes = None # type: Optional[bytes] + self._cache: Dict[str, Any] = {} + url = message.url + if url.is_absolute(): + # absolute URL is given, + # override auto-calculating url, host, and scheme + # all other properties should be good + self._cache["url"] = url + self._cache["host"] = url.host + self._cache["scheme"] = url.scheme + self._rel_url = url.relative() + else: + self._rel_url = message.url + self._post: Optional[MultiDictProxy[Union[str, bytes, FileField]]] = None + self._read_bytes: Optional[bytes] = None self._state = state - self._cache = {} # type: Dict[str, Any] self._task = task self._client_max_size = client_max_size self._loop = loop @@ -190,13 +211,11 @@ def clone( Creates and returns a new instance of Request object. If no parameters are given, an exact copy is returned. If a parameter is not passed, it will reuse the one from the current request object. - """ - if self._read_bytes: raise RuntimeError("Cannot clone request " "after reading its content") - dct = {} # type: Dict[str, Any] + dct: Dict[str, Any] = {} if method is not sentinel: dct["method"] = method if rel_url is not sentinel: @@ -315,7 +334,7 @@ def forwarded(self) -> Tuple[Mapping[str, str], ...]: length = len(field_value) pos = 0 need_separator = False - elem = {} # type: Dict[str, str] + elem: Dict[str, str] = {} elems.append(types.MappingProxyType(elem)) while 0 <= pos < length: match = _FORWARDED_PAIR_RE.match(field_value, pos) @@ -396,8 +415,7 @@ def host(self) -> str: host = self._message.headers.get(hdrs.HOST) if host is not None: return host - else: - return socket.getfqdn() + return socket.getfqdn() @reify def remote(self) -> Optional[str]: @@ -408,10 +426,11 @@ def remote(self) -> Optional[str]: - overridden value by .clone(remote=new_remote) call. - peername of opened socket """ + if self._transport_peername is None: + return None if isinstance(self._transport_peername, (list, tuple)): - return self._transport_peername[0] - else: - return self._transport_peername + return str(self._transport_peername[0]) + return str(self._transport_peername) @reify def url(self) -> URL: @@ -437,6 +456,7 @@ def path_qs(self) -> str: @reify def raw_path(self) -> str: """The URL including raw *PATH INFO* without the host or scheme. + Warning, the path is unquoted and may contains non valid URL characters E.g., ``/my%2Fpath%7Cwith%21some%25strange%24characters`` @@ -446,7 +466,7 @@ def raw_path(self) -> str: @reify def query(self) -> "MultiDictProxy[str]": """A multidict with all the variables in the query string.""" - return self._rel_url.query + return MultiDictProxy(self._rel_url.query) @reify def query_string(self) -> str: @@ -466,22 +486,13 @@ def raw_headers(self) -> RawHeaders: """A sequence of pairs for all headers.""" return self._message.raw_headers - @staticmethod - def _http_date(_date_str: Optional[str]) -> Optional[datetime.datetime]: - """Process a date string, return a datetime object""" - if _date_str is not None: - timetuple = parsedate(_date_str) - if timetuple is not None: - return datetime.datetime(*timetuple[:6], tzinfo=datetime.timezone.utc) - return None - @reify def if_modified_since(self) -> Optional[datetime.datetime]: """The value of If-Modified-Since HTTP header, or None. This header is represented as a `datetime` object. """ - return self._http_date(self.headers.get(hdrs.IF_MODIFIED_SINCE)) + return parse_http_date(self.headers.get(hdrs.IF_MODIFIED_SINCE)) @reify def if_unmodified_since(self) -> Optional[datetime.datetime]: @@ -489,7 +500,53 @@ def if_unmodified_since(self) -> Optional[datetime.datetime]: This header is represented as a `datetime` object. """ - return self._http_date(self.headers.get(hdrs.IF_UNMODIFIED_SINCE)) + return parse_http_date(self.headers.get(hdrs.IF_UNMODIFIED_SINCE)) + + @staticmethod + def _etag_values(etag_header: str) -> Iterator[ETag]: + """Extract `ETag` objects from raw header.""" + if etag_header == ETAG_ANY: + yield ETag( + is_weak=False, + value=ETAG_ANY, + ) + else: + for match in LIST_QUOTED_ETAG_RE.finditer(etag_header): + is_weak, value, garbage = match.group(2, 3, 4) + # Any symbol captured by 4th group means + # that the following sequence is invalid. + if garbage: + break + + yield ETag( + is_weak=bool(is_weak), + value=value, + ) + + @classmethod + def _if_match_or_none_impl( + cls, header_value: Optional[str] + ) -> Optional[Tuple[ETag, ...]]: + if not header_value: + return None + + return tuple(cls._etag_values(header_value)) + + @reify + def if_match(self) -> Optional[Tuple[ETag, ...]]: + """The value of If-Match HTTP header, or None. + + This header is represented as a `tuple` of `ETag` objects. + """ + return self._if_match_or_none_impl(self.headers.get(hdrs.IF_MATCH)) + + @reify + def if_none_match(self) -> Optional[Tuple[ETag, ...]]: + """The value of If-None-Match HTTP header, or None. + + This header is represented as a `tuple` of `ETag` objects. + """ + return self._if_match_or_none_impl(self.headers.get(hdrs.IF_NONE_MATCH)) @reify def if_range(self) -> Optional[datetime.datetime]: @@ -497,7 +554,7 @@ def if_range(self) -> Optional[datetime.datetime]: This header is represented as a `datetime` object. """ - return self._http_date(self.headers.get(hdrs.IF_RANGE)) + return parse_http_date(self.headers.get(hdrs.IF_RANGE)) @reify def keep_alive(self) -> bool: @@ -511,7 +568,7 @@ def cookies(self) -> Mapping[str, str]: A read-only dictionary-like object. """ raw = self.headers.get(hdrs.COOKIE, "") - parsed = SimpleCookie(raw) # type: SimpleCookie[str] + parsed: SimpleCookie[str] = SimpleCookie(raw) return MappingProxyType({key: val.value for key, val in parsed.items()}) @reify @@ -634,7 +691,7 @@ async def post(self) -> "MultiDictProxy[Union[str, bytes, FileField]]": self._post = MultiDictProxy(MultiDict()) return self._post - out = MultiDict() # type: MultiDict[Union[str, bytes, FileField]] + out: MultiDict[Union[str, bytes, FileField]] = MultiDict() if content_type == "multipart/form-data": multipart = await self.multipart() @@ -655,16 +712,17 @@ async def post(self) -> "MultiDictProxy[Union[str, bytes, FileField]]": if field.filename: # store file in temp file tmp = tempfile.TemporaryFile() - chunk = await field.read_chunk(size=2 ** 16) + chunk = await field.read_chunk(size=2**16) while chunk: chunk = field.decode(chunk) tmp.write(chunk) size += len(chunk) if 0 < max_size < size: + tmp.close() raise HTTPRequestEntityTooLarge( max_size=max_size, actual_size=size ) - chunk = await field.read_chunk(size=2 ** 16) + chunk = await field.read_chunk(size=2**16) tmp.seek(0) if field_ct is None: @@ -756,7 +814,7 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: # or information about traversal lookup # initialized after route resolving - self._match_info = None # type: Optional[UrlMappingMatchInfo] + self._match_info: Optional[UrlMappingMatchInfo] = None if DEBUG: diff --git a/aiohttp/web_response.py b/aiohttp/web_response.py index f34b00e..ce07f81 100644 --- a/aiohttp/web_response.py +++ b/aiohttp/web_response.py @@ -8,7 +8,6 @@ import warnings import zlib from concurrent.futures import Executor -from email.utils import parsedate from http.cookies import Morsel, SimpleCookie from typing import ( TYPE_CHECKING, @@ -27,7 +26,17 @@ from . import hdrs, payload from .abc import AbstractStreamWriter -from .helpers import PY_38, HeadersMixin, rfc822_formatted_time, sentinel +from .helpers import ( + ETAG_ANY, + PY_38, + QUOTED_ETAG_RE, + ETag, + HeadersMixin, + parse_http_date, + rfc822_formatted_time, + sentinel, + validate_etag_value, +) from .http import RESPONSES, SERVER_SOFTWARE, HttpVersion10, HttpVersion11 from .payload import Payload from .typedefs import JSONEncoder, LooseHeaders @@ -46,7 +55,7 @@ if not PY_38: # allow samesite to be used in python < 3.8 # already permitted in python 3.8, see https://bugs.python.org/issue29613 - Morsel._reserved["samesite"] = "SameSite" # type: ignore + Morsel._reserved["samesite"] = "SameSite" # type: ignore[attr-defined] class ContentCoding(enum.Enum): @@ -76,20 +85,20 @@ def __init__( headers: Optional[LooseHeaders] = None, ) -> None: self._body = None - self._keep_alive = None # type: Optional[bool] + self._keep_alive: Optional[bool] = None self._chunked = False self._compression = False - self._compression_force = None # type: Optional[ContentCoding] - self._cookies = SimpleCookie() # type: SimpleCookie[str] + self._compression_force: Optional[ContentCoding] = None + self._cookies: SimpleCookie[str] = SimpleCookie() - self._req = None # type: Optional[BaseRequest] - self._payload_writer = None # type: Optional[AbstractStreamWriter] + self._req: Optional[BaseRequest] = None + self._payload_writer: Optional[AbstractStreamWriter] = None self._eof_sent = False self._body_length = 0 - self._state = {} # type: Dict[str, Any] + self._state: Dict[str, Any] = {} if headers is not None: - self._headers = CIMultiDict(headers) # type: CIMultiDict[str] + self._headers: CIMultiDict[str] = CIMultiDict(headers) else: self._headers = CIMultiDict() @@ -100,8 +109,11 @@ def prepared(self) -> bool: return self._payload_writer is not None @property - def task(self) -> "asyncio.Task[None]": - return getattr(self._req, "task", None) + def task(self) -> "Optional[asyncio.Task[None]]": + if self._req: + return self._req.task + else: + return None @property def status(self) -> int: @@ -209,7 +221,6 @@ def set_cookie( Sets new cookie or updates existent with new value. Also updates only those params which are not None. """ - old = self._cookies.get(name) if old is not None and old.coded_value == "": # deleted cookie @@ -314,12 +325,7 @@ def last_modified(self) -> Optional[datetime.datetime]: This header is represented as a `datetime` object. """ - httpdate = self._headers.get(hdrs.LAST_MODIFIED) - if httpdate is not None: - timetuple = parsedate(httpdate) - if timetuple is not None: - return datetime.datetime(*timetuple[:6], tzinfo=datetime.timezone.utc) - return None + return parse_http_date(self._headers.get(hdrs.LAST_MODIFIED)) @last_modified.setter def last_modified( @@ -338,6 +344,43 @@ def last_modified( elif isinstance(value, str): self._headers[hdrs.LAST_MODIFIED] = value + @property + def etag(self) -> Optional[ETag]: + quoted_value = self._headers.get(hdrs.ETAG) + if not quoted_value: + return None + elif quoted_value == ETAG_ANY: + return ETag(value=ETAG_ANY) + match = QUOTED_ETAG_RE.fullmatch(quoted_value) + if not match: + return None + is_weak, value = match.group(1, 2) + return ETag( + is_weak=bool(is_weak), + value=value, + ) + + @etag.setter + def etag(self, value: Optional[Union[ETag, str]]) -> None: + if value is None: + self._headers.pop(hdrs.ETAG, None) + elif (isinstance(value, str) and value == ETAG_ANY) or ( + isinstance(value, ETag) and value.value == ETAG_ANY + ): + self._headers[hdrs.ETAG] = ETAG_ANY + elif isinstance(value, str): + validate_etag_value(value) + self._headers[hdrs.ETAG] = f'"{value}"' + elif isinstance(value, ETag) and isinstance(value.value, str): + validate_etag_value(value.value) + hdr_value = f'W/"{value.value}"' if value.is_weak else f'"{value.value}"' + self._headers[hdrs.ETAG] = hdr_value + else: + raise ValueError( + f"Unsupported etag type: {type(value)}. " + f"etag must be str, ETag or None" + ) + def _generate_content_type_header( self, CONTENT_TYPE: istr = hdrs.CONTENT_TYPE ) -> None: @@ -420,7 +463,7 @@ async def _prepare_headers(self) -> None: elif self._length_check: writer.length = self.content_length if writer.length is None: - if version >= HttpVersion11: + if version >= HttpVersion11 and self.status != 204: writer.enable_chunking() headers[hdrs.TRANSFER_ENCODING] = "chunked" if hdrs.CONTENT_LENGTH in headers: @@ -432,7 +475,8 @@ async def _prepare_headers(self) -> None: elif version >= HttpVersion11 and self.status in (100, 101, 102, 103, 204): del headers[hdrs.CONTENT_LENGTH] - headers.setdefault(hdrs.CONTENT_TYPE, "application/octet-stream") + if self.status not in (204, 304): + headers.setdefault(hdrs.CONTENT_TYPE, "application/octet-stream") headers.setdefault(hdrs.DATE, rfc822_formatted_time()) headers.setdefault(hdrs.SERVER, SERVER_SOFTWARE) @@ -545,7 +589,7 @@ def __init__( raise ValueError("body and text are not allowed together") if headers is None: - real_headers = CIMultiDict() # type: CIMultiDict[str] + real_headers: CIMultiDict[str] = CIMultiDict() elif not isinstance(headers, CIMultiDict): real_headers = CIMultiDict(headers) else: @@ -594,7 +638,7 @@ def __init__( else: self.body = body - self._compressed_body = None # type: Optional[bytes] + self._compressed_body: Optional[bytes] = None self._zlib_executor_size = zlib_executor_size self._zlib_executor = zlib_executor @@ -610,8 +654,8 @@ def body( CONTENT_LENGTH: istr = hdrs.CONTENT_LENGTH, ) -> None: if body is None: - self._body = None # type: Optional[bytes] - self._body_payload = False # type: bool + self._body: Optional[bytes] = None + self._body_payload: bool = False elif isinstance(body, (bytes, bytearray)): self._body = body self._body_payload = False @@ -691,7 +735,7 @@ async def write_eof(self, data: bytes = b"") -> None: if self._eof_sent: return if self._compressed_body is None: - body = self._body # type: Optional[Union[bytes, Payload]] + body: Optional[Union[bytes, Payload]] = self._body else: body = self._compressed_body assert not data, f"data arg is not supported, got {data!r}" diff --git a/aiohttp/web_routedef.py b/aiohttp/web_routedef.py index 1885251..a1eb0a7 100644 --- a/aiohttp/web_routedef.py +++ b/aiohttp/web_routedef.py @@ -3,7 +3,6 @@ from typing import ( TYPE_CHECKING, Any, - Awaitable, Callable, Dict, Iterator, @@ -19,7 +18,7 @@ from . import hdrs from .abc import AbstractView -from .typedefs import PathLike +from .typedefs import Handler, PathLike if TYPE_CHECKING: # pragma: no cover from .web_request import Request @@ -53,8 +52,7 @@ def register(self, router: UrlDispatcher) -> List[AbstractRoute]: pass # pragma: no cover -_SimpleHandler = Callable[[Request], Awaitable[StreamResponse]] -_HandlerType = Union[Type[AbstractView], _SimpleHandler] +_HandlerType = Union[Type[AbstractView], Handler] @attr.s(auto_attribs=True, frozen=True, repr=False, slots=True) @@ -158,10 +156,10 @@ class RouteTableDef(Sequence[AbstractRouteDef]): """Route definition table""" def __init__(self) -> None: - self._items = [] # type: List[AbstractRouteDef] + self._items: List[AbstractRouteDef] = [] def __repr__(self) -> str: - return "".format(len(self._items)) + return f"" @overload def __getitem__(self, index: int) -> AbstractRouteDef: @@ -171,7 +169,7 @@ def __getitem__(self, index: int) -> AbstractRouteDef: def __getitem__(self, index: slice) -> List[AbstractRouteDef]: ... - def __getitem__(self, index): # type: ignore + def __getitem__(self, index): # type: ignore[no-untyped-def] return self._items[index] def __iter__(self) -> Iterator[AbstractRouteDef]: @@ -208,6 +206,9 @@ def patch(self, path: str, **kwargs: Any) -> _Deco: def delete(self, path: str, **kwargs: Any) -> _Deco: return self.route(hdrs.METH_DELETE, path, **kwargs) + def options(self, path: str, **kwargs: Any) -> _Deco: + return self.route(hdrs.METH_OPTIONS, path, **kwargs) + def view(self, path: str, **kwargs: Any) -> _Deco: return self.route(hdrs.METH_ANY, path, **kwargs) diff --git a/aiohttp/web_runner.py b/aiohttp/web_runner.py index 25ac28a..9282bb9 100644 --- a/aiohttp/web_runner.py +++ b/aiohttp/web_runner.py @@ -12,7 +12,7 @@ try: from ssl import SSLContext except ImportError: - SSLContext = object # type: ignore + SSLContext = object # type: ignore[misc,assignment] __all__ = ( @@ -53,7 +53,7 @@ def __init__( self._shutdown_timeout = shutdown_timeout self._ssl_context = ssl_context self._backlog = backlog - self._server = None # type: Optional[asyncio.AbstractServer] + self._server: Optional[asyncio.AbstractServer] = None @property @abstractmethod @@ -171,7 +171,9 @@ def __init__( self, runner: "BaseRunner", path: str, *, shutdown_timeout: float = 60.0 ) -> None: loop = asyncio.get_event_loop() - if not isinstance(loop, asyncio.ProactorEventLoop): # type: ignore + if not isinstance( + loop, asyncio.ProactorEventLoop # type: ignore[attr-defined] + ): raise RuntimeError( "Named Pipes only available in proactor" "loop under windows" ) @@ -187,7 +189,9 @@ async def start(self) -> None: loop = asyncio.get_event_loop() server = self._runner.server assert server is not None - _server = await loop.start_serving_pipe(server, self._path) # type: ignore + _server = await loop.start_serving_pipe( # type: ignore[attr-defined] + server, self._path + ) self._server = _server[0] @@ -238,8 +242,8 @@ class BaseRunner(ABC): def __init__(self, *, handle_signals: bool = False, **kwargs: Any) -> None: self._handle_signals = handle_signals self._kwargs = kwargs - self._server = None # type: Optional[Server] - self._sites = [] # type: List[BaseSite] + self._server: Optional[Server] = None + self._sites: List[BaseSite] = [] @property def server(self) -> Optional[Server]: @@ -247,7 +251,7 @@ def server(self) -> Optional[Server]: @property def addresses(self) -> List[Any]: - ret = [] # type: List[Any] + ret: List[Any] = [] for site in self._sites: server = site._server if server is not None: @@ -281,10 +285,6 @@ async def shutdown(self) -> None: async def cleanup(self) -> None: loop = asyncio.get_event_loop() - if self._server is None: - # no started yet, do nothing - return - # The loop over sites is intentional, an exception on gather() # leaves self._sites in unpredictable state. # The loop guaranties that a site is either deleted on success or diff --git a/aiohttp/web_server.py b/aiohttp/web_server.py index 5657ed9..fa46e90 100644 --- a/aiohttp/web_server.py +++ b/aiohttp/web_server.py @@ -22,7 +22,7 @@ def __init__( **kwargs: Any ) -> None: self._loop = get_running_loop(loop) - self._connections = {} # type: Dict[RequestHandler, asyncio.Transport] + self._connections: Dict[RequestHandler, asyncio.Transport] = {} self._kwargs = kwargs self.requests_count = 0 self.request_handler = handler diff --git a/aiohttp/web_urldispatcher.py b/aiohttp/web_urldispatcher.py index 2afd72f..5942e35 100644 --- a/aiohttp/web_urldispatcher.py +++ b/aiohttp/web_urldispatcher.py @@ -33,14 +33,13 @@ cast, ) -from typing_extensions import TypedDict -from yarl import URL, __version__ as yarl_version # type: ignore +from yarl import URL, __version__ as yarl_version # type: ignore[attr-defined] from . import hdrs from .abc import AbstractMatchInfo, AbstractRouter, AbstractView from .helpers import DEBUG from .http import HttpVersion11 -from .typedefs import PathLike +from .typedefs import Final, Handler, PathLike, TypedDict from .web_exceptions import ( HTTPException, HTTPExpectationFailed, @@ -74,16 +73,19 @@ else: BaseDict = dict -YARL_VERSION = tuple(map(int, yarl_version.split(".")[:2])) +YARL_VERSION: Final[Tuple[int, ...]] = tuple(map(int, yarl_version.split(".")[:2])) -HTTP_METHOD_RE = re.compile(r"^[0-9A-Za-z!#\$%&'\*\+\-\.\^_`\|~]+$") -ROUTE_RE = re.compile(r"(\{[_a-zA-Z][^{}]*(?:\{[^{}]*\}[^{}]*)*\})") -PATH_SEP = re.escape("/") +HTTP_METHOD_RE: Final[Pattern[str]] = re.compile( + r"^[0-9A-Za-z!#\$%&'\*\+\-\.\^_`\|~]+$" +) +ROUTE_RE: Final[Pattern[str]] = re.compile( + r"(\{[_a-zA-Z][^{}]*(?:\{[^{}]*\}[^{}]*)*\})" +) +PATH_SEP: Final[str] = re.escape("/") -_WebHandler = Callable[[Request], Awaitable[StreamResponse]] _ExpectHandler = Callable[[Request], Awaitable[None]] -_Resolve = Tuple[Optional[AbstractMatchInfo], Set[str]] +_Resolve = Tuple[Optional["UrlMappingMatchInfo"], Set[str]] class _InfoDict(TypedDict, total=False): @@ -128,16 +130,16 @@ def url_for(self, **kwargs: str) -> URL: @abc.abstractmethod # pragma: no branch async def resolve(self, request: Request) -> _Resolve: - """Resolve resource + """Resolve resource. - Return (UrlMappingMatchInfo, allowed_methods) pair.""" + Return (UrlMappingMatchInfo, allowed_methods) pair. + """ @abc.abstractmethod def add_prefix(self, prefix: str) -> None: """Add a prefix to processed URLs. Required for subapplications support. - """ @abc.abstractmethod @@ -156,7 +158,7 @@ class AbstractRoute(abc.ABC): def __init__( self, method: str, - handler: Union[_WebHandler, Type[AbstractView]], + handler: Union[Handler, Type[AbstractView]], *, expect_handler: Optional[_ExpectHandler] = None, resource: Optional[AbstractResource] = None, @@ -193,7 +195,7 @@ async def handler_wrapper(request: Request) -> StreamResponse: result = old_handler(request) if asyncio.iscoroutine(result): return await result - return result # type: ignore + return result # type: ignore[return-value] old_handler = handler handler = handler_wrapper @@ -208,7 +210,7 @@ def method(self) -> str: return self._method @property - def handler(self) -> _WebHandler: + def handler(self) -> Handler: return self._handler @property @@ -236,12 +238,12 @@ class UrlMappingMatchInfo(BaseDict, AbstractMatchInfo): def __init__(self, match_dict: Dict[str, str], route: AbstractRoute): super().__init__(match_dict) self._route = route - self._apps = [] # type: List[Application] - self._current_app = None # type: Optional[Application] + self._apps: List[Application] = [] + self._current_app: Optional[Application] = None self._frozen = False @property - def handler(self) -> _WebHandler: + def handler(self) -> Handler: return self._route.handler @property @@ -256,7 +258,7 @@ def expect_handler(self) -> _ExpectHandler: def http_exception(self) -> Optional[HTTPException]: return None - def get_info(self) -> _InfoDict: # type: ignore + def get_info(self) -> _InfoDict: # type: ignore[override] return self._route.get_info() @property @@ -331,12 +333,12 @@ async def _default_expect_handler(request: Request) -> None: class Resource(AbstractResource): def __init__(self, *, name: Optional[str] = None) -> None: super().__init__(name=name) - self._routes = [] # type: List[ResourceRoute] + self._routes: List[ResourceRoute] = [] def add_route( self, method: str, - handler: Union[Type[AbstractView], _WebHandler], + handler: Union[Type[AbstractView], Handler], *, expect_handler: Optional[_ExpectHandler] = None, ) -> "ResourceRoute": @@ -360,7 +362,7 @@ def register_route(self, route: "ResourceRoute") -> None: self._routes.append(route) async def resolve(self, request: Request) -> _Resolve: - allowed_methods = set() # type: Set[str] + allowed_methods: Set[str] = set() match_dict = self._match(request.rel_url.raw_path) if match_dict is None: @@ -421,7 +423,7 @@ def raw_match(self, path: str) -> bool: def get_info(self) -> _InfoDict: return {"path": self._path} - def url_for(self) -> URL: # type: ignore + def url_for(self) -> URL: # type: ignore[override] return URL.build(path=self._path, encoded=True) def __repr__(self) -> str: @@ -511,6 +513,7 @@ def __init__(self, prefix: str, *, name: Optional[str] = None) -> None: assert prefix in ("", "/") or not prefix.endswith("/"), prefix super().__init__(name=name) self._prefix = _requote_path(prefix) + self._prefix2 = self._prefix + "/" @property def canonical(self) -> str: @@ -521,6 +524,7 @@ def add_prefix(self, prefix: str) -> None: assert not prefix.endswith("/") assert len(prefix) > 1 self._prefix = prefix + self._prefix + self._prefix2 = self._prefix + "/" def raw_match(self, prefix: str) -> bool: return False @@ -569,7 +573,7 @@ def __init__( ), } - def url_for( # type: ignore + def url_for( # type: ignore[override] self, *, filename: Union[str, Path], @@ -621,7 +625,7 @@ def get_info(self) -> _InfoDict: "routes": self._routes, } - def set_options_route(self, handler: _WebHandler) -> None: + def set_options_route(self, handler: Handler) -> None: if "OPTIONS" in self._routes: raise RuntimeError("OPTIONS route was set already") self._routes["OPTIONS"] = ResourceRoute( @@ -632,7 +636,7 @@ async def resolve(self, request: Request) -> _Resolve: path = request.rel_url.raw_path method = request.method allowed_methods = set(self._routes) - if not path.startswith(self._prefix): + if not path.startswith(self._prefix2) and path != self._prefix: return None, set() if method not in allowed_methods: @@ -748,7 +752,7 @@ def get_info(self) -> _InfoDict: async def resolve(self, request: Request) -> _Resolve: if ( - not request.url.raw_path.startswith(self._prefix + "/") + not request.url.raw_path.startswith(self._prefix2) and request.url.raw_path != self._prefix ): return None, set() @@ -878,7 +882,7 @@ class ResourceRoute(AbstractRoute): def __init__( self, method: str, - handler: Union[_WebHandler, Type[AbstractView]], + handler: Union[Handler, Type[AbstractView]], resource: AbstractResource, *, expect_handler: Optional[_ExpectHandler] = None, @@ -942,7 +946,9 @@ class View(AbstractView): async def _iter(self) -> StreamResponse: if self.request.method not in hdrs.METH_ALL: self._raise_allowed_methods() - method = getattr(self, self.request.method.lower(), None) + method: Callable[[], Awaitable[StreamResponse]] = getattr( + self, self.request.method.lower(), None + ) if method is None: self._raise_allowed_methods() resp = await method() @@ -972,7 +978,7 @@ def __contains__(self, resource: object) -> bool: class RoutesView(Sized, Iterable[AbstractRoute], Container[AbstractRoute]): def __init__(self, resources: List[AbstractResource]): - self._routes = [] # type: List[AbstractRoute] + self._routes: List[AbstractRoute] = [] for resource in resources: for route in resource: self._routes.append(route) @@ -993,12 +999,12 @@ class UrlDispatcher(AbstractRouter, Mapping[str, AbstractResource]): def __init__(self) -> None: super().__init__() - self._resources = [] # type: List[AbstractResource] - self._named_resources = {} # type: Dict[str, AbstractResource] + self._resources: List[AbstractResource] = [] + self._named_resources: Dict[str, AbstractResource] = {} - async def resolve(self, request: Request) -> AbstractMatchInfo: + async def resolve(self, request: Request) -> UrlMappingMatchInfo: method = request.method - allowed_methods = set() # type: Set[str] + allowed_methods: Set[str] = set() for resource in self._resources: match_dict, allowed = await resource.resolve(request) @@ -1006,11 +1012,11 @@ async def resolve(self, request: Request) -> AbstractMatchInfo: return match_dict else: allowed_methods |= allowed + + if allowed_methods: + return MatchInfoError(HTTPMethodNotAllowed(method, allowed_methods)) else: - if allowed_methods: - return MatchInfoError(HTTPMethodNotAllowed(method, allowed_methods)) - else: - return MatchInfoError(HTTPNotFound()) + return MatchInfoError(HTTPNotFound()) def __iter__(self) -> Iterator[str]: return iter(self._named_resources) @@ -1086,7 +1092,7 @@ def add_route( self, method: str, path: str, - handler: Union[_WebHandler, Type[AbstractView]], + handler: Union[Handler, Type[AbstractView]], *, name: Optional[str] = None, expect_handler: Optional[_ExpectHandler] = None, @@ -1128,72 +1134,53 @@ def add_static( self.register_resource(resource) return resource - def add_head(self, path: str, handler: _WebHandler, **kwargs: Any) -> AbstractRoute: - """ - Shortcut for add_route with method HEAD - """ + def add_head(self, path: str, handler: Handler, **kwargs: Any) -> AbstractRoute: + """Shortcut for add_route with method HEAD.""" return self.add_route(hdrs.METH_HEAD, path, handler, **kwargs) - def add_options( - self, path: str, handler: _WebHandler, **kwargs: Any - ) -> AbstractRoute: - """ - Shortcut for add_route with method OPTIONS - """ + def add_options(self, path: str, handler: Handler, **kwargs: Any) -> AbstractRoute: + """Shortcut for add_route with method OPTIONS.""" return self.add_route(hdrs.METH_OPTIONS, path, handler, **kwargs) def add_get( self, path: str, - handler: _WebHandler, + handler: Handler, *, name: Optional[str] = None, allow_head: bool = True, **kwargs: Any, ) -> AbstractRoute: - """ - Shortcut for add_route with method GET, if allow_head is true another - route is added allowing head requests to the same endpoint + """Shortcut for add_route with method GET. + + If allow_head is true, another + route is added allowing head requests to the same endpoint. """ resource = self.add_resource(path, name=name) if allow_head: resource.add_route(hdrs.METH_HEAD, handler, **kwargs) return resource.add_route(hdrs.METH_GET, handler, **kwargs) - def add_post(self, path: str, handler: _WebHandler, **kwargs: Any) -> AbstractRoute: - """ - Shortcut for add_route with method POST - """ + def add_post(self, path: str, handler: Handler, **kwargs: Any) -> AbstractRoute: + """Shortcut for add_route with method POST.""" return self.add_route(hdrs.METH_POST, path, handler, **kwargs) - def add_put(self, path: str, handler: _WebHandler, **kwargs: Any) -> AbstractRoute: - """ - Shortcut for add_route with method PUT - """ + def add_put(self, path: str, handler: Handler, **kwargs: Any) -> AbstractRoute: + """Shortcut for add_route with method PUT.""" return self.add_route(hdrs.METH_PUT, path, handler, **kwargs) - def add_patch( - self, path: str, handler: _WebHandler, **kwargs: Any - ) -> AbstractRoute: - """ - Shortcut for add_route with method PATCH - """ + def add_patch(self, path: str, handler: Handler, **kwargs: Any) -> AbstractRoute: + """Shortcut for add_route with method PATCH.""" return self.add_route(hdrs.METH_PATCH, path, handler, **kwargs) - def add_delete( - self, path: str, handler: _WebHandler, **kwargs: Any - ) -> AbstractRoute: - """ - Shortcut for add_route with method DELETE - """ + def add_delete(self, path: str, handler: Handler, **kwargs: Any) -> AbstractRoute: + """Shortcut for add_route with method DELETE.""" return self.add_route(hdrs.METH_DELETE, path, handler, **kwargs) def add_view( self, path: str, handler: Type[AbstractView], **kwargs: Any ) -> AbstractRoute: - """ - Shortcut for add_route with ANY methods for a class-based view - """ + """Shortcut for add_route with ANY methods for a class-based view.""" return self.add_route(hdrs.METH_ANY, path, handler, **kwargs) def freeze(self) -> None: diff --git a/aiohttp/web_ws.py b/aiohttp/web_ws.py index da7ce6d..0d32a21 100644 --- a/aiohttp/web_ws.py +++ b/aiohttp/web_ws.py @@ -3,7 +3,7 @@ import binascii import hashlib import json -from typing import Any, Iterable, Optional, Tuple +from typing import Any, Iterable, Optional, Tuple, cast import async_timeout import attr @@ -19,6 +19,7 @@ WebSocketError, WebSocketReader, WebSocketWriter, + WSCloseCode, WSMessage, WSMsgType as WSMsgType, ws_ext_gen, @@ -26,7 +27,7 @@ ) from .log import ws_logger from .streams import EofStream, FlowControlDataQueue -from .typedefs import JSONDecoder, JSONEncoder +from .typedefs import Final, JSONDecoder, JSONEncoder from .web_exceptions import HTTPBadRequest, HTTPException from .web_request import BaseRequest from .web_response import StreamResponse @@ -37,7 +38,7 @@ "WSMsgType", ) -THRESHOLD_CONNLOST_ACCESS = 5 +THRESHOLD_CONNLOST_ACCESS: Final[int] = 5 @attr.s(auto_attribs=True, frozen=True, slots=True) @@ -67,25 +68,25 @@ def __init__( ) -> None: super().__init__(status=101) self._protocols = protocols - self._ws_protocol = None # type: Optional[str] - self._writer = None # type: Optional[WebSocketWriter] - self._reader = None # type: Optional[FlowControlDataQueue[WSMessage]] + self._ws_protocol: Optional[str] = None + self._writer: Optional[WebSocketWriter] = None + self._reader: Optional[FlowControlDataQueue[WSMessage]] = None self._closed = False self._closing = False self._conn_lost = 0 - self._close_code = None # type: Optional[int] - self._loop = None # type: Optional[asyncio.AbstractEventLoop] - self._waiting = None # type: Optional[asyncio.Future[bool]] - self._exception = None # type: Optional[BaseException] + self._close_code: Optional[int] = None + self._loop: Optional[asyncio.AbstractEventLoop] = None + self._waiting: Optional[asyncio.Future[bool]] = None + self._exception: Optional[BaseException] = None self._timeout = timeout self._receive_timeout = receive_timeout self._autoclose = autoclose self._autoping = autoping self._heartbeat = heartbeat - self._heartbeat_cb = None + self._heartbeat_cb: Optional[asyncio.TimerHandle] = None if heartbeat is not None: self._pong_heartbeat = heartbeat / 2.0 - self._pong_response_cb = None + self._pong_response_cb: Optional[asyncio.TimerHandle] = None self._compress = compress self._max_msg_size = max_msg_size @@ -102,16 +103,18 @@ def _reset_heartbeat(self) -> None: self._cancel_heartbeat() if self._heartbeat is not None: + assert self._loop is not None self._heartbeat_cb = call_later( self._send_heartbeat, self._heartbeat, self._loop ) def _send_heartbeat(self) -> None: if self._heartbeat is not None and not self._closed: + assert self._loop is not None # fire-and-forget a task is not perfect but maybe ok for # sending ping. Otherwise we need a long-living heartbeat # task in the class. - self._loop.create_task(self._writer.ping()) # type: ignore + self._loop.create_task(self._writer.ping()) # type: ignore[union-attr] if self._pong_response_cb is not None: self._pong_response_cb.cancel() @@ -122,7 +125,7 @@ def _send_heartbeat(self) -> None: def _pong_not_received(self) -> None: if self._req is not None and self._req.transport is not None: self._closed = True - self._close_code = 1006 + self._close_code = WSCloseCode.ABNORMAL_CLOSURE self._exception = asyncio.TimeoutError() self._req.transport.close() @@ -193,9 +196,9 @@ def _handshake( accept_val = base64.b64encode( hashlib.sha1(key.encode() + WS_KEY).digest() ).decode() - response_headers = CIMultiDict( # type: ignore + response_headers = CIMultiDict( { - hdrs.UPGRADE: "websocket", # type: ignore + hdrs.UPGRADE: "websocket", hdrs.CONNECTION: "upgrade", hdrs.SEC_WEBSOCKET_ACCEPT: accept_val, } @@ -216,7 +219,12 @@ def _handshake( if protocol: response_headers[hdrs.SEC_WEBSOCKET_PROTOCOL] = protocol - return (response_headers, protocol, compress, notakeover) # type: ignore + return ( + response_headers, + protocol, + compress, + notakeover, + ) # type: ignore[return-value] def _pre_start(self, request: BaseRequest) -> Tuple[str, WebSocketWriter]: self._loop = request._loop @@ -245,7 +253,7 @@ def _post_start( loop = self._loop assert loop is not None - self._reader = FlowControlDataQueue(request._protocol, 2 ** 16, loop=loop) + self._reader = FlowControlDataQueue(request._protocol, 2**16, loop=loop) request.protocol.set_parser( WebSocketReader(self._reader, self._max_msg_size, compress=self._compress) ) @@ -315,7 +323,7 @@ async def send_json( ) -> None: await self.send_str(dumps(data), compress=compress) - async def write_eof(self) -> None: # type: ignore + async def write_eof(self) -> None: # type: ignore[override] if self._eof_sent: return if self._payload_writer is None: @@ -324,7 +332,7 @@ async def write_eof(self) -> None: # type: ignore await self.close() self._eof_sent = True - async def close(self, *, code: int = 1000, message: bytes = b"") -> bool: + async def close(self, *, code: int = WSCloseCode.OK, message: bytes = b"") -> bool: if self._writer is None: raise RuntimeError("Call .prepare() first") @@ -346,10 +354,10 @@ async def close(self, *, code: int = 1000, message: bytes = b"") -> bool: assert writer is not None await writer.drain() except (asyncio.CancelledError, asyncio.TimeoutError): - self._close_code = 1006 + self._close_code = WSCloseCode.ABNORMAL_CLOSURE raise except Exception as exc: - self._close_code = 1006 + self._close_code = WSCloseCode.ABNORMAL_CLOSURE self._exception = exc return True @@ -359,13 +367,13 @@ async def close(self, *, code: int = 1000, message: bytes = b"") -> bool: reader = self._reader assert reader is not None try: - with async_timeout.timeout(self._timeout, loop=self._loop): + async with async_timeout.timeout(self._timeout): msg = await reader.read() except asyncio.CancelledError: - self._close_code = 1006 + self._close_code = WSCloseCode.ABNORMAL_CLOSURE raise except Exception as exc: - self._close_code = 1006 + self._close_code = WSCloseCode.ABNORMAL_CLOSURE self._exception = exc return True @@ -373,7 +381,7 @@ async def close(self, *, code: int = 1000, message: bytes = b"") -> bool: self._close_code = msg.data return True - self._close_code = 1006 + self._close_code = WSCloseCode.ABNORMAL_CLOSURE self._exception = asyncio.TimeoutError() return True else: @@ -400,9 +408,7 @@ async def receive(self, timeout: Optional[float] = None) -> WSMessage: try: self._waiting = loop.create_future() try: - with async_timeout.timeout( - timeout or self._receive_timeout, loop=self._loop - ): + async with async_timeout.timeout(timeout or self._receive_timeout): msg = await self._reader.read() self._reset_heartbeat() finally: @@ -410,10 +416,10 @@ async def receive(self, timeout: Optional[float] = None) -> WSMessage: set_result(waiter, True) self._waiting = None except (asyncio.CancelledError, asyncio.TimeoutError): - self._close_code = 1006 + self._close_code = WSCloseCode.ABNORMAL_CLOSURE raise except EofStream: - self._close_code = 1000 + self._close_code = WSCloseCode.OK await self.close() return WSMessage(WSMsgType.CLOSED, None, None) except WebSocketError as exc: @@ -423,7 +429,7 @@ async def receive(self, timeout: Optional[float] = None) -> WSMessage: except Exception as exc: self._exception = exc self._closing = True - self._close_code = 1006 + self._close_code = WSCloseCode.ABNORMAL_CLOSURE await self.close() return WSMessage(WSMsgType.ERROR, exc, None) @@ -450,13 +456,13 @@ async def receive_str(self, *, timeout: Optional[float] = None) -> str: msg.type, msg.data ) ) - return msg.data + return cast(str, msg.data) async def receive_bytes(self, *, timeout: Optional[float] = None) -> bytes: msg = await self.receive(timeout) if msg.type != WSMsgType.BINARY: raise TypeError(f"Received message {msg.type}:{msg.data!r} is not bytes") - return msg.data + return cast(bytes, msg.data) async def receive_json( self, *, loads: JSONDecoder = json.loads, timeout: Optional[float] = None diff --git a/aiohttp/worker.py b/aiohttp/worker.py index 67b244b..ab6007a 100644 --- a/aiohttp/worker.py +++ b/aiohttp/worker.py @@ -22,14 +22,14 @@ SSLContext = ssl.SSLContext except ImportError: # pragma: no cover - ssl = None # type: ignore - SSLContext = object # type: ignore + ssl = None # type: ignore[assignment] + SSLContext = object # type: ignore[misc,assignment] __all__ = ("GunicornWebWorker", "GunicornUVLoopWebWorker", "GunicornTokioWebWorker") -class GunicornWebWorker(base.Worker): +class GunicornWebWorker(base.Worker): # type: ignore[misc,no-any-unimported] DEFAULT_AIOHTTP_LOG_FORMAT = AccessLogger.LOG_FORMAT DEFAULT_GUNICORN_LOG_FORMAT = GunicornAccessLogFormat.default @@ -37,9 +37,9 @@ class GunicornWebWorker(base.Worker): def __init__(self, *args: Any, **kw: Any) -> None: # pragma: no cover super().__init__(*args, **kw) - self._task = None # type: Optional[asyncio.Task[None]] + self._task: Optional[asyncio.Task[None]] = None self.exit_code = 0 - self._notify_waiter = None # type: Optional[asyncio.Future[bool]] + self._notify_waiter: Optional[asyncio.Future[bool]] = None def init_process(self) -> None: # create new event_loop after fork @@ -57,30 +57,39 @@ def run(self) -> None: self.loop.run_until_complete(self._task) except Exception: self.log.exception("Exception in gunicorn worker") - if sys.version_info >= (3, 6): - self.loop.run_until_complete(self.loop.shutdown_asyncgens()) + self.loop.run_until_complete(self.loop.shutdown_asyncgens()) self.loop.close() sys.exit(self.exit_code) async def _run(self) -> None: + runner = None if isinstance(self.wsgi, Application): app = self.wsgi elif asyncio.iscoroutinefunction(self.wsgi): - app = await self.wsgi() + wsgi = await self.wsgi() + if isinstance(wsgi, web.AppRunner): + runner = wsgi + app = runner.app + else: + app = wsgi else: raise RuntimeError( "wsgi app should be either Application or " "async function returning Application, got {}".format(self.wsgi) ) - access_log = self.log.access_log if self.cfg.accesslog else None - runner = web.AppRunner( - app, - logger=self.log, - keepalive_timeout=self.cfg.keepalive, - access_log=access_log, - access_log_format=self._get_valid_log_format(self.cfg.access_log_format), - ) + + if runner is None: + access_log = self.log.access_log if self.cfg.accesslog else None + runner = web.AppRunner( + app, + logger=self.log, + keepalive_timeout=self.cfg.keepalive, + access_log=access_log, + access_log_format=self._get_valid_log_format( + self.cfg.access_log_format + ), + ) await runner.setup() ctx = self._create_ssl_context(self.cfg) if self.cfg.is_ssl else None @@ -101,11 +110,11 @@ async def _run(self) -> None: # If our parent changed then we shut down. pid = os.getpid() try: - while self.alive: # type: ignore + while self.alive: # type: ignore[has-type] self.notify() cnt = server.requests_count - if self.cfg.max_requests and cnt > self.cfg.max_requests: + if self.max_requests and cnt > self.max_requests: self.alive = False self.log.info("Max requests, shutting down: %s", self) @@ -171,6 +180,14 @@ def init_signals(self) -> None: # by interrupting system calls signal.siginterrupt(signal.SIGTERM, False) signal.siginterrupt(signal.SIGUSR1, False) + # Reset signals so Gunicorn doesn't swallow subprocess return codes + # See: https://github.com/aio-libs/aiohttp/issues/6130 + if sys.version_info < (3, 8): + # Starting from Python 3.8, + # the default child watcher is ThreadedChildWatcher. + # The watcher doesn't depend on SIGCHLD signal, + # there is no need to reset it. + signal.signal(signal.SIGCHLD, signal.SIG_DFL) def handle_quit(self, sig: int, frame: FrameType) -> None: self.alive = False diff --git a/debian/changelog b/debian/changelog index 89dd1f3..cd78f81 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,64 @@ +python-aiohttp (3.8.6-1) unstable; urgency=medium + + * New upstream release + + -- Piotr Ożarowski Sat, 14 Oct 2023 13:12:38 +0200 + +python-aiohttp (3.8.5-1) unstable; urgency=medium + + * New upstream release + + -- Piotr Ożarowski Sun, 20 Aug 2023 14:19:30 +0200 + +python-aiohttp (3.8.4-1) unstable; urgency=medium + + [ Debian Janitor ] + * Update standards version to 4.6.2, no changes needed. + + [ Piotr Ożarowski ] + * New upstream release + + -- Piotr Ożarowski Thu, 16 Feb 2023 11:54:52 +0100 + +python-aiohttp (3.8.3-1) unstable; urgency=medium + + * New upstream release + + -- Piotr Ożarowski Mon, 31 Oct 2022 09:58:46 +0100 + +python-aiohttp (3.8.1-5) unstable; urgency=medium + + [ Debian Janitor ] + * Remove constraints unnecessary since buster (oldstable): + + Build-Depends: Drop versioned constraint on python3-all-dev and + python3-yarl. + + python3-aiohttp: Drop versioned constraint on python3-yarl in Depends. + + -- Jelmer Vernooij Fri, 14 Oct 2022 11:57:30 +0100 + +python-aiohttp (3.8.1-4) unstable; urgency=high + + * Team upload. + * debian/control: Add versioned dependency (Closes: #1001642): + + python3-async-timeout (>= 4.0.1) + * debian/py3dist-overrides: Add "idna_ssl python3-idna-ssl" line + to suppress build error raised by newer dh_python3. + + -- Boyuan Yang Sun, 19 Dec 2021 01:05:53 -0500 + +python-aiohttp (3.8.1-3) unstable; urgency=medium + + * Add python3-charset-normalizer to (Build-)Depends (closes: 1000848) + + -- Piotr Ożarowski Tue, 30 Nov 2021 13:58:24 +0100 + +python-aiohttp (3.8.1-2) unstable; urgency=medium + + * New upstream release (closes: 1000680) + * docs: temporarily remove news (sphinxcontrib.towncrier is not yet packaged) + + -- Piotr Ożarowski Sat, 27 Nov 2021 17:20:40 +0100 + python-aiohttp (3.7.4-2) unstable; urgency=medium * Team upload. diff --git a/debian/control b/debian/control index 0fb6343..d874e65 100644 --- a/debian/control +++ b/debian/control @@ -8,22 +8,27 @@ Uploaders: Tianon Gravi , William Grzybowski Build-Depends: debhelper-compat (= 13), dh-python, - python3-all-dev (>= 3.5.3~), + python3-all-dev, python3-setuptools, python3-sphinx, python3-multidict, python3-async-timeout, - python3-yarl (>= 1.0), + python3-yarl, cython3, + python3-aiosignal, + python3-aiodns, + python3-attr, + python3-frozenlist, # for tests: python3-pytest, python3-pytest-mock, python3-chardet, + python3-charset-normalizer, python3-gunicorn, # for documentation: python3-sphinxcontrib.blockdiag Rules-Requires-Root: no -Standards-Version: 4.5.1 +Standards-Version: 4.6.2 Homepage: https://aiohttp.readthedocs.org Vcs-Git: https://salsa.debian.org/python-team/packages/python-aiohttp.git Vcs-Browser: https://salsa.debian.org/python-team/packages/python-aiohttp @@ -31,8 +36,8 @@ Testsuite: autopkgtest-pkg-python Package: python3-aiohttp Architecture: any -Depends: python3-yarl (>= 1.0), ${misc:Depends}, ${python3:Depends}, ${shlibs:Depends}, ${sphinxdoc:Depends} -Recommends: libjs-jquery +Depends: python3-yarl, python3-async-timeout (>= 4.0.1), ${misc:Depends}, ${python3:Depends}, ${shlibs:Depends}, ${sphinxdoc:Depends} +Recommends: libjs-jquery, python3-aiodns Description: http client/server for asyncio HTTP Client for asyncio (PEP 3156 - Asynchronous I/O Support). . diff --git a/debian/gbp.conf b/debian/gbp.conf index cec628c..b4fd331 100644 --- a/debian/gbp.conf +++ b/debian/gbp.conf @@ -1,2 +1,3 @@ [DEFAULT] pristine-tar = True +filter = [ '*.egg-info' ] diff --git a/debian/patches/0003-remove-forkme-button-from-docs-to-prevent-privacy-br.patch b/debian/patches/0003-remove-forkme-button-from-docs-to-prevent-privacy-br.patch index 5b1bb8c..ea54f7b 100644 --- a/debian/patches/0003-remove-forkme-button-from-docs-to-prevent-privacy-br.patch +++ b/debian/patches/0003-remove-forkme-button-from-docs-to-prevent-privacy-br.patch @@ -7,13 +7,13 @@ Subject: remove forkme button from docs to prevent privacy breach 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/conf.py b/docs/conf.py -index 6532648..120469c 100644 +index 029db20..e75f1fe 100644 --- a/docs/conf.py +++ b/docs/conf.py -@@ -151,9 +151,9 @@ html_theme_options = { +@@ -178,9 +178,9 @@ html_theme_options = { "canonical_url": "http://docs.aiohttp.org/en/stable/", - "github_user": "aio-libs", - "github_repo": "aiohttp", + "github_user": github_repo_org, + "github_repo": github_repo_name, - "github_button": True, + "github_button": False, "github_type": "star", @@ -21,4 +21,4 @@ index 6532648..120469c 100644 + "github_banner": False, "badges": [ { - "image": "https://github.com/aio-libs/aiohttp/workflows/CI/badge.svg", + "image": f"{github_repo_url}/workflows/CI/badge.svg", diff --git a/debian/patches/0004-remove-sphinxcontrib.towncrier-for-now.patch b/debian/patches/0004-remove-sphinxcontrib.towncrier-for-now.patch new file mode 100644 index 0000000..88756a0 --- /dev/null +++ b/debian/patches/0004-remove-sphinxcontrib.towncrier-for-now.patch @@ -0,0 +1,54 @@ +From: =?utf-8?q?Piotr_O=C5=BCarowski?= +Date: Sat, 27 Nov 2021 17:48:20 +0100 +Subject: remove sphinxcontrib.towncrier for now + +not packaged in Debian yet +--- + docs/changes.rst | 9 +-------- + docs/conf.py | 2 +- + docs/index.rst | 2 +- + 3 files changed, 3 insertions(+), 10 deletions(-) + +diff --git a/docs/changes.rst b/docs/changes.rst +index 6a61dfb..fe6ab50 100644 +--- a/docs/changes.rst ++++ b/docs/changes.rst +@@ -7,11 +7,4 @@ Changelog + To be included in v\ |release| (if present) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +-.. towncrier-draft-entries:: |release| [UNRELEASED DRAFT] +- +-Released versions +-^^^^^^^^^^^^^^^^^ +- +-.. include:: ../CHANGES.rst +- +-.. include:: ../HISTORY.rst ++Temporarily removed in Debian, sorry. +diff --git a/docs/conf.py b/docs/conf.py +index e75f1fe..5df8646 100644 +--- a/docs/conf.py ++++ b/docs/conf.py +@@ -54,7 +54,7 @@ extensions = [ + # Third-party extensions: + "sphinxcontrib.asyncio", + "sphinxcontrib.blockdiag", +- "sphinxcontrib.towncrier", # provides `towncrier-draft-entries` directive ++ # "sphinxcontrib.towncrier", # provides `towncrier-draft-entries` directive + ] + + +diff --git a/docs/index.rst b/docs/index.rst +index 94cebd0..2540d0c 100644 +--- a/docs/index.rst ++++ b/docs/index.rst +@@ -133,7 +133,7 @@ will: + What's new in aiohttp 3? + ======================== + +-Go to :ref:`aiohttp_whats_new_3_0` page for aiohttp 3.0 major release ++Go to aiohttp_whats_new_3_0 page for aiohttp 3.0 major release + changes. + + diff --git a/debian/patches/series b/debian/patches/series index 59848f3..6c11a3e 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -1,3 +1,4 @@ 0002-Use-local-install-of-jquery.patch 0002-Add-shebang-to-examples.patch 0003-remove-forkme-button-from-docs-to-prevent-privacy-br.patch +0004-remove-sphinxcontrib.towncrier-for-now.patch diff --git a/debian/py3dist-overrides b/debian/py3dist-overrides new file mode 100644 index 0000000..64e5cfc --- /dev/null +++ b/debian/py3dist-overrides @@ -0,0 +1,2 @@ +# not needed for python3.7+ +idna_ssl python3-idna-ssl diff --git a/debian/rules b/debian/rules index 38e66df..cb11b50 100755 --- a/debian/rules +++ b/debian/rules @@ -11,7 +11,7 @@ export DEB_BUILD_MAINT_OPTIONS = hardening=+all override_dh_auto_build: sed -i -e '/sphinxcontrib.asyncio/d' -e '/aiohttp_theme/d' docs/conf.py - ${MAKE} -C docs html + ${MAKE} -C docs html || true dh_auto_build override_dh_auto_clean: diff --git a/debian/source/options b/debian/source/options new file mode 100644 index 0000000..b2b7b88 --- /dev/null +++ b/debian/source/options @@ -0,0 +1 @@ +extend-diff-ignore="^[^/]+\.egg-info/" diff --git a/docs/Makefile b/docs/Makefile index 3837ff3..22eaead 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -2,7 +2,7 @@ # # You can set these variables from the command line. -SPHINXOPTS = +SPHINXOPTS = -W --keep-going -n SPHINXBUILD = sphinx-build PAPER = BUILDDIR = _build diff --git a/docs/_snippets/cchardet-unmaintained-admonition.rst b/docs/_snippets/cchardet-unmaintained-admonition.rst new file mode 100644 index 0000000..ec290e0 --- /dev/null +++ b/docs/_snippets/cchardet-unmaintained-admonition.rst @@ -0,0 +1,5 @@ +.. warning:: + + Note that the :term:`cchardet` project is known not to support + Python 3.10 or higher. See :issue:`6819` and + :gh:`PyYoshi/cChardet/issues/77` for more details. diff --git a/docs/_static/aiohttp-icon-128x128.png b/docs/_static/aiohttp-icon-128x128.png deleted file mode 100644 index e486a04..0000000 Binary files a/docs/_static/aiohttp-icon-128x128.png and /dev/null differ diff --git a/docs/_static/css/logo-adjustments.css b/docs/_static/css/logo-adjustments.css new file mode 100644 index 0000000..b93746f --- /dev/null +++ b/docs/_static/css/logo-adjustments.css @@ -0,0 +1,7 @@ +.sphinxsidebarwrapper>h1.logo { + display: none; +} + +.sphinxsidebarwrapper>p.logo>a>img.logo { + width: 65%; +} diff --git a/docs/abc.rst b/docs/abc.rst index 7930b28..f905d92 100644 --- a/docs/abc.rst +++ b/docs/abc.rst @@ -19,21 +19,21 @@ aiohttp.web is built on top of few concepts: *application*, *router*, *router* is a *plugable* part: a library user may build a *router* from scratch, all other parts should work with new router seamlessly. -:class:`AbstractRouter` has the only mandatory method: -:meth:`AbstractRouter.resolve` coroutine. It must return an -:class:`AbstractMatchInfo` instance. +:class:`aiohttp.abc.AbstractRouter` has the only mandatory method: +:meth:`aiohttp.abc.AbstractRouter.resolve` coroutine. It must return an +:class:`aiohttp.abc.AbstractMatchInfo` instance. If the requested URL handler is found -:meth:`AbstractMatchInfo.handler` is a :term:`web-handler` for -requested URL and :attr:`AbstractMatchInfo.http_exception` is ``None``. +:meth:`aiohttp.abc.AbstractMatchInfo.handler` is a :term:`web-handler` for +requested URL and :attr:`aiohttp.abc.AbstractMatchInfo.http_exception` is ``None``. -Otherwise :attr:`AbstractMatchInfo.http_exception` is an instance of +Otherwise :attr:`aiohttp.abc.AbstractMatchInfo.http_exception` is an instance of :exc:`~aiohttp.web.HTTPException` like *404: NotFound* or *405: Method -Not Allowed*. :meth:`AbstractMatchInfo.handler` raises -:attr:`~AbstractMatchInfo.http_exception` on call. +Not Allowed*. :meth:`aiohttp.abc.AbstractMatchInfo.handler` raises +:attr:`~aiohttp.abc.AbstractMatchInfo.http_exception` on call. -.. class:: aiohttp.abc.AbstractRouter +.. class:: AbstractRouter Abstract router, :class:`aiohttp.web.Application` accepts it as *router* parameter and returns as @@ -49,12 +49,12 @@ Not Allowed*. :meth:`AbstractMatchInfo.handler` raises :attr:`aiohttp.web.Request.match_info` equals to ``None`` at resolving stage. - :return: :class:`AbstractMatchInfo` instance. + :return: :class:`aiohttp.abc.AbstractMatchInfo` instance. -.. class:: aiohttp.abc.AbstractMatchInfo +.. class:: AbstractMatchInfo - Abstract *match info*, returned by :meth:`AbstractRouter.resolve` call. + Abstract *match info*, returned by :meth:`aiohttp.abc.AbstractRouter.resolve` call. .. attribute:: http_exception @@ -100,9 +100,9 @@ attribute. Abstract Cookie Jar ------------------- -.. class:: aiohttp.abc.AbstractCookieJar +.. class:: AbstractCookieJar - The cookie jar instance is available as :attr:`ClientSession.cookie_jar`. + The cookie jar instance is available as :attr:`aiohttp.ClientSession.cookie_jar`. The jar contains :class:`~http.cookies.Morsel` items for storing internal cookie data. @@ -145,12 +145,28 @@ Abstract Cookie Jar :return: :class:`http.cookies.SimpleCookie` with filtered cookies for given URL. -Abstract Abstract Access Logger + .. method:: clear(predicate=None) + + Removes all cookies from the jar if the predicate is ``None``. Otherwise remove only those :class:`~http.cookies.Morsel` that ``predicate(morsel)`` returns ``True``. + + :param predicate: callable that gets :class:`~http.cookies.Morsel` as a parameter and returns ``True`` if this :class:`~http.cookies.Morsel` must be deleted from the jar. + + .. versionadded:: 3.8 + + .. method:: clear_domain(domain) + + Remove all cookies from the jar that belongs to the specified domain or its subdomains. + + :param str domain: domain for which cookies must be deleted from the jar. + + .. versionadded:: 3.8 + +Abstract Access Logger ------------------------------- -.. class:: aiohttp.abc.AbstractAccessLogger +.. class:: AbstractAccessLogger - An abstract class, base for all :class:`RequestHandler` + An abstract class, base for all :class:`aiohttp.web.RequestHandler` ``access_logger`` implementations Method ``log`` should be overridden. diff --git a/docs/aiohttp-icon.svg b/docs/aiohttp-icon.svg index 9356d47..0b3ebac 100644 --- a/docs/aiohttp-icon.svg +++ b/docs/aiohttp-icon.svg @@ -1,62 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - + diff --git a/docs/aiohttp-plain.svg b/docs/aiohttp-plain.svg index f45ccd0..aec1b00 100644 --- a/docs/aiohttp-plain.svg +++ b/docs/aiohttp-plain.svg @@ -1,62 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - + diff --git a/docs/built_with.rst b/docs/built_with.rst index 12fa64c..e9007d2 100644 --- a/docs/built_with.rst +++ b/docs/built_with.rst @@ -18,6 +18,8 @@ You can also add a **Built with aiohttp** link somewhere in your project, pointing to ``_. +* `Pulp `_ Platform for managing repositories + of software packages and making them available to consumers. * `Molotov `_ Load testing tool. * `Arsenic `_ Async WebDriver. * `Home Assistant `_ Home Automation Platform. diff --git a/docs/changes.rst b/docs/changes.rst index 0ecf1d7..6a61dfb 100644 --- a/docs/changes.rst +++ b/docs/changes.rst @@ -1,5 +1,17 @@ .. _aiohttp_changes: +========= +Changelog +========= + +To be included in v\ |release| (if present) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. towncrier-draft-entries:: |release| [UNRELEASED DRAFT] + +Released versions +^^^^^^^^^^^^^^^^^ + .. include:: ../CHANGES.rst .. include:: ../HISTORY.rst diff --git a/docs/client_advanced.rst b/docs/client_advanced.rst index e4e0919..e8f016a 100644 --- a/docs/client_advanced.rst +++ b/docs/client_advanced.rst @@ -56,6 +56,10 @@ For *text/plain* :: await session.post(url, data='Привет, Мир!') +.. note:: + ``Authorization`` header will be removed if you get redirected + to a different host or protocol. + Custom Cookies -------------- @@ -295,7 +299,7 @@ nature are installed to perform their job in each signal handle:: All signals take as a parameters first, the :class:`ClientSession` instance used by the specific request related to that signals and -second, a :class:`SimpleNamespace` instance called +second, a :class:`~types.SimpleNamespace` instance called ``trace_config_ctx``. The ``trace_config_ctx`` object can be used to share the state through to the different signals that belong to the same request and to the same :class:`TraceConfig` class, perhaps:: @@ -310,7 +314,7 @@ same request and to the same :class:`TraceConfig` class, perhaps:: The ``trace_config_ctx`` param is by default a -:class:`SimpleNampespace` that is initialized at the beginning of the +:class:`~types.SimpleNamespace` that is initialized at the beginning of the request flow. However, the factory used to create this object can be overwritten using the ``trace_config_ctx_factory`` constructor param of the :class:`TraceConfig` class. @@ -522,9 +526,11 @@ DER with e.g:: Proxy support ------------- -aiohttp supports plain HTTP proxies and HTTP proxies that can be upgraded to HTTPS -via the HTTP CONNECT method. aiohttp does not support proxies that must be -connected to via ``https://``. To connect, use the *proxy* parameter:: +aiohttp supports plain HTTP proxies and HTTP proxies that can be +upgraded to HTTPS via the HTTP CONNECT method. aiohttp has a limited +support for proxies that must be connected to via ``https://`` — see +the info box below for more details. +To connect, use the *proxy* parameter:: async with aiohttp.ClientSession() as session: async with session.get("http://python.org", @@ -549,16 +555,47 @@ Contrary to the ``requests`` library, it won't read environment variables by default. But you can do so by passing ``trust_env=True`` into :class:`aiohttp.ClientSession` constructor for extracting proxy configuration from -*HTTP_PROXY* or *HTTPS_PROXY* *environment variables* (both are case -insensitive):: +*HTTP_PROXY*, *HTTPS_PROXY*, *WS_PROXY* or *WSS_PROXY* *environment +variables* (all are case insensitive):: async with aiohttp.ClientSession(trust_env=True) as session: async with session.get("http://python.org") as resp: print(resp.status) +.. versionadded:: 3.8 + + *WS_PROXY* and *WSS_PROXY* are supported since aiohttp v3.8. + Proxy credentials are given from ``~/.netrc`` file if present (see :class:`aiohttp.ClientSession` for more details). +.. attention:: + + CPython has introduced the support for TLS in TLS around Python 3.7. + But, as of now (Python 3.10), it's disabled for the transports that + :py:mod:`asyncio` uses. If the further release of Python (say v3.11) + toggles one attribute, it'll *just work™*. + + aiohttp v3.8 and higher is ready for this to happen and has code in + place supports TLS-in-TLS, hence sending HTTPS requests over HTTPS + proxy tunnels. + + ⚠️ For as long as your Python runtime doesn't declare the support for + TLS-in-TLS, please don't file bugs with aiohttp but rather try to + help the CPython upstream enable this feature. Meanwhile, if you + *really* need this to work, there's a patch that may help you make + it happen, include it into your app's code base: + https://github.com/aio-libs/aiohttp/discussions/6044#discussioncomment-1432443. + +.. important:: + + When supplying a custom :py:class:`ssl.SSLContext` instance, bear in + mind that it will be used not only to establish a TLS session with + the HTTPS endpoint you're hitting but also to establish a TLS tunnel + to the HTTPS proxy. To avoid surprises, make sure to set up the trust + chain that would recognize TLS certificates used by both the endpoint + and the proxy. + Graceful Shutdown ----------------- @@ -603,3 +640,33 @@ are changed so that aiohttp itself can wait on the underlying connection to close. Please follow issue `#1925 `_ for the progress on this. + + +Character Set Detection +----------------------- + +If you encounter an 'Automatic charset detection will be removed' warning +when using :meth:`ClientResponse.text()` this may be because the response +does not include the charset needed to decode the body. + +If you know the correct encoding for a request, you can simply specify +the encoding as a parameter (e.g. ``resp.text("windows-1252")``). + +Alternatively, :class:`ClientSession` accepts a ``fallback_charset_resolver`` parameter which +can be used to reintroduce charset guessing functionality. When a charset is not found +in the Content-Type header, this function will be called to get the charset encoding. For +example, this can be used with the ``chardetng_py`` library.:: + + from chardetng_py import detect + + def charset_resolver(resp: ClientResponse, body: bytes) -> str: + tld = resp.url.host.rsplit(".", maxsplit=1)[-1] + return detect(body, allow_utf8=True, tld=tld) + + ClientSession(fallback_charset_resolver=charset_resolver) + +Or, if ``chardetng_py`` doesn't work for you, then ``charset-normalizer`` is another option:: + + from charset_normalizer import detect + + ClientSession(fallback_charset_resolver=lamba r, b: detect(b)["encoding"] or "utf-8") diff --git a/docs/client_quickstart.rst b/docs/client_quickstart.rst index fe77024..e84209c 100644 --- a/docs/client_quickstart.rst +++ b/docs/client_quickstart.rst @@ -33,9 +33,7 @@ Now, let's try to get a web-page. For example let's query print(resp.status) print(await resp.text()) - - loop = asyncio.get_event_loop() - loop.run_until_complete(main()) + asyncio.run(main()) Now, we have a :class:`ClientSession` called ``session`` and a :class:`ClientResponse` object called ``resp``. We can get all the @@ -55,10 +53,22 @@ Other HTTP methods are available as well:: session.options('http://httpbin.org/get') session.patch('http://httpbin.org/patch', data=b'data') +To make several requests to the same site more simple, the parameter ``base_url`` +of :class:`ClientSession` constructor can be used. For example to request different +endpoints of ``http://httpbin.org`` can be used the following code:: + + async with aiohttp.ClientSession('http://httpbin.org') as session: + async with session.get('/get'): + pass + async with session.post('/post', data=b'data'): + pass + async with session.put('/put', data=b'data'): + pass + .. note:: Don't create a session per request. Most likely you need a session - per application which performs all requests altogether. + per application which performs all requests together. More complex cases may require a session per site, e.g. one for Github and other one for Facebook APIs. Anyway making a session for @@ -96,9 +106,9 @@ following code:: You can see that the URL has been correctly encoded by printing the URL. -For sending data with multiple values for the same key :class:`MultiDict` may be -used; the library support nested lists (``{'key': ['value1', 'value2']}``) -alternative as well. +For sending data with multiple values for the same key +:class:`~multidict.MultiDict` may be used; the library support nested lists +(``{'key': ['value1', 'value2']}``) alternative as well. It is also possible to pass a list of 2 item tuples as parameters, in that case you can specify multiple values for each key:: @@ -174,13 +184,13 @@ The ``gzip`` and ``deflate`` transfer-encodings are automatically decoded for you. You can enable ``brotli`` transfer-encodings support, -just install `brotlipy `_. +just install `brotli `_. JSON Request ============ Any of session's request methods like :func:`request`, -:meth:`ClientSession.get`, :meth:`ClientSesssion.post` etc. accept +:meth:`ClientSession.get`, :meth:`ClientSession.post` etc. accept `json` parameter:: async with aiohttp.ClientSession() as session: @@ -242,10 +252,7 @@ In general, however, you should use a pattern like this to save what is being streamed to a file:: with open(filename, 'wb') as fd: - while True: - chunk = await resp.content.read(chunk_size) - if not chunk: - break + async for chunk in resp.content.iter_chunked(chunk_size): fd.write(chunk) It is not possible to use :meth:`~ClientResponse.read`, @@ -315,7 +322,7 @@ You can set the ``filename`` and ``content_type`` explicitly:: await session.post(url, data=data) If you pass a file object as data parameter, aiohttp will stream it to -the server automatically. Check :class:`~aiohttp.streams.StreamReader` +the server automatically. Check :class:`~aiohttp.StreamReader` for supported format information. .. seealso:: :ref:`aiohttp-multipart` diff --git a/docs/client_reference.rst b/docs/client_reference.rst index 5a420e0..bb2f7e2 100644 --- a/docs/client_reference.rst +++ b/docs/client_reference.rst @@ -32,13 +32,13 @@ Usage example:: html = await fetch(client) print(html) - loop = asyncio.get_event_loop() - loop.run_until_complete(main()) + asyncio.run(main()) The client session supports the context manager protocol for self closing. -.. class:: ClientSession(*, connector=None, loop=None, cookies=None, \ +.. class:: ClientSession(base_url=None, *, \ + connector=None, cookies=None, \ headers=None, skip_auto_headers=None, \ auth=None, json_serialize=json.dumps, \ version=aiohttp.HttpVersion11, \ @@ -51,11 +51,17 @@ The client session supports the context manager protocol for self closing. read_bufsize=2**16, \ requote_redirect_url=False, \ trust_env=False, \ - trace_configs=None) + trace_configs=None, \ + fallback_charset_resolver=_chardet_resolver) The class for creating client sessions and making requests. + :param base_url: Base part of the URL (optional) + If set it allows to skip the base part in request calls. + + .. versionadded:: 3.8 + :param aiohttp.BaseConnector connector: BaseConnector sub-class instance to support connection pooling. @@ -88,14 +94,14 @@ The client session supports the context manager protocol for self closing. that generation. Note that ``Content-Length`` autogeneration can't be skipped. - Iterable of :class:`str` or :class:`~aiohttp.istr` (optional) + Iterable of :class:`str` or :class:`~multidict.istr` (optional) :param aiohttp.BasicAuth auth: an object that represents HTTP Basic Authorization (optional) :param version: supported HTTP version, ``HTTP 1.1`` by default. - :param cookie_jar: Cookie Jar, :class:`AbstractCookieJar` instance. + :param cookie_jar: Cookie Jar, :class:`~aiohttp.abc.AbstractCookieJar` instance. By default every session instance has own private cookie jar for automatic cookies processing but user may redefine this behavior @@ -108,7 +114,7 @@ The client session supports the context manager protocol for self closing. :class:`aiohttp.DummyCookieJar` instance can be provided. - :param callable json_serialize: Json *serializer* callable. + :param collections.abc.Callable json_serialize: Json *serializer* callable. By default :func:`json.dumps` function. @@ -195,6 +201,18 @@ The client session supports the context manager protocol for self closing. disabling. See :ref:`aiohttp-client-tracing-reference` for more information. + :param Callable[[ClientResponse,bytes],str] fallback_charset_resolver: + A :term:`callable` that accepts a :class:`ClientResponse` and the + :class:`bytes` contents, and returns a :class:`str` which will be used as + the encoding parameter to :meth:`bytes.decode()`. + + This function will be called when the charset is not known (e.g. not specified in the + Content-Type header). The default function in 3.8.6 calls ``chardetng`` + or ``charset-normaliser``. In 3.9+ this be replaced with a function that + simply defaults to ``utf-8``. + + .. versionadded:: 3.8.6 + .. attribute:: closed ``True`` if the session has been closed, ``False`` otherwise. @@ -210,7 +228,7 @@ The client session supports the context manager protocol for self closing. .. attribute:: cookie_jar - The session cookies, :class:`~aiohttp.AbstractCookieJar` instance. + The session cookies, :class:`~aiohttp.abc.AbstractCookieJar` instance. Gives access to cookie jar's content and modifiers. @@ -261,7 +279,7 @@ The client session supports the context manager protocol for self closing. Set of headers for which autogeneration skipped. - :class:`frozenset` of :class:`str` or :class:`~aiohttp.istr` (optional) + :class:`frozenset` of :class:`str` or :class:`~multidict.istr` (optional) .. versionadded:: 3.7 @@ -293,7 +311,7 @@ The client session supports the context manager protocol for self closing. Should :meth:`ClientResponse.raise_for_status()` be called for each response - Either :class:`bool` or :class:`callable` + Either :class:`bool` or :class:`collections.abc.Callable` .. versionadded:: 3.7 @@ -335,13 +353,15 @@ The client session supports the context manager protocol for self closing. ssl_context=None, proxy_headers=None) :async-with: :coroutine: - :noindex: + :noindexentry: Performs an asynchronous HTTP request. Returns a response object. :param str method: HTTP method - :param url: Request URL, :class:`str` or :class:`~yarl.URL`. + :param url: Request URL, :class:`~yarl.URL` or :class:`str` that will + be encoded with :class:`~yarl.URL` (see :class:`~yarl.URL` + to skip encoding). :param params: Mapping, iterable of tuple of *key*/*value* pairs or string to be sent as parameters in the query @@ -351,8 +371,8 @@ The client session supports the context manager protocol for self closing. Allowed values are: - :class:`collections.abc.Mapping` e.g. :class:`dict`, - :class:`aiohttp.MultiDict` or - :class:`aiohttp.MultiDictProxy` + :class:`multidict.MultiDict` or + :class:`multidict.MultiDictProxy` - :class:`collections.abc.Iterable` e.g. :class:`tuple` or :class:`list` - :class:`str` with preferably url-encoded content @@ -386,7 +406,7 @@ The client session supports the context manager protocol for self closing. passed. Using ``skip_auto_headers`` parameter allows to skip that generation. - Iterable of :class:`str` or :class:`~aiohttp.istr` + Iterable of :class:`str` or :class:`~multidict.istr` (optional) :param aiohttp.BasicAuth auth: an object that represents HTTP @@ -492,7 +512,7 @@ The client session supports the context manager protocol for self closing. Use ``ssl=ssl_context`` - :param abc.Mapping proxy_headers: HTTP headers to send to the proxy if the + :param collections.abc.Mapping proxy_headers: HTTP headers to send to the proxy if the parameter proxy has been provided. .. versionadded:: 2.3 @@ -644,6 +664,7 @@ The client session supports the context manager protocol for self closing. autoping=True,\ heartbeat=None,\ origin=None, \ + params=None, \ headers=None, \ proxy=None, proxy_auth=None, ssl=None, \ verify_ssl=None, fingerprint=None, \ @@ -655,7 +676,9 @@ The client session supports the context manager protocol for self closing. Create a websocket connection. Returns a :class:`ClientWebSocketResponse` object. - :param url: Websocket server url, :class:`str` or :class:`~yarl.URL` + :param url: Websocket server url, :class:`~yarl.URL` or :class:`str` that + will be encoded with :class:`~yarl.URL` (see :class:`~yarl.URL` + to skip encoding). :param tuple protocols: Websocket protocols @@ -685,6 +708,21 @@ The client session supports the context manager protocol for self closing. :param str origin: Origin header to send to server(optional) + :param params: Mapping, iterable of tuple of *key*/*value* pairs or + string to be sent as parameters in the query + string of the new request. Ignored for subsequent + redirected requests (optional) + + Allowed values are: + + - :class:`collections.abc.Mapping` e.g. :class:`dict`, + :class:`multidict.MultiDict` or + :class:`multidict.MultiDictProxy` + - :class:`collections.abc.Iterable` e.g. :class:`tuple` or + :class:`list` + - :class:`str` with preferably url-encoded content + (**Warning:** content will not be encoded by *aiohttp*) + :param dict headers: HTTP Headers to send with the request (optional) @@ -805,7 +843,9 @@ certification chaining. :param str method: HTTP method - :param url: Requested URL, :class:`str` or :class:`~yarl.URL` + :param url: Request URL, :class:`~yarl.URL` or :class:`str` that will + be encoded with :class:`~yarl.URL` (see :class:`~yarl.URL` + to skip encoding). :param dict params: Parameters to be sent in the query string of the new request (optional) @@ -1082,14 +1122,14 @@ TCPConnector very rare cases. :param int family: TCP socket family, both IPv4 and IPv6 by default. - For *IPv4* only use :const:`socket.AF_INET`, - for *IPv6* only -- :const:`socket.AF_INET6`. + For *IPv4* only use :data:`socket.AF_INET`, + for *IPv6* only -- :data:`socket.AF_INET6`. *family* is ``0`` by default, that means both IPv4 and IPv6 are accepted. To specify only concrete version please pass - :const:`socket.AF_INET` or - :const:`socket.AF_INET6` explicitly. + :data:`socket.AF_INET` or + :data:`socket.AF_INET6` explicitly. :param ssl.SSLContext ssl_context: SSL context used for processing *HTTPS* requests (optional). @@ -1110,8 +1150,8 @@ TCPConnector .. attribute:: family - *TCP* socket family e.g. :const:`socket.AF_INET` or - :const:`socket.AF_INET6` + *TCP* socket family e.g. :data:`socket.AF_INET` or + :data:`socket.AF_INET6` Read-only property. @@ -1213,7 +1253,7 @@ Response object .. class:: ClientResponse - Client response returned by :meth:`ClientSession.request` and family. + Client response returned by :meth:`aiohttp.ClientSession.request` and family. User never creates the instance of ClientResponse class but gets it from API calls. @@ -1229,7 +1269,7 @@ Response object .. attribute:: version - Response's version, :class:`HttpVersion` instance. + Response's version, :class:`~aiohttp.protocol.HttpVersion` instance. .. attribute:: status @@ -1373,12 +1413,8 @@ Response object Read response's body and return decoded :class:`str` using specified *encoding* parameter. - If *encoding* is ``None`` content encoding is autocalculated - using ``Content-Type`` HTTP header and *chardet* tool if the - header is not provided by server. - - :term:`cchardet` is used with fallback to :term:`chardet` if - *cchardet* is not available. + If *encoding* is ``None`` content encoding is determined from the + Content-Type header, or using the ``fallback_charset_resolver`` function. Close underlying connection if data reading gets an error, release connection otherwise. @@ -1387,34 +1423,28 @@ Response object ``None`` for encoding autodetection (default). - :return str: decoded *BODY* - :raise LookupError: if the encoding detected by chardet or cchardet is - unknown by Python (e.g. VISCII). .. note:: If response has no ``charset`` info in ``Content-Type`` HTTP - header :term:`cchardet` / :term:`chardet` is used for content - encoding autodetection. + header :term:`cchardet` / :term:`charset-normalizer` is used for + content encoding autodetection. It may hurt performance. If page encoding is known passing explicit *encoding* parameter might help:: await resp.text('ISO-8859-1') - .. comethod:: json(*, encoding=None, loads=json.loads, \ + .. method:: json(*, encoding=None, loads=json.loads, \ content_type='application/json') + :async: Read response's body as *JSON*, return :class:`dict` using specified *encoding* and *loader*. If data is not still available - a ``read`` call will be done, - - If *encoding* is ``None`` content encoding is autocalculated - using :term:`cchardet` or :term:`chardet` as fallback if - *cchardet* is not available. + a ``read`` call will be done. - if response's `content-type` does not match `content_type` parameter + If response's `content-type` does not match `content_type` parameter :exc:`aiohttp.ContentTypeError` get raised. To disable content type check pass ``None`` value. @@ -1428,7 +1458,7 @@ Response object responses. Autodetection works pretty fine anyway. - :param callable loads: :func:`callable` used for loading *JSON* + :param collections.abc.Callable loads: :term:`callable` used for loading *JSON* data, :func:`json.loads` by default. :param str content_type: specify response's content-type, if content type @@ -1441,22 +1471,14 @@ Response object .. attribute:: request_info - A namedtuple with request URL and headers from :class:`ClientRequest` + A namedtuple with request URL and headers from :class:`~aiohttp.ClientRequest` object, :class:`aiohttp.RequestInfo` instance. .. method:: get_encoding() - Automatically detect content encoding using ``charset`` info in - ``Content-Type`` HTTP header. If this info is not exists or there - are no appropriate codecs for encoding then :term:`cchardet` / - :term:`chardet` is used. - - Beware that it is not always safe to use the result of this function to - decode a response. Some encodings detected by cchardet are not known by - Python (e.g. VISCII). - - :raise RuntimeError: if called before the body has been read, - for :term:`cchardet` usage + Retrieve content encoding using ``charset`` info in ``Content-Type`` HTTP header. + If no charset is present or the charset is not understood by Python, the + ``fallback_charset_resolver`` function associated with the ``ClientSession`` is called. .. versionadded:: 3.0 @@ -1562,7 +1584,7 @@ manually. single message, ``None`` for not overriding per-socket setting. - :param callable dumps: any :term:`callable` that accepts an object and + :param collections.abc.Callable dumps: any :term:`callable` that accepts an object and returns a JSON string (:func:`json.dumps` by default). @@ -1578,14 +1600,14 @@ manually. The method is converted into :term:`coroutine`, *compress* parameter added. - .. comethod:: close(*, code=1000, message=b'') + .. comethod:: close(*, code=WSCloseCode.OK, message=b'') A :ref:`coroutine` that initiates closing handshake by sending :const:`~aiohttp.WSMsgType.CLOSE` message. It waits for close response from server. To add a timeout to `close()` call just wrap the call with `asyncio.wait()` or `asyncio.wait_for()`. - :param int code: closing code + :param int code: closing code. See also :class:`~aiohttp.WSCloseCode`. :param message: optional payload of *close* message, :class:`str` (converted to *UTF-8* encoded bytes) or :class:`bytes`. @@ -1630,7 +1652,7 @@ manually. A :ref:`coroutine` that calls :meth:`receive_str` and loads the JSON string to a Python dict. - :param callable loads: any :term:`callable` that accepts + :param collections.abc.Callable loads: any :term:`callable` that accepts :class:`str` and returns :class:`dict` with parsed JSON (:func:`json.loads` by default). @@ -1688,12 +1710,54 @@ ClientTimeout .. versionadded:: 3.3 + + .. note:: + + Timeouts of 5 seconds or more are rounded for scheduling on the next + second boundary (an absolute time where microseconds part is zero) for the + sake of performance. + + E.g., assume a timeout is ``10``, absolute time when timeout should expire + is ``loop.time() + 5``, and it points to ``12345.67 + 10`` which is equal + to ``12355.67``. + + The absolute time for the timeout cancellation is ``12356``. + + It leads to grouping all close scheduled timeout expirations to exactly + the same time to reduce amount of loop wakeups. + + .. versionchanged:: 3.7 + + Rounding to the next seconds boundary is disabled for timeouts smaller + than 5 seconds for the sake of easy debugging. + + In turn, tiny timeouts can lead to significant performance degradation + on production environment. + + +ETag +^^^^ + +.. class:: ETag(name, is_weak=False) + + Represents `ETag` identifier. + + .. attribute:: value + + Value of corresponding etag without quotes. + + .. attribute:: is_weak + + Flag indicates that etag is weak (has `W/` prefix). + + .. versionadded:: 3.8 + RequestInfo ^^^^^^^^^^^ .. class:: RequestInfo() - A data class with request URL and headers from :class:`ClientRequest` + A data class with request URL and headers from :class:`~aiohttp.ClientRequest` object, available as :attr:`ClientResponse.request_info` attribute. .. attribute:: url @@ -1728,7 +1792,7 @@ BasicAuth Should be used for specifying authorization data in client API, - e.g. *auth* parameter for :meth:`ClientSession.request`. + e.g. *auth* parameter for :meth:`ClientSession.request() `. .. classmethod:: decode(auth_header, encoding='latin1') @@ -1761,7 +1825,7 @@ BasicAuth CookieJar ^^^^^^^^^ -.. class:: CookieJar(*, unsafe=False, quote_cookie=True, loop=None) +.. class:: CookieJar(*, unsafe=False, quote_cookie=True, treat_as_secure_origin = []) The cookie jar instance is available as :attr:`ClientSession.cookie_jar`. @@ -1780,7 +1844,7 @@ CookieJar The class implements :class:`collections.abc.Iterable`, :class:`collections.abc.Sized` and - :class:`aiohttp.AbstractCookieJar` interfaces. + :class:`aiohttp.abc.AbstractCookieJar` interfaces. Implements cookie storage adhering to RFC 6265. @@ -1793,11 +1857,17 @@ CookieJar .. versionadded:: 3.7 - :param bool loop: an :ref:`event loop` instance. - See :class:`aiohttp.abc.AbstractCookieJar` + :param treat_as_secure_origin: (optional) Mark origins as secure + for cookies marked as Secured. Possible types are - .. deprecated:: 2.0 + Possible types are: + + - :class:`tuple` or :class:`list` of + :class:`str` or :class:`yarl.URL` + - :class:`str` + - :class:`yarl.URL` + .. versionadded:: 3.8 .. method:: update_cookies(cookies, response_url=None) @@ -1808,7 +1878,7 @@ CookieJar *iterable* of *pairs* with cookies returned by server's response. - :param str response_url: URL of response, ``None`` for *shared + :param ~yarl.URL response_url: URL of response, ``None`` for *shared cookies*. Regular cookies are coupled with server's URL and are sent only to this server, shared ones are sent in every client request. @@ -1818,7 +1888,7 @@ CookieJar Return jar's cookies acceptable for URL and available in ``Cookie`` header for sending client requests for given URL. - :param str response_url: request's URL for which cookies are asked. + :param ~yarl.URL response_url: request's URL for which cookies are asked. :return: :class:`http.cookies.SimpleCookie` with filtered cookies for given URL. @@ -1839,6 +1909,22 @@ CookieJar :param file_path: Path to file from where cookies will be imported, :class:`str` or :class:`pathlib.Path` instance. + .. method:: clear(predicate=None) + + Removes all cookies from the jar if the predicate is ``None``. Otherwise remove only those :class:`~http.cookies.Morsel` that ``predicate(morsel)`` returns ``True``. + + :param predicate: callable that gets :class:`~http.cookies.Morsel` as a parameter and returns ``True`` if this :class:`~http.cookies.Morsel` must be deleted from the jar. + + .. versionadded:: 4.0 + + .. method:: clear_domain(domain) + + Remove all cookies from the jar that belongs to the specified domain or its subdomains. + + :param str domain: domain for which cookies must be deleted from the jar. + + .. versionadded:: 4.0 + .. class:: DummyCookieJar(*, loop=None) @@ -1884,7 +1970,7 @@ added with at least one optional argument to :meth:`add_field[-no-extensions] + + For example, if you want to run tests for python3.7 + without extensions, you can run this command:: + + make test-3.7-no-extensions Tests coverage -------------- diff --git a/docs/deployment.rst b/docs/deployment.rst index e542a34..60f218e 100644 --- a/docs/deployment.rst +++ b/docs/deployment.rst @@ -37,7 +37,7 @@ Nginx+supervisord Running aiohttp servers behind :term:`nginx` makes several advantages. -At first, nginx is the perfect frontend server. It may prevent many +First, nginx is the perfect frontend server. It may prevent many attacks based on malformed http protocol etc. Second, running several aiohttp instances behind nginx allows to @@ -51,10 +51,10 @@ But this way requires more complex configuration. Nginx configuration -------------------- -Here is short extraction about writing Nginx configuration file. +Here is short example of an Nginx configuration file. It does not cover all available Nginx options. -For full reference read `Nginx tutorial +For full details, read `Nginx tutorial `_ and `official Nginx documentation `_. @@ -86,8 +86,8 @@ First configure HTTP server itself: } } -This config listens on port ``80`` for server named ``example.com`` -and redirects everything to ``aiohttp`` backend group. +This config listens on port ``80`` for a server named ``example.com`` +and redirects everything to the ``aiohttp`` backend group. Also it serves static files from ``/path/to/app/static`` path as ``example.com/static``. @@ -124,20 +124,20 @@ selection. .. note:: - Nginx is not the only existing *reverse proxy server* but the most + Nginx is not the only existing *reverse proxy server*, but it's the most popular one. Alternatives like HAProxy may be used as well. Supervisord ----------- -After configuring Nginx we need to start our aiohttp backends. Better -to use some tool for starting them automatically after system reboot +After configuring Nginx we need to start our aiohttp backends. It's best +to use some tool for starting them automatically after a system reboot or backend crash. -There are very many ways to do it: Supervisord, Upstart, Systemd, +There are many ways to do it: Supervisord, Upstart, Systemd, Gaffer, Circus, Runit etc. -Here we'll use `Supervisord `_ for example: +Here we'll use `Supervisord `_ as an example: .. code-block:: cfg @@ -159,7 +159,7 @@ Here we'll use `Supervisord `_ for example: aiohttp server -------------- -The last step is preparing aiohttp server for working with supervisord. +The last step is preparing the aiohttp server to work with supervisord. Assuming we have properly configured :class:`aiohttp.web.Application` and port is specified by command line, the task is trivial: @@ -196,17 +196,17 @@ aiohttp can be deployed using `Gunicorn pre-fork worker model. Gunicorn launches your app as worker processes for handling incoming requests. -In opposite to deployment with :ref:`bare Nginx -` the solution does not need to -manually run several aiohttp processes and use tool like supervisord -for monitoring it. But nothing is for free: running aiohttp +As opposed to deployment with :ref:`bare Nginx +`, this solution does not need to +manually run several aiohttp processes and use a tool like supervisord +to monitor them. But nothing is free: running aiohttp application under gunicorn is slightly slower. Prepare environment ------------------- -You firstly need to setup your deployment environment. This example is +You first need to setup your deployment environment. This example is based on `Ubuntu `_ 16.04. Create a directory for your application:: @@ -214,7 +214,7 @@ Create a directory for your application:: >> mkdir myapp >> cd myapp -Create Python virtual environment:: +Create a Python virtual environment:: >> python3 -m venv venv >> source venv/bin/activate diff --git a/docs/glossary.rst b/docs/glossary.rst index bc5e116..6512185 100644 --- a/docs/glossary.rst +++ b/docs/glossary.rst @@ -32,11 +32,12 @@ Any object that can be called. Use :func:`callable` to check that. - chardet + charset-normalizer - The Universal Character Encoding Detector + The Real First Universal Charset Detector. + Open, modern and actively maintained alternative to Chardet. - https://pypi.python.org/pypi/chardet/ + https://pypi.org/project/charset-normalizer/ cchardet @@ -45,6 +46,8 @@ https://pypi.python.org/pypi/cchardet/ + .. include:: _snippets/cchardet-unmaintained-admonition.rst + gunicorn Gunicorn 'Green Unicorn' is a Python WSGI HTTP Server for diff --git a/docs/http_request_lifecycle.rst b/docs/http_request_lifecycle.rst index e14fb03..22f6fbb 100644 --- a/docs/http_request_lifecycle.rst +++ b/docs/http_request_lifecycle.rst @@ -77,8 +77,7 @@ So you are expected to reuse a session object and make many requests from it. Fo html = await response.text() print(html) - loop = asyncio.get_event_loop() - loop.run_until_complete(main()) + asyncio.run(main()) Can become this: @@ -98,8 +97,7 @@ Can become this: html = await fetch(session, 'http://python.org') print(html) - loop = asyncio.get_event_loop() - loop.run_until_complete(main()) + asyncio.run(main()) On more complex code bases, you can even create a central registry to hold the session object from anywhere in the code, or a higher level ``Client`` class that holds a reference to it. diff --git a/docs/index.rst b/docs/index.rst index 13fe723..94cebd0 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -34,12 +34,14 @@ Library Installation $ pip install aiohttp You may want to install *optional* :term:`cchardet` library as faster -replacement for :term:`chardet`: +replacement for :term:`charset-normalizer`: .. code-block:: bash $ pip install cchardet +.. include:: _snippets/cchardet-unmaintained-admonition.rst + For speeding up DNS resolving by client API you may install :term:`aiodns` as well. This option is highly recommended: @@ -48,11 +50,11 @@ This option is highly recommended: $ pip install aiodns -Installing speedups altogether ------------------------------- +Installing all speedups in one command +-------------------------------------- -The following will get you ``aiohttp`` along with :term:`chardet`, -:term:`aiodns` and ``brotlipy`` in one bundle. No need to type +The following will get you ``aiohttp`` along with :term:`cchardet`, +:term:`aiodns` and ``Brotli`` in one bundle. No need to type separate commands anymore! .. code-block:: bash @@ -81,8 +83,7 @@ Client example html = await response.text() print("Body:", html[:15], "...") - loop = asyncio.get_event_loop() - loop.run_until_complete(main()) + asyncio.run(main()) This prints: @@ -117,6 +118,18 @@ Server example: For more information please visit :ref:`aiohttp-client` and :ref:`aiohttp-web` pages. +Development mode +================ + +When writing your code, we recommend enabling Python's +`development mode `_ +(``python -X dev``). In addition to the extra features enabled for asyncio, aiohttp +will: + +- Use a strict parser in the client code (which can help detect malformed responses + from a server). +- Enable some additional checks (resulting in warnings in certain situations). + What's new in aiohttp 3? ======================== @@ -139,9 +152,6 @@ Please feel free to file an issue on the `bug tracker `_ if you have found a bug or have some suggestion in order to improve the library. -The library uses `Azure Pipelines `_ for -Continuous Integration. - Dependencies ============ @@ -149,17 +159,9 @@ Dependencies - Python 3.6+ - *async_timeout* - *attrs* -- *chardet* +- *charset-normalizer* - *multidict* - *yarl* -- *Optional* :term:`cchardet` as faster replacement for - :term:`chardet`. - - Install it explicitly via: - - .. code-block:: bash - - $ pip install cchardet - *Optional* :term:`aiodns` for fast DNS resolving. The library is highly recommended. diff --git a/docs/multipart.rst b/docs/multipart.rst index b6ecc63..ef821ca 100644 --- a/docs/multipart.rst +++ b/docs/multipart.rst @@ -152,9 +152,9 @@ will include the file's basename:: part = root.append(open(__file__, 'rb')) If you want to send a file with a different name, just handle the -:class:`Payload` instance which :meth:`MultipartWriter.append` will +:class:`~aiohttp.payload.Payload` instance which :meth:`MultipartWriter.append` will always return and set `Content-Disposition` explicitly by using -the :meth:`Payload.set_content_disposition` helper:: +the :meth:`Payload.set_content_disposition() ` helper:: part.set_content_disposition('attachment', filename='secret.txt') diff --git a/docs/multipart_reference.rst b/docs/multipart_reference.rst index 032ecc8..90fda21 100644 --- a/docs/multipart_reference.rst +++ b/docs/multipart_reference.rst @@ -7,7 +7,7 @@ Multipart reference .. class:: MultipartResponseWrapper(resp, stream) - Wrapper around the :class:`MultipartBodyReader` to take care about + Wrapper around the :class:`MultipartReader` to take care about underlying connection and close it when it needs in. @@ -135,7 +135,7 @@ Multipart reference Constructs reader instance from HTTP response. - :param response: :class:`~aiohttp.client.ClientResponse` instance + :param response: :class:`~aiohttp.ClientResponse` instance .. method:: at_eof() diff --git a/docs/new_router.rst b/docs/new_router.rst index a88b208..dd09149 100644 --- a/docs/new_router.rst +++ b/docs/new_router.rst @@ -45,7 +45,7 @@ User still may use wildcard for accepting all HTTP methods (maybe we will add something like ``resource.add_wildcard(handler)`` later). Since **names** belongs to **resources** now ``app.router['name']`` -returns a **resource** instance instead of :class:`aiohttp.web.Route`. +returns a **resource** instance instead of :class:`aiohttp.web.AbstractRoute`. **resource** has ``.url()`` method, so ``app.router['name'].url(parts={'a': 'b'}, query={'arg': 'param'})`` @@ -65,8 +65,8 @@ The refactoring is 99% compatible with previous implementation. 99% means all example and the most of current code works without modifications but we have subtle API backward incompatibles. -``app.router['name']`` returns a :class:`aiohttp.web.BaseResource` -instance instead of :class:`aiohttp.web.Route` but resource has the +``app.router['name']`` returns a :class:`aiohttp.web.AbstractResource` +instance instead of :class:`aiohttp.web.AbstractRoute` but resource has the same ``resource.url(...)`` most useful method, so end user should feel no difference. @@ -81,4 +81,4 @@ shortcut for:: return route ``app.router.register_route(...)`` is still supported, it creates -:class:`aiohttp.web.ResourceAdapter` for every call (but it's deprecated now). +``aiohttp.web.ResourceAdapter`` for every call (but it's deprecated now). diff --git a/docs/powered_by.rst b/docs/powered_by.rst index c6e4971..58ce026 100644 --- a/docs/powered_by.rst +++ b/docs/powered_by.rst @@ -16,7 +16,6 @@ make a Pull Request! * `GNS3 `_ * `TutorCruncher socket `_ -* `Morpheus messaging microservice `_ * `Eyepea - Custom telephony solutions `_ * `ALLOcloud - Telephony in the cloud `_ * `helpmanual - comprehensive help and man page database diff --git a/docs/signals.rst b/docs/signals.rst deleted file mode 100644 index 1126c2f..0000000 --- a/docs/signals.rst +++ /dev/null @@ -1,45 +0,0 @@ -Signals -======= - -.. currentmodule:: aiohttp - -Signal is a list of registered asynchronous callbacks. - -The signal's life-cycle has two stages: after creation its content -could be filled by using standard list operations: ``sig.append()`` -etc. - -After ``sig.freeze()`` call the signal is *frozen*: adding, removing -and dropping callbacks are forbidden. - -The only available operation is calling previously registered -callbacks by ``await sig.send(data)``. - -For concrete usage examples see :ref:`signals in aiohttp.web -` chapter. - -.. versionchanged:: 3.0 - - ``sig.send()`` call is forbidden for non-frozen signal. - - Support for regular (non-async) callbacks is dropped. All callbacks - should be async functions. - - -.. class:: Signal - - The signal, implements :class:`collections.abc.MutableSequence` - interface. - - .. comethod:: send(*args, **kwargs) - - Call all registered callbacks one by one starting from the begin - of list. - - .. attribute:: frozen - - ``True`` if :meth:`freeze` was called, read-only property. - - .. method:: freeze() - - Freeze the list. After the call any content modification is forbidden. diff --git a/docs/spelling_wordlist.txt b/docs/spelling_wordlist.txt index ebf58fd..1626b18 100644 --- a/docs/spelling_wordlist.txt +++ b/docs/spelling_wordlist.txt @@ -1,86 +1,5 @@ -# de-facto: -Arsenic -Backport -Backporting -BaseEventLoop -BasicAuth -BodyPartReader -Bugfixes -BytesIO -brotli -brotlipy -pydantic -CIMultiDict -CPython -Changelog -ClientSession -Codings -Config -CookieJar -Coroutine -Ctrl -Cython -Cythonize -DER -DNSResolver -Dev -Dict -Discord -Django -Dup -Facebook -HTTPException -HttpProcessingError -IP -IPv -Indices -Jinja -KiB -Locator -Mako -Mixcloud -Mongo -Mongo -MsgType -Multidicts -Multipart -Nagle -Nagle’s -Nginx -Nikolay -OAuth -Online -Overridable -PRs -Paolini -Postgres -Punycode -Pytest -Quickstart -Redis -RequestContextManager -Request’s -Runit -SSLContext -Satisfiable -Skyscanner -SocketSocketTransport -Supervisord -Svetlov -Systemd -TCP -TLS -Teardown -TestClient -Testsuite -Tf -UI -Unittest -WSMessage -WSMsgType -Websockets -Workflow abc +addons aiodns aioes aiohttp @@ -91,9 +10,10 @@ alives api api’s app -apps app’s +apps arg +Arsenic async asyncio auth @@ -107,57 +27,95 @@ awaitable backend backends backport +Backport +Backporting backports +BaseEventLoop basename +BasicAuth +BodyPartReader boolean botocore +brotli +brotlipy bugfix +bugfixes +Bugfixes builtin -cChardet +BytesIO +callables cancelled canonicalization canonicalize cchardet +cChardet ceil +Changelog +chardet +Chardet charset charsetdetect chunked chunking +CIMultiDict +ClientSession cls cmd codec +Codings committer committers config +Config configs conjunction contextmanager +CookieJar coroutine +Coroutine coroutines cpu +CPython css ctor +Ctrl cython +Cython +Cythonize cythonized de deduplicate +# de-facto: deprecations +DER dev +Dev dict +Dict +Discord django +Django dns +DNSResolver docstring +docstrings +Dup elasticsearch encodings env environ eof epoll +etag +ETag +expirations +Facebook facto fallback fallbacks filename finalizers +formatter formatters frontend getall @@ -170,36 +128,48 @@ gzipped hackish highlevel hostnames +HTTPException +HttpProcessingError httpretty https impl incapsulates +Indices infos initializer inline intaking io ip +IP ipdb +ipv +IPv ish +isort iterable iterables javascript +Jinja json keepalive keepalived keepalives keepaliving kib +KiB kwarg latin lifecycle linux localhost +Locator login lookup lookups lossless +lowercased +Mako manylinux metadata microservice @@ -208,23 +178,38 @@ middlewares miltidict misbehaviors misformed +Mixcloud +Mongo +Mongo msg +MsgType multi multidict -multidicts multidict’s +multidicts +Multidicts multipart +Multipart mypy +Nagle +Nagle’s namedtuple nameservers namespace netrc nginx +Nginx +Nikolay noop +normalizer nowait +OAuth +Online optimizations os outcoming +Overridable +Paolini param params parsers @@ -238,24 +223,32 @@ plugable plugin poller pong +Postgres pre preloaded proactor programmatically proxied +PRs pubsub +Punycode py +pydantic pyenv pyflakes pytest +Pytest +Quickstart quote’s readonly readpayload rebase redirections +Redis refactor refactored refactoring +referenceable regex regexps regexs @@ -265,23 +258,31 @@ renderers repo repr repr’s +RequestContextManager request’s +Request’s requote requoting resolvehost resolvers reusage reuseconn +Runit runtime +runtimes sa +Satisfiable schemas sendfile serializable serializer shourtcuts skipuntil +Skyscanner +SocketSocketTransport softwares ssl +SSLContext startup subapplication subclasses @@ -292,48 +293,65 @@ subprotocol subprotocols subtype supervisord +Supervisord +Svetlov symlink symlinks syscall syscalls +Systemd tarball +TCP teardown +Teardown +TestClient +Testsuite +Tf timestamps +TLS toolbar toplevel towncrier tp tuples -uWSGI +UI un unawaited unclosed unhandled unicode unittest +Unittest unix unsets unstripped +uppercased upstr url urldispatcher urlencoded -urls url’s +urls utf utils uvloop +uWSGI vcvarsall +vendored waituntil wakeup wakeups webapp websocket -websockets websocket’s +websockets +Websockets wildcard +Workflow ws wsgi +WSMessage +WSMsgType wss www xxx diff --git a/docs/streams.rst b/docs/streams.rst index 8356c39..25a83be 100644 --- a/docs/streams.rst +++ b/docs/streams.rst @@ -7,7 +7,7 @@ Streaming API ``aiohttp`` uses streams for retrieving *BODIES*: -:attr:`aiohttp.web.Request.content` and +:attr:`aiohttp.web.BaseRequest.content` and :attr:`aiohttp.ClientResponse.content` are properties with stream API. @@ -16,7 +16,7 @@ Streaming API The reader from incoming stream. User should never instantiate streams manually but use existing - :attr:`aiohttp.web.Request.content` and + :attr:`aiohttp.web.BaseRequest.content` and :attr:`aiohttp.ClientResponse.content` properties for accessing raw BODY data. @@ -70,6 +70,19 @@ Reading Methods :return bytes: the given line +.. comethod:: StreamReader.readuntil(separator="\n") + + Read until separator, where `separator` is a sequence of bytes. + + If EOF is received, and `separator` was not found, the method will + return the partial read bytes. + + If the EOF was received and the internal buffer is empty, return an + empty bytes object. + + .. versionadded:: 3.8 + + :return bytes: the given data .. comethod:: StreamReader.readchunk() diff --git a/docs/testing.rst b/docs/testing.rst index d722f3a..828c3d0 100644 --- a/docs/testing.rst +++ b/docs/testing.rst @@ -1,10 +1,10 @@ +.. module:: aiohttp.test_utils + .. _aiohttp-testing: Testing ======= -.. currentmodule:: aiohttp.test_utils - Testing aiohttp web servers --------------------------- @@ -57,7 +57,7 @@ requests to this server. :class:`~aiohttp.test_utils.TestServer` runs :class:`aiohttp.web.Application` based server, :class:`~aiohttp.test_utils.RawTestServer` starts -:class:`aiohttp.web.WebServer` low level server. +:class:`aiohttp.web.Server` low level server. For performing HTTP requests to these servers you have to create a test client: :class:`~aiohttp.test_utils.TestClient` instance. @@ -243,7 +243,7 @@ Unittest To test applications with the standard library's unittest or unittest-based functionality, the AioHTTPTestCase is provided:: - from aiohttp.test_utils import AioHTTPTestCase, unittest_run_loop + from aiohttp.test_utils import AioHTTPTestCase from aiohttp import web class MyAppTestCase(AioHTTPTestCase): @@ -259,26 +259,11 @@ functionality, the AioHTTPTestCase is provided:: app.router.add_get('/', hello) return app - # the unittest_run_loop decorator can be used in tandem with - # the AioHTTPTestCase to simplify running - # tests that are asynchronous - @unittest_run_loop async def test_example(self): - resp = await self.client.request("GET", "/") - assert resp.status == 200 - text = await resp.text() - assert "Hello, world" in text - - # a vanilla example - def test_example_vanilla(self): - async def test_get_route(): - url = "/" - resp = await self.client.request("GET", url) - assert resp.status == 200 + async with self.client.request("GET", "/") as resp: + self.assertEqual(resp.status, 200) text = await resp.text() - assert "Hello, world" in text - - self.loop.run_until_complete(test_get_route()) + self.assertIn("Hello, world", text) .. class:: AioHTTPTestCase @@ -306,7 +291,7 @@ functionality, the AioHTTPTestCase is provided:: .. attribute:: app - The application returned by :meth:`get_app` + The application returned by :meth:`~aiohttp.test_utils.AioHTTPTestCase.get_application` (:class:`aiohttp.web.Application` instance). .. comethod:: get_client() @@ -337,18 +322,34 @@ functionality, the AioHTTPTestCase is provided:: .. comethod:: setUpAsync() - This async method do nothing by default and can be overridden to execute - asynchronous code during the ``setUp`` stage of the ``TestCase``. + This async method can be overridden to execute asynchronous code during + the ``setUp`` stage of the ``TestCase``:: + + async def setUpAsync(self): + await super().setUpAsync() + await foo() .. versionadded:: 2.3 + .. versionchanged:: 3.8 + + ``await super().setUpAsync()`` call is required. + .. comethod:: tearDownAsync() - This async method do nothing by default and can be overridden to execute - asynchronous code during the ``tearDown`` stage of the ``TestCase``. + This async method can be overridden to execute asynchronous code during + the ``tearDown`` stage of the ``TestCase``:: + + async def tearDownAsync(self): + await super().tearDownAsync() + await foo() .. versionadded:: 2.3 + .. versionchanged:: 3.8 + + ``await super().tearDownAsync()`` call is required. + .. method:: setUp() Standard test initialization method. @@ -361,16 +362,13 @@ functionality, the AioHTTPTestCase is provided:: .. note:: The ``TestClient``'s methods are asynchronous: you have to - execute function on the test client using asynchronous methods. - - A basic test class wraps every test method by - :func:`unittest_run_loop` decorator:: + execute functions on the test client using asynchronous methods.:: class TestA(AioHTTPTestCase): - @unittest_run_loop async def test_f(self): - resp = await self.client.get('/') + async with self.client.get('/') as resp: + body = await resp.text() .. decorator:: unittest_run_loop: @@ -381,6 +379,10 @@ functionality, the AioHTTPTestCase is provided:: Handles executing an asynchronous function, using the :attr:`AioHTTPTestCase.loop` of the :class:`AioHTTPTestCase`. + .. deprecated:: 3.8 + In 3.8+ :class:`AioHTTPTestCase` inherits from :class:`unittest.IsolatedAsyncioTestCase` + making this decorator unneeded. It is now a no-op. + Faking request object --------------------- @@ -460,7 +462,7 @@ conditions that hard to reproduce on real server:: :type writer: aiohttp.StreamWriter :param transport: asyncio transport instance - :type transport: asyncio.transports.Transport + :type transport: asyncio.Transport :param payload: raw payload reader object :type payload: aiohttp.StreamReader @@ -527,7 +529,7 @@ basis, the TestClient object can be used directly:: A full list of the utilities provided can be found at the -:data:`api reference ` +:mod:`api reference ` Testing API Reference @@ -539,15 +541,15 @@ Test server Runs given :class:`aiohttp.web.Application` instance on random TCP port. After creation the server is not started yet, use -:meth:`~aiohttp.test_utils.TestServer.start_server` for actual server -starting and :meth:`~aiohttp.test_utils.TestServer.close` for +:meth:`~aiohttp.test_utils.BaseTestServer.start_server` for actual server +starting and :meth:`~aiohttp.test_utils.BaseTestServer.close` for stopping/cleanup. Test server usually works in conjunction with :class:`aiohttp.test_utils.TestClient` which provides handy client methods for accessing to the server. -.. class:: BaseTestServer(*, scheme='http', host='127.0.0.1', port=None) +.. class:: BaseTestServer(*, scheme='http', host='127.0.0.1', port=None, socket_factory=get_port_socket) Base class for test servers. @@ -561,6 +563,13 @@ for accessing to the server. .. versionadded:: 3.0 + :param collections.abc.Callable[[str,int,socket.AddressFamily],socket.socket] socket_factory: optional + Factory to create a socket for the server. + By default creates a TCP socket and binds it + to ``host`` and ``port``. + + .. versionadded:: 3.8 + .. attribute:: scheme A *scheme* for tested application, ``'http'`` for non-protected @@ -576,12 +585,18 @@ for accessing to the server. .. attribute:: handler - :class:`aiohttp.web.WebServer` used for HTTP requests serving. + :class:`aiohttp.web.Server` used for HTTP requests serving. .. attribute:: server :class:`asyncio.AbstractServer` used for managing accepted connections. + .. attribute:: socket_factory + + *socket_factory* used to create and bind a server socket. + + .. versionadded:: 3.8 + .. comethod:: start_server(loop=None, **kwargs) :param loop: the event_loop to use @@ -663,7 +678,8 @@ Test Client first with ``TestServer(app)``. :param cookie_jar: an optional :class:`aiohttp.CookieJar` instance, - may be useful with ``CookieJar(unsafe=True)`` + may be useful with + ``CookieJar(unsafe=True, treat_as_secure_origin="http://127.0.0.1")`` option. :param str scheme: HTTP scheme, non-protected ``"http"`` by default. @@ -693,7 +709,7 @@ Test Client .. attribute:: app - An alias for :attr:`self.server.app`. return ``None`` if + An alias for ``self.server.app``. return ``None`` if ``self.server`` is not :class:`TestServer` instance(e.g. :class:`RawTestServer` instance for test low-level server). diff --git a/docs/third_party.rst b/docs/third_party.rst index d5bcb3d..5ba6464 100644 --- a/docs/third_party.rst +++ b/docs/third_party.rst @@ -4,26 +4,26 @@ Third-Party libraries ===================== -aiohttp is not the library for making HTTP requests and creating WEB -server only. +aiohttp is not just a library for making HTTP requests and creating web +servers. -It is the grand basement for libraries built *on top* of aiohttp. +It is the foundation for libraries built *on top* of aiohttp. This page is a list of these tools. -Please feel free to add your open sourced library if it's not enlisted -yet by making Pull Request to https://github.com/aio-libs/aiohttp/ +Please feel free to add your open source library if it's not listed +yet by making a pull request to https://github.com/aio-libs/aiohttp/ -* Why do you might want to include your awesome library into the list? +* Why would you want to include your awesome library in this list? -* Just because the list increases your library visibility. People +* Because the list increases your library visibility. People will have an easy way to find it. Officially supported -------------------- -This list contains libraries which are supported by *aio-libs* team +This list contains libraries which are supported by the *aio-libs* team and located on https://github.com/aio-libs @@ -31,7 +31,7 @@ aiohttp extensions ^^^^^^^^^^^^^^^^^^ - `aiohttp-session `_ - provides sessions for :mod:`aiohttp.web`. + provides sessions for :mod:`aiohttp.web`. - `aiohttp-debugtoolbar `_ is a library for *debug toolbar* support for :mod:`aiohttp.web`. @@ -65,7 +65,7 @@ Database drivers - `aiopg `_ PostgreSQL async driver. -- `aiomysql `_ MySql async driver. +- `aiomysql `_ MySQL async driver. - `aioredis `_ Redis async driver. @@ -82,32 +82,66 @@ Other tools Approved third-party libraries ------------------------------ -The libraries are not part of ``aio-libs`` but they are proven to be very +These libraries are not part of ``aio-libs`` but they have proven to be very well written and highly recommended for usage. - `uvloop `_ Ultra fast implementation of asyncio event loop on top of ``libuv``. - We are highly recommending to use it instead of standard ``asyncio``. + We highly recommend to use this instead of standard ``asyncio``. Database drivers ^^^^^^^^^^^^^^^^ - `asyncpg `_ Another - PostgreSQL async driver. It's much faster than ``aiopg`` but it is - not drop-in replacement -- the API is different. Anyway please take - a look on it -- the driver is really incredible fast. + PostgreSQL async driver. It's much faster than ``aiopg`` but is + not a drop-in replacement -- the API is different. But, please take + a look at it -- the driver is incredibly fast. +OpenAPI / Swagger extensions +---------------------------- + +Extensions bringing `OpenAPI `_ +support to aiohttp web servers. + +- `aiohttp-apispec `_ + Build and document REST APIs with ``aiohttp`` and ``apispec``. + +- `aiohttp_apiset `_ + Package to build routes using swagger specification. + +- `aiohttp-pydantic `_ + An ``aiohttp.View`` to validate the HTTP request's body, query-string, and + headers regarding function annotations and generate OpenAPI doc. Python 3.8+ + required. + +- `aiohttp-swagger `_ + Swagger API Documentation builder for aiohttp server. + +- `aiohttp-swagger3 `_ + Library for Swagger documentation builder and validating aiohttp requests + using swagger specification 3.0. + +- `aiohttp-swaggerify `_ + Library to automatically generate swagger2.0 definition for aiohttp endpoints. + +- `aio-openapi `_ + Asynchronous web middleware for aiohttp and serving Rest APIs with OpenAPI v3 + specification and with optional PostgreSQL database bindings. + +- `rororo `_ + Implement ``aiohttp.web`` OpenAPI 3 server applications with schema first + approach. Python 3.6+ required. Others ------ -The list of libraries which are exists but not enlisted in former categories. +Here is a list of other known libraries that do not belong in the former categories. -They may be perfect or not -- we don't know. +We cannot vouch for the quality of these libraries, use them at your own risk. Please add your library reference here first and after some time -period ask to raise the status. +ask to raise the status. - `aiohttp-cache `_ A cache system for aiohttp server. @@ -118,18 +152,9 @@ period ask to raise the status. - `gain `_ Web crawling framework based on asyncio for everyone. -- `aiohttp-swagger `_ - Swagger API Documentation builder for aiohttp server. - -- `aiohttp-swaggerify `_ - Library to automatically generate swagger2.0 definition for aiohttp endpoints. - - `aiohttp-validate `_ Simple library that helps you validate your API endpoints requests/responses with json schema. -- `aiohttp-pydantic `_ - An ``aiohttp.View`` to validate the HTTP request's body, query-string, and headers regarding function annotations and generate Open API doc. Python 3.8+ required. - - `raven-aiohttp `_ An aiohttp transport for raven-python (Sentry client). @@ -152,9 +177,6 @@ period ask to raise the status. `_ A transmute implementation for aiohttp. -- `aiohttp_apiset `_ - Package to build routes using swagger specification. - - `aiohttp-login `_ Registration and authorization (including social) for aiohttp applications. @@ -206,9 +228,6 @@ period ask to raise the status. - `aiogram `_ A fully asynchronous library for Telegram Bot API written with asyncio and aiohttp. -- `vk.py `_ - Extremely-fast Python 3.6+ toolkit for create applications work`s with VKAPI. - - `aiohttp-graphql `_ GraphQL and GraphIQL interface for aiohttp. @@ -230,9 +249,6 @@ period ask to raise the status. - `GINO `_ An asyncio ORM on top of SQLAlchemy core, delivered with an aiohttp extension. -- `aiohttp-apispec `_ - Build and document REST APIs with ``aiohttp`` and ``apispec``. - - `eider-py `_ Python implementation of the `Eider RPC protocol `_. @@ -248,10 +264,6 @@ period ask to raise the status. - `DBGR `_ Terminal based tool to test and debug HTTP APIs with ``aiohttp``. -- `rororo `_ - Implement ``aiohtp.web`` OpenAPI 3 server applications with schema first - approach. Python 3.6+ required. - - `aiohttp-middlewares `_ Collection of useful middlewares for ``aiohttp.web`` applications. Python 3.6+ required. @@ -262,3 +274,12 @@ period ask to raise the status. - `aiohttp-sse-client `_ A Server-Sent Event python client base on aiohttp. Python 3.6+ required. + +- `aiohttp-retry `_ + Wrapper for aiohttp client for retrying requests. Python 3.6+ required. + +- `aiohttp-socks `_ + SOCKS proxy connector for aiohttp. + +- `aiohttp-catcher `_ + An aiohttp middleware library for centralized error handling in aiohttp servers. diff --git a/docs/tracing_reference.rst b/docs/tracing_reference.rst index 772b485..76fc365 100644 --- a/docs/tracing_reference.rst +++ b/docs/tracing_reference.rst @@ -35,7 +35,7 @@ Overview acquire_connection[description="Connection acquiring"]; headers_received; - headers_sent; + headers_sent[description="on_request_headers_sent"]; chunk_sent[description="on_request_chunk_sent"]; chunk_received[description="on_response_chunk_received"]; @@ -269,6 +269,14 @@ TraceConfig ``params`` is :class:`aiohttp.TraceDnsCacheMissParams` instance. + .. attribute:: on_request_headers_sent + + Property that gives access to the signals that will be executed + when request headers are sent. + + ``params`` is :class:`aiohttp.TraceRequestHeadersSentParams` instance. + + .. versionadded:: 3.8 TraceRequestStartParams ----------------------- @@ -492,3 +500,24 @@ TraceDnsCacheMissParams .. attribute:: host Host didn't find the cache. + +TraceRequestHeadersSentParams +----------------------------- + +.. class:: TraceRequestHeadersSentParams + + See :attr:`TraceConfig.on_request_headers_sent` for details. + + .. versionadded:: 3.8 + + .. attribute:: method + + Method that will be used to make the request. + + .. attribute:: url + + URL that will be used for the request. + + .. attribute:: headers + + Headers that will be used for the request. diff --git a/docs/utilities.rst b/docs/utilities.rst index c328244..76d685d 100644 --- a/docs/utilities.rst +++ b/docs/utilities.rst @@ -15,6 +15,5 @@ Miscellaneous API Shared between Client And Server. multipart multipart_reference streams - signals structures websocket_utilities diff --git a/docs/web_advanced.rst b/docs/web_advanced.rst index 01a3341..3a98b78 100644 --- a/docs/web_advanced.rst +++ b/docs/web_advanced.rst @@ -240,6 +240,13 @@ Data Sharing aka No Singletons Please :mod:`aiohttp.web` discourages the use of *global variables*, aka *singletons*. Every variable should have its own context that is *not global*. +Global variables are generally considered bad practice due to the complexity +they add in keeping track of state changes to variables. + +*aiohttp* does not use globals by design, which will reduce the number of bugs +and/or unexpected behaviors for its users. For example, an i18n translated string +being written for one request and then being served to another. + So, :class:`Application` and :class:`Request` support a :class:`collections.abc.MutableMapping` interface (i.e. they are dict-like objects), allowing them to be used as data stores. @@ -272,6 +279,10 @@ For this please use :attr:`Request.config_dict` read-only property:: async def handler(request): data = request.config_dict['my_private_key'] +The app object can be used in this way to reuse a database connection or anything +else needed throughout the application. + +See this reference section for more detail: :ref:`aiohttp-web-app-and-router`. Request's storage ^^^^^^^^^^^^^^^^^ @@ -431,7 +442,7 @@ the keyword-only ``middlewares`` parameter:: Internally, a single :ref:`request handler ` is constructed by applying the middleware chain to the original handler in reverse order, -and is called by the :class:`RequestHandler` as a regular *handler*. +and is called by the :class:`~aiohttp.web.RequestHandler` as a regular *handler*. Since *middlewares* are themselves coroutines, they may perform extra ``await`` calls when creating a new handler, e.g. call database etc. @@ -615,10 +626,6 @@ one ``yield``. *aiohttp* guarantees that *cleanup code* is called if and only if *startup code* was successfully finished. -Asynchronous generators are supported by Python 3.6+, on Python 3.5 -please use `async_generator `_ -library. - .. versionadded:: 3.1 .. _aiohttp-web-nested-applications: @@ -748,7 +755,7 @@ header:: Custom resource implementation ------------------------------ -To register custom resource use :meth:`UrlDispatcher.register_resource`. +To register custom resource use :meth:`~aiohttp.web.UrlDispatcher.register_resource`. Resource instance must implement `AbstractResource` interface. .. _aiohttp-web-app-runners: @@ -849,9 +856,9 @@ sources (e.g. ZeroMQ, Redis Pub/Sub, AMQP, etc.) to react to received messages within the application. For example the background task could listen to ZeroMQ on -:data:`zmq.SUB` socket, process and forward retrieved messages to +``zmq.SUB`` socket, process and forward retrieved messages to clients connected via WebSocket that are stored somewhere in the -application (e.g. in the :obj:`application['websockets']` list). +application (e.g. in the ``application['websockets']`` list). To run such short and long running background tasks aiohttp provides an ability to register :attr:`Application.on_startup` signal handler(s) that @@ -860,7 +867,8 @@ will run along with the application's request handler. For example there's a need to run one quick task and two long running tasks that will live till the application is alive. The appropriate background tasks could be registered as an :attr:`Application.on_startup` -signal handlers as shown in the example below:: +signal handler or :attr:`Application.cleanup_ctx` as shown in the example +below:: async def listen_to_redis(app): @@ -878,25 +886,70 @@ signal handlers as shown in the example below:: await sub.quit() - async def start_background_tasks(app): + async def background_tasks(app): app['redis_listener'] = asyncio.create_task(listen_to_redis(app)) + yield - async def cleanup_background_tasks(app): app['redis_listener'].cancel() await app['redis_listener'] app = web.Application() - app.on_startup.append(start_background_tasks) - app.on_cleanup.append(cleanup_background_tasks) + app.cleanup_ctx.append(background_tasks) web.run_app(app) -The task :func:`listen_to_redis` will run forever. +The task ``listen_to_redis`` will run forever. To shut it down correctly :attr:`Application.on_cleanup` signal handler may be used to send a cancellation to it. +.. _aiohttp-web-complex-applications: + +Complex Applications +^^^^^^^^^^^^^^^^^^^^ + +Sometimes aiohttp is not the sole part of an application and additional +tasks/processes may need to be run alongside the aiohttp :class:`Application`. + +Generally, the best way to achieve this is to use :func:`aiohttp.web.run_app` +as the entry point for the program. Other tasks can then be run via +:attr:`Application.startup` and :attr:`Application.on_cleanup`. By having the +:class:`Application` control the lifecycle of the entire program, the code +will be more robust and ensure that the tasks are started and stopped along +with the application. + +For example, running a long-lived task alongside the :class:`Application` +can be done with a :ref:`aiohttp-web-cleanup-ctx` function like:: + + + async def run_other_task(_app): + task = asyncio.create_task(other_long_task()) + + yield + + task.cancel() + with suppress(asyncio.CancelledError): + await task # Ensure any exceptions etc. are raised. + + app.cleanup_ctx.append(run_other_task) + + +Or a separate process can be run with something like:: + + + async def run_process(_app): + proc = await asyncio.create_subprocess_exec(path) + + yield + + if proc.returncode is None: + proc.terminate() + await proc.wait() + + app.cleanup_ctx.append(run_process) + + Handling error pages -------------------- @@ -995,8 +1048,7 @@ Install with ``pip``: $ pip install aiohttp-devtools * ``runserver`` provides a development server with auto-reload, - live-reload, static file serving and `aiohttp-debugtoolbar`_ - integration. + live-reload, static file serving. * ``start`` is a `cookiecutter command which does the donkey work of creating new :mod:`aiohttp.web` Applications. diff --git a/docs/web_lowlevel.rst b/docs/web_lowlevel.rst index 696c58d..06c3265 100644 --- a/docs/web_lowlevel.rst +++ b/docs/web_lowlevel.rst @@ -19,7 +19,7 @@ request and returns a response object. This is done by introducing :class:`aiohttp.web.Server` class which serves a *protocol factory* role for -:meth:`asyncio.AbstractEventLoop.create_server` and bridges data +:meth:`asyncio.loop.create_server` and bridges data stream to *web handler* and sends result back. @@ -69,13 +69,7 @@ The following code demonstrates very trivial usage example:: await asyncio.sleep(100*3600) - loop = asyncio.get_event_loop() - - try: - loop.run_until_complete(main()) - except KeyboardInterrupt: - pass - loop.close() + asyncio.run(main()) In the snippet we have ``handler`` which returns a regular diff --git a/docs/web_quickstart.rst b/docs/web_quickstart.rst index 1db1d68..c362327 100644 --- a/docs/web_quickstart.rst +++ b/docs/web_quickstart.rst @@ -132,7 +132,7 @@ requests on a *path* having **any** *HTTP method*:: app.add_routes([web.route('*', '/path', all_handler)]) The *HTTP method* can be queried later in the request handler using the -:attr:`Request.method` property. +:attr:`aiohttp.web.BaseRequest.method` property. By default endpoints added with ``GET`` method will accept ``HEAD`` requests and return the same response headers as they would @@ -346,7 +346,7 @@ Route tables look like Django way:: web.post('/post', handle_post), -The snippet calls :meth:`~aiohttp.web.UrlDispather.add_routes` to +The snippet calls :meth:`~aiohttp.web.UrlDispatcher.add_routes` to register a list of *route definitions* (:class:`aiohttp.web.RouteDef` instances) created by :func:`aiohttp.web.get` or :func:`aiohttp.web.post` functions. @@ -390,7 +390,7 @@ The container is a list-like object with additional decorators routes. After filling the container -:meth:`~aiohttp.web.UrlDispather.add_routes` is used for adding +:meth:`~aiohttp.web.UrlDispatcher.add_routes` is used for adding registered *route definitions* into application's router. .. seealso:: :ref:`aiohttp-web-route-table-def` reference. @@ -459,17 +459,17 @@ HTTP Forms HTTP Forms are supported out of the box. If form's method is ``"GET"`` (``
``) use -:attr:`Request.query` for getting form data. +:attr:`aiohttp.web.BaseRequest.query` for getting form data. To access form data with ``"POST"`` method use -:meth:`Request.post` or :meth:`Request.multipart`. +:meth:`aiohttp.web.BaseRequest.post` or :meth:`aiohttp.web.BaseRequest.multipart`. -:meth:`Request.post` accepts both +:meth:`aiohttp.web.BaseRequest.post` accepts both ``'application/x-www-form-urlencoded'`` and ``'multipart/form-data'`` form's data encoding (e.g. ````). It stores files data in temporary directory. If `client_max_size` is specified `post` raises `ValueError` exception. -For efficiency use :meth:`Request.multipart`, It is especially effective +For efficiency use :meth:`aiohttp.web.BaseRequest.multipart`, It is especially effective for uploading large files (:ref:`aiohttp-web-file-upload`). Values submitted by the following form: @@ -543,10 +543,10 @@ a container for the file as well as some of its metadata:: You might have noticed a big warning in the example above. The general issue is -that :meth:`Request.post` reads the whole payload in memory, +that :meth:`aiohttp.web.BaseRequest.post` reads the whole payload in memory, resulting in possible :abbr:`OOM (Out Of Memory)` errors. To avoid this, for multipart uploads, you -should use :meth:`Request.multipart` which returns a :ref:`multipart reader +should use :meth:`aiohttp.web.BaseRequest.multipart` which returns a :ref:`multipart reader `:: async def store_mp3_handler(request): diff --git a/docs/web_reference.rst b/docs/web_reference.rst index 4073eb2..a156f47 100644 --- a/docs/web_reference.rst +++ b/docs/web_reference.rst @@ -118,7 +118,7 @@ and :ref:`aiohttp-web-signals` handlers. - Overridden value by :meth:`~BaseRequest.clone` call. - *Host* HTTP header - - :func:`socket.gtfqdn` + - :func:`socket.getfqdn` Read-only :class:`str` property. @@ -227,9 +227,9 @@ and :ref:`aiohttp-web-signals` handlers. .. attribute:: cookies - A multidict of all request's cookies. + A read-only dictionary-like object containing the request's cookies. - Read-only :class:`~multidict.MultiDictProxy` lazy property. + Read-only :class:`~types.MappingProxyType` property. .. attribute:: content @@ -336,6 +336,26 @@ and :ref:`aiohttp-web-signals` handlers. .. versionadded:: 3.1 + .. attribute:: if_match + + Read-only property that returns :class:`~aiohttp.ETag` objects specified + in the *If-Match* header. + + Returns :class:`tuple` of :class:`~aiohttp.ETag` or ``None`` if + *If-Match* header is absent. + + .. versionadded:: 3.8 + + .. attribute:: if_none_match + + Read-only property that returns :class:`~aiohttp.ETag` objects specified + *If-None-Match* header. + + Returns :class:`tuple` of :class:`~aiohttp.ETag` or ``None`` if + *If-None-Match* header is absent. + + .. versionadded:: 3.8 + .. attribute:: if_range Read-only property that returns the date specified in the @@ -383,7 +403,7 @@ and :ref:`aiohttp-web-signals` handlers. .. note:: The method **does** store read data internally, subsequent - :meth:`~Request.read` call will return the same value. + :meth:`~aiohttp.web.BaseRequest.read` call will return the same value. .. comethod:: text() @@ -395,7 +415,7 @@ and :ref:`aiohttp-web-signals` handlers. .. note:: The method **does** store read data internally, subsequent - :meth:`~Request.text` call will return the same value. + :meth:`~aiohttp.web.BaseRequest.text` call will return the same value. .. comethod:: json(*, loads=json.loads) @@ -408,7 +428,7 @@ and :ref:`aiohttp-web-signals` handlers. body = await self.text() return loads(body) - :param callable loads: any :term:`callable` that accepts + :param collections.abc.Callable loads: any :term:`callable` that accepts :class:`str` and returns :class:`dict` with parsed JSON (:func:`json.loads` by default). @@ -416,12 +436,12 @@ and :ref:`aiohttp-web-signals` handlers. .. note:: The method **does** store read data internally, subsequent - :meth:`~Request.json` call will return the same value. + :meth:`~aiohttp.web.BaseRequest.json` call will return the same value. .. comethod:: multipart() - Returns :class:`aiohttp.multipart.MultipartReader` which processes + Returns :class:`aiohttp.MultipartReader` which processes incoming *multipart* request. The method is just a boilerplate :ref:`coroutine ` @@ -460,7 +480,7 @@ and :ref:`aiohttp-web-signals` handlers. .. note:: The method **does** store read data internally, subsequent - :meth:`~Request.post` call will return the same value. + :meth:`~aiohttp.web.BaseRequest.post` call will return the same value. .. comethod:: release() @@ -470,7 +490,7 @@ and :ref:`aiohttp-web-signals` handlers. .. note:: - User code may never call :meth:`~Request.release`, all + User code may never call :meth:`~aiohttp.web.BaseRequest.release`, all required work will be processed by :mod:`aiohttp.web` internal machinery. @@ -619,7 +639,7 @@ StreamResponse .. attribute:: keep_alive - Read-only property, copy of :attr:`Request.keep_alive` by default. + Read-only property, copy of :attr:`aiohttp.web.BaseRequest.keep_alive` by default. Can be switched to ``False`` by :meth:`force_close` call. @@ -733,7 +753,7 @@ StreamResponse :param int version: a decimal integer, identifies to which version of the state management specification the cookie - conforms. (Optional, *version=1* by default) + conforms. (optional) :param str samesite: Asserts that a cookie must not be sent with cross-origin requests, providing some protection @@ -782,6 +802,20 @@ StreamResponse as an :class:`int` or a :class:`float` object, and the value ``None`` to unset the header. + .. attribute:: etag + + *ETag* header for outgoing response. + + This property accepts raw :class:`str` values, :class:`~aiohttp.ETag` + objects and the value ``None`` to unset the header. + + In case of :class:`str` input, etag is considered as strong by default. + + **Do not** use double quotes ``"`` in the etag value, + they will be added automatically. + + .. versionadded:: 3.8 + .. comethod:: prepare(request) :param aiohttp.web.Request request: HTTP request object, that the @@ -885,7 +919,7 @@ Response Setting :attr:`text` also recalculates :attr:`~StreamResponse.content_length` value and - :attr:`~StreamResponse.body` value + :attr:`~aiohttp.StreamResponse.body` value Resetting :attr:`text` (assigning ``None``) sets :attr:`~StreamResponse.content_length` to ``None`` too, dropping @@ -1083,7 +1117,7 @@ WebSocketResponse single message, ``None`` for not overriding per-socket setting. - :param callable dumps: any :term:`callable` that accepts an object and + :param collections.abc.Callable dumps: any :term:`callable` that accepts an object and returns a JSON string (:func:`json.dumps` by default). @@ -1098,14 +1132,14 @@ WebSocketResponse The method is converted into :term:`coroutine`, *compress* parameter added. - .. comethod:: close(*, code=1000, message=b'') + .. comethod:: close(*, code=WSCloseCode.OK, message=b'') A :ref:`coroutine` that initiates closing handshake by sending :const:`~aiohttp.WSMsgType.CLOSE` message. It is safe to call `close()` from different task. - :param int code: closing code + :param int code: closing code. See also :class:`~aiohttp.WSCloseCode`. :param message: optional payload of *close* message, :class:`str` (converted to *UTF-8* encoded bytes) @@ -1182,7 +1216,7 @@ WebSocketResponse Can only be called by the request handling task. - :param callable loads: any :term:`callable` that accepts + :param collections.abc.Callable loads: any :term:`callable` that accepts :class:`str` and returns :class:`dict` with parsed JSON (:func:`json.loads` by default). @@ -1304,7 +1338,7 @@ properties for later access from a :ref:`handler` via the conn.execute("DELETE * FROM table") Although :class:`Application` is a :obj:`dict`-like object, it can't be -duplicated like one using :meth:`Application.copy`. +duplicated like one using :meth:`~aiohttp.web.Application.copy`. .. class:: Application(*, logger=, router=None,middlewares=(), \ handler_args=None, client_max_size=1024**2, \ @@ -1373,7 +1407,7 @@ duplicated like one using :meth:`Application.copy`. .. attribute:: on_response_prepare - A :class:`~aiohttp.Signal` that is fired near the end + A :class:`~aiosignal.Signal` that is fired near the end of :meth:`StreamResponse.prepare` with parameters *request* and *response*. It can be used, for example, to add custom headers to each response, or to modify the default headers computed by the application, @@ -1386,7 +1420,7 @@ duplicated like one using :meth:`Application.copy`. .. attribute:: on_startup - A :class:`~aiohttp.Signal` that is fired on application start-up. + A :class:`~aiosignal.Signal` that is fired on application start-up. Subscribers may use the signal to run background tasks in the event loop along with the application's request handler just after the @@ -1401,7 +1435,7 @@ duplicated like one using :meth:`Application.copy`. .. attribute:: on_shutdown - A :class:`~aiohttp.Signal` that is fired on application shutdown. + A :class:`~aiosignal.Signal` that is fired on application shutdown. Subscribers may use the signal for gracefully closing long running connections, e.g. websockets and data streaming. @@ -1421,7 +1455,7 @@ duplicated like one using :meth:`Application.copy`. .. attribute:: on_cleanup - A :class:`~aiohttp.Signal` that is fired on application cleanup. + A :class:`~aiosignal.Signal` that is fired on application cleanup. Subscribers may use the signal for gracefully closing connections to database server etc. @@ -1474,7 +1508,7 @@ duplicated like one using :meth:`Application.copy`. :param Application subapp: nested application. - :returns: a :class:`MatchedSubAppResource` instance. + :returns: a :class:`~aiohttp.web.MatchedSubAppResource` instance. .. method:: add_routes(routes_table) @@ -1581,8 +1615,8 @@ duplicated like one using :meth:`Application.copy`. based but traversal ones). For sake of that fact we have very trivial ABC for - :class:`AbstractRouter`: it should have only - :meth:`AbstractRouter.resolve` coroutine. + :class:`~aiohttp.abc.AbstractRouter`: it should have only + :meth:`aiohttp.abc.AbstractRouter.resolve` coroutine. No methods for adding routes or route reversing (getting URL by route name). All those are router implementation details (but, @@ -1594,7 +1628,7 @@ Server ^^^^^^ A protocol factory compatible with -:meth:`~asyncio.AbstreactEventLoop.create_server`. +:meth:`~asyncio.AbstractEventLoop.create_server`. .. class:: Server @@ -1621,11 +1655,11 @@ Router For dispatching URLs to :ref:`handlers` :mod:`aiohttp.web` uses *routers*. -Router is any object that implements :class:`AbstractRouter` interface. +Router is any object that implements :class:`~aiohttp.abc.AbstractRouter` interface. :mod:`aiohttp.web` provides an implementation called :class:`UrlDispatcher`. -:class:`Application` uses :class:`UrlDispatcher` as :meth:`router` by default. +:class:`Application` uses :class:`UrlDispatcher` as :meth:`~aiohttp.web.Application.router` by default. .. class:: UrlDispatcher() @@ -1684,13 +1718,13 @@ Router is any object that implements :class:`AbstractRouter` interface. :param str path: route path. Should be started with slash (``'/'``). - :param callable handler: route handler. + :param collections.abc.Callable handler: route handler. :param str name: optional route name. - :param coroutine expect_handler: optional *expect* header handler. + :param collections.abc.Coroutine expect_handler: optional *expect* header handler. - :returns: new :class:`PlainRoute` or :class:`DynamicRoute` instance. + :returns: new :class:`AbstractRoute` instance. .. method:: add_routes(routes_table) @@ -1789,7 +1823,7 @@ Router is any object that implements :class:`AbstractRouter` interface. :param str name: optional route name. - :param coroutine expect_handler: optional *expect* header handler. + :param collections.abc.Coroutine expect_handler: optional *expect* header handler. :param int chunk_size: size of single chunk for file downloading, 256Kb by default. @@ -1809,23 +1843,23 @@ Router is any object that implements :class:`AbstractRouter` interface. :param bool append_version: flag for adding file version (hash) to the url query string, this value will be used as default when you call to - :meth:`StaticRoute.url` and - :meth:`StaticRoute.url_for` methods. + :meth:`~aiohttp.web.AbstractRoute.url` and + :meth:`~aiohttp.web.AbstractRoute.url_for` methods. - :returns: new :class:`StaticRoute` instance. + :returns: new :class:`~aiohttp.web.AbstractRoute` instance. .. comethod:: resolve(request) A :ref:`coroutine` that returns - :class:`AbstractMatchInfo` for *request*. + :class:`~aiohttp.abc.AbstractMatchInfo` for *request*. The method never raises exception, but returns - :class:`AbstractMatchInfo` instance with: + :class:`~aiohttp.abc.AbstractMatchInfo` instance with: - 1. :attr:`~AbstractMatchInfo.http_exception` assigned to + 1. :attr:`~aiohttp.abc.AbstractMatchInfo.http_exception` assigned to :exc:`HTTPException` instance. - 2. :attr:`~AbstractMatchInfo.handler` which raises + 2. :meth:`~aiohttp.abc.AbstractMatchInfo.handler` which raises :exc:`HTTPNotFound` or :exc:`HTTPMethodNotAllowed` on handler's execution if there is no registered route for *request*. @@ -1834,7 +1868,7 @@ Router is any object that implements :class:`AbstractRouter` interface. Used by internal machinery, end user unlikely need to call the method. - .. note:: The method uses :attr:`Request.raw_path` for pattern + .. note:: The method uses :attr:`aiohttp.web.BaseRequest.raw_path` for pattern matching against registered routes. .. method:: resources() @@ -1866,7 +1900,7 @@ Router is any object that implements :class:`AbstractRouter` interface. *all* named **resources**. The view maps every named resource's **name** to the - :class:`BaseResource` instance. It supports the usual + :class:`AbstractResource` instance. It supports the usual :obj:`dict`-like operations, except for any mutable operations (i.e. it's **read-only**):: @@ -1900,11 +1934,11 @@ unique *name* and at least one :term:`route`. finished. 4. Otherwise router tries next resource from the *routing table*. 5. If the end of *routing table* is reached and no *resource* / - *route* pair found the *router* returns special :class:`AbstractMatchInfo` - instance with :attr:`AbstractMatchInfo.http_exception` is not ``None`` + *route* pair found the *router* returns special :class:`~aiohttp.abc.AbstractMatchInfo` + instance with :attr:`aiohttp.abc.AbstractMatchInfo.http_exception` is not ``None`` but :exc:`HTTPException` with either *HTTP 404 Not Found* or *HTTP 405 Method Not Allowed* status code. - Registered :attr:`AbstractMatchInfo.handler` raises this exception on call. + Registered :meth:`~aiohttp.abc.AbstractMatchInfo.handler` raises this exception on call. User should never instantiate resource classes but give it by :meth:`UrlDispatcher.add_resource` call. @@ -2000,9 +2034,9 @@ Resource classes hierarchy:: The method should be unique for resource. - :param callable handler: route handler. + :param collections.abc.Callable handler: route handler. - :param coroutine expect_handler: optional *expect* header handler. + :param collections.abc.Coroutine expect_handler: optional *expect* header handler. :returns: new :class:`ResourceRoute` instance. @@ -2387,7 +2421,7 @@ A routes table definition used for describing routes by decorators .. class:: RouteTableDef() A sequence of :class:`RouteDef` instances (implements - :class:`abc.collections.Sequence` protocol). + :class:`collections.abc.Sequence` protocol). In addition to all standard :class:`list` methods the class provides also methods like ``get()`` and ``post()`` for adding new @@ -2471,12 +2505,12 @@ Matching result can be accessible from handler as :attr:`Request.match_info` attribute. In general the result may be any object derived from -:class:`AbstractMatchInfo` (:class:`UrlMappingMatchInfo` for default +:class:`~aiohttp.abc.AbstractMatchInfo` (:class:`UrlMappingMatchInfo` for default :class:`UrlDispatcher` router). .. class:: UrlMappingMatchInfo - Inherited from :class:`dict` and :class:`AbstractMatchInfo`. Dict + Inherited from :class:`dict` and :class:`~aiohttp.abc.AbstractMatchInfo`. Dict items are filled by matching info and is :term:`resource`\-specific. .. attribute:: expect_handler @@ -2489,7 +2523,7 @@ In general the result may be any object derived from .. attribute:: route - :class:`Route` instance for url matching. + :class:`AbstractRoute` instance for url matching. View @@ -2497,7 +2531,7 @@ View .. class:: View(request) - Inherited from :class:`AbstractView`. + Inherited from :class:`~aiohttp.abc.AbstractView`. Base class for class based views. Implementations should derive from :class:`View` and override methods for handling HTTP verbs like @@ -2574,7 +2608,7 @@ application on specific TCP or Unix socket, e.g.:: A :class:`list` of served sockets addresses. - See :meth:`socket.getsockname` for items type. + See :meth:`socket.getsockname() ` for items type. .. versionadded:: 3.3 @@ -2638,6 +2672,10 @@ application on specific TCP or Unix socket, e.g.:: it means that the session global value is used. .. versionadded:: 3.7 + :param bool auto_decompress: Automatically decompress request body, + ``True`` by default. + + .. versionadded:: 3.8 .. attribute:: app @@ -2721,7 +2759,7 @@ application on specific TCP or Unix socket, e.g.:: :param int backlog: a number of unaccepted connections that the system will allow before refusing new - connections, see :meth:`socket.listen` for details. + connections, see :meth:`socket.socket.listen` for details. ``128`` by default. @@ -2756,7 +2794,7 @@ application on specific TCP or Unix socket, e.g.:: :param int backlog: a number of unaccepted connections that the system will allow before refusing new - connections, see :meth:`socket.listen` for details. + connections, see :meth:`socket.socket.listen` for details. ``128`` by default. @@ -2780,7 +2818,7 @@ application on specific TCP or Unix socket, e.g.:: :param runner: a runner to serve. - :param sock: :class:`socket.socket` to listen. + :param sock: A :ref:`socket instance ` to listen to. :param float shutdown_timeout: a timeout for closing opened connections on :meth:`BaseSite.stop` @@ -2792,7 +2830,7 @@ application on specific TCP or Unix socket, e.g.:: :param int backlog: a number of unaccepted connections that the system will allow before refusing new - connections, see :meth:`socket.listen` for details. + connections, see :meth:`socket.socket.listen` for details. ``128`` by default. @@ -2801,8 +2839,8 @@ Utilities .. class:: FileField - A :class:`~collections.namedtuple` instance that is returned as - multidict value by :meth:`Request.POST` if field is uploaded file. + A :mod:`dataclass ` instance that is returned as + multidict value by :meth:`aiohttp.web.BaseRequest.post` if field is uploaded file. .. attribute:: name @@ -2825,6 +2863,7 @@ Utilities .. function:: run_app(app, *, host=None, port=None, path=None, \ sock=None, shutdown_timeout=60.0, \ + keepalive_timeout=75.0, \ ssl_context=None, print=print, backlog=128, \ access_log_class=aiohttp.helpers.AccessLogger, \ access_log_format=aiohttp.helpers.AccessLogger.LOG_FORMAT, \ @@ -2833,13 +2872,15 @@ Utilities reuse_address=None, \ reuse_port=None) - A utility function for running an application, serving it until + A high-level function for running an application, serving it until keyboard interrupt and performing a :ref:`aiohttp-web-graceful-shutdown`. - Suitable as handy tool for scaffolding aiohttp based projects. - Perhaps production config will use more sophisticated runner but it - good enough at least at very beginning stage. + This is a high-level function very similar to :func:`asyncio.run` and + should be used as the main entry point for an application. The + :class:`Application` object essentially becomes our `main()` function. + If additional tasks need to be run in parallel, see + :ref:`aiohttp-web-complex-applications`. The server will listen on any host or Unix domain socket path you supply. If no hosts or paths are supplied, or only a port is supplied, a TCP server @@ -2866,7 +2907,7 @@ Utilities multiple domain sockets. Listening on Unix domain sockets is not supported by all operating systems. - :param socket sock: a preexisting socket object to accept connections on. + :param socket.socket sock: a preexisting socket object to accept connections on. A sequence of socket objects can be passed. :param int shutdown_timeout: a delay to wait for graceful server @@ -2879,6 +2920,12 @@ Utilities timeout but closes a server in a few milliseconds. + :param float keepalive_timeout: a delay before a TCP connection is + closed after a HTTP request. The delay + allows for reuse of a TCP connection. + + .. versionadded:: 3.8 + :param ssl_context: :class:`ssl.SSLContext` for HTTPS server, ``None`` for HTTP connection. diff --git a/docs/websocket_utilities.rst b/docs/websocket_utilities.rst index fca08e1..aa7de2c 100644 --- a/docs/websocket_utilities.rst +++ b/docs/websocket_utilities.rst @@ -42,8 +42,8 @@ WebSocket utilities received a message that violates its policy. This is a generic status code that can be returned when there is no other more suitable status code (e.g., - :attr:`~WSCloseCode.unsupported_data` or - :attr:`~WSCloseCode.message_too_big`) or if there is a need to + :attr:`~aiohttp.WSCloseCode.UNSUPPORTED_DATA` or + :attr:`~aiohttp.WSCloseCode.MESSAGE_TOO_BIG`) or if there is a need to hide specific details about the policy. .. attribute:: MESSAGE_TOO_BIG @@ -79,6 +79,18 @@ WebSocket utilities connect to a different IP (when there are multiple for the target) or reconnect to the same IP upon user action. + .. attribute:: ABNORMAL_CLOSURE + + Used to indicate that a connection was closed abnormally + (that is, with no close frame being sent) when a status code + is expected. + + .. attribute:: BAD_GATEWAY + + The server was acting as a gateway or proxy and received + an invalid response from the upstream server. + This is similar to 502 HTTP Status Code. + .. class:: WSMsgType diff --git a/docs/whats_new_1_1.rst b/docs/whats_new_1_1.rst index db71e10..7b5305e 100644 --- a/docs/whats_new_1_1.rst +++ b/docs/whats_new_1_1.rst @@ -20,8 +20,8 @@ e.g. ``session.get('http://example.com')`` works as well as Internal API has been switched to :class:`yarl.URL`. :class:`aiohttp.CookieJar` accepts :class:`~yarl.URL` instances only. -On server side has added :class:`web.Request.url` and -:class:`web.Request.rel_url` properties for representing relative and +On server side has added :attr:`aiohttp.web.BaseRequest.url` and +:attr:`aiohttp.web.BaseRequest.rel_url` properties for representing relative and absolute request's URL. URL using is the recommended way, already existed properties for @@ -32,7 +32,7 @@ parameter. :class:`str` is still supported and will be supported forever. Reverse URL processing for *router* has been changed. -The main API is :class:`aiohttp.web.Request.url_for(name, **kwargs)` +The main API is ``aiohttp.web.Request.url_for`` which returns a :class:`yarl.URL` instance for named resource. It does not support *query args* but adding *args* is trivial: ``request.url_for('named_resource', param='a').with_query(arg='val')``. diff --git a/examples/__init__.py b/examples/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/examples/background_tasks.py b/examples/background_tasks.py index 2a1ec12..8c2bb9e 100755 --- a/examples/background_tasks.py +++ b/examples/background_tasks.py @@ -43,8 +43,8 @@ async def listen_to_redis(app): print("Redis connection closed.") -async def start_background_tasks(app): - app["redis_listener"] = app.loop.create_task(listen_to_redis(app)) +async def start_background_tasks(app: web.Application) -> None: + app["redis_listener"] = asyncio.create_task(listen_to_redis(app)) async def cleanup_background_tasks(app): diff --git a/examples/client_json.py b/examples/client_json.py index e54edea..f571156 100755 --- a/examples/client_json.py +++ b/examples/client_json.py @@ -4,7 +4,7 @@ import aiohttp -async def fetch(session): +async def fetch(session: aiohttp.ClientSession) -> None: print("Query http://httpbin.org/get") async with session.get("http://httpbin.org/get") as resp: print(resp.status) diff --git a/examples/client_ws.py b/examples/client_ws.py index ec48ecc..38d8300 100755 --- a/examples/client_ws.py +++ b/examples/client_ws.py @@ -44,8 +44,9 @@ async def dispatch(): break # send request - async with aiohttp.ws_connect(url, autoclose=False, autoping=False) as ws: - await dispatch() + async with aiohttp.ClientSession() as session: + async with session.ws_connect(url, autoclose=False, autoping=False) as ws: + await dispatch() ARGS = argparse.ArgumentParser( diff --git a/examples/fake_server.py b/examples/fake_server.py index 007d96b..0006f5f 100755 --- a/examples/fake_server.py +++ b/examples/fake_server.py @@ -6,11 +6,12 @@ import aiohttp from aiohttp import web +from aiohttp.abc import AbstractResolver from aiohttp.resolver import DefaultResolver from aiohttp.test_utils import unused_port -class FakeResolver: +class FakeResolver(AbstractResolver): _LOCAL_HOST = {0: "127.0.0.1", socket.AF_INET: "127.0.0.1", socket.AF_INET6: "::1"} def __init__(self, fakes, *, loop): @@ -34,6 +35,9 @@ async def resolve(self, host, port=0, family=socket.AF_INET): else: return await self._resolver.resolve(host, port, family) + async def close(self) -> None: + self._resolver.close() + class FakeFacebook: def __init__(self, *, loop): @@ -45,7 +49,7 @@ def __init__(self, *, loop): web.get("/v2.7/me/friends", self.on_my_friends), ] ) - self.runner = None + self.runner = web.AppRunner(self.app) here = pathlib.Path(__file__) ssl_cert = here.parent / "server.crt" ssl_key = here.parent / "server.key" diff --git a/examples/legacy/crawl.py b/examples/legacy/crawl.py deleted file mode 100755 index c8029b4..0000000 --- a/examples/legacy/crawl.py +++ /dev/null @@ -1,108 +0,0 @@ -#!/usr/bin/env python3 - -import asyncio -import logging -import re -import signal -import sys -import urllib.parse - -import aiohttp - - -class Crawler: - def __init__(self, rooturl, loop, maxtasks=100): - self.rooturl = rooturl - self.loop = loop - self.todo = set() - self.busy = set() - self.done = {} - self.tasks = set() - self.sem = asyncio.Semaphore(maxtasks, loop=loop) - - # connector stores cookies between requests and uses connection pool - self.session = aiohttp.ClientSession(loop=loop) - - async def run(self): - t = asyncio.ensure_future(self.addurls([(self.rooturl, "")]), loop=self.loop) - await asyncio.sleep(1, loop=self.loop) - while self.busy: - await asyncio.sleep(1, loop=self.loop) - - await t - await self.session.close() - self.loop.stop() - - async def addurls(self, urls): - for url, parenturl in urls: - url = urllib.parse.urljoin(parenturl, url) - url, frag = urllib.parse.urldefrag(url) - if ( - url.startswith(self.rooturl) - and url not in self.busy - and url not in self.done - and url not in self.todo - ): - self.todo.add(url) - await self.sem.acquire() - task = asyncio.ensure_future(self.process(url), loop=self.loop) - task.add_done_callback(lambda t: self.sem.release()) - task.add_done_callback(self.tasks.remove) - self.tasks.add(task) - - async def process(self, url): - print("processing:", url) - - self.todo.remove(url) - self.busy.add(url) - try: - resp = await self.session.get(url) - except Exception as exc: - print("...", url, "has error", repr(str(exc))) - self.done[url] = False - else: - if resp.status == 200 and ("text/html" in resp.headers.get("content-type")): - data = (await resp.read()).decode("utf-8", "replace") - urls = re.findall(r'(?i)href=["\']?([^\s"\'<>]+)', data) - asyncio.Task(self.addurls([(u, url) for u in urls])) - - resp.close() - self.done[url] = True - - self.busy.remove(url) - print( - len(self.done), - "completed tasks,", - len(self.tasks), - "still pending, todo", - len(self.todo), - ) - - -def main(): - loop = asyncio.get_event_loop() - - c = Crawler(sys.argv[1], loop) - asyncio.ensure_future(c.run(), loop=loop) - - try: - loop.add_signal_handler(signal.SIGINT, loop.stop) - except RuntimeError: - pass - loop.run_forever() - print("todo:", len(c.todo)) - print("busy:", len(c.busy)) - print("done:", len(c.done), "; ok:", sum(c.done.values())) - print("tasks:", len(c.tasks)) - - -if __name__ == "__main__": - if "--iocp" in sys.argv: - from asyncio import events, windows_events - - sys.argv.remove("--iocp") - logging.info("using iocp") - el = windows_events.ProactorEventLoop() - events.set_event_loop(el) - - main() diff --git a/examples/legacy/srv.py b/examples/legacy/srv.py deleted file mode 100755 index 628b6f3..0000000 --- a/examples/legacy/srv.py +++ /dev/null @@ -1,178 +0,0 @@ -#!/usr/bin/env python3 -"""Simple server written using an event loop.""" - -import argparse -import asyncio -import logging -import os -import sys - -import aiohttp -import aiohttp.server - -try: - import ssl -except ImportError: # pragma: no cover - ssl = None - - -class HttpRequestHandler(aiohttp.server.ServerHttpProtocol): - async def handle_request(self, message, payload): - print( - "method = {!r}; path = {!r}; version = {!r}".format( - message.method, message.path, message.version - ) - ) - - path = message.path - - if not (path.isprintable() and path.startswith("/")) or "/." in path: - print("bad path", repr(path)) - path = None - else: - path = "." + path - if not os.path.exists(path): - print("no file", repr(path)) - path = None - else: - isdir = os.path.isdir(path) - - if not path: - raise aiohttp.HttpProcessingError(code=404) - - for hdr, val in message.headers.items(): - print(hdr, val) - - if isdir and not path.endswith("/"): - path = path + "/" - raise aiohttp.HttpProcessingError( - code=302, headers=(("URI", path), ("Location", path)) - ) - - response = aiohttp.Response(self.writer, 200, http_version=message.version) - response.add_header("Transfer-Encoding", "chunked") - - # content encoding - accept_encoding = message.headers.get("accept-encoding", "").lower() - if "deflate" in accept_encoding: - response.add_header("Content-Encoding", "deflate") - response.add_compression_filter("deflate") - elif "gzip" in accept_encoding: - response.add_header("Content-Encoding", "gzip") - response.add_compression_filter("gzip") - - response.add_chunking_filter(1025) - - if isdir: - response.add_header("Content-type", "text/html") - response.send_headers() - - response.write(b"
    \r\n") - for name in sorted(os.listdir(path)): - if name.isprintable() and not name.startswith("."): - try: - bname = name.encode("ascii") - except UnicodeError: - pass - else: - if os.path.isdir(os.path.join(path, name)): - response.write( - b'
  • ' - + bname - + b"/
  • \r\n" - ) - else: - response.write( - b'
  • ' - + bname - + b"
  • \r\n" - ) - response.write(b"
") - else: - response.add_header("Content-type", "text/plain") - response.send_headers() - - try: - with open(path, "rb") as fp: - chunk = fp.read(8192) - while chunk: - response.write(chunk) - chunk = fp.read(8192) - except OSError: - response.write(b"Cannot open") - - await response.write_eof() - if response.keep_alive(): - self.keep_alive(True) - - -ARGS = argparse.ArgumentParser(description="Run simple HTTP server.") -ARGS.add_argument( - "--host", action="store", dest="host", default="127.0.0.1", help="Host name" -) -ARGS.add_argument( - "--port", action="store", dest="port", default=8080, type=int, help="Port number" -) -# make iocp and ssl mutually exclusive because ProactorEventLoop is -# incompatible with SSL -group = ARGS.add_mutually_exclusive_group() -group.add_argument( - "--iocp", action="store_true", dest="iocp", help="Windows IOCP event loop" -) -group.add_argument("--ssl", action="store_true", dest="ssl", help="Run ssl mode.") -ARGS.add_argument("--sslcert", action="store", dest="certfile", help="SSL cert file.") -ARGS.add_argument("--sslkey", action="store", dest="keyfile", help="SSL key file.") - - -def main(): - args = ARGS.parse_args() - - if ":" in args.host: - args.host, port = args.host.split(":", 1) - args.port = int(port) - - if args.iocp: - from asyncio import windows_events - - sys.argv.remove("--iocp") - logging.info("using iocp") - el = windows_events.ProactorEventLoop() - asyncio.set_event_loop(el) - - if args.ssl: - here = os.path.join(os.path.dirname(__file__), "tests") - - if args.certfile: - certfile = args.certfile or os.path.join(here, "sample.crt") - keyfile = args.keyfile or os.path.join(here, "sample.key") - else: - certfile = os.path.join(here, "sample.crt") - keyfile = os.path.join(here, "sample.key") - - sslcontext = ssl.SSLContext(ssl.PROTOCOL_SSLv23) - sslcontext.load_cert_chain(certfile, keyfile) - else: - sslcontext = None - - loop = asyncio.get_event_loop() - f = loop.create_server( - lambda: HttpRequestHandler(debug=True, keep_alive=75), - args.host, - args.port, - ssl=sslcontext, - ) - svr = loop.run_until_complete(f) - socks = svr.sockets - print("serving on", socks[0].getsockname()) - try: - loop.run_forever() - except KeyboardInterrupt: - pass - - -if __name__ == "__main__": - main() diff --git a/examples/legacy/tcp_protocol_parser.py b/examples/legacy/tcp_protocol_parser.py deleted file mode 100755 index ca49db7..0000000 --- a/examples/legacy/tcp_protocol_parser.py +++ /dev/null @@ -1,172 +0,0 @@ -#!/usr/bin/env python3 -"""Protocol parser example.""" -import argparse -import asyncio -import collections - -import aiohttp - -try: - import signal -except ImportError: - signal = None - - -MSG_TEXT = b"text:" -MSG_PING = b"ping:" -MSG_PONG = b"pong:" -MSG_STOP = b"stop:" - -Message = collections.namedtuple("Message", ("tp", "data")) - - -def my_protocol_parser(out, buf): - """Parser is used with StreamParser for incremental protocol parsing. - Parser is a generator function, but it is not a coroutine. Usually - parsers are implemented as a state machine. - - more details in asyncio/parsers.py - existing parsers: - * HTTP protocol parsers asyncio/http/protocol.py - * websocket parser asyncio/http/websocket.py - """ - while True: - tp = yield from buf.read(5) - if tp in (MSG_PING, MSG_PONG): - # skip line - yield from buf.skipuntil(b"\r\n") - out.feed_data(Message(tp, None)) - elif tp == MSG_STOP: - out.feed_data(Message(tp, None)) - elif tp == MSG_TEXT: - # read text - text = yield from buf.readuntil(b"\r\n") - out.feed_data(Message(tp, text.strip().decode("utf-8"))) - else: - raise ValueError("Unknown protocol prefix.") - - -class MyProtocolWriter: - def __init__(self, transport): - self.transport = transport - - def ping(self): - self.transport.write(b"ping:\r\n") - - def pong(self): - self.transport.write(b"pong:\r\n") - - def stop(self): - self.transport.write(b"stop:\r\n") - - def send_text(self, text): - self.transport.write(f"text:{text.strip()}\r\n".encode("utf-8")) - - -class EchoServer(asyncio.Protocol): - def connection_made(self, transport): - print("Connection made") - self.transport = transport - self.stream = aiohttp.StreamParser() - asyncio.Task(self.dispatch()) - - def data_received(self, data): - self.stream.feed_data(data) - - def eof_received(self): - self.stream.feed_eof() - - def connection_lost(self, exc): - print("Connection lost") - - async def dispatch(self): - reader = self.stream.set_parser(my_protocol_parser) - writer = MyProtocolWriter(self.transport) - - while True: - try: - msg = await reader.read() - except aiohttp.ConnectionError: - # client has been disconnected - break - - print(f"Message received: {msg}") - - if msg.type == MSG_PING: - writer.pong() - elif msg.type == MSG_TEXT: - writer.send_text("Re: " + msg.data) - elif msg.type == MSG_STOP: - self.transport.close() - break - - -async def start_client(loop, host, port): - transport, stream = await loop.create_connection(aiohttp.StreamProtocol, host, port) - reader = stream.reader.set_parser(my_protocol_parser) - writer = MyProtocolWriter(transport) - writer.ping() - - message = "This is the message. It will be echoed." - - while True: - try: - msg = await reader.read() - except aiohttp.ConnectionError: - print("Server has been disconnected.") - break - - print(f"Message received: {msg}") - if msg.type == MSG_PONG: - writer.send_text(message) - print("data sent:", message) - elif msg.type == MSG_TEXT: - writer.stop() - print("stop sent") - break - - transport.close() - - -def start_server(loop, host, port): - f = loop.create_server(EchoServer, host, port) - srv = loop.run_until_complete(f) - x = srv.sockets[0] - print("serving on", x.getsockname()) - loop.run_forever() - - -ARGS = argparse.ArgumentParser(description="Protocol parser example.") -ARGS.add_argument( - "--server", action="store_true", dest="server", default=False, help="Run tcp server" -) -ARGS.add_argument( - "--client", action="store_true", dest="client", default=False, help="Run tcp client" -) -ARGS.add_argument( - "--host", action="store", dest="host", default="127.0.0.1", help="Host name" -) -ARGS.add_argument( - "--port", action="store", dest="port", default=9999, type=int, help="Port number" -) - - -if __name__ == "__main__": - args = ARGS.parse_args() - - if ":" in args.host: - args.host, port = args.host.split(":", 1) - args.port = int(port) - - if (not (args.server or args.client)) or (args.server and args.client): - print("Please specify --server or --client\n") - ARGS.print_help() - else: - loop = asyncio.get_event_loop() - if signal is not None: - loop.add_signal_handler(signal.SIGINT, loop.stop) - - if args.server: - start_server(loop, args.host, args.port) - else: - loop.run_until_complete(start_client(loop, args.host, args.port)) diff --git a/examples/web_classview.py b/examples/web_classview.py index 0f65f7d..1f1afda 100755 --- a/examples/web_classview.py +++ b/examples/web_classview.py @@ -1,6 +1,5 @@ #!/usr/bin/env python3 -"""Example for aiohttp.web class based views -""" +"""Example for aiohttp.web class based views.""" import functools @@ -14,7 +13,7 @@ async def get(self): return web.json_response( { "method": "get", - "args": dict(self.request.GET), + "args": dict(self.request.query), "headers": dict(self.request.headers), }, dumps=functools.partial(json.dumps, indent=4), @@ -25,7 +24,7 @@ async def post(self): return web.json_response( { "method": "post", - "args": dict(self.request.GET), + "args": dict(self.request.query), "data": dict(data), "headers": dict(self.request.headers), }, diff --git a/examples/web_cookies.py b/examples/web_cookies.py index e7a4a59..c028d19 100755 --- a/examples/web_cookies.py +++ b/examples/web_cookies.py @@ -1,8 +1,8 @@ #!/usr/bin/env python3 -"""Example for aiohttp.web basic server with cookies. -""" +"""Example for aiohttp.web basic server with cookies.""" from pprint import pformat +from typing import NoReturn from aiohttp import web @@ -22,20 +22,20 @@ async def root(request): return resp -async def login(request): - resp = web.HTTPFound(location="/") - resp.set_cookie("AUTH", "secret") - return resp +async def login(request: web.Request) -> NoReturn: + exc = web.HTTPFound(location="/") + exc.set_cookie("AUTH", "secret") + raise exc -async def logout(request): - resp = web.HTTPFound(location="/") - resp.del_cookie("AUTH") - return resp +async def logout(request: web.Request) -> NoReturn: + exc = web.HTTPFound(location="/") + exc.del_cookie("AUTH") + raise exc -def init(loop): - app = web.Application(loop=loop) +def init(): + app = web.Application() app.router.add_get("/", root) app.router.add_get("/login", login) app.router.add_get("/logout", logout) diff --git a/examples/web_rewrite_headers_middleware.py b/examples/web_rewrite_headers_middleware.py index 20799a3..15e985e 100755 --- a/examples/web_rewrite_headers_middleware.py +++ b/examples/web_rewrite_headers_middleware.py @@ -1,9 +1,8 @@ #!/usr/bin/env python3 -""" -Example for rewriting response headers by middleware. -""" +"""Example for rewriting response headers by middleware.""" from aiohttp import web +from aiohttp.typedefs import Handler async def handler(request): @@ -11,7 +10,7 @@ async def handler(request): @web.middleware -async def middleware(request, handler): +async def middleware(request: web.Request, handler: Handler) -> web.StreamResponse: try: response = await handler(request) except web.HTTPException as exc: diff --git a/examples/web_srv.py b/examples/web_srv.py index b572326..4d0e7c4 100755 --- a/examples/web_srv.py +++ b/examples/web_srv.py @@ -1,6 +1,5 @@ #!/usr/bin/env python3 -"""Example for aiohttp.web basic server -""" +"""Example for aiohttp.web basic server.""" import textwrap diff --git a/examples/web_srv_route_deco.py b/examples/web_srv_route_deco.py index 3329903..4e1769d 100644 --- a/examples/web_srv_route_deco.py +++ b/examples/web_srv_route_deco.py @@ -1,7 +1,5 @@ #!/usr/bin/env python3 -"""Example for aiohttp.web basic server -with decorator definition for routes -""" +"""Example for aiohttp.web basic server with decorator definition for routes.""" import textwrap diff --git a/examples/web_srv_route_table.py b/examples/web_srv_route_table.py index f53142a..24815b2 100644 --- a/examples/web_srv_route_table.py +++ b/examples/web_srv_route_table.py @@ -1,7 +1,5 @@ #!/usr/bin/env python3 -"""Example for aiohttp.web basic server -with table definition for routes -""" +"""Example for aiohttp.web basic server with table definition for routes.""" import textwrap diff --git a/examples/web_ws.py b/examples/web_ws.py index 970f150..f6c0593 100755 --- a/examples/web_ws.py +++ b/examples/web_ws.py @@ -1,6 +1,5 @@ #!/usr/bin/env python3 -"""Example for aiohttp.web websocket server -""" +"""Example for aiohttp.web websocket server.""" import os diff --git a/pyproject.toml b/pyproject.toml index e666dfc..262623f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,3 +1,9 @@ +[build-system] +requires = [ + "setuptools >= 46.4.0", +] +build-backend = "setuptools.build_meta" + [tool.towncrier] package = "aiohttp" filename = "CHANGES.rst" @@ -5,3 +11,9 @@ directory = "CHANGES/" title_format = "{version} ({project_date})" template = "CHANGES/.TEMPLATE.rst" issue_format = "`#{issue} `_" + + +[tool.cibuildwheel] +test-command = "" +# don't build PyPy wheels, install from source instead +skip = "pp*" diff --git a/setup.cfg b/setup.cfg index 2f528bc..6f6289b 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,8 +1,81 @@ -[aliases] -test = pytest - [metadata] -license_file = LICENSE.txt +name = aiohttp +version = attr: aiohttp.__version__ +url = https://github.com/aio-libs/aiohttp +project_urls = + Chat: Matrix = https://matrix.to/#/#aio-libs:matrix.org + Chat: Matrix Space = https://matrix.to/#/#aio-libs-space:matrix.org + CI: GitHub Actions = https://github.com/aio-libs/aiohttp/actions?query=workflow%%3ACI + Coverage: codecov = https://codecov.io/github/aio-libs/aiohttp + Docs: Changelog = https://docs.aiohttp.org/en/stable/changes.html + Docs: RTD = https://docs.aiohttp.org + GitHub: issues = https://github.com/aio-libs/aiohttp/issues + GitHub: repo = https://github.com/aio-libs/aiohttp +description = Async http client/server framework (asyncio) +long_description = file: README.rst +long_description_content_type = text/x-rst +maintainer = aiohttp team +maintainer_email = team@aiohttp.org +license = Apache 2 +license_files = LICENSE.txt +classifiers = + Development Status :: 5 - Production/Stable + + Framework :: AsyncIO + + Intended Audience :: Developers + + License :: OSI Approved :: Apache Software License + + Operating System :: POSIX + Operating System :: MacOS :: MacOS X + Operating System :: Microsoft :: Windows + + Programming Language :: Python + Programming Language :: Python :: 3 + Programming Language :: Python :: 3.6 + Programming Language :: Python :: 3.7 + Programming Language :: Python :: 3.8 + Programming Language :: Python :: 3.9 + Programming Language :: Python :: 3.10 + + Topic :: Internet :: WWW/HTTP + +[options] +python_requires = >=3.6 +packages = find: +zip_safe = False +include_package_data = True +install_requires = + attrs >= 17.3.0 + charset-normalizer >=2.0, < 4.0 + multidict >=4.5, < 7.0 + async_timeout >= 4.0.0a3, < 5.0 + asynctest == 0.13.0; python_version<"3.8" + yarl >= 1.0, < 2.0 + idna-ssl >= 1.0; python_version<"3.7" + typing_extensions >= 3.7.4; python_version<"3.8" + frozenlist >= 1.1.1 + aiosignal >= 1.1.2 + +[options.exclude_package_data] +* = + *.c + *.h + +[options.extras_require] +speedups = + aiodns + Brotli + cchardet; python_version < "3.10" + +[options.packages.find] +exclude = + examples + +[options.package_data] +* = + *.so [pep8] max-line-length = 79 @@ -11,7 +84,7 @@ max-line-length = 79 zip_ok = false [flake8] -ignore = N801,N802,N803,E203,E226,E305,W504,E252,E301,E302,E704,W503,W504,F811 +ignore = N801,N802,N803,E203,E226,E305,W504,E252,E301,E302,E704,W503,W504,F811,D1,D4 max-line-length = 88 [isort] @@ -34,58 +107,38 @@ source = aiohttp, tests omit = site-packages [tool:pytest] -addopts = --cov=aiohttp -v -rxXs --durations 10 +addopts = + --durations=10 + + -v + + -ra + + --showlocals + + --cov=aiohttp + --cov=tests/ + + -m "not dev_mode" filterwarnings = error ignore:module 'ssl' has no attribute 'OP_NO_COMPRESSION'. The Python interpreter is compiled against OpenSSL < 1.0.0. Ref. https.//docs.python.org/3/library/ssl.html#ssl.OP_NO_COMPRESSION:UserWarning + ignore:unclosed transport :ResourceWarning + ignore:Unclosed client session =17.3.0", - "chardet>=2.0,<4.0", - "multidict>=4.5,<7.0", - "async_timeout>=3.0,<4.0", - "yarl>=1.0,<2.0", - 'idna-ssl>=1.0; python_version<"3.7"', - "typing_extensions>=3.6.5", -] - - -def read(f): - return (here / f).read_text("utf-8").strip() - - -NEEDS_PYTEST = {"pytest", "test"}.intersection(sys.argv) -pytest_runner = ["pytest-runner"] if NEEDS_PYTEST else [] - -tests_require = [ - "pytest", - "gunicorn", - "pytest-timeout", - "async-generator", - "pytest-xdist", -] - - -args = dict( - name="aiohttp", - version=version, - description="Async http client/server framework (asyncio)", - long_description="\n\n".join((read("README.rst"), read("CHANGES.rst"))), - classifiers=[ - "License :: OSI Approved :: Apache Software License", - "Intended Audience :: Developers", - "Programming Language :: Python", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.6", - "Programming Language :: Python :: 3.7", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", - "Development Status :: 5 - Production/Stable", - "Operating System :: POSIX", - "Operating System :: MacOS :: MacOS X", - "Operating System :: Microsoft :: Windows", - "Topic :: Internet :: WWW/HTTP", - "Framework :: AsyncIO", - ], - author="Nikolay Kim", - author_email="fafhrd91@gmail.com", - maintainer=", ".join( - ( - "Nikolay Kim ", - "Andrew Svetlov ", - ) - ), - maintainer_email="aio-libs@googlegroups.com", - url="https://github.com/aio-libs/aiohttp", - project_urls={ - "Chat: Gitter": "https://gitter.im/aio-libs/Lobby", - "CI: Azure Pipelines": "https://dev.azure.com/aio-libs/aiohttp/_build", - "Coverage: codecov": "https://codecov.io/github/aio-libs/aiohttp", - "Docs: RTD": "https://docs.aiohttp.org", - "GitHub: issues": "https://github.com/aio-libs/aiohttp/issues", - "GitHub: repo": "https://github.com/aio-libs/aiohttp", - }, - license="Apache 2", - packages=["aiohttp"], - python_requires=">=3.6", - install_requires=install_requires, - extras_require={ - "speedups": [ - "aiodns", - "brotlipy", - "cchardet", - ], - }, - tests_require=tests_require, - setup_requires=pytest_runner, - include_package_data=True, - ext_modules=extensions, - cmdclass=dict(build_ext=ve_build_ext), -) +build_type = "Pure" if NO_EXTENSIONS else "Accelerated" +setup_kwargs = {} if NO_EXTENSIONS else {"ext_modules": extensions} -try: - setup(**args) -except BuildFailed: - print("************************************************************") - print("Cannot compile C accelerator module, use pure python version") - print("************************************************************") - del args["ext_modules"] - del args["cmdclass"] - setup(**args) +print("*********************", file=sys.stderr) +print("* {build_type} build *".format_map(locals()), file=sys.stderr) +print("*********************", file=sys.stderr) +setup(**setup_kwargs) diff --git a/tests/autobahn/Dockerfile.aiohttp b/tests/autobahn/Dockerfile.aiohttp new file mode 100644 index 0000000..2d37683 --- /dev/null +++ b/tests/autobahn/Dockerfile.aiohttp @@ -0,0 +1,7 @@ +FROM python:3.9.5 + +COPY ./ /src + +WORKDIR /src + +RUN pip install . diff --git a/tests/autobahn/Dockerfile.autobahn b/tests/autobahn/Dockerfile.autobahn new file mode 100644 index 0000000..45f1818 --- /dev/null +++ b/tests/autobahn/Dockerfile.autobahn @@ -0,0 +1,6 @@ +FROM crossbario/autobahn-testsuite:0.8.2 + +RUN apt-get update && apt-get install python3 python3-pip -y +RUN pip3 install wait-for-it + +CMD ["wstest", "--mode", "fuzzingserver", "--spec", "/config/fuzzingserver.json"] diff --git a/tests/autobahn/client.py b/tests/autobahn/client.py deleted file mode 100644 index 513a4ee..0000000 --- a/tests/autobahn/client.py +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/env python3 - -import asyncio - -import aiohttp - - -async def client(loop, url, name): - ws = await aiohttp.ws_connect(url + "/getCaseCount") - num_tests = int((await ws.receive()).data) - print("running %d cases" % num_tests) - await ws.close() - - for i in range(1, num_tests + 1): - print("running test case:", i) - text_url = url + "/runCase?case=%d&agent=%s" % (i, name) - ws = await aiohttp.ws_connect(text_url) - while True: - msg = await ws.receive() - - if msg.type == aiohttp.WSMsgType.text: - await ws.send_str(msg.data) - elif msg.type == aiohttp.WSMsgType.binary: - await ws.send_bytes(msg.data) - elif msg.type == aiohttp.WSMsgType.close: - await ws.close() - break - else: - break - - url = url + "/updateReports?agent=%s" % name - ws = await aiohttp.ws_connect(url) - await ws.close() - - -async def run(loop, url, name): - try: - await client(loop, url, name) - except Exception: - import traceback - - traceback.print_exc() - - -if __name__ == "__main__": - loop = asyncio.get_event_loop() - try: - loop.run_until_complete(run(loop, "http://localhost:9001", "aiohttp")) - except KeyboardInterrupt: - pass - finally: - loop.close() diff --git a/tests/autobahn/client/client.py b/tests/autobahn/client/client.py new file mode 100644 index 0000000..dfca77d --- /dev/null +++ b/tests/autobahn/client/client.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python3 + +import asyncio + +import aiohttp + + +async def client(url: str, name: str) -> None: + async with aiohttp.ClientSession() as session: + async with session.ws_connect(url + "/getCaseCount") as ws: + num_tests = int((await ws.receive()).data) + print("running %d cases" % num_tests) + + for i in range(1, num_tests + 1): + print("running test case:", i) + text_url = url + "/runCase?case=%d&agent=%s" % (i, name) + async with session.ws_connect(text_url) as ws: + async for msg in ws: + if msg.type == aiohttp.WSMsgType.TEXT: + await ws.send_str(msg.data) + elif msg.type == aiohttp.WSMsgType.BINARY: + await ws.send_bytes(msg.data) + else: + break + + url = url + "/updateReports?agent=%s" % name + async with session.ws_connect(url) as ws: + print("finally requesting %s" % url) + + +async def run(url: str, name: str) -> None: + try: + await client(url, name) + except Exception: + import traceback + + traceback.print_exc() + + +if __name__ == "__main__": + asyncio.run(run("http://localhost:9001", "aiohttp")) diff --git a/tests/autobahn/fuzzingserver.json b/tests/autobahn/client/fuzzingserver.json similarity index 100% rename from tests/autobahn/fuzzingserver.json rename to tests/autobahn/client/fuzzingserver.json diff --git a/tests/autobahn/fuzzingclient.json b/tests/autobahn/fuzzingclient.json deleted file mode 100644 index 31c39d2..0000000 --- a/tests/autobahn/fuzzingclient.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "options": {"failByDrop": false}, - "outdir": "./reports/servers", - - "servers": [{"agent": "AutobahnServer", "url": "ws://localhost:9001", "options": {"version": 18}}], - - "cases": ["*"], - "exclude-cases": ["12.*", "13.*"], - "exclude-agent-cases": {} -} diff --git a/tests/autobahn/server.py b/tests/autobahn/server.py deleted file mode 100644 index 3d39d6c..0000000 --- a/tests/autobahn/server.py +++ /dev/null @@ -1,58 +0,0 @@ -#!/usr/bin/env python3 - -import asyncio -import logging - -from aiohttp import web - - -async def wshandler(request): - ws = web.WebSocketResponse(autoclose=False) - is_ws = ws.can_prepare(request) - if not is_ws: - return web.HTTPBadRequest() - - await ws.prepare(request) - - while True: - msg = await ws.receive() - - if msg.type == web.WSMsgType.text: - await ws.send_str(msg.data) - elif msg.type == web.WSMsgType.binary: - await ws.send_bytes(msg.data) - elif msg.type == web.WSMsgType.close: - await ws.close() - break - else: - break - - return ws - - -async def main(loop): - app = web.Application() - app.router.add_route("GET", "/", wshandler) - - handler = app._make_handler() - srv = await loop.create_server(handler, "127.0.0.1", 9001) - print("Server started at http://127.0.0.1:9001") - return app, srv, handler - - -async def finish(app, srv, handler): - srv.close() - await handler.shutdown() - await srv.wait_closed() - - -if __name__ == "__main__": - loop = asyncio.get_event_loop() - logging.basicConfig( - level=logging.DEBUG, format="%(asctime)s %(levelname)s %(message)s" - ) - app, srv, handler = loop.run_until_complete(main(loop)) - try: - loop.run_forever() - except KeyboardInterrupt: - loop.run_until_complete(finish(app, srv, handler)) diff --git a/tests/autobahn/server/fuzzingclient.json b/tests/autobahn/server/fuzzingclient.json new file mode 100644 index 0000000..0ed2f84 --- /dev/null +++ b/tests/autobahn/server/fuzzingclient.json @@ -0,0 +1,16 @@ +{ + "options": { "failByDrop": false }, + "outdir": "./reports/servers", + + "servers": [ + { + "agent": "AutobahnServer", + "url": "ws://localhost:9001", + "options": { "version": 18 } + } + ], + + "cases": ["*"], + "exclude-cases": ["12.*", "13.*"], + "exclude-agent-cases": {} +} diff --git a/tests/autobahn/server/server.py b/tests/autobahn/server/server.py new file mode 100644 index 0000000..c0e5025 --- /dev/null +++ b/tests/autobahn/server/server.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python3 + +import logging + +from aiohttp import WSCloseCode, web + + +async def wshandler(request: web.Request) -> web.WebSocketResponse: + ws = web.WebSocketResponse(autoclose=False) + is_ws = ws.can_prepare(request) + if not is_ws: + raise web.HTTPBadRequest() + + await ws.prepare(request) + + request.app["websockets"].append(ws) + + while True: + msg = await ws.receive() + + if msg.type == web.WSMsgType.TEXT: + await ws.send_str(msg.data) + elif msg.type == web.WSMsgType.BINARY: + await ws.send_bytes(msg.data) + elif msg.type == web.WSMsgType.CLOSE: + await ws.close() + break + else: + break + + return ws + + +async def on_shutdown(app: web.Application) -> None: + for ws in set(app["websockets"]): + await ws.close(code=WSCloseCode.GOING_AWAY, message="Server shutdown") + + +if __name__ == "__main__": + logging.basicConfig( + level=logging.DEBUG, format="%(asctime)s %(levelname)s %(message)s" + ) + + app = web.Application() + app["websockets"] = [] + app.router.add_route("GET", "/", wshandler) + app.on_shutdown.append(on_shutdown) + try: + web.run_app(app, port=9001) + except KeyboardInterrupt: + print("Server stopped at http://127.0.0.1:9001") diff --git a/tests/autobahn/test_autobahn.py b/tests/autobahn/test_autobahn.py new file mode 100644 index 0000000..76cc54e --- /dev/null +++ b/tests/autobahn/test_autobahn.py @@ -0,0 +1,136 @@ +import json +import subprocess +import sys +from pathlib import Path +from typing import Any, Dict, Generator, List + +import pytest +from pytest import TempPathFactory + +python_on_whales = pytest.importorskip( + "python_on_whales", + reason="'python-on-whales' requires Python 3.7+", +) + + +@pytest.fixture(scope="session") +def report_dir(tmp_path_factory: TempPathFactory) -> Path: + return tmp_path_factory.mktemp("reports") + + +@pytest.fixture(scope="session", autouse=True) +def build_autobahn_testsuite() -> Generator[None, None, None]: + + try: + python_on_whales.docker.build( + file="tests/autobahn/Dockerfile.autobahn", + tags=["autobahn-testsuite"], + context_path=".", + ) + except python_on_whales.DockerException: + pytest.skip(msg="The docker daemon is not running.") + + try: + yield + finally: + python_on_whales.docker.image.remove(x="autobahn-testsuite") + + +def get_failed_tests(report_path: str, name: str) -> List[Dict[str, Any]]: + path = Path(report_path) + result_summary = json.loads((path / "index.json").read_text())[name] + failed_messages = [] + PASS = {"OK", "INFORMATIONAL"} + entry_fields = {"case", "description", "expectation", "expected", "received"} + for results in result_summary.values(): + if results["behavior"] in PASS and results["behaviorClose"] in PASS: + continue + report = json.loads((path / results["reportfile"]).read_text()) + failed_messages.append({field: report[field] for field in entry_fields}) + return failed_messages + + +@pytest.mark.skipif(sys.platform == "darwin", reason="Don't run on macOS") +@pytest.mark.xfail +def test_client(report_dir: Path, request: Any) -> None: + try: + print("Starting autobahn-testsuite server") + autobahn_container = python_on_whales.docker.run( + detach=True, + image="autobahn-testsuite", + name="autobahn", + publish=[(9001, 9001)], + remove=True, + volumes=[ + (f"{request.fspath.dirname}/client", "/config"), + (f"{report_dir}", "/reports"), + ], + ) + print("Running aiohttp test client") + client = subprocess.Popen( + ["wait-for-it", "-s", "localhost:9001", "--"] + + [sys.executable] + + ["tests/autobahn/client/client.py"] + ) + client.wait() + finally: + print("Stopping client and server") + client.terminate() + client.wait() + autobahn_container.stop() + + failed_messages = get_failed_tests(f"{report_dir}/clients", "aiohttp") + + assert not failed_messages, "\n".join( + "\n\t".join( + f"{field}: {msg[field]}" + for field in ("case", "description", "expectation", "expected", "received") + ) + for msg in failed_messages + ) + + +@pytest.mark.skipif(sys.platform == "darwin", reason="Don't run on macOS") +@pytest.mark.xfail +def test_server(report_dir: Path, request: Any) -> None: + try: + print("Starting aiohttp test server") + server = subprocess.Popen( + [sys.executable] + ["tests/autobahn/server/server.py"] + ) + print("Starting autobahn-testsuite client") + python_on_whales.docker.run( + image="autobahn-testsuite", + name="autobahn", + remove=True, + volumes=[ + (f"{request.fspath.dirname}/server", "/config"), + (f"{report_dir}", "/reports"), + ], + networks=["host"], + command=[ + "wait-for-it", + "-s", + "localhost:9001", + "--", + "wstest", + "--mode", + "fuzzingclient", + "--spec", + "/config/fuzzingclient.json", + ], + ) + finally: + print("Stopping client and server") + server.terminate() + server.wait() + + failed_messages = get_failed_tests(f"{report_dir}/servers", "AutobahnServer") + + assert not failed_messages, "\n".join( + "\n\t".join( + f"{field}: {msg[field]}" + for field in ("case", "description", "expectation", "expected", "received") + ) + for msg in failed_messages + ) diff --git a/tests/conftest.py b/tests/conftest.py index 09cbf6c..e33a99d 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,11 +1,12 @@ import asyncio -import hashlib -import pathlib -import shutil +import os +import socket import ssl import sys -import tempfile -import uuid +from hashlib import md5, sha256 +from pathlib import Path +from tempfile import TemporaryDirectory +from uuid import uuid4 import pytest @@ -14,35 +15,36 @@ try: import trustme - TRUSTME = True + # Check if the CA is available in runtime, MacOS on Py3.10 fails somehow + trustme.CA() + + TRUSTME: bool = True except ImportError: TRUSTME = False pytest_plugins = ["aiohttp.pytest_plugin", "pytester"] -@pytest.fixture -def shorttmpdir(): - """Provides a temporary directory with a shorter file system path than the - tmpdir fixture. - """ - tmpdir = pathlib.Path(tempfile.mkdtemp()) - yield tmpdir - # str(tmpdir) is required, Python 3.5 doesn't have __fspath__ - # concept - shutil.rmtree(str(tmpdir), ignore_errors=True) +IS_HPUX = sys.platform.startswith("hp-ux") +"""Specifies whether the current runtime is HP-UX.""" +IS_LINUX = sys.platform.startswith("linux") +"""Specifies whether the current runtime is HP-UX.""" +IS_UNIX = hasattr(socket, "AF_UNIX") +"""Specifies whether the current runtime is *NIX.""" + +needs_unix = pytest.mark.skipif(not IS_UNIX, reason="requires UNIX sockets") @pytest.fixture def tls_certificate_authority(): if not TRUSTME: - pytest.xfail("trustme fails on 32bit Linux") + pytest.xfail("trustme is not supported") return trustme.CA() @pytest.fixture def tls_certificate(tls_certificate_authority): - return tls_certificate_authority.issue_server_cert( + return tls_certificate_authority.issue_cert( "localhost", "127.0.0.1", "::1", @@ -51,7 +53,7 @@ def tls_certificate(tls_certificate_authority): @pytest.fixture def ssl_ctx(tls_certificate): - ssl_ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23) + ssl_ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) tls_certificate.configure_cert(ssl_ctx) return ssl_ctx @@ -83,12 +85,91 @@ def tls_certificate_pem_bytes(tls_certificate): @pytest.fixture def tls_certificate_fingerprint_sha256(tls_certificate_pem_bytes): tls_cert_der = ssl.PEM_cert_to_DER_cert(tls_certificate_pem_bytes.decode()) - return hashlib.sha256(tls_cert_der).digest() + return sha256(tls_cert_der).digest() + + +@pytest.fixture +def unix_sockname(tmp_path, tmp_path_factory): + """Generate an fs path to the UNIX domain socket for testing. + + N.B. Different OS kernels have different fs path length limitations + for it. For Linux, it's 108, for HP-UX it's 92 (or higher) depending + on its version. For for most of the BSDs (Open, Free, macOS) it's + mostly 104 but sometimes it can be down to 100. + + Ref: https://github.com/aio-libs/aiohttp/issues/3572 + """ + if not IS_UNIX: + pytest.skip("requires UNIX sockets") + + max_sock_len = 92 if IS_HPUX else 108 if IS_LINUX else 100 + """Amount of bytes allocated for the UNIX socket path by OS kernel. + + Ref: https://unix.stackexchange.com/a/367012/27133 + """ + + sock_file_name = "unix.sock" + unique_prefix = f"{uuid4()!s}-" + unique_prefix_len = len(unique_prefix.encode()) + + root_tmp_dir = Path("/tmp").resolve() + os_tmp_dir = Path(os.getenv("TMPDIR", "/tmp")).resolve() + original_base_tmp_path = Path( + str(tmp_path_factory.getbasetemp()), + ).resolve() + + original_base_tmp_path_hash = md5( + str(original_base_tmp_path).encode(), + ).hexdigest() + + def make_tmp_dir(base_tmp_dir): + return TemporaryDirectory( + dir=str(base_tmp_dir), + prefix="pt-", + suffix=f"-{original_base_tmp_path_hash!s}", + ) + + def assert_sock_fits(sock_path): + sock_path_len = len(sock_path.encode()) + # exit-check to verify that it's correct and simplify debugging + # in the future + assert sock_path_len <= max_sock_len, ( + "Suggested UNIX socket ({sock_path}) is {sock_path_len} bytes " + "long but the current kernel only has {max_sock_len} bytes " + "allocated to hold it so it must be shorter. " + "See https://github.com/aio-libs/aiohttp/issues/3572 " + "for more info." + ).format_map(locals()) + + paths = original_base_tmp_path, os_tmp_dir, root_tmp_dir + unique_paths = [p for n, p in enumerate(paths) if p not in paths[:n]] + paths_num = len(unique_paths) + + for num, tmp_dir_path in enumerate(paths, 1): + with make_tmp_dir(tmp_dir_path) as tmpd: + tmpd = Path(tmpd).resolve() + sock_path = str(tmpd / sock_file_name) + sock_path_len = len(sock_path.encode()) + + if num >= paths_num: + # exit-check to verify that it's correct and simplify + # debugging in the future + assert_sock_fits(sock_path) + + if sock_path_len <= max_sock_len: + if max_sock_len - sock_path_len >= unique_prefix_len: + # If we're lucky to have extra space in the path, + # let's also make it more unique + sock_path = str(tmpd / "".join((unique_prefix, sock_file_name))) + # Double-checking it: + assert_sock_fits(sock_path) + yield sock_path + return @pytest.fixture def pipe_name(): - name = fr"\\.\pipe\{uuid.uuid4().hex}" + name = rf"\\.\pipe\{uuid4().hex}" return name diff --git a/tests/sample.txt b/tests/sample.txt new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/tests/sample.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/tests/test___all__.py b/tests/test___all__.py new file mode 100644 index 0000000..6c7d855 --- /dev/null +++ b/tests/test___all__.py @@ -0,0 +1,22 @@ +from typing import Any + + +def test___all__(pytester: Any) -> None: + """See https://github.com/aio-libs/aiohttp/issues/6197""" + pytester.makepyfile( + test_a=""" + from aiohttp import * + """ + ) + result = pytester.runpytest("-vv") + result.assert_outcomes(passed=0, errors=0) + + +def test_web___all__(pytester: Any) -> None: + pytester.makepyfile( + test_b=""" + from aiohttp.web import * + """ + ) + result = pytester.runpytest("-vv") + result.assert_outcomes(passed=0, errors=0) diff --git a/tests/test_base_protocol.py b/tests/test_base_protocol.py index 531e55e..a16b1f1 100644 --- a/tests/test_base_protocol.py +++ b/tests/test_base_protocol.py @@ -45,10 +45,10 @@ async def test_connection_lost_not_paused() -> None: pr = BaseProtocol(loop=loop) tr = mock.Mock() pr.connection_made(tr) - assert not pr._connection_lost + assert pr.connected pr.connection_lost(None) assert pr.transport is None - assert pr._connection_lost + assert not pr.connected async def test_connection_lost_paused_without_waiter() -> None: @@ -56,11 +56,11 @@ async def test_connection_lost_paused_without_waiter() -> None: pr = BaseProtocol(loop=loop) tr = mock.Mock() pr.connection_made(tr) - assert not pr._connection_lost + assert pr.connected pr.pause_writing() pr.connection_lost(None) assert pr.transport is None - assert pr._connection_lost + assert not pr.connected async def test_drain_lost() -> None: @@ -180,3 +180,21 @@ async def wait(): with suppress(asyncio.CancelledError): await t assert pr._drain_waiter is None + + +async def test_parallel_drain_race_condition() -> None: + loop = asyncio.get_event_loop() + pr = BaseProtocol(loop=loop) + tr = mock.Mock() + pr.connection_made(tr) + pr.pause_writing() + + ts = [loop.create_task(pr._drain_helper()) for _ in range(5)] + assert not (await asyncio.wait(ts, timeout=0.5))[ + 0 + ], "All draining tasks must be pending" + + assert pr._drain_waiter is not None + pr.resume_writing() + await asyncio.gather(*ts) + assert pr._drain_waiter is None diff --git a/tests/test_circular_imports.py b/tests/test_circular_imports.py new file mode 100644 index 0000000..22e5ea4 --- /dev/null +++ b/tests/test_circular_imports.py @@ -0,0 +1,120 @@ +"""Tests for circular imports in all local packages and modules. + +This ensures all internal packages can be imported right away without +any need to import some other module before doing so. + +This module is based on an idea that pytest uses for self-testing: +* https://github.com/sanitizers/octomachinery/blob/be18b54/tests/circular_imports_test.py +* https://github.com/pytest-dev/pytest/blob/d18c75b/testing/test_meta.py +* https://twitter.com/codewithanthony/status/1229445110510735361 +""" # noqa: E501 +import os +import pkgutil +import subprocess +import sys +from itertools import chain +from pathlib import Path +from types import ModuleType +from typing import TYPE_CHECKING, Generator, List, Union + +import pytest + +if TYPE_CHECKING: + from _pytest.mark.structures import ParameterSet + +from conftest import IS_UNIX # type: ignore[attr-defined] + +import aiohttp + + +def _mark_aiohttp_worker_for_skipping( + importables: List[str], +) -> List[Union[str, "ParameterSet"]]: + return [ + pytest.param( + importable, + marks=pytest.mark.skipif(not IS_UNIX, reason="It's a UNIX-only module"), + ) + if importable == "aiohttp.worker" + else importable + for importable in importables + ] + + +def _find_all_importables(pkg: ModuleType) -> List[str]: + """Find all importables in the project. + + Return them in order. + """ + return sorted( + set( + chain.from_iterable( + _discover_path_importables(Path(p), pkg.__name__) + # FIXME: Unignore after upgrading to `mypy > 0.910`. The fix + # FIXME: is in the `master` branch of upstream since Aug 4, + # FIXME: 2021 but has not yet been included in any releases. + # Refs: + # * https://github.com/python/mypy/issues/1422 + # * https://github.com/python/mypy/pull/9454 + for p in pkg.__path__ # type: ignore[attr-defined] + ), + ), + ) + + +def _discover_path_importables( + pkg_pth: Path, + pkg_name: str, +) -> Generator[str, None, None]: + """Yield all importables under a given path and package.""" + for dir_path, _d, file_names in os.walk(pkg_pth): + pkg_dir_path = Path(dir_path) + + if pkg_dir_path.parts[-1] == "__pycache__": + continue + + if all(Path(_).suffix != ".py" for _ in file_names): + continue + + rel_pt = pkg_dir_path.relative_to(pkg_pth) + pkg_pref = ".".join((pkg_name,) + rel_pt.parts) + yield from ( + pkg_path + for _, pkg_path, _ in pkgutil.walk_packages( + (str(pkg_dir_path),), + prefix=f"{pkg_pref}.", + ) + ) + + +@pytest.mark.parametrize( + "import_path", + _mark_aiohttp_worker_for_skipping(_find_all_importables(aiohttp)), +) +def test_no_warnings(import_path: str) -> None: + """Verify that exploding importables doesn't explode. + + This is seeking for any import errors including ones caused + by circular imports. + """ + imp_cmd = ( + # fmt: off + sys.executable, + "-W", "error", + # The following deprecation warning is triggered by importing + # `gunicorn.util`. Hopefully, it'll get fixed in the future. See + # https://github.com/benoitc/gunicorn/issues/2840 for detail. + "-W", "ignore:module 'sre_constants' is " + "deprecated:DeprecationWarning:pkg_resources._vendor.pyparsing", + # The following deprecation warning is coming from an old + # version of `setuptools` (the last one to support Python 3.6). + # It is stepping on it's own toes. But since it doesn't + # originate in aiohttp, we don't care much about it. + "-W", + "ignore:Creating a LegacyVersion has been deprecated and will " + "be removed in the next major release:DeprecationWarning:", + "-c", f"import {import_path!s}", + # fmt: on + ) + + subprocess.check_call(imp_cmd) diff --git a/tests/test_client_fingerprint.py b/tests/test_client_fingerprint.py index 753a9f3..b1ae3ca 100644 --- a/tests/test_client_fingerprint.py +++ b/tests/test_client_fingerprint.py @@ -41,21 +41,21 @@ def test__merge_ssl_params_verify_ssl() -> None: def test__merge_ssl_params_verify_ssl_conflict() -> None: - ctx = ssl.SSLContext() + ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) with pytest.warns(DeprecationWarning): with pytest.raises(ValueError): _merge_ssl_params(ctx, False, None, None) def test__merge_ssl_params_ssl_context() -> None: - ctx = ssl.SSLContext() + ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) with pytest.warns(DeprecationWarning): assert _merge_ssl_params(None, None, ctx, None) is ctx def test__merge_ssl_params_ssl_context_conflict() -> None: - ctx1 = ssl.SSLContext() - ctx2 = ssl.SSLContext() + ctx1 = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) + ctx2 = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) with pytest.warns(DeprecationWarning): with pytest.raises(ValueError): _merge_ssl_params(ctx1, None, ctx2, None) @@ -70,14 +70,14 @@ def test__merge_ssl_params_fingerprint() -> None: def test__merge_ssl_params_fingerprint_conflict() -> None: fingerprint = aiohttp.Fingerprint(hashlib.sha256(b"123").digest()) - ctx = ssl.SSLContext() + ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) with pytest.warns(DeprecationWarning): with pytest.raises(ValueError): _merge_ssl_params(ctx, None, None, fingerprint) def test__merge_ssl_params_ssl() -> None: - ctx = ssl.SSLContext() + ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) assert ctx is _merge_ssl_params(ctx, None, None, None) diff --git a/tests/test_client_functional.py b/tests/test_client_functional.py index 6bd8d44..4f62b47 100644 --- a/tests/test_client_functional.py +++ b/tests/test_client_functional.py @@ -7,11 +7,12 @@ import json import pathlib import socket +import ssl from unittest import mock import pytest -from async_generator import async_generator, yield_ from multidict import MultiDict +from yarl import URL import aiohttp from aiohttp import Fingerprint, ServerFingerprintMismatch, hdrs, web @@ -234,7 +235,8 @@ async def handler(request): app.router.add_route("POST", "/", handler) client = await aiohttp_client(app) - resp = await client.post("/", data=io.BytesIO(data)) + with io.BytesIO(data) as file_handle: + resp = await client.post("/", data=file_handle) assert 200 == resp.status @@ -245,13 +247,15 @@ async def handler(request): post_data = await request.post() assert ["file"] == list(post_data.keys()) assert data == post_data["file"].file.read() + post_data["file"].file.close() # aiohttp < 4 doesn't autoclose files return web.Response() app = web.Application() app.router.add_route("POST", "/", handler) client = await aiohttp_client(app) - resp = await client.post("/", data={"file": io.BytesIO(data)}) + with io.BytesIO(data) as file_handle: + resp = await client.post("/", data={"file": file_handle}) assert 200 == resp.status @@ -992,7 +996,7 @@ async def handler(request): async def redirect(request): count = int(request.match_info["count"]) if count: - raise web.HTTPFound(location="/redirect/{}".format(count - 1)) + raise web.HTTPFound(location=f"/redirect/{count - 1}") else: raise web.HTTPFound(location="/") @@ -1236,6 +1240,8 @@ async def handler(request): content2 = data["some"].file.read() assert content1 == content2 assert data["test"].file.read() == b"data" + data["some"].file.close() + data["test"].file.close() return web.Response() app = web.Application() @@ -1255,6 +1261,7 @@ async def handler(request): with fname.open("rb") as f: content1 = f.read() content2 = data["some"].file.read() + data["some"].file.close() assert content1 == content2 return web.Response() @@ -1288,7 +1295,7 @@ async def handler(request): async def test_POST_bytes_too_large(aiohttp_client) -> None: - body = b"0" * (2 ** 20 + 1) + body = b"0" * (2**20 + 1) async def handler(request): data = await request.content.read() @@ -1350,6 +1357,7 @@ async def handler(request): with fname.open("rb") as f: content = f.read() assert content == data["some"].file.read() + data["some"].file.close() return web.Response() app = web.Application() @@ -1370,6 +1378,7 @@ async def handler(request): with fname.open("rb") as f: content = f.read() assert content == data["some"].file.read() + data["some"].file.close() return web.Response() app = web.Application() @@ -1425,7 +1434,7 @@ async def handler(request): "text/x-python", ] assert request.headers["content-disposition"] == ( - "inline; filename=\"conftest.py\"; filename*=utf-8''conftest.py" + 'inline; filename="conftest.py"' ) return web.Response() @@ -1472,16 +1481,17 @@ async def handler(request): assert b"data" == data["unknown"].file.read() assert data["unknown"].content_type == "application/octet-stream" assert data["unknown"].filename == "unknown" + data["unknown"].file.close() return web.Response() app = web.Application() app.router.add_post("/", handler) client = await aiohttp_client(app) - data = io.BytesIO(b"data") - resp = await client.post("/", data=[data]) - assert 200 == resp.status - resp.close() + with io.BytesIO(b"data") as file_handle: + resp = await client.post("/", data=[file_handle]) + assert 200 == resp.status + resp.close() async def test_POST_FILES_IO_WITH_PARAMS(aiohttp_client) -> None: @@ -1491,6 +1501,7 @@ async def handler(request): assert data["unknown"].content_type == "application/octet-stream" assert data["unknown"].filename == "unknown" assert data["unknown"].file.read() == b"data" + data["unknown"].file.close() assert data.getall("q") == ["t1", "t2"] return web.Response() @@ -1499,12 +1510,13 @@ async def handler(request): app.router.add_post("/", handler) client = await aiohttp_client(app) - data = io.BytesIO(b"data") - resp = await client.post( - "/", data=(("test", "true"), MultiDict([("q", "t1"), ("q", "t2")]), data) - ) - assert 200 == resp.status - resp.close() + with io.BytesIO(b"data") as file_handle: + resp = await client.post( + "/", + data=(("test", "true"), MultiDict([("q", "t1"), ("q", "t2")]), file_handle), + ) + assert 200 == resp.status + resp.close() async def test_POST_FILES_WITH_DATA(aiohttp_client, fname) -> None: @@ -1519,6 +1531,7 @@ async def handler(request): assert data["some"].filename == fname.name with fname.open("rb") as f: assert data["some"].file.read() == f.read() + data["some"].file.close() return web.Response() @@ -2327,25 +2340,75 @@ async def test_creds_in_auth_and_url() -> None: await session.close() -async def test_drop_auth_on_redirect_to_other_host(aiohttp_server) -> None: - async def srv1(request): - assert request.host == "host1.com" +@pytest.fixture +def create_server_for_url_and_handler(aiohttp_server, tls_certificate_authority): + def create(url, srv): + app = web.Application() + app.router.add_route("GET", url.path, srv) + + kwargs = {} + if url.scheme == "https": + cert = tls_certificate_authority.issue_cert( + url.host, "localhost", "127.0.0.1" + ) + ssl_ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) + cert.configure_cert(ssl_ctx) + kwargs["ssl"] = ssl_ctx + return aiohttp_server(app, **kwargs) + + return create + + +@pytest.mark.parametrize( + ["url_from", "url_to"], + [ + ["http://host1.com/path1", "http://host2.com/path2"], + ["http://host1.com/path1", "https://host1.com/path1"], + ["https://host1.com/path1", "http://host1.com/path2"], + ], + ids=( + "entirely different hosts", + "http -> https", + "https -> http", + ), +) +async def test_drop_auth_on_redirect_to_other_host( + create_server_for_url_and_handler, + url_from, + url_to, +) -> None: + url_from, url_to = URL(url_from), URL(url_to) + + async def srv_from(request): + assert request.host == url_from.host assert request.headers["Authorization"] == "Basic dXNlcjpwYXNz" - raise web.HTTPFound("http://host2.com/path2") + raise web.HTTPFound(url_to) - async def srv2(request): - assert request.host == "host2.com" - assert "Authorization" not in request.headers + async def srv_to(request): + assert request.host == url_to.host + assert "Authorization" not in request.headers, "Header wasn't dropped" return web.Response() - app = web.Application() - app.router.add_route("GET", "/path1", srv1) - app.router.add_route("GET", "/path2", srv2) + server_from = await create_server_for_url_and_handler(url_from, srv_from) + server_to = await create_server_for_url_and_handler(url_to, srv_to) - server = await aiohttp_server(app) + assert ( + url_from.host != url_to.host or server_from.scheme != server_to.scheme + ), "Invalid test case, host or scheme must differ" + + protocol_port_map = { + "http": 80, + "https": 443, + } + etc_hosts = { + (url_from.host, protocol_port_map[server_from.scheme]): server_from, + (url_to.host, protocol_port_map[server_to.scheme]): server_to, + } class FakeResolver(AbstractResolver): async def resolve(self, host, port=0, family=socket.AF_INET): + server = etc_hosts[(host, port)] + return [ { "hostname": host, @@ -2360,45 +2423,35 @@ async def resolve(self, host, port=0, family=socket.AF_INET): async def close(self): pass - connector = aiohttp.TCPConnector(resolver=FakeResolver()) + connector = aiohttp.TCPConnector(resolver=FakeResolver(), ssl=False) + async with aiohttp.ClientSession(connector=connector) as client: resp = await client.get( - "http://host1.com/path1", auth=aiohttp.BasicAuth("user", "pass") + url_from, + auth=aiohttp.BasicAuth("user", "pass"), ) assert resp.status == 200 resp = await client.get( - "http://host1.com/path1", headers={"Authorization": "Basic dXNlcjpwYXNz"} + url_from, + headers={"Authorization": "Basic dXNlcjpwYXNz"}, ) assert resp.status == 200 async def test_async_with_session() -> None: - with pytest.warns(None) as cm: - async with aiohttp.ClientSession() as session: - pass - assert len(cm.list) == 0 + async with aiohttp.ClientSession() as session: + pass assert session.closed async def test_session_close_awaitable() -> None: session = aiohttp.ClientSession() - with pytest.warns(None) as cm: - await session.close() - assert len(cm.list) == 0 + await session.close() assert session.closed -async def test_close_run_until_complete_not_deprecated() -> None: - session = aiohttp.ClientSession() - - with pytest.warns(None) as cm: - await session.close() - - assert len(cm.list) == 0 - - async def test_close_resp_on_error_async_with_session(aiohttp_server) -> None: async def handler(request): resp = web.StreamResponse(headers={"content-length": "100"}) @@ -2515,18 +2568,6 @@ async def test_aiohttp_request_ctx_manager_not_found() -> None: assert False, "never executed" # pragma: no cover -async def test_aiohttp_request_coroutine(aiohttp_server) -> None: - async def handler(request): - return web.Response() - - app = web.Application() - app.router.add_get("/", handler) - server = await aiohttp_server(app) - - with pytest.raises(TypeError): - await aiohttp.request("GET", server.make_url("/")) - - async def test_yield_from_in_session_request(aiohttp_client) -> None: # a test for backward compatibility with yield from syntax async def handler(request): @@ -2715,7 +2756,7 @@ def connection_lost(self, exc): await r.read() assert 0 == len(connector._conns) await session.close() - connector.close() + await connector.close() server.close() await server.wait_closed() @@ -2757,7 +2798,7 @@ def connection_lost(self, exc): assert 0 == len(connector._conns) await session.close() - connector.close() + await connector.close() server.close() await server.wait_closed() @@ -2834,10 +2875,9 @@ async def handler(request): client = await aiohttp_client(app) - @async_generator async def gen(): for i in range(100): - await yield_(b"1234567890") + yield b"1234567890" resp = await client.post("/", data=gen()) assert resp.status == 200 @@ -2950,3 +2990,22 @@ async def handler(request): async with await client.get("/", read_bufsize=4) as resp: assert resp.content.get_read_buffer_limits() == (4, 8) + + +async def test_http_empty_data_text(aiohttp_client) -> None: + async def handler(request): + data = await request.read() + ret = "ok" if data == b"" else "fail" + resp = web.Response(text=ret) + resp.headers["Content-Type"] = request.headers["Content-Type"] + return resp + + app = web.Application() + app.add_routes([web.post("/", handler)]) + + client = await aiohttp_client(app) + + async with await client.post("/", data="") as resp: + assert resp.status == 200 + assert await resp.text() == "ok" + assert resp.headers["Content-Type"] == "text/plain; charset=utf-8" diff --git a/tests/test_client_proto.py b/tests/test_client_proto.py index 85225c7..eea2830 100644 --- a/tests/test_client_proto.py +++ b/tests/test_client_proto.py @@ -134,3 +134,17 @@ async def test_eof_received(loop) -> None: assert proto._read_timeout_handle is not None proto.eof_received() assert proto._read_timeout_handle is None + + +async def test_connection_lost_sets_transport_to_none(loop, mocker) -> None: + """Ensure that the transport is set to None when the connection is lost. + + This ensures the writer knows that the connection is closed. + """ + proto = ResponseHandler(loop=loop) + proto.connection_made(mocker.Mock()) + assert proto.transport is not None + + proto.connection_lost(OSError()) + + assert proto.transport is None diff --git a/tests/test_client_request.py b/tests/test_client_request.py index d650059..9eeb933 100644 --- a/tests/test_client_request.py +++ b/tests/test_client_request.py @@ -8,7 +8,6 @@ from unittest import mock import pytest -from async_generator import async_generator, yield_ from multidict import CIMultiDict, CIMultiDictProxy, istr from yarl import URL @@ -20,6 +19,7 @@ Fingerprint, _merge_ssl_params, ) +from aiohttp.helpers import PY_311 from aiohttp.test_utils import make_mocked_coro @@ -120,11 +120,6 @@ def test_version_err(make_request) -> None: make_request("get", "http://python.org/", version="1.c") -def test_https_proxy(make_request) -> None: - with pytest.raises(ValueError): - make_request("get", "http://python.org/", proxy=URL("https://proxy.org")) - - def test_keep_alive(make_request) -> None: req = make_request("get", "http://python.org/", version=(0, 9)) assert not req.keep_alive() @@ -280,10 +275,18 @@ def test_host_header_ipv6_with_port(make_request) -> None: assert req.headers["HOST"] == "[::2]:99" +@pytest.mark.xfail( + PY_311, + reason="No idea why ClientRequest() is constructed out of loop but " + "it calls `asyncio.get_event_loop()`", + raises=DeprecationWarning, + strict=False, +) def test_default_loop(loop) -> None: asyncio.set_event_loop(loop) req = ClientRequest("get", URL("http://python.org/")) assert req.loop is loop + loop.run_until_complete(req.close()) def test_default_headers_useragent(make_request) -> None: @@ -589,6 +592,8 @@ async def test_connection_header(loop, conn) -> None: await req.send(conn) assert req.headers.get("CONNECTION") == "close" + await req.close() + async def test_no_content_length(loop, conn) -> None: req = ClientRequest("get", URL("http://python.org"), loop=loop) @@ -611,6 +616,7 @@ async def test_content_type_auto_header_get(loop, conn) -> None: resp = await req.send(conn) assert "CONTENT-TYPE" not in req.headers resp.close() + await req.close() async def test_content_type_auto_header_form(loop, conn) -> None: @@ -620,6 +626,7 @@ async def test_content_type_auto_header_form(loop, conn) -> None: resp = await req.send(conn) assert "application/x-www-form-urlencoded" == req.headers.get("CONTENT-TYPE") resp.close() + await req.close() async def test_content_type_auto_header_bytes(loop, conn) -> None: @@ -627,6 +634,7 @@ async def test_content_type_auto_header_bytes(loop, conn) -> None: resp = await req.send(conn) assert "application/octet-stream" == req.headers.get("CONTENT-TYPE") resp.close() + await req.close() async def test_content_type_skip_auto_header_bytes(loop, conn) -> None: @@ -640,6 +648,7 @@ async def test_content_type_skip_auto_header_bytes(loop, conn) -> None: resp = await req.send(conn) assert "CONTENT-TYPE" not in req.headers resp.close() + await req.close() async def test_content_type_skip_auto_header_form(loop, conn) -> None: @@ -653,19 +662,22 @@ async def test_content_type_skip_auto_header_form(loop, conn) -> None: resp = await req.send(conn) assert "CONTENT-TYPE" not in req.headers resp.close() + await req.close() async def test_content_type_auto_header_content_length_no_skip(loop, conn) -> None: - req = ClientRequest( - "post", - URL("http://python.org"), - data=io.BytesIO(b"hey"), - skip_auto_headers={"Content-Length"}, - loop=loop, - ) - resp = await req.send(conn) - assert req.headers.get("CONTENT-LENGTH") == "3" - resp.close() + with io.BytesIO(b"hey") as file_handle: + req = ClientRequest( + "post", + URL("http://python.org"), + data=file_handle, + skip_auto_headers={"Content-Length"}, + loop=loop, + ) + resp = await req.send(conn) + assert req.headers.get("CONTENT-LENGTH") == "3" + resp.close() + await req.close() async def test_urlencoded_formdata_charset(loop, conn) -> None: @@ -679,6 +691,7 @@ async def test_urlencoded_formdata_charset(loop, conn) -> None: assert "application/x-www-form-urlencoded; charset=koi8-r" == req.headers.get( "CONTENT-TYPE" ) + await req.close() async def test_post_data(loop, conn) -> None: @@ -715,6 +728,7 @@ async def test_pass_falsy_data_file(loop, tmpdir) -> None: ) assert req.headers.get("CONTENT-LENGTH", None) is not None await req.close() + testfile.close() # Elasticsearch API requires to send request body with GET-requests @@ -913,6 +927,7 @@ async def test_expect100(loop, conn) -> None: assert req._continue is not None req.terminate() resp.close() + await req.close() async def test_expect_100_continue_header(loop, conn) -> None: @@ -924,13 +939,13 @@ async def test_expect_100_continue_header(loop, conn) -> None: assert req._continue is not None req.terminate() resp.close() + await req.close() async def test_data_stream(loop, buf, conn) -> None: - @async_generator async def gen(): - await yield_(b"binary data") - await yield_(b" result") + yield b"binary data" + yield b" result" req = ClientRequest("POST", URL("http://python.org/"), data=gen(), loop=loop) assert req.chunked @@ -969,30 +984,31 @@ async def gen(writer): async def test_data_file(loop, buf, conn) -> None: - req = ClientRequest( - "POST", - URL("http://python.org/"), - data=io.BufferedReader(io.BytesIO(b"*" * 2)), - loop=loop, - ) - assert req.chunked - assert isinstance(req.body, payload.BufferedReaderPayload) - assert req.headers["TRANSFER-ENCODING"] == "chunked" + with io.BufferedReader(io.BytesIO(b"*" * 2)) as file_handle: + req = ClientRequest( + "POST", + URL("http://python.org/"), + data=file_handle, + loop=loop, + ) + assert req.chunked + assert isinstance(req.body, payload.BufferedReaderPayload) + assert req.headers["TRANSFER-ENCODING"] == "chunked" - resp = await req.send(conn) - assert asyncio.isfuture(req._writer) - await resp.wait_for_close() - assert req._writer is None - assert buf.split(b"\r\n\r\n", 1)[1] == b"2\r\n" + b"*" * 2 + b"\r\n0\r\n\r\n" - await req.close() + resp = await req.send(conn) + assert asyncio.isfuture(req._writer) + await resp.wait_for_close() + + assert req._writer is None + assert buf.split(b"\r\n\r\n", 1)[1] == b"2\r\n" + b"*" * 2 + b"\r\n0\r\n\r\n" + await req.close() async def test_data_stream_exc(loop, conn) -> None: fut = loop.create_future() - @async_generator async def gen(): - await yield_(b"binary data") + yield b"binary data" await fut req = ClientRequest("POST", URL("http://python.org/"), data=gen(), loop=loop) @@ -1015,9 +1031,10 @@ async def throw_exc(): async def test_data_stream_exc_chain(loop, conn) -> None: fut = loop.create_future() - @async_generator async def gen(): await fut + return + yield req = ClientRequest("POST", URL("http://python.org/"), data=gen(), loop=loop) @@ -1041,10 +1058,9 @@ async def throw_exc(): async def test_data_stream_continue(loop, buf, conn) -> None: - @async_generator async def gen(): - await yield_(b"binary data") - await yield_(b" result") + yield b"binary data" + yield b" result" req = ClientRequest( "POST", URL("http://python.org/"), data=gen(), expect100=True, loop=loop @@ -1086,10 +1102,9 @@ async def coro(): async def test_close(loop, buf, conn) -> None: - @async_generator async def gen(): await asyncio.sleep(0.00001) - await yield_(b"result") + yield b"result" req = ClientRequest("POST", URL("http://python.org/"), data=gen(), loop=loop) resp = await req.send(conn) @@ -1125,6 +1140,8 @@ async def test_oserror_on_write_bytes(loop, conn) -> None: exc = conn.protocol.set_exception.call_args[0][0] assert isinstance(exc, aiohttp.ClientOSError) + await req.close() + async def test_terminate(loop, conn) -> None: req = ClientRequest("get", URL("http://python.org"), loop=loop) @@ -1137,6 +1154,8 @@ async def test_terminate(loop, conn) -> None: writer.cancel.assert_called_with() resp.close() + await req.close() + def test_terminate_with_closed_loop(loop, conn) -> None: req = resp = writer = None @@ -1152,6 +1171,7 @@ async def go(): loop.run_until_complete(go()) + loop.run_until_complete(req.close()) loop.close() req.terminate() assert req._writer is None @@ -1166,6 +1186,8 @@ def test_terminate_without_writer(loop) -> None: req.terminate() assert req._writer is None + loop.run_until_complete(req.close()) + async def test_custom_req_rep(loop) -> None: conn = None @@ -1264,3 +1286,5 @@ def test_loose_cookies_types(loop) -> None: for loose_cookies_type in accepted_types: req.update_cookies(cookies=loose_cookies_type) + + loop.run_until_complete(req.close()) diff --git a/tests/test_client_response.py b/tests/test_client_response.py index 55aae97..fa472e7 100644 --- a/tests/test_client_response.py +++ b/tests/test_client_response.py @@ -2,6 +2,7 @@ import gc import sys +from typing import Any from unittest import mock import pytest @@ -46,6 +47,7 @@ async def test_http_processing_error(session) -> None: await response.start(connection) assert info.value.request_info is request_info + response.close() def test_del(session) -> None: @@ -439,7 +441,11 @@ def side_effect(*args, **kwargs): assert not response.get_encoding.called -async def test_text_detect_encoding(loop, session) -> None: +@pytest.mark.parametrize("content_type", ("text/plain", "text/plain;charset=invalid")) +async def test_text_charset_resolver( + content_type: str, loop: Any, session: Any +) -> None: + session._resolve_charset = lambda r, b: "cp1251" response = ClientResponse( "get", URL("http://def-cl-resp.org"), @@ -457,7 +463,7 @@ def side_effect(*args, **kwargs): fut.set_result('{"тест": "пройден"}'.encode("cp1251")) return fut - response._headers = {"Content-Type": "text/plain"} + response._headers = {"Content-Type": content_type} content = response.content = mock.Mock() content.read.side_effect = side_effect @@ -465,35 +471,7 @@ def side_effect(*args, **kwargs): res = await response.text() assert res == '{"тест": "пройден"}' assert response._connection is None - - -async def test_text_detect_encoding_if_invalid_charset(loop, session) -> None: - response = ClientResponse( - "get", - URL("http://def-cl-resp.org"), - request_info=mock.Mock(), - writer=mock.Mock(), - continue100=None, - timer=TimerNoop(), - traces=[], - loop=loop, - session=session, - ) - - def side_effect(*args, **kwargs): - fut = loop.create_future() - fut.set_result('{"тест": "пройден"}'.encode("cp1251")) - return fut - - response._headers = {"Content-Type": "text/plain;charset=invalid"} - content = response.content = mock.Mock() - content.read.side_effect = side_effect - - await response.read() - res = await response.text() - assert res == '{"тест": "пройден"}' - assert response._connection is None - assert response.get_encoding().lower() in ("windows-1251", "maccyrillic") + assert response.get_encoding() == "cp1251" async def test_get_encoding_body_none(loop, session) -> None: @@ -520,7 +498,7 @@ def side_effect(*args, **kwargs): with pytest.raises( RuntimeError, - match="^Cannot guess the encoding of a not yet read body$", + match="^Cannot compute fallback encoding of a not yet read body$", ): response.get_encoding() assert response.closed @@ -741,9 +719,7 @@ def test_get_encoding_unknown(loop, session) -> None: ) response._headers = {"Content-Type": "application/json"} - with mock.patch("aiohttp.client_reqrep.chardet") as m_chardet: - m_chardet.detect.return_value = {"encoding": None} - assert response.get_encoding() == "utf-8" + assert response.get_encoding() == "utf-8" def test_raise_for_status_2xx() -> None: @@ -1256,3 +1232,24 @@ def test_response_links_empty(loop, session) -> None: ) response._headers = CIMultiDict() assert response.links == {} + + +def test_response_not_closed_after_get_ok(mocker) -> None: + response = ClientResponse( + "get", + URL("http://del-cl-resp.org"), + request_info=mock.Mock(), + writer=mock.Mock(), + continue100=None, + timer=TimerNoop(), + traces=[], + loop=mock.Mock(), + session=mock.Mock(), + ) + response.status = 400 + response.reason = "Bad Request" + response._closed = False + spy = mocker.spy(response, "raise_for_status") + assert not response.ok + assert not response.closed + assert spy.call_count == 0 diff --git a/tests/test_client_session.py b/tests/test_client_session.py index 298dac9..effa7b1 100644 --- a/tests/test_client_session.py +++ b/tests/test_client_session.py @@ -1,10 +1,11 @@ import asyncio import contextlib import gc +import io import json import sys from http.cookies import SimpleCookie -from io import BytesIO +from typing import Any, List from unittest import mock import pytest @@ -30,7 +31,7 @@ async def make_conn(): proto = mock.Mock() conn._conns["a"] = [(proto, 123)] yield conn - conn.close() + loop.run_until_complete(conn.close()) @pytest.fixture @@ -292,7 +293,7 @@ async def test_connector(create_session, loop, mocker) -> None: await session.close() assert connector.close.called - connector.close() + await connector.close() async def test_create_connector(create_session, loop, mocker) -> None: @@ -314,7 +315,6 @@ async def make_connector(): connector = another_loop.run_until_complete(make_connector()) - stack.enter_context(contextlib.closing(connector)) with pytest.raises(RuntimeError) as ctx: async def make_sess(): @@ -325,9 +325,13 @@ async def make_sess(): Matches("Session and connector has to use same event loop") == str(ctx.value).strip() ) + another_loop.run_until_complete(connector.close()) + # Cannot use `AsyncExitStack` as it's Python 3.7+: + another_loop.run_until_complete(connector.close()) -def test_detach(session) -> None: + +def test_detach(loop, session) -> None: conn = session.connector try: assert not conn.closed @@ -336,7 +340,7 @@ def test_detach(session) -> None: assert session.closed assert not conn.closed finally: - conn.close() + loop.run_until_complete(conn.close()) async def test_request_closed_session(session) -> None: @@ -345,10 +349,10 @@ async def test_request_closed_session(session) -> None: await session.request("get", "/") -def test_close_flag_for_closed_connector(session) -> None: +def test_close_flag_for_closed_connector(loop, session) -> None: conn = session.connector assert not session.closed - conn.close() + loop.run_until_complete(conn.close()) assert session.closed @@ -398,7 +402,7 @@ async def test_del_debug(connector, loop) -> None: assert logs[0] == expected -async def test_context_manager(connector, loop) -> None: +async def test_session_context_manager(connector, loop) -> None: with pytest.raises(TypeError): with ClientSession(loop=loop, connector=connector) as session: pass @@ -514,6 +518,7 @@ async def handler(request): async def test_session_default_version(loop) -> None: session = aiohttp.ClientSession(loop=loop) assert session.version == aiohttp.HttpVersion11 + await session.close() async def test_session_loop(loop) -> None: @@ -548,53 +553,174 @@ async def handler(request): trace_config_ctx = mock.Mock() trace_request_ctx = {} body = "This is request body" - gathered_req_body = BytesIO() - gathered_res_body = BytesIO() + gathered_req_headers = CIMultiDict() on_request_start = mock.Mock(side_effect=make_mocked_coro(mock.Mock())) on_request_redirect = mock.Mock(side_effect=make_mocked_coro(mock.Mock())) on_request_end = mock.Mock(side_effect=make_mocked_coro(mock.Mock())) - async def on_request_chunk_sent(session, context, params): - gathered_req_body.write(params.chunk) + with io.BytesIO() as gathered_req_body, io.BytesIO() as gathered_res_body: + + async def on_request_chunk_sent(session, context, params): + gathered_req_body.write(params.chunk) + + async def on_response_chunk_received(session, context, params): + gathered_res_body.write(params.chunk) - async def on_response_chunk_received(session, context, params): - gathered_res_body.write(params.chunk) + async def on_request_headers_sent(session, context, params): + gathered_req_headers.extend(**params.headers) + + trace_config = aiohttp.TraceConfig( + trace_config_ctx_factory=mock.Mock(return_value=trace_config_ctx) + ) + trace_config.on_request_start.append(on_request_start) + trace_config.on_request_end.append(on_request_end) + trace_config.on_request_chunk_sent.append(on_request_chunk_sent) + trace_config.on_response_chunk_received.append(on_response_chunk_received) + trace_config.on_request_redirect.append(on_request_redirect) + trace_config.on_request_headers_sent.append(on_request_headers_sent) + + headers = CIMultiDict({"Custom-Header": "Custom value"}) + session = await aiohttp_client( + app, trace_configs=[trace_config], headers=headers + ) + + async with session.post( + "/", data=body, trace_request_ctx=trace_request_ctx + ) as resp: + + await resp.json() + + on_request_start.assert_called_once_with( + session.session, + trace_config_ctx, + aiohttp.TraceRequestStartParams( + hdrs.METH_POST, session.make_url("/"), headers + ), + ) + + on_request_end.assert_called_once_with( + session.session, + trace_config_ctx, + aiohttp.TraceRequestEndParams( + hdrs.METH_POST, session.make_url("/"), headers, resp + ), + ) + assert not on_request_redirect.called + assert gathered_req_body.getvalue() == body.encode("utf8") + assert gathered_res_body.getvalue() == json.dumps({"ok": True}).encode( + "utf8" + ) + assert gathered_req_headers["Custom-Header"] == "Custom value" + + +async def test_request_tracing_url_params(loop: Any, aiohttp_client: Any) -> None: + async def root_handler(request): + return web.Response() + + async def redirect_handler(request): + raise web.HTTPFound("/") + + app = web.Application() + app.router.add_get("/", root_handler) + app.router.add_get("/redirect", redirect_handler) + + mocks = [mock.Mock(side_effect=make_mocked_coro(mock.Mock())) for _ in range(7)] + ( + on_request_start, + on_request_redirect, + on_request_end, + on_request_exception, + on_request_chunk_sent, + on_response_chunk_received, + on_request_headers_sent, + ) = mocks trace_config = aiohttp.TraceConfig( - trace_config_ctx_factory=mock.Mock(return_value=trace_config_ctx) + trace_config_ctx_factory=mock.Mock(return_value=mock.Mock()) ) trace_config.on_request_start.append(on_request_start) + trace_config.on_request_redirect.append(on_request_redirect) trace_config.on_request_end.append(on_request_end) + trace_config.on_request_exception.append(on_request_exception) trace_config.on_request_chunk_sent.append(on_request_chunk_sent) trace_config.on_response_chunk_received.append(on_response_chunk_received) - trace_config.on_request_redirect.append(on_request_redirect) + trace_config.on_request_headers_sent.append(on_request_headers_sent) session = await aiohttp_client(app, trace_configs=[trace_config]) - async with session.post( - "/", data=body, trace_request_ctx=trace_request_ctx - ) as resp: + def reset_mocks() -> None: + for m in mocks: + m.reset_mock() - await resp.json() + def to_trace_urls(mock_func: mock.Mock) -> List[URL]: + return [call_args[0][-1].url for call_args in mock_func.call_args_list] - on_request_start.assert_called_once_with( - session.session, - trace_config_ctx, - aiohttp.TraceRequestStartParams( - hdrs.METH_POST, session.make_url("/"), CIMultiDict() - ), - ) + def to_url(path: str) -> URL: + return session.make_url(path) - on_request_end.assert_called_once_with( - session.session, - trace_config_ctx, - aiohttp.TraceRequestEndParams( - hdrs.METH_POST, session.make_url("/"), CIMultiDict(), resp - ), - ) - assert not on_request_redirect.called - assert gathered_req_body.getvalue() == body.encode("utf8") - assert gathered_res_body.getvalue() == json.dumps({"ok": True}).encode("utf8") + # Standard + for req in [ + lambda: session.get("/?x=0"), + lambda: session.get("/", params=dict(x=0)), + ]: + reset_mocks() + async with req() as resp: + await resp.text() + assert to_trace_urls(on_request_start) == [to_url("/?x=0")] + assert to_trace_urls(on_request_redirect) == [] + assert to_trace_urls(on_request_end) == [to_url("/?x=0")] + assert to_trace_urls(on_request_exception) == [] + assert to_trace_urls(on_request_chunk_sent) == [to_url("/?x=0")] + assert to_trace_urls(on_response_chunk_received) == [to_url("/?x=0")] + assert to_trace_urls(on_request_headers_sent) == [to_url("/?x=0")] + + # Redirect + for req in [ + lambda: session.get("/redirect?x=0"), + lambda: session.get("/redirect", params=dict(x=0)), + ]: + reset_mocks() + async with req() as resp: + await resp.text() + assert to_trace_urls(on_request_start) == [to_url("/redirect?x=0")] + assert to_trace_urls(on_request_redirect) == [to_url("/redirect?x=0")] + assert to_trace_urls(on_request_end) == [to_url("/")] + assert to_trace_urls(on_request_exception) == [] + assert to_trace_urls(on_request_chunk_sent) == [ + to_url("/redirect?x=0"), + to_url("/"), + ] + assert to_trace_urls(on_response_chunk_received) == [to_url("/")] + assert to_trace_urls(on_request_headers_sent) == [ + to_url("/redirect?x=0"), + to_url("/"), + ] + + # Exception + with mock.patch("aiohttp.client.TCPConnector.connect") as connect_patched: + error = Exception() + if sys.version_info >= (3, 8, 1): + connect_patched.side_effect = error + else: + loop = asyncio.get_event_loop() + f = loop.create_future() + f.set_exception(error) + connect_patched.return_value = f + + for req in [ + lambda: session.get("/?x=0"), + lambda: session.get("/", params=dict(x=0)), + ]: + reset_mocks() + with contextlib.suppress(Exception): + await req() + assert to_trace_urls(on_request_start) == [to_url("/?x=0")] + assert to_trace_urls(on_request_redirect) == [] + assert to_trace_urls(on_request_end) == [] + assert to_trace_urls(on_request_exception) == [to_url("?x=0")] + assert to_trace_urls(on_request_chunk_sent) == [] + assert to_trace_urls(on_response_chunk_received) == [] + assert to_trace_urls(on_request_headers_sent) == [] async def test_request_tracing_exception() -> None: @@ -632,6 +758,8 @@ async def test_request_tracing_exception() -> None: ) assert not on_request_end.called + await session.close() + async def test_request_tracing_interpose_headers(loop, aiohttp_client) -> None: async def handler(request): @@ -674,6 +802,7 @@ async def test_client_session_custom_attr(loop) -> None: session = ClientSession(loop=loop) with pytest.warns(DeprecationWarning): session.custom = None + await session.close() async def test_client_session_timeout_args(loop) -> None: @@ -694,25 +823,41 @@ async def test_client_session_timeout_args(loop) -> None: loop=loop, timeout=client.ClientTimeout(total=10 * 60), conn_timeout=30 * 60 ) + await session1.close() + await session2.close() + async def test_client_session_timeout_default_args(loop) -> None: session1 = ClientSession() assert session1.timeout == client.DEFAULT_TIMEOUT + await session1.close() async def test_client_session_timeout_argument() -> None: session = ClientSession(timeout=500) assert session.timeout == 500 + await session.close() + + +async def test_client_session_timeout_zero() -> None: + timeout = client.ClientTimeout(total=10, connect=0, sock_connect=0, sock_read=0) + try: + async with ClientSession(timeout=timeout) as session: + await session.get("http://example.com") + except asyncio.TimeoutError: + pytest.fail("0 should disable timeout.") async def test_requote_redirect_url_default() -> None: session = ClientSession() assert session.requote_redirect_url + await session.close() async def test_requote_redirect_url_default_disable() -> None: session = ClientSession(requote_redirect_url=False) assert not session.requote_redirect_url + await session.close() async def test_requote_redirect_setter() -> None: @@ -721,3 +866,40 @@ async def test_requote_redirect_setter() -> None: with pytest.warns(DeprecationWarning): session.requote_redirect_url = False assert not session.requote_redirect_url + await session.close() + + +@pytest.mark.parametrize( + ("base_url", "url", "expected_url"), + [ + pytest.param( + None, + "http://example.com/test", + URL("http://example.com/test"), + id="base_url=None url='http://example.com/test'", + ), + pytest.param( + None, + URL("http://example.com/test"), + URL("http://example.com/test"), + id="base_url=None url=URL('http://example.com/test')", + ), + pytest.param( + "http://example.com", + "/test", + URL("http://example.com/test"), + id="base_url='http://example.com' url='/test'", + ), + pytest.param( + URL("http://example.com"), + "/test", + URL("http://example.com/test"), + id="base_url=URL('http://example.com') url='/test'", + ), + ], +) +async def test_build_url_returns_expected_url( + create_session, base_url, url, expected_url +) -> None: + session = await create_session(base_url) + assert session._build_url(url) == expected_url diff --git a/tests/test_client_ws.py b/tests/test_client_ws.py index baa4469..f0b7757 100644 --- a/tests/test_client_ws.py +++ b/tests/test_client_ws.py @@ -71,6 +71,30 @@ async def test_ws_connect_with_origin(key_data, loop) -> None: assert m_req.call_args[1]["headers"][hdrs.ORIGIN] == origin +async def test_ws_connect_with_params(ws_key, loop, key_data) -> None: + params = {"key1": "value1", "key2": "value2"} + + resp = mock.Mock() + resp.status = 101 + resp.headers = { + hdrs.UPGRADE: "websocket", + hdrs.CONNECTION: "upgrade", + hdrs.SEC_WEBSOCKET_ACCEPT: ws_key, + hdrs.SEC_WEBSOCKET_PROTOCOL: "chat", + } + with mock.patch("aiohttp.client.os") as m_os: + with mock.patch("aiohttp.client.ClientSession.request") as m_req: + m_os.urandom.return_value = key_data + m_req.return_value = loop.create_future() + m_req.return_value.set_result(resp) + + await aiohttp.ClientSession().ws_connect( + "http://test.org", protocols=("t1", "t2", "chat"), params=params + ) + + assert m_req.call_args[1]["params"] == params + + async def test_ws_connect_custom_response(loop, ws_key, key_data) -> None: class CustomResponse(client.ClientWebSocketResponse): def read(self, decode=False): diff --git a/tests/test_client_ws_functional.py b/tests/test_client_ws_functional.py index e423765..76ef052 100644 --- a/tests/test_client_ws_functional.py +++ b/tests/test_client_ws_functional.py @@ -461,7 +461,7 @@ async def handler(request): await resp.send_str("ask") with pytest.raises(asyncio.TimeoutError): - with async_timeout.timeout(0.01): + async with async_timeout.timeout(0.01): await resp.receive() await resp.close() diff --git a/tests/test_connector.py b/tests/test_connector.py index 0984192..0b992df 100644 --- a/tests/test_connector.py +++ b/tests/test_connector.py @@ -12,6 +12,7 @@ from unittest import mock import pytest +from conftest import needs_unix from yarl import URL import aiohttp @@ -43,12 +44,6 @@ def ssl_key(): return ConnectionKey("localhost", 80, True, None, None, None, None) -@pytest.fixture -def unix_sockname(shorttmpdir): - sock_path = shorttmpdir / "socket.sock" - return str(sock_path) - - @pytest.fixture def unix_server(loop, unix_sockname): runners = [] @@ -84,7 +79,11 @@ async def go(app): def create_mocked_conn(conn_closing_result=None, **kwargs): - loop = asyncio.get_event_loop() + try: + loop = asyncio.get_running_loop() + except (AttributeError, RuntimeError): # AttributeError->py36 + loop = asyncio.get_event_loop_policy().get_event_loop() + proto = mock.Mock(**kwargs) proto.closed = loop.create_future() proto.closed.set_result(conn_closing_result) @@ -244,7 +243,7 @@ async def test_create_conn(loop) -> None: await conn._create_connection(object(), [], object()) -async def test_context_manager(loop) -> None: +async def test_connector_context_manager(loop) -> None: conn = aiohttp.BaseConnector(loop=loop) with pytest.warns(DeprecationWarning): @@ -253,6 +252,8 @@ async def test_context_manager(loop) -> None: assert conn.closed + await conn.close() + async def test_async_context_manager(loop) -> None: conn = aiohttp.BaseConnector(loop=loop) @@ -269,7 +270,7 @@ async def test_close(loop) -> None: conn = aiohttp.BaseConnector(loop=loop) assert not conn.closed conn._conns[("host", 8080, False)] = [(proto, object())] - conn.close() + await conn.close() assert not conn._conns assert proto.close.called @@ -283,7 +284,7 @@ async def test_get(loop) -> None: proto = mock.Mock() conn._conns[1] = [(proto, loop.time())] assert conn._get(1) == proto - conn.close() + await conn.close() async def test_get_unconnected_proto(loop) -> None: @@ -327,7 +328,7 @@ async def test_get_expired(loop) -> None: conn._conns[key] = [(proto, loop.time() - 1000)] assert conn._get(key) is None assert not conn._conns - conn.close() + await conn.close() async def test_get_expired_ssl(loop) -> None: @@ -341,7 +342,7 @@ async def test_get_expired_ssl(loop) -> None: assert conn._get(key) is None assert not conn._conns assert conn._cleanup_closed_transports == [transport] - conn.close() + await conn.close() async def test_release_acquired(loop, key) -> None: @@ -360,7 +361,7 @@ async def test_release_acquired(loop, key) -> None: assert 0 == len(conn._acquired) assert 0 == len(conn._acquired_per_host) - conn.close() + await conn.close() async def test_release_acquired_closed(loop, key) -> None: @@ -375,7 +376,7 @@ async def test_release_acquired_closed(loop, key) -> None: assert 1 == len(conn._acquired) assert 1 == len(conn._acquired_per_host[key]) assert not conn._release_waiter.called - conn.close() + await conn.close() async def test_release(loop, key) -> None: @@ -393,7 +394,7 @@ async def test_release(loop, key) -> None: assert conn._conns[key][0][0] == proto assert conn._conns[key][0][1] == pytest.approx(loop.time(), abs=0.1) assert not conn._cleanup_closed_transports - conn.close() + await conn.close() async def test_release_ssl_transport(loop, ssl_key) -> None: @@ -407,7 +408,7 @@ async def test_release_ssl_transport(loop, ssl_key) -> None: conn._release(ssl_key, proto, should_close=True) assert conn._cleanup_closed_transports == [transport] - conn.close() + await conn.close() async def test_release_already_closed(loop) -> None: @@ -416,7 +417,7 @@ async def test_release_already_closed(loop) -> None: proto = mock.Mock() key = 1 conn._acquired.add(proto) - conn.close() + await conn.close() conn._release_waiters = mock.Mock() conn._release_acquired = mock.Mock() @@ -435,7 +436,7 @@ async def test_release_waiter_no_limit(loop, key, key2) -> None: conn._release_waiter() assert len(conn._waiters[key]) == 0 assert w.done.called - conn.close() + await conn.close() async def test_release_waiter_first_available(loop, key, key2) -> None: @@ -452,7 +453,7 @@ async def test_release_waiter_first_available(loop, key, key2) -> None: or not w1.set_result.called and w2.set_result.called ) - conn.close() + await conn.close() async def test_release_waiter_release_first(loop, key, key2) -> None: @@ -464,7 +465,7 @@ async def test_release_waiter_release_first(loop, key, key2) -> None: conn._release_waiter() assert w1.set_result.called assert not w2.set_result.called - conn.close() + await conn.close() async def test_release_waiter_skip_done_waiter(loop, key, key2) -> None: @@ -476,7 +477,7 @@ async def test_release_waiter_skip_done_waiter(loop, key, key2) -> None: conn._release_waiter() assert not w1.set_result.called assert w2.set_result.called - conn.close() + await conn.close() async def test_release_waiter_per_host(loop, key, key2) -> None: @@ -491,7 +492,7 @@ async def test_release_waiter_per_host(loop, key, key2) -> None: assert (w1.set_result.called and not w2.set_result.called) or ( not w1.set_result.called and w2.set_result.called ) - conn.close() + await conn.close() async def test_release_waiter_no_available(loop, key, key2) -> None: @@ -504,7 +505,7 @@ async def test_release_waiter_no_available(loop, key, key2) -> None: conn._release_waiter() assert len(conn._waiters) == 1 assert not w.done.called - conn.close() + await conn.close() async def test_release_close(loop, key) -> None: @@ -657,7 +658,7 @@ def get_extra_info(param): conn._loop.create_connection = create_connection - await conn.connect(req, [], ClientTimeout()) + established_connection = await conn.connect(req, [], ClientTimeout()) assert ips == ips_tried assert os_error @@ -666,6 +667,8 @@ def get_extra_info(param): assert fingerprint_error assert connected + established_connection.close() + async def test_tcp_connector_resolve_host(loop) -> None: conn = aiohttp.TCPConnector(loop=loop, use_dns_cache=True) @@ -761,7 +764,7 @@ async def test_tcp_connector_dns_throttle_requests_cancelled_when_close( f = loop.create_task(conn._resolve_host("localhost", 8080)) await asyncio.sleep(0) - conn.close() + await conn.close() with pytest.raises(asyncio.CancelledError): await f @@ -976,7 +979,7 @@ async def test_release_close_do_not_delete_existing_connections(key) -> None: conn._release(key, proto) assert conn._conns[key] == [(proto1, 1)] assert proto.close.called - conn.close() + await conn.close() async def test_release_not_started(loop) -> None: @@ -990,7 +993,7 @@ async def test_release_not_started(loop) -> None: assert rec[0][0] == proto assert rec[0][1] == pytest.approx(loop.time(), abs=0.05) assert not proto.close.called - conn.close() + await conn.close() async def test_release_not_opened(loop, key) -> None: @@ -1070,7 +1073,7 @@ async def test_close_during_connect(loop) -> None: task = loop.create_task(conn.connect(req, None, ClientTimeout())) await asyncio.sleep(0) - conn.close() + await conn.close() fut.set_result(proto) with pytest.raises(aiohttp.ClientConnectionError): @@ -1139,7 +1142,7 @@ async def test_cleanup2() -> None: assert conn._cleanup_handle is not None loop.call_at.assert_called_with(310, mock.ANY, mock.ANY) - conn.close() + await conn.close() async def test_cleanup3(key) -> None: @@ -1157,7 +1160,7 @@ async def test_cleanup3(key) -> None: assert conn._cleanup_handle is not None loop.call_at.assert_called_with(319, mock.ANY, mock.ANY) - conn.close() + await conn.close() async def test_cleanup_closed(loop, mocker) -> None: @@ -1262,7 +1265,7 @@ async def test___get_ssl_context1(loop) -> None: async def test___get_ssl_context2(loop) -> None: - ctx = ssl.SSLContext() + ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) conn = aiohttp.TCPConnector(loop=loop) req = mock.Mock() req.is_ssl.return_value = True @@ -1271,7 +1274,7 @@ async def test___get_ssl_context2(loop) -> None: async def test___get_ssl_context3(loop) -> None: - ctx = ssl.SSLContext() + ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) conn = aiohttp.TCPConnector(loop=loop, ssl=ctx) req = mock.Mock() req.is_ssl.return_value = True @@ -1280,7 +1283,7 @@ async def test___get_ssl_context3(loop) -> None: async def test___get_ssl_context4(loop) -> None: - ctx = ssl.SSLContext() + ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) conn = aiohttp.TCPConnector(loop=loop, ssl=ctx) req = mock.Mock() req.is_ssl.return_value = True @@ -1289,7 +1292,7 @@ async def test___get_ssl_context4(loop) -> None: async def test___get_ssl_context5(loop) -> None: - ctx = ssl.SSLContext() + ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) conn = aiohttp.TCPConnector(loop=loop, ssl=ctx) req = mock.Mock() req.is_ssl.return_value = True @@ -1310,14 +1313,14 @@ async def test_close_twice(loop) -> None: conn = aiohttp.BaseConnector(loop=loop) conn._conns[1] = [(proto, object())] - conn.close() + await conn.close() assert not conn._conns assert proto.close.called assert conn.closed conn._conns = "Invalid" # fill with garbage - conn.close() + await conn.close() assert conn.closed @@ -1325,7 +1328,7 @@ async def test_close_cancels_cleanup_handle(loop) -> None: conn = aiohttp.BaseConnector(loop=loop) conn._release(1, mock.Mock(should_close=False)) assert conn._cleanup_handle is not None - conn.close() + await conn.close() assert conn._cleanup_handle is None @@ -1334,7 +1337,7 @@ async def test_close_abort_closed_transports(loop) -> None: conn = aiohttp.BaseConnector(loop=loop) conn._cleanup_closed_transports.append(tr) - conn.close() + await conn.close() assert not conn._cleanup_closed_transports assert tr.abort.called @@ -1344,7 +1347,7 @@ async def test_close_abort_closed_transports(loop) -> None: async def test_close_cancels_cleanup_closed_handle(loop) -> None: conn = aiohttp.BaseConnector(loop=loop, enable_cleanup_closed=True) assert conn._cleanup_closed_handle is not None - conn.close() + await conn.close() assert conn._cleanup_closed_handle is None @@ -1393,7 +1396,7 @@ async def f(): await asyncio.sleep(0) assert acquired await task - conn.close() + await conn.close() async def test_connect_queued_operation_tracing(loop, key) -> None: @@ -1439,7 +1442,7 @@ async def f(): await asyncio.sleep(0.01) connection1.release() await task - conn.close() + await conn.close() async def test_connect_reuseconn_tracing(loop, key) -> None: @@ -1469,7 +1472,7 @@ async def test_connect_reuseconn_tracing(loop, key) -> None: on_connection_reuseconn.assert_called_with( session, trace_config_ctx, aiohttp.TraceConnectionReuseconnParams() ) - conn.close() + await conn.close() async def test_connect_with_limit_and_limit_per_host(loop, key) -> None: @@ -1503,7 +1506,7 @@ async def f(): await asyncio.sleep(0) assert acquired await task - conn.close() + await conn.close() async def test_connect_with_no_limit_and_limit_per_host(loop, key) -> None: @@ -1535,7 +1538,7 @@ async def f(): await asyncio.sleep(0) assert acquired await task - conn.close() + await conn.close() async def test_connect_with_no_limits(loop, key) -> None: @@ -1567,7 +1570,7 @@ async def f(): assert acquired connection1.release() await task - conn.close() + await conn.close() async def test_connect_with_limit_cancelled(loop) -> None: @@ -1595,6 +1598,8 @@ async def test_connect_with_limit_cancelled(loop) -> None: await asyncio.wait_for(conn.connect(req, None, ClientTimeout()), 0.01) connection.close() + await conn.close() + async def test_connect_with_capacity_release_waiters(loop) -> None: def check_with_exc(err): @@ -1668,7 +1673,7 @@ async def f(start=True): await asyncio.wait(tasks) await f() - conn.close() + await conn.close() assert max_connections == num_connections @@ -1731,7 +1736,7 @@ async def test_close_with_acquired_connection(loop) -> None: connection = await conn.connect(req, None, ClientTimeout()) assert 1 == len(conn._acquired) - conn.close() + await conn.close() assert 0 == len(conn._acquired) assert conn.closed proto.close.assert_called_with() @@ -1750,26 +1755,26 @@ async def test_limit_property(loop) -> None: conn = aiohttp.BaseConnector(loop=loop, limit=15) assert 15 == conn.limit - conn.close() + await conn.close() async def test_limit_per_host_property(loop) -> None: conn = aiohttp.BaseConnector(loop=loop, limit_per_host=15) assert 15 == conn.limit_per_host - conn.close() + await conn.close() async def test_limit_property_default(loop) -> None: conn = aiohttp.BaseConnector(loop=loop) assert conn.limit == 100 - conn.close() + await conn.close() async def test_limit_per_host_property_default(loop) -> None: conn = aiohttp.BaseConnector(loop=loop) assert conn.limit_per_host == 0 - conn.close() + await conn.close() async def test_force_close_and_explicit_keep_alive(loop) -> None: @@ -1910,7 +1915,7 @@ async def handler(request): assert r.status == 200 -@pytest.mark.skipif(not hasattr(socket, "AF_UNIX"), reason="requires unix socket") +@needs_unix async def test_unix_connector_not_found(loop) -> None: connector = aiohttp.UnixConnector("/" + uuid.uuid4().hex, loop=loop) @@ -1919,7 +1924,7 @@ async def test_unix_connector_not_found(loop) -> None: await connector.connect(req, None, ClientTimeout()) -@pytest.mark.skipif(not hasattr(socket, "AF_UNIX"), reason="requires unix socket") +@needs_unix async def test_unix_connector_permission(loop) -> None: loop.create_unix_connection = make_mocked_coro(raise_exception=PermissionError()) connector = aiohttp.UnixConnector("/" + uuid.uuid4().hex, loop=loop) @@ -2051,7 +2056,7 @@ async def handler(request): r.close() await session.close() - conn.close() + await conn.close() async def test_tcp_connector_uses_provided_local_addr(aiohttp_server) -> None: @@ -2075,10 +2080,9 @@ async def handler(request): assert first_conn.transport.get_extra_info("sockname") == ("127.0.0.1", port) r.close() await session.close() - conn.close() + await conn.close() -@pytest.mark.skipif(not hasattr(socket, "AF_UNIX"), reason="requires UNIX sockets") async def test_unix_connector(unix_server, unix_sockname) -> None: async def handler(request): return web.Response() @@ -2260,3 +2264,5 @@ async def allow_connection_and_add_dummy_waiter(): await_connection_and_check_waiters(), allow_connection_and_add_dummy_waiter(), ) + + await connector.close() diff --git a/tests/test_cookiejar.py b/tests/test_cookiejar.py index 12bcebc..73e1253 100644 --- a/tests/test_cookiejar.py +++ b/tests/test_cookiejar.py @@ -25,7 +25,7 @@ def cookies_to_send(): "different-domain-cookie=sixth; Domain=different.org; " "secure-cookie=seventh; Domain=secure.com; Secure; " "no-path-cookie=eighth; Domain=pathtest.com; " - "path1-cookie=nineth; Domain=pathtest.com; Path=/; " + "path1-cookie=ninth; Domain=pathtest.com; Path=/; " "path2-cookie=tenth; Domain=pathtest.com; Path=/one; " "path3-cookie=eleventh; Domain=pathtest.com; Path=/one/two; " "path4-cookie=twelfth; Domain=pathtest.com; Path=/one/two/; " @@ -51,7 +51,7 @@ def cookies_to_send_with_expired(): "different-domain-cookie=sixth; Domain=different.org; " "secure-cookie=seventh; Domain=secure.com; Secure; " "no-path-cookie=eighth; Domain=pathtest.com; " - "path1-cookie=nineth; Domain=pathtest.com; Path=/; " + "path1-cookie=ninth; Domain=pathtest.com; Path=/; " "path2-cookie=tenth; Domain=pathtest.com; Path=/one; " "path3-cookie=eleventh; Domain=pathtest.com; Path=/one/two; " "path4-cookie=twelfth; Domain=pathtest.com; Path=/one/two/; " @@ -77,7 +77,7 @@ def cookies_to_receive(): "different-domain-cookie=sixth; Domain=different.org; Path=/; " "no-path-cookie=seventh; Domain=pathtest.com; " "path-cookie=eighth; Domain=pathtest.com; Path=/somepath; " - "wrong-path-cookie=nineth; Domain=pathtest.com; Path=somepath;" + "wrong-path-cookie=ninth; Domain=pathtest.com; Path=somepath;" ) @@ -244,7 +244,7 @@ async def test_domain_filter_ip_cookie_send(loop) -> None: "different-domain-cookie=sixth; Domain=different.org; " "secure-cookie=seventh; Domain=secure.com; Secure; " "no-path-cookie=eighth; Domain=pathtest.com; " - "path1-cookie=nineth; Domain=pathtest.com; Path=/; " + "path1-cookie=ninth; Domain=pathtest.com; Path=/; " "path2-cookie=tenth; Domain=pathtest.com; Path=/one; " "path3-cookie=eleventh; Domain=pathtest.com; Path=/one/two; " "path4-cookie=twelfth; Domain=pathtest.com; Path=/one/two/; " @@ -354,7 +354,7 @@ def setUp(self): "different-domain-cookie=sixth; Domain=different.org; " "secure-cookie=seventh; Domain=secure.com; Secure; " "no-path-cookie=eighth; Domain=pathtest.com; " - "path1-cookie=nineth; Domain=pathtest.com; Path=/; " + "path1-cookie=ninth; Domain=pathtest.com; Path=/; " "path2-cookie=tenth; Domain=pathtest.com; Path=/one; " "path3-cookie=eleventh; Domain=pathtest.com; Path=/one/two; " "path4-cookie=twelfth; Domain=pathtest.com; Path=/one/two/; " @@ -377,7 +377,7 @@ def setUp(self): "different-domain-cookie=sixth; Domain=different.org; Path=/; " "no-path-cookie=seventh; Domain=pathtest.com; " "path-cookie=eighth; Domain=pathtest.com; Path=/somepath; " - "wrong-path-cookie=nineth; Domain=pathtest.com; Path=somepath;" + "wrong-path-cookie=ninth; Domain=pathtest.com; Path=somepath;" ) async def make_jar(): @@ -664,6 +664,56 @@ async def make_jar(): # Assert that there is a cookie. assert len(jar) == 1 + def test_path_filter_diff_folder_same_name(self) -> None: + async def make_jar(): + return CookieJar(unsafe=True) + + jar = self.loop.run_until_complete(make_jar()) + + jar.update_cookies( + SimpleCookie("path-cookie=zero; Domain=pathtest.com; Path=/; ") + ) + jar.update_cookies( + SimpleCookie("path-cookie=one; Domain=pathtest.com; Path=/one; ") + ) + self.assertEqual(len(jar), 2) + + jar_filtered = jar.filter_cookies(URL("http://pathtest.com/")) + self.assertEqual(len(jar_filtered), 1) + self.assertEqual(jar_filtered["path-cookie"].value, "zero") + + jar_filtered = jar.filter_cookies(URL("http://pathtest.com/one")) + self.assertEqual(len(jar_filtered), 1) + self.assertEqual(jar_filtered["path-cookie"].value, "one") + + def test_filter_cookies_order_by_path(self) -> None: + async def make_jar(): + return CookieJar(unsafe=True) + + jar = self.loop.run_until_complete(make_jar()) + jar.update_cookies( + SimpleCookie("path-cookie=one; Domain=pathtest.com; Path=/one; ") + ) + jar.update_cookies( + SimpleCookie("path-cookie=zero; Domain=pathtest.com; Path=/; ") + ) + jar.update_cookies( + SimpleCookie("path-cookie=two; Domain=pathtest.com; Path=/second; ") + ) + self.assertEqual(len(jar), 3) + + jar_filtered = jar.filter_cookies(URL("http://pathtest.com/")) + self.assertEqual(len(jar_filtered), 1) + self.assertEqual(jar_filtered["path-cookie"].value, "zero") + + jar_filtered = jar.filter_cookies(URL("http://pathtest.com/second")) + self.assertEqual(len(jar_filtered), 1) + self.assertEqual(jar_filtered["path-cookie"].value, "two") + + jar_filtered = jar.filter_cookies(URL("http://pathtest.com/one")) + self.assertEqual(len(jar_filtered), 1) + self.assertEqual(jar_filtered["path-cookie"].value, "one") + async def test_dummy_cookie_jar() -> None: cookie = SimpleCookie("foo=bar; Domain=example.com;") @@ -694,3 +744,80 @@ async def test_loose_cookies_types() -> None: for loose_cookies_type in accepted_types: jar.update_cookies(cookies=loose_cookies_type) + + +async def test_cookie_jar_clear_all(): + sut = CookieJar() + cookie = SimpleCookie() + cookie["foo"] = "bar" + sut.update_cookies(cookie) + + sut.clear() + assert len(sut) == 0 + + +async def test_cookie_jar_clear_expired(): + sut = CookieJar() + + cookie = SimpleCookie() + + cookie["foo"] = "bar" + cookie["foo"]["expires"] = "Tue, 1 Jan 1990 12:00:00 GMT" + + with freeze_time("1980-01-01"): + sut.update_cookies(cookie) + + sut.clear(lambda x: False) + with freeze_time("1980-01-01"): + assert len(sut) == 0 + + +async def test_cookie_jar_clear_domain(): + sut = CookieJar() + cookie = SimpleCookie() + cookie["foo"] = "bar" + cookie["domain_cookie"] = "value" + cookie["domain_cookie"]["domain"] = "example.com" + cookie["subdomain_cookie"] = "value" + cookie["subdomain_cookie"]["domain"] = "test.example.com" + sut.update_cookies(cookie) + + sut.clear_domain("example.com") + iterator = iter(sut) + morsel = next(iterator) + assert morsel.key == "foo" + assert morsel.value == "bar" + with pytest.raises(StopIteration): + next(iterator) + + +@pytest.mark.parametrize( + "url", + [ + "http://127.0.0.1/index.html", + URL("http://127.0.0.1/index.html"), + ["http://127.0.0.1/index.html"], + [URL("http://127.0.0.1/index.html")], + ], +) +async def test_treat_as_secure_origin_init(url) -> None: + jar = CookieJar(unsafe=True, treat_as_secure_origin=url) + assert jar._treat_as_secure_origin == [URL("http://127.0.0.1")] + + +async def test_treat_as_secure_origin() -> None: + endpoint = URL("http://127.0.0.1/") + + jar = CookieJar(unsafe=True, treat_as_secure_origin=[endpoint]) + secure_cookie = SimpleCookie( + "cookie-key=cookie-value; HttpOnly; Path=/; Secure", + ) + + jar.update_cookies( + secure_cookie, + endpoint, + ) + + assert len(jar) == 1 + filtered_cookies = jar.filter_cookies(request_url=endpoint) + assert len(filtered_cookies) == 1 diff --git a/tests/test_formdata.py b/tests/test_formdata.py index 987a262..4bb8aa0 100644 --- a/tests/test_formdata.py +++ b/tests/test_formdata.py @@ -2,7 +2,7 @@ import pytest -from aiohttp import ClientSession, FormData +from aiohttp import FormData, web @pytest.fixture @@ -72,28 +72,36 @@ def test_invalid_formdata_content_transfer_encoding() -> None: async def test_formdata_field_name_is_quoted(buf, writer) -> None: form = FormData(charset="ascii") - form.add_field("emails[]", "xxx@x.co", content_type="multipart/form-data") + form.add_field("email 1", "xxx@x.co", content_type="multipart/form-data") payload = form() await payload.write(writer) - assert b'name="emails%5B%5D"' in buf + assert b'name="email\\ 1"' in buf async def test_formdata_field_name_is_not_quoted(buf, writer) -> None: form = FormData(quote_fields=False, charset="ascii") - form.add_field("emails[]", "xxx@x.co", content_type="multipart/form-data") + form.add_field("email 1", "xxx@x.co", content_type="multipart/form-data") payload = form() await payload.write(writer) - assert b'name="emails[]"' in buf + assert b'name="email 1"' in buf -async def test_mark_formdata_as_processed() -> None: - async with ClientSession() as session: - url = "http://httpbin.org/anything" - data = FormData() - data.add_field("test", "test_value", content_type="application/json") +async def test_mark_formdata_as_processed(aiohttp_client) -> None: + async def handler(request): + return web.Response() - await session.post(url, data=data) - assert len(data._writer._parts) == 1 + app = web.Application() + app.add_routes([web.post("/", handler)]) - with pytest.raises(RuntimeError): - await session.post(url, data=data) + client = await aiohttp_client(app) + + data = FormData() + data.add_field("test", "test_value", content_type="application/json") + + resp = await client.post("/", data=data) + assert len(data._writer._parts) == 1 + + with pytest.raises(RuntimeError): + await client.post("/", data=data) + + resp.release() diff --git a/tests/test_frozenlist.py b/tests/test_frozenlist.py deleted file mode 100644 index 68241a2..0000000 --- a/tests/test_frozenlist.py +++ /dev/null @@ -1,230 +0,0 @@ -from collections.abc import MutableSequence - -import pytest - -from aiohttp.frozenlist import FrozenList, PyFrozenList - - -class FrozenListMixin: - FrozenList = NotImplemented - - SKIP_METHODS = {"__abstractmethods__", "__slots__"} - - def test_subclass(self) -> None: - assert issubclass(self.FrozenList, MutableSequence) - - def test_iface(self) -> None: - for name in set(dir(MutableSequence)) - self.SKIP_METHODS: - if ( - name.startswith("_") and not name.endswith("_") - ) or name == "__class_getitem__": - continue - assert hasattr(self.FrozenList, name) - - def test_ctor_default(self) -> None: - _list = self.FrozenList([]) - assert not _list.frozen - - def test_ctor(self) -> None: - _list = self.FrozenList([1]) - assert not _list.frozen - - def test_ctor_copy_list(self) -> None: - orig = [1] - _list = self.FrozenList(orig) - del _list[0] - assert _list != orig - - def test_freeze(self) -> None: - _list = self.FrozenList() - _list.freeze() - assert _list.frozen - - def test_repr(self) -> None: - _list = self.FrozenList([1]) - assert repr(_list) == "" - _list.freeze() - assert repr(_list) == "" - - def test_getitem(self) -> None: - _list = self.FrozenList([1, 2]) - assert _list[1] == 2 - - def test_setitem(self) -> None: - _list = self.FrozenList([1, 2]) - _list[1] = 3 - assert _list[1] == 3 - - def test_delitem(self) -> None: - _list = self.FrozenList([1, 2]) - del _list[0] - assert len(_list) == 1 - assert _list[0] == 2 - - def test_len(self) -> None: - _list = self.FrozenList([1]) - assert len(_list) == 1 - - def test_iter(self) -> None: - _list = self.FrozenList([1, 2]) - assert list(iter(_list)) == [1, 2] - - def test_reversed(self) -> None: - _list = self.FrozenList([1, 2]) - assert list(reversed(_list)) == [2, 1] - - def test_eq(self) -> None: - _list = self.FrozenList([1]) - assert _list == [1] - - def test_ne(self) -> None: - _list = self.FrozenList([1]) - assert _list != [2] - - def test_le(self) -> None: - _list = self.FrozenList([1]) - assert _list <= [1] - - def test_lt(self) -> None: - _list = self.FrozenList([1]) - assert _list <= [3] - - def test_ge(self) -> None: - _list = self.FrozenList([1]) - assert _list >= [1] - - def test_gt(self) -> None: - _list = self.FrozenList([2]) - assert _list > [1] - - def test_insert(self) -> None: - _list = self.FrozenList([2]) - _list.insert(0, 1) - assert _list == [1, 2] - - def test_frozen_setitem(self) -> None: - _list = self.FrozenList([1]) - _list.freeze() - with pytest.raises(RuntimeError): - _list[0] = 2 - - def test_frozen_delitem(self) -> None: - _list = self.FrozenList([1]) - _list.freeze() - with pytest.raises(RuntimeError): - del _list[0] - - def test_frozen_insert(self) -> None: - _list = self.FrozenList([1]) - _list.freeze() - with pytest.raises(RuntimeError): - _list.insert(0, 2) - - def test_contains(self) -> None: - _list = self.FrozenList([2]) - assert 2 in _list - - def test_iadd(self) -> None: - _list = self.FrozenList([1]) - _list += [2] - assert _list == [1, 2] - - def test_iadd_frozen(self) -> None: - _list = self.FrozenList([1]) - _list.freeze() - with pytest.raises(RuntimeError): - _list += [2] - assert _list == [1] - - def test_index(self) -> None: - _list = self.FrozenList([1]) - assert _list.index(1) == 0 - - def test_remove(self) -> None: - _list = self.FrozenList([1]) - _list.remove(1) - assert len(_list) == 0 - - def test_remove_frozen(self) -> None: - _list = self.FrozenList([1]) - _list.freeze() - with pytest.raises(RuntimeError): - _list.remove(1) - assert _list == [1] - - def test_clear(self) -> None: - _list = self.FrozenList([1]) - _list.clear() - assert len(_list) == 0 - - def test_clear_frozen(self) -> None: - _list = self.FrozenList([1]) - _list.freeze() - with pytest.raises(RuntimeError): - _list.clear() - assert _list == [1] - - def test_extend(self) -> None: - _list = self.FrozenList([1]) - _list.extend([2]) - assert _list == [1, 2] - - def test_extend_frozen(self) -> None: - _list = self.FrozenList([1]) - _list.freeze() - with pytest.raises(RuntimeError): - _list.extend([2]) - assert _list == [1] - - def test_reverse(self) -> None: - _list = self.FrozenList([1, 2]) - _list.reverse() - assert _list == [2, 1] - - def test_reverse_frozen(self) -> None: - _list = self.FrozenList([1, 2]) - _list.freeze() - with pytest.raises(RuntimeError): - _list.reverse() - assert _list == [1, 2] - - def test_pop(self) -> None: - _list = self.FrozenList([1, 2]) - assert _list.pop(0) == 1 - assert _list == [2] - - def test_pop_default(self) -> None: - _list = self.FrozenList([1, 2]) - assert _list.pop() == 2 - assert _list == [1] - - def test_pop_frozen(self) -> None: - _list = self.FrozenList([1, 2]) - _list.freeze() - with pytest.raises(RuntimeError): - _list.pop() - assert _list == [1, 2] - - def test_append(self) -> None: - _list = self.FrozenList([1, 2]) - _list.append(3) - assert _list == [1, 2, 3] - - def test_append_frozen(self) -> None: - _list = self.FrozenList([1, 2]) - _list.freeze() - with pytest.raises(RuntimeError): - _list.append(3) - assert _list == [1, 2] - - def test_count(self) -> None: - _list = self.FrozenList([1, 2]) - assert _list.count(1) == 1 - - -class TestFrozenList(FrozenListMixin): - FrozenList = FrozenList - - -class TestFrozenListPy(FrozenListMixin): - FrozenList = PyFrozenList diff --git a/tests/test_helpers.py b/tests/test_helpers.py index 3367c24..6099afa 100644 --- a/tests/test_helpers.py +++ b/tests/test_helpers.py @@ -1,18 +1,20 @@ import asyncio import base64 +import datetime import gc -import os import platform -import sys import tempfile from math import isclose, modf +from pathlib import Path from unittest import mock +from urllib.request import getproxies_environment import pytest from multidict import MultiDict from yarl import URL from aiohttp import helpers +from aiohttp.helpers import parse_http_date IS_PYPY = platform.python_implementation() == "PyPy" @@ -160,7 +162,7 @@ def test_basic_auth_decode_invalid_credentials() -> None: ), ) def test_basic_auth_decode_blank_username(credentials, expected_auth) -> None: - header = "Basic {}".format(base64.b64encode(credentials.encode()).decode()) + header = f"Basic {base64.b64encode(credentials.encode()).decode()}" assert helpers.BasicAuth.decode(header) == expected_auth @@ -177,7 +179,6 @@ def test_basic_auth_from_not_url() -> None: class ReifyMixin: - reify = NotImplemented def test_reify(self) -> None: @@ -350,7 +351,7 @@ def test_timeout_handle_cb_exc(loop) -> None: assert not handle._callbacks -def test_timer_context_cancelled() -> None: +def test_timer_context_not_cancelled() -> None: with mock.patch("aiohttp.helpers.asyncio") as m_asyncio: m_asyncio.TimeoutError = asyncio.TimeoutError loop = mock.Mock() @@ -362,9 +363,9 @@ def test_timer_context_cancelled() -> None: pass if helpers.PY_37: - assert m_asyncio.current_task.return_value.cancel.called + assert not m_asyncio.current_task.return_value.cancel.called else: - assert m_asyncio.Task.current_task.return_value.cancel.called + assert not m_asyncio.Task.current_task.return_value.cancel.called def test_timer_context_no_task(loop) -> None: @@ -391,48 +392,22 @@ async def test_weakref_handle_weak(loop) -> None: await asyncio.sleep(0.1) -def test_ceil_call_later() -> None: - cb = mock.Mock() - loop = mock.Mock() - loop.time.return_value = 10.1 - helpers.call_later(cb, 10.1, loop) - loop.call_at.assert_called_with(21.0, cb) - - -def test_ceil_call_later_no_timeout() -> None: - cb = mock.Mock() - loop = mock.Mock() - helpers.call_later(cb, 0, loop) - assert not loop.call_at.called - - -async def test_ceil_timeout(loop) -> None: - with helpers.CeilTimeout(None, loop=loop) as timeout: - assert timeout._timeout is None - assert timeout._cancel_handler is None - - -def test_ceil_timeout_no_task(loop) -> None: - with pytest.raises(RuntimeError): - with helpers.CeilTimeout(10, loop=loop): - pass +async def test_ceil_timeout() -> None: + async with helpers.ceil_timeout(None) as timeout: + assert timeout.deadline is None -@pytest.mark.skipif( - sys.version_info < (3, 7), reason="TimerHandle.when() doesn't exist" -) -async def test_ceil_timeout_round(loop) -> None: - with helpers.CeilTimeout(7.5, loop=loop) as cm: - frac, integer = modf(cm._cancel_handler.when()) +async def test_ceil_timeout_round() -> None: + async with helpers.ceil_timeout(7.5) as cm: + assert cm.deadline is not None + frac, integer = modf(cm.deadline) assert frac == 0 -@pytest.mark.skipif( - sys.version_info < (3, 7), reason="TimerHandle.when() doesn't exist" -) -async def test_ceil_timeout_small(loop) -> None: - with helpers.CeilTimeout(1.1, loop=loop) as cm: - frac, integer = modf(cm._cancel_handler.when()) +async def test_ceil_timeout_small() -> None: + async with helpers.ceil_timeout(1.1) as cm: + assert cm.deadline is not None + frac, integer = modf(cm.deadline) # a chance for exact integer with zero fraction is negligible assert frac != 0 @@ -440,11 +415,25 @@ async def test_ceil_timeout_small(loop) -> None: # -------------------------------- ContentDisposition ------------------- -def test_content_disposition() -> None: - assert ( - helpers.content_disposition_header("attachment", foo="bar") - == 'attachment; foo="bar"' - ) +@pytest.mark.parametrize( + "kwargs, result", + [ + (dict(foo="bar"), 'attachment; foo="bar"'), + (dict(foo="bar[]"), 'attachment; foo="bar[]"'), + (dict(foo=' a""b\\'), 'attachment; foo="\\ a\\"\\"b\\\\"'), + (dict(foo="bär"), "attachment; foo*=utf-8''b%C3%A4r"), + (dict(foo='bär "\\', quote_fields=False), 'attachment; foo="bär \\"\\\\"'), + (dict(foo="bär", _charset="latin-1"), "attachment; foo*=latin-1''b%E4r"), + (dict(filename="bär"), 'attachment; filename="b%C3%A4r"'), + (dict(filename="bär", _charset="latin-1"), 'attachment; filename="b%E4r"'), + ( + dict(filename='bär "\\', quote_fields=False), + 'attachment; filename="bär \\"\\\\"', + ), + ], +) +def test_content_disposition(kwargs, result) -> None: + assert helpers.content_disposition_header("attachment", **kwargs) == result def test_content_disposition_bad_type() -> None: @@ -472,41 +461,69 @@ def test_set_content_disposition_bad_param() -> None: # --------------------- proxies_from_env ------------------------------ -def test_proxies_from_env_http(mocker) -> None: - url = URL("http://aiohttp.io/path") - mocker.patch.dict(os.environ, {"http_proxy": str(url)}) - ret = helpers.proxies_from_env() - assert ret.keys() == {"http"} - assert ret["http"].proxy == url - assert ret["http"].proxy_auth is None - - -def test_proxies_from_env_http_proxy_for_https_proto(mocker) -> None: - url = URL("http://aiohttp.io/path") - mocker.patch.dict(os.environ, {"https_proxy": str(url)}) +@pytest.mark.parametrize( + ("proxy_env_vars", "url_input", "expected_scheme"), + ( + ({"http_proxy": "http://aiohttp.io/path"}, "http://aiohttp.io/path", "http"), + ({"https_proxy": "http://aiohttp.io/path"}, "http://aiohttp.io/path", "https"), + ({"ws_proxy": "http://aiohttp.io/path"}, "http://aiohttp.io/path", "ws"), + ({"wss_proxy": "http://aiohttp.io/path"}, "http://aiohttp.io/path", "wss"), + ), + indirect=["proxy_env_vars"], + ids=("http", "https", "ws", "wss"), +) +@pytest.mark.usefixtures("proxy_env_vars") +def test_proxies_from_env(url_input, expected_scheme) -> None: + url = URL(url_input) ret = helpers.proxies_from_env() - assert ret.keys() == {"https"} - assert ret["https"].proxy == url - assert ret["https"].proxy_auth is None + assert ret.keys() == {expected_scheme} + assert ret[expected_scheme].proxy == url + assert ret[expected_scheme].proxy_auth is None -def test_proxies_from_env_https_proxy_skipped(mocker) -> None: - url = URL("https://aiohttp.io/path") - mocker.patch.dict(os.environ, {"https_proxy": str(url)}) - log = mocker.patch("aiohttp.log.client_logger.warning") +@pytest.mark.parametrize( + ("proxy_env_vars", "url_input", "expected_scheme"), + ( + ( + {"https_proxy": "https://aiohttp.io/path"}, + "https://aiohttp.io/path", + "https", + ), + ({"wss_proxy": "wss://aiohttp.io/path"}, "wss://aiohttp.io/path", "wss"), + ), + indirect=["proxy_env_vars"], + ids=("https", "wss"), +) +@pytest.mark.usefixtures("proxy_env_vars") +def test_proxies_from_env_skipped(caplog, url_input, expected_scheme) -> None: + url = URL(url_input) assert helpers.proxies_from_env() == {} - log.assert_called_with( - "HTTPS proxies %s are not supported, ignoring", URL("https://aiohttp.io/path") + assert len(caplog.records) == 1 + log_message = "{proto!s} proxies {url!s} are not supported, ignoring".format( + proto=expected_scheme.upper(), url=url ) + assert caplog.record_tuples == [("aiohttp.client", 30, log_message)] -def test_proxies_from_env_http_with_auth(mocker) -> None: +@pytest.mark.parametrize( + ("proxy_env_vars", "url_input", "expected_scheme"), + ( + ( + {"http_proxy": "http://user:pass@aiohttp.io/path"}, + "http://user:pass@aiohttp.io/path", + "http", + ), + ), + indirect=["proxy_env_vars"], + ids=("http",), +) +@pytest.mark.usefixtures("proxy_env_vars") +def test_proxies_from_env_http_with_auth(url_input, expected_scheme) -> None: url = URL("http://user:pass@aiohttp.io/path") - mocker.patch.dict(os.environ, {"http_proxy": str(url)}) ret = helpers.proxies_from_env() - assert ret.keys() == {"http"} - assert ret["http"].proxy == url.with_user(None) - proxy_auth = ret["http"].proxy_auth + assert ret.keys() == {expected_scheme} + assert ret[expected_scheme].proxy == url.with_user(None) + proxy_auth = ret[expected_scheme].proxy_auth assert proxy_auth.login == "user" assert proxy_auth.password == "pass" assert proxy_auth.encoding == "latin1" @@ -524,6 +541,96 @@ async def test_get_running_loop_ok(loop) -> None: assert helpers.get_running_loop() is loop +# --------------------- get_env_proxy_for_url ------------------------------ + + +@pytest.fixture +def proxy_env_vars(monkeypatch, request): + for schema in getproxies_environment().keys(): + monkeypatch.delenv(f"{schema}_proxy", False) + + for proxy_type, proxy_list in request.param.items(): + monkeypatch.setenv(proxy_type, proxy_list) + + return request.param + + +@pytest.mark.parametrize( + ("proxy_env_vars", "url_input", "expected_err_msg"), + ( + ( + {"no_proxy": "aiohttp.io"}, + "http://aiohttp.io/path", + r"Proxying is disallowed for `'aiohttp.io'`", + ), + ( + {"no_proxy": "aiohttp.io,proxy.com"}, + "http://aiohttp.io/path", + r"Proxying is disallowed for `'aiohttp.io'`", + ), + ( + {"http_proxy": "http://example.com"}, + "https://aiohttp.io/path", + r"No proxies found for `https://aiohttp.io/path` in the env", + ), + ( + {"https_proxy": "https://example.com"}, + "http://aiohttp.io/path", + r"No proxies found for `http://aiohttp.io/path` in the env", + ), + ( + {}, + "https://aiohttp.io/path", + r"No proxies found for `https://aiohttp.io/path` in the env", + ), + ( + {"https_proxy": "https://example.com"}, + "", + r"No proxies found for `` in the env", + ), + ), + indirect=["proxy_env_vars"], + ids=( + "url_matches_the_no_proxy_list", + "url_matches_the_no_proxy_list_multiple", + "url_scheme_does_not_match_http_proxy_list", + "url_scheme_does_not_match_https_proxy_list", + "no_proxies_are_set", + "url_is_empty", + ), +) +@pytest.mark.usefixtures("proxy_env_vars") +def test_get_env_proxy_for_url_negative(url_input, expected_err_msg) -> None: + url = URL(url_input) + with pytest.raises(LookupError, match=expected_err_msg): + helpers.get_env_proxy_for_url(url) + + +@pytest.mark.parametrize( + ("proxy_env_vars", "url_input"), + ( + ({"http_proxy": "http://example.com"}, "http://aiohttp.io/path"), + ({"https_proxy": "http://example.com"}, "https://aiohttp.io/path"), + ( + {"http_proxy": "http://example.com,http://proxy.org"}, + "http://aiohttp.io/path", + ), + ), + indirect=["proxy_env_vars"], + ids=( + "url_scheme_match_http_proxy_list", + "url_scheme_match_https_proxy_list", + "url_scheme_match_http_proxy_list_multiple", + ), +) +def test_get_env_proxy_for_url(proxy_env_vars, url_input) -> None: + url = URL(url_input) + proxy, proxy_auth = helpers.get_env_proxy_for_url(url) + proxy_list = proxy_env_vars[url.scheme + "_proxy"] + assert proxy == URL(proxy_list) + assert proxy_auth is None + + # ------------- set_result / set_exception ---------------------- @@ -631,3 +738,48 @@ def test_repr(self) -> None: cp = helpers.ChainMapProxy([d1, d2]) expected = f"ChainMapProxy({d1!r}, {d2!r})" assert expected == repr(cp) + + +@pytest.mark.parametrize( + ["value", "expected"], + [ + # email.utils.parsedate returns None + pytest.param("xxyyzz", None), + # datetime.datetime fails with ValueError("year 4446413 is out of range") + pytest.param("Tue, 08 Oct 4446413 00:56:40 GMT", None), + # datetime.datetime fails with ValueError("second must be in 0..59") + pytest.param("Tue, 08 Oct 2000 00:56:80 GMT", None), + # OK + pytest.param( + "Tue, 08 Oct 2000 00:56:40 GMT", + datetime.datetime(2000, 10, 8, 0, 56, 40, tzinfo=datetime.timezone.utc), + ), + # OK (ignore timezone and overwrite to UTC) + pytest.param( + "Tue, 08 Oct 2000 00:56:40 +0900", + datetime.datetime(2000, 10, 8, 0, 56, 40, tzinfo=datetime.timezone.utc), + ), + ], +) +def test_parse_http_date(value, expected): + assert parse_http_date(value) == expected + + +@pytest.fixture +def protected_dir(tmp_path: Path): + protected_dir = tmp_path / "protected" + protected_dir.mkdir() + try: + protected_dir.chmod(0o600) + yield protected_dir + finally: + protected_dir.rmdir() + + +def test_netrc_from_home_does_not_raise_if_access_denied( + protected_dir: Path, monkeypatch: pytest.MonkeyPatch +): + monkeypatch.setattr(Path, "home", lambda: protected_dir) + monkeypatch.delenv("NETRC", raising=False) + + helpers.netrc_from_env() diff --git a/tests/test_http_exceptions.py b/tests/test_http_exceptions.py index 26a5adb..29d5b91 100644 --- a/tests/test_http_exceptions.py +++ b/tests/test_http_exceptions.py @@ -31,13 +31,13 @@ def test_str(self) -> None: err = http_exceptions.HttpProcessingError( code=500, message="Internal error", headers={} ) - assert str(err) == "500, message='Internal error'" + assert str(err) == "500, message:\n Internal error" def test_repr(self) -> None: err = http_exceptions.HttpProcessingError( code=500, message="Internal error", headers={} ) - assert repr(err) == ("") + assert repr(err) == ("") class TestBadHttpMessage: @@ -60,7 +60,7 @@ def test_pickle(self) -> None: def test_str(self) -> None: err = http_exceptions.BadHttpMessage(message="Bad HTTP message", headers={}) - assert str(err) == "400, message='Bad HTTP message'" + assert str(err) == "400, message:\n Bad HTTP message" def test_repr(self) -> None: err = http_exceptions.BadHttpMessage(message="Bad HTTP message", headers={}) @@ -87,9 +87,8 @@ def test_pickle(self) -> None: def test_str(self) -> None: err = http_exceptions.LineTooLong(line="spam", limit="10", actual_size="12") - assert str(err) == ( - "400, message='Got more than 10 bytes (12) " "when reading spam.'" - ) + expected = "400, message:\n Got more than 10 bytes (12) when reading spam." + assert str(err) == expected def test_repr(self) -> None: err = http_exceptions.LineTooLong(line="spam", limit="10", actual_size="12") @@ -119,25 +118,24 @@ def test_pickle(self) -> None: def test_str(self) -> None: err = http_exceptions.InvalidHeader(hdr="X-Spam") - assert str(err) == "400, message='Invalid HTTP Header: X-Spam'" + assert str(err) == "400, message:\n Invalid HTTP Header: X-Spam" def test_repr(self) -> None: err = http_exceptions.InvalidHeader(hdr="X-Spam") - assert repr(err) == ( - "" - ) + expected = "" + assert repr(err) == expected class TestBadStatusLine: def test_ctor(self) -> None: err = http_exceptions.BadStatusLine("Test") assert err.line == "Test" - assert str(err) == "400, message=\"Bad status line 'Test'\"" + assert str(err) == "400, message:\n Bad status line 'Test'" def test_ctor2(self) -> None: err = http_exceptions.BadStatusLine(b"") assert err.line == "b''" - assert str(err) == "400, message='Bad status line \"b\\'\\'\"'" + assert str(err) == "400, message:\n Bad status line \"b''\"" def test_pickle(self) -> None: err = http_exceptions.BadStatusLine("Test") diff --git a/tests/test_http_parser.py b/tests/test_http_parser.py index 87e98ea..4b185c9 100644 --- a/tests/test_http_parser.py +++ b/tests/test_http_parser.py @@ -1,6 +1,8 @@ # Tests for aiohttp/protocol.py import asyncio +import re +from typing import Any, List from unittest import mock from urllib.parse import quote @@ -11,6 +13,7 @@ import aiohttp from aiohttp import http_exceptions, streams from aiohttp.http_parser import ( + NO_EXTENSIONS, DeflateBuffer, HttpPayloadParser, HttpRequestParserPy, @@ -40,40 +43,47 @@ def protocol(): return mock.Mock() -@pytest.fixture(params=REQUEST_PARSERS) -def parser(loop, protocol, request): +def _gen_ids(parsers: List[Any]) -> List[str]: + return [ + "py-parser" if parser.__module__ == "aiohttp.http_parser" else "c-parser" + for parser in parsers + ] + + +@pytest.fixture(params=REQUEST_PARSERS, ids=_gen_ids(REQUEST_PARSERS)) +def parser(loop: Any, protocol: Any, request: Any): # Parser implementations return request.param( protocol, loop, - 2 ** 16, + 2**16, max_line_size=8190, max_headers=32768, max_field_size=8190, ) -@pytest.fixture(params=REQUEST_PARSERS) -def request_cls(request): +@pytest.fixture(params=REQUEST_PARSERS, ids=_gen_ids(REQUEST_PARSERS)) +def request_cls(request: Any): # Request Parser class return request.param -@pytest.fixture(params=RESPONSE_PARSERS) -def response(loop, protocol, request): +@pytest.fixture(params=RESPONSE_PARSERS, ids=_gen_ids(RESPONSE_PARSERS)) +def response(loop: Any, protocol: Any, request: Any): # Parser implementations return request.param( protocol, loop, - 2 ** 16, + 2**16, max_line_size=8190, max_headers=32768, max_field_size=8190, ) -@pytest.fixture(params=RESPONSE_PARSERS) -def response_cls(request): +@pytest.fixture(params=RESPONSE_PARSERS, ids=_gen_ids(RESPONSE_PARSERS)) +def response_cls(request: Any): # Parser implementations return request.param @@ -83,7 +93,15 @@ def stream(): return mock.Mock() -def test_parse_headers(parser) -> None: +@pytest.mark.skipif(NO_EXTENSIONS, reason="Extentions available but not imported") +def test_c_parser_loaded(): + assert "HttpRequestParserC" in dir(aiohttp.http_parser) + assert "HttpResponseParserC" in dir(aiohttp.http_parser) + assert "RawRequestMessageC" in dir(aiohttp.http_parser) + assert "RawResponseMessageC" in dir(aiohttp.http_parser) + + +def test_parse_headers(parser: Any) -> None: text = b"""GET /test HTTP/1.1\r test: line\r continue\r @@ -101,6 +119,127 @@ def test_parse_headers(parser) -> None: assert not msg.upgrade +@pytest.mark.skipif(NO_EXTENSIONS, reason="Only tests C parser.") +def test_invalid_character(loop: Any, protocol: Any, request: Any) -> None: + parser = HttpRequestParserC( + protocol, + loop, + 2**16, + max_line_size=8190, + max_field_size=8190, + ) + text = b"POST / HTTP/1.1\r\nHost: localhost:8080\r\nSet-Cookie: abc\x01def\r\n\r\n" + error_detail = re.escape( + r""": + + b'Set-Cookie: abc\x01def' + ^""" + ) + with pytest.raises(http_exceptions.BadHttpMessage, match=error_detail): + parser.feed_data(text) + + +@pytest.mark.skipif(NO_EXTENSIONS, reason="Only tests C parser.") +def test_invalid_linebreak(loop: Any, protocol: Any, request: Any) -> None: + parser = HttpRequestParserC( + protocol, + loop, + 2**16, + max_line_size=8190, + max_field_size=8190, + ) + text = b"GET /world HTTP/1.1\r\nHost: 127.0.0.1\n\r\n" + error_detail = re.escape( + r""": + + b'Host: 127.0.0.1\n' + ^""" + ) + with pytest.raises(http_exceptions.BadHttpMessage, match=error_detail): + parser.feed_data(text) + + +def test_cve_2023_37276(parser) -> None: + text = ( + b"POST / HTTP/1.1\r\nHost: localhost:8080\r\n" + b"X-Abc: \rxTransfer-Encoding: chunked\r\n\r\n" + ) + with pytest.raises(http_exceptions.BadHttpMessage): + parser.feed_data(text) + + +@pytest.mark.parametrize( + "hdr", + ( + # https://www.rfc-editor.org/rfc/rfc9110.html#name-content-length + "Content-Length: -5", + "Content-Length: +256", + "Foo: abc\rdef", # https://www.rfc-editor.org/rfc/rfc9110.html#section-5.5-5 + "Bar: abc\ndef", + "Baz: abc\x00def", + "Foo : bar", # https://www.rfc-editor.org/rfc/rfc9112.html#section-5.1-2 + "Foo\t: bar", + ), +) +def test_bad_headers(parser, hdr: str) -> None: + text = f"POST / HTTP/1.1\r\n{hdr}\r\n\r\n".encode() + with pytest.raises(http_exceptions.BadHttpMessage): + parser.feed_data(text) + + +def test_content_length_transfer_encoding(parser) -> None: + text = ( + b"GET / HTTP/1.1\r\nHost: a\r\nContent-Length: 5\r\n" + + b"Transfer-Encoding: a\r\n\r\napple\r\n" + ) + with pytest.raises(http_exceptions.BadHttpMessage): + parser.feed_data(text) + + +def test_bad_chunked_py(loop, protocol) -> None: + """Test that invalid chunked encoding doesn't allow content-length to be used.""" + parser = HttpRequestParserPy( + protocol, + loop, + 2**16, + max_line_size=8190, + max_field_size=8190, + ) + text = ( + b"GET / HTTP/1.1\r\nHost: a\r\nTransfer-Encoding: chunked\r\n\r\n0_2e\r\n\r\n" + + b"GET / HTTP/1.1\r\nHost: a\r\nContent-Length: 5\r\n\r\n0\r\n\r\n" + ) + messages, upgrade, tail = parser.feed_data(text) + assert isinstance(messages[0][1].exception(), http_exceptions.TransferEncodingError) + + +@pytest.mark.skipif( + "HttpRequestParserC" not in dir(aiohttp.http_parser), + reason="C based HTTP parser not available", +) +def test_bad_chunked_c(loop, protocol) -> None: + """C parser behaves differently. Maybe we should align them later.""" + parser = HttpRequestParserC( + protocol, + loop, + 2**16, + max_line_size=8190, + max_field_size=8190, + ) + text = ( + b"GET / HTTP/1.1\r\nHost: a\r\nTransfer-Encoding: chunked\r\n\r\n0_2e\r\n\r\n" + + b"GET / HTTP/1.1\r\nHost: a\r\nContent-Length: 5\r\n\r\n0\r\n\r\n" + ) + with pytest.raises(http_exceptions.BadHttpMessage): + parser.feed_data(text) + + +def test_whitespace_before_header(parser) -> None: + text = b"GET / HTTP/1.1\r\n\tContent-Length: 1\r\n\r\nX" + with pytest.raises(http_exceptions.BadHttpMessage): + parser.feed_data(text) + + def test_parse(parser) -> None: text = b"GET /test HTTP/1.1\r\n\r\n" messages, upgrade, tail = parser.feed_data(text) @@ -274,7 +413,29 @@ def test_request_chunked(parser) -> None: assert isinstance(payload, streams.StreamReader) -def test_conn_upgrade(parser) -> None: +def test_request_te_chunked_with_content_length(parser: Any) -> None: + text = ( + b"GET /test HTTP/1.1\r\n" + b"content-length: 1234\r\n" + b"transfer-encoding: chunked\r\n\r\n" + ) + with pytest.raises( + http_exceptions.BadHttpMessage, + match="Transfer-Encoding can't be present with Content-Length", + ): + parser.feed_data(text) + + +def test_request_te_chunked123(parser: Any) -> None: + text = b"GET /test HTTP/1.1\r\n" b"transfer-encoding: chunked123\r\n\r\n" + with pytest.raises( + http_exceptions.BadHttpMessage, + match="Request has invalid `Transfer-Encoding`", + ): + parser.feed_data(text) + + +def test_conn_upgrade(parser: Any) -> None: text = ( b"GET /test HTTP/1.1\r\n" b"connection: upgrade\r\n" @@ -323,7 +484,15 @@ def test_compression_unknown(parser) -> None: assert msg.compression is None -def test_headers_connect(parser) -> None: +def test_url_connect(parser: Any) -> None: + text = b"CONNECT www.google.com HTTP/1.1\r\n" b"content-length: 0\r\n\r\n" + messages, upgrade, tail = parser.feed_data(text) + msg, payload = messages[0] + assert upgrade + assert msg.url == URL.build(authority="www.google.com") + + +def test_headers_connect(parser: Any) -> None: text = b"CONNECT www.google.com HTTP/1.1\r\n" b"content-length: 0\r\n\r\n" messages, upgrade, tail = parser.feed_data(text) msg, payload = messages[0] @@ -331,7 +500,19 @@ def test_headers_connect(parser) -> None: assert isinstance(payload, streams.StreamReader) -def test_headers_old_websocket_key1(parser) -> None: +def test_url_absolute(parser: Any) -> None: + text = ( + b"GET https://www.google.com/path/to.html HTTP/1.1\r\n" + b"content-length: 0\r\n\r\n" + ) + messages, upgrade, tail = parser.feed_data(text) + msg, payload = messages[0] + assert not upgrade + assert msg.method == "GET" + assert msg.url == URL("https://www.google.com/path/to.html") + + +def test_headers_old_websocket_key1(parser: Any) -> None: text = b"GET /test HTTP/1.1\r\n" b"SEC-WEBSOCKET-KEY1: line\r\n\r\n" with pytest.raises(http_exceptions.BadHttpMessage): @@ -370,7 +551,7 @@ def test_max_header_field_size(parser, size) -> None: name = b"t" * size text = b"GET /test HTTP/1.1\r\n" + name + b":data\r\n\r\n" - match = f"400, message='Got more than 8190 bytes \\({size}\\) when reading" + match = f"400, message:\n Got more than 8190 bytes \\({size}\\) when reading" with pytest.raises(http_exceptions.LineTooLong, match=match): parser.feed_data(text) @@ -398,7 +579,7 @@ def test_max_header_value_size(parser, size) -> None: name = b"t" * size text = b"GET /test HTTP/1.1\r\n" b"data:" + name + b"\r\n\r\n" - match = f"400, message='Got more than 8190 bytes \\({size}\\) when reading" + match = f"400, message:\n Got more than 8190 bytes \\({size}\\) when reading" with pytest.raises(http_exceptions.LineTooLong, match=match): parser.feed_data(text) @@ -426,7 +607,7 @@ def test_max_header_value_size_continuation(parser, size) -> None: name = b"T" * (size - 5) text = b"GET /test HTTP/1.1\r\n" b"data: test\r\n " + name + b"\r\n\r\n" - match = f"400, message='Got more than 8190 bytes \\({size}\\) when reading" + match = f"400, message:\n Got more than 8190 bytes \\({size}\\) when reading" with pytest.raises(http_exceptions.LineTooLong, match=match): parser.feed_data(text) @@ -468,8 +649,10 @@ def test_http_request_parser(parser) -> None: def test_http_request_bad_status_line(parser) -> None: text = b"getpath \r\n\r\n" - with pytest.raises(http_exceptions.BadStatusLine): + with pytest.raises(http_exceptions.BadStatusLine) as exc_info: parser.feed_data(text) + # Check for accidentally escaped message. + assert r"\n" not in exc_info.value.message def test_http_request_upgrade(parser) -> None: @@ -546,10 +729,15 @@ def test_http_request_parser_bad_version(parser) -> None: parser.feed_data(b"GET //get HT/11\r\n\r\n") +def test_http_request_parser_bad_version_number(parser: Any) -> None: + with pytest.raises(http_exceptions.BadHttpMessage): + parser.feed_data(b"GET /test HTTP/12.3\r\n\r\n") + + @pytest.mark.parametrize("size", [40965, 8191]) def test_http_request_max_status_line(parser, size) -> None: path = b"t" * (size - 5) - match = f"400, message='Got more than 8190 bytes \\({size}\\) when reading" + match = f"400, message:\n Got more than 8190 bytes \\({size}\\) when reading" with pytest.raises(http_exceptions.LineTooLong, match=match): parser.feed_data(b"GET /path" + path + b" HTTP/1.1\r\n\r\n") @@ -592,7 +780,7 @@ def test_http_response_parser_utf8(response) -> None: @pytest.mark.parametrize("size", [40962, 8191]) def test_http_response_parser_bad_status_line_too_long(response, size) -> None: reason = b"t" * (size - 2) - match = f"400, message='Got more than 8190 bytes \\({size}\\) when reading" + match = f"400, message:\n Got more than 8190 bytes \\({size}\\) when reading" with pytest.raises(http_exceptions.LineTooLong, match=match): response.feed_data(b"HTTP/1.1 200 Ok" + reason + b"\r\n\r\n") @@ -613,6 +801,11 @@ def test_http_response_parser_bad_version(response) -> None: response.feed_data(b"HT/11 200 Ok\r\n\r\n") +def test_http_response_parser_bad_version_number(response) -> None: + with pytest.raises(http_exceptions.BadHttpMessage): + response.feed_data(b"HTTP/12.3 200 Ok\r\n\r\n") + + def test_http_response_parser_no_reason(response) -> None: msg = response.feed_data(b"HTTP/1.1 200\r\n\r\n")[0][0][0] @@ -621,23 +814,96 @@ def test_http_response_parser_no_reason(response) -> None: assert msg.reason == "" +def test_http_response_parser_lenient_headers(response) -> None: + messages, upgrade, tail = response.feed_data( + b"HTTP/1.1 200 test\r\nFoo: abc\x01def\r\n\r\n" + ) + msg = messages[0][0] + + assert msg.headers["Foo"] == "abc\x01def" + + +@pytest.mark.dev_mode +def test_http_response_parser_strict_headers(response) -> None: + if isinstance(response, HttpResponseParserPy): + pytest.xfail("Py parser is lenient. May update py-parser later.") + with pytest.raises(http_exceptions.BadHttpMessage): + response.feed_data(b"HTTP/1.1 200 test\r\nFoo: abc\x01def\r\n\r\n") + + +def test_http_response_parser_bad_crlf(response) -> None: + """Still a lot of dodgy servers sending bad requests like this.""" + messages, upgrade, tail = response.feed_data( + b"HTTP/1.0 200 OK\nFoo: abc\nBar: def\n\nBODY\n" + ) + msg = messages[0][0] + + assert msg.headers["Foo"] == "abc" + assert msg.headers["Bar"] == "def" + + +async def test_http_response_parser_bad_chunked_lax(response) -> None: + text = ( + b"HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n5 \r\nabcde\r\n0\r\n\r\n" + ) + messages, upgrade, tail = response.feed_data(text) + + assert await messages[0][1].read(5) == b"abcde" + + +@pytest.mark.dev_mode +async def test_http_response_parser_bad_chunked_strict_py(loop, protocol) -> None: + response = HttpResponseParserPy( + protocol, + loop, + 2**16, + max_line_size=8190, + max_field_size=8190, + ) + text = ( + b"HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n5 \r\nabcde\r\n0\r\n\r\n" + ) + messages, upgrade, tail = response.feed_data(text) + assert isinstance(messages[0][1].exception(), http_exceptions.TransferEncodingError) + + +@pytest.mark.dev_mode +@pytest.mark.skipif( + "HttpRequestParserC" not in dir(aiohttp.http_parser), + reason="C based HTTP parser not available", +) +async def test_http_response_parser_bad_chunked_strict_c(loop, protocol) -> None: + response = HttpResponseParserC( + protocol, + loop, + 2**16, + max_line_size=8190, + max_field_size=8190, + ) + text = ( + b"HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n5 \r\nabcde\r\n0\r\n\r\n" + ) + with pytest.raises(http_exceptions.BadHttpMessage): + response.feed_data(text) + + def test_http_response_parser_bad(response) -> None: with pytest.raises(http_exceptions.BadHttpMessage): response.feed_data(b"HTT/1\r\n\r\n") def test_http_response_parser_code_under_100(response) -> None: - msg = response.feed_data(b"HTTP/1.1 99 test\r\n\r\n")[0][0][0] - assert msg.code == 99 + with pytest.raises(http_exceptions.BadStatusLine): + response.feed_data(b"HTTP/1.1 99 test\r\n\r\n") def test_http_response_parser_code_above_999(response) -> None: - with pytest.raises(http_exceptions.BadHttpMessage): + with pytest.raises(http_exceptions.BadStatusLine): response.feed_data(b"HTTP/1.1 9999 test\r\n\r\n") def test_http_response_parser_code_not_int(response) -> None: - with pytest.raises(http_exceptions.BadHttpMessage): + with pytest.raises(http_exceptions.BadStatusLine): response.feed_data(b"HTTP/1.1 ttt test\r\n\r\n") @@ -720,7 +986,7 @@ def _test_parse_no_length_or_te_on_post(loop, protocol, request_cls): def test_parse_payload_response_without_body(loop, protocol, response_cls) -> None: - parser = response_cls(protocol, loop, 2 ** 16, response_with_body=False) + parser = response_cls(protocol, loop, 2**16, response_with_body=False) text = b"HTTP/1.1 200 Ok\r\n" b"content-length: 10\r\n\r\n" msg, payload = parser.feed_data(text)[0][0] @@ -760,19 +1026,6 @@ def test_partial_url(parser) -> None: assert payload.is_eof() -def test_url_parse_non_strict_mode(parser) -> None: - payload = "GET /test/тест HTTP/1.1\r\n\r\n".encode() - messages, upgrade, tail = parser.feed_data(payload) - assert len(messages) == 1 - - msg, payload = messages[0] - - assert msg.method == "GET" - assert msg.path == "/test/тест" - assert msg.version == (1, 1) - assert payload.is_eof() - - @pytest.mark.parametrize( ("uri", "path", "query", "fragment"), [ @@ -797,6 +1050,8 @@ def test_parse_uri_percent_encoded(parser, uri, path, query, fragment) -> None: def test_parse_uri_utf8(parser) -> None: + if not isinstance(parser, HttpRequestParserPy): + pytest.xfail("Not valid HTTP. Maybe update py-parser to reject later.") text = ("GET /путь?ключ=знач#фраг HTTP/1.1\r\n\r\n").encode() messages, upgrade, tail = parser.feed_data(text) msg = messages[0][0] @@ -830,7 +1085,7 @@ def test_parse_bad_method_for_c_parser_raises(loop, protocol): parser = HttpRequestParserC( protocol, loop, - 2 ** 16, + 2**16, max_line_size=8190, max_headers=32768, max_field_size=8190, @@ -843,7 +1098,7 @@ def test_parse_bad_method_for_c_parser_raises(loop, protocol): class TestParsePayload: async def test_parse_eof_payload(self, stream) -> None: out = aiohttp.FlowControlDataQueue( - stream, 2 ** 16, loop=asyncio.get_event_loop() + stream, 2**16, loop=asyncio.get_event_loop() ) p = HttpPayloadParser(out, readall=True) p.feed_data(b"data") @@ -854,7 +1109,7 @@ async def test_parse_eof_payload(self, stream) -> None: async def test_parse_no_body(self, stream) -> None: out = aiohttp.FlowControlDataQueue( - stream, 2 ** 16, loop=asyncio.get_event_loop() + stream, 2**16, loop=asyncio.get_event_loop() ) p = HttpPayloadParser(out, method="PUT") @@ -863,7 +1118,7 @@ async def test_parse_no_body(self, stream) -> None: async def test_parse_length_payload_eof(self, stream) -> None: out = aiohttp.FlowControlDataQueue( - stream, 2 ** 16, loop=asyncio.get_event_loop() + stream, 2**16, loop=asyncio.get_event_loop() ) p = HttpPayloadParser(out, length=4) @@ -874,7 +1129,7 @@ async def test_parse_length_payload_eof(self, stream) -> None: async def test_parse_chunked_payload_size_error(self, stream) -> None: out = aiohttp.FlowControlDataQueue( - stream, 2 ** 16, loop=asyncio.get_event_loop() + stream, 2**16, loop=asyncio.get_event_loop() ) p = HttpPayloadParser(out, chunked=True) with pytest.raises(http_exceptions.TransferEncodingError): @@ -882,7 +1137,7 @@ async def test_parse_chunked_payload_size_error(self, stream) -> None: assert isinstance(out.exception(), http_exceptions.TransferEncodingError) async def test_parse_chunked_payload_split_end(self, protocol) -> None: - out = aiohttp.StreamReader(protocol, 2 ** 16, loop=None) + out = aiohttp.StreamReader(protocol, 2**16, loop=None) p = HttpPayloadParser(out, chunked=True) p.feed_data(b"4\r\nasdf\r\n0\r\n") p.feed_data(b"\r\n") @@ -891,7 +1146,7 @@ async def test_parse_chunked_payload_split_end(self, protocol) -> None: assert b"asdf" == b"".join(out._buffer) async def test_parse_chunked_payload_split_end2(self, protocol) -> None: - out = aiohttp.StreamReader(protocol, 2 ** 16, loop=None) + out = aiohttp.StreamReader(protocol, 2**16, loop=None) p = HttpPayloadParser(out, chunked=True) p.feed_data(b"4\r\nasdf\r\n0\r\n\r") p.feed_data(b"\n") @@ -900,7 +1155,7 @@ async def test_parse_chunked_payload_split_end2(self, protocol) -> None: assert b"asdf" == b"".join(out._buffer) async def test_parse_chunked_payload_split_end_trailers(self, protocol) -> None: - out = aiohttp.StreamReader(protocol, 2 ** 16, loop=None) + out = aiohttp.StreamReader(protocol, 2**16, loop=None) p = HttpPayloadParser(out, chunked=True) p.feed_data(b"4\r\nasdf\r\n0\r\n") p.feed_data(b"Content-MD5: 912ec803b2ce49e4a541068d495ab570\r\n") @@ -910,7 +1165,7 @@ async def test_parse_chunked_payload_split_end_trailers(self, protocol) -> None: assert b"asdf" == b"".join(out._buffer) async def test_parse_chunked_payload_split_end_trailers2(self, protocol) -> None: - out = aiohttp.StreamReader(protocol, 2 ** 16, loop=None) + out = aiohttp.StreamReader(protocol, 2**16, loop=None) p = HttpPayloadParser(out, chunked=True) p.feed_data(b"4\r\nasdf\r\n0\r\n") p.feed_data(b"Content-MD5: 912ec803b2ce49e4a541068d495ab570\r\n\r") @@ -920,7 +1175,7 @@ async def test_parse_chunked_payload_split_end_trailers2(self, protocol) -> None assert b"asdf" == b"".join(out._buffer) async def test_parse_chunked_payload_split_end_trailers3(self, protocol) -> None: - out = aiohttp.StreamReader(protocol, 2 ** 16, loop=None) + out = aiohttp.StreamReader(protocol, 2**16, loop=None) p = HttpPayloadParser(out, chunked=True) p.feed_data(b"4\r\nasdf\r\n0\r\nContent-MD5: ") p.feed_data(b"912ec803b2ce49e4a541068d495ab570\r\n\r\n") @@ -929,7 +1184,7 @@ async def test_parse_chunked_payload_split_end_trailers3(self, protocol) -> None assert b"asdf" == b"".join(out._buffer) async def test_parse_chunked_payload_split_end_trailers4(self, protocol) -> None: - out = aiohttp.StreamReader(protocol, 2 ** 16, loop=None) + out = aiohttp.StreamReader(protocol, 2**16, loop=None) p = HttpPayloadParser(out, chunked=True) p.feed_data(b"4\r\nasdf\r\n0\r\n" b"C") p.feed_data(b"ontent-MD5: 912ec803b2ce49e4a541068d495ab570\r\n\r\n") @@ -939,7 +1194,7 @@ async def test_parse_chunked_payload_split_end_trailers4(self, protocol) -> None async def test_http_payload_parser_length(self, stream) -> None: out = aiohttp.FlowControlDataQueue( - stream, 2 ** 16, loop=asyncio.get_event_loop() + stream, 2**16, loop=asyncio.get_event_loop() ) p = HttpPayloadParser(out, length=2) eof, tail = p.feed_data(b"1245") @@ -954,22 +1209,21 @@ async def test_http_payload_parser_deflate(self, stream) -> None: length = len(COMPRESSED) out = aiohttp.FlowControlDataQueue( - stream, 2 ** 16, loop=asyncio.get_event_loop() + stream, 2**16, loop=asyncio.get_event_loop() ) p = HttpPayloadParser(out, length=length, compression="deflate") p.feed_data(COMPRESSED) assert b"data" == b"".join(d for d, _ in out._buffer) assert out.is_eof() - async def test_http_payload_parser_deflate_no_hdrs(self, stream) -> None: - """Tests incorrectly formed data (no zlib headers) """ - + async def test_http_payload_parser_deflate_no_hdrs(self, stream: Any) -> None: + """Tests incorrectly formed data (no zlib headers).""" # c=compressobj(wbits=-15); b''.join([c.compress(b'data'), c.flush()]) COMPRESSED = b"KI,I\x04\x00" length = len(COMPRESSED) out = aiohttp.FlowControlDataQueue( - stream, 2 ** 16, loop=asyncio.get_event_loop() + stream, 2**16, loop=asyncio.get_event_loop() ) p = HttpPayloadParser(out, length=length, compression="deflate") p.feed_data(COMPRESSED) @@ -982,7 +1236,7 @@ async def test_http_payload_parser_deflate_light(self, stream) -> None: length = len(COMPRESSED) out = aiohttp.FlowControlDataQueue( - stream, 2 ** 16, loop=asyncio.get_event_loop() + stream, 2**16, loop=asyncio.get_event_loop() ) p = HttpPayloadParser(out, length=length, compression="deflate") p.feed_data(COMPRESSED) @@ -991,7 +1245,7 @@ async def test_http_payload_parser_deflate_light(self, stream) -> None: async def test_http_payload_parser_deflate_split(self, stream) -> None: out = aiohttp.FlowControlDataQueue( - stream, 2 ** 16, loop=asyncio.get_event_loop() + stream, 2**16, loop=asyncio.get_event_loop() ) p = HttpPayloadParser(out, compression="deflate", readall=True) # Feeding one correct byte should be enough to choose exact @@ -1003,7 +1257,7 @@ async def test_http_payload_parser_deflate_split(self, stream) -> None: async def test_http_payload_parser_deflate_split_err(self, stream) -> None: out = aiohttp.FlowControlDataQueue( - stream, 2 ** 16, loop=asyncio.get_event_loop() + stream, 2**16, loop=asyncio.get_event_loop() ) p = HttpPayloadParser(out, compression="deflate", readall=True) # Feeding one wrong byte should be enough to choose exact @@ -1015,7 +1269,7 @@ async def test_http_payload_parser_deflate_split_err(self, stream) -> None: async def test_http_payload_parser_length_zero(self, stream) -> None: out = aiohttp.FlowControlDataQueue( - stream, 2 ** 16, loop=asyncio.get_event_loop() + stream, 2**16, loop=asyncio.get_event_loop() ) p = HttpPayloadParser(out, length=0) assert p.done @@ -1025,7 +1279,7 @@ async def test_http_payload_parser_length_zero(self, stream) -> None: async def test_http_payload_brotli(self, stream) -> None: compressed = brotli.compress(b"brotli data") out = aiohttp.FlowControlDataQueue( - stream, 2 ** 16, loop=asyncio.get_event_loop() + stream, 2**16, loop=asyncio.get_event_loop() ) p = HttpPayloadParser(out, length=len(compressed), compression="br") p.feed_data(compressed) @@ -1036,7 +1290,7 @@ async def test_http_payload_brotli(self, stream) -> None: class TestDeflateBuffer: async def test_feed_data(self, stream) -> None: buf = aiohttp.FlowControlDataQueue( - stream, 2 ** 16, loop=asyncio.get_event_loop() + stream, 2**16, loop=asyncio.get_event_loop() ) dbuf = DeflateBuffer(buf, "deflate") @@ -1049,7 +1303,7 @@ async def test_feed_data(self, stream) -> None: async def test_feed_data_err(self, stream) -> None: buf = aiohttp.FlowControlDataQueue( - stream, 2 ** 16, loop=asyncio.get_event_loop() + stream, 2**16, loop=asyncio.get_event_loop() ) dbuf = DeflateBuffer(buf, "deflate") @@ -1064,7 +1318,7 @@ async def test_feed_data_err(self, stream) -> None: async def test_feed_eof(self, stream) -> None: buf = aiohttp.FlowControlDataQueue( - stream, 2 ** 16, loop=asyncio.get_event_loop() + stream, 2**16, loop=asyncio.get_event_loop() ) dbuf = DeflateBuffer(buf, "deflate") @@ -1077,7 +1331,7 @@ async def test_feed_eof(self, stream) -> None: async def test_feed_eof_err_deflate(self, stream) -> None: buf = aiohttp.FlowControlDataQueue( - stream, 2 ** 16, loop=asyncio.get_event_loop() + stream, 2**16, loop=asyncio.get_event_loop() ) dbuf = DeflateBuffer(buf, "deflate") @@ -1090,7 +1344,7 @@ async def test_feed_eof_err_deflate(self, stream) -> None: async def test_feed_eof_no_err_gzip(self, stream) -> None: buf = aiohttp.FlowControlDataQueue( - stream, 2 ** 16, loop=asyncio.get_event_loop() + stream, 2**16, loop=asyncio.get_event_loop() ) dbuf = DeflateBuffer(buf, "gzip") @@ -1103,7 +1357,7 @@ async def test_feed_eof_no_err_gzip(self, stream) -> None: async def test_feed_eof_no_err_brotli(self, stream) -> None: buf = aiohttp.FlowControlDataQueue( - stream, 2 ** 16, loop=asyncio.get_event_loop() + stream, 2**16, loop=asyncio.get_event_loop() ) dbuf = DeflateBuffer(buf, "br") @@ -1116,7 +1370,7 @@ async def test_feed_eof_no_err_brotli(self, stream) -> None: async def test_empty_body(self, stream) -> None: buf = aiohttp.FlowControlDataQueue( - stream, 2 ** 16, loop=asyncio.get_event_loop() + stream, 2**16, loop=asyncio.get_event_loop() ) dbuf = DeflateBuffer(buf, "deflate") dbuf.feed_eof() diff --git a/tests/test_http_writer.py b/tests/test_http_writer.py index 6aca2ea..5649f32 100644 --- a/tests/test_http_writer.py +++ b/tests/test_http_writer.py @@ -3,6 +3,7 @@ from unittest import mock import pytest +from multidict import CIMultiDict from aiohttp import http from aiohttp.test_utils import make_mocked_coro @@ -235,6 +236,21 @@ async def test_write_to_closing_transport(protocol, transport, loop) -> None: await msg.write(b"After closing") +async def test_write_to_closed_transport(protocol, transport, loop) -> None: + """Test that writing to a closed transport raises ConnectionResetError. + + The StreamWriter checks to see if protocol.transport is None before + writing to the transport. If it is None, it raises ConnectionResetError. + """ + msg = http.StreamWriter(protocol, loop) + + await msg.write(b"Before transport close") + protocol.transport = None + + with pytest.raises(ConnectionResetError, match="Cannot write to closing transport"): + await msg.write(b"After transport closed") + + async def test_drain(protocol, transport, loop) -> None: msg = http.StreamWriter(protocol, loop) await msg.drain() @@ -246,3 +262,14 @@ async def test_drain_no_transport(protocol, transport, loop) -> None: msg._protocol.transport = None await msg.drain() assert not protocol._drain_helper.called + + +async def test_write_headers_prevents_injection(protocol, transport, loop) -> None: + msg = http.StreamWriter(protocol, loop) + status_line = "HTTP/1.1 200 OK" + wrong_headers = CIMultiDict({"Set-Cookie: abc=123\r\nContent-Length": "256"}) + with pytest.raises(ValueError): + await msg.write_headers(status_line, wrong_headers) + wrong_headers = CIMultiDict({"Content-Length": "256\r\nSet-Cookie: abc=123"}) + with pytest.raises(ValueError): + await msg.write_headers(status_line, wrong_headers) diff --git a/tests/test_locks.py b/tests/test_locks.py index 55fd233..5f434ea 100644 --- a/tests/test_locks.py +++ b/tests/test_locks.py @@ -18,7 +18,7 @@ async def c(): return 1 t = loop.create_task(c()) - await asyncio.sleep(0, loop=loop) + await asyncio.sleep(0) e = Exception() ev.set(exc=e) assert (await t) == e @@ -31,7 +31,7 @@ async def c(): return 1 t = loop.create_task(c()) - await asyncio.sleep(0, loop=loop) + await asyncio.sleep(0) ev.set() assert (await t) == 1 @@ -43,7 +43,7 @@ async def c(): t1 = loop.create_task(c()) t2 = loop.create_task(c()) - await asyncio.sleep(0, loop=loop) + await asyncio.sleep(0) ev.cancel() ev.set() diff --git a/tests/test_loop.py b/tests/test_loop.py index 24c979e..1423c1f 100644 --- a/tests/test_loop.py +++ b/tests/test_loop.py @@ -5,14 +5,15 @@ import pytest from aiohttp import web -from aiohttp.test_utils import AioHTTPTestCase, unittest_run_loop +from aiohttp.helpers import PY_38 +from aiohttp.test_utils import AioHTTPTestCase, loop_context @pytest.mark.skipif( platform.system() == "Windows", reason="the test is not valid for Windows" ) async def test_subprocess_co(loop) -> None: - assert isinstance(threading.current_thread(), threading._MainThread) + assert PY_38 or isinstance(threading.current_thread(), threading._MainThread) proc = await asyncio.create_subprocess_shell( "exit 0", stdin=asyncio.subprocess.DEVNULL, @@ -31,13 +32,33 @@ async def get_application(self): async def on_startup_hook(self, app): self.on_startup_called = True - @unittest_run_loop async def test_on_startup_hook(self) -> None: self.assertTrue(self.on_startup_called) def test_default_loop(self) -> None: - self.assertIs(self.loop, asyncio.get_event_loop()) + self.assertIs(self.loop, asyncio.get_event_loop_policy().get_event_loop()) def test_default_loop(loop) -> None: - assert asyncio.get_event_loop() is loop + assert asyncio.get_event_loop_policy().get_event_loop() is loop + + +@pytest.mark.xfail(not PY_38, reason="ThreadedChildWatcher is only available in 3.8+") +def test_setup_loop_non_main_thread() -> None: + child_exc = None + + def target() -> None: + try: + with loop_context() as loop: + assert asyncio.get_event_loop_policy().get_event_loop() is loop + loop.run_until_complete(test_subprocess_co(loop)) + except Exception as exc: + nonlocal child_exc + child_exc = exc + + # Ensures setup_test_loop can be called by pytest-xdist in non-main thread. + t = threading.Thread(target=target) + t.start() + t.join() + + assert child_exc is None diff --git a/tests/test_multipart.py b/tests/test_multipart.py index 6c3f121..cc3f5ff 100644 --- a/tests/test_multipart.py +++ b/tests/test_multipart.py @@ -23,6 +23,9 @@ BOUNDARY = b"--:" +newline = b"\r\n" + + @pytest.fixture def buf(): return bytearray() @@ -66,6 +69,12 @@ async def readline(self): def unread_data(self, data): self.content = io.BytesIO(data + self.content.read()) + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_value, traceback): + self.content.close() + class StreamWithShortenRead(Stream): def __init__(self, content): @@ -110,243 +119,270 @@ async def test_release_when_stream_at_eof(self) -> None: class TestPartReader: async def test_next(self) -> None: - obj = aiohttp.BodyPartReader(BOUNDARY, {}, Stream(b"Hello, world!\r\n--:")) - result = await obj.next() - assert b"Hello, world!" == result - assert obj.at_eof() + data = b"Hello, world!%s--:" % newline + with Stream(data) as stream: + obj = aiohttp.BodyPartReader(BOUNDARY, {}, stream) + result = await obj.next() + assert b"Hello, world!" == result + assert obj.at_eof() async def test_next_next(self) -> None: - obj = aiohttp.BodyPartReader(BOUNDARY, {}, Stream(b"Hello, world!\r\n--:")) - result = await obj.next() - assert b"Hello, world!" == result - assert obj.at_eof() - result = await obj.next() - assert result is None + data = b"Hello, world!%s--:" % newline + with Stream(data) as stream: + obj = aiohttp.BodyPartReader(BOUNDARY, {}, stream) + result = await obj.next() + assert b"Hello, world!" == result + assert obj.at_eof() + result = await obj.next() + assert result is None async def test_read(self) -> None: - obj = aiohttp.BodyPartReader(BOUNDARY, {}, Stream(b"Hello, world!\r\n--:")) - result = await obj.read() - assert b"Hello, world!" == result - assert obj.at_eof() + data = b"Hello, world!%s--:" % newline + with Stream(data) as stream: + obj = aiohttp.BodyPartReader(BOUNDARY, {}, stream) + result = await obj.read() + assert b"Hello, world!" == result + assert obj.at_eof() async def test_read_chunk_at_eof(self) -> None: - obj = aiohttp.BodyPartReader(BOUNDARY, {}, Stream(b"--:")) - obj._at_eof = True - result = await obj.read_chunk() + with Stream(b"--:") as stream: + obj = aiohttp.BodyPartReader(BOUNDARY, {}, stream) + obj._at_eof = True + result = await obj.read_chunk() assert b"" == result async def test_read_chunk_without_content_length(self) -> None: - obj = aiohttp.BodyPartReader(BOUNDARY, {}, Stream(b"Hello, world!\r\n--:")) - c1 = await obj.read_chunk(8) - c2 = await obj.read_chunk(8) - c3 = await obj.read_chunk(8) - assert c1 + c2 == b"Hello, world!" - assert c3 == b"" - - async def test_read_incomplete_chunk(self) -> None: - stream = Stream(b"") - - if sys.version_info >= (3, 8, 1): - # Workaround for a weird behavior of patch.object - def prepare(data): - return data - - else: - - async def prepare(data): - return data - - with mock.patch.object( - stream, - "read", - side_effect=[ - prepare(b"Hello, "), - prepare(b"World"), - prepare(b"!\r\n--:"), - prepare(b""), - ], - ): + data = b"Hello, world!%s--:" % newline + with Stream(data) as stream: obj = aiohttp.BodyPartReader(BOUNDARY, {}, stream) c1 = await obj.read_chunk(8) - assert c1 == b"Hello, " c2 = await obj.read_chunk(8) - assert c2 == b"World" c3 = await obj.read_chunk(8) - assert c3 == b"!" + assert c1 + c2 == b"Hello, world!" + assert c3 == b"" + + async def test_read_incomplete_chunk(self) -> None: + with Stream(b"") as stream: + if sys.version_info >= (3, 8, 1): + # Workaround for a weird behavior of patch.object + def prepare(data): + return data + + else: + + async def prepare(data): + return data + + with mock.patch.object( + stream, + "read", + side_effect=[ + prepare(b"Hello, "), + prepare(b"World"), + prepare(b"!%s--:" % newline), + prepare(b""), + ], + ): + obj = aiohttp.BodyPartReader(BOUNDARY, {}, stream) + c1 = await obj.read_chunk(8) + assert c1 == b"Hello, " + c2 = await obj.read_chunk(8) + assert c2 == b"World" + c3 = await obj.read_chunk(8) + assert c3 == b"!" async def test_read_all_at_once(self) -> None: - stream = Stream(b"Hello, World!\r\n--:--\r\n") - obj = aiohttp.BodyPartReader(BOUNDARY, {}, stream) - result = await obj.read_chunk() - assert b"Hello, World!" == result - result = await obj.read_chunk() - assert b"" == result - assert obj.at_eof() + data = b"Hello, World!%s--:--%s" % (newline, newline) + with Stream(data) as stream: + obj = aiohttp.BodyPartReader(BOUNDARY, {}, stream) + result = await obj.read_chunk() + assert b"Hello, World!" == result + result = await obj.read_chunk() + assert b"" == result + assert obj.at_eof() async def test_read_incomplete_body_chunked(self) -> None: - stream = Stream(b"Hello, World!\r\n-") - obj = aiohttp.BodyPartReader(BOUNDARY, {}, stream) - result = b"" - with pytest.raises(AssertionError): - for _ in range(4): - result += await obj.read_chunk(7) - assert b"Hello, World!\r\n-" == result + data = b"Hello, World!%s--" % newline + with Stream(data) as stream: + obj = aiohttp.BodyPartReader(BOUNDARY, {}, stream) + result = b"" + with pytest.raises(AssertionError): + for _ in range(4): + result += await obj.read_chunk(7) + assert data == result async def test_read_boundary_with_incomplete_chunk(self) -> None: - stream = Stream(b"") - - if sys.version_info >= (3, 8, 1): - # Workaround for weird 3.8.1 patch.object() behavior - def prepare(data): - return data - - else: - - async def prepare(data): - return data - - with mock.patch.object( - stream, - "read", - side_effect=[ - prepare(b"Hello, World"), - prepare(b"!\r\n"), - prepare(b"--:"), - prepare(b""), - ], - ): - obj = aiohttp.BodyPartReader(BOUNDARY, {}, stream) - c1 = await obj.read_chunk(12) - assert c1 == b"Hello, World" - c2 = await obj.read_chunk(8) - assert c2 == b"!" - c3 = await obj.read_chunk(8) - assert c3 == b"" + with Stream(b"") as stream: + if sys.version_info >= (3, 8, 1): + # Workaround for weird 3.8.1 patch.object() behavior + def prepare(data): + return data + + else: + + async def prepare(data): + return data + + with mock.patch.object( + stream, + "read", + side_effect=[ + prepare(b"Hello, World"), + prepare(b"!%s" % newline), + prepare(b"--:"), + prepare(b""), + ], + ): + obj = aiohttp.BodyPartReader(BOUNDARY, {}, stream) + c1 = await obj.read_chunk(12) + assert c1 == b"Hello, World" + c2 = await obj.read_chunk(8) + assert c2 == b"!" + c3 = await obj.read_chunk(8) + assert c3 == b"" async def test_multi_read_chunk(self) -> None: - stream = Stream(b"Hello,\r\n--:\r\n\r\nworld!\r\n--:--") - obj = aiohttp.BodyPartReader(BOUNDARY, {}, stream) - result = await obj.read_chunk(8) - assert b"Hello," == result - result = await obj.read_chunk(8) - assert b"" == result - assert obj.at_eof() + data = b"Hello,%s--:%s%sworld!%s--:--" % ((newline,) * 4) + with Stream(data) as stream: + obj = aiohttp.BodyPartReader(BOUNDARY, {}, stream) + result = await obj.read_chunk(8) + assert b"Hello," == result + result = await obj.read_chunk(8) + assert b"" == result + assert obj.at_eof() async def test_read_chunk_properly_counts_read_bytes(self) -> None: expected = b"." * 10 + tail = b"%s--:--" % newline size = len(expected) - obj = aiohttp.BodyPartReader( - BOUNDARY, - {"CONTENT-LENGTH": size}, - StreamWithShortenRead(expected + b"\r\n--:--"), - ) - result = bytearray() - while True: - chunk = await obj.read_chunk() - if not chunk: - break - result.extend(chunk) + with StreamWithShortenRead(expected + tail) as stream: + obj = aiohttp.BodyPartReader( + BOUNDARY, + {"CONTENT-LENGTH": size}, + stream, + ) + result = bytearray() + while True: + chunk = await obj.read_chunk() + if not chunk: + break + result.extend(chunk) assert size == len(result) assert b"." * size == result assert obj.at_eof() async def test_read_does_not_read_boundary(self) -> None: - stream = Stream(b"Hello, world!\r\n--:") - obj = aiohttp.BodyPartReader(BOUNDARY, {}, stream) - result = await obj.read() - assert b"Hello, world!" == result - assert b"--:" == (await stream.read()) + data = b"Hello, world!%s--:" % newline + with Stream(data) as stream: + obj = aiohttp.BodyPartReader(BOUNDARY, {}, stream) + result = await obj.read() + assert b"Hello, world!" == result + assert b"--:" == (await stream.read()) async def test_multiread(self) -> None: - obj = aiohttp.BodyPartReader( - BOUNDARY, {}, Stream(b"Hello,\r\n--:\r\n\r\nworld!\r\n--:--") - ) - result = await obj.read() - assert b"Hello," == result - result = await obj.read() - assert b"" == result - assert obj.at_eof() + data = b"Hello,%s--:%s%sworld!%s--:--" % ((newline,) * 4) + with Stream(data) as stream: + obj = aiohttp.BodyPartReader(BOUNDARY, {}, stream) + result = await obj.read() + assert b"Hello," == result + result = await obj.read() + assert b"" == result + assert obj.at_eof() async def test_read_multiline(self) -> None: - obj = aiohttp.BodyPartReader( - BOUNDARY, {}, Stream(b"Hello\n,\r\nworld!\r\n--:--") - ) - result = await obj.read() - assert b"Hello\n,\r\nworld!" == result - result = await obj.read() - assert b"" == result - assert obj.at_eof() + data = b"Hello\n,\r\nworld!%s--:--" % newline + with Stream(data) as stream: + obj = aiohttp.BodyPartReader(BOUNDARY, {}, stream) + result = await obj.read() + assert b"Hello\n,\r\nworld!" == result + result = await obj.read() + assert b"" == result + assert obj.at_eof() async def test_read_respects_content_length(self) -> None: - obj = aiohttp.BodyPartReader( - BOUNDARY, {"CONTENT-LENGTH": 100500}, Stream(b"." * 100500 + b"\r\n--:--") - ) - result = await obj.read() - assert b"." * 100500 == result - assert obj.at_eof() + data = b"." * 100500 + tail = b"%s--:--" % newline + with Stream(data + tail) as stream: + obj = aiohttp.BodyPartReader( + BOUNDARY, + {"CONTENT-LENGTH": 100500}, + stream, + ) + result = await obj.read() + assert data == result + assert obj.at_eof() async def test_read_with_content_encoding_gzip(self) -> None: - obj = aiohttp.BodyPartReader( - BOUNDARY, - {CONTENT_ENCODING: "gzip"}, - Stream( - b"\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x03\x0b\xc9\xccMU" - b"(\xc9W\x08J\xcdI\xacP\x04\x00$\xfb\x9eV\x0e\x00\x00\x00" - b"\r\n--:--" - ), - ) - result = await obj.read(decode=True) + with Stream( + b"\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x03\x0b\xc9\xccMU" + b"(\xc9W\x08J\xcdI\xacP\x04\x00$\xfb\x9eV\x0e\x00\x00\x00" + b"%s--:--" % newline + ) as stream: + obj = aiohttp.BodyPartReader( + BOUNDARY, + {CONTENT_ENCODING: "gzip"}, + stream, + ) + result = await obj.read(decode=True) assert b"Time to Relax!" == result async def test_read_with_content_encoding_deflate(self) -> None: - obj = aiohttp.BodyPartReader( - BOUNDARY, - {CONTENT_ENCODING: "deflate"}, - Stream(b"\x0b\xc9\xccMU(\xc9W\x08J\xcdI\xacP\x04\x00\r\n--:--"), - ) - result = await obj.read(decode=True) + data = b"\x0b\xc9\xccMU(\xc9W\x08J\xcdI\xacP\x04\x00" + tail = b"%s--:--" % newline + with Stream(data + tail) as stream: + obj = aiohttp.BodyPartReader( + BOUNDARY, + {CONTENT_ENCODING: "deflate"}, + stream, + ) + result = await obj.read(decode=True) assert b"Time to Relax!" == result async def test_read_with_content_encoding_identity(self) -> None: thing = ( b"\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x03\x0b\xc9\xccMU" b"(\xc9W\x08J\xcdI\xacP\x04\x00$\xfb\x9eV\x0e\x00\x00\x00" - b"\r\n" ) - obj = aiohttp.BodyPartReader( - BOUNDARY, {CONTENT_ENCODING: "identity"}, Stream(thing + b"--:--") - ) - result = await obj.read(decode=True) - assert thing[:-2] == result + with Stream(thing + b"%s--:--" % newline) as stream: + obj = aiohttp.BodyPartReader( + BOUNDARY, + {CONTENT_ENCODING: "identity"}, + stream, + ) + result = await obj.read(decode=True) + assert thing == result async def test_read_with_content_encoding_unknown(self) -> None: - obj = aiohttp.BodyPartReader( - BOUNDARY, - {CONTENT_ENCODING: "snappy"}, - Stream(b"\x0e4Time to Relax!\r\n--:--"), - ) - with pytest.raises(RuntimeError): - await obj.read(decode=True) + with Stream(b"\x0e4Time to Relax!%s--:--" % newline) as stream: + obj = aiohttp.BodyPartReader( + BOUNDARY, + {CONTENT_ENCODING: "snappy"}, + stream, + ) + with pytest.raises(RuntimeError): + await obj.read(decode=True) async def test_read_with_content_transfer_encoding_base64(self) -> None: - obj = aiohttp.BodyPartReader( - BOUNDARY, - {CONTENT_TRANSFER_ENCODING: "base64"}, - Stream(b"VGltZSB0byBSZWxheCE=\r\n--:--"), - ) - result = await obj.read(decode=True) + with Stream(b"VGltZSB0byBSZWxheCE=%s--:--" % newline) as stream: + obj = aiohttp.BodyPartReader( + BOUNDARY, + {CONTENT_TRANSFER_ENCODING: "base64"}, + stream, + ) + result = await obj.read(decode=True) assert b"Time to Relax!" == result async def test_read_with_content_transfer_encoding_quoted_printable(self) -> None: - obj = aiohttp.BodyPartReader( - BOUNDARY, - {CONTENT_TRANSFER_ENCODING: "quoted-printable"}, - Stream( - b"=D0=9F=D1=80=D0=B8=D0=B2=D0=B5=D1=82," - b" =D0=BC=D0=B8=D1=80!\r\n--:--" - ), - ) - result = await obj.read(decode=True) + with Stream( + b"=D0=9F=D1=80=D0=B8=D0=B2=D0=B5=D1=82," + b" =D0=BC=D0=B8=D1=80!%s--:--" % newline + ) as stream: + obj = aiohttp.BodyPartReader( + BOUNDARY, + {CONTENT_TRANSFER_ENCODING: "quoted-printable"}, + stream, + ) + result = await obj.read(decode=True) expected = ( b"\xd0\x9f\xd1\x80\xd0\xb8\xd0\xb2\xd0\xb5\xd1\x82," b" \xd0\xbc\xd0\xb8\xd1\x80!" @@ -354,187 +390,249 @@ async def test_read_with_content_transfer_encoding_quoted_printable(self) -> Non assert result == expected @pytest.mark.parametrize("encoding", ("binary", "8bit", "7bit")) - async def test_read_with_content_transfer_encoding_binary(self, encoding) -> None: + async def test_read_with_content_transfer_encoding_binary( + self, encoding: str + ) -> None: data = ( b"\xd0\x9f\xd1\x80\xd0\xb8\xd0\xb2\xd0\xb5\xd1\x82," b" \xd0\xbc\xd0\xb8\xd1\x80!" ) - obj = aiohttp.BodyPartReader( - BOUNDARY, {CONTENT_TRANSFER_ENCODING: encoding}, Stream(data + b"\r\n--:--") - ) - result = await obj.read(decode=True) + with Stream(data + b"%s--:--" % newline) as stream: + obj = aiohttp.BodyPartReader( + BOUNDARY, + {CONTENT_TRANSFER_ENCODING: encoding}, + stream, + ) + result = await obj.read(decode=True) assert data == result async def test_read_with_content_transfer_encoding_unknown(self) -> None: - obj = aiohttp.BodyPartReader( - BOUNDARY, - {CONTENT_TRANSFER_ENCODING: "unknown"}, - Stream(b"\x0e4Time to Relax!\r\n--:--"), - ) - with pytest.raises(RuntimeError): - await obj.read(decode=True) + with Stream(b"\x0e4Time to Relax!%s--:--" % newline) as stream: + obj = aiohttp.BodyPartReader( + BOUNDARY, + {CONTENT_TRANSFER_ENCODING: "unknown"}, + stream, + ) + with pytest.raises(RuntimeError): + await obj.read(decode=True) async def test_read_text(self) -> None: - obj = aiohttp.BodyPartReader(BOUNDARY, {}, Stream(b"Hello, world!\r\n--:--")) - result = await obj.text() + with Stream(b"Hello, world!%s--:--" % newline) as stream: + obj = aiohttp.BodyPartReader( + BOUNDARY, + {}, + stream, + ) + result = await obj.text() assert "Hello, world!" == result async def test_read_text_default_encoding(self) -> None: - obj = aiohttp.BodyPartReader( - BOUNDARY, {}, Stream("Привет, Мир!\r\n--:--".encode()) - ) - result = await obj.text() - assert "Привет, Мир!" == result + data = "Привет, Мир!" + tail = b"%s--:--" % newline + with Stream(data.encode("utf-8") + tail) as stream: + obj = aiohttp.BodyPartReader( + BOUNDARY, + {}, + stream, + ) + result = await obj.text() + assert data == result async def test_read_text_encoding(self) -> None: - obj = aiohttp.BodyPartReader( - BOUNDARY, {}, Stream("Привет, Мир!\r\n--:--".encode("cp1251")) - ) - result = await obj.text(encoding="cp1251") - assert "Привет, Мир!" == result + data = "Привет, Мир!" + tail = b"%s--:--" % newline + with Stream(data.encode("cp1251") + tail) as stream: + obj = aiohttp.BodyPartReader( + BOUNDARY, + {}, + stream, + ) + result = await obj.text(encoding="cp1251") + assert data == result async def test_read_text_guess_encoding(self) -> None: - obj = aiohttp.BodyPartReader( - BOUNDARY, - {CONTENT_TYPE: "text/plain;charset=cp1251"}, - Stream("Привет, Мир!\r\n--:--".encode("cp1251")), - ) - result = await obj.text() - assert "Привет, Мир!" == result + data = "Привет, Мир!" + tail = b"%s--:--" % newline + with Stream(data.encode("cp1251") + tail) as stream: + obj = aiohttp.BodyPartReader( + BOUNDARY, + {CONTENT_TYPE: "text/plain;charset=cp1251"}, + stream, + ) + result = await obj.text() + assert data == result async def test_read_text_compressed(self) -> None: - obj = aiohttp.BodyPartReader( - BOUNDARY, - {CONTENT_ENCODING: "deflate", CONTENT_TYPE: "text/plain"}, - Stream(b"\x0b\xc9\xccMU(\xc9W\x08J\xcdI\xacP\x04\x00\r\n--:--"), - ) - result = await obj.text() + data = b"\x0b\xc9\xccMU(\xc9W\x08J\xcdI\xacP\x04\x00" b"%s--:--" % newline + with Stream(data) as stream: + obj = aiohttp.BodyPartReader( + BOUNDARY, + {CONTENT_ENCODING: "deflate", CONTENT_TYPE: "text/plain"}, + stream, + ) + result = await obj.text() assert "Time to Relax!" == result async def test_read_text_while_closed(self) -> None: - obj = aiohttp.BodyPartReader( - BOUNDARY, {CONTENT_TYPE: "text/plain"}, Stream(b"") - ) - obj._at_eof = True - result = await obj.text() + with Stream(b"") as stream: + obj = aiohttp.BodyPartReader(BOUNDARY, {CONTENT_TYPE: "text/plain"}, stream) + obj._at_eof = True + result = await obj.text() assert "" == result async def test_read_json(self) -> None: - obj = aiohttp.BodyPartReader( - BOUNDARY, - {CONTENT_TYPE: "application/json"}, - Stream(b'{"test": "passed"}\r\n--:--'), - ) - result = await obj.json() + with Stream(b'{"test": "passed"}%s--:--' % newline) as stream: + obj = aiohttp.BodyPartReader( + BOUNDARY, + {CONTENT_TYPE: "application/json"}, + stream, + ) + result = await obj.json() assert {"test": "passed"} == result async def test_read_json_encoding(self) -> None: - obj = aiohttp.BodyPartReader( - BOUNDARY, - {CONTENT_TYPE: "application/json"}, - Stream('{"тест": "пассед"}\r\n--:--'.encode("cp1251")), - ) - result = await obj.json(encoding="cp1251") + data = '{"тест": "пассед"}'.encode("cp1251") + tail = b"%s--:--" % newline + with Stream(data + tail) as stream: + obj = aiohttp.BodyPartReader( + BOUNDARY, + {CONTENT_TYPE: "application/json"}, + stream, + ) + result = await obj.json(encoding="cp1251") assert {"тест": "пассед"} == result async def test_read_json_guess_encoding(self) -> None: - obj = aiohttp.BodyPartReader( - BOUNDARY, - {CONTENT_TYPE: "application/json; charset=cp1251"}, - Stream('{"тест": "пассед"}\r\n--:--'.encode("cp1251")), - ) - result = await obj.json() + data = '{"тест": "пассед"}'.encode("cp1251") + tail = b"%s--:--" % newline + with Stream(data + tail) as stream: + obj = aiohttp.BodyPartReader( + BOUNDARY, + {CONTENT_TYPE: "application/json; charset=cp1251"}, + stream, + ) + result = await obj.json() assert {"тест": "пассед"} == result async def test_read_json_compressed(self) -> None: - obj = aiohttp.BodyPartReader( - BOUNDARY, - {CONTENT_ENCODING: "deflate", CONTENT_TYPE: "application/json"}, - Stream(b"\xabV*I-.Q\xb2RP*H,.NMQ\xaa\x05\x00\r\n--:--"), - ) - result = await obj.json() + with Stream( + b"\xabV*I-.Q\xb2RP*H,.NMQ\xaa\x05\x00" b"%s--:--" % newline + ) as stream: + obj = aiohttp.BodyPartReader( + BOUNDARY, + {CONTENT_ENCODING: "deflate", CONTENT_TYPE: "application/json"}, + stream, + ) + result = await obj.json() assert {"test": "passed"} == result async def test_read_json_while_closed(self) -> None: - stream = Stream(b"") - obj = aiohttp.BodyPartReader( - BOUNDARY, {CONTENT_TYPE: "application/json"}, stream - ) - obj._at_eof = True - result = await obj.json() + with Stream(b"") as stream: + obj = aiohttp.BodyPartReader( + BOUNDARY, {CONTENT_TYPE: "application/json"}, stream + ) + obj._at_eof = True + result = await obj.json() assert result is None async def test_read_form(self) -> None: - obj = aiohttp.BodyPartReader( - BOUNDARY, - {CONTENT_TYPE: "application/x-www-form-urlencoded"}, - Stream(b"foo=bar&foo=baz&boo=\r\n--:--"), - ) - result = await obj.form() + data = b"foo=bar&foo=baz&boo=%s--:--" % newline + with Stream(data) as stream: + obj = aiohttp.BodyPartReader( + BOUNDARY, + {CONTENT_TYPE: "application/x-www-form-urlencoded"}, + stream, + ) + result = await obj.form() assert [("foo", "bar"), ("foo", "baz"), ("boo", "")] == result async def test_read_form_encoding(self) -> None: - obj = aiohttp.BodyPartReader( - BOUNDARY, - {CONTENT_TYPE: "application/x-www-form-urlencoded"}, - Stream("foo=bar&foo=baz&boo=\r\n--:--".encode("cp1251")), - ) - result = await obj.form(encoding="cp1251") + data = b"foo=bar&foo=baz&boo=%s--:--" % newline + with Stream(data) as stream: + obj = aiohttp.BodyPartReader( + BOUNDARY, + {CONTENT_TYPE: "application/x-www-form-urlencoded"}, + stream, + ) + result = await obj.form(encoding="cp1251") assert [("foo", "bar"), ("foo", "baz"), ("boo", "")] == result async def test_read_form_guess_encoding(self) -> None: - obj = aiohttp.BodyPartReader( - BOUNDARY, - {CONTENT_TYPE: "application/x-www-form-urlencoded; charset=utf-8"}, - Stream(b"foo=bar&foo=baz&boo=\r\n--:--"), - ) - result = await obj.form() + data = b"foo=bar&foo=baz&boo=%s--:--" % newline + with Stream(data) as stream: + obj = aiohttp.BodyPartReader( + BOUNDARY, + {CONTENT_TYPE: "application/x-www-form-urlencoded; charset=utf-8"}, + stream, + ) + result = await obj.form() assert [("foo", "bar"), ("foo", "baz"), ("boo", "")] == result async def test_read_form_while_closed(self) -> None: - stream = Stream(b"") - obj = aiohttp.BodyPartReader( - BOUNDARY, {CONTENT_TYPE: "application/x-www-form-urlencoded"}, stream - ) - obj._at_eof = True - result = await obj.form() + with Stream(b"") as stream: + obj = aiohttp.BodyPartReader( + BOUNDARY, + {CONTENT_TYPE: "application/x-www-form-urlencoded"}, + stream, + ) + obj._at_eof = True + result = await obj.form() assert not result async def test_readline(self) -> None: - obj = aiohttp.BodyPartReader( - BOUNDARY, {}, Stream(b"Hello\n,\r\nworld!\r\n--:--") - ) - result = await obj.readline() - assert b"Hello\n" == result - result = await obj.readline() - assert b",\r\n" == result - result = await obj.readline() - assert b"world!" == result - result = await obj.readline() - assert b"" == result - assert obj.at_eof() + data = b"Hello\n,\r\nworld!%s--:--" % newline + with Stream(data) as stream: + obj = aiohttp.BodyPartReader( + BOUNDARY, + {}, + stream, + ) + result = await obj.readline() + assert b"Hello\n" == result + result = await obj.readline() + assert b",\r\n" == result + result = await obj.readline() + assert b"world!" == result + result = await obj.readline() + assert b"" == result + assert obj.at_eof() async def test_release(self) -> None: - stream = Stream(b"Hello,\r\n--:\r\n\r\nworld!\r\n--:--") - obj = aiohttp.BodyPartReader(BOUNDARY, {}, stream) - await obj.release() - assert obj.at_eof() - assert b"--:\r\n\r\nworld!\r\n--:--" == stream.content.read() + data = b"Hello,%s--:\r\n\r\nworld!%s--:--" % (newline, newline) + with Stream(data) as stream: + obj = aiohttp.BodyPartReader( + BOUNDARY, + {}, + stream, + ) + remained = b"--:\r\n\r\nworld!%s--:--" % newline + await obj.release() + assert obj.at_eof() + assert remained == stream.content.read() async def test_release_respects_content_length(self) -> None: - obj = aiohttp.BodyPartReader( - BOUNDARY, {"CONTENT-LENGTH": 100500}, Stream(b"." * 100500 + b"\r\n--:--") - ) - result = await obj.release() - assert result is None - assert obj.at_eof() + with Stream(b"." * 100500 + b"%s--:--" % newline) as stream: + obj = aiohttp.BodyPartReader( + BOUNDARY, + {"CONTENT-LENGTH": 100500}, + stream, + ) + result = await obj.release() + assert result is None + assert obj.at_eof() async def test_release_release(self) -> None: - stream = Stream(b"Hello,\r\n--:\r\n\r\nworld!\r\n--:--") - obj = aiohttp.BodyPartReader(BOUNDARY, {}, stream) - await obj.release() - await obj.release() - assert b"--:\r\n\r\nworld!\r\n--:--" == stream.content.read() + data = b"Hello,%s--:\r\n\r\nworld!%s--:--" % (newline, newline) + remained = b"--:\r\n\r\nworld!%s--:--" % newline + with Stream(data) as stream: + obj = aiohttp.BodyPartReader( + BOUNDARY, + {}, + stream, + ) + await obj.release() + await obj.release() + assert remained == stream.content.read() async def test_filename(self) -> None: part = aiohttp.BodyPartReader( @@ -543,9 +641,9 @@ async def test_filename(self) -> None: assert "foo.html" == part.filename async def test_reading_long_part(self) -> None: - size = 2 * 2 ** 16 + size = 2 * 2**16 protocol = mock.Mock(_reading_paused=False) - stream = StreamReader(protocol, 2 ** 16, loop=asyncio.get_event_loop()) + stream = StreamReader(protocol, 2**16, loop=asyncio.get_event_loop()) stream.feed_data(b"0" * size + b"\r\n--:--") stream.feed_eof() obj = aiohttp.BodyPartReader(BOUNDARY, {}, stream) @@ -555,54 +653,62 @@ async def test_reading_long_part(self) -> None: class TestMultipartReader: def test_from_response(self) -> None: - resp = Response( - {CONTENT_TYPE: 'multipart/related;boundary=":"'}, - Stream(b"--:\r\n\r\nhello\r\n--:--"), - ) - res = aiohttp.MultipartReader.from_response(resp) + with Stream(b"--:%s\r\nhello%s--:--" % (newline, newline)) as stream: + resp = Response( + {CONTENT_TYPE: 'multipart/related;boundary=":"'}, + stream, + ) + res = aiohttp.MultipartReader.from_response(resp) assert isinstance(res, MultipartResponseWrapper) assert isinstance(res.stream, aiohttp.MultipartReader) def test_bad_boundary(self) -> None: - resp = Response( - {CONTENT_TYPE: "multipart/related;boundary=" + "a" * 80}, Stream(b"") - ) - with pytest.raises(ValueError): - aiohttp.MultipartReader.from_response(resp) + with Stream(b"") as stream: + resp = Response( + {CONTENT_TYPE: "multipart/related;boundary=" + "a" * 80}, stream + ) + with pytest.raises(ValueError): + aiohttp.MultipartReader.from_response(resp) def test_dispatch(self) -> None: - reader = aiohttp.MultipartReader( - {CONTENT_TYPE: 'multipart/related;boundary=":"'}, - Stream(b"--:\r\n\r\necho\r\n--:--"), - ) - res = reader._get_part_reader({CONTENT_TYPE: "text/plain"}) + with Stream(b"--:%s\r\necho%s--:--" % (newline, newline)) as stream: + reader = aiohttp.MultipartReader( + {CONTENT_TYPE: 'multipart/related;boundary=":"'}, + stream, + ) + res = reader._get_part_reader({CONTENT_TYPE: "text/plain"}) assert isinstance(res, reader.part_reader_cls) def test_dispatch_bodypart(self) -> None: - reader = aiohttp.MultipartReader( - {CONTENT_TYPE: 'multipart/related;boundary=":"'}, - Stream(b"--:\r\n\r\necho\r\n--:--"), - ) - res = reader._get_part_reader({CONTENT_TYPE: "text/plain"}) + with Stream(b"--:%s\r\necho%s--:--" % (newline, newline)) as stream: + reader = aiohttp.MultipartReader( + {CONTENT_TYPE: 'multipart/related;boundary=":"'}, + stream, + ) + res = reader._get_part_reader({CONTENT_TYPE: "text/plain"}) assert isinstance(res, reader.part_reader_cls) def test_dispatch_multipart(self) -> None: - reader = aiohttp.MultipartReader( - {CONTENT_TYPE: 'multipart/related;boundary=":"'}, - Stream( - b"----:--\r\n" - b"\r\n" - b"test\r\n" - b"----:--\r\n" - b"\r\n" - b"passed\r\n" - b"----:----\r\n" - b"--:--" - ), - ) - res = reader._get_part_reader( - {CONTENT_TYPE: "multipart/related;boundary=--:--"} - ) + with Stream( + newline.join( + [ + b"----:--", + b"", + b"test", + b"----:--", + b"", + b"passed", + b"----:----" b"--:--", + ] + ) + ) as stream: + reader = aiohttp.MultipartReader( + {CONTENT_TYPE: 'multipart/related;boundary=":"'}, + stream, + ) + res = reader._get_part_reader( + {CONTENT_TYPE: "multipart/related;boundary=--:--"} + ) assert isinstance(res, reader.__class__) def test_dispatch_custom_multipart_reader(self) -> None: @@ -629,160 +735,212 @@ class CustomReader(aiohttp.MultipartReader): assert isinstance(res, CustomReader) async def test_emit_next(self) -> None: - reader = aiohttp.MultipartReader( - {CONTENT_TYPE: 'multipart/related;boundary=":"'}, - Stream(b"--:\r\n\r\necho\r\n--:--"), - ) - res = await reader.next() + with Stream(b"--:%s\r\necho%s--:--" % (newline, newline)) as stream: + reader = aiohttp.MultipartReader( + {CONTENT_TYPE: 'multipart/related;boundary=":"'}, + stream, + ) + res = await reader.next() assert isinstance(res, reader.part_reader_cls) async def test_invalid_boundary(self) -> None: - reader = aiohttp.MultipartReader( - {CONTENT_TYPE: 'multipart/related;boundary=":"'}, - Stream(b"---:\r\n\r\necho\r\n---:--"), - ) - with pytest.raises(ValueError): - await reader.next() + with Stream(b"---:%s\r\necho%s---:--" % (newline, newline)) as stream: + reader = aiohttp.MultipartReader( + {CONTENT_TYPE: 'multipart/related;boundary=":"'}, + stream, + ) + with pytest.raises(ValueError): + await reader.next() async def test_release(self) -> None: - reader = aiohttp.MultipartReader( - {CONTENT_TYPE: 'multipart/mixed;boundary=":"'}, - Stream( - b"--:\r\n" - b"Content-Type: multipart/related;boundary=--:--\r\n" - b"\r\n" - b"----:--\r\n" - b"\r\n" - b"test\r\n" - b"----:--\r\n" - b"\r\n" - b"passed\r\n" - b"----:----\r\n" - b"\r\n" - b"--:--" - ), - ) - await reader.release() - assert reader.at_eof() + with Stream( + newline.join( + [ + b"--:", + b"Content-Type: multipart/related;boundary=--:--", + b"", + b"----:--", + b"", + b"test", + b"----:--", + b"", + b"passed", + b"----:----", + b"", + b"--:--", + ] + ) + ) as stream: + reader = aiohttp.MultipartReader( + {CONTENT_TYPE: 'multipart/mixed;boundary=":"'}, + stream, + ) + await reader.release() + assert reader.at_eof() async def test_release_release(self) -> None: - reader = aiohttp.MultipartReader( - {CONTENT_TYPE: 'multipart/related;boundary=":"'}, - Stream(b"--:\r\n\r\necho\r\n--:--"), - ) - await reader.release() - assert reader.at_eof() - await reader.release() - assert reader.at_eof() + with Stream(b"--:%s\r\necho%s--:--" % (newline, newline)) as stream: + reader = aiohttp.MultipartReader( + {CONTENT_TYPE: 'multipart/related;boundary=":"'}, + stream, + ) + await reader.release() + assert reader.at_eof() + await reader.release() + assert reader.at_eof() async def test_release_next(self) -> None: - reader = aiohttp.MultipartReader( - {CONTENT_TYPE: 'multipart/related;boundary=":"'}, - Stream(b"--:\r\n\r\necho\r\n--:--"), - ) - await reader.release() - assert reader.at_eof() - res = await reader.next() - assert res is None + with Stream(b"--:%s\r\necho%s--:--" % (newline, newline)) as stream: + reader = aiohttp.MultipartReader( + {CONTENT_TYPE: 'multipart/related;boundary=":"'}, + stream, + ) + await reader.release() + assert reader.at_eof() + res = await reader.next() + assert res is None async def test_second_next_releases_previous_object(self) -> None: - reader = aiohttp.MultipartReader( - {CONTENT_TYPE: 'multipart/related;boundary=":"'}, - Stream( - b"--:\r\n" b"\r\n" b"test\r\n" b"--:\r\n" b"\r\n" b"passed\r\n" b"--:--" - ), - ) - first = await reader.next() - assert isinstance(first, aiohttp.BodyPartReader) - second = await reader.next() - assert first.at_eof() - assert not second.at_eof() + with Stream( + newline.join( + [ + b"--:", + b"", + b"test", + b"--:", + b"", + b"passed", + b"--:--", + ] + ) + ) as stream: + reader = aiohttp.MultipartReader( + {CONTENT_TYPE: 'multipart/related;boundary=":"'}, + stream, + ) + first = await reader.next() + assert isinstance(first, aiohttp.BodyPartReader) + second = await reader.next() + assert first.at_eof() + assert not second.at_eof() async def test_release_without_read_the_last_object(self) -> None: - reader = aiohttp.MultipartReader( - {CONTENT_TYPE: 'multipart/related;boundary=":"'}, - Stream( - b"--:\r\n" b"\r\n" b"test\r\n" b"--:\r\n" b"\r\n" b"passed\r\n" b"--:--" - ), - ) - first = await reader.next() - second = await reader.next() - third = await reader.next() - assert first.at_eof() - assert second.at_eof() - assert second.at_eof() - assert third is None + with Stream( + newline.join( + [ + b"--:", + b"", + b"test", + b"--:", + b"", + b"passed", + b"--:--", + ] + ) + ) as stream: + reader = aiohttp.MultipartReader( + {CONTENT_TYPE: 'multipart/related;boundary=":"'}, + stream, + ) + first = await reader.next() + second = await reader.next() + third = await reader.next() + + assert first.at_eof() + assert second.at_eof() + assert second.at_eof() + assert third is None async def test_read_chunk_by_length_doesnt_breaks_reader(self) -> None: - reader = aiohttp.MultipartReader( - {CONTENT_TYPE: 'multipart/related;boundary=":"'}, - Stream( - b"--:\r\n" - b"Content-Length: 4\r\n\r\n" - b"test" - b"\r\n--:\r\n" - b"Content-Length: 6\r\n\r\n" - b"passed" - b"\r\n--:--" - ), - ) - body_parts = [] - while True: - read_part = b"" - part = await reader.next() - if part is None: - break - while not part.at_eof(): - read_part += await part.read_chunk(3) - body_parts.append(read_part) + with Stream( + newline.join( + [ + b"--:", + b"Content-Length: 4", + b"", + b"test", + b"--:", + b"Content-Length: 6", + b"", + b"passed", + b"--:--", + ] + ) + ) as stream: + reader = aiohttp.MultipartReader( + {CONTENT_TYPE: 'multipart/related;boundary=":"'}, + stream, + ) + body_parts = [] + while True: + read_part = b"" + part = await reader.next() + if part is None: + break + while not part.at_eof(): + read_part += await part.read_chunk(3) + body_parts.append(read_part) + assert body_parts == [b"test", b"passed"] async def test_read_chunk_from_stream_doesnt_breaks_reader(self) -> None: - reader = aiohttp.MultipartReader( - {CONTENT_TYPE: 'multipart/related;boundary=":"'}, - Stream( - b"--:\r\n" - b"\r\n" - b"chunk" - b"\r\n--:\r\n" - b"\r\n" - b"two_chunks" - b"\r\n--:--" - ), - ) - body_parts = [] - while True: - read_part = b"" - part = await reader.next() - if part is None: - break - while not part.at_eof(): - chunk = await part.read_chunk(5) - assert chunk - read_part += chunk - body_parts.append(read_part) + with Stream( + newline.join( + [ + b"--:", + b"", + b"chunk", + b"--:", + b"", + b"two_chunks", + b"--:--", + ] + ) + ) as stream: + reader = aiohttp.MultipartReader( + {CONTENT_TYPE: 'multipart/related;boundary=":"'}, + stream, + ) + body_parts = [] + while True: + read_part = b"" + part = await reader.next() + if part is None: + break + while not part.at_eof(): + chunk = await part.read_chunk(5) + assert chunk + read_part += chunk + body_parts.append(read_part) + assert body_parts == [b"chunk", b"two_chunks"] async def test_reading_skips_prelude(self) -> None: - reader = aiohttp.MultipartReader( - {CONTENT_TYPE: 'multipart/related;boundary=":"'}, - Stream( - b"Multi-part data is not supported.\r\n" - b"\r\n" - b"--:\r\n" - b"\r\n" - b"test\r\n" - b"--:\r\n" - b"\r\n" - b"passed\r\n" - b"--:--" - ), - ) - first = await reader.next() - assert isinstance(first, aiohttp.BodyPartReader) - second = await reader.next() - assert first.at_eof() - assert not second.at_eof() + with Stream( + newline.join( + [ + b"Multi-part data is not supported.", + b"", + b"--:", + b"", + b"test", + b"--:", + b"", + b"passed", + b"--:--", + ] + ) + ) as stream: + reader = aiohttp.MultipartReader( + {CONTENT_TYPE: 'multipart/related;boundary=":"'}, + stream, + ) + first = await reader.next() + assert isinstance(first, aiohttp.BodyPartReader) + second = await reader.next() + + assert first.at_eof() + assert not second.at_eof() async def test_writer(writer) -> None: @@ -791,9 +949,9 @@ async def test_writer(writer) -> None: async def test_writer_serialize_io_chunk(buf, stream, writer) -> None: - flo = io.BytesIO(b"foobarbaz") - writer.append(flo) - await writer.write(stream) + with io.BytesIO(b"foobarbaz") as file_handle: + writer.append(file_handle) + await writer.write(stream) assert ( buf == b"--:\r\nContent-Type: application/octet-stream" b"\r\nContent-Length: 9\r\n\r\nfoobarbaz\r\n--:--\r\n" @@ -1105,7 +1263,7 @@ async def test_write_preserves_content_disposition(self, buf, stream) -> None: b"Content-Type: test/passed\r\n" b"Content-Length: 3\r\n" b"Content-Disposition:" - b" form-data; filename=\"bug\"; filename*=utf-8''bug" + b' form-data; filename="bug"' ) assert message == b"foo\r\n--:--\r\n" @@ -1186,7 +1344,7 @@ async def test_reset_content_disposition_header(self, buf, stream): b"--:\r\n" b"Content-Type: text/plain\r\n" b"Content-Disposition:" - b" attachments; filename=\"bug.py\"; filename*=utf-8''bug.py\r\n" + b' attachments; filename="bug.py"\r\n' b"Content-Length: %s" b"" % (str(content_length).encode(),) ) @@ -1194,68 +1352,68 @@ async def test_reset_content_disposition_header(self, buf, stream): async def test_async_for_reader() -> None: data = [{"test": "passed"}, 42, b"plain text", b"aiohttp\n", b"no epilogue"] - reader = aiohttp.MultipartReader( - headers={CONTENT_TYPE: 'multipart/mixed; boundary=":"'}, - content=Stream( - b"\r\n".join( - [ - b"--:", - b"Content-Type: application/json", - b"", - json.dumps(data[0]).encode(), - b"--:", - b"Content-Type: application/json", - b"", - json.dumps(data[1]).encode(), - b"--:", - b'Content-Type: multipart/related; boundary="::"', - b"", - b"--::", - b"Content-Type: text/plain", - b"", - data[2], - b"--::", - b'Content-Disposition: attachment; filename="aiohttp"', - b"Content-Type: text/plain", - b"Content-Length: 28", - b"Content-Encoding: gzip", - b"", - b"\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x03K\xcc\xcc\xcf())" - b"\xe0\x02\x00\xd6\x90\xe2O\x08\x00\x00\x00", - b"--::", - b'Content-Type: multipart/related; boundary=":::"', - b"", - b"--:::", - b"Content-Type: text/plain", - b"", - data[4], - b"--:::--", - b"--::--", - b"", - b"--:--", - b"", - ] - ) - ), - ) - idata = iter(data) - - async def check(reader): - async for part in reader: - if isinstance(part, aiohttp.BodyPartReader): - if part.headers[CONTENT_TYPE] == "application/json": - assert next(idata) == (await part.json()) + with Stream( + b"\r\n".join( + [ + b"--:", + b"Content-Type: application/json", + b"", + json.dumps(data[0]).encode(), + b"--:", + b"Content-Type: application/json", + b"", + json.dumps(data[1]).encode(), + b"--:", + b'Content-Type: multipart/related; boundary="::"', + b"", + b"--::", + b"Content-Type: text/plain", + b"", + data[2], + b"--::", + b'Content-Disposition: attachment; filename="aiohttp"', + b"Content-Type: text/plain", + b"Content-Length: 28", + b"Content-Encoding: gzip", + b"", + b"\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x03K\xcc\xcc\xcf())" + b"\xe0\x02\x00\xd6\x90\xe2O\x08\x00\x00\x00", + b"--::", + b'Content-Type: multipart/related; boundary=":::"', + b"", + b"--:::", + b"Content-Type: text/plain", + b"", + data[4], + b"--:::--", + b"--::--", + b"", + b"--:--", + b"", + ] + ) + ) as stream: + reader = aiohttp.MultipartReader( + headers={CONTENT_TYPE: 'multipart/mixed; boundary=":"'}, + content=stream, + ) + idata = iter(data) + + async def check(reader): + async for part in reader: + if isinstance(part, aiohttp.BodyPartReader): + if part.headers[CONTENT_TYPE] == "application/json": + assert next(idata) == (await part.json()) + else: + assert next(idata) == await part.read(decode=True) else: - assert next(idata) == await part.read(decode=True) - else: - await check(part) + await check(part) - await check(reader) + await check(reader) async def test_async_for_bodypart() -> None: - part = aiohttp.BodyPartReader( - boundary=b"--:", headers={}, content=Stream(b"foobarbaz\r\n--:--") - ) - async for data in part: - assert data == b"foobarbaz" + with Stream(b"foobarbaz\r\n--:--") as stream: + part = aiohttp.BodyPartReader(boundary=b"--:", headers={}, content=stream) + async for data in part: + assert data == b"foobarbaz" diff --git a/tests/test_payload.py b/tests/test_payload.py index c075dba..c8681cb 100644 --- a/tests/test_payload.py +++ b/tests/test_payload.py @@ -4,7 +4,6 @@ from unittest import mock import pytest -from async_generator import async_generator from aiohttp import payload, streams @@ -36,7 +35,9 @@ class TestProvider: pass with pytest.raises(ValueError): - payload.register_payload(Payload, TestProvider, order=object()) + payload.register_payload( + Payload, TestProvider, order=object() # type: ignore[arg-type] + ) def test_payload_ctor() -> None: @@ -65,7 +66,7 @@ def test_bytes_payload_explicit_content_type() -> None: def test_bytes_payload_bad_type() -> None: with pytest.raises(TypeError): - payload.BytesPayload(object()) + payload.BytesPayload(object()) # type: ignore[arg-type] def test_bytes_payload_memoryview_correct_size() -> None: @@ -97,18 +98,18 @@ def test_string_io_payload() -> None: def test_async_iterable_payload_default_content_type() -> None: - @async_generator async def gen(): - pass + return + yield p = payload.AsyncIterablePayload(gen()) assert p.content_type == "application/octet-stream" def test_async_iterable_payload_explicit_content_type() -> None: - @async_generator async def gen(): - pass + return + yield p = payload.AsyncIterablePayload(gen(), content_type="application/custom") assert p.content_type == "application/custom" @@ -122,9 +123,9 @@ def test_async_iterable_payload_not_async_iterable() -> None: async def test_stream_reader_long_lines() -> None: loop = asyncio.get_event_loop() - DATA = b"0" * 1024 ** 3 + DATA = b"0" * 1024**3 - stream = streams.StreamReader(mock.Mock(), 2 ** 16, loop=loop) + stream = streams.StreamReader(mock.Mock(), 2**16, loop=loop) stream.feed_data(DATA) stream.feed_eof() body = payload.get_payload(stream) diff --git a/tests/test_proxy.py b/tests/test_proxy.py index 3b1bf0c..25bcb64 100644 --- a/tests/test_proxy.py +++ b/tests/test_proxy.py @@ -5,11 +5,12 @@ import unittest from unittest import mock +import pytest from yarl import URL import aiohttp from aiohttp.client_reqrep import ClientRequest, ClientResponse -from aiohttp.helpers import TimerNoop +from aiohttp.helpers import PY_37, TimerNoop from aiohttp.test_utils import make_mocked_coro @@ -72,6 +73,8 @@ async def make_conn(): ssl=None, ) + conn.close() + @mock.patch("aiohttp.connector.ClientRequest") def test_proxy_headers(self, ClientRequestMock) -> None: req = ClientRequest( @@ -112,6 +115,8 @@ async def make_conn(): ssl=None, ) + conn.close() + def test_proxy_auth(self) -> None: with self.assertRaises(ValueError) as ctx: ClientRequest( @@ -221,6 +226,7 @@ async def make_conn(): tr, proto = mock.Mock(), mock.Mock() self.loop.create_connection = make_mocked_coro((tr, proto)) + self.loop.start_tls = make_mocked_coro(mock.Mock()) req = ClientRequest( "GET", @@ -235,8 +241,6 @@ async def make_conn(): self.assertEqual(req.url.path, "/") self.assertEqual(proxy_req.method, "CONNECT") self.assertEqual(proxy_req.url, URL("https://www.python.org")) - tr.close.assert_called_once_with() - tr.get_extra_info.assert_called_with("socket", default=None) self.loop.run_until_complete(proxy_req.close()) proxy_resp.close() @@ -280,22 +284,10 @@ async def make_conn(): ] ) - seq = 0 - - async def create_connection(*args, **kwargs): - nonlocal seq - seq += 1 - - # connection to http://proxy.example.com - if seq == 1: - return mock.Mock(), mock.Mock() - # connection to https://www.python.org - elif seq == 2: - raise ssl.CertificateError - else: - assert False - - self.loop.create_connection = create_connection + # Called on connection to http://proxy.example.com + self.loop.create_connection = make_mocked_coro((mock.Mock(), mock.Mock())) + # Called on connection to https://www.python.org + self.loop.start_tls = make_mocked_coro(raise_exception=ssl.CertificateError) req = ClientRequest( "GET", @@ -346,22 +338,12 @@ async def make_conn(): ] ) - seq = 0 - - async def create_connection(*args, **kwargs): - nonlocal seq - seq += 1 - - # connection to http://proxy.example.com - if seq == 1: - return mock.Mock(), mock.Mock() - # connection to https://www.python.org - elif seq == 2: - raise ssl.SSLError - else: - assert False - - self.loop.create_connection = create_connection + # Called on connection to http://proxy.example.com + self.loop.create_connection = make_mocked_coro( + (mock.Mock(), mock.Mock()), + ) + # Called on connection to https://www.python.org + self.loop.start_tls = make_mocked_coro(raise_exception=ssl.SSLError) req = ClientRequest( "GET", @@ -374,6 +356,11 @@ async def create_connection(*args, **kwargs): connector._create_connection(req, None, aiohttp.ClientTimeout()) ) + @pytest.mark.skipif( + PY_37, + reason="The tested code path is only reachable below Python 3.7 because those " + "versions don't yet have `asyncio.loop.start_tls()` implemeneted", + ) @mock.patch("aiohttp.connector.ClientRequest") def test_https_connect_runtime_error(self, ClientRequestMock) -> None: proxy_req = ClientRequest( @@ -643,6 +630,7 @@ async def make_conn(): tr, proto = mock.Mock(), mock.Mock() self.loop.create_connection = make_mocked_coro((tr, proto)) + self.loop.start_tls = make_mocked_coro(mock.Mock()) req = ClientRequest( "GET", @@ -654,18 +642,17 @@ async def make_conn(): connector._create_connection(req, None, aiohttp.ClientTimeout()) ) - self.loop.create_connection.assert_called_with( + self.loop.start_tls.assert_called_with( + mock.ANY, mock.ANY, - ssl=connector._make_ssl_context(True), - sock=mock.ANY, + connector._make_ssl_context(True), server_hostname="www.python.org", + ssl_handshake_timeout=mock.ANY, ) self.assertEqual(req.url.path, "/") self.assertEqual(proxy_req.method, "CONNECT") self.assertEqual(proxy_req.url, URL("https://www.python.org")) - tr.close.assert_called_once_with() - tr.get_extra_info.assert_called_with("socket", default=None) self.loop.run_until_complete(proxy_req.close()) proxy_resp.close() @@ -714,6 +701,7 @@ async def make_conn(): tr, proto = mock.Mock(), mock.Mock() self.loop.create_connection = make_mocked_coro((tr, proto)) + self.loop.start_tls = make_mocked_coro(mock.Mock()) self.assertIn("AUTHORIZATION", proxy_req.headers) self.assertNotIn("PROXY-AUTHORIZATION", proxy_req.headers) diff --git a/tests/test_proxy_functional.py b/tests/test_proxy_functional.py index 68763cd..e865ccd 100644 --- a/tests/test_proxy_functional.py +++ b/tests/test_proxy_functional.py @@ -1,13 +1,285 @@ import asyncio +import functools import os import pathlib +import platform +from re import match as match_regex from unittest import mock +from uuid import uuid4 +import proxy import pytest from yarl import URL import aiohttp from aiohttp import web +from aiohttp.client_exceptions import ClientConnectionError, ClientProxyConnectionError +from aiohttp.helpers import IS_MACOS, IS_WINDOWS, PY_37, PY_310 + +pytestmark = [ + pytest.mark.filterwarnings( + "ignore:unclosed None: + """Ensure HTTP(S) sites are accessible through a secure proxy.""" + conn = aiohttp.TCPConnector() + sess = aiohttp.ClientSession(connector=conn) + + response = await sess.get( + web_server_endpoint_url, + proxy=secure_proxy_url, + ssl=client_ssl_ctx, # used for both proxy and endpoint connections + ) + + assert response.status == 200 + assert await response.text() == web_server_endpoint_payload + + response.close() + await sess.close() + await conn.close() + + # https://docs.aiohttp.org/en/v3.8.0/client_advanced.html#graceful-shutdown + await asyncio.sleep(0.1) + + +@secure_proxy_xfail_under_py310_linux(raises=AssertionError) +@pytest.mark.xfail( + not PY_37, + raises=RuntimeError, + reason="`asyncio.loop.start_tls()` is only implemeneted in Python 3.7", +) +@pytest.mark.parametrize("web_server_endpoint_type", ("https",)) +@pytest.mark.usefixtures("loop") +async def test_https_proxy_unsupported_tls_in_tls( + client_ssl_ctx, + secure_proxy_url, + web_server_endpoint_type, +) -> None: + """Ensure connecting to TLS endpoints w/ HTTPS proxy needs patching. + + This also checks that a helpful warning on how to patch the env + is displayed. + """ + url = URL.build(scheme=web_server_endpoint_type, host="python.org") + + escaped_host_port = ":".join((url.host.replace(".", r"\."), str(url.port))) + escaped_proxy_url = str(secure_proxy_url).replace(".", r"\.") + + conn = aiohttp.TCPConnector() + sess = aiohttp.ClientSession(connector=conn) + + expected_warning_text = ( + r"^" + r"An HTTPS request is being sent through an HTTPS proxy\. " + "This support for TLS in TLS is known to be disabled " + r"in the stdlib asyncio\. This is why you'll probably see " + r"an error in the log below\.\n\n" + "It is possible to enable it via monkeypatching under " + r"Python 3\.7 or higher\. For more details, see:\n" + r"\* https://bugs\.python\.org/issue37179\n" + r"\* https://github\.com/python/cpython/pull/28073\n\n" + r"You can temporarily patch this as follows:\n" + r"\* https://docs\.aiohttp\.org/en/stable/client_advanced\.html#proxy-support\n" + r"\* https://github\.com/aio-libs/aiohttp/discussions/6044\n$" + ) + type_err = ( + r"transport is not supported by start_tls\(\)" + ) + expected_exception_reason = ( + r"^" + "Cannot initialize a TLS-in-TLS connection to host " + f"{escaped_host_port!s} through an underlying connection " + f"to an HTTPS proxy {escaped_proxy_url!s} ssl:{client_ssl_ctx!s} " + f"[{type_err!s}]" + r"$" + ) + + with pytest.warns(RuntimeWarning, match=expected_warning_text,), pytest.raises( + ClientConnectionError, + match=expected_exception_reason, + ) as conn_err: + await sess.get(url, proxy=secure_proxy_url, ssl=client_ssl_ctx) + + assert type(conn_err.value.__cause__) == TypeError + assert match_regex(f"^{type_err!s}$", str(conn_err.value.__cause__)) + + await sess.close() + await conn.close() + + +@pytest.mark.skipif( + PY_37, + reason="This test checks an error we emit below Python 3.7", +) +@pytest.mark.usefixtures("loop") +async def test_https_proxy_missing_start_tls() -> None: + """Ensure error is raised for TLS-in-TLS w/ no ``start_tls()``.""" + conn = aiohttp.TCPConnector() + sess = aiohttp.ClientSession(connector=conn) + + expected_exception_reason = ( + r"^" + r"An HTTPS request is being sent through an HTTPS proxy\. " + "This needs support for TLS in TLS but it is not implemented " + r"in your runtime for the stdlib asyncio\.\n\n" + r"Please upgrade to Python 3\.7 or higher\. For more details, " + r"please see:\n" + r"\* https://bugs\.python\.org/issue37179\n" + r"\* https://github\.com/python/cpython/pull/28073\n" + r"\* https://docs\.aiohttp\.org/en/stable/client_advanced\.html#proxy-support\n" + r"\* https://github\.com/aio-libs/aiohttp/discussions/6044\n" + r"$" + ) + + with pytest.raises( + RuntimeError, + match=expected_exception_reason, + ) as runtime_err: + await sess.get("https://python.org", proxy="https://proxy") + + await sess.close() + await conn.close() + + assert type(runtime_err.value.__cause__) is AttributeError + + selector_event_loop_type = "Windows" if IS_WINDOWS else "Unix" + attr_err = ( + f"^'_{selector_event_loop_type}SelectorEventLoop' object " + "has no attribute 'start_tls'$" + ) + assert match_regex(attr_err, str(runtime_err.value.__cause__)) @pytest.fixture @@ -81,29 +353,28 @@ async def test_proxy_http_absolute_path(proxy_test_server, get_request) -> None: assert len(proxy.requests_list) == 1 assert proxy.request.method == "GET" assert proxy.request.host == "aiohttp.io" - assert proxy.request.path_qs == "http://aiohttp.io/path?query=yes" + assert proxy.request.path_qs == "/path?query=yes" async def test_proxy_http_raw_path(proxy_test_server, get_request) -> None: url = "http://aiohttp.io:2561/space sheep?q=can:fly" - raw_url = "http://aiohttp.io:2561/space%20sheep?q=can:fly" + raw_url = "/space%20sheep?q=can:fly" proxy = await proxy_test_server() await get_request(url=url, proxy=proxy.url) - assert proxy.request.host == "aiohttp.io:2561" + assert proxy.request.host == "aiohttp.io" assert proxy.request.path_qs == raw_url async def test_proxy_http_idna_support(proxy_test_server, get_request) -> None: url = "http://éé.com/" - raw_url = "http://xn--9caa.com/" proxy = await proxy_test_server() await get_request(url=url, proxy=proxy.url) - assert proxy.request.host == "xn--9caa.com" - assert proxy.request.path_qs == raw_url + assert proxy.request.host == "éé.com" + assert proxy.request.path_qs == "/" async def test_proxy_http_connection_error(get_request) -> None: @@ -289,7 +560,7 @@ async def xtest_proxy_https_connect_with_port(proxy_test_server, get_request): async def xtest_proxy_https_send_body(proxy_test_server, loop): sess = aiohttp.ClientSession(loop=loop) proxy = await proxy_test_server() - proxy.return_value = {"status": 200, "body": b"1" * (2 ** 20)} + proxy.return_value = {"status": 200, "body": b"1" * (2**20)} url = "https://www.google.com.ua/search?q=aiohttp proxy" resp = await sess.get(url, proxy=proxy.url) @@ -297,7 +568,7 @@ async def xtest_proxy_https_send_body(proxy_test_server, loop): await resp.release() await sess.close() - assert body == b"1" * (2 ** 20) + assert body == b"1" * (2**20) @pytest.mark.xfail @@ -499,7 +770,7 @@ async def test_proxy_from_env_http(proxy_test_server, get_request, mocker) -> No assert len(proxy.requests_list) == 1 assert proxy.request.method == "GET" assert proxy.request.host == "aiohttp.io" - assert proxy.request.path_qs == "http://aiohttp.io/path" + assert proxy.request.path_qs == "/path" assert "Proxy-Authorization" not in proxy.request.headers @@ -521,7 +792,7 @@ async def test_proxy_from_env_http_with_auth(proxy_test_server, get_request, moc assert len(proxy.requests_list) == 1 assert proxy.request.method == "GET" assert proxy.request.host == "aiohttp.io" - assert proxy.request.path_qs == "http://aiohttp.io/path" + assert proxy.request.path_qs == "/path" assert proxy.request.headers["Proxy-Authorization"] == auth.encode() @@ -547,7 +818,7 @@ async def test_proxy_from_env_http_with_auth_from_netrc( assert len(proxy.requests_list) == 1 assert proxy.request.method == "GET" assert proxy.request.host == "aiohttp.io" - assert proxy.request.path_qs == "http://aiohttp.io/path" + assert proxy.request.path_qs == "/path" assert proxy.request.headers["Proxy-Authorization"] == auth.encode() @@ -573,7 +844,7 @@ async def test_proxy_from_env_http_without_auth_from_netrc( assert len(proxy.requests_list) == 1 assert proxy.request.method == "GET" assert proxy.request.host == "aiohttp.io" - assert proxy.request.path_qs == "http://aiohttp.io/path" + assert proxy.request.path_qs == "/path" assert "Proxy-Authorization" not in proxy.request.headers @@ -597,7 +868,7 @@ async def test_proxy_from_env_http_without_auth_from_wrong_netrc( assert len(proxy.requests_list) == 1 assert proxy.request.method == "GET" assert proxy.request.host == "aiohttp.io" - assert proxy.request.path_qs == "http://aiohttp.io/path" + assert proxy.request.path_qs == "/path" assert "Proxy-Authorization" not in proxy.request.headers @@ -613,7 +884,7 @@ async def xtest_proxy_from_env_https(proxy_test_server, get_request, mocker): assert len(proxy.requests_list) == 2 assert proxy.request.method == "GET" assert proxy.request.host == "aiohttp.io" - assert proxy.request.path_qs == "https://aiohttp.io/path" + assert proxy.request.path_qs == "/path" assert "Proxy-Authorization" not in proxy.request.headers diff --git a/tests/test_resolver.py b/tests/test_resolver.py index 199707e..6140e38 100644 --- a/tests/test_resolver.py +++ b/tests/test_resolver.py @@ -1,6 +1,7 @@ import asyncio import ipaddress import socket +from typing import Any, List from unittest.mock import Mock, patch import pytest @@ -39,7 +40,7 @@ async def fake(*args, **kwargs): if not hosts: raise socket.gaierror - return list([(None, None, None, None, [h, 0]) for h in hosts]) + return [(socket.AF_INET, None, socket.SOCK_STREAM, None, [h, 0]) for h in hosts] return fake @@ -153,11 +154,61 @@ async def test_threaded_negative_lookup() -> None: await resolver.resolve("doesnotexist.bla") +async def test_threaded_negative_lookup_with_unknown_result() -> None: + loop = Mock() + + # If compile CPython with `--disable-ipv6` option, + # we will get an (int, bytes) tuple, instead of a Exception. + async def unknown_addrinfo(*args: Any, **kwargs: Any) -> List[Any]: + return [ + ( + socket.AF_INET6, + socket.SOCK_STREAM, + 6, + "", + (10, b"\x01\xbb\x00\x00\x00\x00*\x04NB\x00\x1a\x00\x00"), + ) + ] + + loop.getaddrinfo = unknown_addrinfo + resolver = ThreadedResolver() + resolver._loop = loop + with patch("socket.has_ipv6", False): + res = await resolver.resolve("www.python.org") + assert len(res) == 0 + + async def test_close_for_threaded_resolver(loop) -> None: resolver = ThreadedResolver(loop=loop) await resolver.close() +async def test_threaded_negative_lookup_with_unknown_result() -> None: + loop = Mock() + + # If compile CPython with `--disable-ipv6` option, + # we will get an (int, bytes) tuple, instead of a Exception. + async def unknown_addrinfo(*args: Any, **kwargs: Any) -> List[Any]: + return [ + ( + socket.AF_INET6, + socket.SOCK_STREAM, + 6, + "", + (10, b"\x01\xbb\x00\x00\x00\x00*\x04NB\x00\x1a\x00\x00"), + ) + ] + + loop.getaddrinfo = unknown_addrinfo + resolver = ThreadedResolver() + resolver._loop = loop + with patch("socket.has_ipv6", False): + res = await resolver.resolve("www.python.org") + assert len(res) == 0 + + await resolver.close() + + @pytest.mark.skipif(aiodns is None, reason="aiodns required") async def test_close_for_async_resolver(loop) -> None: resolver = AsyncResolver(loop=loop) diff --git a/tests/test_route_def.py b/tests/test_route_def.py index 49c6c4c..cf9cb12 100644 --- a/tests/test_route_def.py +++ b/tests/test_route_def.py @@ -232,6 +232,22 @@ async def handler(request): assert str(route.url_for()) == "/path" +def test_options_deco(router) -> None: + routes = web.RouteTableDef() + + @routes.options("/path") + async def handler(request): + pass + + router.add_routes(routes) + + assert len(router.routes()) == 1 + + route = list(router.routes())[0] + assert route.method == "OPTIONS" + assert str(route.url_for()) == "/path" + + def test_route_deco(router) -> None: routes = web.RouteTableDef() diff --git a/tests/test_run_app.py b/tests/test_run_app.py index d2ba226..b59634e 100644 --- a/tests/test_run_app.py +++ b/tests/test_run_app.py @@ -12,34 +12,31 @@ from uuid import uuid4 import pytest +from conftest import IS_UNIX, needs_unix from aiohttp import web from aiohttp.helpers import PY_37 from aiohttp.test_utils import make_mocked_coro +from aiohttp.web_runner import BaseRunner # Test for features of OS' socket support -_has_unix_domain_socks = hasattr(socket, "AF_UNIX") -if _has_unix_domain_socks: - _abstract_path_sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) - try: - _abstract_path_sock.bind(b"\x00" + uuid4().hex.encode("ascii")) # type: ignore - except FileNotFoundError: - _abstract_path_failed = True - else: - _abstract_path_failed = False - finally: - _abstract_path_sock.close() - del _abstract_path_sock +if IS_UNIX: + with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as _abstract_path_sock: + try: + _abstract_path_sock.bind(b"\x00" + uuid4().hex.encode("ascii")) + except FileNotFoundError: + _abstract_path_failed = True + else: + _abstract_path_failed = False + finally: + del _abstract_path_sock else: _abstract_path_failed = True skip_if_no_abstract_paths = pytest.mark.skipif( _abstract_path_failed, reason="Linux-style abstract paths are not supported." ) -skip_if_no_unix_socks = pytest.mark.skipif( - not _has_unix_domain_socks, reason="Unix domain sockets are not supported" -) -del _has_unix_domain_socks, _abstract_path_failed +del IS_UNIX, _abstract_path_failed HAS_IPV6 = socket.has_ipv6 if HAS_IPV6: @@ -47,7 +44,8 @@ # support, but the target system still may not have it. # So let's ensure that we really have IPv6 support. try: - socket.socket(socket.AF_INET6, socket.SOCK_STREAM) + with socket.socket(socket.AF_INET6, socket.SOCK_STREAM): + pass except OSError: HAS_IPV6 = False @@ -93,7 +91,7 @@ def test_run_app_http(patched_loop) -> None: cleanup_handler = make_mocked_coro() app.on_cleanup.append(cleanup_handler) - web.run_app(app, print=stopper(patched_loop)) + web.run_app(app, print=stopper(patched_loop), loop=patched_loop) patched_loop.create_server.assert_called_with( mock.ANY, None, 8080, ssl=None, backlog=128, reuse_address=None, reuse_port=None @@ -104,7 +102,7 @@ def test_run_app_http(patched_loop) -> None: def test_run_app_close_loop(patched_loop) -> None: app = web.Application() - web.run_app(app, print=stopper(patched_loop)) + web.run_app(app, print=stopper(patched_loop), loop=patched_loop) patched_loop.create_server.assert_called_with( mock.ANY, None, 8080, ssl=None, backlog=128, reuse_address=None, reuse_port=None @@ -424,7 +422,7 @@ def test_run_app_mixed_bindings( run_app_kwargs, expected_server_calls, expected_unix_server_calls, patched_loop ): app = web.Application() - web.run_app(app, print=stopper(patched_loop), **run_app_kwargs) + web.run_app(app, print=stopper(patched_loop), **run_app_kwargs, loop=patched_loop) assert patched_loop.create_unix_server.mock_calls == expected_unix_server_calls assert patched_loop.create_server.mock_calls == expected_server_calls @@ -434,7 +432,9 @@ def test_run_app_https(patched_loop) -> None: app = web.Application() ssl_context = ssl.create_default_context() - web.run_app(app, ssl_context=ssl_context, print=stopper(patched_loop)) + web.run_app( + app, ssl_context=ssl_context, print=stopper(patched_loop), loop=patched_loop + ) patched_loop.create_server.assert_called_with( mock.ANY, @@ -452,7 +452,9 @@ def test_run_app_nondefault_host_port(patched_loop, aiohttp_unused_port) -> None host = "127.0.0.1" app = web.Application() - web.run_app(app, host=host, port=port, print=stopper(patched_loop)) + web.run_app( + app, host=host, port=port, print=stopper(patched_loop), loop=patched_loop + ) patched_loop.create_server.assert_called_with( mock.ANY, host, port, ssl=None, backlog=128, reuse_address=None, reuse_port=None @@ -463,7 +465,7 @@ def test_run_app_multiple_hosts(patched_loop) -> None: hosts = ("127.0.0.1", "127.0.0.2") app = web.Application() - web.run_app(app, host=hosts, print=stopper(patched_loop)) + web.run_app(app, host=hosts, print=stopper(patched_loop), loop=patched_loop) calls = map( lambda h: mock.call( @@ -482,7 +484,7 @@ def test_run_app_multiple_hosts(patched_loop) -> None: def test_run_app_custom_backlog(patched_loop) -> None: app = web.Application() - web.run_app(app, backlog=10, print=stopper(patched_loop)) + web.run_app(app, backlog=10, print=stopper(patched_loop), loop=patched_loop) patched_loop.create_server.assert_called_with( mock.ANY, None, 8080, ssl=None, backlog=10, reuse_address=None, reuse_port=None @@ -491,49 +493,60 @@ def test_run_app_custom_backlog(patched_loop) -> None: def test_run_app_custom_backlog_unix(patched_loop) -> None: app = web.Application() - web.run_app(app, path="/tmp/tmpsock.sock", backlog=10, print=stopper(patched_loop)) + web.run_app( + app, + path="/tmp/tmpsock.sock", + backlog=10, + print=stopper(patched_loop), + loop=patched_loop, + ) patched_loop.create_unix_server.assert_called_with( mock.ANY, "/tmp/tmpsock.sock", ssl=None, backlog=10 ) -@skip_if_no_unix_socks -def test_run_app_http_unix_socket(patched_loop, shorttmpdir) -> None: +def test_run_app_http_unix_socket(patched_loop, unix_sockname) -> None: app = web.Application() - sock_path = str(shorttmpdir / "socket.sock") printer = mock.Mock(wraps=stopper(patched_loop)) - web.run_app(app, path=sock_path, print=printer) + web.run_app(app, path=unix_sockname, print=printer, loop=patched_loop) patched_loop.create_unix_server.assert_called_with( - mock.ANY, sock_path, ssl=None, backlog=128 + mock.ANY, unix_sockname, ssl=None, backlog=128 ) - assert f"http://unix:{sock_path}:" in printer.call_args[0][0] + assert f"http://unix:{unix_sockname}:" in printer.call_args[0][0] -@skip_if_no_unix_socks -def test_run_app_https_unix_socket(patched_loop, shorttmpdir) -> None: +def test_run_app_https_unix_socket(patched_loop, unix_sockname) -> None: app = web.Application() - sock_path = str(shorttmpdir / "socket.sock") ssl_context = ssl.create_default_context() printer = mock.Mock(wraps=stopper(patched_loop)) - web.run_app(app, path=sock_path, ssl_context=ssl_context, print=printer) + web.run_app( + app, + path=unix_sockname, + ssl_context=ssl_context, + print=printer, + loop=patched_loop, + ) patched_loop.create_unix_server.assert_called_with( - mock.ANY, sock_path, ssl=ssl_context, backlog=128 + mock.ANY, unix_sockname, ssl=ssl_context, backlog=128 ) - assert f"https://unix:{sock_path}:" in printer.call_args[0][0] + assert f"https://unix:{unix_sockname}:" in printer.call_args[0][0] -@skip_if_no_unix_socks +@needs_unix @skip_if_no_abstract_paths def test_run_app_abstract_linux_socket(patched_loop) -> None: sock_path = b"\x00" + uuid4().hex.encode("ascii") app = web.Application() web.run_app( - app, path=sock_path.decode("ascii", "ignore"), print=stopper(patched_loop) + app, + path=sock_path.decode("ascii", "ignore"), + print=stopper(patched_loop), + loop=patched_loop, ) patched_loop.create_unix_server.assert_called_with( @@ -550,7 +563,7 @@ def test_run_app_preexisting_inet_socket(patched_loop, mocker) -> None: _, port = sock.getsockname() printer = mock.Mock(wraps=stopper(patched_loop)) - web.run_app(app, sock=sock, print=printer) + web.run_app(app, sock=sock, print=printer, loop=patched_loop) patched_loop.create_server.assert_called_with( mock.ANY, sock=sock, backlog=128, ssl=None @@ -568,7 +581,7 @@ def test_run_app_preexisting_inet6_socket(patched_loop) -> None: port = sock.getsockname()[1] printer = mock.Mock(wraps=stopper(patched_loop)) - web.run_app(app, sock=sock, print=printer) + web.run_app(app, sock=sock, print=printer, loop=patched_loop) patched_loop.create_server.assert_called_with( mock.ANY, sock=sock, backlog=128, ssl=None @@ -576,7 +589,7 @@ def test_run_app_preexisting_inet6_socket(patched_loop) -> None: assert f"http://[::]:{port}" in printer.call_args[0][0] -@skip_if_no_unix_socks +@needs_unix def test_run_app_preexisting_unix_socket(patched_loop, mocker) -> None: app = web.Application() @@ -587,7 +600,7 @@ def test_run_app_preexisting_unix_socket(patched_loop, mocker) -> None: os.unlink(sock_path) printer = mock.Mock(wraps=stopper(patched_loop)) - web.run_app(app, sock=sock, print=printer) + web.run_app(app, sock=sock, print=printer, loop=patched_loop) patched_loop.create_server.assert_called_with( mock.ANY, sock=sock, backlog=128, ssl=None @@ -607,7 +620,7 @@ def test_run_app_multiple_preexisting_sockets(patched_loop) -> None: _, port2 = sock2.getsockname() printer = mock.Mock(wraps=stopper(patched_loop)) - web.run_app(app, sock=(sock1, sock2), print=printer) + web.run_app(app, sock=(sock1, sock2), print=printer, loop=patched_loop) patched_loop.create_server.assert_has_calls( [ @@ -630,27 +643,29 @@ def test_run_app_multiple_preexisting_sockets(patched_loop) -> None: def test_sigint() -> None: skip_if_on_windows() - proc = subprocess.Popen( - [sys.executable, "-u", "-c", _script_test_signal], stdout=subprocess.PIPE - ) - for line in proc.stdout: - if line.startswith(b"======== Running on"): - break - proc.send_signal(signal.SIGINT) - assert proc.wait() == 0 + with subprocess.Popen( + [sys.executable, "-u", "-c", _script_test_signal], + stdout=subprocess.PIPE, + ) as proc: + for line in proc.stdout: + if line.startswith(b"======== Running on"): + break + proc.send_signal(signal.SIGINT) + assert proc.wait() == 0 def test_sigterm() -> None: skip_if_on_windows() - proc = subprocess.Popen( - [sys.executable, "-u", "-c", _script_test_signal], stdout=subprocess.PIPE - ) - for line in proc.stdout: - if line.startswith(b"======== Running on"): - break - proc.terminate() - assert proc.wait() == 0 + with subprocess.Popen( + [sys.executable, "-u", "-c", _script_test_signal], + stdout=subprocess.PIPE, + ) as proc: + for line in proc.stdout: + if line.startswith(b"======== Running on"): + break + proc.terminate() + assert proc.wait() == 0 def test_startup_cleanup_signals_even_on_failure(patched_loop) -> None: @@ -663,7 +678,7 @@ def test_startup_cleanup_signals_even_on_failure(patched_loop) -> None: app.on_cleanup.append(cleanup_handler) with pytest.raises(RuntimeError): - web.run_app(app, print=stopper(patched_loop)) + web.run_app(app, print=stopper(patched_loop), loop=patched_loop) startup_handler.assert_called_once_with(app) cleanup_handler.assert_called_once_with(app) @@ -681,7 +696,7 @@ async def make_app(): app.on_cleanup.append(cleanup_handler) return app - web.run_app(make_app(), print=stopper(patched_loop)) + web.run_app(make_app(), print=stopper(patched_loop), loop=patched_loop) patched_loop.create_server.assert_called_with( mock.ANY, None, 8080, ssl=None, backlog=128, reuse_address=None, reuse_port=None @@ -702,7 +717,12 @@ def test_run_app_default_logger(monkeypatch, patched_loop): mock_logger.configure_mock(**attrs) app = web.Application() - web.run_app(app, print=stopper(patched_loop), access_log=mock_logger) + web.run_app( + app, + print=stopper(patched_loop), + access_log=mock_logger, + loop=patched_loop, + ) mock_logger.setLevel.assert_any_call(logging.DEBUG) mock_logger.hasHandlers.assert_called_with() assert isinstance(mock_logger.addHandler.call_args[0][0], logging.StreamHandler) @@ -720,7 +740,12 @@ def test_run_app_default_logger_setup_requires_debug(patched_loop): mock_logger.configure_mock(**attrs) app = web.Application() - web.run_app(app, print=stopper(patched_loop), access_log=mock_logger) + web.run_app( + app, + print=stopper(patched_loop), + access_log=mock_logger, + loop=patched_loop, + ) mock_logger.setLevel.assert_not_called() mock_logger.hasHandlers.assert_not_called() mock_logger.addHandler.assert_not_called() @@ -738,7 +763,12 @@ def test_run_app_default_logger_setup_requires_default_logger(patched_loop): mock_logger.configure_mock(**attrs) app = web.Application() - web.run_app(app, print=stopper(patched_loop), access_log=mock_logger) + web.run_app( + app, + print=stopper(patched_loop), + access_log=mock_logger, + loop=patched_loop, + ) mock_logger.setLevel.assert_not_called() mock_logger.hasHandlers.assert_not_called() mock_logger.addHandler.assert_not_called() @@ -756,7 +786,12 @@ def test_run_app_default_logger_setup_only_if_unconfigured(patched_loop): mock_logger.configure_mock(**attrs) app = web.Application() - web.run_app(app, print=stopper(patched_loop), access_log=mock_logger) + web.run_app( + app, + print=stopper(patched_loop), + access_log=mock_logger, + loop=patched_loop, + ) mock_logger.setLevel.assert_not_called() mock_logger.hasHandlers.assert_called_with() mock_logger.addHandler.assert_not_called() @@ -773,7 +808,7 @@ async def on_startup(app): app.on_startup.append(on_startup) - web.run_app(app, print=stopper(patched_loop)) + web.run_app(app, print=stopper(patched_loop), loop=patched_loop) assert task.cancelled() @@ -791,7 +826,7 @@ async def on_startup(app): app.on_startup.append(on_startup) - web.run_app(app, print=stopper(patched_loop)) + web.run_app(app, print=stopper(patched_loop), loop=patched_loop) assert task.done() @@ -817,7 +852,7 @@ async def on_startup(app): exc_handler = mock.Mock() patched_loop.set_exception_handler(exc_handler) - web.run_app(app, print=stopper(patched_loop)) + web.run_app(app, print=stopper(patched_loop), loop=patched_loop) assert task.done() msg = { @@ -828,6 +863,24 @@ async def on_startup(app): exc_handler.assert_called_with(patched_loop, msg) +def test_run_app_keepalive_timeout(patched_loop, mocker, monkeypatch): + new_timeout = 1234 + base_runner_init_orig = BaseRunner.__init__ + + def base_runner_init_spy(self, *args, **kwargs): + assert kwargs["keepalive_timeout"] == new_timeout + base_runner_init_orig(self, *args, **kwargs) + + app = web.Application() + monkeypatch.setattr(BaseRunner, "__init__", base_runner_init_spy) + web.run_app( + app, + keepalive_timeout=new_timeout, + print=stopper(patched_loop), + loop=patched_loop, + ) + + @pytest.mark.skipif(not PY_37, reason="contextvars support is required") def test_run_app_context_vars(patched_loop): from contextvars import ContextVar @@ -857,5 +910,5 @@ async def init(): count += 1 return app - web.run_app(init(), print=stopper(patched_loop)) + web.run_app(init(), print=stopper(patched_loop), loop=patched_loop) assert count == 3 diff --git a/tests/test_signals.py b/tests/test_signals.py deleted file mode 100644 index 971cab5..0000000 --- a/tests/test_signals.py +++ /dev/null @@ -1,167 +0,0 @@ -from unittest import mock - -import pytest -from multidict import CIMultiDict -from re_assert import Matches - -from aiohttp.signals import Signal -from aiohttp.test_utils import make_mocked_coro, make_mocked_request -from aiohttp.web import Application, Response - - -@pytest.fixture -def app(): - return Application() - - -def make_request(app, method, path, headers=CIMultiDict()): - return make_mocked_request(method, path, headers, app=app) - - -async def test_add_signal_handler_not_a_callable(app) -> None: - callback = True - app.on_response_prepare.append(callback) - app.on_response_prepare.freeze() - with pytest.raises(TypeError): - await app.on_response_prepare(None, None) - - -async def test_function_signal_dispatch(app) -> None: - signal = Signal(app) - kwargs = {"foo": 1, "bar": 2} - - callback_mock = mock.Mock() - - async def callback(**kwargs): - callback_mock(**kwargs) - - signal.append(callback) - signal.freeze() - - await signal.send(**kwargs) - callback_mock.assert_called_once_with(**kwargs) - - -async def test_function_signal_dispatch2(app) -> None: - signal = Signal(app) - args = {"a", "b"} - kwargs = {"foo": 1, "bar": 2} - - callback_mock = mock.Mock() - - async def callback(*args, **kwargs): - callback_mock(*args, **kwargs) - - signal.append(callback) - signal.freeze() - - await signal.send(*args, **kwargs) - callback_mock.assert_called_once_with(*args, **kwargs) - - -async def test_response_prepare(app) -> None: - callback = mock.Mock() - - async def cb(*args, **kwargs): - callback(*args, **kwargs) - - app.on_response_prepare.append(cb) - app.on_response_prepare.freeze() - - request = make_request(app, "GET", "/") - response = Response(body=b"") - await response.prepare(request) - - callback.assert_called_once_with(request, response) - - -async def test_non_coroutine(app) -> None: - signal = Signal(app) - kwargs = {"foo": 1, "bar": 2} - - callback = mock.Mock() - - signal.append(callback) - signal.freeze() - - with pytest.raises(TypeError): - await signal.send(**kwargs) - - -def test_setitem(app) -> None: - signal = Signal(app) - m1 = mock.Mock() - signal.append(m1) - assert signal[0] is m1 - m2 = mock.Mock() - signal[0] = m2 - assert signal[0] is m2 - - -def test_delitem(app) -> None: - signal = Signal(app) - m1 = mock.Mock() - signal.append(m1) - assert len(signal) == 1 - del signal[0] - assert len(signal) == 0 - - -def test_cannot_append_to_frozen_signal(app) -> None: - signal = Signal(app) - m1 = mock.Mock() - m2 = mock.Mock() - signal.append(m1) - signal.freeze() - with pytest.raises(RuntimeError): - signal.append(m2) - - assert list(signal) == [m1] - - -def test_cannot_setitem_in_frozen_signal(app) -> None: - signal = Signal(app) - m1 = mock.Mock() - m2 = mock.Mock() - signal.append(m1) - signal.freeze() - with pytest.raises(RuntimeError): - signal[0] = m2 - - assert list(signal) == [m1] - - -def test_cannot_delitem_in_frozen_signal(app) -> None: - signal = Signal(app) - m1 = mock.Mock() - signal.append(m1) - signal.freeze() - with pytest.raises(RuntimeError): - del signal[0] - - assert list(signal) == [m1] - - -async def test_cannot_send_non_frozen_signal(app) -> None: - signal = Signal(app) - - callback = make_mocked_coro() - - signal.append(callback) - - with pytest.raises(RuntimeError): - await signal.send() - - assert not callback.called - - -async def test_repr(app) -> None: - signal = Signal(app) - - callback = make_mocked_coro() - - signal.append(callback) - - assert Matches( - r", frozen=False, " r"\[\]>" - ) == repr(signal) diff --git a/tests/test_streams.py b/tests/test_streams.py index d83941b..4de6fba 100644 --- a/tests/test_streams.py +++ b/tests/test_streams.py @@ -12,6 +12,7 @@ from re_assert import Matches from aiohttp import streams +from aiohttp.helpers import PY_311 DATA = b"line1\nline2\nline3\n" @@ -24,7 +25,7 @@ def chunkify(seq, n): async def create_stream(): loop = asyncio.get_event_loop() protocol = mock.Mock(_reading_paused=False) - stream = streams.StreamReader(protocol, 2 ** 16, loop=loop) + stream = streams.StreamReader(protocol, 2**16, loop=loop) stream.feed_data(DATA) stream.feed_eof() return stream @@ -72,7 +73,7 @@ class TestStreamReader: DATA = b"line1\nline2\nline3\n" def _make_one(self, *args, **kwargs): - kwargs.setdefault("limit", 2 ** 16) + kwargs.setdefault("limit", 2**16) return streams.StreamReader(mock.Mock(_reading_paused=False), *args, **kwargs) async def test_create_waiter(self) -> None: @@ -82,12 +83,26 @@ async def test_create_waiter(self) -> None: with pytest.raises(RuntimeError): await stream._wait("test") + @pytest.mark.xfail( + PY_311, + reason="No idea why ClientRequest() is constructed out of loop but " + "it calls `asyncio.get_event_loop()`", + raises=DeprecationWarning, + strict=False, + ) def test_ctor_global_loop(self) -> None: loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) - stream = streams.StreamReader(mock.Mock(_reading_paused=False), 2 ** 16) + try: + stream = streams.StreamReader(mock.Mock(_reading_paused=False), 2**16) - assert stream._loop is loop + assert stream._loop is loop + finally: # Otherwise an unstopped/unclosed loop affects the next test + # Cleanup, leaks into `test_at_eof` otherwise: + loop.stop() + loop.run_forever() + loop.close() + gc.collect() async def test_at_eof(self) -> None: stream = self._make_one() @@ -394,6 +409,117 @@ async def test_readline_exception(self) -> None: with pytest.raises(ValueError): await stream.readline() + async def test_readuntil(self) -> None: + loop = asyncio.get_event_loop() + # Read one chunk. 'readuntil' will need to wait for the data + # to come from 'cb' + stream = self._make_one() + stream.feed_data(b"chunk1 ") + read_task = loop.create_task(stream.readuntil(b"*")) + + def cb(): + stream.feed_data(b"chunk2 ") + stream.feed_data(b"chunk3 ") + stream.feed_data(b"* chunk4") + + loop.call_soon(cb) + + line = await read_task + assert b"chunk1 chunk2 chunk3 *" == line + + stream.feed_eof() + data = await stream.read() + assert b" chunk4" == data + + async def test_readuntil_limit_with_existing_data(self) -> None: + # Read one chunk. The data is in StreamReader's buffer + # before the event loop is run. + + stream = self._make_one(limit=2) + stream.feed_data(b"li") + stream.feed_data(b"ne1&line2&") + + with pytest.raises(ValueError): + await stream.readuntil(b"&") + # The buffer should contain the remaining data after exception + stream.feed_eof() + data = await stream.read() + assert b"line2&" == data + + async def test_readuntil_limit(self) -> None: + loop = asyncio.get_event_loop() + # Read one chunk. StreamReaders are fed with data after + # their 'readuntil' methods are called. + stream = self._make_one(limit=4) + + def cb(): + stream.feed_data(b"chunk1") + stream.feed_data(b"chunk2$") + stream.feed_data(b"chunk3#") + stream.feed_eof() + + loop.call_soon(cb) + + with pytest.raises(ValueError): + await stream.readuntil(b"$") + data = await stream.read() + assert b"chunk3#" == data + + async def test_readuntil_nolimit_nowait(self) -> None: + # All needed data for the first 'readuntil' call will be + # in the buffer. + stream = self._make_one() + data = b"line1!line2!line3!" + stream.feed_data(data[:6]) + stream.feed_data(data[6:]) + + line = await stream.readuntil(b"!") + assert b"line1!" == line + + stream.feed_eof() + data = await stream.read() + assert b"line2!line3!" == data + + async def test_readuntil_eof(self) -> None: + stream = self._make_one() + stream.feed_data(b"some data") + stream.feed_eof() + + line = await stream.readuntil(b"@") + assert b"some data" == line + + async def test_readuntil_empty_eof(self) -> None: + stream = self._make_one() + stream.feed_eof() + + line = await stream.readuntil(b"@") + assert b"" == line + + async def test_readuntil_read_byte_count(self) -> None: + stream = self._make_one() + data = b"line1!line2!line3!" + stream.feed_data(data) + + await stream.readuntil(b"!") + + data = await stream.read(7) + assert b"line2!l" == data + + stream.feed_eof() + data = await stream.read() + assert b"ine3!" == data + + async def test_readuntil_exception(self) -> None: + stream = self._make_one() + stream.feed_data(b"line#") + + data = await stream.readuntil(b"#") + assert b"line#" == data + + stream.set_exception(ValueError()) + with pytest.raises(ValueError): + await stream.readuntil(b"#") + async def test_readexactly_zero_or_less(self) -> None: # Read exact number of bytes (zero or less). stream = self._make_one() @@ -1123,7 +1249,7 @@ async def set_err(): async def test_feed_data_waiters(protocol) -> None: loop = asyncio.get_event_loop() - reader = streams.StreamReader(protocol, 2 ** 16, loop=loop) + reader = streams.StreamReader(protocol, 2**16, loop=loop) waiter = reader._waiter = loop.create_future() eof_waiter = reader._eof_waiter = loop.create_future() @@ -1140,7 +1266,7 @@ async def test_feed_data_waiters(protocol) -> None: async def test_feed_data_completed_waiters(protocol) -> None: loop = asyncio.get_event_loop() - reader = streams.StreamReader(protocol, 2 ** 16, loop=loop) + reader = streams.StreamReader(protocol, 2**16, loop=loop) waiter = reader._waiter = loop.create_future() waiter.set_result(1) @@ -1151,7 +1277,7 @@ async def test_feed_data_completed_waiters(protocol) -> None: async def test_feed_eof_waiters(protocol) -> None: loop = asyncio.get_event_loop() - reader = streams.StreamReader(protocol, 2 ** 16, loop=loop) + reader = streams.StreamReader(protocol, 2**16, loop=loop) waiter = reader._waiter = loop.create_future() eof_waiter = reader._eof_waiter = loop.create_future() @@ -1166,7 +1292,7 @@ async def test_feed_eof_waiters(protocol) -> None: async def test_feed_eof_cancelled(protocol) -> None: loop = asyncio.get_event_loop() - reader = streams.StreamReader(protocol, 2 ** 16, loop=loop) + reader = streams.StreamReader(protocol, 2**16, loop=loop) waiter = reader._waiter = loop.create_future() eof_waiter = reader._eof_waiter = loop.create_future() @@ -1183,7 +1309,7 @@ async def test_feed_eof_cancelled(protocol) -> None: async def test_on_eof(protocol) -> None: loop = asyncio.get_event_loop() - reader = streams.StreamReader(protocol, 2 ** 16, loop=loop) + reader = streams.StreamReader(protocol, 2**16, loop=loop) on_eof = mock.Mock() reader.on_eof(on_eof) @@ -1204,7 +1330,7 @@ async def test_on_eof_empty_reader() -> None: async def test_on_eof_exc_in_callback(protocol) -> None: loop = asyncio.get_event_loop() - reader = streams.StreamReader(protocol, 2 ** 16, loop=loop) + reader = streams.StreamReader(protocol, 2**16, loop=loop) on_eof = mock.Mock() on_eof.side_effect = ValueError @@ -1228,7 +1354,7 @@ async def test_on_eof_exc_in_callback_empty_stream_reader() -> None: async def test_on_eof_eof_is_set(protocol) -> None: loop = asyncio.get_event_loop() - reader = streams.StreamReader(protocol, 2 ** 16, loop=loop) + reader = streams.StreamReader(protocol, 2**16, loop=loop) reader.feed_eof() on_eof = mock.Mock() @@ -1239,7 +1365,7 @@ async def test_on_eof_eof_is_set(protocol) -> None: async def test_on_eof_eof_is_set_exception(protocol) -> None: loop = asyncio.get_event_loop() - reader = streams.StreamReader(protocol, 2 ** 16, loop=loop) + reader = streams.StreamReader(protocol, 2**16, loop=loop) reader.feed_eof() on_eof = mock.Mock() @@ -1252,7 +1378,7 @@ async def test_on_eof_eof_is_set_exception(protocol) -> None: async def test_set_exception(protocol) -> None: loop = asyncio.get_event_loop() - reader = streams.StreamReader(protocol, 2 ** 16, loop=loop) + reader = streams.StreamReader(protocol, 2**16, loop=loop) waiter = reader._waiter = loop.create_future() eof_waiter = reader._eof_waiter = loop.create_future() @@ -1267,7 +1393,7 @@ async def test_set_exception(protocol) -> None: async def test_set_exception_cancelled(protocol) -> None: loop = asyncio.get_event_loop() - reader = streams.StreamReader(protocol, 2 ** 16, loop=loop) + reader = streams.StreamReader(protocol, 2**16, loop=loop) waiter = reader._waiter = loop.create_future() eof_waiter = reader._eof_waiter = loop.create_future() @@ -1285,7 +1411,7 @@ async def test_set_exception_cancelled(protocol) -> None: async def test_set_exception_eof_callbacks(protocol) -> None: loop = asyncio.get_event_loop() - reader = streams.StreamReader(protocol, 2 ** 16, loop=loop) + reader = streams.StreamReader(protocol, 2**16, loop=loop) on_eof = mock.Mock() reader.on_eof(on_eof) @@ -1368,7 +1494,7 @@ async def test_stream_reader_iter_chunks_no_chunked_encoding() -> None: async def test_stream_reader_iter_chunks_chunked_encoding(protocol) -> None: loop = asyncio.get_event_loop() - stream = streams.StreamReader(protocol, 2 ** 16, loop=loop) + stream = streams.StreamReader(protocol, 2**16, loop=loop) for line in DATA.splitlines(keepends=True): stream.begin_http_chunk_receiving() stream.feed_data(line) @@ -1379,3 +1505,7 @@ async def test_stream_reader_iter_chunks_chunked_encoding(protocol) -> None: async for data, end_of_chunk in stream.iter_chunks(): assert (data, end_of_chunk) == (next(it), True) pytest.raises(StopIteration, next, it) + + +def test_isinstance_check() -> None: + assert isinstance(streams.EMPTY_PAYLOAD, streams.StreamReader) diff --git a/tests/test_tcp_helpers.py b/tests/test_tcp_helpers.py index 18fedb9..5b2438a 100644 --- a/tests/test_tcp_helpers.py +++ b/tests/test_tcp_helpers.py @@ -11,7 +11,8 @@ # support, but the target system still may not have it. # So let's ensure that we really have IPv6 support. try: - socket.socket(socket.AF_INET6, socket.SOCK_STREAM) + with socket.socket(socket.AF_INET6, socket.SOCK_STREAM): + pass except OSError: has_ipv6 = False diff --git a/tests/test_test_utils.py b/tests/test_test_utils.py index cbaed33..1ac742f 100644 --- a/tests/test_test_utils.py +++ b/tests/test_test_utils.py @@ -1,4 +1,6 @@ import gzip +from socket import socket +from typing import Any from unittest import mock import pytest @@ -12,6 +14,7 @@ RawTestServer as _RawTestServer, TestClient as _TestClient, TestServer as _TestServer, + get_port_socket, loop_context, make_mocked_request, unittest_run_loop, @@ -102,14 +105,13 @@ class TestAioHTTPTestCase(AioHTTPTestCase): def get_app(self): return _create_example_app() - @unittest_run_loop async def test_example_with_loop(self) -> None: request = await self.client.request("GET", "/") assert request.status == 200 text = await request.text() assert _hello_world_str == text - def test_example(self) -> None: + def test_inner_example(self) -> None: async def test_get_route() -> None: resp = await self.client.request("GET", "/") assert resp.status == 200 @@ -118,6 +120,32 @@ async def test_get_route() -> None: self.loop.run_until_complete(test_get_route()) + async def test_example_without_explicit_loop(self) -> None: + request = await self.client.request("GET", "/") + assert request.status == 200 + text = await request.text() + assert _hello_world_str == text + + async def test_inner_example_without_explicit_loop(self) -> None: + async def test_get_route() -> None: + resp = await self.client.request("GET", "/") + assert resp.status == 200 + text = await resp.text() + assert _hello_world_str == text + + await test_get_route() + + +def test_unittest_run_loop() -> None: + with pytest.warns( + DeprecationWarning, + match=r"Decorator `@unittest_run_loop` is no longer needed in aiohttp 3\.8\+", + ): + + @unittest_run_loop + def foo(): + pass + def test_get_route(loop, test_client) -> None: async def test_get_route() -> None: @@ -194,6 +222,12 @@ def test_make_mocked_request_app_can_store_values() -> None: assert req.app["a_field"] == "a_value" +def test_make_mocked_request_app_access_non_existing() -> None: + req = make_mocked_request("GET", "/") + with pytest.raises(AttributeError): + req.app.foo + + def test_make_mocked_request_match_info() -> None: req = make_mocked_request("GET", "/", match_info={"a": "1", "b": "2"}) assert req.match_info == {"a": "1", "b": "2"} @@ -314,3 +348,21 @@ async def test_custom_port(loop, app, aiohttp_unused_port) -> None: assert _hello_world_str == text await client.close() + + +@pytest.mark.parametrize("test_server_cls", [_TestServer, _RawTestServer]) +async def test_base_test_server_socket_factory( + test_server_cls: type, app: Any, loop: Any +) -> None: + factory_called = False + + def factory(*args, **kwargs) -> socket: + nonlocal factory_called + factory_called = True + return get_port_socket(*args, **kwargs) + + server = test_server_cls(app, loop=loop, socket_factory=factory) + async with server: + pass + + assert factory_called diff --git a/tests/test_tracing.py b/tests/test_tracing.py index 5523fe9..809d757 100644 --- a/tests/test_tracing.py +++ b/tests/test_tracing.py @@ -61,6 +61,7 @@ def test_freeze(self) -> None: assert trace_config.on_dns_resolvehost_end.frozen assert trace_config.on_dns_cache_hit.frozen assert trace_config.on_dns_cache_miss.frozen + assert trace_config.on_request_headers_sent.frozen class TestTrace: diff --git a/tests/test_web_app.py b/tests/test_web_app.py index f48e54b..13da52d 100644 --- a/tests/test_web_app.py +++ b/tests/test_web_app.py @@ -1,13 +1,14 @@ import asyncio +import gc from unittest import mock import pytest -from async_generator import async_generator, yield_ from aiohttp import log, web from aiohttp.abc import AbstractAccessLogger, AbstractRouter -from aiohttp.helpers import DEBUG, PY_36 +from aiohttp.helpers import DEBUG, PY_36, PY_311 from aiohttp.test_utils import make_mocked_coro +from aiohttp.typedefs import Handler async def test_app_ctor() -> None: @@ -38,14 +39,29 @@ async def test_set_loop() -> None: assert app.loop is loop +@pytest.mark.xfail( + PY_311, + reason="No idea why _set_loop() is constructed out of loop " + "but it calls `asyncio.get_event_loop()`", + raises=DeprecationWarning, + strict=False, +) def test_set_loop_default_loop() -> None: loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) app = web.Application() - app._set_loop(None) - with pytest.warns(DeprecationWarning): - assert app.loop is loop - asyncio.set_event_loop(None) + try: + app._set_loop(None) + with pytest.warns(DeprecationWarning): + assert app.loop is loop + asyncio.set_event_loop(None) + + finally: + # Cleanup, leaks into `test_app_make_handler_debug_exc[True]` otherwise: + loop.stop() + loop.run_forever() + loop.close() + gc.collect() def test_set_loop_with_different_loops() -> None: @@ -58,6 +74,12 @@ def test_set_loop_with_different_loops() -> None: with pytest.raises(RuntimeError): app._set_loop(loop=object()) + # Cleanup, leaks into `test_app_make_handler_debug_exc[True]` otherwise: + loop.stop() + loop.run_forever() + loop.close() + gc.collect() + @pytest.mark.parametrize("debug", [True, False]) async def test_app_make_handler_debug_exc(mocker, debug) -> None: @@ -261,7 +283,7 @@ def test_app_run_middlewares() -> None: assert root._run_middlewares is False @web.middleware - async def middleware(request, handler): + async def middleware(request, handler: Handler): return await handler(request) root = web.Application(middlewares=[middleware]) @@ -306,10 +328,9 @@ async def test_cleanup_ctx() -> None: out = [] def f(num): - @async_generator async def inner(app): out.append("pre_" + str(num)) - await yield_(None) + yield None out.append("post_" + str(num)) return inner @@ -330,12 +351,11 @@ async def test_cleanup_ctx_exception_on_startup() -> None: exc = Exception("fail") def f(num, fail=False): - @async_generator async def inner(app): out.append("pre_" + str(num)) if fail: raise exc - await yield_(None) + yield None out.append("post_" + str(num)) return inner @@ -359,10 +379,9 @@ async def test_cleanup_ctx_exception_on_cleanup() -> None: exc = Exception("fail") def f(num, fail=False): - @async_generator async def inner(app): out.append("pre_" + str(num)) - await yield_(None) + yield None out.append("post_" + str(num)) if fail: raise exc @@ -381,15 +400,40 @@ async def inner(app): assert out == ["pre_1", "pre_2", "pre_3", "post_3", "post_2", "post_1"] +async def test_cleanup_ctx_cleanup_after_exception() -> None: + app = web.Application() + ctx_state = None + + async def success_ctx(app): + nonlocal ctx_state + ctx_state = "START" + yield + ctx_state = "CLEAN" + + async def fail_ctx(app): + raise Exception() + yield + + app.cleanup_ctx.append(success_ctx) + app.cleanup_ctx.append(fail_ctx) + runner = web.AppRunner(app) + try: + with pytest.raises(Exception): + await runner.setup() + finally: + await runner.cleanup() + + assert ctx_state == "CLEAN" + + async def test_cleanup_ctx_exception_on_cleanup_multiple() -> None: app = web.Application() out = [] def f(num, fail=False): - @async_generator async def inner(app): out.append("pre_" + str(num)) - await yield_(None) + yield None out.append("post_" + str(num)) if fail: raise Exception("fail_" + str(num)) @@ -416,12 +460,11 @@ async def test_cleanup_ctx_multiple_yields() -> None: out = [] def f(num): - @async_generator async def inner(app): out.append("pre_" + str(num)) - await yield_(None) + yield None out.append("post_" + str(num)) - await yield_(None) + yield None return inner @@ -505,12 +548,11 @@ async def on_startup(app): ctx_pre_called = False ctx_post_called = False - @async_generator async def cleanup_ctx(app): nonlocal ctx_pre_called, ctx_post_called ctx_pre_called = True app["cleanup"] = True - await yield_(None) + yield None ctx_post_called = True subapp.cleanup_ctx.append(cleanup_ctx) diff --git a/tests/test_web_exceptions.py b/tests/test_web_exceptions.py index 43e5029..80932c8 100644 --- a/tests/test_web_exceptions.py +++ b/tests/test_web_exceptions.py @@ -3,9 +3,10 @@ from traceback import format_exception from unittest import mock +import aiosignal import pytest -from aiohttp import helpers, signals, web +from aiohttp import helpers, web from aiohttp.test_utils import make_mocked_request @@ -41,7 +42,7 @@ async def write_headers(status_line, headers): app = mock.Mock() app._debug = False - app.on_response_prepare = signals.Signal(app) + app.on_response_prepare = aiosignal.Signal(app) app.on_response_prepare.freeze() req = make_mocked_request(method, path, app=app, writer=writer) return req @@ -203,3 +204,40 @@ def test_HTTPException_retains_cause() -> None: tb = "".join(format_exception(ei.type, ei.value, ei.tb)) assert "CustomException" in tb assert "direct cause" in tb + + +async def test_HTTPException_retains_cookie(aiohttp_client): + @web.middleware + async def middleware(request, handler): + try: + return await handler(request) + except web.HTTPException as exc: + exc.set_cookie("foo", request["foo"]) + raise exc + + async def save(request): + request["foo"] = "works" + raise web.HTTPFound("/show") + + async def show(request): + return web.Response(text=request.cookies["foo"]) + + app = web.Application(middlewares=[middleware]) + app.router.add_route("GET", "/save", save) + app.router.add_route("GET", "/show", show) + client = await aiohttp_client(app) + + resp = await client.get("/save") + assert resp.status == 200 + assert str(resp.url)[-5:] == "/show" + text = await resp.text() + assert text == "works" + + +def test_unicode_text_body_unauthorized() -> None: + """Test that HTTPUnauthorized can be initialized with a string.""" + with pytest.warns( + DeprecationWarning, match="body argument is deprecated for http web exceptions" + ): + resp = web.HTTPUnauthorized(body="text") + assert resp.status == 401 diff --git a/tests/test_web_functional.py b/tests/test_web_functional.py index a28fcd4..5fdfb23 100644 --- a/tests/test_web_functional.py +++ b/tests/test_web_functional.py @@ -7,14 +7,14 @@ from unittest import mock import pytest -from async_generator import async_generator, yield_ from multidict import CIMultiDictProxy, MultiDict from yarl import URL import aiohttp from aiohttp import FormData, HttpVersion10, HttpVersion11, TraceConfig, multipart, web -from aiohttp.hdrs import CONTENT_LENGTH, TRANSFER_ENCODING +from aiohttp.hdrs import CONTENT_LENGTH, CONTENT_TYPE, TRANSFER_ENCODING from aiohttp.test_utils import make_mocked_coro +from aiohttp.typedefs import Handler try: import ssl @@ -53,6 +53,8 @@ async def handler(request): txt = await resp.text() assert "OK" == txt + await resp.release() + async def test_simple_get_with_text(aiohttp_client) -> None: async def handler(request): @@ -69,6 +71,8 @@ async def handler(request): txt = await resp.text() assert "OK" == txt + await resp.release() + async def test_handler_returns_not_response(aiohttp_server, aiohttp_client) -> None: asyncio.get_event_loop().set_debug(True) @@ -140,6 +144,8 @@ async def handler(request): text = await resp.text() assert "OK" == text + await resp.release() + async def test_post_form(aiohttp_client) -> None: async def handler(request): @@ -156,6 +162,8 @@ async def handler(request): txt = await resp.text() assert "OK" == txt + await resp.release() + async def test_post_text(aiohttp_client) -> None: async def handler(request): @@ -174,6 +182,8 @@ async def handler(request): txt = await resp.text() assert "русский" == txt + await resp.release() + async def test_post_json(aiohttp_client) -> None: @@ -199,6 +209,8 @@ async def handler(request): data = await resp.json() assert dct == data + await resp.release() + async def test_multipart(aiohttp_client) -> None: with multipart.MultipartWriter() as writer: @@ -297,6 +309,8 @@ async def handler(request): assert "301: Moved Permanently" == txt assert "/path" == resp.headers["location"] + await resp.release() + async def test_post_single_file(aiohttp_client) -> None: @@ -324,9 +338,12 @@ async def handler(request): fname = here / "data.unknown_mime_type" - resp = await client.post("/", data=[fname.open("rb")]) + with fname.open("rb") as fd: + resp = await client.post("/", data=[fd]) assert 200 == resp.status + await resp.release() + async def test_files_upload_with_same_key(aiohttp_client) -> None: async def handler(request): @@ -340,6 +357,7 @@ async def handler(request): if _file.filename == "test2.jpeg": assert _file.file.read() == b"binary data 2" file_names.add(_file.filename) + _file.file.close() assert len(files) == 2 assert file_names == {"test1.jpeg", "test2.jpeg"} resp = web.Response(body=b"OK") @@ -359,6 +377,8 @@ async def handler(request): resp = await client.post("/", data=data) assert 200 == resp.status + await resp.release() + async def test_post_files(aiohttp_client) -> None: @@ -389,6 +409,8 @@ async def handler(request): resp = await client.post("/", data=[f1, f2]) assert 200 == resp.status + await resp.release() + async def test_release_post_data(aiohttp_client) -> None: async def handler(request): @@ -404,6 +426,8 @@ async def handler(request): resp = await client.post("/", data="post text") assert 200 == resp.status + await resp.release() + async def test_POST_DATA_with_content_transfer_encoding(aiohttp_client) -> None: async def handler(request): @@ -421,6 +445,8 @@ async def handler(request): resp = await client.post("/", data=form) assert 200 == resp.status + await resp.release() + async def test_post_form_with_duplicate_keys(aiohttp_client) -> None: async def handler(request): @@ -436,10 +462,12 @@ async def handler(request): resp = await client.post("/", data=MultiDict([("a", 1), ("a", 2)])) assert 200 == resp.status + await resp.release() + def test_repr_for_application() -> None: app = web.Application() - assert "".format(id(app)) == repr(app) + assert f"" == repr(app) async def test_expect_default_handler_unknown(aiohttp_client) -> None: @@ -467,6 +495,8 @@ async def handler(request): resp = await client.post("/", headers={"Expect": "SPAM"}) assert 417 == resp.status + await resp.release() + async def test_100_continue(aiohttp_client) -> None: async def handler(request): @@ -484,6 +514,8 @@ async def handler(request): resp = await client.post("/", data=form, expect100=True) assert 200 == resp.status + await resp.release() + async def test_100_continue_custom(aiohttp_client) -> None: @@ -508,6 +540,8 @@ async def expect_handler(request): assert 200 == resp.status assert expect_received + await resp.release() + async def test_100_continue_custom_response(aiohttp_client) -> None: async def handler(request): @@ -529,10 +563,12 @@ async def expect_handler(request): auth_err = False resp = await client.post("/", data=new_dummy_form(), expect100=True) assert 200 == resp.status + await resp.release() auth_err = True resp = await client.post("/", data=new_dummy_form(), expect100=True) assert 403 == resp.status + await resp.release() async def test_100_continue_for_not_found(aiohttp_client) -> None: @@ -543,6 +579,8 @@ async def test_100_continue_for_not_found(aiohttp_client) -> None: resp = await client.post("/not_found", data="data", expect100=True) assert 404 == resp.status + await resp.release() + async def test_100_continue_for_not_allowed(aiohttp_client) -> None: async def handler(request): @@ -555,6 +593,8 @@ async def handler(request): resp = await client.get("/", expect100=True) assert 405 == resp.status + await resp.release() + async def test_http11_keep_alive_default(aiohttp_client) -> None: async def handler(request): @@ -569,6 +609,8 @@ async def handler(request): assert resp.version == HttpVersion11 assert "Connection" not in resp.headers + await resp.release() + @pytest.mark.xfail async def test_http10_keep_alive_default(aiohttp_client) -> None: @@ -584,6 +626,8 @@ async def handler(request): assert resp.version == HttpVersion10 assert resp.headers["Connection"] == "keep-alive" + await resp.release() + async def test_http10_keep_alive_with_headers_close(aiohttp_client) -> None: async def handler(request): @@ -600,6 +644,8 @@ async def handler(request): assert resp.version == HttpVersion10 assert "Connection" not in resp.headers + await resp.release() + async def test_http10_keep_alive_with_headers(aiohttp_client) -> None: async def handler(request): @@ -616,6 +662,8 @@ async def handler(request): assert resp.version == HttpVersion10 assert resp.headers["Connection"] == "keep-alive" + await resp.release() + async def test_upload_file(aiohttp_client) -> None: @@ -627,6 +675,7 @@ async def test_upload_file(aiohttp_client) -> None: async def handler(request): form = await request.post() raw_data = form["file"].file.read() + form["file"].file.close() assert data == raw_data return web.Response() @@ -637,6 +686,8 @@ async def handler(request): resp = await client.post("/", data={"file": data}) assert 200 == resp.status + await resp.release() + async def test_upload_file_object(aiohttp_client) -> None: here = pathlib.Path(__file__).parent @@ -647,6 +698,7 @@ async def test_upload_file_object(aiohttp_client) -> None: async def handler(request): form = await request.post() raw_data = form["file"].file.read() + form["file"].file.close() assert data == raw_data return web.Response() @@ -658,6 +710,8 @@ async def handler(request): resp = await client.post("/", data={"file": f}) assert 200 == resp.status + await resp.release() + @pytest.mark.parametrize( "method", ["get", "post", "options", "post", "put", "patch", "delete"] @@ -694,6 +748,8 @@ async def handler(request): resp = await client.post("/", data=b"data") assert 200 == resp.status + await resp.release() + async def test_get_with_empty_arg(aiohttp_client) -> None: async def handler(request): @@ -708,6 +764,8 @@ async def handler(request): resp = await client.get("/?arg") assert 200 == resp.status + await resp.release() + async def test_large_header(aiohttp_client) -> None: async def handler(request): @@ -721,6 +779,8 @@ async def handler(request): resp = await client.get("/", headers=headers) assert 400 == resp.status + await resp.release() + async def test_large_header_allowed(aiohttp_client, aiohttp_server) -> None: async def handler(request): @@ -735,6 +795,8 @@ async def handler(request): resp = await client.post("/", headers=headers) assert 200 == resp.status + await resp.release() + async def test_get_with_empty_arg_with_equal(aiohttp_client) -> None: async def handler(request): @@ -749,6 +811,8 @@ async def handler(request): resp = await client.get("/?arg=") assert 200 == resp.status + await resp.release() + async def test_response_with_async_gen(aiohttp_client, fname) -> None: @@ -757,12 +821,11 @@ async def test_response_with_async_gen(aiohttp_client, fname) -> None: data_size = len(data) - @async_generator async def stream(f_name): with f_name.open("rb") as f: data = f.read(100) while data: - await yield_(data) + yield data data = f.read(100) async def handler(request): @@ -779,6 +842,8 @@ async def handler(request): assert resp_data == data assert resp.headers.get("Content-Length") == str(len(resp_data)) + await resp.release() + async def test_response_with_streamer(aiohttp_client, fname) -> None: @@ -819,12 +884,11 @@ async def test_response_with_async_gen_no_params(aiohttp_client, fname) -> None: data_size = len(data) - @async_generator async def stream(): with fname.open("rb") as f: data = f.read(100) while data: - await yield_(data) + yield data data = f.read(100) async def handler(request): @@ -841,6 +905,8 @@ async def handler(request): assert resp_data == data assert resp.headers.get("Content-Length") == str(len(resp_data)) + await resp.release() + async def test_response_with_streamer_no_params(aiohttp_client, fname) -> None: @@ -875,12 +941,15 @@ async def handler(request): async def test_response_with_file(aiohttp_client, fname) -> None: + outer_file_descriptor = None with fname.open("rb") as f: data = f.read() async def handler(request): - return web.Response(body=fname.open("rb")) + nonlocal outer_file_descriptor + outer_file_descriptor = fname.open("rb") + return web.Response(body=outer_file_descriptor) app = web.Application() app.router.add_get("/", handler) @@ -889,9 +958,7 @@ async def handler(request): resp = await client.get("/") assert 200 == resp.status resp_data = await resp.read() - expected_content_disposition = ( - "attachment; filename=\"conftest.py\"; filename*=utf-8''conftest.py" - ) + expected_content_disposition = 'attachment; filename="conftest.py"' assert resp_data == data assert resp.headers.get("Content-Type") in ( "application/octet-stream", @@ -901,15 +968,23 @@ async def handler(request): assert resp.headers.get("Content-Length") == str(len(resp_data)) assert resp.headers.get("Content-Disposition") == expected_content_disposition + await resp.release() + + outer_file_descriptor.close() + async def test_response_with_file_ctype(aiohttp_client, fname) -> None: + outer_file_descriptor = None with fname.open("rb") as f: data = f.read() async def handler(request): + nonlocal outer_file_descriptor + outer_file_descriptor = fname.open("rb") + return web.Response( - body=fname.open("rb"), headers={"content-type": "text/binary"} + body=outer_file_descriptor, headers={"content-type": "text/binary"} ) app = web.Application() @@ -919,22 +994,27 @@ async def handler(request): resp = await client.get("/") assert 200 == resp.status resp_data = await resp.read() - expected_content_disposition = ( - "attachment; filename=\"conftest.py\"; filename*=utf-8''conftest.py" - ) + expected_content_disposition = 'attachment; filename="conftest.py"' assert resp_data == data assert resp.headers.get("Content-Type") == "text/binary" assert resp.headers.get("Content-Length") == str(len(resp_data)) assert resp.headers.get("Content-Disposition") == expected_content_disposition + await resp.release() + + outer_file_descriptor.close() + async def test_response_with_payload_disp(aiohttp_client, fname) -> None: + outer_file_descriptor = None with fname.open("rb") as f: data = f.read() async def handler(request): - pl = aiohttp.get_payload(fname.open("rb")) + nonlocal outer_file_descriptor + outer_file_descriptor = fname.open("rb") + pl = aiohttp.get_payload(outer_file_descriptor) pl.set_content_disposition("inline", filename="test.txt") return web.Response(body=pl, headers={"content-type": "text/binary"}) @@ -948,10 +1028,11 @@ async def handler(request): assert resp_data == data assert resp.headers.get("Content-Type") == "text/binary" assert resp.headers.get("Content-Length") == str(len(resp_data)) - assert ( - resp.headers.get("Content-Disposition") - == "inline; filename=\"test.txt\"; filename*=utf-8''test.txt" - ) + assert resp.headers.get("Content-Disposition") == 'inline; filename="test.txt"' + + await resp.release() + + outer_file_descriptor.close() async def test_response_with_payload_stringio(aiohttp_client, fname) -> None: @@ -967,6 +1048,8 @@ async def handler(request): resp_data = await resp.read() assert resp_data == b"test" + await resp.release() + async def test_response_with_precompressed_body_gzip(aiohttp_client) -> None: async def handler(request): @@ -985,6 +1068,8 @@ async def handler(request): assert b"mydata" == data assert resp.headers.get("Content-Encoding") == "gzip" + await resp.release() + async def test_response_with_precompressed_body_deflate(aiohttp_client) -> None: async def handler(request): @@ -1003,6 +1088,8 @@ async def handler(request): assert b"mydata" == data assert resp.headers.get("Content-Encoding") == "deflate" + await resp.release() + async def test_response_with_precompressed_body_deflate_no_hdrs(aiohttp_client) -> None: async def handler(request): @@ -1040,6 +1127,8 @@ async def handler(request): resp = await client.post("/", data=b"test", headers={"content-encoding": "gzip"}) assert 200 == resp.status + await resp.release() + async def test_stream_response_multiple_chunks(aiohttp_client) -> None: async def handler(request): @@ -1060,6 +1149,8 @@ async def handler(request): data = await resp.read() assert b"xyz" == data + await resp.release() + async def test_start_without_routes(aiohttp_client) -> None: @@ -1069,6 +1160,8 @@ async def test_start_without_routes(aiohttp_client) -> None: resp = await client.get("/") assert 404 == resp.status + await resp.release() + async def test_requests_count(aiohttp_client) -> None: async def handler(request): @@ -1082,14 +1175,17 @@ async def handler(request): resp = await client.get("/") assert 200 == resp.status assert client.server.handler.requests_count == 1 + await resp.release() resp = await client.get("/") assert 200 == resp.status assert client.server.handler.requests_count == 2 + await resp.release() resp = await client.get("/") assert 200 == resp.status assert client.server.handler.requests_count == 3 + await resp.release() async def test_redirect_url(aiohttp_client) -> None: @@ -1107,6 +1203,8 @@ async def redirected(request): resp = await client.get("/redirector") assert resp.status == 200 + await resp.release() + async def test_simple_subapp(aiohttp_client) -> None: async def handler(request): @@ -1123,6 +1221,8 @@ async def handler(request): txt = await resp.text() assert "OK" == txt + await resp.release() + async def test_subapp_reverse_url(aiohttp_client) -> None: async def handler(request): @@ -1144,6 +1244,8 @@ async def handler2(request): assert "OK" == txt assert resp.url.path == "/path/final" + await resp.release() + async def test_subapp_reverse_variable_url(aiohttp_client) -> None: async def handler(request): @@ -1167,6 +1269,8 @@ async def handler2(request): assert "OK" == txt assert resp.url.path == "/path/final" + await resp.release() + async def test_subapp_reverse_static_url(aiohttp_client) -> None: fname = "aiohttp.png" @@ -1188,6 +1292,9 @@ async def handler(request): assert resp.url.path == "/path/static/" + fname assert resp.status == 200 body = await resp.read() + + await resp.release() + with (here / fname).open("rb") as f: assert body == f.read() @@ -1208,6 +1315,8 @@ async def handler(request): txt = await resp.text() assert "OK" == txt + await resp.release() + async def test_subapp_not_found(aiohttp_client) -> None: async def handler(request): @@ -1222,6 +1331,8 @@ async def handler(request): resp = await client.get("/path/other") assert resp.status == 404 + await resp.release() + async def test_subapp_not_found2(aiohttp_client) -> None: async def handler(request): @@ -1236,6 +1347,8 @@ async def handler(request): resp = await client.get("/invalid/other") assert resp.status == 404 + await resp.release() + async def test_subapp_not_allowed(aiohttp_client) -> None: async def handler(request): @@ -1251,6 +1364,8 @@ async def handler(request): assert resp.status == 405 assert resp.headers["Allow"] == "GET,HEAD" + await resp.release() + async def test_subapp_cannot_add_app_in_handler(aiohttp_client) -> None: async def handler(request): @@ -1266,6 +1381,8 @@ async def handler(request): resp = await client.get("/path/to") assert resp.status == 500 + await resp.release() + async def test_subapp_middlewares(aiohttp_client) -> None: order = [] @@ -1273,7 +1390,7 @@ async def test_subapp_middlewares(aiohttp_client) -> None: async def handler(request): return web.Response(text="OK") - async def middleware_factory(app, handler): + async def middleware_factory(app, handler: Handler): async def middleware(request): order.append((1, app)) resp = await handler(request) @@ -1303,6 +1420,8 @@ async def middleware(request): (2, app), ] == order + await resp.release() + async def test_subapp_on_response_prepare(aiohttp_client) -> None: order = [] @@ -1331,6 +1450,8 @@ async def on_response(request, response): assert resp.status == 200 assert [app, subapp1, subapp2] == order + await resp.release() + async def test_subapp_on_startup(aiohttp_server) -> None: order = [] @@ -1412,7 +1533,7 @@ async def test_subapp_middleware_context(aiohttp_client, route, expected, middle def show_app_context(appname): @web.middleware - async def middleware(request, handler): + async def middleware(request, handler: Handler): values.append("{}: {}".format(appname, request.app["my_value"])) return await handler(request) @@ -1444,6 +1565,8 @@ async def handler(request): assert "Ok" == await resp.text() assert expected == values + await resp.release() + async def test_custom_date_header(aiohttp_client) -> None: async def handler(request): @@ -1457,6 +1580,8 @@ async def handler(request): assert 200 == resp.status assert resp.headers["Date"] == "Sun, 30 Oct 2016 03:13:52 GMT" + await resp.release() + async def test_response_prepared_with_clone(aiohttp_client) -> None: async def handler(request): @@ -1472,13 +1597,15 @@ async def handler(request): resp = await client.get("/") assert 200 == resp.status + await resp.release() + async def test_app_max_client_size(aiohttp_client) -> None: async def handler(request): await request.post() return web.Response(body=b"ok") - max_size = 1024 ** 2 + max_size = 1024**2 app = web.Application() app.router.add_post("/", handler) client = await aiohttp_client(app) @@ -1494,23 +1621,28 @@ async def handler(request): body_size = int(resp_text.split()[-1]) assert body_size >= max_size + await resp.release() + async def test_app_max_client_size_adjusted(aiohttp_client) -> None: async def handler(request): await request.post() return web.Response(body=b"ok") - default_max_size = 1024 ** 2 + default_max_size = 1024**2 custom_max_size = default_max_size * 2 app = web.Application(client_max_size=custom_max_size) app.router.add_post("/", handler) client = await aiohttp_client(app) data = {"long_string": default_max_size * "x" + "xxx"} + with pytest.warns(ResourceWarning): resp = await client.post("/", data=data) assert 200 == resp.status resp_text = await resp.text() assert "ok" == resp_text + await resp.release() + too_large_data = {"log_string": custom_max_size * "x" + "xxx"} with pytest.warns(ResourceWarning): resp = await client.post("/", data=too_large_data) @@ -1523,29 +1655,35 @@ async def handler(request): body_size = int(resp_text.split()[-1]) assert body_size >= custom_max_size + await resp.release() + async def test_app_max_client_size_none(aiohttp_client) -> None: async def handler(request): await request.post() return web.Response(body=b"ok") - default_max_size = 1024 ** 2 + default_max_size = 1024**2 custom_max_size = None app = web.Application(client_max_size=custom_max_size) app.router.add_post("/", handler) client = await aiohttp_client(app) + data = {"long_string": default_max_size * "x" + "xxx"} with pytest.warns(ResourceWarning): resp = await client.post("/", data=data) assert 200 == resp.status resp_text = await resp.text() assert "ok" == resp_text + await resp.release() + too_large_data = {"log_string": default_max_size * 2 * "x"} with pytest.warns(ResourceWarning): resp = await client.post("/", data=too_large_data) assert 200 == resp.status resp_text = await resp.text() assert resp_text == "ok" + await resp.release() async def test_post_max_client_size(aiohttp_client) -> None: @@ -1557,14 +1695,19 @@ async def handler(request): app.router.add_post("/", handler) client = await aiohttp_client(app) - data = {"long_string": 1024 * "x", "file": io.BytesIO(b"test")} - resp = await client.post("/", data=data) + with io.BytesIO(b"test") as file_handle: + data = {"long_string": 1024 * "x", "file": file_handle} + resp = await client.post("/", data=data) - assert 413 == resp.status - resp_text = await resp.text() - assert ( - "Maximum request body size 10 exceeded, " "actual body size 1024" in resp_text - ) + assert 413 == resp.status + resp_text = await resp.text() + assert ( + "Maximum request body size 10 exceeded, " + "actual body size 1024" in resp_text + ) + data["file"].close() + + await resp.release() async def test_post_max_client_size_for_file(aiohttp_client) -> None: @@ -1576,11 +1719,14 @@ async def handler(request): app.router.add_post("/", handler) client = await aiohttp_client(app) - data = {"file": io.BytesIO(b"test")} - resp = await client.post("/", data=data) + with io.BytesIO(b"test") as file_handle: + data = {"file": file_handle} + resp = await client.post("/", data=data) assert 413 == resp.status + await resp.release() + async def test_response_with_bodypart(aiohttp_client) -> None: async def handler(request): @@ -1592,18 +1738,18 @@ async def handler(request): app.router.add_post("/", handler) client = await aiohttp_client(app) - data = {"file": io.BytesIO(b"test")} - resp = await client.post("/", data=data) + with io.BytesIO(b"test") as file_handle: + data = {"file": file_handle} + resp = await client.post("/", data=data) - assert 200 == resp.status - body = await resp.read() - assert body == b"test" + assert 200 == resp.status + body = await resp.read() + assert body == b"test" - disp = multipart.parse_content_disposition(resp.headers["content-disposition"]) - assert disp == ( - "attachment", - {"name": "file", "filename": "file", "filename*": "file"}, - ) + disp = multipart.parse_content_disposition(resp.headers["content-disposition"]) + assert disp == ("attachment", {"name": "file", "filename": "file"}) + + await resp.release() async def test_response_with_bodypart_named(aiohttp_client, tmpdir) -> None: @@ -1618,18 +1764,18 @@ async def handler(request): f = tmpdir.join("foobar.txt") f.write_text("test", encoding="utf8") - data = {"file": open(str(f), "rb")} - resp = await client.post("/", data=data) + with open(str(f), "rb") as fd: + data = {"file": fd} + resp = await client.post("/", data=data) - assert 200 == resp.status - body = await resp.read() + assert 200 == resp.status + body = await resp.read() assert body == b"test" disp = multipart.parse_content_disposition(resp.headers["content-disposition"]) - assert disp == ( - "attachment", - {"name": "file", "filename": "foobar.txt", "filename*": "foobar.txt"}, - ) + assert disp == ("attachment", {"name": "file", "filename": "foobar.txt"}) + + await resp.release() async def test_response_with_bodypart_invalid_name(aiohttp_client) -> None: @@ -1652,6 +1798,8 @@ async def handler(request): assert "content-disposition" not in resp.headers + await resp.release() + async def test_request_clone(aiohttp_client) -> None: async def handler(request): @@ -1666,6 +1814,7 @@ async def handler(request): resp = await client.get("/") assert 200 == resp.status + await resp.release() async def test_await(aiohttp_server) -> None: @@ -1700,12 +1849,15 @@ async def handler(request): app = web.Application() app.router.add_route("GET", "/", handler) server = await aiohttp_server(app) - resp = await aiohttp.ClientSession().get(server.make_url("/")) + session = aiohttp.ClientSession() + resp = await session.get(server.make_url("/")) async with resp: assert resp.status == 200 assert resp.connection is None assert resp.connection is None + await session.close() + async def test_response_context_manager_error(aiohttp_server) -> None: async def handler(request): @@ -1726,6 +1878,8 @@ async def handler(request): assert len(session._connector._conns) == 1 + await session.close() + async def aiohttp_client_api_context_manager(aiohttp_server): async def handler(request): @@ -1845,7 +1999,7 @@ async def resolve(self, host, port=0, family=socket.AF_INET): connector = aiohttp.TCPConnector(resolver=resolver) client = aiohttp.ClientSession(connector=connector, trace_configs=[trace_config]) - await client.get("http://example.com/redirector", data="foo") + resp = await client.get("http://example.com/redirector", data="foo") assert on_request_start.called assert on_request_end.called @@ -1854,6 +2008,8 @@ async def resolve(self, host, port=0, family=socket.AF_INET): assert on_request_redirect.called assert on_connection_create_start.called assert on_connection_create_end.called + + await resp.release() await client.close() @@ -1884,6 +2040,7 @@ async def handler(request): assert 200 == resp.status txt = await resp.text() assert "OK" == txt + await resp.release() async def test_app_add_routes(aiohttp_client) -> None: @@ -1896,6 +2053,7 @@ async def handler(request): client = await aiohttp_client(app) resp = await client.get("/get") assert resp.status == 200 + await resp.release() async def test_request_headers_type(aiohttp_client) -> None: @@ -1909,6 +2067,7 @@ async def handler(request): client = await aiohttp_client(app) resp = await client.get("/get") assert resp.status == 200 + await resp.release() async def test_signal_on_error_handler(aiohttp_client) -> None: @@ -1922,6 +2081,7 @@ async def on_prepare(request, response): resp = await client.get("/") assert resp.status == 404 assert resp.headers["X-Custom"] == "val" + await resp.release() @pytest.mark.skipif( @@ -1949,6 +2109,34 @@ async def handler(request): resp = await client.post("/", data=b"data") assert resp.status == 200 assert await resp.text() == "data (2, 4)" + await resp.release() + + +@pytest.mark.parametrize( + "auto_decompress,len_of", [(True, "uncompressed"), (False, "compressed")] +) +async def test_auto_decompress( + aiohttp_client, + auto_decompress, + len_of, +) -> None: + async def handler(request): + data = await request.read() + return web.Response(text=str(len(data))) + + app = web.Application(handler_args={"auto_decompress": auto_decompress}) + app.router.add_post("/", handler) + + client = await aiohttp_client(app) + uncompressed = b"dataaaaaaaaaaaaaaaaaaaaaaaaa" + compressor = zlib.compressobj(wbits=16 + zlib.MAX_WBITS) + compressed = compressor.compress(uncompressed) + compressor.flush() + assert len(compressed) != len(uncompressed) + headers = {"content-encoding": "gzip"} + resp = await client.post("/", data=compressed, headers=headers) + assert resp.status == 200 + assert await resp.text() == str(len(locals()[len_of])) + await resp.release() @pytest.mark.parametrize( @@ -1967,3 +2155,17 @@ async def handler(_): resp = await client.get("/") assert CONTENT_LENGTH not in resp.headers assert TRANSFER_ENCODING not in resp.headers + await resp.release() + + +async def test_stream_response_headers_204(aiohttp_client): + async def handler(_): + return web.StreamResponse(status=204) + + app = web.Application() + app.router.add_get("/", handler) + client = await aiohttp_client(app) + resp = await client.get("/") + assert CONTENT_TYPE not in resp.headers + assert TRANSFER_ENCODING not in resp.headers + await resp.release() diff --git a/tests/test_web_log.py b/tests/test_web_log.py index 0a4168a..54c4fa5 100644 --- a/tests/test_web_log.py +++ b/tests/test_web_log.py @@ -8,6 +8,7 @@ from aiohttp import web from aiohttp.abc import AbstractAccessLogger from aiohttp.helpers import PY_37 +from aiohttp.typedefs import Handler from aiohttp.web_log import AccessLogger try: @@ -177,7 +178,7 @@ async def handler(request): return web.Response() @web.middleware - async def middleware(request, handler): + async def middleware(request, handler: Handler): VAR.set("uuid") return await handler(request) diff --git a/tests/test_web_middleware.py b/tests/test_web_middleware.py index 1a6ea61..4660075 100644 --- a/tests/test_web_middleware.py +++ b/tests/test_web_middleware.py @@ -5,6 +5,7 @@ from yarl import URL from aiohttp import web +from aiohttp.typedefs import Handler async def test_middleware_modifies_response(loop, aiohttp_client) -> None: @@ -12,7 +13,7 @@ async def handler(request): return web.Response(body=b"OK") @web.middleware - async def middleware(request, handler): + async def middleware(request, handler: Handler): resp = await handler(request) assert 200 == resp.status resp.set_status(201) @@ -34,7 +35,7 @@ async def handler(request): raise RuntimeError("Error text") @web.middleware - async def middleware(request, handler): + async def middleware(request, handler: Handler): with pytest.raises(RuntimeError) as ctx: await handler(request) return web.Response(status=501, text=str(ctx.value) + "[MIDDLEWARE]") @@ -62,7 +63,7 @@ async def handler2(request): def make_middleware(num): @web.middleware - async def middleware(request, handler): + async def middleware(request, handler: Handler): middleware_annotation_seen_values.append( getattr(handler, "annotation", None) ) @@ -108,7 +109,7 @@ async def handler(request): def make_middleware(num): @web.middleware - async def middleware(request, handler): + async def middleware(request, handler: Handler): annotation = getattr(handler, "annotation", None) if annotation is not None: middleware_annotation_seen_values.append(f"{annotation}/{num}") @@ -390,7 +391,7 @@ async def test_old_style_middleware(loop, aiohttp_client) -> None: async def handler(request): return web.Response(body=b"OK") - async def middleware_factory(app, handler): + async def middleware_factory(app, handler: Handler): async def middleware(request): resp = await handler(request) assert 200 == resp.status @@ -410,72 +411,21 @@ async def middleware(request): txt = await resp.text() assert "OK[old style middleware]" == txt - assert len(warning_checker) == 1 - msg = str(warning_checker.list[0].message) - assert re.match( - "^old-style middleware " - '".' - 'middleware_factory at 0x[0-9a-fA-F]+>" ' - "deprecated, see #2252$", - msg, - ) - - -async def test_mixed_middleware(loop, aiohttp_client) -> None: - async def handler(request): - return web.Response(body=b"OK") - - async def m_old1(app, handler): - async def middleware(request): - resp = await handler(request) - resp.text += "[old style 1]" - return resp - - return middleware - - @web.middleware - async def m_new1(request, handler): - resp = await handler(request) - resp.text += "[new style 1]" - return resp - - async def m_old2(app, handler): - async def middleware(request): - resp = await handler(request) - resp.text += "[old style 2]" - return resp - - return middleware - - @web.middleware - async def m_new2(request, handler): - resp = await handler(request) - resp.text += "[new style 2]" - return resp - - middlewares = m_old1, m_new1, m_old2, m_new2 - - with pytest.warns(DeprecationWarning) as w: - app = web.Application(middlewares=middlewares) - app.router.add_route("GET", "/", handler) - client = await aiohttp_client(app) - resp = await client.get("/") - assert 200 == resp.status - txt = await resp.text() - assert "OK[new style 2][old style 2][new style 1][old style 1]" == txt - - assert len(w) == 2 - tmpl = ( - "^old-style middleware " - '".' - '{} at 0x[0-9a-fA-F]+>" ' - "deprecated, see #2252$" - ) - p1 = tmpl.format("m_old1") - p2 = tmpl.format("m_old2") + found = False + for obj in warning_checker.list: + msg = str(obj.message) + if "old-style" not in msg: + continue + assert re.match( + "^old-style middleware " + '".' + 'middleware_factory at 0x[0-9a-fA-F]+>" ' + "deprecated, see #2252$", + msg, + ) + found = True - assert re.match(p2, str(w.list[0].message)) - assert re.match(p1, str(w.list[1].message)) + assert found async def test_old_style_middleware_class(loop, aiohttp_client) -> None: @@ -483,7 +433,7 @@ async def handler(request): return web.Response(body=b"OK") class Middleware: - async def __call__(self, app, handler): + async def __call__(self, app, handler: Handler): async def middleware(request): resp = await handler(request) assert 200 == resp.status @@ -503,15 +453,21 @@ async def middleware(request): txt = await resp.text() assert "OK[old style middleware]" == txt - assert len(warning_checker) == 1 - msg = str(warning_checker.list[0].message) - assert re.match( - "^old-style middleware " - '".Middleware object " - 'at 0x[0-9a-fA-F]+>" deprecated, see #2252$', - msg, - ) + found = False + for obj in warning_checker.list: + msg = str(obj.message) + if "old-style" not in msg: + continue + assert re.match( + "^old-style middleware " + '".Middleware object " + 'at 0x[0-9a-fA-F]+>" deprecated, see #2252$', + msg, + ) + found = True + + assert found async def test_new_style_middleware_class(loop, aiohttp_client) -> None: @@ -520,24 +476,21 @@ async def handler(request): @web.middleware class Middleware: - async def __call__(self, request, handler): + async def __call__(self, request, handler: Handler): resp = await handler(request) assert 200 == resp.status resp.set_status(201) resp.text = resp.text + "[new style middleware]" return resp - with pytest.warns(None) as warning_checker: - app = web.Application() - app.middlewares.append(Middleware()) - app.router.add_route("GET", "/", handler) - client = await aiohttp_client(app) - resp = await client.get("/") - assert 201 == resp.status - txt = await resp.text() - assert "OK[new style middleware]" == txt - - assert len(warning_checker) == 0 + app = web.Application() + app.middlewares.append(Middleware()) + app.router.add_route("GET", "/", handler) + client = await aiohttp_client(app) + resp = await client.get("/") + assert 201 == resp.status + txt = await resp.text() + assert "OK[new style middleware]" == txt async def test_new_style_middleware_method(loop, aiohttp_client) -> None: @@ -546,21 +499,18 @@ async def handler(request): class Middleware: @web.middleware - async def call(self, request, handler): + async def call(self, request, handler: Handler): resp = await handler(request) assert 200 == resp.status resp.set_status(201) resp.text = resp.text + "[new style middleware]" return resp - with pytest.warns(None) as warning_checker: - app = web.Application() - app.middlewares.append(Middleware().call) - app.router.add_route("GET", "/", handler) - client = await aiohttp_client(app) - resp = await client.get("/") - assert 201 == resp.status - txt = await resp.text() - assert "OK[new style middleware]" == txt - - assert len(warning_checker) == 0 + app = web.Application() + app.middlewares.append(Middleware().call) + app.router.add_route("GET", "/", handler) + client = await aiohttp_client(app) + resp = await client.get("/") + assert 201 == resp.status + txt = await resp.text() + assert "OK[new style middleware]" == txt diff --git a/tests/test_web_protocol.py b/tests/test_web_protocol.py deleted file mode 100644 index 9795270..0000000 --- a/tests/test_web_protocol.py +++ /dev/null @@ -1,758 +0,0 @@ -# Tests for aiohttp/server.py - -import asyncio -import platform -import socket -from functools import partial -from unittest import mock - -import pytest - -from aiohttp import helpers, http, streams, web - -IS_MACOS = platform.system() == "Darwin" - - -@pytest.fixture -def make_srv(loop, manager): - srv = None - - def maker(*, cls=web.RequestHandler, **kwargs): - nonlocal srv - m = kwargs.pop("manager", manager) - srv = cls(m, loop=loop, access_log=None, **kwargs) - return srv - - yield maker - - if srv is not None: - if srv.transport is not None: - srv.connection_lost(None) - - -@pytest.fixture -def manager(request_handler, loop): - async def maker(): - return web.Server(request_handler) - - return loop.run_until_complete(maker()) - - -@pytest.fixture -def srv(make_srv, transport): - srv = make_srv() - srv.connection_made(transport) - transport.close.side_effect = partial(srv.connection_lost, None) - with mock.patch.object( - web.RequestHandler, "_drain_helper", side_effect=helpers.noop - ): - yield srv - - -@pytest.fixture -def buf(): - return bytearray() - - -@pytest.fixture -def request_handler(): - async def handler(request): - return web.Response() - - m = mock.Mock() - m.side_effect = handler - return m - - -@pytest.fixture -def handle_with_error(): - def wrapper(exc=ValueError): - async def handle(request): - raise exc - - h = mock.Mock() - h.side_effect = handle - return h - - return wrapper - - -@pytest.fixture -def writer(srv): - return http.StreamWriter(srv, srv.transport, srv._loop) - - -@pytest.fixture -def transport(buf): - transport = mock.Mock() - - def write(chunk): - buf.extend(chunk) - - transport.write.side_effect = write - transport.is_closing.return_value = False - - return transport - - -async def test_shutdown(srv, transport) -> None: - loop = asyncio.get_event_loop() - assert transport is srv.transport - - srv._keepalive = True - task_handler = srv._task_handler - - assert srv._waiter is not None - assert srv._task_handler is not None - - t0 = loop.time() - await srv.shutdown() - t1 = loop.time() - - assert t1 - t0 < 0.05, t1 - t0 - - assert transport.close.called - assert srv.transport is None - - assert not srv._task_handler - await asyncio.sleep(0.1) - assert task_handler.done() - - -async def test_double_shutdown(srv, transport) -> None: - await srv.shutdown() - assert transport.close.called - assert srv.transport is None - - transport.reset_mock() - await srv.shutdown() - assert not transport.close.called - assert srv.transport is None - - -async def test_shutdown_wait_error_handler(srv, transport) -> None: - loop = asyncio.get_event_loop() - - async def _error_handle(): - pass - - srv._error_handler = loop.create_task(_error_handle()) - await srv.shutdown() - assert srv._error_handler.done() - - -async def test_close_after_response(srv, transport) -> None: - srv.data_received( - b"GET / HTTP/1.0\r\n" b"Host: example.com\r\n" b"Content-Length: 0\r\n\r\n" - ) - h = srv._task_handler - - await asyncio.sleep(0.1) - assert srv._waiter is None - assert srv._task_handler is None - - assert transport.close.called - assert srv.transport is None - - assert h.done() - - -def test_connection_made(make_srv) -> None: - srv = make_srv() - srv.connection_made(mock.Mock()) - assert not srv._force_close - - -def test_connection_made_with_tcp_keepaplive(make_srv, transport) -> None: - srv = make_srv() - - sock = mock.Mock() - transport.get_extra_info.return_value = sock - srv.connection_made(transport) - sock.setsockopt.assert_called_with(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1) - - -def test_connection_made_without_tcp_keepaplive(make_srv) -> None: - srv = make_srv(tcp_keepalive=False) - - sock = mock.Mock() - transport = mock.Mock() - transport.get_extra_info.return_value = sock - srv.connection_made(transport) - assert not sock.setsockopt.called - - -def test_eof_received(make_srv) -> None: - srv = make_srv() - srv.connection_made(mock.Mock()) - srv.eof_received() - # assert srv.reader._eof - - -async def test_connection_lost(srv) -> None: - srv.data_received( - b"GET / HTTP/1.1\r\n" b"Host: example.com\r\n" b"Content-Length: 0\r\n\r\n" - ) - srv._keepalive = True - - handle = srv._task_handler - await asyncio.sleep(0) # wait for .start() starting - srv.connection_lost(None) - - assert srv._force_close - - await handle - - assert not srv._task_handler - - -def test_srv_keep_alive(srv) -> None: - assert not srv._keepalive - - srv.keep_alive(True) - assert srv._keepalive - - srv.keep_alive(False) - assert not srv._keepalive - - -def test_srv_keep_alive_disable(srv) -> None: - handle = srv._keepalive_handle = mock.Mock() - - srv.keep_alive(False) - assert not srv._keepalive - assert srv._keepalive_handle is None - handle.cancel.assert_called_with() - - -async def test_simple(srv, buf) -> None: - srv.data_received(b"GET / HTTP/1.1\r\n\r\n") - - await asyncio.sleep(0.05) - assert buf.startswith(b"HTTP/1.1 200 OK\r\n") - - -async def test_bad_method(srv, buf) -> None: - srv.data_received(b":BAD; / HTTP/1.0\r\n" b"Host: example.com\r\n\r\n") - - await asyncio.sleep(0) - assert buf.startswith(b"HTTP/1.0 400 Bad Request\r\n") - - -async def test_line_too_long(srv, buf) -> None: - srv.data_received(b"".join([b"a" for _ in range(10000)]) + b"\r\n\r\n") - - await asyncio.sleep(0) - assert buf.startswith(b"HTTP/1.0 400 Bad Request\r\n") - - -async def test_invalid_content_length(srv, buf) -> None: - srv.data_received( - b"GET / HTTP/1.0\r\n" b"Host: example.com\r\n" b"Content-Length: sdgg\r\n\r\n" - ) - await asyncio.sleep(0) - - assert buf.startswith(b"HTTP/1.0 400 Bad Request\r\n") - - -async def test_unhandled_runtime_error(make_srv, transport, request_handler): - async def handle(request): - resp = web.Response() - resp.write_eof = mock.Mock() - resp.write_eof.side_effect = RuntimeError - return resp - - srv = make_srv(lingering_time=0) - srv.debug = True - srv.connection_made(transport) - srv.logger.exception = mock.Mock() - request_handler.side_effect = handle - - srv.data_received( - b"GET / HTTP/1.0\r\n" b"Host: example.com\r\n" b"Content-Length: 0\r\n\r\n" - ) - - await srv._task_handler - assert request_handler.called - srv.logger.exception.assert_called_with( - "Unhandled runtime exception", exc_info=mock.ANY - ) - - -async def test_handle_uncompleted( - make_srv, transport, handle_with_error, request_handler -): - closed = False - - def close(): - nonlocal closed - closed = True - - transport.close.side_effect = close - - srv = make_srv(lingering_time=0) - srv.connection_made(transport) - srv.logger.exception = mock.Mock() - request_handler.side_effect = handle_with_error() - - srv.data_received( - b"GET / HTTP/1.0\r\n" b"Host: example.com\r\n" b"Content-Length: 50000\r\n\r\n" - ) - - await srv._task_handler - assert request_handler.called - assert closed - srv.logger.exception.assert_called_with("Error handling request", exc_info=mock.ANY) - - -@pytest.mark.xfail( - IS_MACOS, - raises=TypeError, - reason="Intermittently fails on macOS", - strict=False, -) -async def test_handle_uncompleted_pipe( - make_srv, transport, request_handler, handle_with_error -): - closed = False - normal_completed = False - - def close(): - nonlocal closed - closed = True - - transport.close.side_effect = close - - srv = make_srv(lingering_time=0) - srv.connection_made(transport) - srv.logger.exception = mock.Mock() - - async def handle(request): - nonlocal normal_completed - normal_completed = True - await asyncio.sleep(0.05) - return web.Response() - - # normal - request_handler.side_effect = handle - srv.data_received( - b"GET / HTTP/1.1\r\n" b"Host: example.com\r\n" b"Content-Length: 0\r\n\r\n" - ) - await asyncio.sleep(0.01) - - # with exception - request_handler.side_effect = handle_with_error() - srv.data_received( - b"GET / HTTP/1.1\r\n" b"Host: example.com\r\n" b"Content-Length: 50000\r\n\r\n" - ) - - assert srv._task_handler - - await asyncio.sleep(0.01) - - await srv._task_handler - assert normal_completed - assert request_handler.called - assert closed - srv.logger.exception.assert_called_with("Error handling request", exc_info=mock.ANY) - - -async def test_lingering(srv, transport) -> None: - assert not transport.close.called - - async def handle(message, request, writer): - pass - - with mock.patch.object( - web.RequestHandler, "handle_request", create=True, new=handle - ): - srv.data_received( - b"GET / HTTP/1.0\r\n" b"Host: example.com\r\n" b"Content-Length: 3\r\n\r\n" - ) - - await asyncio.sleep(0.05) - assert not transport.close.called - - srv.data_received(b"123") - - await asyncio.sleep(0) - transport.close.assert_called_with() - - -async def test_lingering_disabled(make_srv, transport, request_handler) -> None: - async def handle_request(request): - await asyncio.sleep(0) - - srv = make_srv(lingering_time=0) - srv.connection_made(transport) - request_handler.side_effect = handle_request - - await asyncio.sleep(0) - assert not transport.close.called - - srv.data_received( - b"GET / HTTP/1.0\r\n" b"Host: example.com\r\n" b"Content-Length: 50\r\n\r\n" - ) - await asyncio.sleep(0) - assert not transport.close.called - await asyncio.sleep(0.05) - transport.close.assert_called_with() - - -async def test_lingering_timeout(make_srv, transport, request_handler): - async def handle_request(request): - await asyncio.sleep(0) - - srv = make_srv(lingering_time=1e-30) - srv.connection_made(transport) - request_handler.side_effect = handle_request - - await asyncio.sleep(0.05) - assert not transport.close.called - - srv.data_received( - b"GET / HTTP/1.0\r\n" b"Host: example.com\r\n" b"Content-Length: 50\r\n\r\n" - ) - await asyncio.sleep(0) - assert not transport.close.called - - await asyncio.sleep(0.05) - transport.close.assert_called_with() - - -async def test_handle_payload_access_error(make_srv, transport, request_handler): - srv = make_srv(lingering_time=0) - srv.connection_made(transport) - srv.data_received( - b"POST /test HTTP/1.1\r\n" b"Content-Length: 9\r\n\r\n" b"some data" - ) - # start request_handler task - await asyncio.sleep(0.05) - - with pytest.raises(web.PayloadAccessError): - await request_handler.call_args[0][0].content.read() - - -async def test_handle_cancel(make_srv, transport) -> None: - log = mock.Mock() - - srv = make_srv(logger=log, debug=True) - srv.connection_made(transport) - - async def handle_request(message, payload, writer): - await asyncio.sleep(10) - - async def cancel(): - srv._task_handler.cancel() - - with mock.patch.object( - web.RequestHandler, "handle_request", create=True, new=handle_request - ): - srv.data_received( - b"GET / HTTP/1.0\r\n" b"Content-Length: 10\r\n" b"Host: example.com\r\n\r\n" - ) - - await asyncio.gather(srv._task_handler, cancel()) - assert log.debug.called - - -async def test_handle_cancelled(make_srv, transport) -> None: - log = mock.Mock() - - srv = make_srv(logger=log, debug=True) - srv.connection_made(transport) - - # start request_handler task - await asyncio.sleep(0) - - srv.data_received(b"GET / HTTP/1.0\r\n" b"Host: example.com\r\n\r\n") - - r_handler = srv._task_handler - assert (await r_handler) is None - - -async def test_handle_400(srv, buf, transport) -> None: - srv.data_received(b"GET / HT/asd\r\n\r\n") - - await asyncio.sleep(0) - assert b"400 Bad Request" in buf - - -async def test_keep_alive(make_srv, transport) -> None: - loop = asyncio.get_event_loop() - srv = make_srv(keepalive_timeout=0.05) - future = loop.create_future() - future.set_result(1) - - with mock.patch.object( - web.RequestHandler, "KEEPALIVE_RESCHEDULE_DELAY", new=0.1 - ), mock.patch.object( - web.RequestHandler, "handle_request", create=True, return_value=future - ): - srv.connection_made(transport) - srv.keep_alive(True) - srv.data_received( - b"GET / HTTP/1.1\r\n" b"Host: example.com\r\n" b"Content-Length: 0\r\n\r\n" - ) - - waiter = None - while waiter is None: - await asyncio.sleep(0) - waiter = srv._waiter - assert srv._keepalive_handle is not None - assert not transport.close.called - - await asyncio.sleep(0.2) - assert transport.close.called - assert waiter.cancelled - - -async def test_srv_process_request_without_timeout(make_srv, transport) -> None: - srv = make_srv() - srv.connection_made(transport) - - srv.data_received(b"GET / HTTP/1.0\r\n" b"Host: example.com\r\n\r\n") - - await srv._task_handler - assert transport.close.called - - -def test_keep_alive_timeout_default(srv) -> None: - assert 75 == srv.keepalive_timeout - - -def test_keep_alive_timeout_nondefault(make_srv) -> None: - srv = make_srv(keepalive_timeout=10) - assert 10 == srv.keepalive_timeout - - -async def test_supports_connect_method(srv, transport, request_handler) -> None: - srv.data_received( - b"CONNECT aiohttp.readthedocs.org:80 HTTP/1.0\r\n" b"Content-Length: 0\r\n\r\n" - ) - await asyncio.sleep(0.1) - - assert request_handler.called - assert isinstance(request_handler.call_args[0][0].content, streams.StreamReader) - - -async def test_content_length_0(srv, request_handler) -> None: - srv.data_received( - b"GET / HTTP/1.1\r\n" b"Host: example.org\r\n" b"Content-Length: 0\r\n\r\n" - ) - await asyncio.sleep(0.01) - - assert request_handler.called - assert request_handler.call_args[0][0].content == streams.EMPTY_PAYLOAD - - -def test_rudimentary_transport(srv) -> None: - transport = mock.Mock() - srv.connection_made(transport) - - srv.pause_reading() - assert srv._reading_paused - assert transport.pause_reading.called - - srv.resume_reading() - assert not srv._reading_paused - assert transport.resume_reading.called - - transport.resume_reading.side_effect = NotImplementedError() - transport.pause_reading.side_effect = NotImplementedError() - - srv._reading_paused = False - srv.pause_reading() - assert srv._reading_paused - - srv.resume_reading() - assert not srv._reading_paused - - -async def test_pipeline_multiple_messages(srv, transport, request_handler): - transport.close.side_effect = partial(srv.connection_lost, None) - - processed = 0 - - async def handle(request): - nonlocal processed - processed += 1 - return web.Response() - - request_handler.side_effect = handle - - assert transport is srv.transport - - srv._keepalive = True - srv.data_received( - b"GET / HTTP/1.1\r\n" - b"Host: example.com\r\n" - b"Content-Length: 0\r\n\r\n" - b"GET / HTTP/1.1\r\n" - b"Host: example.com\r\n" - b"Content-Length: 0\r\n\r\n" - ) - - assert srv._task_handler is not None - assert len(srv._messages) == 2 - assert srv._waiter is not None - - await asyncio.sleep(0.05) - assert srv._task_handler is not None - assert srv._waiter is not None - assert processed == 2 - - -async def test_pipeline_response_order(srv, buf, transport, request_handler): - transport.close.side_effect = partial(srv.connection_lost, None) - srv._keepalive = True - - processed = [] - - async def handle1(request): - nonlocal processed - await asyncio.sleep(0.01) - resp = web.StreamResponse() - await resp.prepare(request) - await resp.write(b"test1") - await resp.write_eof() - processed.append(1) - return resp - - request_handler.side_effect = handle1 - srv.data_received( - b"GET / HTTP/1.1\r\n" b"Host: example.com\r\n" b"Content-Length: 0\r\n\r\n" - ) - await asyncio.sleep(0.01) - - # second - - async def handle2(request): - nonlocal processed - resp = web.StreamResponse() - await resp.prepare(request) - await resp.write(b"test2") - await resp.write_eof() - processed.append(2) - return resp - - request_handler.side_effect = handle2 - srv.data_received( - b"GET / HTTP/1.1\r\n" b"Host: example.com\r\n" b"Content-Length: 0\r\n\r\n" - ) - await asyncio.sleep(0.01) - - assert srv._task_handler is not None - - await asyncio.sleep(0.1) - assert processed == [1, 2] - - -def test_data_received_close(srv) -> None: - srv.close() - srv.data_received( - b"GET / HTTP/1.1\r\n" b"Host: example.com\r\n" b"Content-Length: 0\r\n\r\n" - ) - - assert not srv._messages - - -def test_data_received_force_close(srv) -> None: - srv.force_close() - srv.data_received( - b"GET / HTTP/1.1\r\n" b"Host: example.com\r\n" b"Content-Length: 0\r\n\r\n" - ) - - assert not srv._messages - - -async def test__process_keepalive(srv) -> None: - loop = asyncio.get_event_loop() - # wait till the waiter is waiting - await asyncio.sleep(0) - - assert srv._waiter is not None - - srv._keepalive_time = 1 - srv._keepalive = True - srv._keepalive_timeout = 1 - expired_time = srv._keepalive_time + srv._keepalive_timeout + 1 - with mock.patch.object(loop, "time", return_value=expired_time): - srv._process_keepalive() - assert srv._force_close - - -async def test__process_keepalive_schedule_next(srv) -> None: - loop = asyncio.get_event_loop() - # wait till the waiter is waiting - await asyncio.sleep(0) - - srv._keepalive = True - srv._keepalive_time = 1 - srv._keepalive_timeout = 1 - expire_time = srv._keepalive_time + srv._keepalive_timeout - with mock.patch.object(loop, "time", return_value=expire_time): - with mock.patch.object(loop, "call_later") as call_later_patched: - srv._process_keepalive() - call_later_patched.assert_called_with(1, srv._process_keepalive) - - -async def test__process_keepalive_force_close(srv) -> None: - loop = asyncio.get_event_loop() - srv._force_close = True - with mock.patch.object(loop, "call_at") as call_at_patched: - srv._process_keepalive() - assert not call_at_patched.called - - -async def test_two_data_received_without_waking_up_start_task(srv) -> None: - # make a chance to srv.start() method start waiting for srv._waiter - await asyncio.sleep(0.01) - assert srv._waiter is not None - - srv.data_received( - b"GET / HTTP/1.1\r\n" b"Host: ex.com\r\n" b"Content-Length: 1\r\n\r\n" b"a" - ) - srv.data_received( - b"GET / HTTP/1.1\r\n" b"Host: ex.com\r\n" b"Content-Length: 1\r\n\r\n" b"b" - ) - - assert len(srv._messages) == 2 - assert srv._waiter.done() - await asyncio.sleep(0.01) - - -async def test_client_disconnect(aiohttp_server) -> None: - async def handler(request): - buf = b"" - with pytest.raises(ConnectionError): - while len(buf) < 10: - buf += await request.content.read(10) - # return with closed transport means premature client disconnection - return web.Response() - - logger = mock.Mock() - app = web.Application() - app._debug = True - app.router.add_route("POST", "/", handler) - server = await aiohttp_server(app, logger=logger) - - _, writer = await asyncio.open_connection("127.0.0.1", server.port) - writer.write( - """POST / HTTP/1.1\r -Connection: keep-alive\r -Content-Length: 10\r -Host: localhost:{port}\r -\r -""".format( - port=server.port - ).encode( - "ascii" - ) - ) - await writer.drain() - await asyncio.sleep(0.1) - writer.write(b"x") - writer.close() - await asyncio.sleep(0.1) - logger.debug.assert_called_with("Ignored premature client disconnection") diff --git a/tests/test_web_request.py b/tests/test_web_request.py index f251e04..c6aeaf8 100644 --- a/tests/test_web_request.py +++ b/tests/test_web_request.py @@ -1,4 +1,5 @@ import asyncio +import datetime import socket from collections.abc import MutableMapping from typing import Any @@ -14,6 +15,7 @@ from aiohttp.streams import StreamReader from aiohttp.test_utils import make_mocked_request from aiohttp.web import BaseRequest, HTTPRequestEntityTooLarge +from aiohttp.web_request import ETag @pytest.fixture @@ -155,6 +157,14 @@ def test_non_ascii_raw_path() -> None: assert "/путь" == req.raw_path +def test_absolute_url() -> None: + req = make_mocked_request("GET", "https://example.com/path/to?a=1") + assert req.url == URL("https://example.com/path/to?a=1") + assert req.scheme == "https" + assert req.host == "example.com" + assert req.rel_url == URL.build(path="/path/to", query={"a": "1"}) + + def test_content_length() -> None: req = make_mocked_request("Get", "/", CIMultiDict([("CONTENT-LENGTH", "123")])) @@ -544,7 +554,7 @@ def test_clone_headers_dict() -> None: async def test_cannot_clone_after_read(protocol) -> None: - payload = StreamReader(protocol, 2 ** 16, loop=asyncio.get_event_loop()) + payload = StreamReader(protocol, 2**16, loop=asyncio.get_event_loop()) payload.feed_data(b"data") payload.feed_eof() req = make_mocked_request("GET", "/path", payload=payload) @@ -554,8 +564,8 @@ async def test_cannot_clone_after_read(protocol) -> None: async def test_make_too_big_request(protocol) -> None: - payload = StreamReader(protocol, 2 ** 16, loop=asyncio.get_event_loop()) - large_file = 1024 ** 2 * b"x" + payload = StreamReader(protocol, 2**16, loop=asyncio.get_event_loop()) + large_file = 1024**2 * b"x" too_large_file = large_file + b"x" payload.feed_data(too_large_file) payload.feed_eof() @@ -567,19 +577,19 @@ async def test_make_too_big_request(protocol) -> None: async def test_make_too_big_request_adjust_limit(protocol) -> None: - payload = StreamReader(protocol, 2 ** 16, loop=asyncio.get_event_loop()) - large_file = 1024 ** 2 * b"x" + payload = StreamReader(protocol, 2**16, loop=asyncio.get_event_loop()) + large_file = 1024**2 * b"x" too_large_file = large_file + b"x" payload.feed_data(too_large_file) payload.feed_eof() - max_size = 1024 ** 2 + 2 + max_size = 1024**2 + 2 req = make_mocked_request("POST", "/", payload=payload, client_max_size=max_size) txt = await req.read() - assert len(txt) == 1024 ** 2 + 1 + assert len(txt) == 1024**2 + 1 async def test_multipart_formdata(protocol) -> None: - payload = StreamReader(protocol, 2 ** 16, loop=asyncio.get_event_loop()) + payload = StreamReader(protocol, 2**16, loop=asyncio.get_event_loop()) payload.feed_data( b"-----------------------------326931944431359\r\n" b'Content-Disposition: form-data; name="a"\r\n' @@ -604,7 +614,7 @@ async def test_multipart_formdata(protocol) -> None: async def test_multipart_formdata_file(protocol) -> None: # Make sure file uploads work, even without a content type - payload = StreamReader(protocol, 2 ** 16, loop=asyncio.get_event_loop()) + payload = StreamReader(protocol, 2**16, loop=asyncio.get_event_loop()) payload.feed_data( b"-----------------------------326931944431359\r\n" b'Content-Disposition: form-data; name="a_file"; filename="binary"\r\n' @@ -624,17 +634,19 @@ async def test_multipart_formdata_file(protocol) -> None: content = result["a_file"].file.read() assert content == b"\ff" + result["a_file"].file.close() + async def test_make_too_big_request_limit_None(protocol) -> None: - payload = StreamReader(protocol, 2 ** 16, loop=asyncio.get_event_loop()) - large_file = 1024 ** 2 * b"x" + payload = StreamReader(protocol, 2**16, loop=asyncio.get_event_loop()) + large_file = 1024**2 * b"x" too_large_file = large_file + b"x" payload.feed_data(too_large_file) payload.feed_eof() max_size = None req = make_mocked_request("POST", "/", payload=payload, client_max_size=max_size) txt = await req.read() - assert len(txt) == 1024 ** 2 + 1 + assert len(txt) == 1024**2 + 1 def test_remote_peername_tcp() -> None: @@ -742,3 +754,72 @@ async def test_loop_prop() -> None: req = make_mocked_request("GET", "/path", loop=loop) with pytest.warns(DeprecationWarning): assert req.loop is loop + + +@pytest.mark.parametrize( + ["header", "header_attr"], + [ + pytest.param("If-Match", "if_match"), + pytest.param("If-None-Match", "if_none_match"), + ], +) +@pytest.mark.parametrize( + ["header_val", "expected"], + [ + pytest.param( + '"67ab43", W/"54ed21", "7892,dd"', + ( + ETag(is_weak=False, value="67ab43"), + ETag(is_weak=True, value="54ed21"), + ETag(is_weak=False, value="7892,dd"), + ), + ), + pytest.param( + '"bfc1ef-5b2c2730249c88ca92d82d"', + (ETag(is_weak=False, value="bfc1ef-5b2c2730249c88ca92d82d"),), + ), + pytest.param( + '"valid-tag", "also-valid-tag",somegarbage"last-tag"', + ( + ETag(is_weak=False, value="valid-tag"), + ETag(is_weak=False, value="also-valid-tag"), + ), + ), + pytest.param( + '"ascii", "это точно не ascii", "ascii again"', + (ETag(is_weak=False, value="ascii"),), + ), + pytest.param( + "*", + (ETag(is_weak=False, value="*"),), + ), + ], +) +def test_etag_headers(header, header_attr, header_val, expected) -> None: + req = make_mocked_request("GET", "/", headers={header: header_val}) + assert getattr(req, header_attr) == expected + + +@pytest.mark.parametrize( + ["header", "header_attr"], + [ + pytest.param("If-Modified-Since", "if_modified_since"), + pytest.param("If-Unmodified-Since", "if_unmodified_since"), + pytest.param("If-Range", "if_range"), + ], +) +@pytest.mark.parametrize( + ["header_val", "expected"], + [ + pytest.param("xxyyzz", None), + pytest.param("Tue, 08 Oct 4446413 00:56:40 GMT", None), + pytest.param("Tue, 08 Oct 2000 00:56:80 GMT", None), + pytest.param( + "Tue, 08 Oct 2000 00:56:40 GMT", + datetime.datetime(2000, 10, 8, 0, 56, 40, tzinfo=datetime.timezone.utc), + ), + ], +) +def test_datetime_headers(header, header_attr, header_val, expected) -> None: + req = make_mocked_request("GET", "/", headers={header: header_val}) + assert getattr(req, header_attr) == expected diff --git a/tests/test_web_response.py b/tests/test_web_response.py index f847343..c514cba 100644 --- a/tests/test_web_response.py +++ b/tests/test_web_response.py @@ -5,11 +5,14 @@ from concurrent.futures import ThreadPoolExecutor from unittest import mock +import aiosignal import pytest from multidict import CIMultiDict, CIMultiDictProxy from re_assert import Matches -from aiohttp import HttpVersion, HttpVersion10, HttpVersion11, hdrs, signals +from aiohttp import HttpVersion, HttpVersion10, HttpVersion11, hdrs +from aiohttp.helpers import ETag +from aiohttp.http_writer import _serialize_headers from aiohttp.payload import BytesPayload from aiohttp.test_utils import make_mocked_coro, make_mocked_request from aiohttp.web import ContentCoding, Response, StreamResponse, json_response @@ -21,12 +24,12 @@ def make_request( headers=CIMultiDict(), version=HttpVersion11, on_response_prepare=None, - **kwargs + **kwargs, ): app = kwargs.pop("app", None) or mock.Mock() app._debug = False if on_response_prepare is None: - on_response_prepare = signals.Signal(app) + on_response_prepare = aiosignal.Signal(app) app.on_response_prepare = on_response_prepare app.on_response_prepare.freeze() protocol = kwargs.pop("protocol", None) or mock.Mock() @@ -54,12 +57,7 @@ def write(chunk): buf.extend(chunk) async def write_headers(status_line, headers): - headers = ( - status_line - + "\r\n" - + "".join([k + ": " + v + "\r\n" for k, v in headers.items()]) - ) - headers = headers.encode("utf-8") + b"\r\n" + headers = _serialize_headers(status_line, headers) buf.extend(headers) async def write_eof(chunk=b""): @@ -253,6 +251,95 @@ def test_last_modified_reset() -> None: assert resp.last_modified is None +@pytest.mark.parametrize( + ["header_val", "expected"], + [ + pytest.param("xxyyzz", None), + pytest.param("Tue, 08 Oct 4446413 00:56:40 GMT", None), + pytest.param("Tue, 08 Oct 2000 00:56:80 GMT", None), + ], +) +def test_last_modified_string_invalid(header_val, expected) -> None: + resp = StreamResponse(headers={"Last-Modified": header_val}) + assert resp.last_modified == expected + + +def test_etag_initial() -> None: + resp = StreamResponse() + assert resp.etag is None + + +def test_etag_string() -> None: + resp = StreamResponse() + value = "0123-kotik" + resp.etag = value + assert resp.etag == ETag(value=value) + assert resp.headers[hdrs.ETAG] == f'"{value}"' + + +@pytest.mark.parametrize( + ["etag", "expected_header"], + ( + (ETag(value="0123-weak-kotik", is_weak=True), 'W/"0123-weak-kotik"'), + (ETag(value="0123-strong-kotik", is_weak=False), '"0123-strong-kotik"'), + ), +) +def test_etag_class(etag, expected_header) -> None: + resp = StreamResponse() + resp.etag = etag + assert resp.etag == etag + assert resp.headers[hdrs.ETAG] == expected_header + + +def test_etag_any() -> None: + resp = StreamResponse() + resp.etag = "*" + assert resp.etag == ETag(value="*") + assert resp.headers[hdrs.ETAG] == "*" + + +@pytest.mark.parametrize( + "invalid_value", + ( + '"invalid"', + "повинен бути ascii", + ETag(value='"invalid"', is_weak=True), + ETag(value="bad ©®"), + ), +) +def test_etag_invalid_value_set(invalid_value) -> None: + resp = StreamResponse() + with pytest.raises(ValueError, match="is not a valid etag"): + resp.etag = invalid_value + + +@pytest.mark.parametrize( + "header", + ( + "forgotten quotes", + '"∀ x ∉ ascii"', + ), +) +def test_etag_invalid_value_get(header) -> None: + resp = StreamResponse() + resp.headers["ETag"] = header + assert resp.etag is None + + +@pytest.mark.parametrize("invalid", (123, ETag(value=123, is_weak=True))) +def test_etag_invalid_value_class(invalid) -> None: + resp = StreamResponse() + with pytest.raises(ValueError, match="Unsupported etag type"): + resp.etag = invalid + + +def test_etag_reset() -> None: + resp = StreamResponse() + resp.etag = "*" + resp.etag = None + assert resp.etag is None + + async def test_start() -> None: req = make_request("GET", "/") resp = StreamResponse() @@ -820,7 +907,7 @@ async def test_prepare_twice() -> None: async def test_prepare_calls_signal() -> None: app = mock.Mock() sig = make_mocked_coro() - on_response_prepare = signals.Signal(app) + on_response_prepare = aiosignal.Signal(app) on_response_prepare.append(sig) req = make_request("GET", "/", app=app, on_response_prepare=on_response_prepare) resp = StreamResponse() @@ -1184,7 +1271,7 @@ async def _strip_server(req, res): del res.headers["Server"] app = mock.Mock() - sig = signals.Signal(app) + sig = aiosignal.Signal(app) sig.append(_strip_server) req = make_request("GET", "/", on_response_prepare=sig, app=app) diff --git a/tests/test_web_runner.py b/tests/test_web_runner.py index af6df1a..b8a738e 100644 --- a/tests/test_web_runner.py +++ b/tests/test_web_runner.py @@ -1,6 +1,7 @@ import asyncio import platform import signal +import sys from unittest.mock import patch import pytest @@ -104,21 +105,17 @@ def test_non_app() -> None: web.AppRunner(object()) -@pytest.mark.skipif( - platform.system() == "Windows", reason="Unix socket support is required" -) -async def test_addresses(make_runner, shorttmpdir) -> None: +async def test_addresses(make_runner, unix_sockname) -> None: _sock = get_unused_port_socket("127.0.0.1") runner = make_runner() await runner.setup() tcp = web.SockSite(runner, _sock) await tcp.start() - path = str(shorttmpdir / "tmp.sock") - unix = web.UnixSite(runner, path) + unix = web.UnixSite(runner, unix_sockname) await unix.start() actual_addrs = runner.addresses expected_host, expected_post = _sock.getsockname()[:2] - assert actual_addrs == [(expected_host, expected_post), path] + assert actual_addrs == [(expected_host, expected_post), unix_sockname] @pytest.mark.skipif( @@ -162,3 +159,28 @@ async def mock_create_server(*args, **kwargs): assert server is runner.server assert host is None assert port == 8080 + + +@pytest.mark.skipif(sys.version_info < (3, 7), reason="Requires asyncio.run()") +def test_run_after_asyncio_run() -> None: + async def nothing(): + pass + + def spy(): + spy.called = True + + spy.called = False + + async def shutdown(): + spy() + raise web.GracefulExit() + + # asyncio.run() creates a new loop and closes it. + asyncio.run(nothing()) + + app = web.Application() + # create_task() will delay the function until app is run. + app.on_startup.append(lambda a: asyncio.create_task(shutdown())) + + web.run_app(app) + assert spy.called, "run_app() should work after asyncio.run()." diff --git a/tests/test_web_sendfile.py b/tests/test_web_sendfile.py index 4835354..d7e078a 100644 --- a/tests/test_web_sendfile.py +++ b/tests/test_web_sendfile.py @@ -14,7 +14,8 @@ def test_using_gzip_if_header_present_and_file_available(loop) -> None: gz_filepath.open = mock.mock_open() gz_filepath.is_file.return_value = True gz_filepath.stat.return_value = mock.MagicMock() - gz_filepath.stat.st_size = 1024 + gz_filepath.stat.return_value.st_size = 1024 + gz_filepath.stat.return_value.st_mtime_ns = 1603733507222449291 filepath = mock.Mock() filepath.name = "logo.png" @@ -22,7 +23,7 @@ def test_using_gzip_if_header_present_and_file_available(loop) -> None: filepath.with_name.return_value = gz_filepath file_sender = FileResponse(filepath) - file_sender._sendfile = make_mocked_coro(None) + file_sender._sendfile = make_mocked_coro(None) # type: ignore[assignment] loop.run_until_complete(file_sender.prepare(request)) @@ -42,10 +43,11 @@ def test_gzip_if_header_not_present_and_file_available(loop) -> None: filepath.open = mock.mock_open() filepath.with_name.return_value = gz_filepath filepath.stat.return_value = mock.MagicMock() - filepath.stat.st_size = 1024 + filepath.stat.return_value.st_size = 1024 + filepath.stat.return_value.st_mtime_ns = 1603733507222449291 file_sender = FileResponse(filepath) - file_sender._sendfile = make_mocked_coro(None) + file_sender._sendfile = make_mocked_coro(None) # type: ignore[assignment] loop.run_until_complete(file_sender.prepare(request)) @@ -65,10 +67,11 @@ def test_gzip_if_header_not_present_and_file_not_available(loop) -> None: filepath.open = mock.mock_open() filepath.with_name.return_value = gz_filepath filepath.stat.return_value = mock.MagicMock() - filepath.stat.st_size = 1024 + filepath.stat.return_value.st_size = 1024 + filepath.stat.return_value.st_mtime_ns = 1603733507222449291 file_sender = FileResponse(filepath) - file_sender._sendfile = make_mocked_coro(None) + file_sender._sendfile = make_mocked_coro(None) # type: ignore[assignment] loop.run_until_complete(file_sender.prepare(request)) @@ -90,10 +93,11 @@ def test_gzip_if_header_present_and_file_not_available(loop) -> None: filepath.open = mock.mock_open() filepath.with_name.return_value = gz_filepath filepath.stat.return_value = mock.MagicMock() - filepath.stat.st_size = 1024 + filepath.stat.return_value.st_size = 1024 + filepath.stat.return_value.st_mtime_ns = 1603733507222449291 file_sender = FileResponse(filepath) - file_sender._sendfile = make_mocked_coro(None) + file_sender._sendfile = make_mocked_coro(None) # type: ignore[assignment] loop.run_until_complete(file_sender.prepare(request)) @@ -108,10 +112,11 @@ def test_status_controlled_by_user(loop) -> None: filepath.name = "logo.png" filepath.open = mock.mock_open() filepath.stat.return_value = mock.MagicMock() - filepath.stat.st_size = 1024 + filepath.stat.return_value.st_size = 1024 + filepath.stat.return_value.st_mtime_ns = 1603733507222449291 file_sender = FileResponse(filepath, status=203) - file_sender._sendfile = make_mocked_coro(None) + file_sender._sendfile = make_mocked_coro(None) # type: ignore[assignment] loop.run_until_complete(file_sender.prepare(request)) diff --git a/tests/test_web_sendfile_functional.py b/tests/test_web_sendfile_functional.py index 60a542b..3f4f133 100644 --- a/tests/test_web_sendfile_functional.py +++ b/tests/test_web_sendfile_functional.py @@ -3,6 +3,7 @@ import pathlib import socket import zlib +from typing import Any, Iterable import pytest @@ -24,6 +25,17 @@ def sendfile(*args, **kwargs): return loop +@pytest.fixture +def loop_with_mocked_native_sendfile(loop: Any): + def sendfile(transport, fobj, offset, count): + if count == 0: + raise ValueError("count must be a positive integer (got 0)") + raise NotImplementedError + + loop.sendfile = sendfile + return loop + + @pytest.fixture(params=["sendfile", "no_sendfile"], ids=["sendfile", "no_sendfile"]) def sender(request, loop_without_sendfile): def maker(*args, **kwargs): @@ -35,15 +47,24 @@ def maker(*args, **kwargs): return maker -async def test_static_file_ok(aiohttp_client, sender) -> None: - filepath = pathlib.Path(__file__).parent / "data.unknown_mime_type" +@pytest.fixture +def app_with_static_route(sender): + filename = "data.unknown_mime_type" + filepath = pathlib.Path(__file__).parent / filename async def handler(request): return sender(filepath) app = web.Application() app.router.add_get("/", handler) - client = await aiohttp_client(app) + return app + + +async def test_static_file_ok( + aiohttp_client: Any, + app_with_static_route: web.Application, +) -> None: + client = await aiohttp_client(app_with_static_route) resp = await client.get("/") assert resp.status == 200 @@ -52,6 +73,7 @@ async def handler(request): assert "application/octet-stream" == resp.headers["Content-Type"] assert resp.headers.get("Content-Encoding") is None await resp.release() + await client.close() async def test_zero_bytes_file_ok(aiohttp_client, sender) -> None: @@ -64,25 +86,56 @@ async def handler(request): app.router.add_get("/", handler) client = await aiohttp_client(app) - resp = await client.get("/") - assert resp.status == 200 - txt = await resp.text() - assert "" == txt.rstrip() - assert "application/octet-stream" == resp.headers["Content-Type"] - assert resp.headers.get("Content-Encoding") is None - await resp.release() + # Run the request multiple times to ensure + # that an untrapped exception is not hidden + # because there is no read of the zero bytes + for i in range(2): + resp = await client.get("/") + assert resp.status == 200 + txt = await resp.text() + assert "" == txt.rstrip() + assert "application/octet-stream" == resp.headers["Content-Type"] + assert resp.headers.get("Content-Encoding") is None + await resp.release() + await client.close() -async def test_static_file_ok_string_path(aiohttp_client, sender) -> None: - filepath = pathlib.Path(__file__).parent / "data.unknown_mime_type" + +async def test_zero_bytes_file_mocked_native_sendfile( + aiohttp_client: Any, loop_with_mocked_native_sendfile: Any +) -> None: + filepath = pathlib.Path(__file__).parent / "data.zero_bytes" async def handler(request): - return sender(str(filepath)) + asyncio.set_event_loop(loop_with_mocked_native_sendfile) + return web.FileResponse(filepath) app = web.Application() app.router.add_get("/", handler) client = await aiohttp_client(app) + # Run the request multiple times to ensure + # that an untrapped exception is not hidden + # because there is no read of the zero bytes + for i in range(2): + resp = await client.get("/") + assert resp.status == 200 + txt = await resp.text() + assert "" == txt.rstrip() + assert "application/octet-stream" == resp.headers["Content-Type"] + assert resp.headers.get("Content-Encoding") is None + assert resp.headers.get("Content-Length") == "0" + await resp.release() + + await client.close() + + +async def test_static_file_ok_string_path( + aiohttp_client: Any, + app_with_static_route: web.Application, +) -> None: + client = await aiohttp_client(app_with_static_route) + resp = await client.get("/") assert resp.status == 200 txt = await resp.text() @@ -90,6 +143,7 @@ async def handler(request): assert "application/octet-stream" == resp.headers["Content-Type"] assert resp.headers.get("Content-Encoding") is None await resp.release() + await client.close() async def test_static_file_not_exists(aiohttp_client) -> None: @@ -100,6 +154,7 @@ async def test_static_file_not_exists(aiohttp_client) -> None: resp = await client.get("/fake") assert resp.status == 404 await resp.release() + await client.close() async def test_static_file_name_too_long(aiohttp_client) -> None: @@ -110,6 +165,7 @@ async def test_static_file_name_too_long(aiohttp_client) -> None: resp = await client.get("/x*500") assert resp.status == 404 await resp.release() + await client.close() async def test_static_file_upper_directory(aiohttp_client) -> None: @@ -120,6 +176,7 @@ async def test_static_file_upper_directory(aiohttp_client) -> None: resp = await client.get("/../../") assert resp.status == 404 await resp.release() + await client.close() async def test_static_file_with_content_type(aiohttp_client, sender) -> None: @@ -141,6 +198,8 @@ async def handler(request): assert resp.headers["Content-Type"] == "image/jpeg" assert resp.headers.get("Content-Encoding") is None resp.close() + await resp.release() + await client.close() async def test_static_file_custom_content_type(aiohttp_client, sender) -> None: @@ -164,6 +223,8 @@ async def handler(request): assert resp.headers["Content-Type"] == "application/pdf" assert resp.headers.get("Content-Encoding") is None resp.close() + await resp.release() + await client.close() async def test_static_file_custom_content_type_compress(aiohttp_client, sender): @@ -185,6 +246,8 @@ async def handler(request): assert resp.headers["Content-Type"] == "application/pdf" assert resp.headers.get("Content-Encoding") == "gzip" resp.close() + await resp.release() + await client.close() async def test_static_file_with_content_encoding(aiohttp_client, sender) -> None: @@ -207,42 +270,39 @@ async def handler(request): assert "gzip" == encoding resp.close() + await resp.release() + await client.close() -async def test_static_file_if_modified_since(aiohttp_client, sender) -> None: - filename = "data.unknown_mime_type" - filepath = pathlib.Path(__file__).parent / filename - - async def handler(request): - return sender(filepath) - app = web.Application() - app.router.add_get("/", handler) - client = await aiohttp_client(app) +async def test_static_file_if_modified_since( + aiohttp_client: Any, + app_with_static_route: web.Application, +) -> None: + client = await aiohttp_client(app_with_static_route) resp = await client.get("/") assert 200 == resp.status lastmod = resp.headers.get("Last-Modified") assert lastmod is not None resp.close() + await resp.release() resp = await client.get("/", headers={"If-Modified-Since": lastmod}) body = await resp.read() assert 304 == resp.status assert resp.headers.get("Content-Length") is None + assert resp.headers.get("Last-Modified") == lastmod assert b"" == body resp.close() + await resp.release() + await client.close() -async def test_static_file_if_modified_since_past_date(aiohttp_client, sender) -> None: - filename = "data.unknown_mime_type" - filepath = pathlib.Path(__file__).parent / filename - - async def handler(request): - return sender(filepath) - - app = web.Application() - app.router.add_get("/", handler) - client = await aiohttp_client(app) +async def test_static_file_if_modified_since_past_date( + aiohttp_client: Any, + app_with_static_route: web.Application, +) -> None: + client = await aiohttp_client(app_with_static_route) lastmod = "Mon, 1 Jan 1990 01:01:01 GMT" @@ -250,17 +310,15 @@ async def handler(request): assert 200 == resp.status resp.close() + await resp.release() + await client.close() -async def test_static_file_if_modified_since_invalid_date(aiohttp_client, sender): - filename = "data.unknown_mime_type" - filepath = pathlib.Path(__file__).parent / filename - - async def handler(request): - return sender(filepath) - app = web.Application() - app.router.add_get("/", handler) - client = await aiohttp_client(app) +async def test_static_file_if_modified_since_invalid_date( + aiohttp_client: Any, + app_with_static_route: web.Application, +) -> None: + client = await aiohttp_client(app_with_static_route) lastmod = "not a valid HTTP-date" @@ -268,17 +326,15 @@ async def handler(request): assert 200 == resp.status resp.close() + await resp.release() + await client.close() -async def test_static_file_if_modified_since_future_date(aiohttp_client, sender): - filename = "data.unknown_mime_type" - filepath = pathlib.Path(__file__).parent / filename - - async def handler(request): - return sender(filepath) - app = web.Application() - app.router.add_get("/", handler) - client = await aiohttp_client(app) +async def test_static_file_if_modified_since_future_date( + aiohttp_client: Any, + app_with_static_route: web.Application, +) -> None: + client = await aiohttp_client(app_with_static_route) lastmod = "Fri, 31 Dec 9999 23:59:59 GMT" @@ -286,9 +342,131 @@ async def handler(request): body = await resp.read() assert 304 == resp.status assert resp.headers.get("Content-Length") is None + assert resp.headers.get("Last-Modified") assert b"" == body resp.close() + await resp.release() + await client.close() + + +@pytest.mark.parametrize("if_unmodified_since", ("", "Fri, 31 Dec 0000 23:59:59 GMT")) +async def test_static_file_if_match( + aiohttp_client: Any, + app_with_static_route: web.Application, + if_unmodified_since: str, +) -> None: + client = await aiohttp_client(app_with_static_route) + + resp = await client.get("/") + assert 200 == resp.status + original_etag = resp.headers.get("ETag") + + assert original_etag is not None + resp.close() + await resp.release() + + headers = {"If-Match": original_etag, "If-Unmodified-Since": if_unmodified_since} + resp = await client.head("/", headers=headers) + body = await resp.read() + assert 200 == resp.status + assert resp.headers.get("ETag") + assert resp.headers.get("Last-Modified") + assert b"" == body + resp.close() + await resp.release() + + await client.close() + + +@pytest.mark.parametrize("if_unmodified_since", ("", "Fri, 31 Dec 0000 23:59:59 GMT")) +@pytest.mark.parametrize( + "etags,expected_status", + [ + (("*",), 200), + (('"example-tag"', 'W/"weak-tag"'), 412), + ], +) +async def test_static_file_if_match_custom_tags( + aiohttp_client: Any, + app_with_static_route: web.Application, + if_unmodified_since: str, + etags: Iterable[str], + expected_status: Iterable[int], +) -> None: + client = await aiohttp_client(app_with_static_route) + + if_match = ", ".join(etags) + headers = {"If-Match": if_match, "If-Unmodified-Since": if_unmodified_since} + resp = await client.head("/", headers=headers) + body = await resp.read() + assert expected_status == resp.status + assert b"" == body + resp.close() + + await resp.release() + await client.close() + + +@pytest.mark.parametrize("if_modified_since", ("", "Fri, 31 Dec 9999 23:59:59 GMT")) +@pytest.mark.parametrize( + "additional_etags", + ( + (), + ('"some-other-strong-etag"', 'W/"weak-tag"', "invalid-tag"), + ), +) +async def test_static_file_if_none_match( + aiohttp_client: Any, + app_with_static_route: web.Application, + if_modified_since: str, + additional_etags: Iterable[str], +) -> None: + client = await aiohttp_client(app_with_static_route) + + resp = await client.get("/") + assert 200 == resp.status + original_etag = resp.headers.get("ETag") + + assert resp.headers.get("Last-Modified") is not None + assert original_etag is not None + resp.close() + await resp.release() + + etag = ",".join((original_etag, *additional_etags)) + + resp = await client.get( + "/", headers={"If-None-Match": etag, "If-Modified-Since": if_modified_since} + ) + body = await resp.read() + assert 304 == resp.status + assert resp.headers.get("Content-Length") is None + assert resp.headers.get("ETag") == original_etag + assert b"" == body + resp.close() + await resp.release() + + await client.close() + + +async def test_static_file_if_none_match_star( + aiohttp_client: Any, + app_with_static_route: web.Application, +) -> None: + client = await aiohttp_client(app_with_static_route) + + resp = await client.head("/", headers={"If-None-Match": "*"}) + body = await resp.read() + assert 304 == resp.status + assert resp.headers.get("Content-Length") is None + assert resp.headers.get("ETag") + assert resp.headers.get("Last-Modified") + assert b"" == body + resp.close() + + await resp.release() + await client.close() + @pytest.mark.skipif(not ssl, reason="ssl not supported") async def test_static_file_ssl( @@ -313,6 +491,9 @@ async def test_static_file_ssl( assert "application/octet-stream" == ct assert resp.headers.get("CONTENT-ENCODING") is None + await resp.release() + await client.close() + async def test_static_file_directory_traversal_attack(aiohttp_client) -> None: dirname = os.path.dirname(__file__) @@ -325,14 +506,19 @@ async def test_static_file_directory_traversal_attack(aiohttp_client) -> None: resp = await client.get("/static/" + relpath) assert 404 == resp.status + await resp.release() url_relpath2 = "/static/dir/../" + relpath resp = await client.get(url_relpath2) assert 404 == resp.status + await resp.release() url_abspath = "/static/" + os.path.abspath(os.path.join(dirname, relpath)) resp = await client.get(url_abspath) assert 403 == resp.status + await resp.release() + + await client.close() def test_static_route_path_existence_check() -> None: @@ -376,9 +562,12 @@ async def test_static_file_huge(aiohttp_client, tmpdir) -> None: cnt += 1 f.close() + await resp.release() + await client.close() -async def test_static_file_range(aiohttp_client, sender) -> None: - filepath = pathlib.Path(__file__).parent.parent / "LICENSE.txt" + +async def test_static_file_range(aiohttp_client: Any, sender: Any) -> None: + filepath = pathlib.Path(__file__).parent / "sample.txt" filesize = filepath.stat().st_size @@ -428,8 +617,14 @@ async def handler(request): responses[1].close() responses[2].close() + await asyncio.gather( + *(resp.release() for resp in responses), + ) + assert content == b"".join(body) + await client.close() + async def test_static_file_range_end_bigger_than_size(aiohttp_client, sender): filepath = pathlib.Path(__file__).parent / "aiohttp.png" @@ -461,6 +656,9 @@ async def handler(request): assert content[54000:] == body + await response.release() + await client.close() + async def test_static_file_range_beyond_eof(aiohttp_client, sender) -> None: filepath = pathlib.Path(__file__).parent / "aiohttp.png" @@ -479,6 +677,9 @@ async def handler(request): "failed 'bytes=1000000-1200000': %s" % response.reason ) + await response.release() + await client.close() + async def test_static_file_range_tail(aiohttp_client, sender) -> None: filepath = pathlib.Path(__file__).parent / "aiohttp.png" @@ -501,6 +702,7 @@ async def handler(request): ), "failed: Content-Range Error" body4 = await resp.read() resp.close() + await resp.release() assert content[-500:] == body4 # Ensure out-of-range tails could be handled @@ -509,6 +711,9 @@ async def handler(request): assert ( resp2.headers["Content-Range"] == "bytes 0-54996/54997" ), "failed: Content-Range Error" + await resp2.release() + + await client.close() async def test_static_file_invalid_range(aiohttp_client, sender) -> None: @@ -525,43 +730,46 @@ async def handler(request): resp = await client.get("/", headers={"Range": "blocks=0-10"}) assert resp.status == 416, "Range must be in bytes" resp.close() + await resp.release() # start > end resp = await client.get("/", headers={"Range": "bytes=100-0"}) assert resp.status == 416, "Range start can't be greater than end" resp.close() + await resp.release() # start > end resp = await client.get("/", headers={"Range": "bytes=10-9"}) assert resp.status == 416, "Range start can't be greater than end" resp.close() + await resp.release() # non-number range resp = await client.get("/", headers={"Range": "bytes=a-f"}) assert resp.status == 416, "Range must be integers" resp.close() + await resp.release() # double dash range resp = await client.get("/", headers={"Range": "bytes=0--10"}) assert resp.status == 416, "double dash in range" resp.close() + await resp.release() # no range resp = await client.get("/", headers={"Range": "bytes=-"}) assert resp.status == 416, "no range given" resp.close() + await resp.release() + await client.close() -async def test_static_file_if_unmodified_since_past_with_range(aiohttp_client, sender): - filename = "data.unknown_mime_type" - filepath = pathlib.Path(__file__).parent / filename - - async def handler(request): - return sender(filepath) - app = web.Application() - app.router.add_get("/", handler) - client = await aiohttp_client(app) +async def test_static_file_if_unmodified_since_past_with_range( + aiohttp_client: Any, + app_with_static_route: web.Application, +) -> None: + client = await aiohttp_client(app_with_static_route) lastmod = "Mon, 1 Jan 1990 01:01:01 GMT" @@ -570,20 +778,16 @@ async def handler(request): ) assert 412 == resp.status resp.close() + await resp.release() + await client.close() -async def test_static_file_if_unmodified_since_future_with_range( - aiohttp_client, sender -): - filename = "data.unknown_mime_type" - filepath = pathlib.Path(__file__).parent / filename - - async def handler(request): - return sender(filepath) - app = web.Application() - app.router.add_get("/", handler) - client = await aiohttp_client(app) +async def test_static_file_if_unmodified_since_future_with_range( + aiohttp_client: Any, + app_with_static_route: web.Application, +) -> None: + client = await aiohttp_client(app_with_static_route) lastmod = "Fri, 31 Dec 9999 23:59:59 GMT" @@ -594,18 +798,16 @@ async def handler(request): assert resp.headers["Content-Range"] == "bytes 2-12/13" assert resp.headers["Content-Length"] == "11" resp.close() + await resp.release() + await client.close() -async def test_static_file_if_range_past_with_range(aiohttp_client, sender): - filename = "data.unknown_mime_type" - filepath = pathlib.Path(__file__).parent / filename - - async def handler(request): - return sender(filepath) - app = web.Application() - app.router.add_get("/", handler) - client = await aiohttp_client(app) +async def test_static_file_if_range_past_with_range( + aiohttp_client: Any, + app_with_static_route: web.Application, +) -> None: + client = await aiohttp_client(app_with_static_route) lastmod = "Mon, 1 Jan 1990 01:01:01 GMT" @@ -613,18 +815,15 @@ async def handler(request): assert 200 == resp.status assert resp.headers["Content-Length"] == "13" resp.close() + await resp.release() + await client.close() -async def test_static_file_if_range_future_with_range(aiohttp_client, sender): - filename = "data.unknown_mime_type" - filepath = pathlib.Path(__file__).parent / filename - - async def handler(request): - return sender(filepath) - - app = web.Application() - app.router.add_get("/", handler) - client = await aiohttp_client(app) +async def test_static_file_if_range_future_with_range( + aiohttp_client: Any, + app_with_static_route: web.Application, +) -> None: + client = await aiohttp_client(app_with_static_route) lastmod = "Fri, 31 Dec 9999 23:59:59 GMT" @@ -634,19 +833,15 @@ async def handler(request): assert resp.headers["Content-Length"] == "11" resp.close() + await resp.release() + await client.close() -async def test_static_file_if_unmodified_since_past_without_range( - aiohttp_client, sender -): - filename = "data.unknown_mime_type" - filepath = pathlib.Path(__file__).parent / filename - - async def handler(request): - return sender(filepath) - app = web.Application() - app.router.add_get("/", handler) - client = await aiohttp_client(app) +async def test_static_file_if_unmodified_since_past_without_range( + aiohttp_client: Any, + app_with_static_route: web.Application, +) -> None: + client = await aiohttp_client(app_with_static_route) lastmod = "Mon, 1 Jan 1990 01:01:01 GMT" @@ -654,19 +849,15 @@ async def handler(request): assert 412 == resp.status resp.close() + await resp.release() + await client.close() -async def test_static_file_if_unmodified_since_future_without_range( - aiohttp_client, sender -): - filename = "data.unknown_mime_type" - filepath = pathlib.Path(__file__).parent / filename - - async def handler(request): - return sender(filepath) - app = web.Application() - app.router.add_get("/", handler) - client = await aiohttp_client(app) +async def test_static_file_if_unmodified_since_future_without_range( + aiohttp_client: Any, + app_with_static_route: web.Application, +) -> None: + client = await aiohttp_client(app_with_static_route) lastmod = "Fri, 31 Dec 9999 23:59:59 GMT" @@ -675,17 +866,15 @@ async def handler(request): assert resp.headers["Content-Length"] == "13" resp.close() + await resp.release() + await client.close() -async def test_static_file_if_range_past_without_range(aiohttp_client, sender): - filename = "data.unknown_mime_type" - filepath = pathlib.Path(__file__).parent / filename - - async def handler(request): - return sender(filepath) - app = web.Application() - app.router.add_get("/", handler) - client = await aiohttp_client(app) +async def test_static_file_if_range_past_without_range( + aiohttp_client: Any, + app_with_static_route: web.Application, +) -> None: + client = await aiohttp_client(app_with_static_route) lastmod = "Mon, 1 Jan 1990 01:01:01 GMT" @@ -694,17 +883,15 @@ async def handler(request): assert resp.headers["Content-Length"] == "13" resp.close() + await resp.release() + await client.close() -async def test_static_file_if_range_future_without_range(aiohttp_client, sender): - filename = "data.unknown_mime_type" - filepath = pathlib.Path(__file__).parent / filename - async def handler(request): - return sender(filepath) - - app = web.Application() - app.router.add_get("/", handler) - client = await aiohttp_client(app) +async def test_static_file_if_range_future_without_range( + aiohttp_client: Any, + app_with_static_route: web.Application, +) -> None: + client = await aiohttp_client(app_with_static_route) lastmod = "Fri, 31 Dec 9999 23:59:59 GMT" @@ -713,17 +900,15 @@ async def handler(request): assert resp.headers["Content-Length"] == "13" resp.close() + await resp.release() + await client.close() -async def test_static_file_if_unmodified_since_invalid_date(aiohttp_client, sender): - filename = "data.unknown_mime_type" - filepath = pathlib.Path(__file__).parent / filename - - async def handler(request): - return sender(filepath) - app = web.Application() - app.router.add_get("/", handler) - client = await aiohttp_client(app) +async def test_static_file_if_unmodified_since_invalid_date( + aiohttp_client: Any, + app_with_static_route: web.Application, +) -> None: + client = await aiohttp_client(app_with_static_route) lastmod = "not a valid HTTP-date" @@ -731,23 +916,24 @@ async def handler(request): assert 200 == resp.status resp.close() + await resp.release() + await client.close() -async def test_static_file_if_range_invalid_date(aiohttp_client, sender): - filename = "data.unknown_mime_type" - filepath = pathlib.Path(__file__).parent / filename - - async def handler(request): - return sender(filepath) - app = web.Application() - app.router.add_get("/", handler) - client = await aiohttp_client(app) +async def test_static_file_if_range_invalid_date( + aiohttp_client: Any, + app_with_static_route: web.Application, +) -> None: + client = await aiohttp_client(app_with_static_route) lastmod = "not a valid HTTP-date" resp = await client.get("/", headers={"If-Range": lastmod}) assert 200 == resp.status resp.close() + await resp.release() + + await client.close() async def test_static_file_compression(aiohttp_client, sender) -> None: @@ -771,6 +957,8 @@ async def handler(request): assert resp.headers.get("Content-Encoding") == "deflate" await resp.release() + await client.close() + async def test_static_file_huge_cancel(aiohttp_client, tmpdir) -> None: filename = "huge_data.unknown_mime_type" @@ -809,6 +997,9 @@ async def handler(request): break assert len(data) < 1024 * 1024 * 20 + await resp.release() + await client.close() + async def test_static_file_huge_error(aiohttp_client, tmpdir) -> None: filename = "huge_data.unknown_mime_type" @@ -835,3 +1026,6 @@ async def handler(request): assert resp.status == 200 # raise an exception on server side resp.close() + + await resp.release() + await client.close() diff --git a/tests/test_web_server.py b/tests/test_web_server.py index b02787b..627f0f9 100644 --- a/tests/test_web_server.py +++ b/tests/test_web_server.py @@ -3,7 +3,7 @@ import pytest -from aiohttp import client, web +from aiohttp import client, helpers, web async def test_simple_server(aiohttp_raw_server, aiohttp_client) -> None: @@ -18,6 +18,28 @@ async def handler(request): assert txt == "/path/to" +@pytest.mark.xfail( + not helpers.NO_EXTENSIONS, + raises=client.ServerDisconnectedError, + reason="The behavior of C-extensions differs from pure-Python: " + "https://github.com/aio-libs/aiohttp/issues/6446", +) +async def test_unsupported_upgrade(aiohttp_raw_server, aiohttp_client) -> None: + # don't fail if a client probes for an unsupported protocol upgrade + # https://github.com/aio-libs/aiohttp/issues/6446#issuecomment-999032039 + async def handler(request: web.Request): + return web.Response(body=await request.read()) + + upgrade_headers = {"Connection": "Upgrade", "Upgrade": "unsupported_proto"} + server = await aiohttp_raw_server(handler) + cli = await aiohttp_client(server) + test_data = b"Test" + resp = await cli.post("/path/to", data=test_data, headers=upgrade_headers) + assert resp.status == 200 + data = await resp.read() + assert data == test_data + + async def test_raw_server_not_http_exception(aiohttp_raw_server, aiohttp_client): exc = RuntimeError("custom runtime error") diff --git a/tests/test_web_urldispatcher.py b/tests/test_web_urldispatcher.py index 0ba2e7c..f24f451 100644 --- a/tests/test_web_urldispatcher.py +++ b/tests/test_web_urldispatcher.py @@ -5,10 +5,12 @@ import shutil import sys import tempfile +from typing import Any from unittest import mock from unittest.mock import MagicMock import pytest +import yarl from aiohttp import abc, web from aiohttp.web_urldispatcher import SystemRoute @@ -18,6 +20,7 @@ def tmp_dir_path(request): """ Give a path for a temporary directory + The directory is destroyed at the end of the test. """ # Temporary directory. @@ -152,6 +155,7 @@ async def test_access_to_the_file_with_spaces( r = await client.get(url) assert r.status == 200 assert (await r.text()) == data + await r.release() async def test_access_non_existing_resource(tmp_dir_path, aiohttp_client) -> None: @@ -192,10 +196,7 @@ async def handler(request): async def test_handler_metadata_persistence() -> None: - """ - Tests accessing metadata of a handler after registering it on the app - router. - """ + """Tests accessing metadata of a handler after registering it on the app router.""" app = web.Application() async def async_handler(request): @@ -515,3 +516,50 @@ async def test_static_absolute_url(aiohttp_client, tmpdir) -> None: client = await aiohttp_client(app) resp = await client.get("/static/" + str(fname)) assert resp.status == 403 + + +async def test_for_issue_5250(aiohttp_client: Any, tmp_path: Any) -> None: + app = web.Application() + app.router.add_static("/foo", tmp_path) + + async def get_foobar(request): + return web.Response(body="success!") + + app.router.add_get("/foobar", get_foobar) + + client = await aiohttp_client(app) + async with await client.get("/foobar") as resp: + assert resp.status == 200 + assert (await resp.text()) == "success!" + + +@pytest.mark.xfail( + raises=AssertionError, + reason="Regression in v3.7: https://github.com/aio-libs/aiohttp/issues/5621", +) +@pytest.mark.parametrize( + ("route_definition", "urlencoded_path", "expected_http_resp_status"), + ( + ("/467,802,24834/hello", "/467%2C802%2C24834/hello", 200), + ("/{user_ids:([0-9]+)(,([0-9]+))*}/hello", "/467%2C802%2C24834/hello", 200), + ("/1%2C3/hello", "/1%2C3/hello", 404), + ), + ids=("urldecoded_route", "urldecoded_route_with_regex", "urlencoded_route"), +) +async def test_decoded_url_match( + aiohttp_client, + route_definition, + urlencoded_path, + expected_http_resp_status, +) -> None: + app = web.Application() + + async def handler(_): + return web.Response() + + app.router.add_get(route_definition, handler) + client = await aiohttp_client(app) + + r = await client.get(yarl.URL(urlencoded_path, encoded=True)) + assert r.status == expected_http_resp_status + await r.release() diff --git a/tests/test_web_websocket.py b/tests/test_web_websocket.py index 0a79113..ee8ae2d 100644 --- a/tests/test_web_websocket.py +++ b/tests/test_web_websocket.py @@ -1,10 +1,11 @@ import asyncio from unittest import mock +import aiosignal import pytest from multidict import CIMultiDict -from aiohttp import WSMessage, WSMsgType, signals +from aiohttp import WSMessage, WSMsgType from aiohttp.streams import EofStream from aiohttp.test_utils import make_mocked_coro, make_mocked_request from aiohttp.web import HTTPBadRequest, WebSocketResponse @@ -16,7 +17,7 @@ def app(loop): ret = mock.Mock() ret.loop = loop ret._debug = False - ret.on_response_prepare = signals.Signal(ret) + ret.on_response_prepare = aiosignal.Signal(ret) ret.on_response_prepare.freeze() return ret diff --git a/tests/test_web_websocket_functional.py b/tests/test_web_websocket_functional.py index e5ea2a5..da855a4 100644 --- a/tests/test_web_websocket_functional.py +++ b/tests/test_web_websocket_functional.py @@ -6,7 +6,7 @@ import aiohttp from aiohttp import web -from aiohttp.http import WSMsgType +from aiohttp.http import WSCloseCode, WSMsgType async def test_websocket_can_prepare(loop, aiohttp_client) -> None: @@ -153,11 +153,11 @@ async def handler(request): msg = await ws.receive() assert msg.type == aiohttp.WSMsgType.CLOSE - assert msg.data == 1000 + assert msg.data == WSCloseCode.OK assert msg.extra == "" assert ws.closed - assert ws.close_code == 1000 + assert ws.close_code == WSCloseCode.OK await closed @@ -188,11 +188,11 @@ async def handler(request): msg = await ws.receive() assert msg.type == aiohttp.WSMsgType.CLOSE - assert msg.data == 1000 + assert msg.data == WSCloseCode.OK assert msg.extra == "" assert ws.closed - assert ws.close_code == 1000 + assert ws.close_code == WSCloseCode.OK await closed @@ -223,7 +223,7 @@ async def handler(request): msg = await ws.receive() assert msg.type == aiohttp.WSMsgType.CLOSE - assert msg.data == 1000 + assert msg.data == WSCloseCode.OK assert msg.extra == "" await ws.close() @@ -244,7 +244,7 @@ async def handler(request): begin = ws._loop.time() assert await ws.close() elapsed = ws._loop.time() - begin - assert ws.close_code == 1006 + assert ws.close_code == WSCloseCode.ABNORMAL_CLOSURE assert isinstance(ws.exception(), asyncio.TimeoutError) aborted.set_result(1) return ws @@ -300,7 +300,7 @@ async def handler(request): ws = await client.ws_connect("/", autoclose=False, protocols=("eggs", "bar")) - await srv_ws.close(code=1007) + await srv_ws.close(code=WSCloseCode.INVALID_TEXT) msg = await ws.receive() assert msg.type == WSMsgType.CLOSE @@ -321,7 +321,7 @@ async def handler(request): msg = await ws.receive() assert msg.type == WSMsgType.CLOSE - assert msg.data == 1000 + assert msg.data == WSCloseCode.OK assert msg.extra == "exit message" closed.set_result(None) return ws @@ -336,7 +336,7 @@ async def handler(request): msg = await ws.receive() assert msg.type == WSMsgType.PONG - await ws.close(code=1000, message="exit message") + await ws.close(code=WSCloseCode.OK, message="exit message") await closed @@ -407,7 +407,7 @@ async def handler(request): msg = await ws.receive() assert msg.type == WSMsgType.CLOSE - assert msg.data == 1000 + assert msg.data == WSCloseCode.OK assert msg.extra == "exit message" closed.set_result(None) return ws @@ -423,7 +423,7 @@ async def handler(request): assert msg.type == WSMsgType.PONG assert msg.data == b"data" - await ws.close(code=1000, message="exit message") + await ws.close(code=WSCloseCode.OK, message="exit message") await closed @@ -511,7 +511,7 @@ async def handler(request): assert not ws.closed await ws.close() assert ws.closed - assert ws.close_code == 1007 + assert ws.close_code == WSCloseCode.INVALID_TEXT msg = await ws.receive() assert msg.type == WSMsgType.CLOSED @@ -525,7 +525,7 @@ async def handler(request): ws = await client.ws_connect("/", autoclose=False, protocols=("eggs", "bar")) - await ws.close(code=1007) + await ws.close(code=WSCloseCode.INVALID_TEXT) msg = await ws.receive() assert msg.type == WSMsgType.CLOSED await closed diff --git a/tests/test_worker.py b/tests/test_worker.py index 64cff82..68c28c8 100644 --- a/tests/test_worker.py +++ b/tests/test_worker.py @@ -212,8 +212,8 @@ async def test__run_ok_parent_changed(worker, loop, aiohttp_unused_port) -> None worker.sockets = [sock] worker.log = mock.Mock() worker.loop = loop + worker.max_requests = 0 worker.cfg.access_log_format = ACCEPTABLE_LOG_FORMAT - worker.cfg.max_requests = 0 worker.cfg.is_ssl = False await worker._run() @@ -233,8 +233,8 @@ async def test__run_exc(worker, loop, aiohttp_unused_port) -> None: worker.sockets = [sock] worker.log = mock.Mock() worker.loop = loop + worker.max_requests = 0 worker.cfg.access_log_format = ACCEPTABLE_LOG_FORMAT - worker.cfg.max_requests = 0 worker.cfg.is_ssl = False def raiser(): @@ -252,7 +252,7 @@ def test__create_ssl_context_without_certs_and_ciphers( worker, tls_certificate_pem_path, ) -> None: - worker.cfg.ssl_version = ssl.PROTOCOL_SSLv23 + worker.cfg.ssl_version = ssl.PROTOCOL_TLS_CLIENT worker.cfg.cert_reqs = ssl.CERT_OPTIONAL worker.cfg.certfile = tls_certificate_pem_path worker.cfg.keyfile = tls_certificate_pem_path @@ -266,7 +266,7 @@ def test__create_ssl_context_with_ciphers( worker, tls_certificate_pem_path, ) -> None: - worker.cfg.ssl_version = ssl.PROTOCOL_SSLv23 + worker.cfg.ssl_version = ssl.PROTOCOL_TLS_CLIENT worker.cfg.cert_reqs = ssl.CERT_OPTIONAL worker.cfg.certfile = tls_certificate_pem_path worker.cfg.keyfile = tls_certificate_pem_path @@ -281,7 +281,7 @@ def test__create_ssl_context_with_ca_certs( tls_ca_certificate_pem_path, tls_certificate_pem_path, ) -> None: - worker.cfg.ssl_version = ssl.PROTOCOL_SSLv23 + worker.cfg.ssl_version = ssl.PROTOCOL_TLS_CLIENT worker.cfg.cert_reqs = ssl.CERT_OPTIONAL worker.cfg.certfile = tls_certificate_pem_path worker.cfg.keyfile = tls_certificate_pem_path diff --git a/vendor/README.rst b/vendor/README.rst new file mode 100644 index 0000000..6156f37 --- /dev/null +++ b/vendor/README.rst @@ -0,0 +1,23 @@ +LLHTTP +------ + +When building aiohttp from source, there is a pure Python parser used by default. +For better performance, you may want to build the higher performance C parser. + +To build this ``llhttp`` parser, first get/update the submodules (to update to a +newer release, add ``--remote``):: + + git submodule update --init --recursive + +Then build ``llhttp``:: + + cd vendor/llhttp/ + npm install + make + +Then build our parser:: + + cd - + make cythonize + +Then you can build or install it with ``python -m build`` or ``pip install -e .`` diff --git a/vendor/http-parser/.gitignore b/vendor/http-parser/.gitignore deleted file mode 100644 index c122e76..0000000 --- a/vendor/http-parser/.gitignore +++ /dev/null @@ -1,30 +0,0 @@ -/out/ -core -tags -*.o -test -test_g -test_fast -bench -url_parser -parsertrace -parsertrace_g -*.mk -*.Makefile -*.so.* -*.exe.* -*.exe -*.a - - -# Visual Studio uglies -*.suo -*.sln -*.vcxproj -*.vcxproj.filters -*.vcxproj.user -*.opensdf -*.ncrunchsolution* -*.sdf -*.vsp -*.psess diff --git a/vendor/http-parser/.mailmap b/vendor/http-parser/.mailmap deleted file mode 100644 index 278d141..0000000 --- a/vendor/http-parser/.mailmap +++ /dev/null @@ -1,8 +0,0 @@ -# update AUTHORS with: -# git log --all --reverse --format='%aN <%aE>' | perl -ne 'BEGIN{print "# Authors ordered by first contribution.\n"} print unless $h{$_}; $h{$_} = 1' > AUTHORS -Ryan Dahl -Salman Haq -Simon Zimmermann -Thomas LE ROUX LE ROUX Thomas -Thomas LE ROUX Thomas LE ROUX -Fedor Indutny diff --git a/vendor/http-parser/.travis.yml b/vendor/http-parser/.travis.yml deleted file mode 100644 index 4b038e6..0000000 --- a/vendor/http-parser/.travis.yml +++ /dev/null @@ -1,13 +0,0 @@ -language: c - -compiler: - - clang - - gcc - -script: - - "make" - -notifications: - email: false - irc: - - "irc.freenode.net#node-ci" diff --git a/vendor/http-parser/AUTHORS b/vendor/http-parser/AUTHORS deleted file mode 100644 index 5323b68..0000000 --- a/vendor/http-parser/AUTHORS +++ /dev/null @@ -1,68 +0,0 @@ -# Authors ordered by first contribution. -Ryan Dahl -Jeremy Hinegardner -Sergey Shepelev -Joe Damato -tomika -Phoenix Sol -Cliff Frey -Ewen Cheslack-Postava -Santiago Gala -Tim Becker -Jeff Terrace -Ben Noordhuis -Nathan Rajlich -Mark Nottingham -Aman Gupta -Tim Becker -Sean Cunningham -Peter Griess -Salman Haq -Cliff Frey -Jon Kolb -Fouad Mardini -Paul Querna -Felix Geisendörfer -koichik -Andre Caron -Ivo Raisr -James McLaughlin -David Gwynne -Thomas LE ROUX -Randy Rizun -Andre Louis Caron -Simon Zimmermann -Erik Dubbelboer -Martell Malone -Bertrand Paquet -BogDan Vatra -Peter Faiman -Corey Richardson -Tóth Tamás -Cam Swords -Chris Dickinson -Uli Köhler -Charlie Somerville -Patrik Stutz -Fedor Indutny -runner -Alexis Campailla -David Wragg -Vinnie Falco -Alex Butum -Rex Feng -Alex Kocharin -Mark Koopman -Helge Heß -Alexis La Goutte -George Miroshnykov -Maciej Małecki -Marc O'Morain -Jeff Pinner -Timothy J Fontaine -Akagi201 -Romain Giraud -Jay Satiro -Arne Steen -Kjell Schubert -Olivier Mengué diff --git a/vendor/http-parser/LICENSE-MIT b/vendor/http-parser/LICENSE-MIT deleted file mode 100644 index 1ec0ab4..0000000 --- a/vendor/http-parser/LICENSE-MIT +++ /dev/null @@ -1,19 +0,0 @@ -Copyright Joyent, Inc. and other Node contributors. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to -deal in the Software without restriction, including without limitation the -rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -sell copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -IN THE SOFTWARE. diff --git a/vendor/http-parser/Makefile b/vendor/http-parser/Makefile deleted file mode 100644 index 5d21221..0000000 --- a/vendor/http-parser/Makefile +++ /dev/null @@ -1,160 +0,0 @@ -# Copyright Joyent, Inc. and other Node contributors. All rights reserved. -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -PLATFORM ?= $(shell sh -c 'uname -s | tr "[A-Z]" "[a-z]"') -HELPER ?= -BINEXT ?= -SOLIBNAME = libhttp_parser -SOMAJOR = 2 -SOMINOR = 9 -SOREV = 4 -ifeq (darwin,$(PLATFORM)) -SOEXT ?= dylib -SONAME ?= $(SOLIBNAME).$(SOMAJOR).$(SOMINOR).$(SOEXT) -LIBNAME ?= $(SOLIBNAME).$(SOMAJOR).$(SOMINOR).$(SOREV).$(SOEXT) -else ifeq (wine,$(PLATFORM)) -CC = winegcc -BINEXT = .exe.so -HELPER = wine -else -SOEXT ?= so -SONAME ?= $(SOLIBNAME).$(SOEXT).$(SOMAJOR).$(SOMINOR) -LIBNAME ?= $(SOLIBNAME).$(SOEXT).$(SOMAJOR).$(SOMINOR).$(SOREV) -endif - -CC?=gcc -AR?=ar - -CPPFLAGS ?= -LDFLAGS ?= - -CPPFLAGS += -I. -CPPFLAGS_DEBUG = $(CPPFLAGS) -DHTTP_PARSER_STRICT=1 -CPPFLAGS_DEBUG += $(CPPFLAGS_DEBUG_EXTRA) -CPPFLAGS_FAST = $(CPPFLAGS) -DHTTP_PARSER_STRICT=0 -CPPFLAGS_FAST += $(CPPFLAGS_FAST_EXTRA) -CPPFLAGS_BENCH = $(CPPFLAGS_FAST) - -CFLAGS += -Wall -Wextra -Werror -CFLAGS_DEBUG = $(CFLAGS) -O0 -g $(CFLAGS_DEBUG_EXTRA) -CFLAGS_FAST = $(CFLAGS) -O3 $(CFLAGS_FAST_EXTRA) -CFLAGS_BENCH = $(CFLAGS_FAST) -Wno-unused-parameter -CFLAGS_LIB = $(CFLAGS_FAST) -fPIC - -LDFLAGS_LIB = $(LDFLAGS) -shared - -INSTALL ?= install -PREFIX ?= /usr/local -LIBDIR = $(PREFIX)/lib -INCLUDEDIR = $(PREFIX)/include - -ifeq (darwin,$(PLATFORM)) -LDFLAGS_LIB += -Wl,-install_name,$(LIBDIR)/$(SONAME) -else -# TODO(bnoordhuis) The native SunOS linker expects -h rather than -soname... -LDFLAGS_LIB += -Wl,-soname=$(SONAME) -endif - -test: test_g test_fast - $(HELPER) ./test_g$(BINEXT) - $(HELPER) ./test_fast$(BINEXT) - -test_g: http_parser_g.o test_g.o - $(CC) $(CFLAGS_DEBUG) $(LDFLAGS) http_parser_g.o test_g.o -o $@ - -test_g.o: test.c http_parser.h Makefile - $(CC) $(CPPFLAGS_DEBUG) $(CFLAGS_DEBUG) -c test.c -o $@ - -http_parser_g.o: http_parser.c http_parser.h Makefile - $(CC) $(CPPFLAGS_DEBUG) $(CFLAGS_DEBUG) -c http_parser.c -o $@ - -test_fast: http_parser.o test.o http_parser.h - $(CC) $(CFLAGS_FAST) $(LDFLAGS) http_parser.o test.o -o $@ - -test.o: test.c http_parser.h Makefile - $(CC) $(CPPFLAGS_FAST) $(CFLAGS_FAST) -c test.c -o $@ - -bench: http_parser.o bench.o - $(CC) $(CFLAGS_BENCH) $(LDFLAGS) http_parser.o bench.o -o $@ - -bench.o: bench.c http_parser.h Makefile - $(CC) $(CPPFLAGS_BENCH) $(CFLAGS_BENCH) -c bench.c -o $@ - -http_parser.o: http_parser.c http_parser.h Makefile - $(CC) $(CPPFLAGS_FAST) $(CFLAGS_FAST) -c http_parser.c - -test-run-timed: test_fast - while(true) do time $(HELPER) ./test_fast$(BINEXT) > /dev/null; done - -test-valgrind: test_g - valgrind ./test_g - -libhttp_parser.o: http_parser.c http_parser.h Makefile - $(CC) $(CPPFLAGS_FAST) $(CFLAGS_LIB) -c http_parser.c -o libhttp_parser.o - -library: libhttp_parser.o - $(CC) $(LDFLAGS_LIB) -o $(LIBNAME) $< - -package: http_parser.o - $(AR) rcs libhttp_parser.a http_parser.o - -url_parser: http_parser.o contrib/url_parser.c - $(CC) $(CPPFLAGS_FAST) $(CFLAGS_FAST) $^ -o $@ - -url_parser_g: http_parser_g.o contrib/url_parser.c - $(CC) $(CPPFLAGS_DEBUG) $(CFLAGS_DEBUG) $^ -o $@ - -parsertrace: http_parser.o contrib/parsertrace.c - $(CC) $(CPPFLAGS_FAST) $(CFLAGS_FAST) $^ -o parsertrace$(BINEXT) - -parsertrace_g: http_parser_g.o contrib/parsertrace.c - $(CC) $(CPPFLAGS_DEBUG) $(CFLAGS_DEBUG) $^ -o parsertrace_g$(BINEXT) - -tags: http_parser.c http_parser.h test.c - ctags $^ - -install: library - $(INSTALL) -D http_parser.h $(DESTDIR)$(INCLUDEDIR)/http_parser.h - $(INSTALL) -D $(LIBNAME) $(DESTDIR)$(LIBDIR)/$(LIBNAME) - ln -sf $(LIBNAME) $(DESTDIR)$(LIBDIR)/$(SONAME) - ln -sf $(LIBNAME) $(DESTDIR)$(LIBDIR)/$(SOLIBNAME).$(SOEXT) - -install-strip: library - $(INSTALL) -D http_parser.h $(DESTDIR)$(INCLUDEDIR)/http_parser.h - $(INSTALL) -D -s $(LIBNAME) $(DESTDIR)$(LIBDIR)/$(LIBNAME) - ln -sf $(LIBNAME) $(DESTDIR)$(LIBDIR)/$(SONAME) - ln -sf $(LIBNAME) $(DESTDIR)$(LIBDIR)/$(SOLIBNAME).$(SOEXT) - -uninstall: - rm $(DESTDIR)$(INCLUDEDIR)/http_parser.h - rm $(DESTDIR)$(LIBDIR)/$(SOLIBNAME).$(SOEXT) - rm $(DESTDIR)$(LIBDIR)/$(SONAME) - rm $(DESTDIR)$(LIBDIR)/$(LIBNAME) - -clean: - rm -f *.o *.a tags test test_fast test_g \ - http_parser.tar libhttp_parser.so.* \ - url_parser url_parser_g parsertrace parsertrace_g \ - *.exe *.exe.so - -contrib/url_parser.c: http_parser.h -contrib/parsertrace.c: http_parser.h - -.PHONY: clean package test-run test-run-timed test-valgrind install install-strip uninstall diff --git a/vendor/http-parser/README.md b/vendor/http-parser/README.md deleted file mode 100644 index b265d71..0000000 --- a/vendor/http-parser/README.md +++ /dev/null @@ -1,246 +0,0 @@ -HTTP Parser -=========== - -[![Build Status](https://api.travis-ci.org/nodejs/http-parser.svg?branch=master)](https://travis-ci.org/nodejs/http-parser) - -This is a parser for HTTP messages written in C. It parses both requests and -responses. The parser is designed to be used in performance HTTP -applications. It does not make any syscalls nor allocations, it does not -buffer data, it can be interrupted at anytime. Depending on your -architecture, it only requires about 40 bytes of data per message -stream (in a web server that is per connection). - -Features: - - * No dependencies - * Handles persistent streams (keep-alive). - * Decodes chunked encoding. - * Upgrade support - * Defends against buffer overflow attacks. - -The parser extracts the following information from HTTP messages: - - * Header fields and values - * Content-Length - * Request method - * Response status code - * Transfer-Encoding - * HTTP version - * Request URL - * Message body - - -Usage ------ - -One `http_parser` object is used per TCP connection. Initialize the struct -using `http_parser_init()` and set the callbacks. That might look something -like this for a request parser: -```c -http_parser_settings settings; -settings.on_url = my_url_callback; -settings.on_header_field = my_header_field_callback; -/* ... */ - -http_parser *parser = malloc(sizeof(http_parser)); -http_parser_init(parser, HTTP_REQUEST); -parser->data = my_socket; -``` - -When data is received on the socket execute the parser and check for errors. - -```c -size_t len = 80*1024, nparsed; -char buf[len]; -ssize_t recved; - -recved = recv(fd, buf, len, 0); - -if (recved < 0) { - /* Handle error. */ -} - -/* Start up / continue the parser. - * Note we pass recved==0 to signal that EOF has been received. - */ -nparsed = http_parser_execute(parser, &settings, buf, recved); - -if (parser->upgrade) { - /* handle new protocol */ -} else if (nparsed != recved) { - /* Handle error. Usually just close the connection. */ -} -``` - -`http_parser` needs to know where the end of the stream is. For example, sometimes -servers send responses without Content-Length and expect the client to -consume input (for the body) until EOF. To tell `http_parser` about EOF, give -`0` as the fourth parameter to `http_parser_execute()`. Callbacks and errors -can still be encountered during an EOF, so one must still be prepared -to receive them. - -Scalar valued message information such as `status_code`, `method`, and the -HTTP version are stored in the parser structure. This data is only -temporally stored in `http_parser` and gets reset on each new message. If -this information is needed later, copy it out of the structure during the -`headers_complete` callback. - -The parser decodes the transfer-encoding for both requests and responses -transparently. That is, a chunked encoding is decoded before being sent to -the on_body callback. - - -The Special Problem of Upgrade ------------------------------- - -`http_parser` supports upgrading the connection to a different protocol. An -increasingly common example of this is the WebSocket protocol which sends -a request like - - GET /demo HTTP/1.1 - Upgrade: WebSocket - Connection: Upgrade - Host: example.com - Origin: http://example.com - WebSocket-Protocol: sample - -followed by non-HTTP data. - -(See [RFC6455](https://tools.ietf.org/html/rfc6455) for more information the -WebSocket protocol.) - -To support this, the parser will treat this as a normal HTTP message without a -body, issuing both on_headers_complete and on_message_complete callbacks. However -http_parser_execute() will stop parsing at the end of the headers and return. - -The user is expected to check if `parser->upgrade` has been set to 1 after -`http_parser_execute()` returns. Non-HTTP data begins at the buffer supplied -offset by the return value of `http_parser_execute()`. - - -Callbacks ---------- - -During the `http_parser_execute()` call, the callbacks set in -`http_parser_settings` will be executed. The parser maintains state and -never looks behind, so buffering the data is not necessary. If you need to -save certain data for later usage, you can do that from the callbacks. - -There are two types of callbacks: - -* notification `typedef int (*http_cb) (http_parser*);` - Callbacks: on_message_begin, on_headers_complete, on_message_complete. -* data `typedef int (*http_data_cb) (http_parser*, const char *at, size_t length);` - Callbacks: (requests only) on_url, - (common) on_header_field, on_header_value, on_body; - -Callbacks must return 0 on success. Returning a non-zero value indicates -error to the parser, making it exit immediately. - -For cases where it is necessary to pass local information to/from a callback, -the `http_parser` object's `data` field can be used. -An example of such a case is when using threads to handle a socket connection, -parse a request, and then give a response over that socket. By instantiation -of a thread-local struct containing relevant data (e.g. accepted socket, -allocated memory for callbacks to write into, etc), a parser's callbacks are -able to communicate data between the scope of the thread and the scope of the -callback in a threadsafe manner. This allows `http_parser` to be used in -multi-threaded contexts. - -Example: -```c - typedef struct { - socket_t sock; - void* buffer; - int buf_len; - } custom_data_t; - - -int my_url_callback(http_parser* parser, const char *at, size_t length) { - /* access to thread local custom_data_t struct. - Use this access save parsed data for later use into thread local - buffer, or communicate over socket - */ - parser->data; - ... - return 0; -} - -... - -void http_parser_thread(socket_t sock) { - int nparsed = 0; - /* allocate memory for user data */ - custom_data_t *my_data = malloc(sizeof(custom_data_t)); - - /* some information for use by callbacks. - * achieves thread -> callback information flow */ - my_data->sock = sock; - - /* instantiate a thread-local parser */ - http_parser *parser = malloc(sizeof(http_parser)); - http_parser_init(parser, HTTP_REQUEST); /* initialise parser */ - /* this custom data reference is accessible through the reference to the - parser supplied to callback functions */ - parser->data = my_data; - - http_parser_settings settings; /* set up callbacks */ - settings.on_url = my_url_callback; - - /* execute parser */ - nparsed = http_parser_execute(parser, &settings, buf, recved); - - ... - /* parsed information copied from callback. - can now perform action on data copied into thread-local memory from callbacks. - achieves callback -> thread information flow */ - my_data->buffer; - ... -} - -``` - -In case you parse HTTP message in chunks (i.e. `read()` request line -from socket, parse, read half headers, parse, etc) your data callbacks -may be called more than once. `http_parser` guarantees that data pointer is only -valid for the lifetime of callback. You can also `read()` into a heap allocated -buffer to avoid copying memory around if this fits your application. - -Reading headers may be a tricky task if you read/parse headers partially. -Basically, you need to remember whether last header callback was field or value -and apply the following logic: - - (on_header_field and on_header_value shortened to on_h_*) - ------------------------ ------------ -------------------------------------------- - | State (prev. callback) | Callback | Description/action | - ------------------------ ------------ -------------------------------------------- - | nothing (first call) | on_h_field | Allocate new buffer and copy callback data | - | | | into it | - ------------------------ ------------ -------------------------------------------- - | value | on_h_field | New header started. | - | | | Copy current name,value buffers to headers | - | | | list and allocate new buffer for new name | - ------------------------ ------------ -------------------------------------------- - | field | on_h_field | Previous name continues. Reallocate name | - | | | buffer and append callback data to it | - ------------------------ ------------ -------------------------------------------- - | field | on_h_value | Value for current header started. Allocate | - | | | new buffer and copy callback data to it | - ------------------------ ------------ -------------------------------------------- - | value | on_h_value | Value continues. Reallocate value buffer | - | | | and append callback data to it | - ------------------------ ------------ -------------------------------------------- - - -Parsing URLs ------------- - -A simplistic zero-copy URL parser is provided as `http_parser_parse_url()`. -Users of this library may wish to use it to parse URLs constructed from -consecutive `on_url` callbacks. - -See examples of reading in headers: - -* [partial example](http://gist.github.com/155877) in C -* [from http-parser tests](http://github.com/joyent/http-parser/blob/37a0ff8/test.c#L403) in C -* [from Node library](http://github.com/joyent/node/blob/842eaf4/src/http.js#L284) in Javascript diff --git a/vendor/http-parser/bench.c b/vendor/http-parser/bench.c deleted file mode 100644 index 678f555..0000000 --- a/vendor/http-parser/bench.c +++ /dev/null @@ -1,128 +0,0 @@ -/* Copyright Fedor Indutny. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ -#include "http_parser.h" -#include -#include -#include -#include -#include - -/* 8 gb */ -static const int64_t kBytes = 8LL << 30; - -static const char data[] = - "POST /joyent/http-parser HTTP/1.1\r\n" - "Host: github.com\r\n" - "DNT: 1\r\n" - "Accept-Encoding: gzip, deflate, sdch\r\n" - "Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4\r\n" - "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) " - "AppleWebKit/537.36 (KHTML, like Gecko) " - "Chrome/39.0.2171.65 Safari/537.36\r\n" - "Accept: text/html,application/xhtml+xml,application/xml;q=0.9," - "image/webp,*/*;q=0.8\r\n" - "Referer: https://github.com/joyent/http-parser\r\n" - "Connection: keep-alive\r\n" - "Transfer-Encoding: chunked\r\n" - "Cache-Control: max-age=0\r\n\r\nb\r\nhello world\r\n0\r\n"; -static const size_t data_len = sizeof(data) - 1; - -static int on_info(http_parser* p) { - return 0; -} - - -static int on_data(http_parser* p, const char *at, size_t length) { - return 0; -} - -static http_parser_settings settings = { - .on_message_begin = on_info, - .on_headers_complete = on_info, - .on_message_complete = on_info, - .on_header_field = on_data, - .on_header_value = on_data, - .on_url = on_data, - .on_status = on_data, - .on_body = on_data -}; - -int bench(int iter_count, int silent) { - struct http_parser parser; - int i; - int err; - struct timeval start; - struct timeval end; - - if (!silent) { - err = gettimeofday(&start, NULL); - assert(err == 0); - } - - fprintf(stderr, "req_len=%d\n", (int) data_len); - for (i = 0; i < iter_count; i++) { - size_t parsed; - http_parser_init(&parser, HTTP_REQUEST); - - parsed = http_parser_execute(&parser, &settings, data, data_len); - assert(parsed == data_len); - } - - if (!silent) { - double elapsed; - double bw; - double total; - - err = gettimeofday(&end, NULL); - assert(err == 0); - - fprintf(stdout, "Benchmark result:\n"); - - elapsed = (double) (end.tv_sec - start.tv_sec) + - (end.tv_usec - start.tv_usec) * 1e-6f; - - total = (double) iter_count * data_len; - bw = (double) total / elapsed; - - fprintf(stdout, "%.2f mb | %.2f mb/s | %.2f req/sec | %.2f s\n", - (double) total / (1024 * 1024), - bw / (1024 * 1024), - (double) iter_count / elapsed, - elapsed); - - fflush(stdout); - } - - return 0; -} - -int main(int argc, char** argv) { - int64_t iterations; - - iterations = kBytes / (int64_t) data_len; - if (argc == 2 && strcmp(argv[1], "infinite") == 0) { - for (;;) - bench(iterations, 1); - return 0; - } else { - return bench(iterations, 0); - } -} diff --git a/vendor/http-parser/contrib/parsertrace.c b/vendor/http-parser/contrib/parsertrace.c deleted file mode 100644 index 3daa7f4..0000000 --- a/vendor/http-parser/contrib/parsertrace.c +++ /dev/null @@ -1,157 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -/* Dump what the parser finds to stdout as it happen */ - -#include "http_parser.h" -#include -#include -#include - -int on_message_begin(http_parser* _) { - (void)_; - printf("\n***MESSAGE BEGIN***\n\n"); - return 0; -} - -int on_headers_complete(http_parser* _) { - (void)_; - printf("\n***HEADERS COMPLETE***\n\n"); - return 0; -} - -int on_message_complete(http_parser* _) { - (void)_; - printf("\n***MESSAGE COMPLETE***\n\n"); - return 0; -} - -int on_url(http_parser* _, const char* at, size_t length) { - (void)_; - printf("Url: %.*s\n", (int)length, at); - return 0; -} - -int on_header_field(http_parser* _, const char* at, size_t length) { - (void)_; - printf("Header field: %.*s\n", (int)length, at); - return 0; -} - -int on_header_value(http_parser* _, const char* at, size_t length) { - (void)_; - printf("Header value: %.*s\n", (int)length, at); - return 0; -} - -int on_body(http_parser* _, const char* at, size_t length) { - (void)_; - printf("Body: %.*s\n", (int)length, at); - return 0; -} - -void usage(const char* name) { - fprintf(stderr, - "Usage: %s $type $filename\n" - " type: -x, where x is one of {r,b,q}\n" - " parses file as a Response, reQuest, or Both\n", - name); - exit(EXIT_FAILURE); -} - -int main(int argc, char* argv[]) { - enum http_parser_type file_type; - - if (argc != 3) { - usage(argv[0]); - } - - char* type = argv[1]; - if (type[0] != '-') { - usage(argv[0]); - } - - switch (type[1]) { - /* in the case of "-", type[1] will be NUL */ - case 'r': - file_type = HTTP_RESPONSE; - break; - case 'q': - file_type = HTTP_REQUEST; - break; - case 'b': - file_type = HTTP_BOTH; - break; - default: - usage(argv[0]); - } - - char* filename = argv[2]; - FILE* file = fopen(filename, "r"); - if (file == NULL) { - perror("fopen"); - goto fail; - } - - fseek(file, 0, SEEK_END); - long file_length = ftell(file); - if (file_length == -1) { - perror("ftell"); - goto fail; - } - fseek(file, 0, SEEK_SET); - - char* data = malloc(file_length); - if (fread(data, 1, file_length, file) != (size_t)file_length) { - fprintf(stderr, "couldn't read entire file\n"); - free(data); - goto fail; - } - - http_parser_settings settings; - memset(&settings, 0, sizeof(settings)); - settings.on_message_begin = on_message_begin; - settings.on_url = on_url; - settings.on_header_field = on_header_field; - settings.on_header_value = on_header_value; - settings.on_headers_complete = on_headers_complete; - settings.on_body = on_body; - settings.on_message_complete = on_message_complete; - - http_parser parser; - http_parser_init(&parser, file_type); - size_t nparsed = http_parser_execute(&parser, &settings, data, file_length); - free(data); - - if (nparsed != (size_t)file_length) { - fprintf(stderr, - "Error: %s (%s)\n", - http_errno_description(HTTP_PARSER_ERRNO(&parser)), - http_errno_name(HTTP_PARSER_ERRNO(&parser))); - goto fail; - } - - return EXIT_SUCCESS; - -fail: - fclose(file); - return EXIT_FAILURE; -} diff --git a/vendor/http-parser/contrib/url_parser.c b/vendor/http-parser/contrib/url_parser.c deleted file mode 100644 index f235bed..0000000 --- a/vendor/http-parser/contrib/url_parser.c +++ /dev/null @@ -1,47 +0,0 @@ -#include "http_parser.h" -#include -#include - -void -dump_url (const char *url, const struct http_parser_url *u) -{ - unsigned int i; - - printf("\tfield_set: 0x%x, port: %u\n", u->field_set, u->port); - for (i = 0; i < UF_MAX; i++) { - if ((u->field_set & (1 << i)) == 0) { - printf("\tfield_data[%u]: unset\n", i); - continue; - } - - printf("\tfield_data[%u]: off: %u, len: %u, part: %.*s\n", - i, - u->field_data[i].off, - u->field_data[i].len, - u->field_data[i].len, - url + u->field_data[i].off); - } -} - -int main(int argc, char ** argv) { - struct http_parser_url u; - int len, connect, result; - - if (argc != 3) { - printf("Syntax : %s connect|get url\n", argv[0]); - return 1; - } - len = strlen(argv[2]); - connect = strcmp("connect", argv[1]) == 0 ? 1 : 0; - printf("Parsing %s, connect %d\n", argv[2], connect); - - http_parser_url_init(&u); - result = http_parser_parse_url(argv[2], len, connect, &u); - if (result != 0) { - printf("Parse error : %d\n", result); - return result; - } - printf("Parse ok, result : \n"); - dump_url(argv[2], &u); - return 0; -} diff --git a/vendor/http-parser/http_parser.c b/vendor/http-parser/http_parser.c deleted file mode 100644 index 95ff42f..0000000 --- a/vendor/http-parser/http_parser.c +++ /dev/null @@ -1,2568 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ -#include "http_parser.h" -#include -#include -#include -#include -#include - -static uint32_t max_header_size = HTTP_MAX_HEADER_SIZE; - -#ifndef ULLONG_MAX -# define ULLONG_MAX ((uint64_t) -1) /* 2^64-1 */ -#endif - -#ifndef MIN -# define MIN(a,b) ((a) < (b) ? (a) : (b)) -#endif - -#ifndef ARRAY_SIZE -# define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) -#endif - -#ifndef BIT_AT -# define BIT_AT(a, i) \ - (!!((unsigned int) (a)[(unsigned int) (i) >> 3] & \ - (1 << ((unsigned int) (i) & 7)))) -#endif - -#ifndef ELEM_AT -# define ELEM_AT(a, i, v) ((unsigned int) (i) < ARRAY_SIZE(a) ? (a)[(i)] : (v)) -#endif - -#define SET_ERRNO(e) \ -do { \ - parser->nread = nread; \ - parser->http_errno = (e); \ -} while(0) - -#define CURRENT_STATE() p_state -#define UPDATE_STATE(V) p_state = (enum state) (V); -#define RETURN(V) \ -do { \ - parser->nread = nread; \ - parser->state = CURRENT_STATE(); \ - return (V); \ -} while (0); -#define REEXECUTE() \ - goto reexecute; \ - - -#ifdef __GNUC__ -# define LIKELY(X) __builtin_expect(!!(X), 1) -# define UNLIKELY(X) __builtin_expect(!!(X), 0) -#else -# define LIKELY(X) (X) -# define UNLIKELY(X) (X) -#endif - - -/* Run the notify callback FOR, returning ER if it fails */ -#define CALLBACK_NOTIFY_(FOR, ER) \ -do { \ - assert(HTTP_PARSER_ERRNO(parser) == HPE_OK); \ - \ - if (LIKELY(settings->on_##FOR)) { \ - parser->state = CURRENT_STATE(); \ - if (UNLIKELY(0 != settings->on_##FOR(parser))) { \ - SET_ERRNO(HPE_CB_##FOR); \ - } \ - UPDATE_STATE(parser->state); \ - \ - /* We either errored above or got paused; get out */ \ - if (UNLIKELY(HTTP_PARSER_ERRNO(parser) != HPE_OK)) { \ - return (ER); \ - } \ - } \ -} while (0) - -/* Run the notify callback FOR and consume the current byte */ -#define CALLBACK_NOTIFY(FOR) CALLBACK_NOTIFY_(FOR, p - data + 1) - -/* Run the notify callback FOR and don't consume the current byte */ -#define CALLBACK_NOTIFY_NOADVANCE(FOR) CALLBACK_NOTIFY_(FOR, p - data) - -/* Run data callback FOR with LEN bytes, returning ER if it fails */ -#define CALLBACK_DATA_(FOR, LEN, ER) \ -do { \ - assert(HTTP_PARSER_ERRNO(parser) == HPE_OK); \ - \ - if (FOR##_mark) { \ - if (LIKELY(settings->on_##FOR)) { \ - parser->state = CURRENT_STATE(); \ - if (UNLIKELY(0 != \ - settings->on_##FOR(parser, FOR##_mark, (LEN)))) { \ - SET_ERRNO(HPE_CB_##FOR); \ - } \ - UPDATE_STATE(parser->state); \ - \ - /* We either errored above or got paused; get out */ \ - if (UNLIKELY(HTTP_PARSER_ERRNO(parser) != HPE_OK)) { \ - return (ER); \ - } \ - } \ - FOR##_mark = NULL; \ - } \ -} while (0) - -/* Run the data callback FOR and consume the current byte */ -#define CALLBACK_DATA(FOR) \ - CALLBACK_DATA_(FOR, p - FOR##_mark, p - data + 1) - -/* Run the data callback FOR and don't consume the current byte */ -#define CALLBACK_DATA_NOADVANCE(FOR) \ - CALLBACK_DATA_(FOR, p - FOR##_mark, p - data) - -/* Set the mark FOR; non-destructive if mark is already set */ -#define MARK(FOR) \ -do { \ - if (!FOR##_mark) { \ - FOR##_mark = p; \ - } \ -} while (0) - -/* Don't allow the total size of the HTTP headers (including the status - * line) to exceed max_header_size. This check is here to protect - * embedders against denial-of-service attacks where the attacker feeds - * us a never-ending header that the embedder keeps buffering. - * - * This check is arguably the responsibility of embedders but we're doing - * it on the embedder's behalf because most won't bother and this way we - * make the web a little safer. max_header_size is still far bigger - * than any reasonable request or response so this should never affect - * day-to-day operation. - */ -#define COUNT_HEADER_SIZE(V) \ -do { \ - nread += (uint32_t)(V); \ - if (UNLIKELY(nread > max_header_size)) { \ - SET_ERRNO(HPE_HEADER_OVERFLOW); \ - goto error; \ - } \ -} while (0) - - -#define PROXY_CONNECTION "proxy-connection" -#define CONNECTION "connection" -#define CONTENT_LENGTH "content-length" -#define TRANSFER_ENCODING "transfer-encoding" -#define UPGRADE "upgrade" -#define CHUNKED "chunked" -#define KEEP_ALIVE "keep-alive" -#define CLOSE "close" - - -static const char *method_strings[] = - { -#define XX(num, name, string) #string, - HTTP_METHOD_MAP(XX) -#undef XX - }; - - -/* Tokens as defined by rfc 2616. Also lowercases them. - * token = 1* - * separators = "(" | ")" | "<" | ">" | "@" - * | "," | ";" | ":" | "\" | <"> - * | "/" | "[" | "]" | "?" | "=" - * | "{" | "}" | SP | HT - */ -static const char tokens[256] = { -/* 0 nul 1 soh 2 stx 3 etx 4 eot 5 enq 6 ack 7 bel */ - 0, 0, 0, 0, 0, 0, 0, 0, -/* 8 bs 9 ht 10 nl 11 vt 12 np 13 cr 14 so 15 si */ - 0, 0, 0, 0, 0, 0, 0, 0, -/* 16 dle 17 dc1 18 dc2 19 dc3 20 dc4 21 nak 22 syn 23 etb */ - 0, 0, 0, 0, 0, 0, 0, 0, -/* 24 can 25 em 26 sub 27 esc 28 fs 29 gs 30 rs 31 us */ - 0, 0, 0, 0, 0, 0, 0, 0, -/* 32 sp 33 ! 34 " 35 # 36 $ 37 % 38 & 39 ' */ - ' ', '!', 0, '#', '$', '%', '&', '\'', -/* 40 ( 41 ) 42 * 43 + 44 , 45 - 46 . 47 / */ - 0, 0, '*', '+', 0, '-', '.', 0, -/* 48 0 49 1 50 2 51 3 52 4 53 5 54 6 55 7 */ - '0', '1', '2', '3', '4', '5', '6', '7', -/* 56 8 57 9 58 : 59 ; 60 < 61 = 62 > 63 ? */ - '8', '9', 0, 0, 0, 0, 0, 0, -/* 64 @ 65 A 66 B 67 C 68 D 69 E 70 F 71 G */ - 0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', -/* 72 H 73 I 74 J 75 K 76 L 77 M 78 N 79 O */ - 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', -/* 80 P 81 Q 82 R 83 S 84 T 85 U 86 V 87 W */ - 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', -/* 88 X 89 Y 90 Z 91 [ 92 \ 93 ] 94 ^ 95 _ */ - 'x', 'y', 'z', 0, 0, 0, '^', '_', -/* 96 ` 97 a 98 b 99 c 100 d 101 e 102 f 103 g */ - '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', -/* 104 h 105 i 106 j 107 k 108 l 109 m 110 n 111 o */ - 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', -/* 112 p 113 q 114 r 115 s 116 t 117 u 118 v 119 w */ - 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', -/* 120 x 121 y 122 z 123 { 124 | 125 } 126 ~ 127 del */ - 'x', 'y', 'z', 0, '|', 0, '~', 0 }; - - -static const int8_t unhex[256] = - {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 - ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 - ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 - , 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1 - ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1 - ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 - ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1 - ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 - }; - - -#if HTTP_PARSER_STRICT -# define T(v) 0 -#else -# define T(v) v -#endif - - -static const uint8_t normal_url_char[32] = { -/* 0 nul 1 soh 2 stx 3 etx 4 eot 5 enq 6 ack 7 bel */ - 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0, -/* 8 bs 9 ht 10 nl 11 vt 12 np 13 cr 14 so 15 si */ - 0 | T(2) | 0 | 0 | T(16) | 0 | 0 | 0, -/* 16 dle 17 dc1 18 dc2 19 dc3 20 dc4 21 nak 22 syn 23 etb */ - 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0, -/* 24 can 25 em 26 sub 27 esc 28 fs 29 gs 30 rs 31 us */ - 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0, -/* 32 sp 33 ! 34 " 35 # 36 $ 37 % 38 & 39 ' */ - 0 | 2 | 4 | 0 | 16 | 32 | 64 | 128, -/* 40 ( 41 ) 42 * 43 + 44 , 45 - 46 . 47 / */ - 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, -/* 48 0 49 1 50 2 51 3 52 4 53 5 54 6 55 7 */ - 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, -/* 56 8 57 9 58 : 59 ; 60 < 61 = 62 > 63 ? */ - 1 | 2 | 4 | 8 | 16 | 32 | 64 | 0, -/* 64 @ 65 A 66 B 67 C 68 D 69 E 70 F 71 G */ - 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, -/* 72 H 73 I 74 J 75 K 76 L 77 M 78 N 79 O */ - 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, -/* 80 P 81 Q 82 R 83 S 84 T 85 U 86 V 87 W */ - 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, -/* 88 X 89 Y 90 Z 91 [ 92 \ 93 ] 94 ^ 95 _ */ - 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, -/* 96 ` 97 a 98 b 99 c 100 d 101 e 102 f 103 g */ - 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, -/* 104 h 105 i 106 j 107 k 108 l 109 m 110 n 111 o */ - 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, -/* 112 p 113 q 114 r 115 s 116 t 117 u 118 v 119 w */ - 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, -/* 120 x 121 y 122 z 123 { 124 | 125 } 126 ~ 127 del */ - 1 | 2 | 4 | 8 | 16 | 32 | 64 | 0, }; - -#undef T - -enum state - { s_dead = 1 /* important that this is > 0 */ - - , s_start_req_or_res - , s_res_or_resp_H - , s_start_res - , s_res_H - , s_res_HT - , s_res_HTT - , s_res_HTTP - , s_res_http_major - , s_res_http_dot - , s_res_http_minor - , s_res_http_end - , s_res_first_status_code - , s_res_status_code - , s_res_status_start - , s_res_status - , s_res_line_almost_done - - , s_start_req - - , s_req_method - , s_req_spaces_before_url - , s_req_schema - , s_req_schema_slash - , s_req_schema_slash_slash - , s_req_server_start - , s_req_server - , s_req_server_with_at - , s_req_path - , s_req_query_string_start - , s_req_query_string - , s_req_fragment_start - , s_req_fragment - , s_req_http_start - , s_req_http_H - , s_req_http_HT - , s_req_http_HTT - , s_req_http_HTTP - , s_req_http_I - , s_req_http_IC - , s_req_http_major - , s_req_http_dot - , s_req_http_minor - , s_req_http_end - , s_req_line_almost_done - - , s_header_field_start - , s_header_field - , s_header_value_discard_ws - , s_header_value_discard_ws_almost_done - , s_header_value_discard_lws - , s_header_value_start - , s_header_value - , s_header_value_lws - - , s_header_almost_done - - , s_chunk_size_start - , s_chunk_size - , s_chunk_parameters - , s_chunk_size_almost_done - - , s_headers_almost_done - , s_headers_done - - /* Important: 's_headers_done' must be the last 'header' state. All - * states beyond this must be 'body' states. It is used for overflow - * checking. See the PARSING_HEADER() macro. - */ - - , s_chunk_data - , s_chunk_data_almost_done - , s_chunk_data_done - - , s_body_identity - , s_body_identity_eof - - , s_message_done - }; - - -#define PARSING_HEADER(state) (state <= s_headers_done) - - -enum header_states - { h_general = 0 - , h_C - , h_CO - , h_CON - - , h_matching_connection - , h_matching_proxy_connection - , h_matching_content_length - , h_matching_transfer_encoding - , h_matching_upgrade - - , h_connection - , h_content_length - , h_content_length_num - , h_content_length_ws - , h_transfer_encoding - , h_upgrade - - , h_matching_transfer_encoding_token_start - , h_matching_transfer_encoding_chunked - , h_matching_transfer_encoding_token - - , h_matching_connection_token_start - , h_matching_connection_keep_alive - , h_matching_connection_close - , h_matching_connection_upgrade - , h_matching_connection_token - - , h_transfer_encoding_chunked - , h_connection_keep_alive - , h_connection_close - , h_connection_upgrade - }; - -enum http_host_state - { - s_http_host_dead = 1 - , s_http_userinfo_start - , s_http_userinfo - , s_http_host_start - , s_http_host_v6_start - , s_http_host - , s_http_host_v6 - , s_http_host_v6_end - , s_http_host_v6_zone_start - , s_http_host_v6_zone - , s_http_host_port_start - , s_http_host_port -}; - -/* Macros for character classes; depends on strict-mode */ -#define CR '\r' -#define LF '\n' -#define LOWER(c) (unsigned char)(c | 0x20) -#define IS_ALPHA(c) (LOWER(c) >= 'a' && LOWER(c) <= 'z') -#define IS_NUM(c) ((c) >= '0' && (c) <= '9') -#define IS_ALPHANUM(c) (IS_ALPHA(c) || IS_NUM(c)) -#define IS_HEX(c) (IS_NUM(c) || (LOWER(c) >= 'a' && LOWER(c) <= 'f')) -#define IS_MARK(c) ((c) == '-' || (c) == '_' || (c) == '.' || \ - (c) == '!' || (c) == '~' || (c) == '*' || (c) == '\'' || (c) == '(' || \ - (c) == ')') -#define IS_USERINFO_CHAR(c) (IS_ALPHANUM(c) || IS_MARK(c) || (c) == '%' || \ - (c) == ';' || (c) == ':' || (c) == '&' || (c) == '=' || (c) == '+' || \ - (c) == '$' || (c) == ',') - -#define STRICT_TOKEN(c) ((c == ' ') ? 0 : tokens[(unsigned char)c]) - -#if HTTP_PARSER_STRICT -#define TOKEN(c) STRICT_TOKEN(c) -#define IS_URL_CHAR(c) (BIT_AT(normal_url_char, (unsigned char)c)) -#define IS_HOST_CHAR(c) (IS_ALPHANUM(c) || (c) == '.' || (c) == '-') -#else -#define TOKEN(c) tokens[(unsigned char)c] -#define IS_URL_CHAR(c) \ - (BIT_AT(normal_url_char, (unsigned char)c) || ((c) & 0x80)) -#define IS_HOST_CHAR(c) \ - (IS_ALPHANUM(c) || (c) == '.' || (c) == '-' || (c) == '_') -#endif - -/** - * Verify that a char is a valid visible (printable) US-ASCII - * character or %x80-FF - **/ -#define IS_HEADER_CHAR(ch) \ - (ch == CR || ch == LF || ch == 9 || ((unsigned char)ch > 31 && ch != 127)) - -#define start_state (parser->type == HTTP_REQUEST ? s_start_req : s_start_res) - - -#if HTTP_PARSER_STRICT -# define STRICT_CHECK(cond) \ -do { \ - if (cond) { \ - SET_ERRNO(HPE_STRICT); \ - goto error; \ - } \ -} while (0) -# define NEW_MESSAGE() (http_should_keep_alive(parser) ? start_state : s_dead) -#else -# define STRICT_CHECK(cond) -# define NEW_MESSAGE() start_state -#endif - - -/* Map errno values to strings for human-readable output */ -#define HTTP_STRERROR_GEN(n, s) { "HPE_" #n, s }, -static struct { - const char *name; - const char *description; -} http_strerror_tab[] = { - HTTP_ERRNO_MAP(HTTP_STRERROR_GEN) -}; -#undef HTTP_STRERROR_GEN - -int http_message_needs_eof(const http_parser *parser); - -/* Our URL parser. - * - * This is designed to be shared by http_parser_execute() for URL validation, - * hence it has a state transition + byte-for-byte interface. In addition, it - * is meant to be embedded in http_parser_parse_url(), which does the dirty - * work of turning state transitions URL components for its API. - * - * This function should only be invoked with non-space characters. It is - * assumed that the caller cares about (and can detect) the transition between - * URL and non-URL states by looking for these. - */ -static enum state -parse_url_char(enum state s, const char ch) -{ - if (ch == ' ' || ch == '\r' || ch == '\n') { - return s_dead; - } - -#if HTTP_PARSER_STRICT - if (ch == '\t' || ch == '\f') { - return s_dead; - } -#endif - - switch (s) { - case s_req_spaces_before_url: - /* Proxied requests are followed by scheme of an absolute URI (alpha). - * All methods except CONNECT are followed by '/' or '*'. - */ - - if (ch == '/' || ch == '*') { - return s_req_path; - } - - if (IS_ALPHA(ch)) { - return s_req_schema; - } - - break; - - case s_req_schema: - if (IS_ALPHA(ch)) { - return s; - } - - if (ch == ':') { - return s_req_schema_slash; - } - - break; - - case s_req_schema_slash: - if (ch == '/') { - return s_req_schema_slash_slash; - } - - break; - - case s_req_schema_slash_slash: - if (ch == '/') { - return s_req_server_start; - } - - break; - - case s_req_server_with_at: - if (ch == '@') { - return s_dead; - } - - /* fall through */ - case s_req_server_start: - case s_req_server: - if (ch == '/') { - return s_req_path; - } - - if (ch == '?') { - return s_req_query_string_start; - } - - if (ch == '@') { - return s_req_server_with_at; - } - - if (IS_USERINFO_CHAR(ch) || ch == '[' || ch == ']') { - return s_req_server; - } - - break; - - case s_req_path: - if (IS_URL_CHAR(ch)) { - return s; - } - - switch (ch) { - case '?': - return s_req_query_string_start; - - case '#': - return s_req_fragment_start; - } - - break; - - case s_req_query_string_start: - case s_req_query_string: - if (IS_URL_CHAR(ch)) { - return s_req_query_string; - } - - switch (ch) { - case '?': - /* allow extra '?' in query string */ - return s_req_query_string; - - case '#': - return s_req_fragment_start; - } - - break; - - case s_req_fragment_start: - if (IS_URL_CHAR(ch)) { - return s_req_fragment; - } - - switch (ch) { - case '?': - return s_req_fragment; - - case '#': - return s; - } - - break; - - case s_req_fragment: - if (IS_URL_CHAR(ch)) { - return s; - } - - switch (ch) { - case '?': - case '#': - return s; - } - - break; - - default: - break; - } - - /* We should never fall out of the switch above unless there's an error */ - return s_dead; -} - -size_t http_parser_execute (http_parser *parser, - const http_parser_settings *settings, - const char *data, - size_t len) -{ - char c, ch; - int8_t unhex_val; - const char *p = data; - const char *header_field_mark = 0; - const char *header_value_mark = 0; - const char *url_mark = 0; - const char *body_mark = 0; - const char *status_mark = 0; - enum state p_state = (enum state) parser->state; - const unsigned int lenient = parser->lenient_http_headers; - uint32_t nread = parser->nread; - - /* We're in an error state. Don't bother doing anything. */ - if (HTTP_PARSER_ERRNO(parser) != HPE_OK) { - return 0; - } - - if (len == 0) { - switch (CURRENT_STATE()) { - case s_body_identity_eof: - /* Use of CALLBACK_NOTIFY() here would erroneously return 1 byte read if - * we got paused. - */ - CALLBACK_NOTIFY_NOADVANCE(message_complete); - return 0; - - case s_dead: - case s_start_req_or_res: - case s_start_res: - case s_start_req: - return 0; - - default: - SET_ERRNO(HPE_INVALID_EOF_STATE); - return 1; - } - } - - - if (CURRENT_STATE() == s_header_field) - header_field_mark = data; - if (CURRENT_STATE() == s_header_value) - header_value_mark = data; - switch (CURRENT_STATE()) { - case s_req_path: - case s_req_schema: - case s_req_schema_slash: - case s_req_schema_slash_slash: - case s_req_server_start: - case s_req_server: - case s_req_server_with_at: - case s_req_query_string_start: - case s_req_query_string: - case s_req_fragment_start: - case s_req_fragment: - url_mark = data; - break; - case s_res_status: - status_mark = data; - break; - default: - break; - } - - for (p=data; p != data + len; p++) { - ch = *p; - - if (PARSING_HEADER(CURRENT_STATE())) - COUNT_HEADER_SIZE(1); - -reexecute: - switch (CURRENT_STATE()) { - - case s_dead: - /* this state is used after a 'Connection: close' message - * the parser will error out if it reads another message - */ - if (LIKELY(ch == CR || ch == LF)) - break; - - SET_ERRNO(HPE_CLOSED_CONNECTION); - goto error; - - case s_start_req_or_res: - { - if (ch == CR || ch == LF) - break; - parser->flags = 0; - parser->extra_flags = 0; - parser->content_length = ULLONG_MAX; - - if (ch == 'H') { - UPDATE_STATE(s_res_or_resp_H); - - CALLBACK_NOTIFY(message_begin); - } else { - parser->type = HTTP_REQUEST; - UPDATE_STATE(s_start_req); - REEXECUTE(); - } - - break; - } - - case s_res_or_resp_H: - if (ch == 'T') { - parser->type = HTTP_RESPONSE; - UPDATE_STATE(s_res_HT); - } else { - if (UNLIKELY(ch != 'E')) { - SET_ERRNO(HPE_INVALID_CONSTANT); - goto error; - } - - parser->type = HTTP_REQUEST; - parser->method = HTTP_HEAD; - parser->index = 2; - UPDATE_STATE(s_req_method); - } - break; - - case s_start_res: - { - if (ch == CR || ch == LF) - break; - parser->flags = 0; - parser->extra_flags = 0; - parser->content_length = ULLONG_MAX; - - if (ch == 'H') { - UPDATE_STATE(s_res_H); - } else { - SET_ERRNO(HPE_INVALID_CONSTANT); - goto error; - } - - CALLBACK_NOTIFY(message_begin); - break; - } - - case s_res_H: - STRICT_CHECK(ch != 'T'); - UPDATE_STATE(s_res_HT); - break; - - case s_res_HT: - STRICT_CHECK(ch != 'T'); - UPDATE_STATE(s_res_HTT); - break; - - case s_res_HTT: - STRICT_CHECK(ch != 'P'); - UPDATE_STATE(s_res_HTTP); - break; - - case s_res_HTTP: - STRICT_CHECK(ch != '/'); - UPDATE_STATE(s_res_http_major); - break; - - case s_res_http_major: - if (UNLIKELY(!IS_NUM(ch))) { - SET_ERRNO(HPE_INVALID_VERSION); - goto error; - } - - parser->http_major = ch - '0'; - UPDATE_STATE(s_res_http_dot); - break; - - case s_res_http_dot: - { - if (UNLIKELY(ch != '.')) { - SET_ERRNO(HPE_INVALID_VERSION); - goto error; - } - - UPDATE_STATE(s_res_http_minor); - break; - } - - case s_res_http_minor: - if (UNLIKELY(!IS_NUM(ch))) { - SET_ERRNO(HPE_INVALID_VERSION); - goto error; - } - - parser->http_minor = ch - '0'; - UPDATE_STATE(s_res_http_end); - break; - - case s_res_http_end: - { - if (UNLIKELY(ch != ' ')) { - SET_ERRNO(HPE_INVALID_VERSION); - goto error; - } - - UPDATE_STATE(s_res_first_status_code); - break; - } - - case s_res_first_status_code: - { - if (!IS_NUM(ch)) { - if (ch == ' ') { - break; - } - - SET_ERRNO(HPE_INVALID_STATUS); - goto error; - } - parser->status_code = ch - '0'; - UPDATE_STATE(s_res_status_code); - break; - } - - case s_res_status_code: - { - if (!IS_NUM(ch)) { - switch (ch) { - case ' ': - UPDATE_STATE(s_res_status_start); - break; - case CR: - case LF: - UPDATE_STATE(s_res_status_start); - REEXECUTE(); - break; - default: - SET_ERRNO(HPE_INVALID_STATUS); - goto error; - } - break; - } - - parser->status_code *= 10; - parser->status_code += ch - '0'; - - if (UNLIKELY(parser->status_code > 999)) { - SET_ERRNO(HPE_INVALID_STATUS); - goto error; - } - - break; - } - - case s_res_status_start: - { - MARK(status); - UPDATE_STATE(s_res_status); - parser->index = 0; - - if (ch == CR || ch == LF) - REEXECUTE(); - - break; - } - - case s_res_status: - if (ch == CR) { - UPDATE_STATE(s_res_line_almost_done); - CALLBACK_DATA(status); - break; - } - - if (ch == LF) { - UPDATE_STATE(s_header_field_start); - CALLBACK_DATA(status); - break; - } - - break; - - case s_res_line_almost_done: - STRICT_CHECK(ch != LF); - UPDATE_STATE(s_header_field_start); - break; - - case s_start_req: - { - if (ch == CR || ch == LF) - break; - parser->flags = 0; - parser->extra_flags = 0; - parser->content_length = ULLONG_MAX; - - if (UNLIKELY(!IS_ALPHA(ch))) { - SET_ERRNO(HPE_INVALID_METHOD); - goto error; - } - - parser->method = (enum http_method) 0; - parser->index = 1; - switch (ch) { - case 'A': parser->method = HTTP_ACL; break; - case 'B': parser->method = HTTP_BIND; break; - case 'C': parser->method = HTTP_CONNECT; /* or COPY, CHECKOUT */ break; - case 'D': parser->method = HTTP_DELETE; break; - case 'G': parser->method = HTTP_GET; break; - case 'H': parser->method = HTTP_HEAD; break; - case 'L': parser->method = HTTP_LOCK; /* or LINK */ break; - case 'M': parser->method = HTTP_MKCOL; /* or MOVE, MKACTIVITY, MERGE, M-SEARCH, MKCALENDAR */ break; - case 'N': parser->method = HTTP_NOTIFY; break; - case 'O': parser->method = HTTP_OPTIONS; break; - case 'P': parser->method = HTTP_POST; - /* or PROPFIND|PROPPATCH|PUT|PATCH|PURGE */ - break; - case 'R': parser->method = HTTP_REPORT; /* or REBIND */ break; - case 'S': parser->method = HTTP_SUBSCRIBE; /* or SEARCH, SOURCE */ break; - case 'T': parser->method = HTTP_TRACE; break; - case 'U': parser->method = HTTP_UNLOCK; /* or UNSUBSCRIBE, UNBIND, UNLINK */ break; - default: - SET_ERRNO(HPE_INVALID_METHOD); - goto error; - } - UPDATE_STATE(s_req_method); - - CALLBACK_NOTIFY(message_begin); - - break; - } - - case s_req_method: - { - const char *matcher; - if (UNLIKELY(ch == '\0')) { - SET_ERRNO(HPE_INVALID_METHOD); - goto error; - } - - matcher = method_strings[parser->method]; - if (ch == ' ' && matcher[parser->index] == '\0') { - UPDATE_STATE(s_req_spaces_before_url); - } else if (ch == matcher[parser->index]) { - ; /* nada */ - } else if ((ch >= 'A' && ch <= 'Z') || ch == '-') { - - switch (parser->method << 16 | parser->index << 8 | ch) { -#define XX(meth, pos, ch, new_meth) \ - case (HTTP_##meth << 16 | pos << 8 | ch): \ - parser->method = HTTP_##new_meth; break; - - XX(POST, 1, 'U', PUT) - XX(POST, 1, 'A', PATCH) - XX(POST, 1, 'R', PROPFIND) - XX(PUT, 2, 'R', PURGE) - XX(CONNECT, 1, 'H', CHECKOUT) - XX(CONNECT, 2, 'P', COPY) - XX(MKCOL, 1, 'O', MOVE) - XX(MKCOL, 1, 'E', MERGE) - XX(MKCOL, 1, '-', MSEARCH) - XX(MKCOL, 2, 'A', MKACTIVITY) - XX(MKCOL, 3, 'A', MKCALENDAR) - XX(SUBSCRIBE, 1, 'E', SEARCH) - XX(SUBSCRIBE, 1, 'O', SOURCE) - XX(REPORT, 2, 'B', REBIND) - XX(PROPFIND, 4, 'P', PROPPATCH) - XX(LOCK, 1, 'I', LINK) - XX(UNLOCK, 2, 'S', UNSUBSCRIBE) - XX(UNLOCK, 2, 'B', UNBIND) - XX(UNLOCK, 3, 'I', UNLINK) -#undef XX - default: - SET_ERRNO(HPE_INVALID_METHOD); - goto error; - } - } else { - SET_ERRNO(HPE_INVALID_METHOD); - goto error; - } - - ++parser->index; - break; - } - - case s_req_spaces_before_url: - { - if (ch == ' ') break; - - MARK(url); - if (parser->method == HTTP_CONNECT) { - UPDATE_STATE(s_req_server_start); - } - - UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch)); - if (UNLIKELY(CURRENT_STATE() == s_dead)) { - SET_ERRNO(HPE_INVALID_URL); - goto error; - } - - break; - } - - case s_req_schema: - case s_req_schema_slash: - case s_req_schema_slash_slash: - case s_req_server_start: - { - switch (ch) { - /* No whitespace allowed here */ - case ' ': - case CR: - case LF: - SET_ERRNO(HPE_INVALID_URL); - goto error; - default: - UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch)); - if (UNLIKELY(CURRENT_STATE() == s_dead)) { - SET_ERRNO(HPE_INVALID_URL); - goto error; - } - } - - break; - } - - case s_req_server: - case s_req_server_with_at: - case s_req_path: - case s_req_query_string_start: - case s_req_query_string: - case s_req_fragment_start: - case s_req_fragment: - { - switch (ch) { - case ' ': - UPDATE_STATE(s_req_http_start); - CALLBACK_DATA(url); - break; - case CR: - case LF: - parser->http_major = 0; - parser->http_minor = 9; - UPDATE_STATE((ch == CR) ? - s_req_line_almost_done : - s_header_field_start); - CALLBACK_DATA(url); - break; - default: - UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch)); - if (UNLIKELY(CURRENT_STATE() == s_dead)) { - SET_ERRNO(HPE_INVALID_URL); - goto error; - } - } - break; - } - - case s_req_http_start: - switch (ch) { - case ' ': - break; - case 'H': - UPDATE_STATE(s_req_http_H); - break; - case 'I': - if (parser->method == HTTP_SOURCE) { - UPDATE_STATE(s_req_http_I); - break; - } - /* fall through */ - default: - SET_ERRNO(HPE_INVALID_CONSTANT); - goto error; - } - break; - - case s_req_http_H: - STRICT_CHECK(ch != 'T'); - UPDATE_STATE(s_req_http_HT); - break; - - case s_req_http_HT: - STRICT_CHECK(ch != 'T'); - UPDATE_STATE(s_req_http_HTT); - break; - - case s_req_http_HTT: - STRICT_CHECK(ch != 'P'); - UPDATE_STATE(s_req_http_HTTP); - break; - - case s_req_http_I: - STRICT_CHECK(ch != 'C'); - UPDATE_STATE(s_req_http_IC); - break; - - case s_req_http_IC: - STRICT_CHECK(ch != 'E'); - UPDATE_STATE(s_req_http_HTTP); /* Treat "ICE" as "HTTP". */ - break; - - case s_req_http_HTTP: - STRICT_CHECK(ch != '/'); - UPDATE_STATE(s_req_http_major); - break; - - case s_req_http_major: - if (UNLIKELY(!IS_NUM(ch))) { - SET_ERRNO(HPE_INVALID_VERSION); - goto error; - } - - parser->http_major = ch - '0'; - UPDATE_STATE(s_req_http_dot); - break; - - case s_req_http_dot: - { - if (UNLIKELY(ch != '.')) { - SET_ERRNO(HPE_INVALID_VERSION); - goto error; - } - - UPDATE_STATE(s_req_http_minor); - break; - } - - case s_req_http_minor: - if (UNLIKELY(!IS_NUM(ch))) { - SET_ERRNO(HPE_INVALID_VERSION); - goto error; - } - - parser->http_minor = ch - '0'; - UPDATE_STATE(s_req_http_end); - break; - - case s_req_http_end: - { - if (ch == CR) { - UPDATE_STATE(s_req_line_almost_done); - break; - } - - if (ch == LF) { - UPDATE_STATE(s_header_field_start); - break; - } - - SET_ERRNO(HPE_INVALID_VERSION); - goto error; - break; - } - - /* end of request line */ - case s_req_line_almost_done: - { - if (UNLIKELY(ch != LF)) { - SET_ERRNO(HPE_LF_EXPECTED); - goto error; - } - - UPDATE_STATE(s_header_field_start); - break; - } - - case s_header_field_start: - { - if (ch == CR) { - UPDATE_STATE(s_headers_almost_done); - break; - } - - if (ch == LF) { - /* they might be just sending \n instead of \r\n so this would be - * the second \n to denote the end of headers*/ - UPDATE_STATE(s_headers_almost_done); - REEXECUTE(); - } - - c = TOKEN(ch); - - if (UNLIKELY(!c)) { - SET_ERRNO(HPE_INVALID_HEADER_TOKEN); - goto error; - } - - MARK(header_field); - - parser->index = 0; - UPDATE_STATE(s_header_field); - - switch (c) { - case 'c': - parser->header_state = h_C; - break; - - case 'p': - parser->header_state = h_matching_proxy_connection; - break; - - case 't': - parser->header_state = h_matching_transfer_encoding; - break; - - case 'u': - parser->header_state = h_matching_upgrade; - break; - - default: - parser->header_state = h_general; - break; - } - break; - } - - case s_header_field: - { - const char* start = p; - for (; p != data + len; p++) { - ch = *p; - c = TOKEN(ch); - - if (!c) - break; - - switch (parser->header_state) { - case h_general: { - size_t left = data + len - p; - const char* pe = p + MIN(left, max_header_size); - while (p+1 < pe && TOKEN(p[1])) { - p++; - } - break; - } - - case h_C: - parser->index++; - parser->header_state = (c == 'o' ? h_CO : h_general); - break; - - case h_CO: - parser->index++; - parser->header_state = (c == 'n' ? h_CON : h_general); - break; - - case h_CON: - parser->index++; - switch (c) { - case 'n': - parser->header_state = h_matching_connection; - break; - case 't': - parser->header_state = h_matching_content_length; - break; - default: - parser->header_state = h_general; - break; - } - break; - - /* connection */ - - case h_matching_connection: - parser->index++; - if (parser->index > sizeof(CONNECTION)-1 - || c != CONNECTION[parser->index]) { - parser->header_state = h_general; - } else if (parser->index == sizeof(CONNECTION)-2) { - parser->header_state = h_connection; - } - break; - - /* proxy-connection */ - - case h_matching_proxy_connection: - parser->index++; - if (parser->index > sizeof(PROXY_CONNECTION)-1 - || c != PROXY_CONNECTION[parser->index]) { - parser->header_state = h_general; - } else if (parser->index == sizeof(PROXY_CONNECTION)-2) { - parser->header_state = h_connection; - } - break; - - /* content-length */ - - case h_matching_content_length: - parser->index++; - if (parser->index > sizeof(CONTENT_LENGTH)-1 - || c != CONTENT_LENGTH[parser->index]) { - parser->header_state = h_general; - } else if (parser->index == sizeof(CONTENT_LENGTH)-2) { - parser->header_state = h_content_length; - } - break; - - /* transfer-encoding */ - - case h_matching_transfer_encoding: - parser->index++; - if (parser->index > sizeof(TRANSFER_ENCODING)-1 - || c != TRANSFER_ENCODING[parser->index]) { - parser->header_state = h_general; - } else if (parser->index == sizeof(TRANSFER_ENCODING)-2) { - parser->header_state = h_transfer_encoding; - parser->extra_flags |= F_TRANSFER_ENCODING >> 8; - } - break; - - /* upgrade */ - - case h_matching_upgrade: - parser->index++; - if (parser->index > sizeof(UPGRADE)-1 - || c != UPGRADE[parser->index]) { - parser->header_state = h_general; - } else if (parser->index == sizeof(UPGRADE)-2) { - parser->header_state = h_upgrade; - } - break; - - case h_connection: - case h_content_length: - case h_transfer_encoding: - case h_upgrade: - if (ch != ' ') parser->header_state = h_general; - break; - - default: - assert(0 && "Unknown header_state"); - break; - } - } - - if (p == data + len) { - --p; - COUNT_HEADER_SIZE(p - start); - break; - } - - COUNT_HEADER_SIZE(p - start); - - if (ch == ':') { - UPDATE_STATE(s_header_value_discard_ws); - CALLBACK_DATA(header_field); - break; - } - - SET_ERRNO(HPE_INVALID_HEADER_TOKEN); - goto error; - } - - case s_header_value_discard_ws: - if (ch == ' ' || ch == '\t') break; - - if (ch == CR) { - UPDATE_STATE(s_header_value_discard_ws_almost_done); - break; - } - - if (ch == LF) { - UPDATE_STATE(s_header_value_discard_lws); - break; - } - - /* fall through */ - - case s_header_value_start: - { - MARK(header_value); - - UPDATE_STATE(s_header_value); - parser->index = 0; - - c = LOWER(ch); - - switch (parser->header_state) { - case h_upgrade: - parser->flags |= F_UPGRADE; - parser->header_state = h_general; - break; - - case h_transfer_encoding: - /* looking for 'Transfer-Encoding: chunked' */ - if ('c' == c) { - parser->header_state = h_matching_transfer_encoding_chunked; - } else { - parser->header_state = h_matching_transfer_encoding_token; - } - break; - - /* Multi-value `Transfer-Encoding` header */ - case h_matching_transfer_encoding_token_start: - break; - - case h_content_length: - if (UNLIKELY(!IS_NUM(ch))) { - SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); - goto error; - } - - if (parser->flags & F_CONTENTLENGTH) { - SET_ERRNO(HPE_UNEXPECTED_CONTENT_LENGTH); - goto error; - } - - parser->flags |= F_CONTENTLENGTH; - parser->content_length = ch - '0'; - parser->header_state = h_content_length_num; - break; - - /* when obsolete line folding is encountered for content length - * continue to the s_header_value state */ - case h_content_length_ws: - break; - - case h_connection: - /* looking for 'Connection: keep-alive' */ - if (c == 'k') { - parser->header_state = h_matching_connection_keep_alive; - /* looking for 'Connection: close' */ - } else if (c == 'c') { - parser->header_state = h_matching_connection_close; - } else if (c == 'u') { - parser->header_state = h_matching_connection_upgrade; - } else { - parser->header_state = h_matching_connection_token; - } - break; - - /* Multi-value `Connection` header */ - case h_matching_connection_token_start: - break; - - default: - parser->header_state = h_general; - break; - } - break; - } - - case s_header_value: - { - const char* start = p; - enum header_states h_state = (enum header_states) parser->header_state; - for (; p != data + len; p++) { - ch = *p; - if (ch == CR) { - UPDATE_STATE(s_header_almost_done); - parser->header_state = h_state; - CALLBACK_DATA(header_value); - break; - } - - if (ch == LF) { - UPDATE_STATE(s_header_almost_done); - COUNT_HEADER_SIZE(p - start); - parser->header_state = h_state; - CALLBACK_DATA_NOADVANCE(header_value); - REEXECUTE(); - } - - if (!lenient && !IS_HEADER_CHAR(ch)) { - SET_ERRNO(HPE_INVALID_HEADER_TOKEN); - goto error; - } - - c = LOWER(ch); - - switch (h_state) { - case h_general: - { - size_t left = data + len - p; - const char* pe = p + MIN(left, max_header_size); - - for (; p != pe; p++) { - ch = *p; - if (ch == CR || ch == LF) { - --p; - break; - } - if (!lenient && !IS_HEADER_CHAR(ch)) { - SET_ERRNO(HPE_INVALID_HEADER_TOKEN); - goto error; - } - } - if (p == data + len) - --p; - break; - } - - case h_connection: - case h_transfer_encoding: - assert(0 && "Shouldn't get here."); - break; - - case h_content_length: - if (ch == ' ') break; - h_state = h_content_length_num; - /* fall through */ - - case h_content_length_num: - { - uint64_t t; - - if (ch == ' ') { - h_state = h_content_length_ws; - break; - } - - if (UNLIKELY(!IS_NUM(ch))) { - SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); - parser->header_state = h_state; - goto error; - } - - t = parser->content_length; - t *= 10; - t += ch - '0'; - - /* Overflow? Test against a conservative limit for simplicity. */ - if (UNLIKELY((ULLONG_MAX - 10) / 10 < parser->content_length)) { - SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); - parser->header_state = h_state; - goto error; - } - - parser->content_length = t; - break; - } - - case h_content_length_ws: - if (ch == ' ') break; - SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); - parser->header_state = h_state; - goto error; - - /* Transfer-Encoding: chunked */ - case h_matching_transfer_encoding_token_start: - /* looking for 'Transfer-Encoding: chunked' */ - if ('c' == c) { - h_state = h_matching_transfer_encoding_chunked; - } else if (STRICT_TOKEN(c)) { - /* TODO(indutny): similar code below does this, but why? - * At the very least it seems to be inconsistent given that - * h_matching_transfer_encoding_token does not check for - * `STRICT_TOKEN` - */ - h_state = h_matching_transfer_encoding_token; - } else if (c == ' ' || c == '\t') { - /* Skip lws */ - } else { - h_state = h_general; - } - break; - - case h_matching_transfer_encoding_chunked: - parser->index++; - if (parser->index > sizeof(CHUNKED)-1 - || c != CHUNKED[parser->index]) { - h_state = h_matching_transfer_encoding_token; - } else if (parser->index == sizeof(CHUNKED)-2) { - h_state = h_transfer_encoding_chunked; - } - break; - - case h_matching_transfer_encoding_token: - if (ch == ',') { - h_state = h_matching_transfer_encoding_token_start; - parser->index = 0; - } - break; - - case h_matching_connection_token_start: - /* looking for 'Connection: keep-alive' */ - if (c == 'k') { - h_state = h_matching_connection_keep_alive; - /* looking for 'Connection: close' */ - } else if (c == 'c') { - h_state = h_matching_connection_close; - } else if (c == 'u') { - h_state = h_matching_connection_upgrade; - } else if (STRICT_TOKEN(c)) { - h_state = h_matching_connection_token; - } else if (c == ' ' || c == '\t') { - /* Skip lws */ - } else { - h_state = h_general; - } - break; - - /* looking for 'Connection: keep-alive' */ - case h_matching_connection_keep_alive: - parser->index++; - if (parser->index > sizeof(KEEP_ALIVE)-1 - || c != KEEP_ALIVE[parser->index]) { - h_state = h_matching_connection_token; - } else if (parser->index == sizeof(KEEP_ALIVE)-2) { - h_state = h_connection_keep_alive; - } - break; - - /* looking for 'Connection: close' */ - case h_matching_connection_close: - parser->index++; - if (parser->index > sizeof(CLOSE)-1 || c != CLOSE[parser->index]) { - h_state = h_matching_connection_token; - } else if (parser->index == sizeof(CLOSE)-2) { - h_state = h_connection_close; - } - break; - - /* looking for 'Connection: upgrade' */ - case h_matching_connection_upgrade: - parser->index++; - if (parser->index > sizeof(UPGRADE) - 1 || - c != UPGRADE[parser->index]) { - h_state = h_matching_connection_token; - } else if (parser->index == sizeof(UPGRADE)-2) { - h_state = h_connection_upgrade; - } - break; - - case h_matching_connection_token: - if (ch == ',') { - h_state = h_matching_connection_token_start; - parser->index = 0; - } - break; - - case h_transfer_encoding_chunked: - if (ch != ' ') h_state = h_matching_transfer_encoding_token; - break; - - case h_connection_keep_alive: - case h_connection_close: - case h_connection_upgrade: - if (ch == ',') { - if (h_state == h_connection_keep_alive) { - parser->flags |= F_CONNECTION_KEEP_ALIVE; - } else if (h_state == h_connection_close) { - parser->flags |= F_CONNECTION_CLOSE; - } else if (h_state == h_connection_upgrade) { - parser->flags |= F_CONNECTION_UPGRADE; - } - h_state = h_matching_connection_token_start; - parser->index = 0; - } else if (ch != ' ') { - h_state = h_matching_connection_token; - } - break; - - default: - UPDATE_STATE(s_header_value); - h_state = h_general; - break; - } - } - parser->header_state = h_state; - - if (p == data + len) - --p; - - COUNT_HEADER_SIZE(p - start); - break; - } - - case s_header_almost_done: - { - if (UNLIKELY(ch != LF)) { - SET_ERRNO(HPE_LF_EXPECTED); - goto error; - } - - UPDATE_STATE(s_header_value_lws); - break; - } - - case s_header_value_lws: - { - if (ch == ' ' || ch == '\t') { - if (parser->header_state == h_content_length_num) { - /* treat obsolete line folding as space */ - parser->header_state = h_content_length_ws; - } - UPDATE_STATE(s_header_value_start); - REEXECUTE(); - } - - /* finished the header */ - switch (parser->header_state) { - case h_connection_keep_alive: - parser->flags |= F_CONNECTION_KEEP_ALIVE; - break; - case h_connection_close: - parser->flags |= F_CONNECTION_CLOSE; - break; - case h_transfer_encoding_chunked: - parser->flags |= F_CHUNKED; - break; - case h_connection_upgrade: - parser->flags |= F_CONNECTION_UPGRADE; - break; - default: - break; - } - - UPDATE_STATE(s_header_field_start); - REEXECUTE(); - } - - case s_header_value_discard_ws_almost_done: - { - STRICT_CHECK(ch != LF); - UPDATE_STATE(s_header_value_discard_lws); - break; - } - - case s_header_value_discard_lws: - { - if (ch == ' ' || ch == '\t') { - UPDATE_STATE(s_header_value_discard_ws); - break; - } else { - switch (parser->header_state) { - case h_connection_keep_alive: - parser->flags |= F_CONNECTION_KEEP_ALIVE; - break; - case h_connection_close: - parser->flags |= F_CONNECTION_CLOSE; - break; - case h_connection_upgrade: - parser->flags |= F_CONNECTION_UPGRADE; - break; - case h_transfer_encoding_chunked: - parser->flags |= F_CHUNKED; - break; - case h_content_length: - /* do not allow empty content length */ - SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); - goto error; - break; - default: - break; - } - - /* header value was empty */ - MARK(header_value); - UPDATE_STATE(s_header_field_start); - CALLBACK_DATA_NOADVANCE(header_value); - REEXECUTE(); - } - } - - case s_headers_almost_done: - { - STRICT_CHECK(ch != LF); - - if (parser->flags & F_TRAILING) { - /* End of a chunked request */ - UPDATE_STATE(s_message_done); - CALLBACK_NOTIFY_NOADVANCE(chunk_complete); - REEXECUTE(); - } - - /* Cannot us transfer-encoding and a content-length header together - per the HTTP specification. (RFC 7230 Section 3.3.3) */ - if ((parser->extra_flags & (F_TRANSFER_ENCODING >> 8)) && - (parser->flags & F_CONTENTLENGTH)) { - /* Allow it for lenient parsing as long as `Transfer-Encoding` is - * not `chunked` - */ - if (!lenient || (parser->flags & F_CHUNKED)) { - SET_ERRNO(HPE_UNEXPECTED_CONTENT_LENGTH); - goto error; - } - } - - UPDATE_STATE(s_headers_done); - - /* Set this here so that on_headers_complete() callbacks can see it */ - if ((parser->flags & F_UPGRADE) && - (parser->flags & F_CONNECTION_UPGRADE)) { - /* For responses, "Upgrade: foo" and "Connection: upgrade" are - * mandatory only when it is a 101 Switching Protocols response, - * otherwise it is purely informational, to announce support. - */ - parser->upgrade = - (parser->type == HTTP_REQUEST || parser->status_code == 101); - } else { - parser->upgrade = (parser->method == HTTP_CONNECT); - } - - /* Here we call the headers_complete callback. This is somewhat - * different than other callbacks because if the user returns 1, we - * will interpret that as saying that this message has no body. This - * is needed for the annoying case of recieving a response to a HEAD - * request. - * - * We'd like to use CALLBACK_NOTIFY_NOADVANCE() here but we cannot, so - * we have to simulate it by handling a change in errno below. - */ - if (settings->on_headers_complete) { - switch (settings->on_headers_complete(parser)) { - case 0: - break; - - case 2: - parser->upgrade = 1; - - /* fall through */ - case 1: - parser->flags |= F_SKIPBODY; - break; - - default: - SET_ERRNO(HPE_CB_headers_complete); - RETURN(p - data); /* Error */ - } - } - - if (HTTP_PARSER_ERRNO(parser) != HPE_OK) { - RETURN(p - data); - } - - REEXECUTE(); - } - - case s_headers_done: - { - int hasBody; - STRICT_CHECK(ch != LF); - - parser->nread = 0; - nread = 0; - - hasBody = parser->flags & F_CHUNKED || - (parser->content_length > 0 && parser->content_length != ULLONG_MAX); - if (parser->upgrade && (parser->method == HTTP_CONNECT || - (parser->flags & F_SKIPBODY) || !hasBody)) { - /* Exit, the rest of the message is in a different protocol. */ - UPDATE_STATE(NEW_MESSAGE()); - CALLBACK_NOTIFY(message_complete); - RETURN((p - data) + 1); - } - - if (parser->flags & F_SKIPBODY) { - UPDATE_STATE(NEW_MESSAGE()); - CALLBACK_NOTIFY(message_complete); - } else if (parser->flags & F_CHUNKED) { - /* chunked encoding - ignore Content-Length header, - * prepare for a chunk */ - UPDATE_STATE(s_chunk_size_start); - } else if (parser->extra_flags & (F_TRANSFER_ENCODING >> 8)) { - if (parser->type == HTTP_REQUEST && !lenient) { - /* RFC 7230 3.3.3 */ - - /* If a Transfer-Encoding header field - * is present in a request and the chunked transfer coding is not - * the final encoding, the message body length cannot be determined - * reliably; the server MUST respond with the 400 (Bad Request) - * status code and then close the connection. - */ - SET_ERRNO(HPE_INVALID_TRANSFER_ENCODING); - RETURN(p - data); /* Error */ - } else { - /* RFC 7230 3.3.3 */ - - /* If a Transfer-Encoding header field is present in a response and - * the chunked transfer coding is not the final encoding, the - * message body length is determined by reading the connection until - * it is closed by the server. - */ - UPDATE_STATE(s_body_identity_eof); - } - } else { - if (parser->content_length == 0) { - /* Content-Length header given but zero: Content-Length: 0\r\n */ - UPDATE_STATE(NEW_MESSAGE()); - CALLBACK_NOTIFY(message_complete); - } else if (parser->content_length != ULLONG_MAX) { - /* Content-Length header given and non-zero */ - UPDATE_STATE(s_body_identity); - } else { - if (!http_message_needs_eof(parser)) { - /* Assume content-length 0 - read the next */ - UPDATE_STATE(NEW_MESSAGE()); - CALLBACK_NOTIFY(message_complete); - } else { - /* Read body until EOF */ - UPDATE_STATE(s_body_identity_eof); - } - } - } - - break; - } - - case s_body_identity: - { - uint64_t to_read = MIN(parser->content_length, - (uint64_t) ((data + len) - p)); - - assert(parser->content_length != 0 - && parser->content_length != ULLONG_MAX); - - /* The difference between advancing content_length and p is because - * the latter will automaticaly advance on the next loop iteration. - * Further, if content_length ends up at 0, we want to see the last - * byte again for our message complete callback. - */ - MARK(body); - parser->content_length -= to_read; - p += to_read - 1; - - if (parser->content_length == 0) { - UPDATE_STATE(s_message_done); - - /* Mimic CALLBACK_DATA_NOADVANCE() but with one extra byte. - * - * The alternative to doing this is to wait for the next byte to - * trigger the data callback, just as in every other case. The - * problem with this is that this makes it difficult for the test - * harness to distinguish between complete-on-EOF and - * complete-on-length. It's not clear that this distinction is - * important for applications, but let's keep it for now. - */ - CALLBACK_DATA_(body, p - body_mark + 1, p - data); - REEXECUTE(); - } - - break; - } - - /* read until EOF */ - case s_body_identity_eof: - MARK(body); - p = data + len - 1; - - break; - - case s_message_done: - UPDATE_STATE(NEW_MESSAGE()); - CALLBACK_NOTIFY(message_complete); - if (parser->upgrade) { - /* Exit, the rest of the message is in a different protocol. */ - RETURN((p - data) + 1); - } - break; - - case s_chunk_size_start: - { - assert(nread == 1); - assert(parser->flags & F_CHUNKED); - - unhex_val = unhex[(unsigned char)ch]; - if (UNLIKELY(unhex_val == -1)) { - SET_ERRNO(HPE_INVALID_CHUNK_SIZE); - goto error; - } - - parser->content_length = unhex_val; - UPDATE_STATE(s_chunk_size); - break; - } - - case s_chunk_size: - { - uint64_t t; - - assert(parser->flags & F_CHUNKED); - - if (ch == CR) { - UPDATE_STATE(s_chunk_size_almost_done); - break; - } - - unhex_val = unhex[(unsigned char)ch]; - - if (unhex_val == -1) { - if (ch == ';' || ch == ' ') { - UPDATE_STATE(s_chunk_parameters); - break; - } - - SET_ERRNO(HPE_INVALID_CHUNK_SIZE); - goto error; - } - - t = parser->content_length; - t *= 16; - t += unhex_val; - - /* Overflow? Test against a conservative limit for simplicity. */ - if (UNLIKELY((ULLONG_MAX - 16) / 16 < parser->content_length)) { - SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); - goto error; - } - - parser->content_length = t; - break; - } - - case s_chunk_parameters: - { - assert(parser->flags & F_CHUNKED); - /* just ignore this shit. TODO check for overflow */ - if (ch == CR) { - UPDATE_STATE(s_chunk_size_almost_done); - break; - } - break; - } - - case s_chunk_size_almost_done: - { - assert(parser->flags & F_CHUNKED); - STRICT_CHECK(ch != LF); - - parser->nread = 0; - nread = 0; - - if (parser->content_length == 0) { - parser->flags |= F_TRAILING; - UPDATE_STATE(s_header_field_start); - } else { - UPDATE_STATE(s_chunk_data); - } - CALLBACK_NOTIFY(chunk_header); - break; - } - - case s_chunk_data: - { - uint64_t to_read = MIN(parser->content_length, - (uint64_t) ((data + len) - p)); - - assert(parser->flags & F_CHUNKED); - assert(parser->content_length != 0 - && parser->content_length != ULLONG_MAX); - - /* See the explanation in s_body_identity for why the content - * length and data pointers are managed this way. - */ - MARK(body); - parser->content_length -= to_read; - p += to_read - 1; - - if (parser->content_length == 0) { - UPDATE_STATE(s_chunk_data_almost_done); - } - - break; - } - - case s_chunk_data_almost_done: - assert(parser->flags & F_CHUNKED); - assert(parser->content_length == 0); - STRICT_CHECK(ch != CR); - UPDATE_STATE(s_chunk_data_done); - CALLBACK_DATA(body); - break; - - case s_chunk_data_done: - assert(parser->flags & F_CHUNKED); - STRICT_CHECK(ch != LF); - parser->nread = 0; - nread = 0; - UPDATE_STATE(s_chunk_size_start); - CALLBACK_NOTIFY(chunk_complete); - break; - - default: - assert(0 && "unhandled state"); - SET_ERRNO(HPE_INVALID_INTERNAL_STATE); - goto error; - } - } - - /* Run callbacks for any marks that we have leftover after we ran out of - * bytes. There should be at most one of these set, so it's OK to invoke - * them in series (unset marks will not result in callbacks). - * - * We use the NOADVANCE() variety of callbacks here because 'p' has already - * overflowed 'data' and this allows us to correct for the off-by-one that - * we'd otherwise have (since CALLBACK_DATA() is meant to be run with a 'p' - * value that's in-bounds). - */ - - assert(((header_field_mark ? 1 : 0) + - (header_value_mark ? 1 : 0) + - (url_mark ? 1 : 0) + - (body_mark ? 1 : 0) + - (status_mark ? 1 : 0)) <= 1); - - CALLBACK_DATA_NOADVANCE(header_field); - CALLBACK_DATA_NOADVANCE(header_value); - CALLBACK_DATA_NOADVANCE(url); - CALLBACK_DATA_NOADVANCE(body); - CALLBACK_DATA_NOADVANCE(status); - - RETURN(len); - -error: - if (HTTP_PARSER_ERRNO(parser) == HPE_OK) { - SET_ERRNO(HPE_UNKNOWN); - } - - RETURN(p - data); -} - - -/* Does the parser need to see an EOF to find the end of the message? */ -int -http_message_needs_eof (const http_parser *parser) -{ - if (parser->type == HTTP_REQUEST) { - return 0; - } - - /* See RFC 2616 section 4.4 */ - if (parser->status_code / 100 == 1 || /* 1xx e.g. Continue */ - parser->status_code == 204 || /* No Content */ - parser->status_code == 304 || /* Not Modified */ - parser->flags & F_SKIPBODY) { /* response to a HEAD request */ - return 0; - } - - /* RFC 7230 3.3.3, see `s_headers_almost_done` */ - if ((parser->extra_flags & (F_TRANSFER_ENCODING >> 8)) && - (parser->flags & F_CHUNKED) == 0) { - return 1; - } - - if ((parser->flags & F_CHUNKED) || parser->content_length != ULLONG_MAX) { - return 0; - } - - return 1; -} - - -int -http_should_keep_alive (const http_parser *parser) -{ - if (parser->http_major > 0 && parser->http_minor > 0) { - /* HTTP/1.1 */ - if (parser->flags & F_CONNECTION_CLOSE) { - return 0; - } - } else { - /* HTTP/1.0 or earlier */ - if (!(parser->flags & F_CONNECTION_KEEP_ALIVE)) { - return 0; - } - } - - return !http_message_needs_eof(parser); -} - - -const char * -http_method_str (enum http_method m) -{ - return ELEM_AT(method_strings, m, ""); -} - -const char * -http_status_str (enum http_status s) -{ - switch (s) { -#define XX(num, name, string) case HTTP_STATUS_##name: return #string; - HTTP_STATUS_MAP(XX) -#undef XX - default: return ""; - } -} - -void -http_parser_init (http_parser *parser, enum http_parser_type t) -{ - void *data = parser->data; /* preserve application data */ - memset(parser, 0, sizeof(*parser)); - parser->data = data; - parser->type = t; - parser->state = (t == HTTP_REQUEST ? s_start_req : (t == HTTP_RESPONSE ? s_start_res : s_start_req_or_res)); - parser->http_errno = HPE_OK; -} - -void -http_parser_settings_init(http_parser_settings *settings) -{ - memset(settings, 0, sizeof(*settings)); -} - -const char * -http_errno_name(enum http_errno err) { - assert(((size_t) err) < ARRAY_SIZE(http_strerror_tab)); - return http_strerror_tab[err].name; -} - -const char * -http_errno_description(enum http_errno err) { - assert(((size_t) err) < ARRAY_SIZE(http_strerror_tab)); - return http_strerror_tab[err].description; -} - -static enum http_host_state -http_parse_host_char(enum http_host_state s, const char ch) { - switch(s) { - case s_http_userinfo: - case s_http_userinfo_start: - if (ch == '@') { - return s_http_host_start; - } - - if (IS_USERINFO_CHAR(ch)) { - return s_http_userinfo; - } - break; - - case s_http_host_start: - if (ch == '[') { - return s_http_host_v6_start; - } - - if (IS_HOST_CHAR(ch)) { - return s_http_host; - } - - break; - - case s_http_host: - if (IS_HOST_CHAR(ch)) { - return s_http_host; - } - - /* fall through */ - case s_http_host_v6_end: - if (ch == ':') { - return s_http_host_port_start; - } - - break; - - case s_http_host_v6: - if (ch == ']') { - return s_http_host_v6_end; - } - - /* fall through */ - case s_http_host_v6_start: - if (IS_HEX(ch) || ch == ':' || ch == '.') { - return s_http_host_v6; - } - - if (s == s_http_host_v6 && ch == '%') { - return s_http_host_v6_zone_start; - } - break; - - case s_http_host_v6_zone: - if (ch == ']') { - return s_http_host_v6_end; - } - - /* fall through */ - case s_http_host_v6_zone_start: - /* RFC 6874 Zone ID consists of 1*( unreserved / pct-encoded) */ - if (IS_ALPHANUM(ch) || ch == '%' || ch == '.' || ch == '-' || ch == '_' || - ch == '~') { - return s_http_host_v6_zone; - } - break; - - case s_http_host_port: - case s_http_host_port_start: - if (IS_NUM(ch)) { - return s_http_host_port; - } - - break; - - default: - break; - } - return s_http_host_dead; -} - -static int -http_parse_host(const char * buf, struct http_parser_url *u, int found_at) { - enum http_host_state s; - - const char *p; - size_t buflen = u->field_data[UF_HOST].off + u->field_data[UF_HOST].len; - - assert(u->field_set & (1 << UF_HOST)); - - u->field_data[UF_HOST].len = 0; - - s = found_at ? s_http_userinfo_start : s_http_host_start; - - for (p = buf + u->field_data[UF_HOST].off; p < buf + buflen; p++) { - enum http_host_state new_s = http_parse_host_char(s, *p); - - if (new_s == s_http_host_dead) { - return 1; - } - - switch(new_s) { - case s_http_host: - if (s != s_http_host) { - u->field_data[UF_HOST].off = (uint16_t)(p - buf); - } - u->field_data[UF_HOST].len++; - break; - - case s_http_host_v6: - if (s != s_http_host_v6) { - u->field_data[UF_HOST].off = (uint16_t)(p - buf); - } - u->field_data[UF_HOST].len++; - break; - - case s_http_host_v6_zone_start: - case s_http_host_v6_zone: - u->field_data[UF_HOST].len++; - break; - - case s_http_host_port: - if (s != s_http_host_port) { - u->field_data[UF_PORT].off = (uint16_t)(p - buf); - u->field_data[UF_PORT].len = 0; - u->field_set |= (1 << UF_PORT); - } - u->field_data[UF_PORT].len++; - break; - - case s_http_userinfo: - if (s != s_http_userinfo) { - u->field_data[UF_USERINFO].off = (uint16_t)(p - buf); - u->field_data[UF_USERINFO].len = 0; - u->field_set |= (1 << UF_USERINFO); - } - u->field_data[UF_USERINFO].len++; - break; - - default: - break; - } - s = new_s; - } - - /* Make sure we don't end somewhere unexpected */ - switch (s) { - case s_http_host_start: - case s_http_host_v6_start: - case s_http_host_v6: - case s_http_host_v6_zone_start: - case s_http_host_v6_zone: - case s_http_host_port_start: - case s_http_userinfo: - case s_http_userinfo_start: - return 1; - default: - break; - } - - return 0; -} - -void -http_parser_url_init(struct http_parser_url *u) { - memset(u, 0, sizeof(*u)); -} - -int -http_parser_parse_url(const char *buf, size_t buflen, int is_connect, - struct http_parser_url *u) -{ - enum state s; - const char *p; - enum http_parser_url_fields uf, old_uf; - int found_at = 0; - - if (buflen == 0) { - return 1; - } - - u->port = u->field_set = 0; - s = is_connect ? s_req_server_start : s_req_spaces_before_url; - old_uf = UF_MAX; - - for (p = buf; p < buf + buflen; p++) { - s = parse_url_char(s, *p); - - /* Figure out the next field that we're operating on */ - switch (s) { - case s_dead: - return 1; - - /* Skip delimeters */ - case s_req_schema_slash: - case s_req_schema_slash_slash: - case s_req_server_start: - case s_req_query_string_start: - case s_req_fragment_start: - continue; - - case s_req_schema: - uf = UF_SCHEMA; - break; - - case s_req_server_with_at: - found_at = 1; - - /* fall through */ - case s_req_server: - uf = UF_HOST; - break; - - case s_req_path: - uf = UF_PATH; - break; - - case s_req_query_string: - uf = UF_QUERY; - break; - - case s_req_fragment: - uf = UF_FRAGMENT; - break; - - default: - assert(!"Unexpected state"); - return 1; - } - - /* Nothing's changed; soldier on */ - if (uf == old_uf) { - u->field_data[uf].len++; - continue; - } - - u->field_data[uf].off = (uint16_t)(p - buf); - u->field_data[uf].len = 1; - - u->field_set |= (1 << uf); - old_uf = uf; - } - - /* host must be present if there is a schema */ - /* parsing http:///toto will fail */ - if ((u->field_set & (1 << UF_SCHEMA)) && - (u->field_set & (1 << UF_HOST)) == 0) { - return 1; - } - - if (u->field_set & (1 << UF_HOST)) { - if (http_parse_host(buf, u, found_at) != 0) { - return 1; - } - } - - /* CONNECT requests can only contain "hostname:port" */ - if (is_connect && u->field_set != ((1 << UF_HOST)|(1 << UF_PORT))) { - return 1; - } - - if (u->field_set & (1 << UF_PORT)) { - uint16_t off; - uint16_t len; - const char* p; - const char* end; - unsigned long v; - - off = u->field_data[UF_PORT].off; - len = u->field_data[UF_PORT].len; - end = buf + off + len; - - /* NOTE: The characters are already validated and are in the [0-9] range */ - assert(off + len <= buflen && "Port number overflow"); - v = 0; - for (p = buf + off; p < end; p++) { - v *= 10; - v += *p - '0'; - - /* Ports have a max value of 2^16 */ - if (v > 0xffff) { - return 1; - } - } - - u->port = (uint16_t) v; - } - - return 0; -} - -void -http_parser_pause(http_parser *parser, int paused) { - /* Users should only be pausing/unpausing a parser that is not in an error - * state. In non-debug builds, there's not much that we can do about this - * other than ignore it. - */ - if (HTTP_PARSER_ERRNO(parser) == HPE_OK || - HTTP_PARSER_ERRNO(parser) == HPE_PAUSED) { - uint32_t nread = parser->nread; /* used by the SET_ERRNO macro */ - SET_ERRNO((paused) ? HPE_PAUSED : HPE_OK); - } else { - assert(0 && "Attempting to pause parser in error state"); - } -} - -int -http_body_is_final(const struct http_parser *parser) { - return parser->state == s_message_done; -} - -unsigned long -http_parser_version(void) { - return HTTP_PARSER_VERSION_MAJOR * 0x10000 | - HTTP_PARSER_VERSION_MINOR * 0x00100 | - HTTP_PARSER_VERSION_PATCH * 0x00001; -} - -void -http_parser_set_max_header_size(uint32_t size) { - max_header_size = size; -} diff --git a/vendor/http-parser/http_parser.gyp b/vendor/http-parser/http_parser.gyp deleted file mode 100644 index ef34eca..0000000 --- a/vendor/http-parser/http_parser.gyp +++ /dev/null @@ -1,111 +0,0 @@ -# This file is used with the GYP meta build system. -# http://code.google.com/p/gyp/ -# To build try this: -# svn co http://gyp.googlecode.com/svn/trunk gyp -# ./gyp/gyp -f make --depth=`pwd` http_parser.gyp -# ./out/Debug/test -{ - 'target_defaults': { - 'default_configuration': 'Debug', - 'configurations': { - # TODO: hoist these out and put them somewhere common, because - # RuntimeLibrary MUST MATCH across the entire project - 'Debug': { - 'defines': [ 'DEBUG', '_DEBUG' ], - 'cflags': [ '-Wall', '-Wextra', '-O0', '-g', '-ftrapv' ], - 'msvs_settings': { - 'VCCLCompilerTool': { - 'RuntimeLibrary': 1, # static debug - }, - }, - }, - 'Release': { - 'defines': [ 'NDEBUG' ], - 'cflags': [ '-Wall', '-Wextra', '-O3' ], - 'msvs_settings': { - 'VCCLCompilerTool': { - 'RuntimeLibrary': 0, # static release - }, - }, - } - }, - 'msvs_settings': { - 'VCCLCompilerTool': { - }, - 'VCLibrarianTool': { - }, - 'VCLinkerTool': { - 'GenerateDebugInformation': 'true', - }, - }, - 'conditions': [ - ['OS == "win"', { - 'defines': [ - 'WIN32' - ], - }] - ], - }, - - 'targets': [ - { - 'target_name': 'http_parser', - 'type': 'static_library', - 'include_dirs': [ '.' ], - 'direct_dependent_settings': { - 'defines': [ 'HTTP_PARSER_STRICT=0' ], - 'include_dirs': [ '.' ], - }, - 'defines': [ 'HTTP_PARSER_STRICT=0' ], - 'sources': [ './http_parser.c', ], - 'conditions': [ - ['OS=="win"', { - 'msvs_settings': { - 'VCCLCompilerTool': { - # Compile as C++. http_parser.c is actually C99, but C++ is - # close enough in this case. - 'CompileAs': 2, - }, - }, - }] - ], - }, - - { - 'target_name': 'http_parser_strict', - 'type': 'static_library', - 'include_dirs': [ '.' ], - 'direct_dependent_settings': { - 'defines': [ 'HTTP_PARSER_STRICT=1' ], - 'include_dirs': [ '.' ], - }, - 'defines': [ 'HTTP_PARSER_STRICT=1' ], - 'sources': [ './http_parser.c', ], - 'conditions': [ - ['OS=="win"', { - 'msvs_settings': { - 'VCCLCompilerTool': { - # Compile as C++. http_parser.c is actually C99, but C++ is - # close enough in this case. - 'CompileAs': 2, - }, - }, - }] - ], - }, - - { - 'target_name': 'test-nonstrict', - 'type': 'executable', - 'dependencies': [ 'http_parser' ], - 'sources': [ 'test.c' ] - }, - - { - 'target_name': 'test-strict', - 'type': 'executable', - 'dependencies': [ 'http_parser_strict' ], - 'sources': [ 'test.c' ] - } - ] -} diff --git a/vendor/http-parser/http_parser.h b/vendor/http-parser/http_parser.h deleted file mode 100644 index df88252..0000000 --- a/vendor/http-parser/http_parser.h +++ /dev/null @@ -1,443 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ -#ifndef http_parser_h -#define http_parser_h -#ifdef __cplusplus -extern "C" { -#endif - -/* Also update SONAME in the Makefile whenever you change these. */ -#define HTTP_PARSER_VERSION_MAJOR 2 -#define HTTP_PARSER_VERSION_MINOR 9 -#define HTTP_PARSER_VERSION_PATCH 4 - -#include -#if defined(_WIN32) && !defined(__MINGW32__) && \ - (!defined(_MSC_VER) || _MSC_VER<1600) && !defined(__WINE__) -#include -typedef __int8 int8_t; -typedef unsigned __int8 uint8_t; -typedef __int16 int16_t; -typedef unsigned __int16 uint16_t; -typedef __int32 int32_t; -typedef unsigned __int32 uint32_t; -typedef __int64 int64_t; -typedef unsigned __int64 uint64_t; -#else -#include -#endif - -/* Compile with -DHTTP_PARSER_STRICT=0 to make less checks, but run - * faster - */ -#ifndef HTTP_PARSER_STRICT -# define HTTP_PARSER_STRICT 1 -#endif - -/* Maximium header size allowed. If the macro is not defined - * before including this header then the default is used. To - * change the maximum header size, define the macro in the build - * environment (e.g. -DHTTP_MAX_HEADER_SIZE=). To remove - * the effective limit on the size of the header, define the macro - * to a very large number (e.g. -DHTTP_MAX_HEADER_SIZE=0x7fffffff) - */ -#ifndef HTTP_MAX_HEADER_SIZE -# define HTTP_MAX_HEADER_SIZE (80*1024) -#endif - -typedef struct http_parser http_parser; -typedef struct http_parser_settings http_parser_settings; - - -/* Callbacks should return non-zero to indicate an error. The parser will - * then halt execution. - * - * The one exception is on_headers_complete. In a HTTP_RESPONSE parser - * returning '1' from on_headers_complete will tell the parser that it - * should not expect a body. This is used when receiving a response to a - * HEAD request which may contain 'Content-Length' or 'Transfer-Encoding: - * chunked' headers that indicate the presence of a body. - * - * Returning `2` from on_headers_complete will tell parser that it should not - * expect neither a body nor any futher responses on this connection. This is - * useful for handling responses to a CONNECT request which may not contain - * `Upgrade` or `Connection: upgrade` headers. - * - * http_data_cb does not return data chunks. It will be called arbitrarily - * many times for each string. E.G. you might get 10 callbacks for "on_url" - * each providing just a few characters more data. - */ -typedef int (*http_data_cb) (http_parser*, const char *at, size_t length); -typedef int (*http_cb) (http_parser*); - - -/* Status Codes */ -#define HTTP_STATUS_MAP(XX) \ - XX(100, CONTINUE, Continue) \ - XX(101, SWITCHING_PROTOCOLS, Switching Protocols) \ - XX(102, PROCESSING, Processing) \ - XX(200, OK, OK) \ - XX(201, CREATED, Created) \ - XX(202, ACCEPTED, Accepted) \ - XX(203, NON_AUTHORITATIVE_INFORMATION, Non-Authoritative Information) \ - XX(204, NO_CONTENT, No Content) \ - XX(205, RESET_CONTENT, Reset Content) \ - XX(206, PARTIAL_CONTENT, Partial Content) \ - XX(207, MULTI_STATUS, Multi-Status) \ - XX(208, ALREADY_REPORTED, Already Reported) \ - XX(226, IM_USED, IM Used) \ - XX(300, MULTIPLE_CHOICES, Multiple Choices) \ - XX(301, MOVED_PERMANENTLY, Moved Permanently) \ - XX(302, FOUND, Found) \ - XX(303, SEE_OTHER, See Other) \ - XX(304, NOT_MODIFIED, Not Modified) \ - XX(305, USE_PROXY, Use Proxy) \ - XX(307, TEMPORARY_REDIRECT, Temporary Redirect) \ - XX(308, PERMANENT_REDIRECT, Permanent Redirect) \ - XX(400, BAD_REQUEST, Bad Request) \ - XX(401, UNAUTHORIZED, Unauthorized) \ - XX(402, PAYMENT_REQUIRED, Payment Required) \ - XX(403, FORBIDDEN, Forbidden) \ - XX(404, NOT_FOUND, Not Found) \ - XX(405, METHOD_NOT_ALLOWED, Method Not Allowed) \ - XX(406, NOT_ACCEPTABLE, Not Acceptable) \ - XX(407, PROXY_AUTHENTICATION_REQUIRED, Proxy Authentication Required) \ - XX(408, REQUEST_TIMEOUT, Request Timeout) \ - XX(409, CONFLICT, Conflict) \ - XX(410, GONE, Gone) \ - XX(411, LENGTH_REQUIRED, Length Required) \ - XX(412, PRECONDITION_FAILED, Precondition Failed) \ - XX(413, PAYLOAD_TOO_LARGE, Payload Too Large) \ - XX(414, URI_TOO_LONG, URI Too Long) \ - XX(415, UNSUPPORTED_MEDIA_TYPE, Unsupported Media Type) \ - XX(416, RANGE_NOT_SATISFIABLE, Range Not Satisfiable) \ - XX(417, EXPECTATION_FAILED, Expectation Failed) \ - XX(421, MISDIRECTED_REQUEST, Misdirected Request) \ - XX(422, UNPROCESSABLE_ENTITY, Unprocessable Entity) \ - XX(423, LOCKED, Locked) \ - XX(424, FAILED_DEPENDENCY, Failed Dependency) \ - XX(426, UPGRADE_REQUIRED, Upgrade Required) \ - XX(428, PRECONDITION_REQUIRED, Precondition Required) \ - XX(429, TOO_MANY_REQUESTS, Too Many Requests) \ - XX(431, REQUEST_HEADER_FIELDS_TOO_LARGE, Request Header Fields Too Large) \ - XX(451, UNAVAILABLE_FOR_LEGAL_REASONS, Unavailable For Legal Reasons) \ - XX(500, INTERNAL_SERVER_ERROR, Internal Server Error) \ - XX(501, NOT_IMPLEMENTED, Not Implemented) \ - XX(502, BAD_GATEWAY, Bad Gateway) \ - XX(503, SERVICE_UNAVAILABLE, Service Unavailable) \ - XX(504, GATEWAY_TIMEOUT, Gateway Timeout) \ - XX(505, HTTP_VERSION_NOT_SUPPORTED, HTTP Version Not Supported) \ - XX(506, VARIANT_ALSO_NEGOTIATES, Variant Also Negotiates) \ - XX(507, INSUFFICIENT_STORAGE, Insufficient Storage) \ - XX(508, LOOP_DETECTED, Loop Detected) \ - XX(510, NOT_EXTENDED, Not Extended) \ - XX(511, NETWORK_AUTHENTICATION_REQUIRED, Network Authentication Required) \ - -enum http_status - { -#define XX(num, name, string) HTTP_STATUS_##name = num, - HTTP_STATUS_MAP(XX) -#undef XX - }; - - -/* Request Methods */ -#define HTTP_METHOD_MAP(XX) \ - XX(0, DELETE, DELETE) \ - XX(1, GET, GET) \ - XX(2, HEAD, HEAD) \ - XX(3, POST, POST) \ - XX(4, PUT, PUT) \ - /* pathological */ \ - XX(5, CONNECT, CONNECT) \ - XX(6, OPTIONS, OPTIONS) \ - XX(7, TRACE, TRACE) \ - /* WebDAV */ \ - XX(8, COPY, COPY) \ - XX(9, LOCK, LOCK) \ - XX(10, MKCOL, MKCOL) \ - XX(11, MOVE, MOVE) \ - XX(12, PROPFIND, PROPFIND) \ - XX(13, PROPPATCH, PROPPATCH) \ - XX(14, SEARCH, SEARCH) \ - XX(15, UNLOCK, UNLOCK) \ - XX(16, BIND, BIND) \ - XX(17, REBIND, REBIND) \ - XX(18, UNBIND, UNBIND) \ - XX(19, ACL, ACL) \ - /* subversion */ \ - XX(20, REPORT, REPORT) \ - XX(21, MKACTIVITY, MKACTIVITY) \ - XX(22, CHECKOUT, CHECKOUT) \ - XX(23, MERGE, MERGE) \ - /* upnp */ \ - XX(24, MSEARCH, M-SEARCH) \ - XX(25, NOTIFY, NOTIFY) \ - XX(26, SUBSCRIBE, SUBSCRIBE) \ - XX(27, UNSUBSCRIBE, UNSUBSCRIBE) \ - /* RFC-5789 */ \ - XX(28, PATCH, PATCH) \ - XX(29, PURGE, PURGE) \ - /* CalDAV */ \ - XX(30, MKCALENDAR, MKCALENDAR) \ - /* RFC-2068, section 19.6.1.2 */ \ - XX(31, LINK, LINK) \ - XX(32, UNLINK, UNLINK) \ - /* icecast */ \ - XX(33, SOURCE, SOURCE) \ - -enum http_method - { -#define XX(num, name, string) HTTP_##name = num, - HTTP_METHOD_MAP(XX) -#undef XX - }; - - -enum http_parser_type { HTTP_REQUEST, HTTP_RESPONSE, HTTP_BOTH }; - - -/* Flag values for http_parser.flags field */ -enum flags - { F_CHUNKED = 1 << 0 - , F_CONNECTION_KEEP_ALIVE = 1 << 1 - , F_CONNECTION_CLOSE = 1 << 2 - , F_CONNECTION_UPGRADE = 1 << 3 - , F_TRAILING = 1 << 4 - , F_UPGRADE = 1 << 5 - , F_SKIPBODY = 1 << 6 - , F_CONTENTLENGTH = 1 << 7 - , F_TRANSFER_ENCODING = 1 << 8 /* Never set in http_parser.flags */ - }; - - -/* Map for errno-related constants - * - * The provided argument should be a macro that takes 2 arguments. - */ -#define HTTP_ERRNO_MAP(XX) \ - /* No error */ \ - XX(OK, "success") \ - \ - /* Callback-related errors */ \ - XX(CB_message_begin, "the on_message_begin callback failed") \ - XX(CB_url, "the on_url callback failed") \ - XX(CB_header_field, "the on_header_field callback failed") \ - XX(CB_header_value, "the on_header_value callback failed") \ - XX(CB_headers_complete, "the on_headers_complete callback failed") \ - XX(CB_body, "the on_body callback failed") \ - XX(CB_message_complete, "the on_message_complete callback failed") \ - XX(CB_status, "the on_status callback failed") \ - XX(CB_chunk_header, "the on_chunk_header callback failed") \ - XX(CB_chunk_complete, "the on_chunk_complete callback failed") \ - \ - /* Parsing-related errors */ \ - XX(INVALID_EOF_STATE, "stream ended at an unexpected time") \ - XX(HEADER_OVERFLOW, \ - "too many header bytes seen; overflow detected") \ - XX(CLOSED_CONNECTION, \ - "data received after completed connection: close message") \ - XX(INVALID_VERSION, "invalid HTTP version") \ - XX(INVALID_STATUS, "invalid HTTP status code") \ - XX(INVALID_METHOD, "invalid HTTP method") \ - XX(INVALID_URL, "invalid URL") \ - XX(INVALID_HOST, "invalid host") \ - XX(INVALID_PORT, "invalid port") \ - XX(INVALID_PATH, "invalid path") \ - XX(INVALID_QUERY_STRING, "invalid query string") \ - XX(INVALID_FRAGMENT, "invalid fragment") \ - XX(LF_EXPECTED, "LF character expected") \ - XX(INVALID_HEADER_TOKEN, "invalid character in header") \ - XX(INVALID_CONTENT_LENGTH, \ - "invalid character in content-length header") \ - XX(UNEXPECTED_CONTENT_LENGTH, \ - "unexpected content-length header") \ - XX(INVALID_CHUNK_SIZE, \ - "invalid character in chunk size header") \ - XX(INVALID_CONSTANT, "invalid constant string") \ - XX(INVALID_INTERNAL_STATE, "encountered unexpected internal state")\ - XX(STRICT, "strict mode assertion failed") \ - XX(PAUSED, "parser is paused") \ - XX(UNKNOWN, "an unknown error occurred") \ - XX(INVALID_TRANSFER_ENCODING, \ - "request has invalid transfer-encoding") \ - - -/* Define HPE_* values for each errno value above */ -#define HTTP_ERRNO_GEN(n, s) HPE_##n, -enum http_errno { - HTTP_ERRNO_MAP(HTTP_ERRNO_GEN) -}; -#undef HTTP_ERRNO_GEN - - -/* Get an http_errno value from an http_parser */ -#define HTTP_PARSER_ERRNO(p) ((enum http_errno) (p)->http_errno) - - -struct http_parser { - /** PRIVATE **/ - unsigned int type : 2; /* enum http_parser_type */ - unsigned int flags : 8; /* F_* values from 'flags' enum; semi-public */ - unsigned int state : 7; /* enum state from http_parser.c */ - unsigned int header_state : 7; /* enum header_state from http_parser.c */ - unsigned int index : 5; /* index into current matcher */ - unsigned int extra_flags : 2; - unsigned int lenient_http_headers : 1; - - uint32_t nread; /* # bytes read in various scenarios */ - uint64_t content_length; /* # bytes in body (0 if no Content-Length header) */ - - /** READ-ONLY **/ - unsigned short http_major; - unsigned short http_minor; - unsigned int status_code : 16; /* responses only */ - unsigned int method : 8; /* requests only */ - unsigned int http_errno : 7; - - /* 1 = Upgrade header was present and the parser has exited because of that. - * 0 = No upgrade header present. - * Should be checked when http_parser_execute() returns in addition to - * error checking. - */ - unsigned int upgrade : 1; - - /** PUBLIC **/ - void *data; /* A pointer to get hook to the "connection" or "socket" object */ -}; - - -struct http_parser_settings { - http_cb on_message_begin; - http_data_cb on_url; - http_data_cb on_status; - http_data_cb on_header_field; - http_data_cb on_header_value; - http_cb on_headers_complete; - http_data_cb on_body; - http_cb on_message_complete; - /* When on_chunk_header is called, the current chunk length is stored - * in parser->content_length. - */ - http_cb on_chunk_header; - http_cb on_chunk_complete; -}; - - -enum http_parser_url_fields - { UF_SCHEMA = 0 - , UF_HOST = 1 - , UF_PORT = 2 - , UF_PATH = 3 - , UF_QUERY = 4 - , UF_FRAGMENT = 5 - , UF_USERINFO = 6 - , UF_MAX = 7 - }; - - -/* Result structure for http_parser_parse_url(). - * - * Callers should index into field_data[] with UF_* values iff field_set - * has the relevant (1 << UF_*) bit set. As a courtesy to clients (and - * because we probably have padding left over), we convert any port to - * a uint16_t. - */ -struct http_parser_url { - uint16_t field_set; /* Bitmask of (1 << UF_*) values */ - uint16_t port; /* Converted UF_PORT string */ - - struct { - uint16_t off; /* Offset into buffer in which field starts */ - uint16_t len; /* Length of run in buffer */ - } field_data[UF_MAX]; -}; - - -/* Returns the library version. Bits 16-23 contain the major version number, - * bits 8-15 the minor version number and bits 0-7 the patch level. - * Usage example: - * - * unsigned long version = http_parser_version(); - * unsigned major = (version >> 16) & 255; - * unsigned minor = (version >> 8) & 255; - * unsigned patch = version & 255; - * printf("http_parser v%u.%u.%u\n", major, minor, patch); - */ -unsigned long http_parser_version(void); - -void http_parser_init(http_parser *parser, enum http_parser_type type); - - -/* Initialize http_parser_settings members to 0 - */ -void http_parser_settings_init(http_parser_settings *settings); - - -/* Executes the parser. Returns number of parsed bytes. Sets - * `parser->http_errno` on error. */ -size_t http_parser_execute(http_parser *parser, - const http_parser_settings *settings, - const char *data, - size_t len); - - -/* If http_should_keep_alive() in the on_headers_complete or - * on_message_complete callback returns 0, then this should be - * the last message on the connection. - * If you are the server, respond with the "Connection: close" header. - * If you are the client, close the connection. - */ -int http_should_keep_alive(const http_parser *parser); - -/* Returns a string version of the HTTP method. */ -const char *http_method_str(enum http_method m); - -/* Returns a string version of the HTTP status code. */ -const char *http_status_str(enum http_status s); - -/* Return a string name of the given error */ -const char *http_errno_name(enum http_errno err); - -/* Return a string description of the given error */ -const char *http_errno_description(enum http_errno err); - -/* Initialize all http_parser_url members to 0 */ -void http_parser_url_init(struct http_parser_url *u); - -/* Parse a URL; return nonzero on failure */ -int http_parser_parse_url(const char *buf, size_t buflen, - int is_connect, - struct http_parser_url *u); - -/* Pause or un-pause the parser; a nonzero value pauses */ -void http_parser_pause(http_parser *parser, int paused); - -/* Checks if this is the final chunk of the body. */ -int http_body_is_final(const http_parser *parser); - -/* Change the maximum header size provided at compile time. */ -void http_parser_set_max_header_size(uint32_t size); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/vendor/http-parser/test.c b/vendor/http-parser/test.c deleted file mode 100644 index 7983424..0000000 --- a/vendor/http-parser/test.c +++ /dev/null @@ -1,4600 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ -#include "http_parser.h" -#include -#include -#include -#include /* rand */ -#include -#include - -#if defined(__APPLE__) -# undef strlncpy -#endif /* defined(__APPLE__) */ - -#undef TRUE -#define TRUE 1 -#undef FALSE -#define FALSE 0 - -#define MAX_HEADERS 13 -#define MAX_ELEMENT_SIZE 2048 -#define MAX_CHUNKS 16 - -#define MIN(a,b) ((a) < (b) ? (a) : (b)) - -#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*x)) - -static http_parser parser; - -struct message { - const char *name; // for debugging purposes - const char *raw; - enum http_parser_type type; - enum http_method method; - int status_code; - char response_status[MAX_ELEMENT_SIZE]; - char request_path[MAX_ELEMENT_SIZE]; - char request_url[MAX_ELEMENT_SIZE]; - char fragment[MAX_ELEMENT_SIZE]; - char query_string[MAX_ELEMENT_SIZE]; - char body[MAX_ELEMENT_SIZE]; - size_t body_size; - const char *host; - const char *userinfo; - uint16_t port; - int num_headers; - enum { NONE=0, FIELD, VALUE } last_header_element; - char headers [MAX_HEADERS][2][MAX_ELEMENT_SIZE]; - int should_keep_alive; - - int num_chunks; - int num_chunks_complete; - int chunk_lengths[MAX_CHUNKS]; - - const char *upgrade; // upgraded body - - unsigned short http_major; - unsigned short http_minor; - - int message_begin_cb_called; - int headers_complete_cb_called; - int message_complete_cb_called; - int status_cb_called; - int message_complete_on_eof; - int body_is_final; -}; - -static int currently_parsing_eof; - -static struct message messages[5]; -static int num_messages; -static http_parser_settings *current_pause_parser; - -/* * R E Q U E S T S * */ -const struct message requests[] = -#define CURL_GET 0 -{ {.name= "curl get" - ,.type= HTTP_REQUEST - ,.raw= "GET /test HTTP/1.1\r\n" - "User-Agent: curl/7.18.0 (i486-pc-linux-gnu) libcurl/7.18.0 OpenSSL/0.9.8g zlib/1.2.3.3 libidn/1.1\r\n" - "Host: 0.0.0.0=5000\r\n" - "Accept: */*\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_GET - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/test" - ,.request_url= "/test" - ,.num_headers= 3 - ,.headers= - { { "User-Agent", "curl/7.18.0 (i486-pc-linux-gnu) libcurl/7.18.0 OpenSSL/0.9.8g zlib/1.2.3.3 libidn/1.1" } - , { "Host", "0.0.0.0=5000" } - , { "Accept", "*/*" } - } - ,.body= "" - } - -#define FIREFOX_GET 1 -, {.name= "firefox get" - ,.type= HTTP_REQUEST - ,.raw= "GET /favicon.ico HTTP/1.1\r\n" - "Host: 0.0.0.0=5000\r\n" - "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9) Gecko/2008061015 Firefox/3.0\r\n" - "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n" - "Accept-Language: en-us,en;q=0.5\r\n" - "Accept-Encoding: gzip,deflate\r\n" - "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n" - "Keep-Alive: 300\r\n" - "Connection: keep-alive\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_GET - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/favicon.ico" - ,.request_url= "/favicon.ico" - ,.num_headers= 8 - ,.headers= - { { "Host", "0.0.0.0=5000" } - , { "User-Agent", "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9) Gecko/2008061015 Firefox/3.0" } - , { "Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" } - , { "Accept-Language", "en-us,en;q=0.5" } - , { "Accept-Encoding", "gzip,deflate" } - , { "Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.7" } - , { "Keep-Alive", "300" } - , { "Connection", "keep-alive" } - } - ,.body= "" - } - -#define DUMBLUCK 2 -, {.name= "dumbluck" - ,.type= HTTP_REQUEST - ,.raw= "GET /dumbluck HTTP/1.1\r\n" - "aaaaaaaaaaaaa:++++++++++\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_GET - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/dumbluck" - ,.request_url= "/dumbluck" - ,.num_headers= 1 - ,.headers= - { { "aaaaaaaaaaaaa", "++++++++++" } - } - ,.body= "" - } - -#define FRAGMENT_IN_URI 3 -, {.name= "fragment in url" - ,.type= HTTP_REQUEST - ,.raw= "GET /forums/1/topics/2375?page=1#posts-17408 HTTP/1.1\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_GET - ,.query_string= "page=1" - ,.fragment= "posts-17408" - ,.request_path= "/forums/1/topics/2375" - /* XXX request url does include fragment? */ - ,.request_url= "/forums/1/topics/2375?page=1#posts-17408" - ,.num_headers= 0 - ,.body= "" - } - -#define GET_NO_HEADERS_NO_BODY 4 -, {.name= "get no headers no body" - ,.type= HTTP_REQUEST - ,.raw= "GET /get_no_headers_no_body/world HTTP/1.1\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE /* would need Connection: close */ - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_GET - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/get_no_headers_no_body/world" - ,.request_url= "/get_no_headers_no_body/world" - ,.num_headers= 0 - ,.body= "" - } - -#define GET_ONE_HEADER_NO_BODY 5 -, {.name= "get one header no body" - ,.type= HTTP_REQUEST - ,.raw= "GET /get_one_header_no_body HTTP/1.1\r\n" - "Accept: */*\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE /* would need Connection: close */ - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_GET - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/get_one_header_no_body" - ,.request_url= "/get_one_header_no_body" - ,.num_headers= 1 - ,.headers= - { { "Accept" , "*/*" } - } - ,.body= "" - } - -#define GET_FUNKY_CONTENT_LENGTH 6 -, {.name= "get funky content length body hello" - ,.type= HTTP_REQUEST - ,.raw= "GET /get_funky_content_length_body_hello HTTP/1.0\r\n" - "conTENT-Length: 5\r\n" - "\r\n" - "HELLO" - ,.should_keep_alive= FALSE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 0 - ,.method= HTTP_GET - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/get_funky_content_length_body_hello" - ,.request_url= "/get_funky_content_length_body_hello" - ,.num_headers= 1 - ,.headers= - { { "conTENT-Length" , "5" } - } - ,.body= "HELLO" - } - -#define POST_IDENTITY_BODY_WORLD 7 -, {.name= "post identity body world" - ,.type= HTTP_REQUEST - ,.raw= "POST /post_identity_body_world?q=search#hey HTTP/1.1\r\n" - "Accept: */*\r\n" - "Content-Length: 5\r\n" - "\r\n" - "World" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_POST - ,.query_string= "q=search" - ,.fragment= "hey" - ,.request_path= "/post_identity_body_world" - ,.request_url= "/post_identity_body_world?q=search#hey" - ,.num_headers= 2 - ,.headers= - { { "Accept", "*/*" } - , { "Content-Length", "5" } - } - ,.body= "World" - } - -#define POST_CHUNKED_ALL_YOUR_BASE 8 -, {.name= "post - chunked body: all your base are belong to us" - ,.type= HTTP_REQUEST - ,.raw= "POST /post_chunked_all_your_base HTTP/1.1\r\n" - "Transfer-Encoding: chunked\r\n" - "\r\n" - "1e\r\nall your base are belong to us\r\n" - "0\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_POST - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/post_chunked_all_your_base" - ,.request_url= "/post_chunked_all_your_base" - ,.num_headers= 1 - ,.headers= - { { "Transfer-Encoding" , "chunked" } - } - ,.body= "all your base are belong to us" - ,.num_chunks_complete= 2 - ,.chunk_lengths= { 0x1e } - } - -#define TWO_CHUNKS_MULT_ZERO_END 9 -, {.name= "two chunks ; triple zero ending" - ,.type= HTTP_REQUEST - ,.raw= "POST /two_chunks_mult_zero_end HTTP/1.1\r\n" - "Transfer-Encoding: chunked\r\n" - "\r\n" - "5\r\nhello\r\n" - "6\r\n world\r\n" - "000\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_POST - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/two_chunks_mult_zero_end" - ,.request_url= "/two_chunks_mult_zero_end" - ,.num_headers= 1 - ,.headers= - { { "Transfer-Encoding", "chunked" } - } - ,.body= "hello world" - ,.num_chunks_complete= 3 - ,.chunk_lengths= { 5, 6 } - } - -#define CHUNKED_W_TRAILING_HEADERS 10 -, {.name= "chunked with trailing headers. blech." - ,.type= HTTP_REQUEST - ,.raw= "POST /chunked_w_trailing_headers HTTP/1.1\r\n" - "Transfer-Encoding: chunked\r\n" - "\r\n" - "5\r\nhello\r\n" - "6\r\n world\r\n" - "0\r\n" - "Vary: *\r\n" - "Content-Type: text/plain\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_POST - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/chunked_w_trailing_headers" - ,.request_url= "/chunked_w_trailing_headers" - ,.num_headers= 3 - ,.headers= - { { "Transfer-Encoding", "chunked" } - , { "Vary", "*" } - , { "Content-Type", "text/plain" } - } - ,.body= "hello world" - ,.num_chunks_complete= 3 - ,.chunk_lengths= { 5, 6 } - } - -#define CHUNKED_W_NONSENSE_AFTER_LENGTH 11 -, {.name= "with nonsense after the length" - ,.type= HTTP_REQUEST - ,.raw= "POST /chunked_w_nonsense_after_length HTTP/1.1\r\n" - "Transfer-Encoding: chunked\r\n" - "\r\n" - "5; ilovew3;whattheluck=aretheseparametersfor\r\nhello\r\n" - "6; blahblah; blah\r\n world\r\n" - "0\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_POST - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/chunked_w_nonsense_after_length" - ,.request_url= "/chunked_w_nonsense_after_length" - ,.num_headers= 1 - ,.headers= - { { "Transfer-Encoding", "chunked" } - } - ,.body= "hello world" - ,.num_chunks_complete= 3 - ,.chunk_lengths= { 5, 6 } - } - -#define WITH_QUOTES 12 -, {.name= "with quotes" - ,.type= HTTP_REQUEST - ,.raw= "GET /with_\"stupid\"_quotes?foo=\"bar\" HTTP/1.1\r\n\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_GET - ,.query_string= "foo=\"bar\"" - ,.fragment= "" - ,.request_path= "/with_\"stupid\"_quotes" - ,.request_url= "/with_\"stupid\"_quotes?foo=\"bar\"" - ,.num_headers= 0 - ,.headers= { } - ,.body= "" - } - -#define APACHEBENCH_GET 13 -/* The server receiving this request SHOULD NOT wait for EOF - * to know that content-length == 0. - * How to represent this in a unit test? message_complete_on_eof - * Compare with NO_CONTENT_LENGTH_RESPONSE. - */ -, {.name = "apachebench get" - ,.type= HTTP_REQUEST - ,.raw= "GET /test HTTP/1.0\r\n" - "Host: 0.0.0.0:5000\r\n" - "User-Agent: ApacheBench/2.3\r\n" - "Accept: */*\r\n\r\n" - ,.should_keep_alive= FALSE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 0 - ,.method= HTTP_GET - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/test" - ,.request_url= "/test" - ,.num_headers= 3 - ,.headers= { { "Host", "0.0.0.0:5000" } - , { "User-Agent", "ApacheBench/2.3" } - , { "Accept", "*/*" } - } - ,.body= "" - } - -#define QUERY_URL_WITH_QUESTION_MARK_GET 14 -/* Some clients include '?' characters in query strings. - */ -, {.name = "query url with question mark" - ,.type= HTTP_REQUEST - ,.raw= "GET /test.cgi?foo=bar?baz HTTP/1.1\r\n\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_GET - ,.query_string= "foo=bar?baz" - ,.fragment= "" - ,.request_path= "/test.cgi" - ,.request_url= "/test.cgi?foo=bar?baz" - ,.num_headers= 0 - ,.headers= {} - ,.body= "" - } - -#define PREFIX_NEWLINE_GET 15 -/* Some clients, especially after a POST in a keep-alive connection, - * will send an extra CRLF before the next request - */ -, {.name = "newline prefix get" - ,.type= HTTP_REQUEST - ,.raw= "\r\nGET /test HTTP/1.1\r\n\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_GET - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/test" - ,.request_url= "/test" - ,.num_headers= 0 - ,.headers= { } - ,.body= "" - } - -#define UPGRADE_REQUEST 16 -, {.name = "upgrade request" - ,.type= HTTP_REQUEST - ,.raw= "GET /demo HTTP/1.1\r\n" - "Host: example.com\r\n" - "Connection: Upgrade\r\n" - "Sec-WebSocket-Key2: 12998 5 Y3 1 .P00\r\n" - "Sec-WebSocket-Protocol: sample\r\n" - "Upgrade: WebSocket\r\n" - "Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5\r\n" - "Origin: http://example.com\r\n" - "\r\n" - "Hot diggity dogg" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_GET - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/demo" - ,.request_url= "/demo" - ,.num_headers= 7 - ,.upgrade="Hot diggity dogg" - ,.headers= { { "Host", "example.com" } - , { "Connection", "Upgrade" } - , { "Sec-WebSocket-Key2", "12998 5 Y3 1 .P00" } - , { "Sec-WebSocket-Protocol", "sample" } - , { "Upgrade", "WebSocket" } - , { "Sec-WebSocket-Key1", "4 @1 46546xW%0l 1 5" } - , { "Origin", "http://example.com" } - } - ,.body= "" - } - -#define CONNECT_REQUEST 17 -, {.name = "connect request" - ,.type= HTTP_REQUEST - ,.raw= "CONNECT 0-home0.netscape.com:443 HTTP/1.0\r\n" - "User-agent: Mozilla/1.1N\r\n" - "Proxy-authorization: basic aGVsbG86d29ybGQ=\r\n" - "\r\n" - "some data\r\n" - "and yet even more data" - ,.should_keep_alive= FALSE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 0 - ,.method= HTTP_CONNECT - ,.query_string= "" - ,.fragment= "" - ,.request_path= "" - ,.request_url= "0-home0.netscape.com:443" - ,.num_headers= 2 - ,.upgrade="some data\r\nand yet even more data" - ,.headers= { { "User-agent", "Mozilla/1.1N" } - , { "Proxy-authorization", "basic aGVsbG86d29ybGQ=" } - } - ,.body= "" - } - -#define REPORT_REQ 18 -, {.name= "report request" - ,.type= HTTP_REQUEST - ,.raw= "REPORT /test HTTP/1.1\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_REPORT - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/test" - ,.request_url= "/test" - ,.num_headers= 0 - ,.headers= {} - ,.body= "" - } - -#define NO_HTTP_VERSION 19 -, {.name= "request with no http version" - ,.type= HTTP_REQUEST - ,.raw= "GET /\r\n" - "\r\n" - ,.should_keep_alive= FALSE - ,.message_complete_on_eof= FALSE - ,.http_major= 0 - ,.http_minor= 9 - ,.method= HTTP_GET - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/" - ,.request_url= "/" - ,.num_headers= 0 - ,.headers= {} - ,.body= "" - } - -#define MSEARCH_REQ 20 -, {.name= "m-search request" - ,.type= HTTP_REQUEST - ,.raw= "M-SEARCH * HTTP/1.1\r\n" - "HOST: 239.255.255.250:1900\r\n" - "MAN: \"ssdp:discover\"\r\n" - "ST: \"ssdp:all\"\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_MSEARCH - ,.query_string= "" - ,.fragment= "" - ,.request_path= "*" - ,.request_url= "*" - ,.num_headers= 3 - ,.headers= { { "HOST", "239.255.255.250:1900" } - , { "MAN", "\"ssdp:discover\"" } - , { "ST", "\"ssdp:all\"" } - } - ,.body= "" - } - -#define LINE_FOLDING_IN_HEADER 21 -, {.name= "line folding in header value" - ,.type= HTTP_REQUEST - ,.raw= "GET / HTTP/1.1\r\n" - "Line1: abc\r\n" - "\tdef\r\n" - " ghi\r\n" - "\t\tjkl\r\n" - " mno \r\n" - "\t \tqrs\r\n" - "Line2: \t line2\t\r\n" - "Line3:\r\n" - " line3\r\n" - "Line4: \r\n" - " \r\n" - "Connection:\r\n" - " close\r\n" - "\r\n" - ,.should_keep_alive= FALSE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_GET - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/" - ,.request_url= "/" - ,.num_headers= 5 - ,.headers= { { "Line1", "abc\tdef ghi\t\tjkl mno \t \tqrs" } - , { "Line2", "line2\t" } - , { "Line3", "line3" } - , { "Line4", "" } - , { "Connection", "close" }, - } - ,.body= "" - } - - -#define QUERY_TERMINATED_HOST 22 -, {.name= "host terminated by a query string" - ,.type= HTTP_REQUEST - ,.raw= "GET http://hypnotoad.org?hail=all HTTP/1.1\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_GET - ,.query_string= "hail=all" - ,.fragment= "" - ,.request_path= "" - ,.request_url= "http://hypnotoad.org?hail=all" - ,.host= "hypnotoad.org" - ,.num_headers= 0 - ,.headers= { } - ,.body= "" - } - -#define QUERY_TERMINATED_HOSTPORT 23 -, {.name= "host:port terminated by a query string" - ,.type= HTTP_REQUEST - ,.raw= "GET http://hypnotoad.org:1234?hail=all HTTP/1.1\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_GET - ,.query_string= "hail=all" - ,.fragment= "" - ,.request_path= "" - ,.request_url= "http://hypnotoad.org:1234?hail=all" - ,.host= "hypnotoad.org" - ,.port= 1234 - ,.num_headers= 0 - ,.headers= { } - ,.body= "" - } - -#define SPACE_TERMINATED_HOSTPORT 24 -, {.name= "host:port terminated by a space" - ,.type= HTTP_REQUEST - ,.raw= "GET http://hypnotoad.org:1234 HTTP/1.1\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_GET - ,.query_string= "" - ,.fragment= "" - ,.request_path= "" - ,.request_url= "http://hypnotoad.org:1234" - ,.host= "hypnotoad.org" - ,.port= 1234 - ,.num_headers= 0 - ,.headers= { } - ,.body= "" - } - -#define PATCH_REQ 25 -, {.name = "PATCH request" - ,.type= HTTP_REQUEST - ,.raw= "PATCH /file.txt HTTP/1.1\r\n" - "Host: www.example.com\r\n" - "Content-Type: application/example\r\n" - "If-Match: \"e0023aa4e\"\r\n" - "Content-Length: 10\r\n" - "\r\n" - "cccccccccc" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_PATCH - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/file.txt" - ,.request_url= "/file.txt" - ,.num_headers= 4 - ,.headers= { { "Host", "www.example.com" } - , { "Content-Type", "application/example" } - , { "If-Match", "\"e0023aa4e\"" } - , { "Content-Length", "10" } - } - ,.body= "cccccccccc" - } - -#define CONNECT_CAPS_REQUEST 26 -, {.name = "connect caps request" - ,.type= HTTP_REQUEST - ,.raw= "CONNECT HOME0.NETSCAPE.COM:443 HTTP/1.0\r\n" - "User-agent: Mozilla/1.1N\r\n" - "Proxy-authorization: basic aGVsbG86d29ybGQ=\r\n" - "\r\n" - ,.should_keep_alive= FALSE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 0 - ,.method= HTTP_CONNECT - ,.query_string= "" - ,.fragment= "" - ,.request_path= "" - ,.request_url= "HOME0.NETSCAPE.COM:443" - ,.num_headers= 2 - ,.upgrade="" - ,.headers= { { "User-agent", "Mozilla/1.1N" } - , { "Proxy-authorization", "basic aGVsbG86d29ybGQ=" } - } - ,.body= "" - } - -#if !HTTP_PARSER_STRICT -#define UTF8_PATH_REQ 27 -, {.name= "utf-8 path request" - ,.type= HTTP_REQUEST - ,.raw= "GET /δ¶/δt/pope?q=1#narf HTTP/1.1\r\n" - "Host: github.com\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_GET - ,.query_string= "q=1" - ,.fragment= "narf" - ,.request_path= "/δ¶/δt/pope" - ,.request_url= "/δ¶/δt/pope?q=1#narf" - ,.num_headers= 1 - ,.headers= { {"Host", "github.com" } - } - ,.body= "" - } - -#define HOSTNAME_UNDERSCORE 28 -, {.name = "hostname underscore" - ,.type= HTTP_REQUEST - ,.raw= "CONNECT home_0.netscape.com:443 HTTP/1.0\r\n" - "User-agent: Mozilla/1.1N\r\n" - "Proxy-authorization: basic aGVsbG86d29ybGQ=\r\n" - "\r\n" - ,.should_keep_alive= FALSE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 0 - ,.method= HTTP_CONNECT - ,.query_string= "" - ,.fragment= "" - ,.request_path= "" - ,.request_url= "home_0.netscape.com:443" - ,.num_headers= 2 - ,.upgrade="" - ,.headers= { { "User-agent", "Mozilla/1.1N" } - , { "Proxy-authorization", "basic aGVsbG86d29ybGQ=" } - } - ,.body= "" - } -#endif /* !HTTP_PARSER_STRICT */ - -/* see https://github.com/ry/http-parser/issues/47 */ -#define EAT_TRAILING_CRLF_NO_CONNECTION_CLOSE 29 -, {.name = "eat CRLF between requests, no \"Connection: close\" header" - ,.raw= "POST / HTTP/1.1\r\n" - "Host: www.example.com\r\n" - "Content-Type: application/x-www-form-urlencoded\r\n" - "Content-Length: 4\r\n" - "\r\n" - "q=42\r\n" /* note the trailing CRLF */ - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_POST - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/" - ,.request_url= "/" - ,.num_headers= 3 - ,.upgrade= 0 - ,.headers= { { "Host", "www.example.com" } - , { "Content-Type", "application/x-www-form-urlencoded" } - , { "Content-Length", "4" } - } - ,.body= "q=42" - } - -/* see https://github.com/ry/http-parser/issues/47 */ -#define EAT_TRAILING_CRLF_WITH_CONNECTION_CLOSE 30 -, {.name = "eat CRLF between requests even if \"Connection: close\" is set" - ,.raw= "POST / HTTP/1.1\r\n" - "Host: www.example.com\r\n" - "Content-Type: application/x-www-form-urlencoded\r\n" - "Content-Length: 4\r\n" - "Connection: close\r\n" - "\r\n" - "q=42\r\n" /* note the trailing CRLF */ - ,.should_keep_alive= FALSE - ,.message_complete_on_eof= FALSE /* input buffer isn't empty when on_message_complete is called */ - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_POST - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/" - ,.request_url= "/" - ,.num_headers= 4 - ,.upgrade= 0 - ,.headers= { { "Host", "www.example.com" } - , { "Content-Type", "application/x-www-form-urlencoded" } - , { "Content-Length", "4" } - , { "Connection", "close" } - } - ,.body= "q=42" - } - -#define PURGE_REQ 31 -, {.name = "PURGE request" - ,.type= HTTP_REQUEST - ,.raw= "PURGE /file.txt HTTP/1.1\r\n" - "Host: www.example.com\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_PURGE - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/file.txt" - ,.request_url= "/file.txt" - ,.num_headers= 1 - ,.headers= { { "Host", "www.example.com" } } - ,.body= "" - } - -#define SEARCH_REQ 32 -, {.name = "SEARCH request" - ,.type= HTTP_REQUEST - ,.raw= "SEARCH / HTTP/1.1\r\n" - "Host: www.example.com\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_SEARCH - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/" - ,.request_url= "/" - ,.num_headers= 1 - ,.headers= { { "Host", "www.example.com" } } - ,.body= "" - } - -#define PROXY_WITH_BASIC_AUTH 33 -, {.name= "host:port and basic_auth" - ,.type= HTTP_REQUEST - ,.raw= "GET http://a%12:b!&*$@hypnotoad.org:1234/toto HTTP/1.1\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_GET - ,.fragment= "" - ,.request_path= "/toto" - ,.request_url= "http://a%12:b!&*$@hypnotoad.org:1234/toto" - ,.host= "hypnotoad.org" - ,.userinfo= "a%12:b!&*$" - ,.port= 1234 - ,.num_headers= 0 - ,.headers= { } - ,.body= "" - } - -#define LINE_FOLDING_IN_HEADER_WITH_LF 34 -, {.name= "line folding in header value" - ,.type= HTTP_REQUEST - ,.raw= "GET / HTTP/1.1\n" - "Line1: abc\n" - "\tdef\n" - " ghi\n" - "\t\tjkl\n" - " mno \n" - "\t \tqrs\n" - "Line2: \t line2\t\n" - "Line3:\n" - " line3\n" - "Line4: \n" - " \n" - "Connection:\n" - " close\n" - "\n" - ,.should_keep_alive= FALSE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_GET - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/" - ,.request_url= "/" - ,.num_headers= 5 - ,.headers= { { "Line1", "abc\tdef ghi\t\tjkl mno \t \tqrs" } - , { "Line2", "line2\t" } - , { "Line3", "line3" } - , { "Line4", "" } - , { "Connection", "close" }, - } - ,.body= "" - } - -#define CONNECTION_MULTI 35 -, {.name = "multiple connection header values with folding" - ,.type= HTTP_REQUEST - ,.raw= "GET /demo HTTP/1.1\r\n" - "Host: example.com\r\n" - "Connection: Something,\r\n" - " Upgrade, ,Keep-Alive\r\n" - "Sec-WebSocket-Key2: 12998 5 Y3 1 .P00\r\n" - "Sec-WebSocket-Protocol: sample\r\n" - "Upgrade: WebSocket\r\n" - "Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5\r\n" - "Origin: http://example.com\r\n" - "\r\n" - "Hot diggity dogg" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_GET - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/demo" - ,.request_url= "/demo" - ,.num_headers= 7 - ,.upgrade="Hot diggity dogg" - ,.headers= { { "Host", "example.com" } - , { "Connection", "Something, Upgrade, ,Keep-Alive" } - , { "Sec-WebSocket-Key2", "12998 5 Y3 1 .P00" } - , { "Sec-WebSocket-Protocol", "sample" } - , { "Upgrade", "WebSocket" } - , { "Sec-WebSocket-Key1", "4 @1 46546xW%0l 1 5" } - , { "Origin", "http://example.com" } - } - ,.body= "" - } - -#define CONNECTION_MULTI_LWS 36 -, {.name = "multiple connection header values with folding and lws" - ,.type= HTTP_REQUEST - ,.raw= "GET /demo HTTP/1.1\r\n" - "Connection: keep-alive, upgrade\r\n" - "Upgrade: WebSocket\r\n" - "\r\n" - "Hot diggity dogg" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_GET - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/demo" - ,.request_url= "/demo" - ,.num_headers= 2 - ,.upgrade="Hot diggity dogg" - ,.headers= { { "Connection", "keep-alive, upgrade" } - , { "Upgrade", "WebSocket" } - } - ,.body= "" - } - -#define CONNECTION_MULTI_LWS_CRLF 37 -, {.name = "multiple connection header values with folding and lws" - ,.type= HTTP_REQUEST - ,.raw= "GET /demo HTTP/1.1\r\n" - "Connection: keep-alive, \r\n upgrade\r\n" - "Upgrade: WebSocket\r\n" - "\r\n" - "Hot diggity dogg" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_GET - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/demo" - ,.request_url= "/demo" - ,.num_headers= 2 - ,.upgrade="Hot diggity dogg" - ,.headers= { { "Connection", "keep-alive, upgrade" } - , { "Upgrade", "WebSocket" } - } - ,.body= "" - } - -#define UPGRADE_POST_REQUEST 38 -, {.name = "upgrade post request" - ,.type= HTTP_REQUEST - ,.raw= "POST /demo HTTP/1.1\r\n" - "Host: example.com\r\n" - "Connection: Upgrade\r\n" - "Upgrade: HTTP/2.0\r\n" - "Content-Length: 15\r\n" - "\r\n" - "sweet post body" - "Hot diggity dogg" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_POST - ,.request_path= "/demo" - ,.request_url= "/demo" - ,.num_headers= 4 - ,.upgrade="Hot diggity dogg" - ,.headers= { { "Host", "example.com" } - , { "Connection", "Upgrade" } - , { "Upgrade", "HTTP/2.0" } - , { "Content-Length", "15" } - } - ,.body= "sweet post body" - } - -#define CONNECT_WITH_BODY_REQUEST 39 -, {.name = "connect with body request" - ,.type= HTTP_REQUEST - ,.raw= "CONNECT foo.bar.com:443 HTTP/1.0\r\n" - "User-agent: Mozilla/1.1N\r\n" - "Proxy-authorization: basic aGVsbG86d29ybGQ=\r\n" - "Content-Length: 10\r\n" - "\r\n" - "blarfcicle" - ,.should_keep_alive= FALSE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 0 - ,.method= HTTP_CONNECT - ,.request_url= "foo.bar.com:443" - ,.num_headers= 3 - ,.upgrade="blarfcicle" - ,.headers= { { "User-agent", "Mozilla/1.1N" } - , { "Proxy-authorization", "basic aGVsbG86d29ybGQ=" } - , { "Content-Length", "10" } - } - ,.body= "" - } - -/* Examples from the Internet draft for LINK/UNLINK methods: - * https://tools.ietf.org/id/draft-snell-link-method-01.html#rfc.section.5 - */ - -#define LINK_REQUEST 40 -, {.name = "link request" - ,.type= HTTP_REQUEST - ,.raw= "LINK /images/my_dog.jpg HTTP/1.1\r\n" - "Host: example.com\r\n" - "Link: ; rel=\"tag\"\r\n" - "Link: ; rel=\"tag\"\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_LINK - ,.request_path= "/images/my_dog.jpg" - ,.request_url= "/images/my_dog.jpg" - ,.query_string= "" - ,.fragment= "" - ,.num_headers= 3 - ,.headers= { { "Host", "example.com" } - , { "Link", "; rel=\"tag\"" } - , { "Link", "; rel=\"tag\"" } - } - ,.body= "" - } - -#define UNLINK_REQUEST 41 -, {.name = "unlink request" - ,.type= HTTP_REQUEST - ,.raw= "UNLINK /images/my_dog.jpg HTTP/1.1\r\n" - "Host: example.com\r\n" - "Link: ; rel=\"tag\"\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_UNLINK - ,.request_path= "/images/my_dog.jpg" - ,.request_url= "/images/my_dog.jpg" - ,.query_string= "" - ,.fragment= "" - ,.num_headers= 2 - ,.headers= { { "Host", "example.com" } - , { "Link", "; rel=\"tag\"" } - } - ,.body= "" - } - -#define SOURCE_REQUEST 42 -, {.name = "source request" - ,.type= HTTP_REQUEST - ,.raw= "SOURCE /music/sweet/music HTTP/1.1\r\n" - "Host: example.com\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_SOURCE - ,.request_path= "/music/sweet/music" - ,.request_url= "/music/sweet/music" - ,.query_string= "" - ,.fragment= "" - ,.num_headers= 1 - ,.headers= { { "Host", "example.com" } } - ,.body= "" - } - -#define SOURCE_ICE_REQUEST 42 -, {.name = "source request" - ,.type= HTTP_REQUEST - ,.raw= "SOURCE /music/sweet/music ICE/1.0\r\n" - "Host: example.com\r\n" - "\r\n" - ,.should_keep_alive= FALSE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 0 - ,.method= HTTP_SOURCE - ,.request_path= "/music/sweet/music" - ,.request_url= "/music/sweet/music" - ,.query_string= "" - ,.fragment= "" - ,.num_headers= 1 - ,.headers= { { "Host", "example.com" } } - ,.body= "" - } - -#define POST_MULTI_TE_LAST_CHUNKED 43 -, {.name= "post - multi coding transfer-encoding chunked body" - ,.type= HTTP_REQUEST - ,.raw= "POST / HTTP/1.1\r\n" - "Transfer-Encoding: deflate, chunked\r\n" - "\r\n" - "1e\r\nall your base are belong to us\r\n" - "0\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_POST - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/" - ,.request_url= "/" - ,.num_headers= 1 - ,.headers= - { { "Transfer-Encoding" , "deflate, chunked" } - } - ,.body= "all your base are belong to us" - ,.num_chunks_complete= 2 - ,.chunk_lengths= { 0x1e } - } - -#define POST_MULTI_LINE_TE_LAST_CHUNKED 44 -, {.name= "post - multi line coding transfer-encoding chunked body" - ,.type= HTTP_REQUEST - ,.raw= "POST / HTTP/1.1\r\n" - "Transfer-Encoding: deflate,\r\n" - " chunked\r\n" - "\r\n" - "1e\r\nall your base are belong to us\r\n" - "0\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_POST - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/" - ,.request_url= "/" - ,.num_headers= 1 - ,.headers= - { { "Transfer-Encoding" , "deflate, chunked" } - } - ,.body= "all your base are belong to us" - ,.num_chunks_complete= 2 - ,.chunk_lengths= { 0x1e } - } -}; - -/* * R E S P O N S E S * */ -const struct message responses[] = -#define GOOGLE_301 0 -{ {.name= "google 301" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/1.1 301 Moved Permanently\r\n" - "Location: http://www.google.com/\r\n" - "Content-Type: text/html; charset=UTF-8\r\n" - "Date: Sun, 26 Apr 2009 11:11:49 GMT\r\n" - "Expires: Tue, 26 May 2009 11:11:49 GMT\r\n" - "X-$PrototypeBI-Version: 1.6.0.3\r\n" /* $ char in header field */ - "Cache-Control: public, max-age=2592000\r\n" - "Server: gws\r\n" - "Content-Length: 219 \r\n" - "\r\n" - "\n" - "301 Moved\n" - "

301 Moved

\n" - "The document has moved\n" - "here.\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.status_code= 301 - ,.response_status= "Moved Permanently" - ,.num_headers= 8 - ,.headers= - { { "Location", "http://www.google.com/" } - , { "Content-Type", "text/html; charset=UTF-8" } - , { "Date", "Sun, 26 Apr 2009 11:11:49 GMT" } - , { "Expires", "Tue, 26 May 2009 11:11:49 GMT" } - , { "X-$PrototypeBI-Version", "1.6.0.3" } - , { "Cache-Control", "public, max-age=2592000" } - , { "Server", "gws" } - , { "Content-Length", "219 " } - } - ,.body= "\n" - "301 Moved\n" - "

301 Moved

\n" - "The document has moved\n" - "here.\r\n" - "\r\n" - } - -#define NO_CONTENT_LENGTH_RESPONSE 1 -/* The client should wait for the server's EOF. That is, when content-length - * is not specified, and "Connection: close", the end of body is specified - * by the EOF. - * Compare with APACHEBENCH_GET - */ -, {.name= "no content-length response" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/1.1 200 OK\r\n" - "Date: Tue, 04 Aug 2009 07:59:32 GMT\r\n" - "Server: Apache\r\n" - "X-Powered-By: Servlet/2.5 JSP/2.1\r\n" - "Content-Type: text/xml; charset=utf-8\r\n" - "Connection: close\r\n" - "\r\n" - "\n" - "\n" - " \n" - " \n" - " SOAP-ENV:Client\n" - " Client Error\n" - " \n" - " \n" - "" - ,.should_keep_alive= FALSE - ,.message_complete_on_eof= TRUE - ,.http_major= 1 - ,.http_minor= 1 - ,.status_code= 200 - ,.response_status= "OK" - ,.num_headers= 5 - ,.headers= - { { "Date", "Tue, 04 Aug 2009 07:59:32 GMT" } - , { "Server", "Apache" } - , { "X-Powered-By", "Servlet/2.5 JSP/2.1" } - , { "Content-Type", "text/xml; charset=utf-8" } - , { "Connection", "close" } - } - ,.body= "\n" - "\n" - " \n" - " \n" - " SOAP-ENV:Client\n" - " Client Error\n" - " \n" - " \n" - "" - } - -#define NO_HEADERS_NO_BODY_404 2 -, {.name= "404 no headers no body" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/1.1 404 Not Found\r\n\r\n" - ,.should_keep_alive= FALSE - ,.message_complete_on_eof= TRUE - ,.http_major= 1 - ,.http_minor= 1 - ,.status_code= 404 - ,.response_status= "Not Found" - ,.num_headers= 0 - ,.headers= {} - ,.body_size= 0 - ,.body= "" - } - -#define NO_REASON_PHRASE 3 -, {.name= "301 no response phrase" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/1.1 301\r\n\r\n" - ,.should_keep_alive = FALSE - ,.message_complete_on_eof= TRUE - ,.http_major= 1 - ,.http_minor= 1 - ,.status_code= 301 - ,.response_status= "" - ,.num_headers= 0 - ,.headers= {} - ,.body= "" - } - -#define TRAILING_SPACE_ON_CHUNKED_BODY 4 -, {.name="200 trailing space on chunked body" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/1.1 200 OK\r\n" - "Content-Type: text/plain\r\n" - "Transfer-Encoding: chunked\r\n" - "\r\n" - "25 \r\n" - "This is the data in the first chunk\r\n" - "\r\n" - "1C\r\n" - "and this is the second one\r\n" - "\r\n" - "0 \r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.status_code= 200 - ,.response_status= "OK" - ,.num_headers= 2 - ,.headers= - { {"Content-Type", "text/plain" } - , {"Transfer-Encoding", "chunked" } - } - ,.body_size = 37+28 - ,.body = - "This is the data in the first chunk\r\n" - "and this is the second one\r\n" - ,.num_chunks_complete= 3 - ,.chunk_lengths= { 0x25, 0x1c } - } - -#define NO_CARRIAGE_RET 5 -, {.name="no carriage ret" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/1.1 200 OK\n" - "Content-Type: text/html; charset=utf-8\n" - "Connection: close\n" - "\n" - "these headers are from http://news.ycombinator.com/" - ,.should_keep_alive= FALSE - ,.message_complete_on_eof= TRUE - ,.http_major= 1 - ,.http_minor= 1 - ,.status_code= 200 - ,.response_status= "OK" - ,.num_headers= 2 - ,.headers= - { {"Content-Type", "text/html; charset=utf-8" } - , {"Connection", "close" } - } - ,.body= "these headers are from http://news.ycombinator.com/" - } - -#define PROXY_CONNECTION 6 -, {.name="proxy connection" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/1.1 200 OK\r\n" - "Content-Type: text/html; charset=UTF-8\r\n" - "Content-Length: 11\r\n" - "Proxy-Connection: close\r\n" - "Date: Thu, 31 Dec 2009 20:55:48 +0000\r\n" - "\r\n" - "hello world" - ,.should_keep_alive= FALSE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.status_code= 200 - ,.response_status= "OK" - ,.num_headers= 4 - ,.headers= - { {"Content-Type", "text/html; charset=UTF-8" } - , {"Content-Length", "11" } - , {"Proxy-Connection", "close" } - , {"Date", "Thu, 31 Dec 2009 20:55:48 +0000"} - } - ,.body= "hello world" - } - -#define UNDERSTORE_HEADER_KEY 7 - // shown by - // curl -o /dev/null -v "http://ad.doubleclick.net/pfadx/DARTSHELLCONFIGXML;dcmt=text/xml;" -, {.name="underscore header key" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/1.1 200 OK\r\n" - "Server: DCLK-AdSvr\r\n" - "Content-Type: text/xml\r\n" - "Content-Length: 0\r\n" - "DCLK_imp: v7;x;114750856;0-0;0;17820020;0/0;21603567/21621457/1;;~okv=;dcmt=text/xml;;~cs=o\r\n\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.status_code= 200 - ,.response_status= "OK" - ,.num_headers= 4 - ,.headers= - { {"Server", "DCLK-AdSvr" } - , {"Content-Type", "text/xml" } - , {"Content-Length", "0" } - , {"DCLK_imp", "v7;x;114750856;0-0;0;17820020;0/0;21603567/21621457/1;;~okv=;dcmt=text/xml;;~cs=o" } - } - ,.body= "" - } - -#define BONJOUR_MADAME_FR 8 -/* The client should not merge two headers fields when the first one doesn't - * have a value. - */ -, {.name= "bonjourmadame.fr" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/1.0 301 Moved Permanently\r\n" - "Date: Thu, 03 Jun 2010 09:56:32 GMT\r\n" - "Server: Apache/2.2.3 (Red Hat)\r\n" - "Cache-Control: public\r\n" - "Pragma: \r\n" - "Location: http://www.bonjourmadame.fr/\r\n" - "Vary: Accept-Encoding\r\n" - "Content-Length: 0\r\n" - "Content-Type: text/html; charset=UTF-8\r\n" - "Connection: keep-alive\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 0 - ,.status_code= 301 - ,.response_status= "Moved Permanently" - ,.num_headers= 9 - ,.headers= - { { "Date", "Thu, 03 Jun 2010 09:56:32 GMT" } - , { "Server", "Apache/2.2.3 (Red Hat)" } - , { "Cache-Control", "public" } - , { "Pragma", "" } - , { "Location", "http://www.bonjourmadame.fr/" } - , { "Vary", "Accept-Encoding" } - , { "Content-Length", "0" } - , { "Content-Type", "text/html; charset=UTF-8" } - , { "Connection", "keep-alive" } - } - ,.body= "" - } - -#define RES_FIELD_UNDERSCORE 9 -/* Should handle spaces in header fields */ -, {.name= "field underscore" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/1.1 200 OK\r\n" - "Date: Tue, 28 Sep 2010 01:14:13 GMT\r\n" - "Server: Apache\r\n" - "Cache-Control: no-cache, must-revalidate\r\n" - "Expires: Mon, 26 Jul 1997 05:00:00 GMT\r\n" - ".et-Cookie: PlaxoCS=1274804622353690521; path=/; domain=.plaxo.com\r\n" - "Vary: Accept-Encoding\r\n" - "_eep-Alive: timeout=45\r\n" /* semantic value ignored */ - "_onnection: Keep-Alive\r\n" /* semantic value ignored */ - "Transfer-Encoding: chunked\r\n" - "Content-Type: text/html\r\n" - "Connection: close\r\n" - "\r\n" - "0\r\n\r\n" - ,.should_keep_alive= FALSE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.status_code= 200 - ,.response_status= "OK" - ,.num_headers= 11 - ,.headers= - { { "Date", "Tue, 28 Sep 2010 01:14:13 GMT" } - , { "Server", "Apache" } - , { "Cache-Control", "no-cache, must-revalidate" } - , { "Expires", "Mon, 26 Jul 1997 05:00:00 GMT" } - , { ".et-Cookie", "PlaxoCS=1274804622353690521; path=/; domain=.plaxo.com" } - , { "Vary", "Accept-Encoding" } - , { "_eep-Alive", "timeout=45" } - , { "_onnection", "Keep-Alive" } - , { "Transfer-Encoding", "chunked" } - , { "Content-Type", "text/html" } - , { "Connection", "close" } - } - ,.body= "" - ,.num_chunks_complete= 1 - ,.chunk_lengths= {} - } - -#define NON_ASCII_IN_STATUS_LINE 10 -/* Should handle non-ASCII in status line */ -, {.name= "non-ASCII in status line" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/1.1 500 Oriëntatieprobleem\r\n" - "Date: Fri, 5 Nov 2010 23:07:12 GMT+2\r\n" - "Content-Length: 0\r\n" - "Connection: close\r\n" - "\r\n" - ,.should_keep_alive= FALSE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.status_code= 500 - ,.response_status= "Oriëntatieprobleem" - ,.num_headers= 3 - ,.headers= - { { "Date", "Fri, 5 Nov 2010 23:07:12 GMT+2" } - , { "Content-Length", "0" } - , { "Connection", "close" } - } - ,.body= "" - } - -#define HTTP_VERSION_0_9 11 -/* Should handle HTTP/0.9 */ -, {.name= "http version 0.9" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/0.9 200 OK\r\n" - "\r\n" - ,.should_keep_alive= FALSE - ,.message_complete_on_eof= TRUE - ,.http_major= 0 - ,.http_minor= 9 - ,.status_code= 200 - ,.response_status= "OK" - ,.num_headers= 0 - ,.headers= - {} - ,.body= "" - } - -#define NO_CONTENT_LENGTH_NO_TRANSFER_ENCODING_RESPONSE 12 -/* The client should wait for the server's EOF. That is, when neither - * content-length nor transfer-encoding is specified, the end of body - * is specified by the EOF. - */ -, {.name= "neither content-length nor transfer-encoding response" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/1.1 200 OK\r\n" - "Content-Type: text/plain\r\n" - "\r\n" - "hello world" - ,.should_keep_alive= FALSE - ,.message_complete_on_eof= TRUE - ,.http_major= 1 - ,.http_minor= 1 - ,.status_code= 200 - ,.response_status= "OK" - ,.num_headers= 1 - ,.headers= - { { "Content-Type", "text/plain" } - } - ,.body= "hello world" - } - -#define NO_BODY_HTTP10_KA_200 13 -, {.name= "HTTP/1.0 with keep-alive and EOF-terminated 200 status" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/1.0 200 OK\r\n" - "Connection: keep-alive\r\n" - "\r\n" - ,.should_keep_alive= FALSE - ,.message_complete_on_eof= TRUE - ,.http_major= 1 - ,.http_minor= 0 - ,.status_code= 200 - ,.response_status= "OK" - ,.num_headers= 1 - ,.headers= - { { "Connection", "keep-alive" } - } - ,.body_size= 0 - ,.body= "" - } - -#define NO_BODY_HTTP10_KA_204 14 -, {.name= "HTTP/1.0 with keep-alive and a 204 status" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/1.0 204 No content\r\n" - "Connection: keep-alive\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 0 - ,.status_code= 204 - ,.response_status= "No content" - ,.num_headers= 1 - ,.headers= - { { "Connection", "keep-alive" } - } - ,.body_size= 0 - ,.body= "" - } - -#define NO_BODY_HTTP11_KA_200 15 -, {.name= "HTTP/1.1 with an EOF-terminated 200 status" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/1.1 200 OK\r\n" - "\r\n" - ,.should_keep_alive= FALSE - ,.message_complete_on_eof= TRUE - ,.http_major= 1 - ,.http_minor= 1 - ,.status_code= 200 - ,.response_status= "OK" - ,.num_headers= 0 - ,.headers={} - ,.body_size= 0 - ,.body= "" - } - -#define NO_BODY_HTTP11_KA_204 16 -, {.name= "HTTP/1.1 with a 204 status" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/1.1 204 No content\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.status_code= 204 - ,.response_status= "No content" - ,.num_headers= 0 - ,.headers={} - ,.body_size= 0 - ,.body= "" - } - -#define NO_BODY_HTTP11_NOKA_204 17 -, {.name= "HTTP/1.1 with a 204 status and keep-alive disabled" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/1.1 204 No content\r\n" - "Connection: close\r\n" - "\r\n" - ,.should_keep_alive= FALSE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.status_code= 204 - ,.response_status= "No content" - ,.num_headers= 1 - ,.headers= - { { "Connection", "close" } - } - ,.body_size= 0 - ,.body= "" - } - -#define NO_BODY_HTTP11_KA_CHUNKED_200 18 -, {.name= "HTTP/1.1 with chunked endocing and a 200 response" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/1.1 200 OK\r\n" - "Transfer-Encoding: chunked\r\n" - "\r\n" - "0\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.status_code= 200 - ,.response_status= "OK" - ,.num_headers= 1 - ,.headers= - { { "Transfer-Encoding", "chunked" } - } - ,.body_size= 0 - ,.body= "" - ,.num_chunks_complete= 1 - } - -#if !HTTP_PARSER_STRICT -#define SPACE_IN_FIELD_RES 19 -/* Should handle spaces in header fields */ -, {.name= "field space" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/1.1 200 OK\r\n" - "Server: Microsoft-IIS/6.0\r\n" - "X-Powered-By: ASP.NET\r\n" - "en-US Content-Type: text/xml\r\n" /* this is the problem */ - "Content-Type: text/xml\r\n" - "Content-Length: 16\r\n" - "Date: Fri, 23 Jul 2010 18:45:38 GMT\r\n" - "Connection: keep-alive\r\n" - "\r\n" - "hello" /* fake body */ - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.status_code= 200 - ,.response_status= "OK" - ,.num_headers= 7 - ,.headers= - { { "Server", "Microsoft-IIS/6.0" } - , { "X-Powered-By", "ASP.NET" } - , { "en-US Content-Type", "text/xml" } - , { "Content-Type", "text/xml" } - , { "Content-Length", "16" } - , { "Date", "Fri, 23 Jul 2010 18:45:38 GMT" } - , { "Connection", "keep-alive" } - } - ,.body= "hello" - } -#endif /* !HTTP_PARSER_STRICT */ - -#define AMAZON_COM 20 -, {.name= "amazon.com" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/1.1 301 MovedPermanently\r\n" - "Date: Wed, 15 May 2013 17:06:33 GMT\r\n" - "Server: Server\r\n" - "x-amz-id-1: 0GPHKXSJQ826RK7GZEB2\r\n" - "p3p: policyref=\"http://www.amazon.com/w3c/p3p.xml\",CP=\"CAO DSP LAW CUR ADM IVAo IVDo CONo OTPo OUR DELi PUBi OTRi BUS PHY ONL UNI PUR FIN COM NAV INT DEM CNT STA HEA PRE LOC GOV OTC \"\r\n" - "x-amz-id-2: STN69VZxIFSz9YJLbz1GDbxpbjG6Qjmmq5E3DxRhOUw+Et0p4hr7c/Q8qNcx4oAD\r\n" - "Location: http://www.amazon.com/Dan-Brown/e/B000AP9DSU/ref=s9_pop_gw_al1?_encoding=UTF8&refinementId=618073011&pf_rd_m=ATVPDKIKX0DER&pf_rd_s=center-2&pf_rd_r=0SHYY5BZXN3KR20BNFAY&pf_rd_t=101&pf_rd_p=1263340922&pf_rd_i=507846\r\n" - "Vary: Accept-Encoding,User-Agent\r\n" - "Content-Type: text/html; charset=ISO-8859-1\r\n" - "Transfer-Encoding: chunked\r\n" - "\r\n" - "1\r\n" - "\n\r\n" - "0\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.status_code= 301 - ,.response_status= "MovedPermanently" - ,.num_headers= 9 - ,.headers= { { "Date", "Wed, 15 May 2013 17:06:33 GMT" } - , { "Server", "Server" } - , { "x-amz-id-1", "0GPHKXSJQ826RK7GZEB2" } - , { "p3p", "policyref=\"http://www.amazon.com/w3c/p3p.xml\",CP=\"CAO DSP LAW CUR ADM IVAo IVDo CONo OTPo OUR DELi PUBi OTRi BUS PHY ONL UNI PUR FIN COM NAV INT DEM CNT STA HEA PRE LOC GOV OTC \"" } - , { "x-amz-id-2", "STN69VZxIFSz9YJLbz1GDbxpbjG6Qjmmq5E3DxRhOUw+Et0p4hr7c/Q8qNcx4oAD" } - , { "Location", "http://www.amazon.com/Dan-Brown/e/B000AP9DSU/ref=s9_pop_gw_al1?_encoding=UTF8&refinementId=618073011&pf_rd_m=ATVPDKIKX0DER&pf_rd_s=center-2&pf_rd_r=0SHYY5BZXN3KR20BNFAY&pf_rd_t=101&pf_rd_p=1263340922&pf_rd_i=507846" } - , { "Vary", "Accept-Encoding,User-Agent" } - , { "Content-Type", "text/html; charset=ISO-8859-1" } - , { "Transfer-Encoding", "chunked" } - } - ,.body= "\n" - ,.num_chunks_complete= 2 - ,.chunk_lengths= { 1 } - } - -#define EMPTY_REASON_PHRASE_AFTER_SPACE 20 -, {.name= "empty reason phrase after space" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/1.1 200 \r\n" - "\r\n" - ,.should_keep_alive= FALSE - ,.message_complete_on_eof= TRUE - ,.http_major= 1 - ,.http_minor= 1 - ,.status_code= 200 - ,.response_status= "" - ,.num_headers= 0 - ,.headers= {} - ,.body= "" - } - -#define CONTENT_LENGTH_X 21 -, {.name= "Content-Length-X" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/1.1 200 OK\r\n" - "Content-Length-X: 0\r\n" - "Transfer-Encoding: chunked\r\n" - "\r\n" - "2\r\n" - "OK\r\n" - "0\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.status_code= 200 - ,.response_status= "OK" - ,.num_headers= 2 - ,.headers= { { "Content-Length-X", "0" } - , { "Transfer-Encoding", "chunked" } - } - ,.body= "OK" - ,.num_chunks_complete= 2 - ,.chunk_lengths= { 2 } - } - -#define HTTP_101_RESPONSE_WITH_UPGRADE_HEADER 22 -, {.name= "HTTP 101 response with Upgrade header" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/1.1 101 Switching Protocols\r\n" - "Connection: upgrade\r\n" - "Upgrade: h2c\r\n" - "\r\n" - "proto" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.status_code= 101 - ,.response_status= "Switching Protocols" - ,.upgrade= "proto" - ,.num_headers= 2 - ,.headers= - { { "Connection", "upgrade" } - , { "Upgrade", "h2c" } - } - } - -#define HTTP_101_RESPONSE_WITH_UPGRADE_HEADER_AND_CONTENT_LENGTH 23 -, {.name= "HTTP 101 response with Upgrade and Content-Length header" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/1.1 101 Switching Protocols\r\n" - "Connection: upgrade\r\n" - "Upgrade: h2c\r\n" - "Content-Length: 4\r\n" - "\r\n" - "body" - "proto" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.status_code= 101 - ,.response_status= "Switching Protocols" - ,.body= "body" - ,.upgrade= "proto" - ,.num_headers= 3 - ,.headers= - { { "Connection", "upgrade" } - , { "Upgrade", "h2c" } - , { "Content-Length", "4" } - } - } - -#define HTTP_101_RESPONSE_WITH_UPGRADE_HEADER_AND_TRANSFER_ENCODING 24 -, {.name= "HTTP 101 response with Upgrade and Transfer-Encoding header" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/1.1 101 Switching Protocols\r\n" - "Connection: upgrade\r\n" - "Upgrade: h2c\r\n" - "Transfer-Encoding: chunked\r\n" - "\r\n" - "2\r\n" - "bo\r\n" - "2\r\n" - "dy\r\n" - "0\r\n" - "\r\n" - "proto" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.status_code= 101 - ,.response_status= "Switching Protocols" - ,.body= "body" - ,.upgrade= "proto" - ,.num_headers= 3 - ,.headers= - { { "Connection", "upgrade" } - , { "Upgrade", "h2c" } - , { "Transfer-Encoding", "chunked" } - } - ,.num_chunks_complete= 3 - ,.chunk_lengths= { 2, 2 } - } - -#define HTTP_200_RESPONSE_WITH_UPGRADE_HEADER 25 -, {.name= "HTTP 200 response with Upgrade header" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/1.1 200 OK\r\n" - "Connection: upgrade\r\n" - "Upgrade: h2c\r\n" - "\r\n" - "body" - ,.should_keep_alive= FALSE - ,.message_complete_on_eof= TRUE - ,.http_major= 1 - ,.http_minor= 1 - ,.status_code= 200 - ,.response_status= "OK" - ,.body= "body" - ,.upgrade= NULL - ,.num_headers= 2 - ,.headers= - { { "Connection", "upgrade" } - , { "Upgrade", "h2c" } - } - } - -#define HTTP_200_RESPONSE_WITH_UPGRADE_HEADER_AND_CONTENT_LENGTH 26 -, {.name= "HTTP 200 response with Upgrade and Content-Length header" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/1.1 200 OK\r\n" - "Connection: upgrade\r\n" - "Upgrade: h2c\r\n" - "Content-Length: 4\r\n" - "\r\n" - "body" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.status_code= 200 - ,.response_status= "OK" - ,.num_headers= 3 - ,.body= "body" - ,.upgrade= NULL - ,.headers= - { { "Connection", "upgrade" } - , { "Upgrade", "h2c" } - , { "Content-Length", "4" } - } - } - -#define HTTP_200_RESPONSE_WITH_UPGRADE_HEADER_AND_TRANSFER_ENCODING 27 -, {.name= "HTTP 200 response with Upgrade and Transfer-Encoding header" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/1.1 200 OK\r\n" - "Connection: upgrade\r\n" - "Upgrade: h2c\r\n" - "Transfer-Encoding: chunked\r\n" - "\r\n" - "2\r\n" - "bo\r\n" - "2\r\n" - "dy\r\n" - "0\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.status_code= 200 - ,.response_status= "OK" - ,.num_headers= 3 - ,.body= "body" - ,.upgrade= NULL - ,.headers= - { { "Connection", "upgrade" } - , { "Upgrade", "h2c" } - , { "Transfer-Encoding", "chunked" } - } - ,.num_chunks_complete= 3 - ,.chunk_lengths= { 2, 2 } - } -#define HTTP_200_MULTI_TE_NOT_LAST_CHUNKED 28 -, {.name= "HTTP 200 response with `chunked` being *not last* Transfer-Encoding" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/1.1 200 OK\r\n" - "Transfer-Encoding: chunked, identity\r\n" - "\r\n" - "2\r\n" - "OK\r\n" - "0\r\n" - "\r\n" - ,.should_keep_alive= FALSE - ,.message_complete_on_eof= TRUE - ,.http_major= 1 - ,.http_minor= 1 - ,.status_code= 200 - ,.response_status= "OK" - ,.num_headers= 1 - ,.headers= { { "Transfer-Encoding", "chunked, identity" } - } - ,.body= "2\r\nOK\r\n0\r\n\r\n" - ,.num_chunks_complete= 0 - } -}; - -/* strnlen() is a POSIX.2008 addition. Can't rely on it being available so - * define it ourselves. - */ -size_t -strnlen(const char *s, size_t maxlen) -{ - const char *p; - - p = memchr(s, '\0', maxlen); - if (p == NULL) - return maxlen; - - return p - s; -} - -size_t -strlncat(char *dst, size_t len, const char *src, size_t n) -{ - size_t slen; - size_t dlen; - size_t rlen; - size_t ncpy; - - slen = strnlen(src, n); - dlen = strnlen(dst, len); - - if (dlen < len) { - rlen = len - dlen; - ncpy = slen < rlen ? slen : (rlen - 1); - memcpy(dst + dlen, src, ncpy); - dst[dlen + ncpy] = '\0'; - } - - assert(len > slen + dlen); - return slen + dlen; -} - -size_t -strlncpy(char *dst, size_t len, const char *src, size_t n) -{ - size_t slen; - size_t ncpy; - - slen = strnlen(src, n); - - if (len > 0) { - ncpy = slen < len ? slen : (len - 1); - memcpy(dst, src, ncpy); - dst[ncpy] = '\0'; - } - - assert(len > slen); - return slen; -} - -int -request_url_cb (http_parser *p, const char *buf, size_t len) -{ - assert(p == &parser); - strlncat(messages[num_messages].request_url, - sizeof(messages[num_messages].request_url), - buf, - len); - return 0; -} - -int -header_field_cb (http_parser *p, const char *buf, size_t len) -{ - assert(p == &parser); - struct message *m = &messages[num_messages]; - - if (m->last_header_element != FIELD) - m->num_headers++; - - strlncat(m->headers[m->num_headers-1][0], - sizeof(m->headers[m->num_headers-1][0]), - buf, - len); - - m->last_header_element = FIELD; - - return 0; -} - -int -header_value_cb (http_parser *p, const char *buf, size_t len) -{ - assert(p == &parser); - struct message *m = &messages[num_messages]; - - strlncat(m->headers[m->num_headers-1][1], - sizeof(m->headers[m->num_headers-1][1]), - buf, - len); - - m->last_header_element = VALUE; - - return 0; -} - -void -check_body_is_final (const http_parser *p) -{ - if (messages[num_messages].body_is_final) { - fprintf(stderr, "\n\n *** Error http_body_is_final() should return 1 " - "on last on_body callback call " - "but it doesn't! ***\n\n"); - assert(0); - abort(); - } - messages[num_messages].body_is_final = http_body_is_final(p); -} - -int -body_cb (http_parser *p, const char *buf, size_t len) -{ - assert(p == &parser); - strlncat(messages[num_messages].body, - sizeof(messages[num_messages].body), - buf, - len); - messages[num_messages].body_size += len; - check_body_is_final(p); - // printf("body_cb: '%s'\n", requests[num_messages].body); - return 0; -} - -int -count_body_cb (http_parser *p, const char *buf, size_t len) -{ - assert(p == &parser); - assert(buf); - messages[num_messages].body_size += len; - check_body_is_final(p); - return 0; -} - -int -message_begin_cb (http_parser *p) -{ - assert(p == &parser); - assert(!messages[num_messages].message_begin_cb_called); - messages[num_messages].message_begin_cb_called = TRUE; - return 0; -} - -int -headers_complete_cb (http_parser *p) -{ - assert(p == &parser); - messages[num_messages].method = parser.method; - messages[num_messages].status_code = parser.status_code; - messages[num_messages].http_major = parser.http_major; - messages[num_messages].http_minor = parser.http_minor; - messages[num_messages].headers_complete_cb_called = TRUE; - messages[num_messages].should_keep_alive = http_should_keep_alive(&parser); - return 0; -} - -int -message_complete_cb (http_parser *p) -{ - assert(p == &parser); - if (messages[num_messages].should_keep_alive != - http_should_keep_alive(&parser)) - { - fprintf(stderr, "\n\n *** Error http_should_keep_alive() should have same " - "value in both on_message_complete and on_headers_complete " - "but it doesn't! ***\n\n"); - assert(0); - abort(); - } - - if (messages[num_messages].body_size && - http_body_is_final(p) && - !messages[num_messages].body_is_final) - { - fprintf(stderr, "\n\n *** Error http_body_is_final() should return 1 " - "on last on_body callback call " - "but it doesn't! ***\n\n"); - assert(0); - abort(); - } - - messages[num_messages].message_complete_cb_called = TRUE; - - messages[num_messages].message_complete_on_eof = currently_parsing_eof; - - num_messages++; - return 0; -} - -int -response_status_cb (http_parser *p, const char *buf, size_t len) -{ - assert(p == &parser); - - messages[num_messages].status_cb_called = TRUE; - - strlncat(messages[num_messages].response_status, - sizeof(messages[num_messages].response_status), - buf, - len); - return 0; -} - -int -chunk_header_cb (http_parser *p) -{ - assert(p == &parser); - int chunk_idx = messages[num_messages].num_chunks; - messages[num_messages].num_chunks++; - if (chunk_idx < MAX_CHUNKS) { - messages[num_messages].chunk_lengths[chunk_idx] = p->content_length; - } - - return 0; -} - -int -chunk_complete_cb (http_parser *p) -{ - assert(p == &parser); - - /* Here we want to verify that each chunk_header_cb is matched by a - * chunk_complete_cb, so not only should the total number of calls to - * both callbacks be the same, but they also should be interleaved - * properly */ - assert(messages[num_messages].num_chunks == - messages[num_messages].num_chunks_complete + 1); - - messages[num_messages].num_chunks_complete++; - return 0; -} - -/* These dontcall_* callbacks exist so that we can verify that when we're - * paused, no additional callbacks are invoked */ -int -dontcall_message_begin_cb (http_parser *p) -{ - if (p) { } // gcc - fprintf(stderr, "\n\n*** on_message_begin() called on paused parser ***\n\n"); - abort(); -} - -int -dontcall_header_field_cb (http_parser *p, const char *buf, size_t len) -{ - if (p || buf || len) { } // gcc - fprintf(stderr, "\n\n*** on_header_field() called on paused parser ***\n\n"); - abort(); -} - -int -dontcall_header_value_cb (http_parser *p, const char *buf, size_t len) -{ - if (p || buf || len) { } // gcc - fprintf(stderr, "\n\n*** on_header_value() called on paused parser ***\n\n"); - abort(); -} - -int -dontcall_request_url_cb (http_parser *p, const char *buf, size_t len) -{ - if (p || buf || len) { } // gcc - fprintf(stderr, "\n\n*** on_request_url() called on paused parser ***\n\n"); - abort(); -} - -int -dontcall_body_cb (http_parser *p, const char *buf, size_t len) -{ - if (p || buf || len) { } // gcc - fprintf(stderr, "\n\n*** on_body_cb() called on paused parser ***\n\n"); - abort(); -} - -int -dontcall_headers_complete_cb (http_parser *p) -{ - if (p) { } // gcc - fprintf(stderr, "\n\n*** on_headers_complete() called on paused " - "parser ***\n\n"); - abort(); -} - -int -dontcall_message_complete_cb (http_parser *p) -{ - if (p) { } // gcc - fprintf(stderr, "\n\n*** on_message_complete() called on paused " - "parser ***\n\n"); - abort(); -} - -int -dontcall_response_status_cb (http_parser *p, const char *buf, size_t len) -{ - if (p || buf || len) { } // gcc - fprintf(stderr, "\n\n*** on_status() called on paused parser ***\n\n"); - abort(); -} - -int -dontcall_chunk_header_cb (http_parser *p) -{ - if (p) { } // gcc - fprintf(stderr, "\n\n*** on_chunk_header() called on paused parser ***\n\n"); - exit(1); -} - -int -dontcall_chunk_complete_cb (http_parser *p) -{ - if (p) { } // gcc - fprintf(stderr, "\n\n*** on_chunk_complete() " - "called on paused parser ***\n\n"); - exit(1); -} - -static http_parser_settings settings_dontcall = - {.on_message_begin = dontcall_message_begin_cb - ,.on_header_field = dontcall_header_field_cb - ,.on_header_value = dontcall_header_value_cb - ,.on_url = dontcall_request_url_cb - ,.on_status = dontcall_response_status_cb - ,.on_body = dontcall_body_cb - ,.on_headers_complete = dontcall_headers_complete_cb - ,.on_message_complete = dontcall_message_complete_cb - ,.on_chunk_header = dontcall_chunk_header_cb - ,.on_chunk_complete = dontcall_chunk_complete_cb - }; - -/* These pause_* callbacks always pause the parser and just invoke the regular - * callback that tracks content. Before returning, we overwrite the parser - * settings to point to the _dontcall variety so that we can verify that - * the pause actually did, you know, pause. */ -int -pause_message_begin_cb (http_parser *p) -{ - http_parser_pause(p, 1); - *current_pause_parser = settings_dontcall; - return message_begin_cb(p); -} - -int -pause_header_field_cb (http_parser *p, const char *buf, size_t len) -{ - http_parser_pause(p, 1); - *current_pause_parser = settings_dontcall; - return header_field_cb(p, buf, len); -} - -int -pause_header_value_cb (http_parser *p, const char *buf, size_t len) -{ - http_parser_pause(p, 1); - *current_pause_parser = settings_dontcall; - return header_value_cb(p, buf, len); -} - -int -pause_request_url_cb (http_parser *p, const char *buf, size_t len) -{ - http_parser_pause(p, 1); - *current_pause_parser = settings_dontcall; - return request_url_cb(p, buf, len); -} - -int -pause_body_cb (http_parser *p, const char *buf, size_t len) -{ - http_parser_pause(p, 1); - *current_pause_parser = settings_dontcall; - return body_cb(p, buf, len); -} - -int -pause_headers_complete_cb (http_parser *p) -{ - http_parser_pause(p, 1); - *current_pause_parser = settings_dontcall; - return headers_complete_cb(p); -} - -int -pause_message_complete_cb (http_parser *p) -{ - http_parser_pause(p, 1); - *current_pause_parser = settings_dontcall; - return message_complete_cb(p); -} - -int -pause_response_status_cb (http_parser *p, const char *buf, size_t len) -{ - http_parser_pause(p, 1); - *current_pause_parser = settings_dontcall; - return response_status_cb(p, buf, len); -} - -int -pause_chunk_header_cb (http_parser *p) -{ - http_parser_pause(p, 1); - *current_pause_parser = settings_dontcall; - return chunk_header_cb(p); -} - -int -pause_chunk_complete_cb (http_parser *p) -{ - http_parser_pause(p, 1); - *current_pause_parser = settings_dontcall; - return chunk_complete_cb(p); -} - -int -connect_headers_complete_cb (http_parser *p) -{ - headers_complete_cb(p); - return 1; -} - -int -connect_message_complete_cb (http_parser *p) -{ - messages[num_messages].should_keep_alive = http_should_keep_alive(&parser); - return message_complete_cb(p); -} - -static http_parser_settings settings_pause = - {.on_message_begin = pause_message_begin_cb - ,.on_header_field = pause_header_field_cb - ,.on_header_value = pause_header_value_cb - ,.on_url = pause_request_url_cb - ,.on_status = pause_response_status_cb - ,.on_body = pause_body_cb - ,.on_headers_complete = pause_headers_complete_cb - ,.on_message_complete = pause_message_complete_cb - ,.on_chunk_header = pause_chunk_header_cb - ,.on_chunk_complete = pause_chunk_complete_cb - }; - -static http_parser_settings settings = - {.on_message_begin = message_begin_cb - ,.on_header_field = header_field_cb - ,.on_header_value = header_value_cb - ,.on_url = request_url_cb - ,.on_status = response_status_cb - ,.on_body = body_cb - ,.on_headers_complete = headers_complete_cb - ,.on_message_complete = message_complete_cb - ,.on_chunk_header = chunk_header_cb - ,.on_chunk_complete = chunk_complete_cb - }; - -static http_parser_settings settings_count_body = - {.on_message_begin = message_begin_cb - ,.on_header_field = header_field_cb - ,.on_header_value = header_value_cb - ,.on_url = request_url_cb - ,.on_status = response_status_cb - ,.on_body = count_body_cb - ,.on_headers_complete = headers_complete_cb - ,.on_message_complete = message_complete_cb - ,.on_chunk_header = chunk_header_cb - ,.on_chunk_complete = chunk_complete_cb - }; - -static http_parser_settings settings_connect = - {.on_message_begin = message_begin_cb - ,.on_header_field = header_field_cb - ,.on_header_value = header_value_cb - ,.on_url = request_url_cb - ,.on_status = response_status_cb - ,.on_body = dontcall_body_cb - ,.on_headers_complete = connect_headers_complete_cb - ,.on_message_complete = connect_message_complete_cb - ,.on_chunk_header = chunk_header_cb - ,.on_chunk_complete = chunk_complete_cb - }; - -static http_parser_settings settings_null = - {.on_message_begin = 0 - ,.on_header_field = 0 - ,.on_header_value = 0 - ,.on_url = 0 - ,.on_status = 0 - ,.on_body = 0 - ,.on_headers_complete = 0 - ,.on_message_complete = 0 - ,.on_chunk_header = 0 - ,.on_chunk_complete = 0 - }; - -void -parser_init (enum http_parser_type type) -{ - num_messages = 0; - http_parser_init(&parser, type); - memset(&messages, 0, sizeof messages); -} - -size_t parse (const char *buf, size_t len) -{ - size_t nparsed; - currently_parsing_eof = (len == 0); - nparsed = http_parser_execute(&parser, &settings, buf, len); - return nparsed; -} - -size_t parse_count_body (const char *buf, size_t len) -{ - size_t nparsed; - currently_parsing_eof = (len == 0); - nparsed = http_parser_execute(&parser, &settings_count_body, buf, len); - return nparsed; -} - -size_t parse_pause (const char *buf, size_t len) -{ - size_t nparsed; - http_parser_settings s = settings_pause; - - currently_parsing_eof = (len == 0); - current_pause_parser = &s; - nparsed = http_parser_execute(&parser, current_pause_parser, buf, len); - return nparsed; -} - -size_t parse_connect (const char *buf, size_t len) -{ - size_t nparsed; - currently_parsing_eof = (len == 0); - nparsed = http_parser_execute(&parser, &settings_connect, buf, len); - return nparsed; -} - -static inline int -check_str_eq (const struct message *m, - const char *prop, - const char *expected, - const char *found) { - if ((expected == NULL) != (found == NULL)) { - printf("\n*** Error: %s in '%s' ***\n\n", prop, m->name); - printf("expected %s\n", (expected == NULL) ? "NULL" : expected); - printf(" found %s\n", (found == NULL) ? "NULL" : found); - return 0; - } - if (expected != NULL && 0 != strcmp(expected, found)) { - printf("\n*** Error: %s in '%s' ***\n\n", prop, m->name); - printf("expected '%s'\n", expected); - printf(" found '%s'\n", found); - return 0; - } - return 1; -} - -static inline int -check_num_eq (const struct message *m, - const char *prop, - int expected, - int found) { - if (expected != found) { - printf("\n*** Error: %s in '%s' ***\n\n", prop, m->name); - printf("expected %d\n", expected); - printf(" found %d\n", found); - return 0; - } - return 1; -} - -#define MESSAGE_CHECK_STR_EQ(expected, found, prop) \ - if (!check_str_eq(expected, #prop, expected->prop, found->prop)) return 0 - -#define MESSAGE_CHECK_NUM_EQ(expected, found, prop) \ - if (!check_num_eq(expected, #prop, expected->prop, found->prop)) return 0 - -#define MESSAGE_CHECK_URL_EQ(u, expected, found, prop, fn) \ -do { \ - char ubuf[256]; \ - \ - if ((u)->field_set & (1 << (fn))) { \ - memcpy(ubuf, (found)->request_url + (u)->field_data[(fn)].off, \ - (u)->field_data[(fn)].len); \ - ubuf[(u)->field_data[(fn)].len] = '\0'; \ - } else { \ - ubuf[0] = '\0'; \ - } \ - \ - check_str_eq(expected, #prop, expected->prop, ubuf); \ -} while(0) - -int -message_eq (int index, int connect, const struct message *expected) -{ - int i; - struct message *m = &messages[index]; - - MESSAGE_CHECK_NUM_EQ(expected, m, http_major); - MESSAGE_CHECK_NUM_EQ(expected, m, http_minor); - - if (expected->type == HTTP_REQUEST) { - MESSAGE_CHECK_NUM_EQ(expected, m, method); - } else { - MESSAGE_CHECK_NUM_EQ(expected, m, status_code); - MESSAGE_CHECK_STR_EQ(expected, m, response_status); - assert(m->status_cb_called); - } - - if (!connect) { - MESSAGE_CHECK_NUM_EQ(expected, m, should_keep_alive); - MESSAGE_CHECK_NUM_EQ(expected, m, message_complete_on_eof); - } - - assert(m->message_begin_cb_called); - assert(m->headers_complete_cb_called); - assert(m->message_complete_cb_called); - - - MESSAGE_CHECK_STR_EQ(expected, m, request_url); - - /* Check URL components; we can't do this w/ CONNECT since it doesn't - * send us a well-formed URL. - */ - if (*m->request_url && m->method != HTTP_CONNECT) { - struct http_parser_url u; - - if (http_parser_parse_url(m->request_url, strlen(m->request_url), 0, &u)) { - fprintf(stderr, "\n\n*** failed to parse URL %s ***\n\n", - m->request_url); - abort(); - } - - if (expected->host) { - MESSAGE_CHECK_URL_EQ(&u, expected, m, host, UF_HOST); - } - - if (expected->userinfo) { - MESSAGE_CHECK_URL_EQ(&u, expected, m, userinfo, UF_USERINFO); - } - - m->port = (u.field_set & (1 << UF_PORT)) ? - u.port : 0; - - MESSAGE_CHECK_URL_EQ(&u, expected, m, query_string, UF_QUERY); - MESSAGE_CHECK_URL_EQ(&u, expected, m, fragment, UF_FRAGMENT); - MESSAGE_CHECK_URL_EQ(&u, expected, m, request_path, UF_PATH); - MESSAGE_CHECK_NUM_EQ(expected, m, port); - } - - if (connect) { - check_num_eq(m, "body_size", 0, m->body_size); - } else if (expected->body_size) { - MESSAGE_CHECK_NUM_EQ(expected, m, body_size); - } else { - MESSAGE_CHECK_STR_EQ(expected, m, body); - } - - if (connect) { - check_num_eq(m, "num_chunks_complete", 0, m->num_chunks_complete); - } else { - assert(m->num_chunks == m->num_chunks_complete); - MESSAGE_CHECK_NUM_EQ(expected, m, num_chunks_complete); - for (i = 0; i < m->num_chunks && i < MAX_CHUNKS; i++) { - MESSAGE_CHECK_NUM_EQ(expected, m, chunk_lengths[i]); - } - } - - MESSAGE_CHECK_NUM_EQ(expected, m, num_headers); - - int r; - for (i = 0; i < m->num_headers; i++) { - r = check_str_eq(expected, "header field", expected->headers[i][0], m->headers[i][0]); - if (!r) return 0; - r = check_str_eq(expected, "header value", expected->headers[i][1], m->headers[i][1]); - if (!r) return 0; - } - - if (!connect) { - MESSAGE_CHECK_STR_EQ(expected, m, upgrade); - } - - return 1; -} - -/* Given a sequence of varargs messages, return the number of them that the - * parser should successfully parse, taking into account that upgraded - * messages prevent all subsequent messages from being parsed. - */ -size_t -count_parsed_messages(const size_t nmsgs, ...) { - size_t i; - va_list ap; - - va_start(ap, nmsgs); - - for (i = 0; i < nmsgs; i++) { - struct message *m = va_arg(ap, struct message *); - - if (m->upgrade) { - va_end(ap); - return i + 1; - } - } - - va_end(ap); - return nmsgs; -} - -/* Given a sequence of bytes and the number of these that we were able to - * parse, verify that upgrade bodies are correct. - */ -void -upgrade_message_fix(char *body, const size_t nread, const size_t nmsgs, ...) { - va_list ap; - size_t i; - size_t off = 0; - - va_start(ap, nmsgs); - - for (i = 0; i < nmsgs; i++) { - struct message *m = va_arg(ap, struct message *); - - off += strlen(m->raw); - - if (m->upgrade) { - off -= strlen(m->upgrade); - - /* Check the portion of the response after its specified upgrade */ - if (!check_str_eq(m, "upgrade", body + off, body + nread)) { - abort(); - } - - /* Fix up the response so that message_eq() will verify the beginning - * of the upgrade */ - *(body + nread + strlen(m->upgrade)) = '\0'; - messages[num_messages -1 ].upgrade = body + nread; - - va_end(ap); - return; - } - } - - va_end(ap); - printf("\n\n*** Error: expected a message with upgrade ***\n"); - - abort(); -} - -static void -print_error (const char *raw, size_t error_location) -{ - fprintf(stderr, "\n*** %s ***\n\n", - http_errno_description(HTTP_PARSER_ERRNO(&parser))); - - int this_line = 0, char_len = 0; - size_t i, j, len = strlen(raw), error_location_line = 0; - for (i = 0; i < len; i++) { - if (i == error_location) this_line = 1; - switch (raw[i]) { - case '\r': - char_len = 2; - fprintf(stderr, "\\r"); - break; - - case '\n': - fprintf(stderr, "\\n\n"); - - if (this_line) goto print; - - error_location_line = 0; - continue; - - default: - char_len = 1; - fputc(raw[i], stderr); - break; - } - if (!this_line) error_location_line += char_len; - } - - fprintf(stderr, "[eof]\n"); - - print: - for (j = 0; j < error_location_line; j++) { - fputc(' ', stderr); - } - fprintf(stderr, "^\n\nerror location: %u\n", (unsigned int)error_location); -} - -void -test_preserve_data (void) -{ - char my_data[] = "application-specific data"; - http_parser parser; - parser.data = my_data; - http_parser_init(&parser, HTTP_REQUEST); - if (parser.data != my_data) { - printf("\n*** parser.data not preserved accross http_parser_init ***\n\n"); - abort(); - } -} - -struct url_test { - const char *name; - const char *url; - int is_connect; - struct http_parser_url u; - int rv; -}; - -const struct url_test url_tests[] = -{ {.name="proxy request" - ,.url="http://hostname/" - ,.is_connect=0 - ,.u= - {.field_set=(1 << UF_SCHEMA) | (1 << UF_HOST) | (1 << UF_PATH) - ,.port=0 - ,.field_data= - {{ 0, 4 } /* UF_SCHEMA */ - ,{ 7, 8 } /* UF_HOST */ - ,{ 0, 0 } /* UF_PORT */ - ,{ 15, 1 } /* UF_PATH */ - ,{ 0, 0 } /* UF_QUERY */ - ,{ 0, 0 } /* UF_FRAGMENT */ - ,{ 0, 0 } /* UF_USERINFO */ - } - } - ,.rv=0 - } - -, {.name="proxy request with port" - ,.url="http://hostname:444/" - ,.is_connect=0 - ,.u= - {.field_set=(1 << UF_SCHEMA) | (1 << UF_HOST) | (1 << UF_PORT) | (1 << UF_PATH) - ,.port=444 - ,.field_data= - {{ 0, 4 } /* UF_SCHEMA */ - ,{ 7, 8 } /* UF_HOST */ - ,{ 16, 3 } /* UF_PORT */ - ,{ 19, 1 } /* UF_PATH */ - ,{ 0, 0 } /* UF_QUERY */ - ,{ 0, 0 } /* UF_FRAGMENT */ - ,{ 0, 0 } /* UF_USERINFO */ - } - } - ,.rv=0 - } - -, {.name="CONNECT request" - ,.url="hostname:443" - ,.is_connect=1 - ,.u= - {.field_set=(1 << UF_HOST) | (1 << UF_PORT) - ,.port=443 - ,.field_data= - {{ 0, 0 } /* UF_SCHEMA */ - ,{ 0, 8 } /* UF_HOST */ - ,{ 9, 3 } /* UF_PORT */ - ,{ 0, 0 } /* UF_PATH */ - ,{ 0, 0 } /* UF_QUERY */ - ,{ 0, 0 } /* UF_FRAGMENT */ - ,{ 0, 0 } /* UF_USERINFO */ - } - } - ,.rv=0 - } - -, {.name="CONNECT request but not connect" - ,.url="hostname:443" - ,.is_connect=0 - ,.rv=1 - } - -, {.name="proxy ipv6 request" - ,.url="http://[1:2::3:4]/" - ,.is_connect=0 - ,.u= - {.field_set=(1 << UF_SCHEMA) | (1 << UF_HOST) | (1 << UF_PATH) - ,.port=0 - ,.field_data= - {{ 0, 4 } /* UF_SCHEMA */ - ,{ 8, 8 } /* UF_HOST */ - ,{ 0, 0 } /* UF_PORT */ - ,{ 17, 1 } /* UF_PATH */ - ,{ 0, 0 } /* UF_QUERY */ - ,{ 0, 0 } /* UF_FRAGMENT */ - ,{ 0, 0 } /* UF_USERINFO */ - } - } - ,.rv=0 - } - -, {.name="proxy ipv6 request with port" - ,.url="http://[1:2::3:4]:67/" - ,.is_connect=0 - ,.u= - {.field_set=(1 << UF_SCHEMA) | (1 << UF_HOST) | (1 << UF_PORT) | (1 << UF_PATH) - ,.port=67 - ,.field_data= - {{ 0, 4 } /* UF_SCHEMA */ - ,{ 8, 8 } /* UF_HOST */ - ,{ 18, 2 } /* UF_PORT */ - ,{ 20, 1 } /* UF_PATH */ - ,{ 0, 0 } /* UF_QUERY */ - ,{ 0, 0 } /* UF_FRAGMENT */ - ,{ 0, 0 } /* UF_USERINFO */ - } - } - ,.rv=0 - } - -, {.name="CONNECT ipv6 address" - ,.url="[1:2::3:4]:443" - ,.is_connect=1 - ,.u= - {.field_set=(1 << UF_HOST) | (1 << UF_PORT) - ,.port=443 - ,.field_data= - {{ 0, 0 } /* UF_SCHEMA */ - ,{ 1, 8 } /* UF_HOST */ - ,{ 11, 3 } /* UF_PORT */ - ,{ 0, 0 } /* UF_PATH */ - ,{ 0, 0 } /* UF_QUERY */ - ,{ 0, 0 } /* UF_FRAGMENT */ - ,{ 0, 0 } /* UF_USERINFO */ - } - } - ,.rv=0 - } - -, {.name="ipv4 in ipv6 address" - ,.url="http://[2001:0000:0000:0000:0000:0000:1.9.1.1]/" - ,.is_connect=0 - ,.u= - {.field_set=(1 << UF_SCHEMA) | (1 << UF_HOST) | (1 << UF_PATH) - ,.port=0 - ,.field_data= - {{ 0, 4 } /* UF_SCHEMA */ - ,{ 8, 37 } /* UF_HOST */ - ,{ 0, 0 } /* UF_PORT */ - ,{ 46, 1 } /* UF_PATH */ - ,{ 0, 0 } /* UF_QUERY */ - ,{ 0, 0 } /* UF_FRAGMENT */ - ,{ 0, 0 } /* UF_USERINFO */ - } - } - ,.rv=0 - } - -, {.name="extra ? in query string" - ,.url="http://a.tbcdn.cn/p/fp/2010c/??fp-header-min.css,fp-base-min.css," - "fp-channel-min.css,fp-product-min.css,fp-mall-min.css,fp-category-min.css," - "fp-sub-min.css,fp-gdp4p-min.css,fp-css3-min.css,fp-misc-min.css?t=20101022.css" - ,.is_connect=0 - ,.u= - {.field_set=(1<field_set, u->port); - for (i = 0; i < UF_MAX; i++) { - if ((u->field_set & (1 << i)) == 0) { - printf("\tfield_data[%u]: unset\n", i); - continue; - } - - printf("\tfield_data[%u]: off: %u len: %u part: \"%.*s\n\"", - i, - u->field_data[i].off, - u->field_data[i].len, - u->field_data[i].len, - url + u->field_data[i].off); - } -} - -void -test_parse_url (void) -{ - struct http_parser_url u; - const struct url_test *test; - unsigned int i; - int rv; - - for (i = 0; i < (sizeof(url_tests) / sizeof(url_tests[0])); i++) { - test = &url_tests[i]; - memset(&u, 0, sizeof(u)); - - rv = http_parser_parse_url(test->url, - test->url ? strlen(test->url) : 0, - test->is_connect, - &u); - - if (test->rv == 0) { - if (rv != 0) { - printf("\n*** http_parser_parse_url(\"%s\") \"%s\" test failed, " - "unexpected rv %d ***\n\n", test->url, test->name, rv); - abort(); - } - - if (memcmp(&u, &test->u, sizeof(u)) != 0) { - printf("\n*** http_parser_parse_url(\"%s\") \"%s\" failed ***\n", - test->url, test->name); - - printf("target http_parser_url:\n"); - dump_url(test->url, &test->u); - printf("result http_parser_url:\n"); - dump_url(test->url, &u); - - abort(); - } - } else { - /* test->rv != 0 */ - if (rv == 0) { - printf("\n*** http_parser_parse_url(\"%s\") \"%s\" test failed, " - "unexpected rv %d ***\n\n", test->url, test->name, rv); - abort(); - } - } - } -} - -void -test_method_str (void) -{ - assert(0 == strcmp("GET", http_method_str(HTTP_GET))); - assert(0 == strcmp("", http_method_str(1337))); -} - -void -test_status_str (void) -{ - assert(0 == strcmp("OK", http_status_str(HTTP_STATUS_OK))); - assert(0 == strcmp("Not Found", http_status_str(HTTP_STATUS_NOT_FOUND))); - assert(0 == strcmp("", http_status_str(1337))); -} - -void -test_message (const struct message *message) -{ - size_t raw_len = strlen(message->raw); - size_t msg1len; - for (msg1len = 0; msg1len < raw_len; msg1len++) { - parser_init(message->type); - - size_t read; - const char *msg1 = message->raw; - const char *msg2 = msg1 + msg1len; - size_t msg2len = raw_len - msg1len; - - if (msg1len) { - assert(num_messages == 0); - messages[0].headers_complete_cb_called = FALSE; - - read = parse(msg1, msg1len); - - if (!messages[0].headers_complete_cb_called && parser.nread != read) { - assert(parser.nread == read); - print_error(msg1, read); - abort(); - } - - if (message->upgrade && parser.upgrade && num_messages > 0) { - messages[num_messages - 1].upgrade = msg1 + read; - goto test; - } - - if (read != msg1len) { - print_error(msg1, read); - abort(); - } - } - - - read = parse(msg2, msg2len); - - if (message->upgrade && parser.upgrade) { - messages[num_messages - 1].upgrade = msg2 + read; - goto test; - } - - if (read != msg2len) { - print_error(msg2, read); - abort(); - } - - read = parse(NULL, 0); - - if (read != 0) { - print_error(message->raw, read); - abort(); - } - - test: - - if (num_messages != 1) { - printf("\n*** num_messages != 1 after testing '%s' ***\n\n", message->name); - abort(); - } - - if(!message_eq(0, 0, message)) abort(); - } -} - -void -test_message_count_body (const struct message *message) -{ - parser_init(message->type); - - size_t read; - size_t l = strlen(message->raw); - size_t i, toread; - size_t chunk = 4024; - - for (i = 0; i < l; i+= chunk) { - toread = MIN(l-i, chunk); - read = parse_count_body(message->raw + i, toread); - if (read != toread) { - print_error(message->raw, read); - abort(); - } - } - - - read = parse_count_body(NULL, 0); - if (read != 0) { - print_error(message->raw, read); - abort(); - } - - if (num_messages != 1) { - printf("\n*** num_messages != 1 after testing '%s' ***\n\n", message->name); - abort(); - } - - if(!message_eq(0, 0, message)) abort(); -} - -void -test_simple_type (const char *buf, - enum http_errno err_expected, - enum http_parser_type type) -{ - parser_init(type); - - enum http_errno err; - - parse(buf, strlen(buf)); - err = HTTP_PARSER_ERRNO(&parser); - parse(NULL, 0); - - /* In strict mode, allow us to pass with an unexpected HPE_STRICT as - * long as the caller isn't expecting success. - */ -#if HTTP_PARSER_STRICT - if (err_expected != err && err_expected != HPE_OK && err != HPE_STRICT) { -#else - if (err_expected != err) { -#endif - fprintf(stderr, "\n*** test_simple expected %s, but saw %s ***\n\n%s\n", - http_errno_name(err_expected), http_errno_name(err), buf); - abort(); - } -} - -void -test_simple (const char *buf, enum http_errno err_expected) -{ - test_simple_type(buf, err_expected, HTTP_REQUEST); -} - -void -test_invalid_header_content (int req, const char* str) -{ - http_parser parser; - http_parser_init(&parser, req ? HTTP_REQUEST : HTTP_RESPONSE); - size_t parsed; - const char *buf; - buf = req ? - "GET / HTTP/1.1\r\n" : - "HTTP/1.1 200 OK\r\n"; - parsed = http_parser_execute(&parser, &settings_null, buf, strlen(buf)); - assert(parsed == strlen(buf)); - - buf = str; - size_t buflen = strlen(buf); - - parsed = http_parser_execute(&parser, &settings_null, buf, buflen); - if (parsed != buflen) { - assert(HTTP_PARSER_ERRNO(&parser) == HPE_INVALID_HEADER_TOKEN); - return; - } - - fprintf(stderr, - "\n*** Error expected but none in invalid header content test ***\n"); - abort(); -} - -void -test_invalid_header_field_content_error (int req) -{ - test_invalid_header_content(req, "Foo: F\01ailure"); - test_invalid_header_content(req, "Foo: B\02ar"); -} - -void -test_invalid_header_field (int req, const char* str) -{ - http_parser parser; - http_parser_init(&parser, req ? HTTP_REQUEST : HTTP_RESPONSE); - size_t parsed; - const char *buf; - buf = req ? - "GET / HTTP/1.1\r\n" : - "HTTP/1.1 200 OK\r\n"; - parsed = http_parser_execute(&parser, &settings_null, buf, strlen(buf)); - assert(parsed == strlen(buf)); - - buf = str; - size_t buflen = strlen(buf); - - parsed = http_parser_execute(&parser, &settings_null, buf, buflen); - if (parsed != buflen) { - assert(HTTP_PARSER_ERRNO(&parser) == HPE_INVALID_HEADER_TOKEN); - return; - } - - fprintf(stderr, - "\n*** Error expected but none in invalid header token test ***\n"); - abort(); -} - -void -test_invalid_header_field_token_error (int req) -{ - test_invalid_header_field(req, "Fo@: Failure"); - test_invalid_header_field(req, "Foo\01\test: Bar"); -} - -void -test_double_content_length_error (int req) -{ - http_parser parser; - http_parser_init(&parser, req ? HTTP_REQUEST : HTTP_RESPONSE); - size_t parsed; - const char *buf; - buf = req ? - "GET / HTTP/1.1\r\n" : - "HTTP/1.1 200 OK\r\n"; - parsed = http_parser_execute(&parser, &settings_null, buf, strlen(buf)); - assert(parsed == strlen(buf)); - - buf = "Content-Length: 0\r\nContent-Length: 1\r\n\r\n"; - size_t buflen = strlen(buf); - - parsed = http_parser_execute(&parser, &settings_null, buf, buflen); - if (parsed != buflen) { - assert(HTTP_PARSER_ERRNO(&parser) == HPE_UNEXPECTED_CONTENT_LENGTH); - return; - } - - fprintf(stderr, - "\n*** Error expected but none in double content-length test ***\n"); - abort(); -} - -void -test_chunked_content_length_error (int req) -{ - http_parser parser; - http_parser_init(&parser, req ? HTTP_REQUEST : HTTP_RESPONSE); - size_t parsed; - const char *buf; - buf = req ? - "GET / HTTP/1.1\r\n" : - "HTTP/1.1 200 OK\r\n"; - parsed = http_parser_execute(&parser, &settings_null, buf, strlen(buf)); - assert(parsed == strlen(buf)); - - buf = "Transfer-Encoding: anything\r\nContent-Length: 1\r\n\r\n"; - size_t buflen = strlen(buf); - - parsed = http_parser_execute(&parser, &settings_null, buf, buflen); - if (parsed != buflen) { - assert(HTTP_PARSER_ERRNO(&parser) == HPE_UNEXPECTED_CONTENT_LENGTH); - return; - } - - fprintf(stderr, - "\n*** Error expected but none in chunked content-length test ***\n"); - abort(); -} - -void -test_header_cr_no_lf_error (int req) -{ - http_parser parser; - http_parser_init(&parser, req ? HTTP_REQUEST : HTTP_RESPONSE); - size_t parsed; - const char *buf; - buf = req ? - "GET / HTTP/1.1\r\n" : - "HTTP/1.1 200 OK\r\n"; - parsed = http_parser_execute(&parser, &settings_null, buf, strlen(buf)); - assert(parsed == strlen(buf)); - - buf = "Foo: 1\rBar: 1\r\n\r\n"; - size_t buflen = strlen(buf); - - parsed = http_parser_execute(&parser, &settings_null, buf, buflen); - if (parsed != buflen) { - assert(HTTP_PARSER_ERRNO(&parser) == HPE_LF_EXPECTED); - return; - } - - fprintf(stderr, - "\n*** Error expected but none in header whitespace test ***\n"); - abort(); -} - -void -test_no_overflow_parse_url (void) -{ - int rv; - struct http_parser_url u; - - http_parser_url_init(&u); - rv = http_parser_parse_url("http://example.com:8001", 22, 0, &u); - - if (rv != 0) { - fprintf(stderr, - "\n*** test_no_overflow_parse_url invalid return value=%d\n", - rv); - abort(); - } - - if (u.port != 800) { - fprintf(stderr, - "\n*** test_no_overflow_parse_url invalid port number=%d\n", - u.port); - abort(); - } -} - -void -test_header_overflow_error (int req) -{ - http_parser parser; - http_parser_init(&parser, req ? HTTP_REQUEST : HTTP_RESPONSE); - size_t parsed; - const char *buf; - buf = req ? "GET / HTTP/1.1\r\n" : "HTTP/1.0 200 OK\r\n"; - parsed = http_parser_execute(&parser, &settings_null, buf, strlen(buf)); - assert(parsed == strlen(buf)); - - buf = "header-key: header-value\r\n"; - size_t buflen = strlen(buf); - - int i; - for (i = 0; i < 10000; i++) { - parsed = http_parser_execute(&parser, &settings_null, buf, buflen); - if (parsed != buflen) { - //fprintf(stderr, "error found on iter %d\n", i); - assert(HTTP_PARSER_ERRNO(&parser) == HPE_HEADER_OVERFLOW); - return; - } - } - - fprintf(stderr, "\n*** Error expected but none in header overflow test ***\n"); - abort(); -} - - -void -test_header_nread_value () -{ - http_parser parser; - http_parser_init(&parser, HTTP_REQUEST); - size_t parsed; - const char *buf; - buf = "GET / HTTP/1.1\r\nheader: value\nhdr: value\r\n"; - parsed = http_parser_execute(&parser, &settings_null, buf, strlen(buf)); - assert(parsed == strlen(buf)); - - assert(parser.nread == strlen(buf)); -} - - -static void -test_content_length_overflow (const char *buf, size_t buflen, int expect_ok) -{ - http_parser parser; - http_parser_init(&parser, HTTP_RESPONSE); - http_parser_execute(&parser, &settings_null, buf, buflen); - - if (expect_ok) - assert(HTTP_PARSER_ERRNO(&parser) == HPE_OK); - else - assert(HTTP_PARSER_ERRNO(&parser) == HPE_INVALID_CONTENT_LENGTH); -} - -void -test_header_content_length_overflow_error (void) -{ -#define X(size) \ - "HTTP/1.1 200 OK\r\n" \ - "Content-Length: " #size "\r\n" \ - "\r\n" - const char a[] = X(1844674407370955160); /* 2^64 / 10 - 1 */ - const char b[] = X(18446744073709551615); /* 2^64-1 */ - const char c[] = X(18446744073709551616); /* 2^64 */ -#undef X - test_content_length_overflow(a, sizeof(a) - 1, 1); /* expect ok */ - test_content_length_overflow(b, sizeof(b) - 1, 0); /* expect failure */ - test_content_length_overflow(c, sizeof(c) - 1, 0); /* expect failure */ -} - -void -test_chunk_content_length_overflow_error (void) -{ -#define X(size) \ - "HTTP/1.1 200 OK\r\n" \ - "Transfer-Encoding: chunked\r\n" \ - "\r\n" \ - #size "\r\n" \ - "..." - const char a[] = X(FFFFFFFFFFFFFFE); /* 2^64 / 16 - 1 */ - const char b[] = X(FFFFFFFFFFFFFFFF); /* 2^64-1 */ - const char c[] = X(10000000000000000); /* 2^64 */ -#undef X - test_content_length_overflow(a, sizeof(a) - 1, 1); /* expect ok */ - test_content_length_overflow(b, sizeof(b) - 1, 0); /* expect failure */ - test_content_length_overflow(c, sizeof(c) - 1, 0); /* expect failure */ -} - -void -test_no_overflow_long_body (int req, size_t length) -{ - http_parser parser; - http_parser_init(&parser, req ? HTTP_REQUEST : HTTP_RESPONSE); - size_t parsed; - size_t i; - char buf1[3000]; - size_t buf1len = sprintf(buf1, "%s\r\nConnection: Keep-Alive\r\nContent-Length: %lu\r\n\r\n", - req ? "POST / HTTP/1.0" : "HTTP/1.0 200 OK", (unsigned long)length); - parsed = http_parser_execute(&parser, &settings_null, buf1, buf1len); - if (parsed != buf1len) - goto err; - - for (i = 0; i < length; i++) { - char foo = 'a'; - parsed = http_parser_execute(&parser, &settings_null, &foo, 1); - if (parsed != 1) - goto err; - } - - parsed = http_parser_execute(&parser, &settings_null, buf1, buf1len); - if (parsed != buf1len) goto err; - return; - - err: - fprintf(stderr, - "\n*** error in test_no_overflow_long_body %s of length %lu ***\n", - req ? "REQUEST" : "RESPONSE", - (unsigned long)length); - abort(); -} - -void -test_multiple3 (const struct message *r1, const struct message *r2, const struct message *r3) -{ - int message_count = count_parsed_messages(3, r1, r2, r3); - - char total[ strlen(r1->raw) - + strlen(r2->raw) - + strlen(r3->raw) - + 1 - ]; - total[0] = '\0'; - - strcat(total, r1->raw); - strcat(total, r2->raw); - strcat(total, r3->raw); - - parser_init(r1->type); - - size_t read; - - read = parse(total, strlen(total)); - - if (parser.upgrade) { - upgrade_message_fix(total, read, 3, r1, r2, r3); - goto test; - } - - if (read != strlen(total)) { - print_error(total, read); - abort(); - } - - read = parse(NULL, 0); - - if (read != 0) { - print_error(total, read); - abort(); - } - -test: - - if (message_count != num_messages) { - fprintf(stderr, "\n\n*** Parser didn't see 3 messages only %d *** \n", num_messages); - abort(); - } - - if (!message_eq(0, 0, r1)) abort(); - if (message_count > 1 && !message_eq(1, 0, r2)) abort(); - if (message_count > 2 && !message_eq(2, 0, r3)) abort(); -} - -/* SCAN through every possible breaking to make sure the - * parser can handle getting the content in any chunks that - * might come from the socket - */ -void -test_scan (const struct message *r1, const struct message *r2, const struct message *r3) -{ - char total[80*1024] = "\0"; - char buf1[80*1024] = "\0"; - char buf2[80*1024] = "\0"; - char buf3[80*1024] = "\0"; - - strcat(total, r1->raw); - strcat(total, r2->raw); - strcat(total, r3->raw); - - size_t read; - - int total_len = strlen(total); - - int total_ops = 2 * (total_len - 1) * (total_len - 2) / 2; - int ops = 0 ; - - size_t buf1_len, buf2_len, buf3_len; - int message_count = count_parsed_messages(3, r1, r2, r3); - - int i,j,type_both; - for (type_both = 0; type_both < 2; type_both ++ ) { - for (j = 2; j < total_len; j ++ ) { - for (i = 1; i < j; i ++ ) { - - if (ops % 1000 == 0) { - printf("\b\b\b\b%3.0f%%", 100 * (float)ops /(float)total_ops); - fflush(stdout); - } - ops += 1; - - parser_init(type_both ? HTTP_BOTH : r1->type); - - buf1_len = i; - strlncpy(buf1, sizeof(buf1), total, buf1_len); - buf1[buf1_len] = 0; - - buf2_len = j - i; - strlncpy(buf2, sizeof(buf1), total+i, buf2_len); - buf2[buf2_len] = 0; - - buf3_len = total_len - j; - strlncpy(buf3, sizeof(buf1), total+j, buf3_len); - buf3[buf3_len] = 0; - - assert(num_messages == 0); - messages[0].headers_complete_cb_called = FALSE; - - read = parse(buf1, buf1_len); - - if (!messages[0].headers_complete_cb_called && parser.nread != read) { - print_error(buf1, read); - goto error; - } - - if (parser.upgrade) goto test; - - if (read != buf1_len) { - print_error(buf1, read); - goto error; - } - - read += parse(buf2, buf2_len); - - if (parser.upgrade) goto test; - - if (read != buf1_len + buf2_len) { - print_error(buf2, read); - goto error; - } - - read += parse(buf3, buf3_len); - - if (parser.upgrade) goto test; - - if (read != buf1_len + buf2_len + buf3_len) { - print_error(buf3, read); - goto error; - } - - parse(NULL, 0); - -test: - if (parser.upgrade) { - upgrade_message_fix(total, read, 3, r1, r2, r3); - } - - if (message_count != num_messages) { - fprintf(stderr, "\n\nParser didn't see %d messages only %d\n", - message_count, num_messages); - goto error; - } - - if (!message_eq(0, 0, r1)) { - fprintf(stderr, "\n\nError matching messages[0] in test_scan.\n"); - goto error; - } - - if (message_count > 1 && !message_eq(1, 0, r2)) { - fprintf(stderr, "\n\nError matching messages[1] in test_scan.\n"); - goto error; - } - - if (message_count > 2 && !message_eq(2, 0, r3)) { - fprintf(stderr, "\n\nError matching messages[2] in test_scan.\n"); - goto error; - } - } - } - } - puts("\b\b\b\b100%"); - return; - - error: - fprintf(stderr, "i=%d j=%d\n", i, j); - fprintf(stderr, "buf1 (%u) %s\n\n", (unsigned int)buf1_len, buf1); - fprintf(stderr, "buf2 (%u) %s\n\n", (unsigned int)buf2_len , buf2); - fprintf(stderr, "buf3 (%u) %s\n", (unsigned int)buf3_len, buf3); - abort(); -} - -// user required to free the result -// string terminated by \0 -char * -create_large_chunked_message (int body_size_in_kb, const char* headers) -{ - int i; - size_t wrote = 0; - size_t headers_len = strlen(headers); - size_t bufsize = headers_len + (5+1024+2)*body_size_in_kb + 6; - char * buf = malloc(bufsize); - - memcpy(buf, headers, headers_len); - wrote += headers_len; - - for (i = 0; i < body_size_in_kb; i++) { - // write 1kb chunk into the body. - memcpy(buf + wrote, "400\r\n", 5); - wrote += 5; - memset(buf + wrote, 'C', 1024); - wrote += 1024; - strcpy(buf + wrote, "\r\n"); - wrote += 2; - } - - memcpy(buf + wrote, "0\r\n\r\n", 6); - wrote += 6; - assert(wrote == bufsize); - - return buf; -} - -/* Verify that we can pause parsing at any of the bytes in the - * message and still get the result that we're expecting. */ -void -test_message_pause (const struct message *msg) -{ - char *buf = (char*) msg->raw; - size_t buflen = strlen(msg->raw); - size_t nread; - - parser_init(msg->type); - - do { - nread = parse_pause(buf, buflen); - - // We can only set the upgrade buffer once we've gotten our message - // completion callback. - if (messages[0].message_complete_cb_called && - msg->upgrade && - parser.upgrade) { - messages[0].upgrade = buf + nread; - goto test; - } - - if (nread < buflen) { - - // Not much do to if we failed a strict-mode check - if (HTTP_PARSER_ERRNO(&parser) == HPE_STRICT) { - return; - } - - assert (HTTP_PARSER_ERRNO(&parser) == HPE_PAUSED); - } - - buf += nread; - buflen -= nread; - http_parser_pause(&parser, 0); - } while (buflen > 0); - - nread = parse_pause(NULL, 0); - assert (nread == 0); - -test: - if (num_messages != 1) { - printf("\n*** num_messages != 1 after testing '%s' ***\n\n", msg->name); - abort(); - } - - if(!message_eq(0, 0, msg)) abort(); -} - -/* Verify that body and next message won't be parsed in responses to CONNECT */ -void -test_message_connect (const struct message *msg) -{ - char *buf = (char*) msg->raw; - size_t buflen = strlen(msg->raw); - - parser_init(msg->type); - - parse_connect(buf, buflen); - - if (num_messages != 1) { - printf("\n*** num_messages != 1 after testing '%s' ***\n\n", msg->name); - abort(); - } - - if(!message_eq(0, 1, msg)) abort(); -} - -int -main (void) -{ - unsigned i, j, k; - unsigned long version; - unsigned major; - unsigned minor; - unsigned patch; - - version = http_parser_version(); - major = (version >> 16) & 255; - minor = (version >> 8) & 255; - patch = version & 255; - printf("http_parser v%u.%u.%u (0x%06lx)\n", major, minor, patch, version); - - printf("sizeof(http_parser) = %u\n", (unsigned int)sizeof(http_parser)); - assert(sizeof(http_parser) == 4 + 4 + 8 + 2 + 2 + 4 + sizeof(void *)); - - //// API - test_preserve_data(); - test_parse_url(); - test_method_str(); - test_status_str(); - - //// NREAD - test_header_nread_value(); - - //// OVERFLOW CONDITIONS - test_no_overflow_parse_url(); - - test_header_overflow_error(HTTP_REQUEST); - test_no_overflow_long_body(HTTP_REQUEST, 1000); - test_no_overflow_long_body(HTTP_REQUEST, 100000); - - test_header_overflow_error(HTTP_RESPONSE); - test_no_overflow_long_body(HTTP_RESPONSE, 1000); - test_no_overflow_long_body(HTTP_RESPONSE, 100000); - - test_header_content_length_overflow_error(); - test_chunk_content_length_overflow_error(); - - //// HEADER FIELD CONDITIONS - test_double_content_length_error(HTTP_REQUEST); - test_chunked_content_length_error(HTTP_REQUEST); - test_header_cr_no_lf_error(HTTP_REQUEST); - test_invalid_header_field_token_error(HTTP_REQUEST); - test_invalid_header_field_content_error(HTTP_REQUEST); - test_double_content_length_error(HTTP_RESPONSE); - test_chunked_content_length_error(HTTP_RESPONSE); - test_header_cr_no_lf_error(HTTP_RESPONSE); - test_invalid_header_field_token_error(HTTP_RESPONSE); - test_invalid_header_field_content_error(HTTP_RESPONSE); - - test_simple_type( - "POST / HTTP/1.1\r\n" - "Content-Length:\r\n" // empty - "\r\n", - HPE_INVALID_CONTENT_LENGTH, - HTTP_REQUEST); - - test_simple_type( - "POST / HTTP/1.1\r\n" - "Content-Length: 42 \r\n" // Note the surrounding whitespace. - "\r\n", - HPE_OK, - HTTP_REQUEST); - - test_simple_type( - "POST / HTTP/1.1\r\n" - "Content-Length: 4 2\r\n" - "\r\n", - HPE_INVALID_CONTENT_LENGTH, - HTTP_REQUEST); - - test_simple_type( - "POST / HTTP/1.1\r\n" - "Content-Length: 13 37\r\n" - "\r\n", - HPE_INVALID_CONTENT_LENGTH, - HTTP_REQUEST); - - test_simple_type( - "POST / HTTP/1.1\r\n" - "Content-Length: 42\r\n" - " Hello world!\r\n", - HPE_INVALID_CONTENT_LENGTH, - HTTP_REQUEST); - - test_simple_type( - "POST / HTTP/1.1\r\n" - "Content-Length: 42\r\n" - " \r\n", - HPE_OK, - HTTP_REQUEST); - - //// RESPONSES - - test_simple_type("HTP/1.1 200 OK\r\n\r\n", HPE_INVALID_VERSION, HTTP_RESPONSE); - test_simple_type("HTTP/01.1 200 OK\r\n\r\n", HPE_INVALID_VERSION, HTTP_RESPONSE); - test_simple_type("HTTP/11.1 200 OK\r\n\r\n", HPE_INVALID_VERSION, HTTP_RESPONSE); - test_simple_type("HTTP/1.01 200 OK\r\n\r\n", HPE_INVALID_VERSION, HTTP_RESPONSE); - test_simple_type("HTTP/1.1\t200 OK\r\n\r\n", HPE_INVALID_VERSION, HTTP_RESPONSE); - test_simple_type("\rHTTP/1.1\t200 OK\r\n\r\n", HPE_INVALID_VERSION, HTTP_RESPONSE); - - for (i = 0; i < ARRAY_SIZE(responses); i++) { - test_message(&responses[i]); - } - - for (i = 0; i < ARRAY_SIZE(responses); i++) { - test_message_pause(&responses[i]); - } - - for (i = 0; i < ARRAY_SIZE(responses); i++) { - test_message_connect(&responses[i]); - } - - for (i = 0; i < ARRAY_SIZE(responses); i++) { - if (!responses[i].should_keep_alive) continue; - for (j = 0; j < ARRAY_SIZE(responses); j++) { - if (!responses[j].should_keep_alive) continue; - for (k = 0; k < ARRAY_SIZE(responses); k++) { - test_multiple3(&responses[i], &responses[j], &responses[k]); - } - } - } - - test_message_count_body(&responses[NO_HEADERS_NO_BODY_404]); - test_message_count_body(&responses[TRAILING_SPACE_ON_CHUNKED_BODY]); - - // test very large chunked response - { - char * msg = create_large_chunked_message(31337, - "HTTP/1.0 200 OK\r\n" - "Transfer-Encoding: chunked\r\n" - "Content-Type: text/plain\r\n" - "\r\n"); - struct message large_chunked = - {.name= "large chunked" - ,.type= HTTP_RESPONSE - ,.raw= msg - ,.should_keep_alive= FALSE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 0 - ,.status_code= 200 - ,.response_status= "OK" - ,.num_headers= 2 - ,.headers= - { { "Transfer-Encoding", "chunked" } - , { "Content-Type", "text/plain" } - } - ,.body_size= 31337*1024 - ,.num_chunks_complete= 31338 - }; - for (i = 0; i < MAX_CHUNKS; i++) { - large_chunked.chunk_lengths[i] = 1024; - } - test_message_count_body(&large_chunked); - free(msg); - } - - - - printf("response scan 1/2 "); - test_scan( &responses[TRAILING_SPACE_ON_CHUNKED_BODY] - , &responses[NO_BODY_HTTP10_KA_204] - , &responses[NO_REASON_PHRASE] - ); - - printf("response scan 2/2 "); - test_scan( &responses[BONJOUR_MADAME_FR] - , &responses[UNDERSTORE_HEADER_KEY] - , &responses[NO_CARRIAGE_RET] - ); - - puts("responses okay"); - - - /// REQUESTS - - test_simple("GET / IHTTP/1.0\r\n\r\n", HPE_INVALID_CONSTANT); - test_simple("GET / ICE/1.0\r\n\r\n", HPE_INVALID_CONSTANT); - test_simple("GET / HTP/1.1\r\n\r\n", HPE_INVALID_VERSION); - test_simple("GET / HTTP/01.1\r\n\r\n", HPE_INVALID_VERSION); - test_simple("GET / HTTP/11.1\r\n\r\n", HPE_INVALID_VERSION); - test_simple("GET / HTTP/1.01\r\n\r\n", HPE_INVALID_VERSION); - - test_simple("GET / HTTP/1.0\r\nHello: w\1rld\r\n\r\n", HPE_INVALID_HEADER_TOKEN); - test_simple("GET / HTTP/1.0\r\nHello: woooo\2rld\r\n\r\n", HPE_INVALID_HEADER_TOKEN); - - // Extended characters - see nodejs/test/parallel/test-http-headers-obstext.js - test_simple("GET / HTTP/1.1\r\n" - "Test: Düsseldorf\r\n", - HPE_OK); - - // Well-formed but incomplete - test_simple("GET / HTTP/1.1\r\n" - "Content-Type: text/plain\r\n" - "Content-Length: 6\r\n" - "\r\n" - "fooba", - HPE_OK); - - // Unknown Transfer-Encoding in request - test_simple("GET / HTTP/1.1\r\n" - "Transfer-Encoding: unknown\r\n" - "\r\n", - HPE_INVALID_TRANSFER_ENCODING); - - static const char *all_methods[] = { - "DELETE", - "GET", - "HEAD", - "POST", - "PUT", - //"CONNECT", //CONNECT can't be tested like other methods, it's a tunnel - "OPTIONS", - "TRACE", - "COPY", - "LOCK", - "MKCOL", - "MOVE", - "PROPFIND", - "PROPPATCH", - "SEARCH", - "UNLOCK", - "BIND", - "REBIND", - "UNBIND", - "ACL", - "REPORT", - "MKACTIVITY", - "CHECKOUT", - "MERGE", - "M-SEARCH", - "NOTIFY", - "SUBSCRIBE", - "UNSUBSCRIBE", - "PATCH", - "PURGE", - "MKCALENDAR", - "LINK", - "UNLINK", - 0 }; - const char **this_method; - for (this_method = all_methods; *this_method; this_method++) { - char buf[200]; - sprintf(buf, "%s / HTTP/1.1\r\n\r\n", *this_method); - test_simple(buf, HPE_OK); - } - - static const char *bad_methods[] = { - "ASDF", - "C******", - "COLA", - "GEM", - "GETA", - "M****", - "MKCOLA", - "PROPPATCHA", - "PUN", - "PX", - "SA", - "hello world", - 0 }; - for (this_method = bad_methods; *this_method; this_method++) { - char buf[200]; - sprintf(buf, "%s / HTTP/1.1\r\n\r\n", *this_method); - test_simple(buf, HPE_INVALID_METHOD); - } - - // illegal header field name line folding - test_simple("GET / HTTP/1.1\r\n" - "name\r\n" - " : value\r\n" - "\r\n", - HPE_INVALID_HEADER_TOKEN); - - const char *dumbluck2 = - "GET / HTTP/1.1\r\n" - "X-SSL-Nonsense: -----BEGIN CERTIFICATE-----\r\n" - "\tMIIFbTCCBFWgAwIBAgICH4cwDQYJKoZIhvcNAQEFBQAwcDELMAkGA1UEBhMCVUsx\r\n" - "\tETAPBgNVBAoTCGVTY2llbmNlMRIwEAYDVQQLEwlBdXRob3JpdHkxCzAJBgNVBAMT\r\n" - "\tAkNBMS0wKwYJKoZIhvcNAQkBFh5jYS1vcGVyYXRvckBncmlkLXN1cHBvcnQuYWMu\r\n" - "\tdWswHhcNMDYwNzI3MTQxMzI4WhcNMDcwNzI3MTQxMzI4WjBbMQswCQYDVQQGEwJV\r\n" - "\tSzERMA8GA1UEChMIZVNjaWVuY2UxEzARBgNVBAsTCk1hbmNoZXN0ZXIxCzAJBgNV\r\n" - "\tBAcTmrsogriqMWLAk1DMRcwFQYDVQQDEw5taWNoYWVsIHBhcmQYJKoZIhvcNAQEB\r\n" - "\tBQADggEPADCCAQoCggEBANPEQBgl1IaKdSS1TbhF3hEXSl72G9J+WC/1R64fAcEF\r\n" - "\tW51rEyFYiIeZGx/BVzwXbeBoNUK41OK65sxGuflMo5gLflbwJtHBRIEKAfVVp3YR\r\n" - "\tgW7cMA/s/XKgL1GEC7rQw8lIZT8RApukCGqOVHSi/F1SiFlPDxuDfmdiNzL31+sL\r\n" - "\t0iwHDdNkGjy5pyBSB8Y79dsSJtCW/iaLB0/n8Sj7HgvvZJ7x0fr+RQjYOUUfrePP\r\n" - "\tu2MSpFyf+9BbC/aXgaZuiCvSR+8Snv3xApQY+fULK/xY8h8Ua51iXoQ5jrgu2SqR\r\n" - "\twgA7BUi3G8LFzMBl8FRCDYGUDy7M6QaHXx1ZWIPWNKsCAwEAAaOCAiQwggIgMAwG\r\n" - "\tA1UdEwEB/wQCMAAwEQYJYIZIAYb4QgHTTPAQDAgWgMA4GA1UdDwEB/wQEAwID6DAs\r\n" - "\tBglghkgBhvhCAQ0EHxYdVUsgZS1TY2llbmNlIFVzZXIgQ2VydGlmaWNhdGUwHQYD\r\n" - "\tVR0OBBYEFDTt/sf9PeMaZDHkUIldrDYMNTBZMIGaBgNVHSMEgZIwgY+AFAI4qxGj\r\n" - "\tloCLDdMVKwiljjDastqooXSkcjBwMQswCQYDVQQGEwJVSzERMA8GA1UEChMIZVNj\r\n" - "\taWVuY2UxEjAQBgNVBAsTCUF1dGhvcml0eTELMAkGA1UEAxMCQ0ExLTArBgkqhkiG\r\n" - "\t9w0BCQEWHmNhLW9wZXJhdG9yQGdyaWQtc3VwcG9ydC5hYy51a4IBADApBgNVHRIE\r\n" - "\tIjAggR5jYS1vcGVyYXRvckBncmlkLXN1cHBvcnQuYWMudWswGQYDVR0gBBIwEDAO\r\n" - "\tBgwrBgEEAdkvAQEBAQYwPQYJYIZIAYb4QgEEBDAWLmh0dHA6Ly9jYS5ncmlkLXN1\r\n" - "\tcHBvcnQuYWMudmT4sopwqlBWsvcHViL2NybC9jYWNybC5jcmwwPQYJYIZIAYb4QgEDBDAWLmh0\r\n" - "\tdHA6Ly9jYS5ncmlkLXN1cHBvcnQuYWMudWsvcHViL2NybC9jYWNybC5jcmwwPwYD\r\n" - "\tVR0fBDgwNjA0oDKgMIYuaHR0cDovL2NhLmdyaWQt5hYy51ay9wdWIv\r\n" - "\tY3JsL2NhY3JsLmNybDANBgkqhkiG9w0BAQUFAAOCAQEAS/U4iiooBENGW/Hwmmd3\r\n" - "\tXCy6Zrt08YjKCzGNjorT98g8uGsqYjSxv/hmi0qlnlHs+k/3Iobc3LjS5AMYr5L8\r\n" - "\tUO7OSkgFFlLHQyC9JzPfmLCAugvzEbyv4Olnsr8hbxF1MbKZoQxUZtMVu29wjfXk\r\n" - "\thTeApBv7eaKCWpSp7MCbvgzm74izKhu3vlDk9w6qVrxePfGgpKPqfHiOoGhFnbTK\r\n" - "\twTC6o2xq5y0qZ03JonF7OJspEd3I5zKY3E+ov7/ZhW6DqT8UFvsAdjvQbXyhV8Eu\r\n" - "\tYhixw1aKEPzNjNowuIseVogKOLXxWI5vAi5HgXdS0/ES5gDGsABo4fqovUKlgop3\r\n" - "\tRA==\r\n" - "\t-----END CERTIFICATE-----\r\n" - "\r\n"; - test_simple(dumbluck2, HPE_OK); - - const char *corrupted_connection = - "GET / HTTP/1.1\r\n" - "Host: www.example.com\r\n" - "Connection\r\033\065\325eep-Alive\r\n" - "Accept-Encoding: gzip\r\n" - "\r\n"; - test_simple(corrupted_connection, HPE_INVALID_HEADER_TOKEN); - - const char *corrupted_header_name = - "GET / HTTP/1.1\r\n" - "Host: www.example.com\r\n" - "X-Some-Header\r\033\065\325eep-Alive\r\n" - "Accept-Encoding: gzip\r\n" - "\r\n"; - test_simple(corrupted_header_name, HPE_INVALID_HEADER_TOKEN); - -#if 0 - // NOTE(Wed Nov 18 11:57:27 CET 2009) this seems okay. we just read body - // until EOF. - // - // no content-length - // error if there is a body without content length - const char *bad_get_no_headers_no_body = "GET /bad_get_no_headers_no_body/world HTTP/1.1\r\n" - "Accept: */*\r\n" - "\r\n" - "HELLO"; - test_simple(bad_get_no_headers_no_body, 0); -#endif - /* TODO sending junk and large headers gets rejected */ - - - /* check to make sure our predefined requests are okay */ - for (i = 0; i < ARRAY_SIZE(requests); i++) { - test_message(&requests[i]); - } - - for (i = 0; i < ARRAY_SIZE(requests); i++) { - test_message_pause(&requests[i]); - } - - for (i = 0; i < ARRAY_SIZE(requests); i++) { - if (!requests[i].should_keep_alive) continue; - for (j = 0; j < ARRAY_SIZE(requests); j++) { - if (!requests[j].should_keep_alive) continue; - for (k = 0; k < ARRAY_SIZE(requests); k++) { - test_multiple3(&requests[i], &requests[j], &requests[k]); - } - } - } - - printf("request scan 1/4 "); - test_scan( &requests[GET_NO_HEADERS_NO_BODY] - , &requests[GET_ONE_HEADER_NO_BODY] - , &requests[GET_NO_HEADERS_NO_BODY] - ); - - printf("request scan 2/4 "); - test_scan( &requests[POST_CHUNKED_ALL_YOUR_BASE] - , &requests[POST_IDENTITY_BODY_WORLD] - , &requests[GET_FUNKY_CONTENT_LENGTH] - ); - - printf("request scan 3/4 "); - test_scan( &requests[TWO_CHUNKS_MULT_ZERO_END] - , &requests[CHUNKED_W_TRAILING_HEADERS] - , &requests[CHUNKED_W_NONSENSE_AFTER_LENGTH] - ); - - printf("request scan 4/4 "); - test_scan( &requests[QUERY_URL_WITH_QUESTION_MARK_GET] - , &requests[PREFIX_NEWLINE_GET ] - , &requests[CONNECT_REQUEST] - ); - - puts("requests okay"); - - return 0; -} diff --git a/vendor/llhttp/.dockerignore b/vendor/llhttp/.dockerignore new file mode 100644 index 0000000..11b226d --- /dev/null +++ b/vendor/llhttp/.dockerignore @@ -0,0 +1,6 @@ +* +!package.json +!package-lock.json +!tsconfig.json +!bin +!src diff --git a/vendor/llhttp/.eslintrc.js b/vendor/llhttp/.eslintrc.js new file mode 100644 index 0000000..595cf53 --- /dev/null +++ b/vendor/llhttp/.eslintrc.js @@ -0,0 +1,31 @@ +module.exports = { + 'env': { + 'browser': false, + 'commonjs': true, + 'es6': true, + 'node': true + }, + 'extends': 'eslint:recommended', + 'rules': { + 'max-len': [ 2, { + 'code': 80, + 'ignoreComments': true + } ], + 'indent': [ + 'error', + 2 + ], + 'linebreak-style': [ + 'error', + 'unix' + ], + 'quotes': [ + 'error', + 'single' + ], + 'semi': [ + 'error', + 'always' + ] + } +}; diff --git a/vendor/llhttp/.github/workflows/aiohttp.yml b/vendor/llhttp/.github/workflows/aiohttp.yml new file mode 100644 index 0000000..8ae8eb3 --- /dev/null +++ b/vendor/llhttp/.github/workflows/aiohttp.yml @@ -0,0 +1,61 @@ +name: Aiohttp +# If you don't understand the reason for a test failure, ping @Dreamsorcerer or open an issue in aio-libs/aiohttp. + +on: + push: + branches: + - 'main' + pull_request: + branches: + - 'main' + +jobs: + test: + permissions: + contents: read # to fetch code (actions/checkout) + + name: Aiohttp regression tests + runs-on: ubuntu-latest + steps: + - name: Checkout aiohttp + uses: actions/checkout@v4 + with: + repository: aio-libs/aiohttp + - name: Checkout llhttp + uses: actions/checkout@v4 + with: + path: vendor/llhttp + - name: Restore node_modules cache + uses: actions/cache@v3 + with: + path: vendor/llhttp/.npm + key: ubuntu-latest-node-${{ hashFiles('vendor/llhttp/**/package-lock.json') }} + restore-keys: ubuntu-latest-node- + - name: Install llhttp dependencies + run: npm install --ignore-scripts + working-directory: vendor/llhttp + - name: Build llhttp + run: make + working-directory: vendor/llhttp + - name: Setup Python + uses: actions/setup-python@v4 + with: + python-version: 3.x + cache: 'pip' + cache-dependency-path: 'requirements/*.txt' + - name: Provision the dev env + run: >- + PATH="${HOME}/.local/bin:${PATH}" + make .develop + - name: Run tests + env: + COLOR: yes + run: >- + PATH="${HOME}/.local/bin:${PATH}" + pytest tests/test_http_parser.py tests/test_web_functional.py + - name: Run dev_mode tests + env: + COLOR: yes + run: >- + PATH="${HOME}/.local/bin:${PATH}" + python -X dev -m pytest -m dev_mode tests/test_http_parser.py tests/test_web_functional.py diff --git a/vendor/llhttp/.github/workflows/ci.yaml b/vendor/llhttp/.github/workflows/ci.yaml new file mode 100644 index 0000000..d1b3a65 --- /dev/null +++ b/vendor/llhttp/.github/workflows/ci.yaml @@ -0,0 +1,117 @@ +name: CI + +on: [push, pull_request] + +env: + CI: true + +jobs: + build: + name: Build libllhttp.a + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: + - macos-latest + - ubuntu-latest + - windows-latest + steps: + - name: Install clang for Windows + if: runner.os == 'Windows' + run: | + iwr -useb get.scoop.sh -outfile 'install.ps1' + .\install.ps1 -RunAsAdmin + scoop install llvm --global + + # Scoop modifies the PATH so we make the modified PATH global. + echo $env:PATH >> $env:GITHUB_PATH + + - name: Fetch code + uses: actions/checkout@v3 + with: + fetch-depth: 1 + + # Skip macOS & Windows, cache there is slower + - name: Restore node_modules cache for Linux + uses: actions/cache@v3 + if: runner.os == 'Linux' + with: + path: ~/.npm + key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-node- + + - name: Install dependencies + run: npm install --ignore-scripts + + - name: Build libllhttp.a + shell: bash + run: | + make build/libllhttp.a + + test: + name: Run tests + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: + - macos-latest + - ubuntu-latest + - windows-latest + steps: + - name: Install clang for Windows + if: runner.os == 'Windows' + run: | + iwr -useb get.scoop.sh -outfile 'install.ps1' + .\install.ps1 -RunAsAdmin + scoop install llvm --global + + # Scoop modifies the PATH so we make the modified PATH global. + echo $env:PATH >> $env:GITHUB_PATH + + - name: Fetch code + uses: actions/checkout@v3 + with: + fetch-depth: 1 + + # Skip macOS & Windows, cache there is slower + - name: Restore node_modules cache for Linux + uses: actions/cache@v3 + if: runner.os == 'Linux' + with: + path: ~/.npm + key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-node- + + - name: Install dependencies + run: npm install --ignore-scripts + + # Custom script, because progress looks not good in CI + - name: Run tests + env: + CFLAGS: -O0 + run: npx mocha --timeout 30000 -r ts-node/register/type-check test/*-test.ts + + lint: + name: Run TSLint + runs-on: ubuntu-latest + steps: + - name: Fetch code + uses: actions/checkout@v3 + with: + fetch-depth: 1 + + - name: Restore node_modules cache + uses: actions/cache@v3 + with: + path: ~/.npm + key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-node- + + - name: Install dependencies + run: npm install --ignore-scripts + + - name: Run lint command + run: npm run lint diff --git a/vendor/llhttp/.gitignore b/vendor/llhttp/.gitignore new file mode 100644 index 0000000..c2e9902 --- /dev/null +++ b/vendor/llhttp/.gitignore @@ -0,0 +1,6 @@ +node_modules/ +npm-debug.log +test/tmp/ +lib/ +build/ +release/ diff --git a/vendor/llhttp/.npmrc b/vendor/llhttp/.npmrc new file mode 100644 index 0000000..cafe685 --- /dev/null +++ b/vendor/llhttp/.npmrc @@ -0,0 +1 @@ +package-lock=true diff --git a/vendor/llhttp/CMakeLists.txt b/vendor/llhttp/CMakeLists.txt new file mode 100644 index 0000000..97fa408 --- /dev/null +++ b/vendor/llhttp/CMakeLists.txt @@ -0,0 +1,117 @@ +cmake_minimum_required(VERSION 3.5.1) +cmake_policy(SET CMP0069 NEW) + +project(llhttp VERSION _RELEASE_) +include(GNUInstallDirs) + +set(CMAKE_C_STANDARD 99) + +# By default build in relwithdebinfo type, supports both lowercase and uppercase +if(NOT CMAKE_CONFIGURATION_TYPES) + set(allowableBuildTypes DEBUG RELEASE RELWITHDEBINFO MINSIZEREL) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "${allowableBuildTypes}") + if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE RELWITHDEBINFO CACHE STRING "" FORCE) + else() + string(TOUPPER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE) + if(NOT CMAKE_BUILD_TYPE IN_LIST allowableBuildTypes) + message(FATAL_ERROR "Invalid build type: ${CMAKE_BUILD_TYPE}") + endif() + endif() +endif() + +# +# Options +# +# Generic option +option(BUILD_SHARED_LIBS "Build shared libraries (.dll/.so)" ON) +option(BUILD_STATIC_LIBS "Build static libraries (.lib/.a)" OFF) + +# Source code +set(LLHTTP_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/src/llhttp.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/http.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/api.c +) + +set(LLHTTP_HEADERS + ${CMAKE_CURRENT_SOURCE_DIR}/include/llhttp.h +) + +configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/libllhttp.pc.in + ${CMAKE_CURRENT_SOURCE_DIR}/libllhttp.pc + @ONLY +) + +function(config_library target) + target_sources(${target} PRIVATE ${LLHTTP_SOURCES} ${LLHTTP_HEADERS}) + + target_include_directories(${target} PUBLIC + $ + $ + ) + + set_target_properties(${target} PROPERTIES + OUTPUT_NAME llhttp + VERSION ${PROJECT_VERSION} + SOVERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR} + PUBLIC_HEADER ${LLHTTP_HEADERS} + ) + + install(TARGETS ${target} + EXPORT llhttp + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + ) + + install(FILES + ${CMAKE_CURRENT_SOURCE_DIR}/libllhttp.pc + DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig + ) + + # This is required to work with FetchContent + install(EXPORT llhttp + FILE llhttp-config.cmake + NAMESPACE llhttp:: + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/llhttp + ) +endfunction(config_library target) + +if(BUILD_SHARED_LIBS) + add_library(llhttp_shared SHARED + ${llhttp_src} + ) + add_library(llhttp::llhttp ALIAS llhttp_shared) + config_library(llhttp_shared) +endif() + +if(BUILD_STATIC_LIBS) + add_library(llhttp_static STATIC + ${llhttp_src} + ) + if(BUILD_SHARED_LIBS) + add_library(llhttp::llhttp ALIAS llhttp_shared) + else() + add_library(llhttp::llhttp ALIAS llhttp_static) + endif() + config_library(llhttp_static) +endif() + +# On windows with Visual Studio, add a debug postfix so that release +# and debug libraries can coexist. +if(MSVC) + set(CMAKE_DEBUG_POSTFIX "d") +endif() + +# Print project configure summary +message(STATUS "") +message(STATUS "") +message(STATUS "Project configure summary:") +message(STATUS "") +message(STATUS " CMake build type .................: ${CMAKE_BUILD_TYPE}") +message(STATUS " Install prefix ...................: ${CMAKE_INSTALL_PREFIX}") +message(STATUS " Build shared library .............: ${BUILD_SHARED_LIBS}") +message(STATUS " Build static library .............: ${BUILD_STATIC_LIBS}") +message(STATUS "") diff --git a/vendor/llhttp/CNAME b/vendor/llhttp/CNAME new file mode 100644 index 0000000..4c4e078 --- /dev/null +++ b/vendor/llhttp/CNAME @@ -0,0 +1 @@ +llhttp.org \ No newline at end of file diff --git a/vendor/llhttp/CODE_OF_CONDUCT.md b/vendor/llhttp/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..8470ae4 --- /dev/null +++ b/vendor/llhttp/CODE_OF_CONDUCT.md @@ -0,0 +1,4 @@ +# Code of Conduct + +* [Node.js Code of Conduct](https://github.com/nodejs/admin/blob/main/CODE_OF_CONDUCT.md) +* [Node.js Moderation Policy](https://github.com/nodejs/admin/blob/main/Moderation-Policy.md) diff --git a/vendor/llhttp/Dockerfile b/vendor/llhttp/Dockerfile new file mode 100644 index 0000000..2b5bfae --- /dev/null +++ b/vendor/llhttp/Dockerfile @@ -0,0 +1,13 @@ +FROM node:18-alpine +ARG UID=1000 +ARG GID=1000 + +RUN apk add -U clang lld wasi-sdk && mkdir /home/node/llhttp + +WORKDIR /home/node/llhttp + +COPY . . + +RUN npm ci + +USER node diff --git a/vendor/llhttp/LICENSE-MIT b/vendor/llhttp/LICENSE-MIT new file mode 100644 index 0000000..6c1512d --- /dev/null +++ b/vendor/llhttp/LICENSE-MIT @@ -0,0 +1,22 @@ +This software is licensed under the MIT License. + +Copyright Fedor Indutny, 2018. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to permit +persons to whom the Software is furnished to do so, subject to the +following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/llhttp/Makefile b/vendor/llhttp/Makefile new file mode 100644 index 0000000..d9c6d35 --- /dev/null +++ b/vendor/llhttp/Makefile @@ -0,0 +1,93 @@ +CLANG ?= clang +CFLAGS ?= +OS ?= + +CFLAGS += -Os -g3 -Wall -Wextra -Wno-unused-parameter +ifneq ($(OS),Windows_NT) + # NOTE: clang on windows does not support fPIC + CFLAGS += -fPIC +endif + +INCLUDES += -Ibuild/ + +INSTALL ?= install +PREFIX ?= /usr/local +LIBDIR = $(PREFIX)/lib +INCLUDEDIR = $(PREFIX)/include + +all: build/libllhttp.a build/libllhttp.so + +clean: + rm -rf release/ + rm -rf build/ + +build/libllhttp.so: build/c/llhttp.o build/native/api.o \ + build/native/http.o + $(CLANG) -shared $^ -o $@ + +build/libllhttp.a: build/c/llhttp.o build/native/api.o \ + build/native/http.o + $(AR) rcs $@ build/c/llhttp.o build/native/api.o build/native/http.o + +build/c/llhttp.o: build/c/llhttp.c + $(CLANG) $(CFLAGS) $(INCLUDES) -c $< -o $@ + +build/native/%.o: src/native/%.c build/llhttp.h src/native/api.h \ + build/native + $(CLANG) $(CFLAGS) $(INCLUDES) -c $< -o $@ + +build/llhttp.h: generate +build/c/llhttp.c: generate + +build/native: + mkdir -p build/native + +release: clean generate + @echo "${RELEASE}" | grep -q -E ".+" || { echo "Please make sure the RELEASE argument is set."; exit 1; } + rm -rf release + mkdir -p release/src + mkdir -p release/include + cp -rf build/llhttp.h release/include/ + cp -rf build/c/llhttp.c release/src/ + cp -rf src/native/*.c release/src/ + cp -rf src/llhttp.gyp release/ + cp -rf src/common.gypi release/ + sed s/_RELEASE_/$(RELEASE)/ CMakeLists.txt > release/CMakeLists.txt + cp -rf libllhttp.pc.in release/ + cp -rf README.md release/ + cp -rf LICENSE-MIT release/ + +github-release: + @echo "${RELEASE_V}" | grep -q -E "^v" || { echo "Please make sure version starts with \"v\"."; exit 1; } + gh release create -d --generate-notes ${RELEASE_V} + @sleep 5 + gh release view ${RELEASE_V} -t "{{.body}}" --json body > RELEASE_NOTES + gh release delete ${RELEASE_V} -y + gh release create -F RELEASE_NOTES -d --title ${RELEASE_V} --target release release/${RELEASE_V} + @sleep 5 + rm -rf RELEASE_NOTES + open $$(gh release view release/${RELEASE_V} --json url -t "{{.url}}") + +postversion: release + git fetch origin + git push + git checkout release -- + cp -rf release/* ./ + rm -rf release + git add include src *.gyp *.gypi CMakeLists.txt README.md LICENSE-MIT libllhttp.pc.in + git commit -a -m "release: $(RELEASE)" + git tag "release/v$(RELEASE)" + git push && git push --tags + git checkout main + +generate: + npx ts-node bin/generate.ts + +install: build/libllhttp.a build/libllhttp.so + $(INSTALL) -d $(DESTDIR)$(INCLUDEDIR) + $(INSTALL) -d $(DESTDIR)$(LIBDIR) + $(INSTALL) -C build/llhttp.h $(DESTDIR)$(INCLUDEDIR)/llhttp.h + $(INSTALL) -C build/libllhttp.a $(DESTDIR)$(LIBDIR)/libllhttp.a + $(INSTALL) build/libllhttp.so $(DESTDIR)$(LIBDIR)/libllhttp.so + +.PHONY: all generate clean release postversion github-release diff --git a/vendor/llhttp/README.md b/vendor/llhttp/README.md new file mode 100644 index 0000000..4960dbb --- /dev/null +++ b/vendor/llhttp/README.md @@ -0,0 +1,501 @@ +# llhttp +[![CI](https://github.com/nodejs/llhttp/workflows/CI/badge.svg)](https://github.com/nodejs/llhttp/actions?query=workflow%3ACI) + +Port of [http_parser][0] to [llparse][1]. + +## Why? + +Let's face it, [http_parser][0] is practically unmaintainable. Even +introduction of a single new method results in a significant code churn. + +This project aims to: + +* Make it maintainable +* Verifiable +* Improving benchmarks where possible + +More details in [Fedor Indutny's talk at JSConf EU 2019](https://youtu.be/x3k_5Mi66sY) + +## How? + +Over time, different approaches for improving [http_parser][0]'s code base +were tried. However, all of them failed due to resulting significant performance +degradation. + +This project is a port of [http_parser][0] to TypeScript. [llparse][1] is used +to generate the output C source file, which could be compiled and +linked with the embedder's program (like [Node.js][7]). + +## Performance + +So far llhttp outperforms http_parser: + +| | input size | bandwidth | reqs/sec | time | +|:----------------|-----------:|-------------:|-----------:|--------:| +| **llhttp** | 8192.00 mb | 1777.24 mb/s | 3583799.39 req/sec | 4.61 s | +| **http_parser** | 8192.00 mb | 694.66 mb/s | 1406180.33 req/sec | 11.79 s | + +llhttp is faster by approximately **156%**. + +## Maintenance + +llhttp project has about 1400 lines of TypeScript code describing the parser +itself and around 450 lines of C code and headers providing the helper methods. +The whole [http_parser][0] is implemented in approximately 2500 lines of C, and +436 lines of headers. + +All optimizations and multi-character matching in llhttp are generated +automatically, and thus doesn't add any extra maintenance cost. On the contrary, +most of http_parser's code is hand-optimized and unrolled. Instead describing +"how" it should parse the HTTP requests/responses, a maintainer should +implement the new features in [http_parser][0] cautiously, considering +possible performance degradation and manually optimizing the new code. + +## Verification + +The state machine graph is encoded explicitly in llhttp. The [llparse][1] +automatically checks the graph for absence of loops and correct reporting of the +input ranges (spans) like header names and values. In the future, additional +checks could be performed to get even stricter verification of the llhttp. + +## Usage + +```C +#include "stdio.h" +#include "llhttp.h" +#include "string.h" + +int handle_on_message_complete(llhttp_t* parser) { + fprintf(stdout, "Message completed!\n"); + return 0; +} + +int main() { + llhttp_t parser; + llhttp_settings_t settings; + + /*Initialize user callbacks and settings */ + llhttp_settings_init(&settings); + + /*Set user callback */ + settings.on_message_complete = handle_on_message_complete; + + /*Initialize the parser in HTTP_BOTH mode, meaning that it will select between + *HTTP_REQUEST and HTTP_RESPONSE parsing automatically while reading the first + *input. + */ + llhttp_init(&parser, HTTP_BOTH, &settings); + + /*Parse request! */ + const char* request = "GET / HTTP/1.1\r\n\r\n"; + int request_len = strlen(request); + + enum llhttp_errno err = llhttp_execute(&parser, request, request_len); + if (err == HPE_OK) { + fprintf(stdout, "Successfully parsed!\n"); + } else { + fprintf(stderr, "Parse error: %s %s\n", llhttp_errno_name(err), parser.reason); + } +} +``` +For more information on API usage, please refer to [src/native/api.h](https://github.com/nodejs/llhttp/blob/main/src/native/api.h). + +## API + +### llhttp_settings_t + +The settings object contains a list of callbacks that the parser will invoke. + +The following callbacks can return `0` (proceed normally), `-1` (error) or `HPE_PAUSED` (pause the parser): + +* `on_message_begin`: Invoked when a new request/response starts. +* `on_message_complete`: Invoked when a request/response has been completedly parsed. +* `on_url_complete`: Invoked after the URL has been parsed. +* `on_method_complete`: Invoked after the HTTP method has been parsed. +* `on_version_complete`: Invoked after the HTTP version has been parsed. +* `on_status_complete`: Invoked after the status code has been parsed. +* `on_header_field_complete`: Invoked after a header name has been parsed. +* `on_header_value_complete`: Invoked after a header value has been parsed. +* `on_chunk_header`: Invoked after a new chunk is started. The current chunk length is stored in `parser->content_length`. +* `on_chunk_extension_name_complete`: Invoked after a chunk extension name is started. +* `on_chunk_extension_value_complete`: Invoked after a chunk extension value is started. +* `on_chunk_complete`: Invoked after a new chunk is received. +* `on_reset`: Invoked after `on_message_complete` and before `on_message_begin` when a new message + is received on the same parser. This is not invoked for the first message of the parser. + +The following callbacks can return `0` (proceed normally), `-1` (error) or `HPE_USER` (error from the callback): + +* `on_url`: Invoked when another character of the URL is received. +* `on_status`: Invoked when another character of the status is received. +* `on_method`: Invoked when another character of the method is received. + When parser is created with `HTTP_BOTH` and the input is a response, this also invoked for the sequence `HTTP/` + of the first message. +* `on_version`: Invoked when another character of the version is received. +* `on_header_field`: Invoked when another character of a header name is received. +* `on_header_value`: Invoked when another character of a header value is received. +* `on_chunk_extension_name`: Invoked when another character of a chunk extension name is received. +* `on_chunk_extension_value`: Invoked when another character of a extension value is received. + +The callback `on_headers_complete`, invoked when headers are completed, can return: + +* `0`: Proceed normally. +* `1`: Assume that request/response has no body, and proceed to parsing the next message. +* `2`: Assume absence of body (as above) and make `llhttp_execute()` return `HPE_PAUSED_UPGRADE`. +* `-1`: Error +* `HPE_PAUSED`: Pause the parser. + +### `void llhttp_init(llhttp_t* parser, llhttp_type_t type, const llhttp_settings_t* settings)` + +Initialize the parser with specific type and user settings. + +### `uint8_t llhttp_get_type(llhttp_t* parser)` + +Returns the type of the parser. + +### `uint8_t llhttp_get_http_major(llhttp_t* parser)` + +Returns the major version of the HTTP protocol of the current request/response. + +### `uint8_t llhttp_get_http_minor(llhttp_t* parser)` + +Returns the minor version of the HTTP protocol of the current request/response. + +### `uint8_t llhttp_get_method(llhttp_t* parser)` + +Returns the method of the current request. + +### `int llhttp_get_status_code(llhttp_t* parser)` + +Returns the method of the current response. + +### `uint8_t llhttp_get_upgrade(llhttp_t* parser)` + +Returns `1` if request includes the `Connection: upgrade` header. + +### `void llhttp_reset(llhttp_t* parser)` + +Reset an already initialized parser back to the start state, preserving the +existing parser type, callback settings, user data, and lenient flags. + +### `void llhttp_settings_init(llhttp_settings_t* settings)` + +Initialize the settings object. + +### `llhttp_errno_t llhttp_execute(llhttp_t* parser, const char* data, size_t len)` + +Parse full or partial request/response, invoking user callbacks along the way. + +If any of `llhttp_data_cb` returns errno not equal to `HPE_OK` - the parsing interrupts, +and such errno is returned from `llhttp_execute()`. If `HPE_PAUSED` was used as a errno, +the execution can be resumed with `llhttp_resume()` call. + +In a special case of CONNECT/Upgrade request/response `HPE_PAUSED_UPGRADE` is returned +after fully parsing the request/response. If the user wishes to continue parsing, +they need to invoke `llhttp_resume_after_upgrade()`. + +**if this function ever returns a non-pause type error, it will continue to return +the same error upon each successive call up until `llhttp_init()` is called.** + +### `llhttp_errno_t llhttp_finish(llhttp_t* parser)` + +This method should be called when the other side has no further bytes to +send (e.g. shutdown of readable side of the TCP connection.) + +Requests without `Content-Length` and other messages might require treating +all incoming bytes as the part of the body, up to the last byte of the +connection. + +This method will invoke `on_message_complete()` callback if the +request was terminated safely. Otherwise a error code would be returned. + + +### `int llhttp_message_needs_eof(const llhttp_t* parser)` + +Returns `1` if the incoming message is parsed until the last byte, and has to be completed by calling `llhttp_finish()` on EOF. + +### `int llhttp_should_keep_alive(const llhttp_t* parser)` + +Returns `1` if there might be any other messages following the last that was +successfully parsed. + +### `void llhttp_pause(llhttp_t* parser)` + +Make further calls of `llhttp_execute()` return `HPE_PAUSED` and set +appropriate error reason. + +**Do not call this from user callbacks! User callbacks must return +`HPE_PAUSED` if pausing is required.** + +### `void llhttp_resume(llhttp_t* parser)` + +Might be called to resume the execution after the pause in user's callback. + +See `llhttp_execute()` above for details. + +**Call this only if `llhttp_execute()` returns `HPE_PAUSED`.** + +### `void llhttp_resume_after_upgrade(llhttp_t* parser)` + +Might be called to resume the execution after the pause in user's callback. +See `llhttp_execute()` above for details. + +**Call this only if `llhttp_execute()` returns `HPE_PAUSED_UPGRADE`** + +### `llhttp_errno_t llhttp_get_errno(const llhttp_t* parser)` + +Returns the latest error. + +### `const char* llhttp_get_error_reason(const llhttp_t* parser)` + +Returns the verbal explanation of the latest returned error. + +**User callback should set error reason when returning the error. See +`llhttp_set_error_reason()` for details.** + +### `void llhttp_set_error_reason(llhttp_t* parser, const char* reason)` + +Assign verbal description to the returned error. Must be called in user +callbacks right before returning the errno. + +**`HPE_USER` error code might be useful in user callbacks.** + +### `const char* llhttp_get_error_pos(const llhttp_t* parser)` + +Returns the pointer to the last parsed byte before the returned error. The +pointer is relative to the `data` argument of `llhttp_execute()`. + +**This method might be useful for counting the number of parsed bytes.** + +### `const char* llhttp_errno_name(llhttp_errno_t err)` + +Returns textual name of error code. + +### `const char* llhttp_method_name(llhttp_method_t method)` + +Returns textual name of HTTP method. + +### `const char* llhttp_status_name(llhttp_status_t status)` + +Returns textual name of HTTP status. + +### `void llhttp_set_lenient_headers(llhttp_t* parser, int enabled)` + +Enables/disables lenient header value parsing (disabled by default). +Lenient parsing disables header value token checks, extending llhttp's +protocol support to highly non-compliant clients/server. + +No `HPE_INVALID_HEADER_TOKEN` will be raised for incorrect header values when +lenient parsing is "on". + +**Enabling this flag can pose a security issue since you will be exposed to request smuggling attacks. USE WITH CAUTION!** + +### `void llhttp_set_lenient_chunked_length(llhttp_t* parser, int enabled)` + +Enables/disables lenient handling of conflicting `Transfer-Encoding` and +`Content-Length` headers (disabled by default). + +Normally `llhttp` would error when `Transfer-Encoding` is present in +conjunction with `Content-Length`. + +This error is important to prevent HTTP request smuggling, but may be less desirable +for small number of cases involving legacy servers. + +**Enabling this flag can pose a security issue since you will be exposed to request smuggling attacks. USE WITH CAUTION!** + +### `void llhttp_set_lenient_keep_alive(llhttp_t* parser, int enabled)` + +Enables/disables lenient handling of `Connection: close` and HTTP/1.0 +requests responses. + +Normally `llhttp` would error the HTTP request/response +after the request/response with `Connection: close` and `Content-Length`. + +This is important to prevent cache poisoning attacks, +but might interact badly with outdated and insecure clients. + +With this flag the extra request/response will be parsed normally. + +**Enabling this flag can pose a security issue since you will be exposed to poisoning attacks. USE WITH CAUTION!** + +### `void llhttp_set_lenient_transfer_encoding(llhttp_t* parser, int enabled)` + +Enables/disables lenient handling of `Transfer-Encoding` header. + +Normally `llhttp` would error when a `Transfer-Encoding` has `chunked` value +and another value after it (either in a single header or in multiple +headers whose value are internally joined using `, `). + +This is mandated by the spec to reliably determine request body size and thus +avoid request smuggling. + +With this flag the extra value will be parsed normally. + +**Enabling this flag can pose a security issue since you will be exposed to request smuggling attacks. USE WITH CAUTION!** + +### `void llhttp_set_lenient_version(llhttp_t* parser, int enabled)` + +Enables/disables lenient handling of HTTP version. + +Normally `llhttp` would error when the HTTP version in the request or status line +is not `0.9`, `1.0`, `1.1` or `2.0`. +With this flag the extra value will be parsed normally. + +**Enabling this flag can pose a security issue since you will allow unsupported HTTP versions. USE WITH CAUTION!** + +### `void llhttp_set_lenient_data_after_close(llhttp_t* parser, int enabled)` + +Enables/disables lenient handling of additional data received after a message ends +and keep-alive is disabled. + +Normally `llhttp` would error when additional unexpected data is received if the message +contains the `Connection` header with `close` value. +With this flag the extra data will discarded without throwing an error. + +**Enabling this flag can pose a security issue since you will be exposed to poisoning attacks. USE WITH CAUTION!** + +### `void llhttp_set_lenient_optional_lf_after_cr(llhttp_t* parser, int enabled)` + +Enables/disables lenient handling of incomplete CRLF sequences. + +Normally `llhttp` would error when a CR is not followed by LF when terminating the +request line, the status line, the headers or a chunk header. +With this flag only a CR is required to terminate such sections. + +**Enabling this flag can pose a security issue since you will be exposed to request smuggling attacks. USE WITH CAUTION!** + +### `void llhttp_set_lenient_optional_cr_before_lf(llhttp_t* parser, int enabled)` + +Enables/disables lenient handling of line separators. + +Normally `llhttp` would error when a LF is not preceded by CR when terminating the +request line, the status line, the headers, a chunk header or a chunk data. +With this flag only a LF is required to terminate such sections. + +**Enabling this flag can pose a security issue since you will be exposed to request smuggling attacks. USE WITH CAUTION!** + +### `void llhttp_set_lenient_optional_crlf_after_chunk(llhttp_t* parser, int enabled)` + +Enables/disables lenient handling of chunks not separated via CRLF. + +Normally `llhttp` would error when after a chunk data a CRLF is missing before +starting a new chunk. +With this flag the new chunk can start immediately after the previous one. + +**Enabling this flag can pose a security issue since you will be exposed to request smuggling attacks. USE WITH CAUTION!** + +### `void llhttp_set_lenient_spaces_after_chunk_size(llhttp_t* parser, int enabled)` + +Enables/disables lenient handling of spaces after chunk size. + +Normally `llhttp` would error when after a chunk size is followed by one or more spaces are present instead of a CRLF or `;`. +With this flag this check is disabled. + +**Enabling this flag can pose a security issue since you will be exposed to request smuggling attacks. USE WITH CAUTION!** + +## Build Instructions + +Make sure you have [Node.js](https://nodejs.org/), npm and npx installed. Then under project directory run: + +```sh +npm install +make +``` + +--- + +### Bindings to other languages + +* Lua: [MunifTanjim/llhttp.lua][11] +* Python: [pallas/pyllhttp][8] +* Ruby: [metabahn/llhttp][9] +* Rust: [JackLiar/rust-llhttp][10] + +### Using with CMake + +If you want to use this library in a CMake project as a shared library, you can use the snippet below. + +``` +FetchContent_Declare(llhttp + URL "https://github.com/nodejs/llhttp/archive/refs/tags/release/v8.1.0.tar.gz") + +FetchContent_MakeAvailable(llhttp) + +# Link with the llhttp_shared target +target_link_libraries(${EXAMPLE_PROJECT_NAME} ${PROJECT_LIBRARIES} llhttp_shared ${PROJECT_NAME}) +``` + +If you want to use this library in a CMake project as a static library, you can set some cache variables first. + +``` +FetchContent_Declare(llhttp + URL "https://github.com/nodejs/llhttp/archive/refs/tags/release/v8.1.0.tar.gz") + +set(BUILD_SHARED_LIBS OFF CACHE INTERNAL "") +set(BUILD_STATIC_LIBS ON CACHE INTERNAL "") +FetchContent_MakeAvailable(llhttp) + +# Link with the llhttp_static target +target_link_libraries(${EXAMPLE_PROJECT_NAME} ${PROJECT_LIBRARIES} llhttp_static ${PROJECT_NAME}) +``` + +_Note that using the git repo directly (e.g., via a git repo url and tag) will not work with FetchContent_Declare because [CMakeLists.txt](./CMakeLists.txt) requires string replacements (e.g., `_RELEASE_`) before it will build._ + +## Building on Windows + +### Installation + +* `choco install git` +* `choco install node` +* `choco install llvm` (or install the `C++ Clang tools for Windows` optional package from the Visual Studio 2019 installer) +* `choco install make` (or if you have MinGW, it comes bundled) + +1. Ensure that `Clang` and `make` are in your system path. +2. Using Git Bash, clone the repo to your preferred location. +3. Cd into the cloned directory and run `npm install` +5. Run `make` +6. Your `repo/build` directory should now have `libllhttp.a` and `libllhttp.so` static and dynamic libraries. +7. When building your executable, you can link to these libraries. Make sure to set the build folder as an include path when building so you can reference the declarations in `repo/build/llhttp.h`. + +### A simple example on linking with the library: + +Assuming you have an executable `main.cpp` in your current working directory, you would run: `clang++ -Os -g3 -Wall -Wextra -Wno-unused-parameter -I/path/to/llhttp/build main.cpp /path/to/llhttp/build/libllhttp.a -o main.exe`. + +If you are getting `unresolved external symbol` linker errors you are likely attempting to build `llhttp.c` without linking it with object files from `api.c` and `http.c`. + +#### LICENSE + +This software is licensed under the MIT License. + +Copyright Fedor Indutny, 2018. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to permit +persons to whom the Software is furnished to do so, subject to the +following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +[0]: https://github.com/nodejs/http-parser +[1]: https://github.com/nodejs/llparse +[2]: https://en.wikipedia.org/wiki/Register_allocation#Spilling +[3]: https://en.wikipedia.org/wiki/Tail_call +[4]: https://llvm.org/docs/LangRef.html +[5]: https://llvm.org/docs/LangRef.html#call-instruction +[6]: https://clang.llvm.org/ +[7]: https://github.com/nodejs/node +[8]: https://github.com/pallas/pyllhttp +[9]: https://github.com/metabahn/llhttp +[10]: https://github.com/JackLiar/rust-llhttp +[11]: https://github.com/MunifTanjim/llhttp.lua diff --git a/vendor/llhttp/_config.yml b/vendor/llhttp/_config.yml new file mode 100644 index 0000000..1885487 --- /dev/null +++ b/vendor/llhttp/_config.yml @@ -0,0 +1 @@ +theme: jekyll-theme-midnight \ No newline at end of file diff --git a/vendor/llhttp/bench/index.ts b/vendor/llhttp/bench/index.ts new file mode 100644 index 0000000..b3ff2e1 --- /dev/null +++ b/vendor/llhttp/bench/index.ts @@ -0,0 +1,71 @@ +import * as assert from "assert"; +import { spawnSync } from "child_process"; +import { existsSync } from "fs"; +import { resolve } from "path"; + +function request(tpl: TemplateStringsArray): string { + return tpl.raw[0].replace(/^\s+/gm, '').replace(/\n/gm, '').replace(/\\r/gm, '\r').replace(/\\n/gm, '\n') +} + +const urlExecutable = resolve(__dirname, "../test/tmp/url-url-c"); +const httpExecutable = resolve(__dirname, "../test/tmp/http-request-c"); + +const httpRequests: Record = { + "seanmonstar/httparse": request` + GET /wp-content/uploads/2010/03/hello-kitty-darth-vader-pink.jpg HTTP/1.1\r\n + Host: www.kittyhell.com\r\n + User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; ja-JP-mac; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3 Pathtraq/0.9\r\n + Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n + Accept-Language: ja,en-us;q=0.7,en;q=0.3\r\n + Accept-Encoding: gzip,deflate\r\n + Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.7\r\n + Keep-Alive: 115\r\n + Connection: keep-alive\r\n + Cookie: wp_ozh_wsa_visits=2; wp_ozh_wsa_visit_lasttime=xxxxxxxxxx; __utma=xxxxxxxxx.xxxxxxxxxx.xxxxxxxxxx.xxxxxxxxxx.xxxxxxxxxx.x; __utmz=xxxxxxxxx.xxxxxxxxxx.x.x.utmccn=(referral)|utmcsr=reader.livedoor.com|utmcct=/reader/|utmcmd=referral\r\n\r\n + `, + "nodejs/http-parser": request` + POST /joyent/http-parser HTTP/1.1\r\n + Host: github.com\r\n + DNT: 1\r\n + Accept-Encoding: gzip, deflate, sdch\r\n + Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4\r\n + User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) + AppleWebKit/537.36 (KHTML, like Gecko) + Chrome/39.0.2171.65 Safari/537.36\r\n + Accept: text/html,application/xhtml+xml,application/xml;q=0.9, + image/webp,*/*;q=0.8\r\n + Referer: https://github.com/joyent/http-parser\r\n + Connection: keep-alive\r\n + Transfer-Encoding: chunked\r\n + Cache-Control: max-age=0\r\n\r\nb\r\nhello world\r\n0\r\n\r\n + ` +} +const urlRequest = "http://example.com/path/to/file?query=value#fragment"; + +if (!existsSync(urlExecutable) || !existsSync(urlExecutable)) { + console.error( + "\x1b[31m\x1b[1mPlease run npm test in order to create required executables." + ); + process.exit(1); +} + +if (process.argv[2] === "loop") { + const reqName = process.argv[3]; + const request = httpRequests[reqName]!; + + assert(request, `Unknown request name: "${reqName}"`); + spawnSync(httpExecutable, ["loop", request], { stdio: "inherit" }); + process.exit(0); +} + +if (!process.argv[2] || process.argv[2] === "url") { + console.log("url (C)"); + spawnSync(urlExecutable, ["bench", urlRequest], { stdio: "inherit" }); +} + +if (!process.argv[2] || process.argv[2] === "http") { + for (const [name, request] of Object.entries(httpRequests)) { + console.log('http: "%s" (C)', name); + spawnSync(httpExecutable, ["bench", request], { stdio: "inherit" }); + } +} diff --git a/vendor/llhttp/bin/build_wasm.ts b/vendor/llhttp/bin/build_wasm.ts new file mode 100644 index 0000000..a885703 --- /dev/null +++ b/vendor/llhttp/bin/build_wasm.ts @@ -0,0 +1,95 @@ +import { execSync } from 'child_process'; +import { copyFileSync, mkdirSync } from 'fs'; +import { join, resolve } from 'path'; + +let platform = process.env.WASM_PLATFORM ?? ''; +const WASM_OUT = resolve(__dirname, '../build/wasm'); +const WASM_SRC = resolve(__dirname, '../'); + +if (!platform && process.argv[2]) { + platform = execSync('docker info -f "{{.OSType}}/{{.Architecture}}"').toString().trim(); +} + +if (process.argv[2] === '--prebuild') { + const cmd = `docker build --platform=${platform.toString().trim()} -t llhttp_wasm_builder .`; + + /* tslint:disable-next-line no-console */ + console.log(`> ${cmd}\n\n`); + execSync(cmd, { stdio: 'inherit' }); + + process.exit(0); +} + +if (process.argv[2] === '--setup') { + try { + mkdirSync(join(WASM_SRC, 'build')); + process.exit(0); + } catch (error) { + if (error.code !== 'EEXIST') { + throw error; + } + process.exit(0); + } +} + +if (process.argv[2] === '--docker') { + let cmd = `docker run --rm -it --platform=${platform.toString().trim()}`; + // Try to avoid root permission problems on compiled assets + // when running on linux. + // It will work flawessly if uid === gid === 1000 + // there will be some warnings otherwise. + if (process.platform === 'linux') { + cmd += ` --user ${process.getuid()}:${process.getegid()}`; + } + cmd += ` --mount type=bind,source=${WASM_SRC}/build,target=/home/node/llhttp/build llhttp_wasm_builder npm run wasm`; + + /* tslint:disable-next-line no-console */ + console.log(`> ${cmd}\n\n`); + execSync(cmd, { cwd: WASM_SRC, stdio: 'inherit' }); + process.exit(0); +} + +try { + mkdirSync(WASM_OUT); +} catch (error) { + if (error.code !== 'EEXIST') { + throw error; + } +} + +// Build ts +execSync('npm run build', { cwd: WASM_SRC, stdio: 'inherit' }); + +// Build wasm binary +execSync( + `clang \ + --sysroot=/usr/share/wasi-sysroot \ + -target wasm32-unknown-wasi \ + -Ofast \ + -fno-exceptions \ + -fvisibility=hidden \ + -mexec-model=reactor \ + -Wl,-error-limit=0 \ + -Wl,-O3 \ + -Wl,--lto-O3 \ + -Wl,--strip-all \ + -Wl,--allow-undefined \ + -Wl,--export-dynamic \ + -Wl,--export-table \ + -Wl,--export=malloc \ + -Wl,--export=free \ + -Wl,--no-entry \ + ${join(WASM_SRC, 'build', 'c')}/*.c \ + ${join(WASM_SRC, 'src', 'native')}/*.c \ + -I${join(WASM_SRC, 'build')} \ + -o ${join(WASM_OUT, 'llhttp.wasm')}`, + { stdio: 'inherit' }, +); + +// Copy constants for `.js` and `.ts` users. +copyFileSync(join(WASM_SRC, 'lib', 'llhttp', 'constants.js'), join(WASM_OUT, 'constants.js')); +copyFileSync(join(WASM_SRC, 'lib', 'llhttp', 'constants.js.map'), join(WASM_OUT, 'constants.js.map')); +copyFileSync(join(WASM_SRC, 'lib', 'llhttp', 'constants.d.ts'), join(WASM_OUT, 'constants.d.ts')); +copyFileSync(join(WASM_SRC, 'lib', 'llhttp', 'utils.js'), join(WASM_OUT, 'utils.js')); +copyFileSync(join(WASM_SRC, 'lib', 'llhttp', 'utils.js.map'), join(WASM_OUT, 'utils.js.map')); +copyFileSync(join(WASM_SRC, 'lib', 'llhttp', 'utils.d.ts'), join(WASM_OUT, 'utils.d.ts')); diff --git a/vendor/llhttp/bin/generate.ts b/vendor/llhttp/bin/generate.ts new file mode 100755 index 0000000..edb7f49 --- /dev/null +++ b/vendor/llhttp/bin/generate.ts @@ -0,0 +1,47 @@ +#!/usr/bin/env -S npx ts-node + +import { mkdirSync, readFileSync, writeFileSync } from 'fs'; +import { LLParse } from 'llparse'; +import { dirname, resolve } from 'path'; +import { parse } from 'semver'; +import { CHeaders, HTTP } from '../src/llhttp'; + +const C_FILE = resolve(__dirname, '../build/c/llhttp.c'); +const HEADER_FILE = resolve(__dirname, '../build/llhttp.h'); + +const pkg = JSON.parse( + readFileSync(resolve(__dirname, '..', 'package.json')).toString(), +); +const version = parse(pkg.version)!; +const llparse = new LLParse('llhttp__internal'); + +const cHeaders = new CHeaders(); +const nativeHeaders = readFileSync(resolve(__dirname, '../src/native/api.h')); +const generated = llparse.build(new HTTP(llparse).build().entry, { + c: { + header: 'llhttp', + }, + debug: process.env.LLPARSE_DEBUG ? 'llhttp__debug' : undefined, + headerGuard: 'INCLUDE_LLHTTP_ITSELF_H_', +}); + +const headers = ` +#ifndef INCLUDE_LLHTTP_H_ +#define INCLUDE_LLHTTP_H_ + +#define LLHTTP_VERSION_MAJOR ${version.major} +#define LLHTTP_VERSION_MINOR ${version.minor} +#define LLHTTP_VERSION_PATCH ${version.patch} + +${generated.header} + +${cHeaders.build()} + +${nativeHeaders} + +#endif /* INCLUDE_LLHTTP_H_ */ +`; + +mkdirSync(dirname(C_FILE), { recursive: true }); +writeFileSync(HEADER_FILE, headers); +writeFileSync(C_FILE, generated.c); diff --git a/vendor/llhttp/build/c/llhttp.c b/vendor/llhttp/build/c/llhttp.c new file mode 100644 index 0000000..af84c42 --- /dev/null +++ b/vendor/llhttp/build/c/llhttp.c @@ -0,0 +1,10102 @@ +#include +#include +#include + +#ifdef __SSE4_2__ + #ifdef _MSC_VER + #include + #else /* !_MSC_VER */ + #include + #endif /* _MSC_VER */ +#endif /* __SSE4_2__ */ + +#ifdef _MSC_VER + #define ALIGN(n) _declspec(align(n)) +#else /* !_MSC_VER */ + #define ALIGN(n) __attribute__((aligned(n))) +#endif /* _MSC_VER */ + +#include "llhttp.h" + +typedef int (*llhttp__internal__span_cb)( + llhttp__internal_t*, const char*, const char*); + +static const unsigned char llparse_blob0[] = { + 'o', 'n' +}; +static const unsigned char llparse_blob1[] = { + 'e', 'c', 't', 'i', 'o', 'n' +}; +static const unsigned char llparse_blob2[] = { + 'l', 'o', 's', 'e' +}; +static const unsigned char llparse_blob3[] = { + 'e', 'e', 'p', '-', 'a', 'l', 'i', 'v', 'e' +}; +static const unsigned char llparse_blob4[] = { + 'p', 'g', 'r', 'a', 'd', 'e' +}; +static const unsigned char llparse_blob5[] = { + 'c', 'h', 'u', 'n', 'k', 'e', 'd' +}; +#ifdef __SSE4_2__ +static const unsigned char ALIGN(16) llparse_blob6[] = { + 0x9, 0x9, ' ', '~', 0x80, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0 +}; +#endif /* __SSE4_2__ */ +#ifdef __SSE4_2__ +static const unsigned char ALIGN(16) llparse_blob7[] = { + '!', '!', '#', '\'', '*', '+', '-', '.', '0', '9', 'A', + 'Z', '^', 'z', '|', '|' +}; +#endif /* __SSE4_2__ */ +#ifdef __SSE4_2__ +static const unsigned char ALIGN(16) llparse_blob8[] = { + '~', '~', 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0 +}; +#endif /* __SSE4_2__ */ +static const unsigned char llparse_blob9[] = { + 'e', 'n', 't', '-', 'l', 'e', 'n', 'g', 't', 'h' +}; +static const unsigned char llparse_blob10[] = { + 'r', 'o', 'x', 'y', '-', 'c', 'o', 'n', 'n', 'e', 'c', + 't', 'i', 'o', 'n' +}; +static const unsigned char llparse_blob11[] = { + 'r', 'a', 'n', 's', 'f', 'e', 'r', '-', 'e', 'n', 'c', + 'o', 'd', 'i', 'n', 'g' +}; +static const unsigned char llparse_blob12[] = { + 'p', 'g', 'r', 'a', 'd', 'e' +}; +static const unsigned char llparse_blob13[] = { + 'T', 'T', 'P', '/' +}; +static const unsigned char llparse_blob14[] = { + 0xd, 0xa, 0xd, 0xa, 'S', 'M', 0xd, 0xa, 0xd, 0xa +}; +static const unsigned char llparse_blob15[] = { + 'C', 'E', '/' +}; +static const unsigned char llparse_blob16[] = { + 'T', 'S', 'P', '/' +}; +static const unsigned char llparse_blob17[] = { + 'N', 'O', 'U', 'N', 'C', 'E' +}; +static const unsigned char llparse_blob18[] = { + 'I', 'N', 'D' +}; +static const unsigned char llparse_blob19[] = { + 'E', 'C', 'K', 'O', 'U', 'T' +}; +static const unsigned char llparse_blob20[] = { + 'N', 'E', 'C', 'T' +}; +static const unsigned char llparse_blob21[] = { + 'E', 'T', 'E' +}; +static const unsigned char llparse_blob22[] = { + 'C', 'R', 'I', 'B', 'E' +}; +static const unsigned char llparse_blob23[] = { + 'L', 'U', 'S', 'H' +}; +static const unsigned char llparse_blob24[] = { + 'E', 'T' +}; +static const unsigned char llparse_blob25[] = { + 'P', 'A', 'R', 'A', 'M', 'E', 'T', 'E', 'R' +}; +static const unsigned char llparse_blob26[] = { + 'E', 'A', 'D' +}; +static const unsigned char llparse_blob27[] = { + 'N', 'K' +}; +static const unsigned char llparse_blob28[] = { + 'C', 'K' +}; +static const unsigned char llparse_blob29[] = { + 'S', 'E', 'A', 'R', 'C', 'H' +}; +static const unsigned char llparse_blob30[] = { + 'R', 'G', 'E' +}; +static const unsigned char llparse_blob31[] = { + 'C', 'T', 'I', 'V', 'I', 'T', 'Y' +}; +static const unsigned char llparse_blob32[] = { + 'L', 'E', 'N', 'D', 'A', 'R' +}; +static const unsigned char llparse_blob33[] = { + 'V', 'E' +}; +static const unsigned char llparse_blob34[] = { + 'O', 'T', 'I', 'F', 'Y' +}; +static const unsigned char llparse_blob35[] = { + 'P', 'T', 'I', 'O', 'N', 'S' +}; +static const unsigned char llparse_blob36[] = { + 'C', 'H' +}; +static const unsigned char llparse_blob37[] = { + 'S', 'E' +}; +static const unsigned char llparse_blob38[] = { + 'A', 'Y' +}; +static const unsigned char llparse_blob39[] = { + 'S', 'T' +}; +static const unsigned char llparse_blob40[] = { + 'I', 'N', 'D' +}; +static const unsigned char llparse_blob41[] = { + 'A', 'T', 'C', 'H' +}; +static const unsigned char llparse_blob42[] = { + 'G', 'E' +}; +static const unsigned char llparse_blob43[] = { + 'I', 'N', 'D' +}; +static const unsigned char llparse_blob44[] = { + 'O', 'R', 'D' +}; +static const unsigned char llparse_blob45[] = { + 'I', 'R', 'E', 'C', 'T' +}; +static const unsigned char llparse_blob46[] = { + 'O', 'R', 'T' +}; +static const unsigned char llparse_blob47[] = { + 'R', 'C', 'H' +}; +static const unsigned char llparse_blob48[] = { + 'P', 'A', 'R', 'A', 'M', 'E', 'T', 'E', 'R' +}; +static const unsigned char llparse_blob49[] = { + 'U', 'R', 'C', 'E' +}; +static const unsigned char llparse_blob50[] = { + 'B', 'S', 'C', 'R', 'I', 'B', 'E' +}; +static const unsigned char llparse_blob51[] = { + 'A', 'R', 'D', 'O', 'W', 'N' +}; +static const unsigned char llparse_blob52[] = { + 'A', 'C', 'E' +}; +static const unsigned char llparse_blob53[] = { + 'I', 'N', 'D' +}; +static const unsigned char llparse_blob54[] = { + 'N', 'K' +}; +static const unsigned char llparse_blob55[] = { + 'C', 'K' +}; +static const unsigned char llparse_blob56[] = { + 'U', 'B', 'S', 'C', 'R', 'I', 'B', 'E' +}; +static const unsigned char llparse_blob57[] = { + 'H', 'T', 'T', 'P', '/' +}; +static const unsigned char llparse_blob58[] = { + 'A', 'D' +}; +static const unsigned char llparse_blob59[] = { + 'T', 'P', '/' +}; + +enum llparse_match_status_e { + kMatchComplete, + kMatchPause, + kMatchMismatch +}; +typedef enum llparse_match_status_e llparse_match_status_t; + +struct llparse_match_s { + llparse_match_status_t status; + const unsigned char* current; +}; +typedef struct llparse_match_s llparse_match_t; + +static llparse_match_t llparse__match_sequence_to_lower( + llhttp__internal_t* s, const unsigned char* p, + const unsigned char* endp, + const unsigned char* seq, uint32_t seq_len) { + uint32_t index; + llparse_match_t res; + + index = s->_index; + for (; p != endp; p++) { + unsigned char current; + + current = ((*p) >= 'A' && (*p) <= 'Z' ? (*p | 0x20) : (*p)); + if (current == seq[index]) { + if (++index == seq_len) { + res.status = kMatchComplete; + goto reset; + } + } else { + res.status = kMatchMismatch; + goto reset; + } + } + s->_index = index; + res.status = kMatchPause; + res.current = p; + return res; +reset: + s->_index = 0; + res.current = p; + return res; +} + +static llparse_match_t llparse__match_sequence_to_lower_unsafe( + llhttp__internal_t* s, const unsigned char* p, + const unsigned char* endp, + const unsigned char* seq, uint32_t seq_len) { + uint32_t index; + llparse_match_t res; + + index = s->_index; + for (; p != endp; p++) { + unsigned char current; + + current = ((*p) | 0x20); + if (current == seq[index]) { + if (++index == seq_len) { + res.status = kMatchComplete; + goto reset; + } + } else { + res.status = kMatchMismatch; + goto reset; + } + } + s->_index = index; + res.status = kMatchPause; + res.current = p; + return res; +reset: + s->_index = 0; + res.current = p; + return res; +} + +static llparse_match_t llparse__match_sequence_id( + llhttp__internal_t* s, const unsigned char* p, + const unsigned char* endp, + const unsigned char* seq, uint32_t seq_len) { + uint32_t index; + llparse_match_t res; + + index = s->_index; + for (; p != endp; p++) { + unsigned char current; + + current = *p; + if (current == seq[index]) { + if (++index == seq_len) { + res.status = kMatchComplete; + goto reset; + } + } else { + res.status = kMatchMismatch; + goto reset; + } + } + s->_index = index; + res.status = kMatchPause; + res.current = p; + return res; +reset: + s->_index = 0; + res.current = p; + return res; +} + +enum llparse_state_e { + s_error, + s_n_llhttp__internal__n_closed, + s_n_llhttp__internal__n_invoke_llhttp__after_message_complete, + s_n_llhttp__internal__n_pause_1, + s_n_llhttp__internal__n_invoke_is_equal_upgrade, + s_n_llhttp__internal__n_invoke_llhttp__on_message_complete_2, + s_n_llhttp__internal__n_chunk_data_almost_done_1, + s_n_llhttp__internal__n_chunk_data_almost_done, + s_n_llhttp__internal__n_consume_content_length, + s_n_llhttp__internal__n_span_start_llhttp__on_body, + s_n_llhttp__internal__n_invoke_is_equal_content_length, + s_n_llhttp__internal__n_chunk_size_almost_done, + s_n_llhttp__internal__n_invoke_test_lenient_flags_9, + s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_name_complete, + s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_name_complete_1, + s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_name_complete_2, + s_n_llhttp__internal__n_invoke_test_lenient_flags_10, + s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_value_complete, + s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_value_complete_1, + s_n_llhttp__internal__n_chunk_extension_quoted_value_done, + s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_value_complete_2, + s_n_llhttp__internal__n_error_30, + s_n_llhttp__internal__n_chunk_extension_quoted_value_quoted_pair, + s_n_llhttp__internal__n_error_31, + s_n_llhttp__internal__n_chunk_extension_quoted_value, + s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_value_complete_3, + s_n_llhttp__internal__n_error_33, + s_n_llhttp__internal__n_chunk_extension_value, + s_n_llhttp__internal__n_span_start_llhttp__on_chunk_extension_value, + s_n_llhttp__internal__n_error_34, + s_n_llhttp__internal__n_chunk_extension_name, + s_n_llhttp__internal__n_span_start_llhttp__on_chunk_extension_name, + s_n_llhttp__internal__n_chunk_extensions, + s_n_llhttp__internal__n_chunk_size_otherwise, + s_n_llhttp__internal__n_chunk_size, + s_n_llhttp__internal__n_chunk_size_digit, + s_n_llhttp__internal__n_invoke_update_content_length_1, + s_n_llhttp__internal__n_consume_content_length_1, + s_n_llhttp__internal__n_span_start_llhttp__on_body_1, + s_n_llhttp__internal__n_eof, + s_n_llhttp__internal__n_span_start_llhttp__on_body_2, + s_n_llhttp__internal__n_invoke_llhttp__after_headers_complete, + s_n_llhttp__internal__n_error_5, + s_n_llhttp__internal__n_headers_almost_done, + s_n_llhttp__internal__n_header_field_colon_discard_ws, + s_n_llhttp__internal__n_invoke_llhttp__on_header_value_complete, + s_n_llhttp__internal__n_span_start_llhttp__on_header_value, + s_n_llhttp__internal__n_header_value_discard_lws, + s_n_llhttp__internal__n_header_value_discard_ws_almost_done, + s_n_llhttp__internal__n_header_value_lws, + s_n_llhttp__internal__n_header_value_almost_done, + s_n_llhttp__internal__n_invoke_test_lenient_flags_17, + s_n_llhttp__internal__n_header_value_lenient, + s_n_llhttp__internal__n_error_52, + s_n_llhttp__internal__n_header_value_otherwise, + s_n_llhttp__internal__n_header_value_connection_token, + s_n_llhttp__internal__n_header_value_connection_ws, + s_n_llhttp__internal__n_header_value_connection_1, + s_n_llhttp__internal__n_header_value_connection_2, + s_n_llhttp__internal__n_header_value_connection_3, + s_n_llhttp__internal__n_header_value_connection, + s_n_llhttp__internal__n_error_54, + s_n_llhttp__internal__n_error_55, + s_n_llhttp__internal__n_header_value_content_length_ws, + s_n_llhttp__internal__n_header_value_content_length, + s_n_llhttp__internal__n_error_57, + s_n_llhttp__internal__n_error_56, + s_n_llhttp__internal__n_header_value_te_token_ows, + s_n_llhttp__internal__n_header_value, + s_n_llhttp__internal__n_header_value_te_token, + s_n_llhttp__internal__n_header_value_te_chunked_last, + s_n_llhttp__internal__n_header_value_te_chunked, + s_n_llhttp__internal__n_span_start_llhttp__on_header_value_1, + s_n_llhttp__internal__n_header_value_discard_ws, + s_n_llhttp__internal__n_invoke_load_header_state, + s_n_llhttp__internal__n_invoke_llhttp__on_header_field_complete, + s_n_llhttp__internal__n_header_field_general_otherwise, + s_n_llhttp__internal__n_header_field_general, + s_n_llhttp__internal__n_header_field_colon, + s_n_llhttp__internal__n_header_field_3, + s_n_llhttp__internal__n_header_field_4, + s_n_llhttp__internal__n_header_field_2, + s_n_llhttp__internal__n_header_field_1, + s_n_llhttp__internal__n_header_field_5, + s_n_llhttp__internal__n_header_field_6, + s_n_llhttp__internal__n_header_field_7, + s_n_llhttp__internal__n_header_field, + s_n_llhttp__internal__n_span_start_llhttp__on_header_field, + s_n_llhttp__internal__n_header_field_start, + s_n_llhttp__internal__n_headers_start, + s_n_llhttp__internal__n_url_to_http_09, + s_n_llhttp__internal__n_url_skip_to_http09, + s_n_llhttp__internal__n_url_skip_lf_to_http09_1, + s_n_llhttp__internal__n_url_skip_lf_to_http09, + s_n_llhttp__internal__n_req_pri_upgrade, + s_n_llhttp__internal__n_req_http_complete_crlf, + s_n_llhttp__internal__n_req_http_complete, + s_n_llhttp__internal__n_invoke_load_method_1, + s_n_llhttp__internal__n_invoke_llhttp__on_version_complete, + s_n_llhttp__internal__n_error_64, + s_n_llhttp__internal__n_error_71, + s_n_llhttp__internal__n_req_http_minor, + s_n_llhttp__internal__n_error_72, + s_n_llhttp__internal__n_req_http_dot, + s_n_llhttp__internal__n_error_73, + s_n_llhttp__internal__n_req_http_major, + s_n_llhttp__internal__n_span_start_llhttp__on_version, + s_n_llhttp__internal__n_req_http_start_1, + s_n_llhttp__internal__n_req_http_start_2, + s_n_llhttp__internal__n_req_http_start_3, + s_n_llhttp__internal__n_req_http_start, + s_n_llhttp__internal__n_url_to_http, + s_n_llhttp__internal__n_url_skip_to_http, + s_n_llhttp__internal__n_url_fragment, + s_n_llhttp__internal__n_span_end_stub_query_3, + s_n_llhttp__internal__n_url_query, + s_n_llhttp__internal__n_url_query_or_fragment, + s_n_llhttp__internal__n_url_path, + s_n_llhttp__internal__n_span_start_stub_path_2, + s_n_llhttp__internal__n_span_start_stub_path, + s_n_llhttp__internal__n_span_start_stub_path_1, + s_n_llhttp__internal__n_url_server_with_at, + s_n_llhttp__internal__n_url_server, + s_n_llhttp__internal__n_url_schema_delim_1, + s_n_llhttp__internal__n_url_schema_delim, + s_n_llhttp__internal__n_span_end_stub_schema, + s_n_llhttp__internal__n_url_schema, + s_n_llhttp__internal__n_url_start, + s_n_llhttp__internal__n_span_start_llhttp__on_url_1, + s_n_llhttp__internal__n_url_entry_normal, + s_n_llhttp__internal__n_span_start_llhttp__on_url, + s_n_llhttp__internal__n_url_entry_connect, + s_n_llhttp__internal__n_req_spaces_before_url, + s_n_llhttp__internal__n_req_first_space_before_url, + s_n_llhttp__internal__n_invoke_llhttp__on_method_complete_1, + s_n_llhttp__internal__n_after_start_req_2, + s_n_llhttp__internal__n_after_start_req_3, + s_n_llhttp__internal__n_after_start_req_1, + s_n_llhttp__internal__n_after_start_req_4, + s_n_llhttp__internal__n_after_start_req_6, + s_n_llhttp__internal__n_after_start_req_8, + s_n_llhttp__internal__n_after_start_req_9, + s_n_llhttp__internal__n_after_start_req_7, + s_n_llhttp__internal__n_after_start_req_5, + s_n_llhttp__internal__n_after_start_req_12, + s_n_llhttp__internal__n_after_start_req_13, + s_n_llhttp__internal__n_after_start_req_11, + s_n_llhttp__internal__n_after_start_req_10, + s_n_llhttp__internal__n_after_start_req_14, + s_n_llhttp__internal__n_after_start_req_17, + s_n_llhttp__internal__n_after_start_req_16, + s_n_llhttp__internal__n_after_start_req_15, + s_n_llhttp__internal__n_after_start_req_18, + s_n_llhttp__internal__n_after_start_req_20, + s_n_llhttp__internal__n_after_start_req_21, + s_n_llhttp__internal__n_after_start_req_19, + s_n_llhttp__internal__n_after_start_req_23, + s_n_llhttp__internal__n_after_start_req_24, + s_n_llhttp__internal__n_after_start_req_26, + s_n_llhttp__internal__n_after_start_req_28, + s_n_llhttp__internal__n_after_start_req_29, + s_n_llhttp__internal__n_after_start_req_27, + s_n_llhttp__internal__n_after_start_req_25, + s_n_llhttp__internal__n_after_start_req_30, + s_n_llhttp__internal__n_after_start_req_22, + s_n_llhttp__internal__n_after_start_req_31, + s_n_llhttp__internal__n_after_start_req_32, + s_n_llhttp__internal__n_after_start_req_35, + s_n_llhttp__internal__n_after_start_req_36, + s_n_llhttp__internal__n_after_start_req_34, + s_n_llhttp__internal__n_after_start_req_37, + s_n_llhttp__internal__n_after_start_req_38, + s_n_llhttp__internal__n_after_start_req_42, + s_n_llhttp__internal__n_after_start_req_43, + s_n_llhttp__internal__n_after_start_req_41, + s_n_llhttp__internal__n_after_start_req_40, + s_n_llhttp__internal__n_after_start_req_39, + s_n_llhttp__internal__n_after_start_req_45, + s_n_llhttp__internal__n_after_start_req_44, + s_n_llhttp__internal__n_after_start_req_33, + s_n_llhttp__internal__n_after_start_req_48, + s_n_llhttp__internal__n_after_start_req_49, + s_n_llhttp__internal__n_after_start_req_50, + s_n_llhttp__internal__n_after_start_req_51, + s_n_llhttp__internal__n_after_start_req_47, + s_n_llhttp__internal__n_after_start_req_46, + s_n_llhttp__internal__n_after_start_req_54, + s_n_llhttp__internal__n_after_start_req_56, + s_n_llhttp__internal__n_after_start_req_57, + s_n_llhttp__internal__n_after_start_req_55, + s_n_llhttp__internal__n_after_start_req_53, + s_n_llhttp__internal__n_after_start_req_58, + s_n_llhttp__internal__n_after_start_req_59, + s_n_llhttp__internal__n_after_start_req_52, + s_n_llhttp__internal__n_after_start_req_61, + s_n_llhttp__internal__n_after_start_req_62, + s_n_llhttp__internal__n_after_start_req_60, + s_n_llhttp__internal__n_after_start_req_65, + s_n_llhttp__internal__n_after_start_req_67, + s_n_llhttp__internal__n_after_start_req_68, + s_n_llhttp__internal__n_after_start_req_66, + s_n_llhttp__internal__n_after_start_req_69, + s_n_llhttp__internal__n_after_start_req_64, + s_n_llhttp__internal__n_after_start_req_63, + s_n_llhttp__internal__n_after_start_req, + s_n_llhttp__internal__n_span_start_llhttp__on_method_1, + s_n_llhttp__internal__n_res_line_almost_done, + s_n_llhttp__internal__n_invoke_test_lenient_flags_29, + s_n_llhttp__internal__n_res_status, + s_n_llhttp__internal__n_span_start_llhttp__on_status, + s_n_llhttp__internal__n_res_status_code_otherwise, + s_n_llhttp__internal__n_res_status_code_digit_3, + s_n_llhttp__internal__n_res_status_code_digit_2, + s_n_llhttp__internal__n_res_status_code_digit_1, + s_n_llhttp__internal__n_res_after_version, + s_n_llhttp__internal__n_invoke_llhttp__on_version_complete_1, + s_n_llhttp__internal__n_error_87, + s_n_llhttp__internal__n_error_101, + s_n_llhttp__internal__n_res_http_minor, + s_n_llhttp__internal__n_error_102, + s_n_llhttp__internal__n_res_http_dot, + s_n_llhttp__internal__n_error_103, + s_n_llhttp__internal__n_res_http_major, + s_n_llhttp__internal__n_span_start_llhttp__on_version_1, + s_n_llhttp__internal__n_start_res, + s_n_llhttp__internal__n_invoke_llhttp__on_method_complete, + s_n_llhttp__internal__n_req_or_res_method_2, + s_n_llhttp__internal__n_invoke_update_type_1, + s_n_llhttp__internal__n_req_or_res_method_3, + s_n_llhttp__internal__n_req_or_res_method_1, + s_n_llhttp__internal__n_req_or_res_method, + s_n_llhttp__internal__n_span_start_llhttp__on_method, + s_n_llhttp__internal__n_start_req_or_res, + s_n_llhttp__internal__n_invoke_load_type, + s_n_llhttp__internal__n_invoke_update_finish, + s_n_llhttp__internal__n_start, +}; +typedef enum llparse_state_e llparse_state_t; + +int llhttp__on_method( + llhttp__internal_t* s, const unsigned char* p, + const unsigned char* endp); + +int llhttp__on_url( + llhttp__internal_t* s, const unsigned char* p, + const unsigned char* endp); + +int llhttp__on_version( + llhttp__internal_t* s, const unsigned char* p, + const unsigned char* endp); + +int llhttp__on_header_field( + llhttp__internal_t* s, const unsigned char* p, + const unsigned char* endp); + +int llhttp__on_header_value( + llhttp__internal_t* s, const unsigned char* p, + const unsigned char* endp); + +int llhttp__on_body( + llhttp__internal_t* s, const unsigned char* p, + const unsigned char* endp); + +int llhttp__on_chunk_extension_name( + llhttp__internal_t* s, const unsigned char* p, + const unsigned char* endp); + +int llhttp__on_chunk_extension_value( + llhttp__internal_t* s, const unsigned char* p, + const unsigned char* endp); + +int llhttp__on_status( + llhttp__internal_t* s, const unsigned char* p, + const unsigned char* endp); + +int llhttp__internal__c_load_initial_message_completed( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp) { + return state->initial_message_completed; +} + +int llhttp__on_reset( + llhttp__internal_t* s, const unsigned char* p, + const unsigned char* endp); + +int llhttp__internal__c_update_finish( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp) { + state->finish = 2; + return 0; +} + +int llhttp__on_message_begin( + llhttp__internal_t* s, const unsigned char* p, + const unsigned char* endp); + +int llhttp__internal__c_load_type( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp) { + return state->type; +} + +int llhttp__internal__c_store_method( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp, + int match) { + state->method = match; + return 0; +} + +int llhttp__on_method_complete( + llhttp__internal_t* s, const unsigned char* p, + const unsigned char* endp); + +int llhttp__internal__c_is_equal_method( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp) { + return state->method == 5; +} + +int llhttp__internal__c_update_http_major( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp) { + state->http_major = 0; + return 0; +} + +int llhttp__internal__c_update_http_minor( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp) { + state->http_minor = 9; + return 0; +} + +int llhttp__on_url_complete( + llhttp__internal_t* s, const unsigned char* p, + const unsigned char* endp); + +int llhttp__internal__c_test_lenient_flags( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp) { + return (state->lenient_flags & 1) == 1; +} + +int llhttp__internal__c_test_lenient_flags_1( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp) { + return (state->lenient_flags & 256) == 256; +} + +int llhttp__internal__c_test_flags( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp) { + return (state->flags & 128) == 128; +} + +int llhttp__on_chunk_complete( + llhttp__internal_t* s, const unsigned char* p, + const unsigned char* endp); + +int llhttp__on_message_complete( + llhttp__internal_t* s, const unsigned char* p, + const unsigned char* endp); + +int llhttp__internal__c_is_equal_upgrade( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp) { + return state->upgrade == 1; +} + +int llhttp__after_message_complete( + llhttp__internal_t* s, const unsigned char* p, + const unsigned char* endp); + +int llhttp__internal__c_update_content_length( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp) { + state->content_length = 0; + return 0; +} + +int llhttp__internal__c_update_initial_message_completed( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp) { + state->initial_message_completed = 1; + return 0; +} + +int llhttp__internal__c_update_finish_1( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp) { + state->finish = 0; + return 0; +} + +int llhttp__internal__c_test_lenient_flags_2( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp) { + return (state->lenient_flags & 4) == 4; +} + +int llhttp__internal__c_test_lenient_flags_3( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp) { + return (state->lenient_flags & 32) == 32; +} + +int llhttp__before_headers_complete( + llhttp__internal_t* s, const unsigned char* p, + const unsigned char* endp); + +int llhttp__on_headers_complete( + llhttp__internal_t* s, const unsigned char* p, + const unsigned char* endp); + +int llhttp__after_headers_complete( + llhttp__internal_t* s, const unsigned char* p, + const unsigned char* endp); + +int llhttp__internal__c_mul_add_content_length( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp, + int match) { + /* Multiplication overflow */ + if (state->content_length > 0xffffffffffffffffULL / 16) { + return 1; + } + + state->content_length *= 16; + + /* Addition overflow */ + if (match >= 0) { + if (state->content_length > 0xffffffffffffffffULL - match) { + return 1; + } + } else { + if (state->content_length < 0ULL - match) { + return 1; + } + } + state->content_length += match; + return 0; +} + +int llhttp__internal__c_test_lenient_flags_4( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp) { + return (state->lenient_flags & 512) == 512; +} + +int llhttp__on_chunk_header( + llhttp__internal_t* s, const unsigned char* p, + const unsigned char* endp); + +int llhttp__internal__c_is_equal_content_length( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp) { + return state->content_length == 0; +} + +int llhttp__internal__c_test_lenient_flags_7( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp) { + return (state->lenient_flags & 128) == 128; +} + +int llhttp__internal__c_or_flags( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp) { + state->flags |= 128; + return 0; +} + +int llhttp__internal__c_test_lenient_flags_8( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp) { + return (state->lenient_flags & 64) == 64; +} + +int llhttp__on_chunk_extension_name_complete( + llhttp__internal_t* s, const unsigned char* p, + const unsigned char* endp); + +int llhttp__on_chunk_extension_value_complete( + llhttp__internal_t* s, const unsigned char* p, + const unsigned char* endp); + +int llhttp__internal__c_update_finish_3( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp) { + state->finish = 1; + return 0; +} + +int llhttp__internal__c_or_flags_1( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp) { + state->flags |= 64; + return 0; +} + +int llhttp__internal__c_update_upgrade( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp) { + state->upgrade = 1; + return 0; +} + +int llhttp__internal__c_store_header_state( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp, + int match) { + state->header_state = match; + return 0; +} + +int llhttp__on_header_field_complete( + llhttp__internal_t* s, const unsigned char* p, + const unsigned char* endp); + +int llhttp__internal__c_load_header_state( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp) { + return state->header_state; +} + +int llhttp__internal__c_test_flags_4( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp) { + return (state->flags & 512) == 512; +} + +int llhttp__internal__c_test_lenient_flags_21( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp) { + return (state->lenient_flags & 2) == 2; +} + +int llhttp__internal__c_or_flags_5( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp) { + state->flags |= 1; + return 0; +} + +int llhttp__internal__c_update_header_state( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp) { + state->header_state = 1; + return 0; +} + +int llhttp__on_header_value_complete( + llhttp__internal_t* s, const unsigned char* p, + const unsigned char* endp); + +int llhttp__internal__c_or_flags_6( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp) { + state->flags |= 2; + return 0; +} + +int llhttp__internal__c_or_flags_7( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp) { + state->flags |= 4; + return 0; +} + +int llhttp__internal__c_or_flags_8( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp) { + state->flags |= 8; + return 0; +} + +int llhttp__internal__c_update_header_state_3( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp) { + state->header_state = 6; + return 0; +} + +int llhttp__internal__c_update_header_state_1( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp) { + state->header_state = 0; + return 0; +} + +int llhttp__internal__c_update_header_state_6( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp) { + state->header_state = 5; + return 0; +} + +int llhttp__internal__c_update_header_state_7( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp) { + state->header_state = 7; + return 0; +} + +int llhttp__internal__c_test_flags_2( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp) { + return (state->flags & 32) == 32; +} + +int llhttp__internal__c_mul_add_content_length_1( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp, + int match) { + /* Multiplication overflow */ + if (state->content_length > 0xffffffffffffffffULL / 10) { + return 1; + } + + state->content_length *= 10; + + /* Addition overflow */ + if (match >= 0) { + if (state->content_length > 0xffffffffffffffffULL - match) { + return 1; + } + } else { + if (state->content_length < 0ULL - match) { + return 1; + } + } + state->content_length += match; + return 0; +} + +int llhttp__internal__c_or_flags_17( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp) { + state->flags |= 32; + return 0; +} + +int llhttp__internal__c_test_flags_3( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp) { + return (state->flags & 8) == 8; +} + +int llhttp__internal__c_test_lenient_flags_19( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp) { + return (state->lenient_flags & 8) == 8; +} + +int llhttp__internal__c_or_flags_18( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp) { + state->flags |= 512; + return 0; +} + +int llhttp__internal__c_and_flags( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp) { + state->flags &= -9; + return 0; +} + +int llhttp__internal__c_update_header_state_8( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp) { + state->header_state = 8; + return 0; +} + +int llhttp__internal__c_or_flags_20( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp) { + state->flags |= 16; + return 0; +} + +int llhttp__internal__c_load_method( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp) { + return state->method; +} + +int llhttp__internal__c_store_http_major( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp, + int match) { + state->http_major = match; + return 0; +} + +int llhttp__internal__c_store_http_minor( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp, + int match) { + state->http_minor = match; + return 0; +} + +int llhttp__internal__c_test_lenient_flags_23( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp) { + return (state->lenient_flags & 16) == 16; +} + +int llhttp__on_version_complete( + llhttp__internal_t* s, const unsigned char* p, + const unsigned char* endp); + +int llhttp__internal__c_load_http_major( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp) { + return state->http_major; +} + +int llhttp__internal__c_load_http_minor( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp) { + return state->http_minor; +} + +int llhttp__internal__c_update_status_code( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp) { + state->status_code = 0; + return 0; +} + +int llhttp__internal__c_mul_add_status_code( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp, + int match) { + /* Multiplication overflow */ + if (state->status_code > 0xffff / 10) { + return 1; + } + + state->status_code *= 10; + + /* Addition overflow */ + if (match >= 0) { + if (state->status_code > 0xffff - match) { + return 1; + } + } else { + if (state->status_code < 0 - match) { + return 1; + } + } + state->status_code += match; + return 0; +} + +int llhttp__on_status_complete( + llhttp__internal_t* s, const unsigned char* p, + const unsigned char* endp); + +int llhttp__internal__c_update_type( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp) { + state->type = 1; + return 0; +} + +int llhttp__internal__c_update_type_1( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp) { + state->type = 2; + return 0; +} + +int llhttp__internal_init(llhttp__internal_t* state) { + memset(state, 0, sizeof(*state)); + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_start; + return 0; +} + +static llparse_state_t llhttp__internal__run( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp) { + int match; + switch ((llparse_state_t) (intptr_t) state->_current) { + case s_n_llhttp__internal__n_closed: + s_n_llhttp__internal__n_closed: { + if (p == endp) { + return s_n_llhttp__internal__n_closed; + } + switch (*p) { + case 10: { + p++; + goto s_n_llhttp__internal__n_closed; + } + case 13: { + p++; + goto s_n_llhttp__internal__n_closed; + } + default: { + p++; + goto s_n_llhttp__internal__n_invoke_test_lenient_flags_3; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_invoke_llhttp__after_message_complete: + s_n_llhttp__internal__n_invoke_llhttp__after_message_complete: { + switch (llhttp__after_message_complete(state, p, endp)) { + case 1: + goto s_n_llhttp__internal__n_invoke_update_content_length; + default: + goto s_n_llhttp__internal__n_invoke_update_finish_1; + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_pause_1: + s_n_llhttp__internal__n_pause_1: { + state->error = 0x16; + state->reason = "Pause on CONNECT/Upgrade"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_llhttp__after_message_complete; + return s_error; + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_invoke_is_equal_upgrade: + s_n_llhttp__internal__n_invoke_is_equal_upgrade: { + switch (llhttp__internal__c_is_equal_upgrade(state, p, endp)) { + case 0: + goto s_n_llhttp__internal__n_invoke_llhttp__after_message_complete; + default: + goto s_n_llhttp__internal__n_pause_1; + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_invoke_llhttp__on_message_complete_2: + s_n_llhttp__internal__n_invoke_llhttp__on_message_complete_2: { + switch (llhttp__on_message_complete(state, p, endp)) { + case 0: + goto s_n_llhttp__internal__n_invoke_is_equal_upgrade; + case 21: + goto s_n_llhttp__internal__n_pause_13; + default: + goto s_n_llhttp__internal__n_error_38; + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_chunk_data_almost_done_1: + s_n_llhttp__internal__n_chunk_data_almost_done_1: { + if (p == endp) { + return s_n_llhttp__internal__n_chunk_data_almost_done_1; + } + switch (*p) { + case 10: { + p++; + goto s_n_llhttp__internal__n_invoke_llhttp__on_chunk_complete; + } + default: { + goto s_n_llhttp__internal__n_invoke_test_lenient_flags_7; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_chunk_data_almost_done: + s_n_llhttp__internal__n_chunk_data_almost_done: { + if (p == endp) { + return s_n_llhttp__internal__n_chunk_data_almost_done; + } + switch (*p) { + case 10: { + p++; + goto s_n_llhttp__internal__n_invoke_test_lenient_flags_6; + } + case 13: { + p++; + goto s_n_llhttp__internal__n_chunk_data_almost_done_1; + } + default: { + goto s_n_llhttp__internal__n_invoke_test_lenient_flags_7; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_consume_content_length: + s_n_llhttp__internal__n_consume_content_length: { + size_t avail; + uint64_t need; + + avail = endp - p; + need = state->content_length; + if (avail >= need) { + p += need; + state->content_length = 0; + goto s_n_llhttp__internal__n_span_end_llhttp__on_body; + } + + state->content_length -= avail; + return s_n_llhttp__internal__n_consume_content_length; + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_span_start_llhttp__on_body: + s_n_llhttp__internal__n_span_start_llhttp__on_body: { + if (p == endp) { + return s_n_llhttp__internal__n_span_start_llhttp__on_body; + } + state->_span_pos0 = (void*) p; + state->_span_cb0 = llhttp__on_body; + goto s_n_llhttp__internal__n_consume_content_length; + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_invoke_is_equal_content_length: + s_n_llhttp__internal__n_invoke_is_equal_content_length: { + switch (llhttp__internal__c_is_equal_content_length(state, p, endp)) { + case 0: + goto s_n_llhttp__internal__n_span_start_llhttp__on_body; + default: + goto s_n_llhttp__internal__n_invoke_or_flags; + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_chunk_size_almost_done: + s_n_llhttp__internal__n_chunk_size_almost_done: { + if (p == endp) { + return s_n_llhttp__internal__n_chunk_size_almost_done; + } + switch (*p) { + case 10: { + p++; + goto s_n_llhttp__internal__n_invoke_llhttp__on_chunk_header; + } + default: { + goto s_n_llhttp__internal__n_invoke_test_lenient_flags_8; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_invoke_test_lenient_flags_9: + s_n_llhttp__internal__n_invoke_test_lenient_flags_9: { + switch (llhttp__internal__c_test_lenient_flags_1(state, p, endp)) { + case 1: + goto s_n_llhttp__internal__n_chunk_size_almost_done; + default: + goto s_n_llhttp__internal__n_error_20; + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_name_complete: + s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_name_complete: { + switch (llhttp__on_chunk_extension_name_complete(state, p, endp)) { + case 0: + goto s_n_llhttp__internal__n_invoke_test_lenient_flags_9; + case 21: + goto s_n_llhttp__internal__n_pause_5; + default: + goto s_n_llhttp__internal__n_error_19; + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_name_complete_1: + s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_name_complete_1: { + switch (llhttp__on_chunk_extension_name_complete(state, p, endp)) { + case 0: + goto s_n_llhttp__internal__n_chunk_size_almost_done; + case 21: + goto s_n_llhttp__internal__n_pause_6; + default: + goto s_n_llhttp__internal__n_error_21; + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_name_complete_2: + s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_name_complete_2: { + switch (llhttp__on_chunk_extension_name_complete(state, p, endp)) { + case 0: + goto s_n_llhttp__internal__n_chunk_extensions; + case 21: + goto s_n_llhttp__internal__n_pause_7; + default: + goto s_n_llhttp__internal__n_error_22; + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_invoke_test_lenient_flags_10: + s_n_llhttp__internal__n_invoke_test_lenient_flags_10: { + switch (llhttp__internal__c_test_lenient_flags_1(state, p, endp)) { + case 1: + goto s_n_llhttp__internal__n_chunk_size_almost_done; + default: + goto s_n_llhttp__internal__n_error_25; + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_value_complete: + s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_value_complete: { + switch (llhttp__on_chunk_extension_value_complete(state, p, endp)) { + case 0: + goto s_n_llhttp__internal__n_invoke_test_lenient_flags_10; + case 21: + goto s_n_llhttp__internal__n_pause_8; + default: + goto s_n_llhttp__internal__n_error_24; + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_value_complete_1: + s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_value_complete_1: { + switch (llhttp__on_chunk_extension_value_complete(state, p, endp)) { + case 0: + goto s_n_llhttp__internal__n_chunk_size_almost_done; + case 21: + goto s_n_llhttp__internal__n_pause_9; + default: + goto s_n_llhttp__internal__n_error_26; + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_chunk_extension_quoted_value_done: + s_n_llhttp__internal__n_chunk_extension_quoted_value_done: { + if (p == endp) { + return s_n_llhttp__internal__n_chunk_extension_quoted_value_done; + } + switch (*p) { + case 10: { + goto s_n_llhttp__internal__n_invoke_test_lenient_flags_11; + } + case 13: { + p++; + goto s_n_llhttp__internal__n_chunk_size_almost_done; + } + case ';': { + p++; + goto s_n_llhttp__internal__n_chunk_extensions; + } + default: { + goto s_n_llhttp__internal__n_error_29; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_value_complete_2: + s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_value_complete_2: { + switch (llhttp__on_chunk_extension_value_complete(state, p, endp)) { + case 0: + goto s_n_llhttp__internal__n_chunk_extension_quoted_value_done; + case 21: + goto s_n_llhttp__internal__n_pause_10; + default: + goto s_n_llhttp__internal__n_error_27; + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_error_30: + s_n_llhttp__internal__n_error_30: { + state->error = 0x2; + state->reason = "Invalid quoted-pair in chunk extensions quoted value"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_chunk_extension_quoted_value_quoted_pair: + s_n_llhttp__internal__n_chunk_extension_quoted_value_quoted_pair: { + static uint8_t lookup_table[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + }; + if (p == endp) { + return s_n_llhttp__internal__n_chunk_extension_quoted_value_quoted_pair; + } + switch (lookup_table[(uint8_t) *p]) { + case 1: { + p++; + goto s_n_llhttp__internal__n_chunk_extension_quoted_value; + } + default: { + goto s_n_llhttp__internal__n_span_end_llhttp__on_chunk_extension_value_3; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_error_31: + s_n_llhttp__internal__n_error_31: { + state->error = 0x2; + state->reason = "Invalid character in chunk extensions quoted value"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_chunk_extension_quoted_value: + s_n_llhttp__internal__n_chunk_extension_quoted_value: { + static uint8_t lookup_table[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + }; + if (p == endp) { + return s_n_llhttp__internal__n_chunk_extension_quoted_value; + } + switch (lookup_table[(uint8_t) *p]) { + case 1: { + p++; + goto s_n_llhttp__internal__n_chunk_extension_quoted_value; + } + case 2: { + p++; + goto s_n_llhttp__internal__n_span_end_llhttp__on_chunk_extension_value_2; + } + case 3: { + p++; + goto s_n_llhttp__internal__n_chunk_extension_quoted_value_quoted_pair; + } + default: { + goto s_n_llhttp__internal__n_span_end_llhttp__on_chunk_extension_value_4; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_value_complete_3: + s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_value_complete_3: { + switch (llhttp__on_chunk_extension_value_complete(state, p, endp)) { + case 0: + goto s_n_llhttp__internal__n_chunk_extensions; + case 21: + goto s_n_llhttp__internal__n_pause_11; + default: + goto s_n_llhttp__internal__n_error_32; + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_error_33: + s_n_llhttp__internal__n_error_33: { + state->error = 0x2; + state->reason = "Invalid character in chunk extensions value"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_chunk_extension_value: + s_n_llhttp__internal__n_chunk_extension_value: { + static uint8_t lookup_table[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3, 4, 3, 3, 3, 3, 3, 0, 0, 3, 3, 0, 3, 3, 0, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 5, 0, 0, 0, 0, + 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 3, 0, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + if (p == endp) { + return s_n_llhttp__internal__n_chunk_extension_value; + } + switch (lookup_table[(uint8_t) *p]) { + case 1: { + goto s_n_llhttp__internal__n_span_end_llhttp__on_chunk_extension_value; + } + case 2: { + goto s_n_llhttp__internal__n_span_end_llhttp__on_chunk_extension_value_1; + } + case 3: { + p++; + goto s_n_llhttp__internal__n_chunk_extension_value; + } + case 4: { + p++; + goto s_n_llhttp__internal__n_chunk_extension_quoted_value; + } + case 5: { + goto s_n_llhttp__internal__n_span_end_llhttp__on_chunk_extension_value_5; + } + default: { + goto s_n_llhttp__internal__n_span_end_llhttp__on_chunk_extension_value_6; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_span_start_llhttp__on_chunk_extension_value: + s_n_llhttp__internal__n_span_start_llhttp__on_chunk_extension_value: { + if (p == endp) { + return s_n_llhttp__internal__n_span_start_llhttp__on_chunk_extension_value; + } + state->_span_pos0 = (void*) p; + state->_span_cb0 = llhttp__on_chunk_extension_value; + goto s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_name_complete_3; + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_error_34: + s_n_llhttp__internal__n_error_34: { + state->error = 0x2; + state->reason = "Invalid character in chunk extensions name"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_chunk_extension_name: + s_n_llhttp__internal__n_chunk_extension_name: { + static uint8_t lookup_table[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3, 0, 3, 3, 3, 3, 3, 0, 0, 3, 3, 0, 3, 3, 0, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 4, 0, 5, 0, 0, + 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 3, 0, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + if (p == endp) { + return s_n_llhttp__internal__n_chunk_extension_name; + } + switch (lookup_table[(uint8_t) *p]) { + case 1: { + goto s_n_llhttp__internal__n_span_end_llhttp__on_chunk_extension_name; + } + case 2: { + goto s_n_llhttp__internal__n_span_end_llhttp__on_chunk_extension_name_1; + } + case 3: { + p++; + goto s_n_llhttp__internal__n_chunk_extension_name; + } + case 4: { + goto s_n_llhttp__internal__n_span_end_llhttp__on_chunk_extension_name_2; + } + case 5: { + goto s_n_llhttp__internal__n_span_end_llhttp__on_chunk_extension_name_3; + } + default: { + goto s_n_llhttp__internal__n_span_end_llhttp__on_chunk_extension_name_4; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_span_start_llhttp__on_chunk_extension_name: + s_n_llhttp__internal__n_span_start_llhttp__on_chunk_extension_name: { + if (p == endp) { + return s_n_llhttp__internal__n_span_start_llhttp__on_chunk_extension_name; + } + state->_span_pos0 = (void*) p; + state->_span_cb0 = llhttp__on_chunk_extension_name; + goto s_n_llhttp__internal__n_chunk_extension_name; + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_chunk_extensions: + s_n_llhttp__internal__n_chunk_extensions: { + if (p == endp) { + return s_n_llhttp__internal__n_chunk_extensions; + } + switch (*p) { + case 13: { + p++; + goto s_n_llhttp__internal__n_error_17; + } + case ' ': { + p++; + goto s_n_llhttp__internal__n_error_18; + } + default: { + goto s_n_llhttp__internal__n_span_start_llhttp__on_chunk_extension_name; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_chunk_size_otherwise: + s_n_llhttp__internal__n_chunk_size_otherwise: { + if (p == endp) { + return s_n_llhttp__internal__n_chunk_size_otherwise; + } + switch (*p) { + case 9: { + p++; + goto s_n_llhttp__internal__n_invoke_test_lenient_flags_4; + } + case 10: { + p++; + goto s_n_llhttp__internal__n_invoke_test_lenient_flags_5; + } + case 13: { + p++; + goto s_n_llhttp__internal__n_chunk_size_almost_done; + } + case ' ': { + p++; + goto s_n_llhttp__internal__n_invoke_test_lenient_flags_4; + } + case ';': { + p++; + goto s_n_llhttp__internal__n_chunk_extensions; + } + default: { + goto s_n_llhttp__internal__n_error_35; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_chunk_size: + s_n_llhttp__internal__n_chunk_size: { + if (p == endp) { + return s_n_llhttp__internal__n_chunk_size; + } + switch (*p) { + case '0': { + p++; + match = 0; + goto s_n_llhttp__internal__n_invoke_mul_add_content_length; + } + case '1': { + p++; + match = 1; + goto s_n_llhttp__internal__n_invoke_mul_add_content_length; + } + case '2': { + p++; + match = 2; + goto s_n_llhttp__internal__n_invoke_mul_add_content_length; + } + case '3': { + p++; + match = 3; + goto s_n_llhttp__internal__n_invoke_mul_add_content_length; + } + case '4': { + p++; + match = 4; + goto s_n_llhttp__internal__n_invoke_mul_add_content_length; + } + case '5': { + p++; + match = 5; + goto s_n_llhttp__internal__n_invoke_mul_add_content_length; + } + case '6': { + p++; + match = 6; + goto s_n_llhttp__internal__n_invoke_mul_add_content_length; + } + case '7': { + p++; + match = 7; + goto s_n_llhttp__internal__n_invoke_mul_add_content_length; + } + case '8': { + p++; + match = 8; + goto s_n_llhttp__internal__n_invoke_mul_add_content_length; + } + case '9': { + p++; + match = 9; + goto s_n_llhttp__internal__n_invoke_mul_add_content_length; + } + case 'A': { + p++; + match = 10; + goto s_n_llhttp__internal__n_invoke_mul_add_content_length; + } + case 'B': { + p++; + match = 11; + goto s_n_llhttp__internal__n_invoke_mul_add_content_length; + } + case 'C': { + p++; + match = 12; + goto s_n_llhttp__internal__n_invoke_mul_add_content_length; + } + case 'D': { + p++; + match = 13; + goto s_n_llhttp__internal__n_invoke_mul_add_content_length; + } + case 'E': { + p++; + match = 14; + goto s_n_llhttp__internal__n_invoke_mul_add_content_length; + } + case 'F': { + p++; + match = 15; + goto s_n_llhttp__internal__n_invoke_mul_add_content_length; + } + case 'a': { + p++; + match = 10; + goto s_n_llhttp__internal__n_invoke_mul_add_content_length; + } + case 'b': { + p++; + match = 11; + goto s_n_llhttp__internal__n_invoke_mul_add_content_length; + } + case 'c': { + p++; + match = 12; + goto s_n_llhttp__internal__n_invoke_mul_add_content_length; + } + case 'd': { + p++; + match = 13; + goto s_n_llhttp__internal__n_invoke_mul_add_content_length; + } + case 'e': { + p++; + match = 14; + goto s_n_llhttp__internal__n_invoke_mul_add_content_length; + } + case 'f': { + p++; + match = 15; + goto s_n_llhttp__internal__n_invoke_mul_add_content_length; + } + default: { + goto s_n_llhttp__internal__n_chunk_size_otherwise; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_chunk_size_digit: + s_n_llhttp__internal__n_chunk_size_digit: { + if (p == endp) { + return s_n_llhttp__internal__n_chunk_size_digit; + } + switch (*p) { + case '0': { + p++; + match = 0; + goto s_n_llhttp__internal__n_invoke_mul_add_content_length; + } + case '1': { + p++; + match = 1; + goto s_n_llhttp__internal__n_invoke_mul_add_content_length; + } + case '2': { + p++; + match = 2; + goto s_n_llhttp__internal__n_invoke_mul_add_content_length; + } + case '3': { + p++; + match = 3; + goto s_n_llhttp__internal__n_invoke_mul_add_content_length; + } + case '4': { + p++; + match = 4; + goto s_n_llhttp__internal__n_invoke_mul_add_content_length; + } + case '5': { + p++; + match = 5; + goto s_n_llhttp__internal__n_invoke_mul_add_content_length; + } + case '6': { + p++; + match = 6; + goto s_n_llhttp__internal__n_invoke_mul_add_content_length; + } + case '7': { + p++; + match = 7; + goto s_n_llhttp__internal__n_invoke_mul_add_content_length; + } + case '8': { + p++; + match = 8; + goto s_n_llhttp__internal__n_invoke_mul_add_content_length; + } + case '9': { + p++; + match = 9; + goto s_n_llhttp__internal__n_invoke_mul_add_content_length; + } + case 'A': { + p++; + match = 10; + goto s_n_llhttp__internal__n_invoke_mul_add_content_length; + } + case 'B': { + p++; + match = 11; + goto s_n_llhttp__internal__n_invoke_mul_add_content_length; + } + case 'C': { + p++; + match = 12; + goto s_n_llhttp__internal__n_invoke_mul_add_content_length; + } + case 'D': { + p++; + match = 13; + goto s_n_llhttp__internal__n_invoke_mul_add_content_length; + } + case 'E': { + p++; + match = 14; + goto s_n_llhttp__internal__n_invoke_mul_add_content_length; + } + case 'F': { + p++; + match = 15; + goto s_n_llhttp__internal__n_invoke_mul_add_content_length; + } + case 'a': { + p++; + match = 10; + goto s_n_llhttp__internal__n_invoke_mul_add_content_length; + } + case 'b': { + p++; + match = 11; + goto s_n_llhttp__internal__n_invoke_mul_add_content_length; + } + case 'c': { + p++; + match = 12; + goto s_n_llhttp__internal__n_invoke_mul_add_content_length; + } + case 'd': { + p++; + match = 13; + goto s_n_llhttp__internal__n_invoke_mul_add_content_length; + } + case 'e': { + p++; + match = 14; + goto s_n_llhttp__internal__n_invoke_mul_add_content_length; + } + case 'f': { + p++; + match = 15; + goto s_n_llhttp__internal__n_invoke_mul_add_content_length; + } + default: { + goto s_n_llhttp__internal__n_error_37; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_invoke_update_content_length_1: + s_n_llhttp__internal__n_invoke_update_content_length_1: { + switch (llhttp__internal__c_update_content_length(state, p, endp)) { + default: + goto s_n_llhttp__internal__n_chunk_size_digit; + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_consume_content_length_1: + s_n_llhttp__internal__n_consume_content_length_1: { + size_t avail; + uint64_t need; + + avail = endp - p; + need = state->content_length; + if (avail >= need) { + p += need; + state->content_length = 0; + goto s_n_llhttp__internal__n_span_end_llhttp__on_body_1; + } + + state->content_length -= avail; + return s_n_llhttp__internal__n_consume_content_length_1; + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_span_start_llhttp__on_body_1: + s_n_llhttp__internal__n_span_start_llhttp__on_body_1: { + if (p == endp) { + return s_n_llhttp__internal__n_span_start_llhttp__on_body_1; + } + state->_span_pos0 = (void*) p; + state->_span_cb0 = llhttp__on_body; + goto s_n_llhttp__internal__n_consume_content_length_1; + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_eof: + s_n_llhttp__internal__n_eof: { + if (p == endp) { + return s_n_llhttp__internal__n_eof; + } + p++; + goto s_n_llhttp__internal__n_eof; + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_span_start_llhttp__on_body_2: + s_n_llhttp__internal__n_span_start_llhttp__on_body_2: { + if (p == endp) { + return s_n_llhttp__internal__n_span_start_llhttp__on_body_2; + } + state->_span_pos0 = (void*) p; + state->_span_cb0 = llhttp__on_body; + goto s_n_llhttp__internal__n_eof; + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_invoke_llhttp__after_headers_complete: + s_n_llhttp__internal__n_invoke_llhttp__after_headers_complete: { + switch (llhttp__after_headers_complete(state, p, endp)) { + case 1: + goto s_n_llhttp__internal__n_invoke_llhttp__on_message_complete_1; + case 2: + goto s_n_llhttp__internal__n_invoke_update_content_length_1; + case 3: + goto s_n_llhttp__internal__n_span_start_llhttp__on_body_1; + case 4: + goto s_n_llhttp__internal__n_invoke_update_finish_3; + case 5: + goto s_n_llhttp__internal__n_error_39; + default: + goto s_n_llhttp__internal__n_invoke_llhttp__on_message_complete; + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_error_5: + s_n_llhttp__internal__n_error_5: { + state->error = 0xa; + state->reason = "Invalid header field char"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_headers_almost_done: + s_n_llhttp__internal__n_headers_almost_done: { + if (p == endp) { + return s_n_llhttp__internal__n_headers_almost_done; + } + switch (*p) { + case 10: { + p++; + goto s_n_llhttp__internal__n_invoke_test_flags_1; + } + default: { + goto s_n_llhttp__internal__n_invoke_test_lenient_flags_12; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_header_field_colon_discard_ws: + s_n_llhttp__internal__n_header_field_colon_discard_ws: { + if (p == endp) { + return s_n_llhttp__internal__n_header_field_colon_discard_ws; + } + switch (*p) { + case ' ': { + p++; + goto s_n_llhttp__internal__n_header_field_colon_discard_ws; + } + default: { + goto s_n_llhttp__internal__n_header_field_colon; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_invoke_llhttp__on_header_value_complete: + s_n_llhttp__internal__n_invoke_llhttp__on_header_value_complete: { + switch (llhttp__on_header_value_complete(state, p, endp)) { + case 0: + goto s_n_llhttp__internal__n_header_field_start; + case 21: + goto s_n_llhttp__internal__n_pause_18; + default: + goto s_n_llhttp__internal__n_error_47; + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_span_start_llhttp__on_header_value: + s_n_llhttp__internal__n_span_start_llhttp__on_header_value: { + if (p == endp) { + return s_n_llhttp__internal__n_span_start_llhttp__on_header_value; + } + state->_span_pos0 = (void*) p; + state->_span_cb0 = llhttp__on_header_value; + goto s_n_llhttp__internal__n_span_end_llhttp__on_header_value; + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_header_value_discard_lws: + s_n_llhttp__internal__n_header_value_discard_lws: { + if (p == endp) { + return s_n_llhttp__internal__n_header_value_discard_lws; + } + switch (*p) { + case 9: { + p++; + goto s_n_llhttp__internal__n_invoke_test_lenient_flags_15; + } + case ' ': { + p++; + goto s_n_llhttp__internal__n_invoke_test_lenient_flags_15; + } + default: { + goto s_n_llhttp__internal__n_invoke_load_header_state_1; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_header_value_discard_ws_almost_done: + s_n_llhttp__internal__n_header_value_discard_ws_almost_done: { + if (p == endp) { + return s_n_llhttp__internal__n_header_value_discard_ws_almost_done; + } + switch (*p) { + case 10: { + p++; + goto s_n_llhttp__internal__n_header_value_discard_lws; + } + default: { + goto s_n_llhttp__internal__n_invoke_test_lenient_flags_16; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_header_value_lws: + s_n_llhttp__internal__n_header_value_lws: { + if (p == endp) { + return s_n_llhttp__internal__n_header_value_lws; + } + switch (*p) { + case 9: { + goto s_n_llhttp__internal__n_invoke_load_header_state_4; + } + case ' ': { + goto s_n_llhttp__internal__n_invoke_load_header_state_4; + } + default: { + goto s_n_llhttp__internal__n_invoke_load_header_state_5; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_header_value_almost_done: + s_n_llhttp__internal__n_header_value_almost_done: { + if (p == endp) { + return s_n_llhttp__internal__n_header_value_almost_done; + } + switch (*p) { + case 10: { + p++; + goto s_n_llhttp__internal__n_header_value_lws; + } + default: { + goto s_n_llhttp__internal__n_error_51; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_invoke_test_lenient_flags_17: + s_n_llhttp__internal__n_invoke_test_lenient_flags_17: { + switch (llhttp__internal__c_test_lenient_flags_1(state, p, endp)) { + case 1: + goto s_n_llhttp__internal__n_header_value_almost_done; + default: + goto s_n_llhttp__internal__n_error_50; + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_header_value_lenient: + s_n_llhttp__internal__n_header_value_lenient: { + if (p == endp) { + return s_n_llhttp__internal__n_header_value_lenient; + } + switch (*p) { + case 10: { + goto s_n_llhttp__internal__n_span_end_llhttp__on_header_value_4; + } + case 13: { + goto s_n_llhttp__internal__n_span_end_llhttp__on_header_value_5; + } + default: { + p++; + goto s_n_llhttp__internal__n_header_value_lenient; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_error_52: + s_n_llhttp__internal__n_error_52: { + state->error = 0xa; + state->reason = "Invalid header value char"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_header_value_otherwise: + s_n_llhttp__internal__n_header_value_otherwise: { + if (p == endp) { + return s_n_llhttp__internal__n_header_value_otherwise; + } + switch (*p) { + case 10: { + goto s_n_llhttp__internal__n_span_end_llhttp__on_header_value_1; + } + case 13: { + goto s_n_llhttp__internal__n_span_end_llhttp__on_header_value_2; + } + default: { + goto s_n_llhttp__internal__n_invoke_test_lenient_flags_18; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_header_value_connection_token: + s_n_llhttp__internal__n_header_value_connection_token: { + static uint8_t lookup_table[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + }; + if (p == endp) { + return s_n_llhttp__internal__n_header_value_connection_token; + } + switch (lookup_table[(uint8_t) *p]) { + case 1: { + p++; + goto s_n_llhttp__internal__n_header_value_connection_token; + } + case 2: { + p++; + goto s_n_llhttp__internal__n_header_value_connection; + } + default: { + goto s_n_llhttp__internal__n_header_value_otherwise; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_header_value_connection_ws: + s_n_llhttp__internal__n_header_value_connection_ws: { + if (p == endp) { + return s_n_llhttp__internal__n_header_value_connection_ws; + } + switch (*p) { + case 10: { + goto s_n_llhttp__internal__n_header_value_otherwise; + } + case 13: { + goto s_n_llhttp__internal__n_header_value_otherwise; + } + case ' ': { + p++; + goto s_n_llhttp__internal__n_header_value_connection_ws; + } + case ',': { + p++; + goto s_n_llhttp__internal__n_invoke_load_header_state_6; + } + default: { + goto s_n_llhttp__internal__n_invoke_update_header_state_5; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_header_value_connection_1: + s_n_llhttp__internal__n_header_value_connection_1: { + llparse_match_t match_seq; + + if (p == endp) { + return s_n_llhttp__internal__n_header_value_connection_1; + } + match_seq = llparse__match_sequence_to_lower(state, p, endp, llparse_blob2, 4); + p = match_seq.current; + switch (match_seq.status) { + case kMatchComplete: { + p++; + goto s_n_llhttp__internal__n_invoke_update_header_state_3; + } + case kMatchPause: { + return s_n_llhttp__internal__n_header_value_connection_1; + } + case kMatchMismatch: { + goto s_n_llhttp__internal__n_header_value_connection_token; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_header_value_connection_2: + s_n_llhttp__internal__n_header_value_connection_2: { + llparse_match_t match_seq; + + if (p == endp) { + return s_n_llhttp__internal__n_header_value_connection_2; + } + match_seq = llparse__match_sequence_to_lower(state, p, endp, llparse_blob3, 9); + p = match_seq.current; + switch (match_seq.status) { + case kMatchComplete: { + p++; + goto s_n_llhttp__internal__n_invoke_update_header_state_6; + } + case kMatchPause: { + return s_n_llhttp__internal__n_header_value_connection_2; + } + case kMatchMismatch: { + goto s_n_llhttp__internal__n_header_value_connection_token; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_header_value_connection_3: + s_n_llhttp__internal__n_header_value_connection_3: { + llparse_match_t match_seq; + + if (p == endp) { + return s_n_llhttp__internal__n_header_value_connection_3; + } + match_seq = llparse__match_sequence_to_lower(state, p, endp, llparse_blob4, 6); + p = match_seq.current; + switch (match_seq.status) { + case kMatchComplete: { + p++; + goto s_n_llhttp__internal__n_invoke_update_header_state_7; + } + case kMatchPause: { + return s_n_llhttp__internal__n_header_value_connection_3; + } + case kMatchMismatch: { + goto s_n_llhttp__internal__n_header_value_connection_token; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_header_value_connection: + s_n_llhttp__internal__n_header_value_connection: { + if (p == endp) { + return s_n_llhttp__internal__n_header_value_connection; + } + switch (((*p) >= 'A' && (*p) <= 'Z' ? (*p | 0x20) : (*p))) { + case 9: { + p++; + goto s_n_llhttp__internal__n_header_value_connection; + } + case ' ': { + p++; + goto s_n_llhttp__internal__n_header_value_connection; + } + case 'c': { + p++; + goto s_n_llhttp__internal__n_header_value_connection_1; + } + case 'k': { + p++; + goto s_n_llhttp__internal__n_header_value_connection_2; + } + case 'u': { + p++; + goto s_n_llhttp__internal__n_header_value_connection_3; + } + default: { + goto s_n_llhttp__internal__n_header_value_connection_token; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_error_54: + s_n_llhttp__internal__n_error_54: { + state->error = 0xb; + state->reason = "Content-Length overflow"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_error_55: + s_n_llhttp__internal__n_error_55: { + state->error = 0xb; + state->reason = "Invalid character in Content-Length"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_header_value_content_length_ws: + s_n_llhttp__internal__n_header_value_content_length_ws: { + if (p == endp) { + return s_n_llhttp__internal__n_header_value_content_length_ws; + } + switch (*p) { + case 10: { + goto s_n_llhttp__internal__n_invoke_or_flags_17; + } + case 13: { + goto s_n_llhttp__internal__n_invoke_or_flags_17; + } + case ' ': { + p++; + goto s_n_llhttp__internal__n_header_value_content_length_ws; + } + default: { + goto s_n_llhttp__internal__n_span_end_llhttp__on_header_value_7; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_header_value_content_length: + s_n_llhttp__internal__n_header_value_content_length: { + if (p == endp) { + return s_n_llhttp__internal__n_header_value_content_length; + } + switch (*p) { + case '0': { + p++; + match = 0; + goto s_n_llhttp__internal__n_invoke_mul_add_content_length_1; + } + case '1': { + p++; + match = 1; + goto s_n_llhttp__internal__n_invoke_mul_add_content_length_1; + } + case '2': { + p++; + match = 2; + goto s_n_llhttp__internal__n_invoke_mul_add_content_length_1; + } + case '3': { + p++; + match = 3; + goto s_n_llhttp__internal__n_invoke_mul_add_content_length_1; + } + case '4': { + p++; + match = 4; + goto s_n_llhttp__internal__n_invoke_mul_add_content_length_1; + } + case '5': { + p++; + match = 5; + goto s_n_llhttp__internal__n_invoke_mul_add_content_length_1; + } + case '6': { + p++; + match = 6; + goto s_n_llhttp__internal__n_invoke_mul_add_content_length_1; + } + case '7': { + p++; + match = 7; + goto s_n_llhttp__internal__n_invoke_mul_add_content_length_1; + } + case '8': { + p++; + match = 8; + goto s_n_llhttp__internal__n_invoke_mul_add_content_length_1; + } + case '9': { + p++; + match = 9; + goto s_n_llhttp__internal__n_invoke_mul_add_content_length_1; + } + default: { + goto s_n_llhttp__internal__n_header_value_content_length_ws; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_error_57: + s_n_llhttp__internal__n_error_57: { + state->error = 0xf; + state->reason = "Invalid `Transfer-Encoding` header value"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_error_56: + s_n_llhttp__internal__n_error_56: { + state->error = 0xf; + state->reason = "Invalid `Transfer-Encoding` header value"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_header_value_te_token_ows: + s_n_llhttp__internal__n_header_value_te_token_ows: { + if (p == endp) { + return s_n_llhttp__internal__n_header_value_te_token_ows; + } + switch (*p) { + case 9: { + p++; + goto s_n_llhttp__internal__n_header_value_te_token_ows; + } + case ' ': { + p++; + goto s_n_llhttp__internal__n_header_value_te_token_ows; + } + default: { + goto s_n_llhttp__internal__n_header_value_te_chunked; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_header_value: + s_n_llhttp__internal__n_header_value: { + static uint8_t lookup_table[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + }; + if (p == endp) { + return s_n_llhttp__internal__n_header_value; + } + #ifdef __SSE4_2__ + if (endp - p >= 16) { + __m128i ranges; + __m128i input; + int avail; + int match_len; + + /* Load input */ + input = _mm_loadu_si128((__m128i const*) p); + ranges = _mm_loadu_si128((__m128i const*) llparse_blob6); + + /* Find first character that does not match `ranges` */ + match_len = _mm_cmpestri(ranges, 6, + input, 16, + _SIDD_UBYTE_OPS | _SIDD_CMP_RANGES | + _SIDD_NEGATIVE_POLARITY); + + if (match_len != 0) { + p += match_len; + goto s_n_llhttp__internal__n_header_value; + } + goto s_n_llhttp__internal__n_header_value_otherwise; + } + #endif /* __SSE4_2__ */ + switch (lookup_table[(uint8_t) *p]) { + case 1: { + p++; + goto s_n_llhttp__internal__n_header_value; + } + default: { + goto s_n_llhttp__internal__n_header_value_otherwise; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_header_value_te_token: + s_n_llhttp__internal__n_header_value_te_token: { + static uint8_t lookup_table[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + }; + if (p == endp) { + return s_n_llhttp__internal__n_header_value_te_token; + } + switch (lookup_table[(uint8_t) *p]) { + case 1: { + p++; + goto s_n_llhttp__internal__n_header_value_te_token; + } + case 2: { + p++; + goto s_n_llhttp__internal__n_header_value_te_token_ows; + } + default: { + goto s_n_llhttp__internal__n_invoke_update_header_state_9; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_header_value_te_chunked_last: + s_n_llhttp__internal__n_header_value_te_chunked_last: { + if (p == endp) { + return s_n_llhttp__internal__n_header_value_te_chunked_last; + } + switch (*p) { + case 10: { + goto s_n_llhttp__internal__n_invoke_update_header_state_8; + } + case 13: { + goto s_n_llhttp__internal__n_invoke_update_header_state_8; + } + case ' ': { + p++; + goto s_n_llhttp__internal__n_header_value_te_chunked_last; + } + case ',': { + goto s_n_llhttp__internal__n_invoke_load_type_1; + } + default: { + goto s_n_llhttp__internal__n_header_value_te_token; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_header_value_te_chunked: + s_n_llhttp__internal__n_header_value_te_chunked: { + llparse_match_t match_seq; + + if (p == endp) { + return s_n_llhttp__internal__n_header_value_te_chunked; + } + match_seq = llparse__match_sequence_to_lower_unsafe(state, p, endp, llparse_blob5, 7); + p = match_seq.current; + switch (match_seq.status) { + case kMatchComplete: { + p++; + goto s_n_llhttp__internal__n_header_value_te_chunked_last; + } + case kMatchPause: { + return s_n_llhttp__internal__n_header_value_te_chunked; + } + case kMatchMismatch: { + goto s_n_llhttp__internal__n_header_value_te_token; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_span_start_llhttp__on_header_value_1: + s_n_llhttp__internal__n_span_start_llhttp__on_header_value_1: { + if (p == endp) { + return s_n_llhttp__internal__n_span_start_llhttp__on_header_value_1; + } + state->_span_pos0 = (void*) p; + state->_span_cb0 = llhttp__on_header_value; + goto s_n_llhttp__internal__n_invoke_load_header_state_3; + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_header_value_discard_ws: + s_n_llhttp__internal__n_header_value_discard_ws: { + if (p == endp) { + return s_n_llhttp__internal__n_header_value_discard_ws; + } + switch (*p) { + case 9: { + p++; + goto s_n_llhttp__internal__n_header_value_discard_ws; + } + case 10: { + p++; + goto s_n_llhttp__internal__n_invoke_test_lenient_flags_14; + } + case 13: { + p++; + goto s_n_llhttp__internal__n_header_value_discard_ws_almost_done; + } + case ' ': { + p++; + goto s_n_llhttp__internal__n_header_value_discard_ws; + } + default: { + goto s_n_llhttp__internal__n_span_start_llhttp__on_header_value_1; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_invoke_load_header_state: + s_n_llhttp__internal__n_invoke_load_header_state: { + switch (llhttp__internal__c_load_header_state(state, p, endp)) { + case 2: + goto s_n_llhttp__internal__n_invoke_test_flags_4; + case 3: + goto s_n_llhttp__internal__n_invoke_test_flags_5; + default: + goto s_n_llhttp__internal__n_header_value_discard_ws; + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_invoke_llhttp__on_header_field_complete: + s_n_llhttp__internal__n_invoke_llhttp__on_header_field_complete: { + switch (llhttp__on_header_field_complete(state, p, endp)) { + case 0: + goto s_n_llhttp__internal__n_invoke_load_header_state; + case 21: + goto s_n_llhttp__internal__n_pause_19; + default: + goto s_n_llhttp__internal__n_error_44; + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_header_field_general_otherwise: + s_n_llhttp__internal__n_header_field_general_otherwise: { + if (p == endp) { + return s_n_llhttp__internal__n_header_field_general_otherwise; + } + switch (*p) { + case ':': { + goto s_n_llhttp__internal__n_span_end_llhttp__on_header_field_2; + } + default: { + goto s_n_llhttp__internal__n_error_60; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_header_field_general: + s_n_llhttp__internal__n_header_field_general: { + static uint8_t lookup_table[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + if (p == endp) { + return s_n_llhttp__internal__n_header_field_general; + } + #ifdef __SSE4_2__ + if (endp - p >= 16) { + __m128i ranges; + __m128i input; + int avail; + int match_len; + + /* Load input */ + input = _mm_loadu_si128((__m128i const*) p); + ranges = _mm_loadu_si128((__m128i const*) llparse_blob7); + + /* Find first character that does not match `ranges` */ + match_len = _mm_cmpestri(ranges, 16, + input, 16, + _SIDD_UBYTE_OPS | _SIDD_CMP_RANGES | + _SIDD_NEGATIVE_POLARITY); + + if (match_len != 0) { + p += match_len; + goto s_n_llhttp__internal__n_header_field_general; + } + ranges = _mm_loadu_si128((__m128i const*) llparse_blob8); + + /* Find first character that does not match `ranges` */ + match_len = _mm_cmpestri(ranges, 2, + input, 16, + _SIDD_UBYTE_OPS | _SIDD_CMP_RANGES | + _SIDD_NEGATIVE_POLARITY); + + if (match_len != 0) { + p += match_len; + goto s_n_llhttp__internal__n_header_field_general; + } + goto s_n_llhttp__internal__n_header_field_general_otherwise; + } + #endif /* __SSE4_2__ */ + switch (lookup_table[(uint8_t) *p]) { + case 1: { + p++; + goto s_n_llhttp__internal__n_header_field_general; + } + default: { + goto s_n_llhttp__internal__n_header_field_general_otherwise; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_header_field_colon: + s_n_llhttp__internal__n_header_field_colon: { + if (p == endp) { + return s_n_llhttp__internal__n_header_field_colon; + } + switch (*p) { + case ' ': { + goto s_n_llhttp__internal__n_invoke_test_lenient_flags_13; + } + case ':': { + goto s_n_llhttp__internal__n_span_end_llhttp__on_header_field_1; + } + default: { + goto s_n_llhttp__internal__n_invoke_update_header_state_10; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_header_field_3: + s_n_llhttp__internal__n_header_field_3: { + llparse_match_t match_seq; + + if (p == endp) { + return s_n_llhttp__internal__n_header_field_3; + } + match_seq = llparse__match_sequence_to_lower(state, p, endp, llparse_blob1, 6); + p = match_seq.current; + switch (match_seq.status) { + case kMatchComplete: { + p++; + match = 1; + goto s_n_llhttp__internal__n_invoke_store_header_state; + } + case kMatchPause: { + return s_n_llhttp__internal__n_header_field_3; + } + case kMatchMismatch: { + goto s_n_llhttp__internal__n_invoke_update_header_state_11; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_header_field_4: + s_n_llhttp__internal__n_header_field_4: { + llparse_match_t match_seq; + + if (p == endp) { + return s_n_llhttp__internal__n_header_field_4; + } + match_seq = llparse__match_sequence_to_lower(state, p, endp, llparse_blob9, 10); + p = match_seq.current; + switch (match_seq.status) { + case kMatchComplete: { + p++; + match = 2; + goto s_n_llhttp__internal__n_invoke_store_header_state; + } + case kMatchPause: { + return s_n_llhttp__internal__n_header_field_4; + } + case kMatchMismatch: { + goto s_n_llhttp__internal__n_invoke_update_header_state_11; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_header_field_2: + s_n_llhttp__internal__n_header_field_2: { + if (p == endp) { + return s_n_llhttp__internal__n_header_field_2; + } + switch (((*p) >= 'A' && (*p) <= 'Z' ? (*p | 0x20) : (*p))) { + case 'n': { + p++; + goto s_n_llhttp__internal__n_header_field_3; + } + case 't': { + p++; + goto s_n_llhttp__internal__n_header_field_4; + } + default: { + goto s_n_llhttp__internal__n_invoke_update_header_state_11; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_header_field_1: + s_n_llhttp__internal__n_header_field_1: { + llparse_match_t match_seq; + + if (p == endp) { + return s_n_llhttp__internal__n_header_field_1; + } + match_seq = llparse__match_sequence_to_lower(state, p, endp, llparse_blob0, 2); + p = match_seq.current; + switch (match_seq.status) { + case kMatchComplete: { + p++; + goto s_n_llhttp__internal__n_header_field_2; + } + case kMatchPause: { + return s_n_llhttp__internal__n_header_field_1; + } + case kMatchMismatch: { + goto s_n_llhttp__internal__n_invoke_update_header_state_11; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_header_field_5: + s_n_llhttp__internal__n_header_field_5: { + llparse_match_t match_seq; + + if (p == endp) { + return s_n_llhttp__internal__n_header_field_5; + } + match_seq = llparse__match_sequence_to_lower(state, p, endp, llparse_blob10, 15); + p = match_seq.current; + switch (match_seq.status) { + case kMatchComplete: { + p++; + match = 1; + goto s_n_llhttp__internal__n_invoke_store_header_state; + } + case kMatchPause: { + return s_n_llhttp__internal__n_header_field_5; + } + case kMatchMismatch: { + goto s_n_llhttp__internal__n_invoke_update_header_state_11; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_header_field_6: + s_n_llhttp__internal__n_header_field_6: { + llparse_match_t match_seq; + + if (p == endp) { + return s_n_llhttp__internal__n_header_field_6; + } + match_seq = llparse__match_sequence_to_lower(state, p, endp, llparse_blob11, 16); + p = match_seq.current; + switch (match_seq.status) { + case kMatchComplete: { + p++; + match = 3; + goto s_n_llhttp__internal__n_invoke_store_header_state; + } + case kMatchPause: { + return s_n_llhttp__internal__n_header_field_6; + } + case kMatchMismatch: { + goto s_n_llhttp__internal__n_invoke_update_header_state_11; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_header_field_7: + s_n_llhttp__internal__n_header_field_7: { + llparse_match_t match_seq; + + if (p == endp) { + return s_n_llhttp__internal__n_header_field_7; + } + match_seq = llparse__match_sequence_to_lower(state, p, endp, llparse_blob12, 6); + p = match_seq.current; + switch (match_seq.status) { + case kMatchComplete: { + p++; + match = 4; + goto s_n_llhttp__internal__n_invoke_store_header_state; + } + case kMatchPause: { + return s_n_llhttp__internal__n_header_field_7; + } + case kMatchMismatch: { + goto s_n_llhttp__internal__n_invoke_update_header_state_11; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_header_field: + s_n_llhttp__internal__n_header_field: { + if (p == endp) { + return s_n_llhttp__internal__n_header_field; + } + switch (((*p) >= 'A' && (*p) <= 'Z' ? (*p | 0x20) : (*p))) { + case 'c': { + p++; + goto s_n_llhttp__internal__n_header_field_1; + } + case 'p': { + p++; + goto s_n_llhttp__internal__n_header_field_5; + } + case 't': { + p++; + goto s_n_llhttp__internal__n_header_field_6; + } + case 'u': { + p++; + goto s_n_llhttp__internal__n_header_field_7; + } + default: { + goto s_n_llhttp__internal__n_invoke_update_header_state_11; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_span_start_llhttp__on_header_field: + s_n_llhttp__internal__n_span_start_llhttp__on_header_field: { + if (p == endp) { + return s_n_llhttp__internal__n_span_start_llhttp__on_header_field; + } + state->_span_pos0 = (void*) p; + state->_span_cb0 = llhttp__on_header_field; + goto s_n_llhttp__internal__n_header_field; + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_header_field_start: + s_n_llhttp__internal__n_header_field_start: { + if (p == endp) { + return s_n_llhttp__internal__n_header_field_start; + } + switch (*p) { + case 10: { + p++; + goto s_n_llhttp__internal__n_invoke_test_lenient_flags_1; + } + case 13: { + p++; + goto s_n_llhttp__internal__n_headers_almost_done; + } + default: { + goto s_n_llhttp__internal__n_span_start_llhttp__on_header_field; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_headers_start: + s_n_llhttp__internal__n_headers_start: { + if (p == endp) { + return s_n_llhttp__internal__n_headers_start; + } + switch (*p) { + case ' ': { + p++; + goto s_n_llhttp__internal__n_invoke_test_lenient_flags; + } + default: { + goto s_n_llhttp__internal__n_header_field_start; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_url_to_http_09: + s_n_llhttp__internal__n_url_to_http_09: { + if (p == endp) { + return s_n_llhttp__internal__n_url_to_http_09; + } + switch (*p) { + case 9: { + p++; + goto s_n_llhttp__internal__n_error_2; + } + case 12: { + p++; + goto s_n_llhttp__internal__n_error_2; + } + default: { + goto s_n_llhttp__internal__n_invoke_update_http_major; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_url_skip_to_http09: + s_n_llhttp__internal__n_url_skip_to_http09: { + if (p == endp) { + return s_n_llhttp__internal__n_url_skip_to_http09; + } + switch (*p) { + case 9: { + p++; + goto s_n_llhttp__internal__n_error_2; + } + case 12: { + p++; + goto s_n_llhttp__internal__n_error_2; + } + default: { + p++; + goto s_n_llhttp__internal__n_url_to_http_09; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_url_skip_lf_to_http09_1: + s_n_llhttp__internal__n_url_skip_lf_to_http09_1: { + if (p == endp) { + return s_n_llhttp__internal__n_url_skip_lf_to_http09_1; + } + switch (*p) { + case 10: { + p++; + goto s_n_llhttp__internal__n_url_to_http_09; + } + default: { + goto s_n_llhttp__internal__n_error_61; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_url_skip_lf_to_http09: + s_n_llhttp__internal__n_url_skip_lf_to_http09: { + if (p == endp) { + return s_n_llhttp__internal__n_url_skip_lf_to_http09; + } + switch (*p) { + case 9: { + p++; + goto s_n_llhttp__internal__n_error_2; + } + case 12: { + p++; + goto s_n_llhttp__internal__n_error_2; + } + case 13: { + p++; + goto s_n_llhttp__internal__n_url_skip_lf_to_http09_1; + } + default: { + goto s_n_llhttp__internal__n_error_61; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_req_pri_upgrade: + s_n_llhttp__internal__n_req_pri_upgrade: { + llparse_match_t match_seq; + + if (p == endp) { + return s_n_llhttp__internal__n_req_pri_upgrade; + } + match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob14, 10); + p = match_seq.current; + switch (match_seq.status) { + case kMatchComplete: { + p++; + goto s_n_llhttp__internal__n_error_69; + } + case kMatchPause: { + return s_n_llhttp__internal__n_req_pri_upgrade; + } + case kMatchMismatch: { + goto s_n_llhttp__internal__n_error_70; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_req_http_complete_crlf: + s_n_llhttp__internal__n_req_http_complete_crlf: { + if (p == endp) { + return s_n_llhttp__internal__n_req_http_complete_crlf; + } + switch (*p) { + case 10: { + p++; + goto s_n_llhttp__internal__n_headers_start; + } + default: { + goto s_n_llhttp__internal__n_invoke_test_lenient_flags_25; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_req_http_complete: + s_n_llhttp__internal__n_req_http_complete: { + if (p == endp) { + return s_n_llhttp__internal__n_req_http_complete; + } + switch (*p) { + case 10: { + p++; + goto s_n_llhttp__internal__n_invoke_test_lenient_flags_24; + } + case 13: { + p++; + goto s_n_llhttp__internal__n_req_http_complete_crlf; + } + default: { + goto s_n_llhttp__internal__n_error_68; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_invoke_load_method_1: + s_n_llhttp__internal__n_invoke_load_method_1: { + switch (llhttp__internal__c_load_method(state, p, endp)) { + case 34: + goto s_n_llhttp__internal__n_req_pri_upgrade; + default: + goto s_n_llhttp__internal__n_req_http_complete; + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_invoke_llhttp__on_version_complete: + s_n_llhttp__internal__n_invoke_llhttp__on_version_complete: { + switch (llhttp__on_version_complete(state, p, endp)) { + case 0: + goto s_n_llhttp__internal__n_invoke_load_method_1; + case 21: + goto s_n_llhttp__internal__n_pause_21; + default: + goto s_n_llhttp__internal__n_error_65; + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_error_64: + s_n_llhttp__internal__n_error_64: { + state->error = 0x9; + state->reason = "Invalid HTTP version"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_error_71: + s_n_llhttp__internal__n_error_71: { + state->error = 0x9; + state->reason = "Invalid minor version"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_req_http_minor: + s_n_llhttp__internal__n_req_http_minor: { + if (p == endp) { + return s_n_llhttp__internal__n_req_http_minor; + } + switch (*p) { + case '0': { + p++; + match = 0; + goto s_n_llhttp__internal__n_invoke_store_http_minor; + } + case '1': { + p++; + match = 1; + goto s_n_llhttp__internal__n_invoke_store_http_minor; + } + case '2': { + p++; + match = 2; + goto s_n_llhttp__internal__n_invoke_store_http_minor; + } + case '3': { + p++; + match = 3; + goto s_n_llhttp__internal__n_invoke_store_http_minor; + } + case '4': { + p++; + match = 4; + goto s_n_llhttp__internal__n_invoke_store_http_minor; + } + case '5': { + p++; + match = 5; + goto s_n_llhttp__internal__n_invoke_store_http_minor; + } + case '6': { + p++; + match = 6; + goto s_n_llhttp__internal__n_invoke_store_http_minor; + } + case '7': { + p++; + match = 7; + goto s_n_llhttp__internal__n_invoke_store_http_minor; + } + case '8': { + p++; + match = 8; + goto s_n_llhttp__internal__n_invoke_store_http_minor; + } + case '9': { + p++; + match = 9; + goto s_n_llhttp__internal__n_invoke_store_http_minor; + } + default: { + goto s_n_llhttp__internal__n_span_end_llhttp__on_version_2; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_error_72: + s_n_llhttp__internal__n_error_72: { + state->error = 0x9; + state->reason = "Expected dot"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_req_http_dot: + s_n_llhttp__internal__n_req_http_dot: { + if (p == endp) { + return s_n_llhttp__internal__n_req_http_dot; + } + switch (*p) { + case '.': { + p++; + goto s_n_llhttp__internal__n_req_http_minor; + } + default: { + goto s_n_llhttp__internal__n_span_end_llhttp__on_version_3; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_error_73: + s_n_llhttp__internal__n_error_73: { + state->error = 0x9; + state->reason = "Invalid major version"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_req_http_major: + s_n_llhttp__internal__n_req_http_major: { + if (p == endp) { + return s_n_llhttp__internal__n_req_http_major; + } + switch (*p) { + case '0': { + p++; + match = 0; + goto s_n_llhttp__internal__n_invoke_store_http_major; + } + case '1': { + p++; + match = 1; + goto s_n_llhttp__internal__n_invoke_store_http_major; + } + case '2': { + p++; + match = 2; + goto s_n_llhttp__internal__n_invoke_store_http_major; + } + case '3': { + p++; + match = 3; + goto s_n_llhttp__internal__n_invoke_store_http_major; + } + case '4': { + p++; + match = 4; + goto s_n_llhttp__internal__n_invoke_store_http_major; + } + case '5': { + p++; + match = 5; + goto s_n_llhttp__internal__n_invoke_store_http_major; + } + case '6': { + p++; + match = 6; + goto s_n_llhttp__internal__n_invoke_store_http_major; + } + case '7': { + p++; + match = 7; + goto s_n_llhttp__internal__n_invoke_store_http_major; + } + case '8': { + p++; + match = 8; + goto s_n_llhttp__internal__n_invoke_store_http_major; + } + case '9': { + p++; + match = 9; + goto s_n_llhttp__internal__n_invoke_store_http_major; + } + default: { + goto s_n_llhttp__internal__n_span_end_llhttp__on_version_4; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_span_start_llhttp__on_version: + s_n_llhttp__internal__n_span_start_llhttp__on_version: { + if (p == endp) { + return s_n_llhttp__internal__n_span_start_llhttp__on_version; + } + state->_span_pos0 = (void*) p; + state->_span_cb0 = llhttp__on_version; + goto s_n_llhttp__internal__n_req_http_major; + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_req_http_start_1: + s_n_llhttp__internal__n_req_http_start_1: { + llparse_match_t match_seq; + + if (p == endp) { + return s_n_llhttp__internal__n_req_http_start_1; + } + match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob13, 4); + p = match_seq.current; + switch (match_seq.status) { + case kMatchComplete: { + p++; + goto s_n_llhttp__internal__n_invoke_load_method; + } + case kMatchPause: { + return s_n_llhttp__internal__n_req_http_start_1; + } + case kMatchMismatch: { + goto s_n_llhttp__internal__n_error_76; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_req_http_start_2: + s_n_llhttp__internal__n_req_http_start_2: { + llparse_match_t match_seq; + + if (p == endp) { + return s_n_llhttp__internal__n_req_http_start_2; + } + match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob15, 3); + p = match_seq.current; + switch (match_seq.status) { + case kMatchComplete: { + p++; + goto s_n_llhttp__internal__n_invoke_load_method_2; + } + case kMatchPause: { + return s_n_llhttp__internal__n_req_http_start_2; + } + case kMatchMismatch: { + goto s_n_llhttp__internal__n_error_76; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_req_http_start_3: + s_n_llhttp__internal__n_req_http_start_3: { + llparse_match_t match_seq; + + if (p == endp) { + return s_n_llhttp__internal__n_req_http_start_3; + } + match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob16, 4); + p = match_seq.current; + switch (match_seq.status) { + case kMatchComplete: { + p++; + goto s_n_llhttp__internal__n_invoke_load_method_3; + } + case kMatchPause: { + return s_n_llhttp__internal__n_req_http_start_3; + } + case kMatchMismatch: { + goto s_n_llhttp__internal__n_error_76; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_req_http_start: + s_n_llhttp__internal__n_req_http_start: { + if (p == endp) { + return s_n_llhttp__internal__n_req_http_start; + } + switch (*p) { + case ' ': { + p++; + goto s_n_llhttp__internal__n_req_http_start; + } + case 'H': { + p++; + goto s_n_llhttp__internal__n_req_http_start_1; + } + case 'I': { + p++; + goto s_n_llhttp__internal__n_req_http_start_2; + } + case 'R': { + p++; + goto s_n_llhttp__internal__n_req_http_start_3; + } + default: { + goto s_n_llhttp__internal__n_error_76; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_url_to_http: + s_n_llhttp__internal__n_url_to_http: { + if (p == endp) { + return s_n_llhttp__internal__n_url_to_http; + } + switch (*p) { + case 9: { + p++; + goto s_n_llhttp__internal__n_error_2; + } + case 12: { + p++; + goto s_n_llhttp__internal__n_error_2; + } + default: { + goto s_n_llhttp__internal__n_invoke_llhttp__on_url_complete_1; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_url_skip_to_http: + s_n_llhttp__internal__n_url_skip_to_http: { + if (p == endp) { + return s_n_llhttp__internal__n_url_skip_to_http; + } + switch (*p) { + case 9: { + p++; + goto s_n_llhttp__internal__n_error_2; + } + case 12: { + p++; + goto s_n_llhttp__internal__n_error_2; + } + default: { + p++; + goto s_n_llhttp__internal__n_url_to_http; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_url_fragment: + s_n_llhttp__internal__n_url_fragment: { + static uint8_t lookup_table[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 1, 3, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + if (p == endp) { + return s_n_llhttp__internal__n_url_fragment; + } + switch (lookup_table[(uint8_t) *p]) { + case 1: { + p++; + goto s_n_llhttp__internal__n_error_2; + } + case 2: { + goto s_n_llhttp__internal__n_span_end_llhttp__on_url_6; + } + case 3: { + goto s_n_llhttp__internal__n_span_end_llhttp__on_url_7; + } + case 4: { + goto s_n_llhttp__internal__n_span_end_llhttp__on_url_8; + } + case 5: { + p++; + goto s_n_llhttp__internal__n_url_fragment; + } + default: { + goto s_n_llhttp__internal__n_error_77; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_span_end_stub_query_3: + s_n_llhttp__internal__n_span_end_stub_query_3: { + if (p == endp) { + return s_n_llhttp__internal__n_span_end_stub_query_3; + } + p++; + goto s_n_llhttp__internal__n_url_fragment; + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_url_query: + s_n_llhttp__internal__n_url_query: { + static uint8_t lookup_table[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 1, 3, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 5, 5, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + if (p == endp) { + return s_n_llhttp__internal__n_url_query; + } + switch (lookup_table[(uint8_t) *p]) { + case 1: { + p++; + goto s_n_llhttp__internal__n_error_2; + } + case 2: { + goto s_n_llhttp__internal__n_span_end_llhttp__on_url_9; + } + case 3: { + goto s_n_llhttp__internal__n_span_end_llhttp__on_url_10; + } + case 4: { + goto s_n_llhttp__internal__n_span_end_llhttp__on_url_11; + } + case 5: { + p++; + goto s_n_llhttp__internal__n_url_query; + } + case 6: { + goto s_n_llhttp__internal__n_span_end_stub_query_3; + } + default: { + goto s_n_llhttp__internal__n_error_78; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_url_query_or_fragment: + s_n_llhttp__internal__n_url_query_or_fragment: { + if (p == endp) { + return s_n_llhttp__internal__n_url_query_or_fragment; + } + switch (*p) { + case 9: { + p++; + goto s_n_llhttp__internal__n_error_2; + } + case 10: { + goto s_n_llhttp__internal__n_span_end_llhttp__on_url_3; + } + case 12: { + p++; + goto s_n_llhttp__internal__n_error_2; + } + case 13: { + goto s_n_llhttp__internal__n_span_end_llhttp__on_url_4; + } + case ' ': { + goto s_n_llhttp__internal__n_span_end_llhttp__on_url_5; + } + case '#': { + p++; + goto s_n_llhttp__internal__n_url_fragment; + } + case '?': { + p++; + goto s_n_llhttp__internal__n_url_query; + } + default: { + goto s_n_llhttp__internal__n_error_79; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_url_path: + s_n_llhttp__internal__n_url_path: { + static uint8_t lookup_table[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + if (p == endp) { + return s_n_llhttp__internal__n_url_path; + } + switch (lookup_table[(uint8_t) *p]) { + case 1: { + p++; + goto s_n_llhttp__internal__n_error_2; + } + case 2: { + p++; + goto s_n_llhttp__internal__n_url_path; + } + default: { + goto s_n_llhttp__internal__n_url_query_or_fragment; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_span_start_stub_path_2: + s_n_llhttp__internal__n_span_start_stub_path_2: { + if (p == endp) { + return s_n_llhttp__internal__n_span_start_stub_path_2; + } + p++; + goto s_n_llhttp__internal__n_url_path; + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_span_start_stub_path: + s_n_llhttp__internal__n_span_start_stub_path: { + if (p == endp) { + return s_n_llhttp__internal__n_span_start_stub_path; + } + p++; + goto s_n_llhttp__internal__n_url_path; + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_span_start_stub_path_1: + s_n_llhttp__internal__n_span_start_stub_path_1: { + if (p == endp) { + return s_n_llhttp__internal__n_span_start_stub_path_1; + } + p++; + goto s_n_llhttp__internal__n_url_path; + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_url_server_with_at: + s_n_llhttp__internal__n_url_server_with_at: { + static uint8_t lookup_table[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 1, 3, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 5, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 5, 0, 7, + 8, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 5, 0, 5, + 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 5, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + if (p == endp) { + return s_n_llhttp__internal__n_url_server_with_at; + } + switch (lookup_table[(uint8_t) *p]) { + case 1: { + p++; + goto s_n_llhttp__internal__n_error_2; + } + case 2: { + goto s_n_llhttp__internal__n_span_end_llhttp__on_url_12; + } + case 3: { + goto s_n_llhttp__internal__n_span_end_llhttp__on_url_13; + } + case 4: { + goto s_n_llhttp__internal__n_span_end_llhttp__on_url_14; + } + case 5: { + p++; + goto s_n_llhttp__internal__n_url_server; + } + case 6: { + goto s_n_llhttp__internal__n_span_start_stub_path_1; + } + case 7: { + p++; + goto s_n_llhttp__internal__n_url_query; + } + case 8: { + p++; + goto s_n_llhttp__internal__n_error_80; + } + default: { + goto s_n_llhttp__internal__n_error_81; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_url_server: + s_n_llhttp__internal__n_url_server: { + static uint8_t lookup_table[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 1, 3, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 5, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 5, 0, 7, + 8, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 5, 0, 5, + 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 5, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + if (p == endp) { + return s_n_llhttp__internal__n_url_server; + } + switch (lookup_table[(uint8_t) *p]) { + case 1: { + p++; + goto s_n_llhttp__internal__n_error_2; + } + case 2: { + goto s_n_llhttp__internal__n_span_end_llhttp__on_url; + } + case 3: { + goto s_n_llhttp__internal__n_span_end_llhttp__on_url_1; + } + case 4: { + goto s_n_llhttp__internal__n_span_end_llhttp__on_url_2; + } + case 5: { + p++; + goto s_n_llhttp__internal__n_url_server; + } + case 6: { + goto s_n_llhttp__internal__n_span_start_stub_path; + } + case 7: { + p++; + goto s_n_llhttp__internal__n_url_query; + } + case 8: { + p++; + goto s_n_llhttp__internal__n_url_server_with_at; + } + default: { + goto s_n_llhttp__internal__n_error_82; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_url_schema_delim_1: + s_n_llhttp__internal__n_url_schema_delim_1: { + if (p == endp) { + return s_n_llhttp__internal__n_url_schema_delim_1; + } + switch (*p) { + case '/': { + p++; + goto s_n_llhttp__internal__n_url_server; + } + default: { + goto s_n_llhttp__internal__n_error_83; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_url_schema_delim: + s_n_llhttp__internal__n_url_schema_delim: { + if (p == endp) { + return s_n_llhttp__internal__n_url_schema_delim; + } + switch (*p) { + case 9: { + p++; + goto s_n_llhttp__internal__n_error_2; + } + case 10: { + p++; + goto s_n_llhttp__internal__n_error_2; + } + case 12: { + p++; + goto s_n_llhttp__internal__n_error_2; + } + case 13: { + p++; + goto s_n_llhttp__internal__n_error_2; + } + case ' ': { + p++; + goto s_n_llhttp__internal__n_error_2; + } + case '/': { + p++; + goto s_n_llhttp__internal__n_url_schema_delim_1; + } + default: { + goto s_n_llhttp__internal__n_error_83; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_span_end_stub_schema: + s_n_llhttp__internal__n_span_end_stub_schema: { + if (p == endp) { + return s_n_llhttp__internal__n_span_end_stub_schema; + } + p++; + goto s_n_llhttp__internal__n_url_schema_delim; + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_url_schema: + s_n_llhttp__internal__n_url_schema: { + static uint8_t lookup_table[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, + 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, + 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + if (p == endp) { + return s_n_llhttp__internal__n_url_schema; + } + switch (lookup_table[(uint8_t) *p]) { + case 1: { + p++; + goto s_n_llhttp__internal__n_error_2; + } + case 2: { + goto s_n_llhttp__internal__n_span_end_stub_schema; + } + case 3: { + p++; + goto s_n_llhttp__internal__n_url_schema; + } + default: { + goto s_n_llhttp__internal__n_error_84; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_url_start: + s_n_llhttp__internal__n_url_start: { + static uint8_t lookup_table[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, + 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + if (p == endp) { + return s_n_llhttp__internal__n_url_start; + } + switch (lookup_table[(uint8_t) *p]) { + case 1: { + p++; + goto s_n_llhttp__internal__n_error_2; + } + case 2: { + goto s_n_llhttp__internal__n_span_start_stub_path_2; + } + case 3: { + goto s_n_llhttp__internal__n_url_schema; + } + default: { + goto s_n_llhttp__internal__n_error_85; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_span_start_llhttp__on_url_1: + s_n_llhttp__internal__n_span_start_llhttp__on_url_1: { + if (p == endp) { + return s_n_llhttp__internal__n_span_start_llhttp__on_url_1; + } + state->_span_pos0 = (void*) p; + state->_span_cb0 = llhttp__on_url; + goto s_n_llhttp__internal__n_url_start; + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_url_entry_normal: + s_n_llhttp__internal__n_url_entry_normal: { + if (p == endp) { + return s_n_llhttp__internal__n_url_entry_normal; + } + switch (*p) { + case 9: { + p++; + goto s_n_llhttp__internal__n_error_2; + } + case 12: { + p++; + goto s_n_llhttp__internal__n_error_2; + } + default: { + goto s_n_llhttp__internal__n_span_start_llhttp__on_url_1; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_span_start_llhttp__on_url: + s_n_llhttp__internal__n_span_start_llhttp__on_url: { + if (p == endp) { + return s_n_llhttp__internal__n_span_start_llhttp__on_url; + } + state->_span_pos0 = (void*) p; + state->_span_cb0 = llhttp__on_url; + goto s_n_llhttp__internal__n_url_server; + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_url_entry_connect: + s_n_llhttp__internal__n_url_entry_connect: { + if (p == endp) { + return s_n_llhttp__internal__n_url_entry_connect; + } + switch (*p) { + case 9: { + p++; + goto s_n_llhttp__internal__n_error_2; + } + case 12: { + p++; + goto s_n_llhttp__internal__n_error_2; + } + default: { + goto s_n_llhttp__internal__n_span_start_llhttp__on_url; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_req_spaces_before_url: + s_n_llhttp__internal__n_req_spaces_before_url: { + if (p == endp) { + return s_n_llhttp__internal__n_req_spaces_before_url; + } + switch (*p) { + case ' ': { + p++; + goto s_n_llhttp__internal__n_req_spaces_before_url; + } + default: { + goto s_n_llhttp__internal__n_invoke_is_equal_method; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_req_first_space_before_url: + s_n_llhttp__internal__n_req_first_space_before_url: { + if (p == endp) { + return s_n_llhttp__internal__n_req_first_space_before_url; + } + switch (*p) { + case ' ': { + p++; + goto s_n_llhttp__internal__n_req_spaces_before_url; + } + default: { + goto s_n_llhttp__internal__n_error_86; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_invoke_llhttp__on_method_complete_1: + s_n_llhttp__internal__n_invoke_llhttp__on_method_complete_1: { + switch (llhttp__on_method_complete(state, p, endp)) { + case 0: + goto s_n_llhttp__internal__n_req_first_space_before_url; + case 21: + goto s_n_llhttp__internal__n_pause_26; + default: + goto s_n_llhttp__internal__n_error_105; + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_2: + s_n_llhttp__internal__n_after_start_req_2: { + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_2; + } + switch (*p) { + case 'L': { + p++; + match = 19; + goto s_n_llhttp__internal__n_invoke_store_method_1; + } + default: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_3: + s_n_llhttp__internal__n_after_start_req_3: { + llparse_match_t match_seq; + + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_3; + } + match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob17, 6); + p = match_seq.current; + switch (match_seq.status) { + case kMatchComplete: { + p++; + match = 36; + goto s_n_llhttp__internal__n_invoke_store_method_1; + } + case kMatchPause: { + return s_n_llhttp__internal__n_after_start_req_3; + } + case kMatchMismatch: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_1: + s_n_llhttp__internal__n_after_start_req_1: { + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_1; + } + switch (*p) { + case 'C': { + p++; + goto s_n_llhttp__internal__n_after_start_req_2; + } + case 'N': { + p++; + goto s_n_llhttp__internal__n_after_start_req_3; + } + default: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_4: + s_n_llhttp__internal__n_after_start_req_4: { + llparse_match_t match_seq; + + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_4; + } + match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob18, 3); + p = match_seq.current; + switch (match_seq.status) { + case kMatchComplete: { + p++; + match = 16; + goto s_n_llhttp__internal__n_invoke_store_method_1; + } + case kMatchPause: { + return s_n_llhttp__internal__n_after_start_req_4; + } + case kMatchMismatch: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_6: + s_n_llhttp__internal__n_after_start_req_6: { + llparse_match_t match_seq; + + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_6; + } + match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob19, 6); + p = match_seq.current; + switch (match_seq.status) { + case kMatchComplete: { + p++; + match = 22; + goto s_n_llhttp__internal__n_invoke_store_method_1; + } + case kMatchPause: { + return s_n_llhttp__internal__n_after_start_req_6; + } + case kMatchMismatch: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_8: + s_n_llhttp__internal__n_after_start_req_8: { + llparse_match_t match_seq; + + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_8; + } + match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob20, 4); + p = match_seq.current; + switch (match_seq.status) { + case kMatchComplete: { + p++; + match = 5; + goto s_n_llhttp__internal__n_invoke_store_method_1; + } + case kMatchPause: { + return s_n_llhttp__internal__n_after_start_req_8; + } + case kMatchMismatch: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_9: + s_n_llhttp__internal__n_after_start_req_9: { + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_9; + } + switch (*p) { + case 'Y': { + p++; + match = 8; + goto s_n_llhttp__internal__n_invoke_store_method_1; + } + default: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_7: + s_n_llhttp__internal__n_after_start_req_7: { + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_7; + } + switch (*p) { + case 'N': { + p++; + goto s_n_llhttp__internal__n_after_start_req_8; + } + case 'P': { + p++; + goto s_n_llhttp__internal__n_after_start_req_9; + } + default: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_5: + s_n_llhttp__internal__n_after_start_req_5: { + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_5; + } + switch (*p) { + case 'H': { + p++; + goto s_n_llhttp__internal__n_after_start_req_6; + } + case 'O': { + p++; + goto s_n_llhttp__internal__n_after_start_req_7; + } + default: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_12: + s_n_llhttp__internal__n_after_start_req_12: { + llparse_match_t match_seq; + + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_12; + } + match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob21, 3); + p = match_seq.current; + switch (match_seq.status) { + case kMatchComplete: { + p++; + match = 0; + goto s_n_llhttp__internal__n_invoke_store_method_1; + } + case kMatchPause: { + return s_n_llhttp__internal__n_after_start_req_12; + } + case kMatchMismatch: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_13: + s_n_llhttp__internal__n_after_start_req_13: { + llparse_match_t match_seq; + + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_13; + } + match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob22, 5); + p = match_seq.current; + switch (match_seq.status) { + case kMatchComplete: { + p++; + match = 35; + goto s_n_llhttp__internal__n_invoke_store_method_1; + } + case kMatchPause: { + return s_n_llhttp__internal__n_after_start_req_13; + } + case kMatchMismatch: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_11: + s_n_llhttp__internal__n_after_start_req_11: { + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_11; + } + switch (*p) { + case 'L': { + p++; + goto s_n_llhttp__internal__n_after_start_req_12; + } + case 'S': { + p++; + goto s_n_llhttp__internal__n_after_start_req_13; + } + default: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_10: + s_n_llhttp__internal__n_after_start_req_10: { + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_10; + } + switch (*p) { + case 'E': { + p++; + goto s_n_llhttp__internal__n_after_start_req_11; + } + default: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_14: + s_n_llhttp__internal__n_after_start_req_14: { + llparse_match_t match_seq; + + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_14; + } + match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob23, 4); + p = match_seq.current; + switch (match_seq.status) { + case kMatchComplete: { + p++; + match = 45; + goto s_n_llhttp__internal__n_invoke_store_method_1; + } + case kMatchPause: { + return s_n_llhttp__internal__n_after_start_req_14; + } + case kMatchMismatch: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_17: + s_n_llhttp__internal__n_after_start_req_17: { + llparse_match_t match_seq; + + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_17; + } + match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob25, 9); + p = match_seq.current; + switch (match_seq.status) { + case kMatchComplete: { + p++; + match = 41; + goto s_n_llhttp__internal__n_invoke_store_method_1; + } + case kMatchPause: { + return s_n_llhttp__internal__n_after_start_req_17; + } + case kMatchMismatch: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_16: + s_n_llhttp__internal__n_after_start_req_16: { + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_16; + } + switch (*p) { + case '_': { + p++; + goto s_n_llhttp__internal__n_after_start_req_17; + } + default: { + match = 1; + goto s_n_llhttp__internal__n_invoke_store_method_1; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_15: + s_n_llhttp__internal__n_after_start_req_15: { + llparse_match_t match_seq; + + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_15; + } + match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob24, 2); + p = match_seq.current; + switch (match_seq.status) { + case kMatchComplete: { + p++; + goto s_n_llhttp__internal__n_after_start_req_16; + } + case kMatchPause: { + return s_n_llhttp__internal__n_after_start_req_15; + } + case kMatchMismatch: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_18: + s_n_llhttp__internal__n_after_start_req_18: { + llparse_match_t match_seq; + + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_18; + } + match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob26, 3); + p = match_seq.current; + switch (match_seq.status) { + case kMatchComplete: { + p++; + match = 2; + goto s_n_llhttp__internal__n_invoke_store_method_1; + } + case kMatchPause: { + return s_n_llhttp__internal__n_after_start_req_18; + } + case kMatchMismatch: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_20: + s_n_llhttp__internal__n_after_start_req_20: { + llparse_match_t match_seq; + + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_20; + } + match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob27, 2); + p = match_seq.current; + switch (match_seq.status) { + case kMatchComplete: { + p++; + match = 31; + goto s_n_llhttp__internal__n_invoke_store_method_1; + } + case kMatchPause: { + return s_n_llhttp__internal__n_after_start_req_20; + } + case kMatchMismatch: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_21: + s_n_llhttp__internal__n_after_start_req_21: { + llparse_match_t match_seq; + + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_21; + } + match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob28, 2); + p = match_seq.current; + switch (match_seq.status) { + case kMatchComplete: { + p++; + match = 9; + goto s_n_llhttp__internal__n_invoke_store_method_1; + } + case kMatchPause: { + return s_n_llhttp__internal__n_after_start_req_21; + } + case kMatchMismatch: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_19: + s_n_llhttp__internal__n_after_start_req_19: { + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_19; + } + switch (*p) { + case 'I': { + p++; + goto s_n_llhttp__internal__n_after_start_req_20; + } + case 'O': { + p++; + goto s_n_llhttp__internal__n_after_start_req_21; + } + default: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_23: + s_n_llhttp__internal__n_after_start_req_23: { + llparse_match_t match_seq; + + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_23; + } + match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob29, 6); + p = match_seq.current; + switch (match_seq.status) { + case kMatchComplete: { + p++; + match = 24; + goto s_n_llhttp__internal__n_invoke_store_method_1; + } + case kMatchPause: { + return s_n_llhttp__internal__n_after_start_req_23; + } + case kMatchMismatch: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_24: + s_n_llhttp__internal__n_after_start_req_24: { + llparse_match_t match_seq; + + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_24; + } + match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob30, 3); + p = match_seq.current; + switch (match_seq.status) { + case kMatchComplete: { + p++; + match = 23; + goto s_n_llhttp__internal__n_invoke_store_method_1; + } + case kMatchPause: { + return s_n_llhttp__internal__n_after_start_req_24; + } + case kMatchMismatch: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_26: + s_n_llhttp__internal__n_after_start_req_26: { + llparse_match_t match_seq; + + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_26; + } + match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob31, 7); + p = match_seq.current; + switch (match_seq.status) { + case kMatchComplete: { + p++; + match = 21; + goto s_n_llhttp__internal__n_invoke_store_method_1; + } + case kMatchPause: { + return s_n_llhttp__internal__n_after_start_req_26; + } + case kMatchMismatch: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_28: + s_n_llhttp__internal__n_after_start_req_28: { + llparse_match_t match_seq; + + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_28; + } + match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob32, 6); + p = match_seq.current; + switch (match_seq.status) { + case kMatchComplete: { + p++; + match = 30; + goto s_n_llhttp__internal__n_invoke_store_method_1; + } + case kMatchPause: { + return s_n_llhttp__internal__n_after_start_req_28; + } + case kMatchMismatch: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_29: + s_n_llhttp__internal__n_after_start_req_29: { + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_29; + } + switch (*p) { + case 'L': { + p++; + match = 10; + goto s_n_llhttp__internal__n_invoke_store_method_1; + } + default: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_27: + s_n_llhttp__internal__n_after_start_req_27: { + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_27; + } + switch (*p) { + case 'A': { + p++; + goto s_n_llhttp__internal__n_after_start_req_28; + } + case 'O': { + p++; + goto s_n_llhttp__internal__n_after_start_req_29; + } + default: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_25: + s_n_llhttp__internal__n_after_start_req_25: { + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_25; + } + switch (*p) { + case 'A': { + p++; + goto s_n_llhttp__internal__n_after_start_req_26; + } + case 'C': { + p++; + goto s_n_llhttp__internal__n_after_start_req_27; + } + default: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_30: + s_n_llhttp__internal__n_after_start_req_30: { + llparse_match_t match_seq; + + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_30; + } + match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob33, 2); + p = match_seq.current; + switch (match_seq.status) { + case kMatchComplete: { + p++; + match = 11; + goto s_n_llhttp__internal__n_invoke_store_method_1; + } + case kMatchPause: { + return s_n_llhttp__internal__n_after_start_req_30; + } + case kMatchMismatch: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_22: + s_n_llhttp__internal__n_after_start_req_22: { + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_22; + } + switch (*p) { + case '-': { + p++; + goto s_n_llhttp__internal__n_after_start_req_23; + } + case 'E': { + p++; + goto s_n_llhttp__internal__n_after_start_req_24; + } + case 'K': { + p++; + goto s_n_llhttp__internal__n_after_start_req_25; + } + case 'O': { + p++; + goto s_n_llhttp__internal__n_after_start_req_30; + } + default: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_31: + s_n_llhttp__internal__n_after_start_req_31: { + llparse_match_t match_seq; + + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_31; + } + match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob34, 5); + p = match_seq.current; + switch (match_seq.status) { + case kMatchComplete: { + p++; + match = 25; + goto s_n_llhttp__internal__n_invoke_store_method_1; + } + case kMatchPause: { + return s_n_llhttp__internal__n_after_start_req_31; + } + case kMatchMismatch: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_32: + s_n_llhttp__internal__n_after_start_req_32: { + llparse_match_t match_seq; + + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_32; + } + match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob35, 6); + p = match_seq.current; + switch (match_seq.status) { + case kMatchComplete: { + p++; + match = 6; + goto s_n_llhttp__internal__n_invoke_store_method_1; + } + case kMatchPause: { + return s_n_llhttp__internal__n_after_start_req_32; + } + case kMatchMismatch: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_35: + s_n_llhttp__internal__n_after_start_req_35: { + llparse_match_t match_seq; + + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_35; + } + match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob36, 2); + p = match_seq.current; + switch (match_seq.status) { + case kMatchComplete: { + p++; + match = 28; + goto s_n_llhttp__internal__n_invoke_store_method_1; + } + case kMatchPause: { + return s_n_llhttp__internal__n_after_start_req_35; + } + case kMatchMismatch: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_36: + s_n_llhttp__internal__n_after_start_req_36: { + llparse_match_t match_seq; + + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_36; + } + match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob37, 2); + p = match_seq.current; + switch (match_seq.status) { + case kMatchComplete: { + p++; + match = 39; + goto s_n_llhttp__internal__n_invoke_store_method_1; + } + case kMatchPause: { + return s_n_llhttp__internal__n_after_start_req_36; + } + case kMatchMismatch: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_34: + s_n_llhttp__internal__n_after_start_req_34: { + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_34; + } + switch (*p) { + case 'T': { + p++; + goto s_n_llhttp__internal__n_after_start_req_35; + } + case 'U': { + p++; + goto s_n_llhttp__internal__n_after_start_req_36; + } + default: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_37: + s_n_llhttp__internal__n_after_start_req_37: { + llparse_match_t match_seq; + + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_37; + } + match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob38, 2); + p = match_seq.current; + switch (match_seq.status) { + case kMatchComplete: { + p++; + match = 38; + goto s_n_llhttp__internal__n_invoke_store_method_1; + } + case kMatchPause: { + return s_n_llhttp__internal__n_after_start_req_37; + } + case kMatchMismatch: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_38: + s_n_llhttp__internal__n_after_start_req_38: { + llparse_match_t match_seq; + + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_38; + } + match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob39, 2); + p = match_seq.current; + switch (match_seq.status) { + case kMatchComplete: { + p++; + match = 3; + goto s_n_llhttp__internal__n_invoke_store_method_1; + } + case kMatchPause: { + return s_n_llhttp__internal__n_after_start_req_38; + } + case kMatchMismatch: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_42: + s_n_llhttp__internal__n_after_start_req_42: { + llparse_match_t match_seq; + + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_42; + } + match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob40, 3); + p = match_seq.current; + switch (match_seq.status) { + case kMatchComplete: { + p++; + match = 12; + goto s_n_llhttp__internal__n_invoke_store_method_1; + } + case kMatchPause: { + return s_n_llhttp__internal__n_after_start_req_42; + } + case kMatchMismatch: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_43: + s_n_llhttp__internal__n_after_start_req_43: { + llparse_match_t match_seq; + + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_43; + } + match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob41, 4); + p = match_seq.current; + switch (match_seq.status) { + case kMatchComplete: { + p++; + match = 13; + goto s_n_llhttp__internal__n_invoke_store_method_1; + } + case kMatchPause: { + return s_n_llhttp__internal__n_after_start_req_43; + } + case kMatchMismatch: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_41: + s_n_llhttp__internal__n_after_start_req_41: { + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_41; + } + switch (*p) { + case 'F': { + p++; + goto s_n_llhttp__internal__n_after_start_req_42; + } + case 'P': { + p++; + goto s_n_llhttp__internal__n_after_start_req_43; + } + default: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_40: + s_n_llhttp__internal__n_after_start_req_40: { + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_40; + } + switch (*p) { + case 'P': { + p++; + goto s_n_llhttp__internal__n_after_start_req_41; + } + default: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_39: + s_n_llhttp__internal__n_after_start_req_39: { + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_39; + } + switch (*p) { + case 'I': { + p++; + match = 34; + goto s_n_llhttp__internal__n_invoke_store_method_1; + } + case 'O': { + p++; + goto s_n_llhttp__internal__n_after_start_req_40; + } + default: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_45: + s_n_llhttp__internal__n_after_start_req_45: { + llparse_match_t match_seq; + + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_45; + } + match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob42, 2); + p = match_seq.current; + switch (match_seq.status) { + case kMatchComplete: { + p++; + match = 29; + goto s_n_llhttp__internal__n_invoke_store_method_1; + } + case kMatchPause: { + return s_n_llhttp__internal__n_after_start_req_45; + } + case kMatchMismatch: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_44: + s_n_llhttp__internal__n_after_start_req_44: { + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_44; + } + switch (*p) { + case 'R': { + p++; + goto s_n_llhttp__internal__n_after_start_req_45; + } + case 'T': { + p++; + match = 4; + goto s_n_llhttp__internal__n_invoke_store_method_1; + } + default: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_33: + s_n_llhttp__internal__n_after_start_req_33: { + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_33; + } + switch (*p) { + case 'A': { + p++; + goto s_n_llhttp__internal__n_after_start_req_34; + } + case 'L': { + p++; + goto s_n_llhttp__internal__n_after_start_req_37; + } + case 'O': { + p++; + goto s_n_llhttp__internal__n_after_start_req_38; + } + case 'R': { + p++; + goto s_n_llhttp__internal__n_after_start_req_39; + } + case 'U': { + p++; + goto s_n_llhttp__internal__n_after_start_req_44; + } + default: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_48: + s_n_llhttp__internal__n_after_start_req_48: { + llparse_match_t match_seq; + + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_48; + } + match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob43, 3); + p = match_seq.current; + switch (match_seq.status) { + case kMatchComplete: { + p++; + match = 17; + goto s_n_llhttp__internal__n_invoke_store_method_1; + } + case kMatchPause: { + return s_n_llhttp__internal__n_after_start_req_48; + } + case kMatchMismatch: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_49: + s_n_llhttp__internal__n_after_start_req_49: { + llparse_match_t match_seq; + + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_49; + } + match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob44, 3); + p = match_seq.current; + switch (match_seq.status) { + case kMatchComplete: { + p++; + match = 44; + goto s_n_llhttp__internal__n_invoke_store_method_1; + } + case kMatchPause: { + return s_n_llhttp__internal__n_after_start_req_49; + } + case kMatchMismatch: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_50: + s_n_llhttp__internal__n_after_start_req_50: { + llparse_match_t match_seq; + + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_50; + } + match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob45, 5); + p = match_seq.current; + switch (match_seq.status) { + case kMatchComplete: { + p++; + match = 43; + goto s_n_llhttp__internal__n_invoke_store_method_1; + } + case kMatchPause: { + return s_n_llhttp__internal__n_after_start_req_50; + } + case kMatchMismatch: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_51: + s_n_llhttp__internal__n_after_start_req_51: { + llparse_match_t match_seq; + + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_51; + } + match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob46, 3); + p = match_seq.current; + switch (match_seq.status) { + case kMatchComplete: { + p++; + match = 20; + goto s_n_llhttp__internal__n_invoke_store_method_1; + } + case kMatchPause: { + return s_n_llhttp__internal__n_after_start_req_51; + } + case kMatchMismatch: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_47: + s_n_llhttp__internal__n_after_start_req_47: { + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_47; + } + switch (*p) { + case 'B': { + p++; + goto s_n_llhttp__internal__n_after_start_req_48; + } + case 'C': { + p++; + goto s_n_llhttp__internal__n_after_start_req_49; + } + case 'D': { + p++; + goto s_n_llhttp__internal__n_after_start_req_50; + } + case 'P': { + p++; + goto s_n_llhttp__internal__n_after_start_req_51; + } + default: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_46: + s_n_llhttp__internal__n_after_start_req_46: { + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_46; + } + switch (*p) { + case 'E': { + p++; + goto s_n_llhttp__internal__n_after_start_req_47; + } + default: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_54: + s_n_llhttp__internal__n_after_start_req_54: { + llparse_match_t match_seq; + + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_54; + } + match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob47, 3); + p = match_seq.current; + switch (match_seq.status) { + case kMatchComplete: { + p++; + match = 14; + goto s_n_llhttp__internal__n_invoke_store_method_1; + } + case kMatchPause: { + return s_n_llhttp__internal__n_after_start_req_54; + } + case kMatchMismatch: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_56: + s_n_llhttp__internal__n_after_start_req_56: { + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_56; + } + switch (*p) { + case 'P': { + p++; + match = 37; + goto s_n_llhttp__internal__n_invoke_store_method_1; + } + default: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_57: + s_n_llhttp__internal__n_after_start_req_57: { + llparse_match_t match_seq; + + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_57; + } + match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob48, 9); + p = match_seq.current; + switch (match_seq.status) { + case kMatchComplete: { + p++; + match = 42; + goto s_n_llhttp__internal__n_invoke_store_method_1; + } + case kMatchPause: { + return s_n_llhttp__internal__n_after_start_req_57; + } + case kMatchMismatch: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_55: + s_n_llhttp__internal__n_after_start_req_55: { + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_55; + } + switch (*p) { + case 'U': { + p++; + goto s_n_llhttp__internal__n_after_start_req_56; + } + case '_': { + p++; + goto s_n_llhttp__internal__n_after_start_req_57; + } + default: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_53: + s_n_llhttp__internal__n_after_start_req_53: { + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_53; + } + switch (*p) { + case 'A': { + p++; + goto s_n_llhttp__internal__n_after_start_req_54; + } + case 'T': { + p++; + goto s_n_llhttp__internal__n_after_start_req_55; + } + default: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_58: + s_n_llhttp__internal__n_after_start_req_58: { + llparse_match_t match_seq; + + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_58; + } + match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob49, 4); + p = match_seq.current; + switch (match_seq.status) { + case kMatchComplete: { + p++; + match = 33; + goto s_n_llhttp__internal__n_invoke_store_method_1; + } + case kMatchPause: { + return s_n_llhttp__internal__n_after_start_req_58; + } + case kMatchMismatch: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_59: + s_n_llhttp__internal__n_after_start_req_59: { + llparse_match_t match_seq; + + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_59; + } + match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob50, 7); + p = match_seq.current; + switch (match_seq.status) { + case kMatchComplete: { + p++; + match = 26; + goto s_n_llhttp__internal__n_invoke_store_method_1; + } + case kMatchPause: { + return s_n_llhttp__internal__n_after_start_req_59; + } + case kMatchMismatch: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_52: + s_n_llhttp__internal__n_after_start_req_52: { + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_52; + } + switch (*p) { + case 'E': { + p++; + goto s_n_llhttp__internal__n_after_start_req_53; + } + case 'O': { + p++; + goto s_n_llhttp__internal__n_after_start_req_58; + } + case 'U': { + p++; + goto s_n_llhttp__internal__n_after_start_req_59; + } + default: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_61: + s_n_llhttp__internal__n_after_start_req_61: { + llparse_match_t match_seq; + + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_61; + } + match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob51, 6); + p = match_seq.current; + switch (match_seq.status) { + case kMatchComplete: { + p++; + match = 40; + goto s_n_llhttp__internal__n_invoke_store_method_1; + } + case kMatchPause: { + return s_n_llhttp__internal__n_after_start_req_61; + } + case kMatchMismatch: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_62: + s_n_llhttp__internal__n_after_start_req_62: { + llparse_match_t match_seq; + + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_62; + } + match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob52, 3); + p = match_seq.current; + switch (match_seq.status) { + case kMatchComplete: { + p++; + match = 7; + goto s_n_llhttp__internal__n_invoke_store_method_1; + } + case kMatchPause: { + return s_n_llhttp__internal__n_after_start_req_62; + } + case kMatchMismatch: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_60: + s_n_llhttp__internal__n_after_start_req_60: { + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_60; + } + switch (*p) { + case 'E': { + p++; + goto s_n_llhttp__internal__n_after_start_req_61; + } + case 'R': { + p++; + goto s_n_llhttp__internal__n_after_start_req_62; + } + default: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_65: + s_n_llhttp__internal__n_after_start_req_65: { + llparse_match_t match_seq; + + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_65; + } + match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob53, 3); + p = match_seq.current; + switch (match_seq.status) { + case kMatchComplete: { + p++; + match = 18; + goto s_n_llhttp__internal__n_invoke_store_method_1; + } + case kMatchPause: { + return s_n_llhttp__internal__n_after_start_req_65; + } + case kMatchMismatch: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_67: + s_n_llhttp__internal__n_after_start_req_67: { + llparse_match_t match_seq; + + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_67; + } + match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob54, 2); + p = match_seq.current; + switch (match_seq.status) { + case kMatchComplete: { + p++; + match = 32; + goto s_n_llhttp__internal__n_invoke_store_method_1; + } + case kMatchPause: { + return s_n_llhttp__internal__n_after_start_req_67; + } + case kMatchMismatch: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_68: + s_n_llhttp__internal__n_after_start_req_68: { + llparse_match_t match_seq; + + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_68; + } + match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob55, 2); + p = match_seq.current; + switch (match_seq.status) { + case kMatchComplete: { + p++; + match = 15; + goto s_n_llhttp__internal__n_invoke_store_method_1; + } + case kMatchPause: { + return s_n_llhttp__internal__n_after_start_req_68; + } + case kMatchMismatch: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_66: + s_n_llhttp__internal__n_after_start_req_66: { + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_66; + } + switch (*p) { + case 'I': { + p++; + goto s_n_llhttp__internal__n_after_start_req_67; + } + case 'O': { + p++; + goto s_n_llhttp__internal__n_after_start_req_68; + } + default: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_69: + s_n_llhttp__internal__n_after_start_req_69: { + llparse_match_t match_seq; + + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_69; + } + match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob56, 8); + p = match_seq.current; + switch (match_seq.status) { + case kMatchComplete: { + p++; + match = 27; + goto s_n_llhttp__internal__n_invoke_store_method_1; + } + case kMatchPause: { + return s_n_llhttp__internal__n_after_start_req_69; + } + case kMatchMismatch: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_64: + s_n_llhttp__internal__n_after_start_req_64: { + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_64; + } + switch (*p) { + case 'B': { + p++; + goto s_n_llhttp__internal__n_after_start_req_65; + } + case 'L': { + p++; + goto s_n_llhttp__internal__n_after_start_req_66; + } + case 'S': { + p++; + goto s_n_llhttp__internal__n_after_start_req_69; + } + default: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req_63: + s_n_llhttp__internal__n_after_start_req_63: { + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req_63; + } + switch (*p) { + case 'N': { + p++; + goto s_n_llhttp__internal__n_after_start_req_64; + } + default: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_after_start_req: + s_n_llhttp__internal__n_after_start_req: { + if (p == endp) { + return s_n_llhttp__internal__n_after_start_req; + } + switch (*p) { + case 'A': { + p++; + goto s_n_llhttp__internal__n_after_start_req_1; + } + case 'B': { + p++; + goto s_n_llhttp__internal__n_after_start_req_4; + } + case 'C': { + p++; + goto s_n_llhttp__internal__n_after_start_req_5; + } + case 'D': { + p++; + goto s_n_llhttp__internal__n_after_start_req_10; + } + case 'F': { + p++; + goto s_n_llhttp__internal__n_after_start_req_14; + } + case 'G': { + p++; + goto s_n_llhttp__internal__n_after_start_req_15; + } + case 'H': { + p++; + goto s_n_llhttp__internal__n_after_start_req_18; + } + case 'L': { + p++; + goto s_n_llhttp__internal__n_after_start_req_19; + } + case 'M': { + p++; + goto s_n_llhttp__internal__n_after_start_req_22; + } + case 'N': { + p++; + goto s_n_llhttp__internal__n_after_start_req_31; + } + case 'O': { + p++; + goto s_n_llhttp__internal__n_after_start_req_32; + } + case 'P': { + p++; + goto s_n_llhttp__internal__n_after_start_req_33; + } + case 'R': { + p++; + goto s_n_llhttp__internal__n_after_start_req_46; + } + case 'S': { + p++; + goto s_n_llhttp__internal__n_after_start_req_52; + } + case 'T': { + p++; + goto s_n_llhttp__internal__n_after_start_req_60; + } + case 'U': { + p++; + goto s_n_llhttp__internal__n_after_start_req_63; + } + default: { + goto s_n_llhttp__internal__n_error_106; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_span_start_llhttp__on_method_1: + s_n_llhttp__internal__n_span_start_llhttp__on_method_1: { + if (p == endp) { + return s_n_llhttp__internal__n_span_start_llhttp__on_method_1; + } + state->_span_pos0 = (void*) p; + state->_span_cb0 = llhttp__on_method; + goto s_n_llhttp__internal__n_after_start_req; + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_res_line_almost_done: + s_n_llhttp__internal__n_res_line_almost_done: { + if (p == endp) { + return s_n_llhttp__internal__n_res_line_almost_done; + } + switch (*p) { + case 10: { + p++; + goto s_n_llhttp__internal__n_invoke_llhttp__on_status_complete; + } + case 13: { + p++; + goto s_n_llhttp__internal__n_invoke_llhttp__on_status_complete; + } + default: { + goto s_n_llhttp__internal__n_invoke_test_lenient_flags_28; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_invoke_test_lenient_flags_29: + s_n_llhttp__internal__n_invoke_test_lenient_flags_29: { + switch (llhttp__internal__c_test_lenient_flags_1(state, p, endp)) { + case 1: + goto s_n_llhttp__internal__n_invoke_llhttp__on_status_complete; + default: + goto s_n_llhttp__internal__n_error_92; + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_res_status: + s_n_llhttp__internal__n_res_status: { + if (p == endp) { + return s_n_llhttp__internal__n_res_status; + } + switch (*p) { + case 10: { + goto s_n_llhttp__internal__n_span_end_llhttp__on_status; + } + case 13: { + goto s_n_llhttp__internal__n_span_end_llhttp__on_status_1; + } + default: { + p++; + goto s_n_llhttp__internal__n_res_status; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_span_start_llhttp__on_status: + s_n_llhttp__internal__n_span_start_llhttp__on_status: { + if (p == endp) { + return s_n_llhttp__internal__n_span_start_llhttp__on_status; + } + state->_span_pos0 = (void*) p; + state->_span_cb0 = llhttp__on_status; + goto s_n_llhttp__internal__n_res_status; + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_res_status_code_otherwise: + s_n_llhttp__internal__n_res_status_code_otherwise: { + if (p == endp) { + return s_n_llhttp__internal__n_res_status_code_otherwise; + } + switch (*p) { + case 10: { + p++; + goto s_n_llhttp__internal__n_invoke_test_lenient_flags_27; + } + case 13: { + p++; + goto s_n_llhttp__internal__n_res_line_almost_done; + } + case ' ': { + p++; + goto s_n_llhttp__internal__n_span_start_llhttp__on_status; + } + default: { + goto s_n_llhttp__internal__n_error_93; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_res_status_code_digit_3: + s_n_llhttp__internal__n_res_status_code_digit_3: { + if (p == endp) { + return s_n_llhttp__internal__n_res_status_code_digit_3; + } + switch (*p) { + case '0': { + p++; + match = 0; + goto s_n_llhttp__internal__n_invoke_mul_add_status_code_2; + } + case '1': { + p++; + match = 1; + goto s_n_llhttp__internal__n_invoke_mul_add_status_code_2; + } + case '2': { + p++; + match = 2; + goto s_n_llhttp__internal__n_invoke_mul_add_status_code_2; + } + case '3': { + p++; + match = 3; + goto s_n_llhttp__internal__n_invoke_mul_add_status_code_2; + } + case '4': { + p++; + match = 4; + goto s_n_llhttp__internal__n_invoke_mul_add_status_code_2; + } + case '5': { + p++; + match = 5; + goto s_n_llhttp__internal__n_invoke_mul_add_status_code_2; + } + case '6': { + p++; + match = 6; + goto s_n_llhttp__internal__n_invoke_mul_add_status_code_2; + } + case '7': { + p++; + match = 7; + goto s_n_llhttp__internal__n_invoke_mul_add_status_code_2; + } + case '8': { + p++; + match = 8; + goto s_n_llhttp__internal__n_invoke_mul_add_status_code_2; + } + case '9': { + p++; + match = 9; + goto s_n_llhttp__internal__n_invoke_mul_add_status_code_2; + } + default: { + goto s_n_llhttp__internal__n_error_95; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_res_status_code_digit_2: + s_n_llhttp__internal__n_res_status_code_digit_2: { + if (p == endp) { + return s_n_llhttp__internal__n_res_status_code_digit_2; + } + switch (*p) { + case '0': { + p++; + match = 0; + goto s_n_llhttp__internal__n_invoke_mul_add_status_code_1; + } + case '1': { + p++; + match = 1; + goto s_n_llhttp__internal__n_invoke_mul_add_status_code_1; + } + case '2': { + p++; + match = 2; + goto s_n_llhttp__internal__n_invoke_mul_add_status_code_1; + } + case '3': { + p++; + match = 3; + goto s_n_llhttp__internal__n_invoke_mul_add_status_code_1; + } + case '4': { + p++; + match = 4; + goto s_n_llhttp__internal__n_invoke_mul_add_status_code_1; + } + case '5': { + p++; + match = 5; + goto s_n_llhttp__internal__n_invoke_mul_add_status_code_1; + } + case '6': { + p++; + match = 6; + goto s_n_llhttp__internal__n_invoke_mul_add_status_code_1; + } + case '7': { + p++; + match = 7; + goto s_n_llhttp__internal__n_invoke_mul_add_status_code_1; + } + case '8': { + p++; + match = 8; + goto s_n_llhttp__internal__n_invoke_mul_add_status_code_1; + } + case '9': { + p++; + match = 9; + goto s_n_llhttp__internal__n_invoke_mul_add_status_code_1; + } + default: { + goto s_n_llhttp__internal__n_error_97; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_res_status_code_digit_1: + s_n_llhttp__internal__n_res_status_code_digit_1: { + if (p == endp) { + return s_n_llhttp__internal__n_res_status_code_digit_1; + } + switch (*p) { + case '0': { + p++; + match = 0; + goto s_n_llhttp__internal__n_invoke_mul_add_status_code; + } + case '1': { + p++; + match = 1; + goto s_n_llhttp__internal__n_invoke_mul_add_status_code; + } + case '2': { + p++; + match = 2; + goto s_n_llhttp__internal__n_invoke_mul_add_status_code; + } + case '3': { + p++; + match = 3; + goto s_n_llhttp__internal__n_invoke_mul_add_status_code; + } + case '4': { + p++; + match = 4; + goto s_n_llhttp__internal__n_invoke_mul_add_status_code; + } + case '5': { + p++; + match = 5; + goto s_n_llhttp__internal__n_invoke_mul_add_status_code; + } + case '6': { + p++; + match = 6; + goto s_n_llhttp__internal__n_invoke_mul_add_status_code; + } + case '7': { + p++; + match = 7; + goto s_n_llhttp__internal__n_invoke_mul_add_status_code; + } + case '8': { + p++; + match = 8; + goto s_n_llhttp__internal__n_invoke_mul_add_status_code; + } + case '9': { + p++; + match = 9; + goto s_n_llhttp__internal__n_invoke_mul_add_status_code; + } + default: { + goto s_n_llhttp__internal__n_error_99; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_res_after_version: + s_n_llhttp__internal__n_res_after_version: { + if (p == endp) { + return s_n_llhttp__internal__n_res_after_version; + } + switch (*p) { + case ' ': { + p++; + goto s_n_llhttp__internal__n_invoke_update_status_code; + } + default: { + goto s_n_llhttp__internal__n_error_100; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_invoke_llhttp__on_version_complete_1: + s_n_llhttp__internal__n_invoke_llhttp__on_version_complete_1: { + switch (llhttp__on_version_complete(state, p, endp)) { + case 0: + goto s_n_llhttp__internal__n_res_after_version; + case 21: + goto s_n_llhttp__internal__n_pause_25; + default: + goto s_n_llhttp__internal__n_error_88; + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_error_87: + s_n_llhttp__internal__n_error_87: { + state->error = 0x9; + state->reason = "Invalid HTTP version"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_error_101: + s_n_llhttp__internal__n_error_101: { + state->error = 0x9; + state->reason = "Invalid minor version"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_res_http_minor: + s_n_llhttp__internal__n_res_http_minor: { + if (p == endp) { + return s_n_llhttp__internal__n_res_http_minor; + } + switch (*p) { + case '0': { + p++; + match = 0; + goto s_n_llhttp__internal__n_invoke_store_http_minor_1; + } + case '1': { + p++; + match = 1; + goto s_n_llhttp__internal__n_invoke_store_http_minor_1; + } + case '2': { + p++; + match = 2; + goto s_n_llhttp__internal__n_invoke_store_http_minor_1; + } + case '3': { + p++; + match = 3; + goto s_n_llhttp__internal__n_invoke_store_http_minor_1; + } + case '4': { + p++; + match = 4; + goto s_n_llhttp__internal__n_invoke_store_http_minor_1; + } + case '5': { + p++; + match = 5; + goto s_n_llhttp__internal__n_invoke_store_http_minor_1; + } + case '6': { + p++; + match = 6; + goto s_n_llhttp__internal__n_invoke_store_http_minor_1; + } + case '7': { + p++; + match = 7; + goto s_n_llhttp__internal__n_invoke_store_http_minor_1; + } + case '8': { + p++; + match = 8; + goto s_n_llhttp__internal__n_invoke_store_http_minor_1; + } + case '9': { + p++; + match = 9; + goto s_n_llhttp__internal__n_invoke_store_http_minor_1; + } + default: { + goto s_n_llhttp__internal__n_span_end_llhttp__on_version_7; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_error_102: + s_n_llhttp__internal__n_error_102: { + state->error = 0x9; + state->reason = "Expected dot"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_res_http_dot: + s_n_llhttp__internal__n_res_http_dot: { + if (p == endp) { + return s_n_llhttp__internal__n_res_http_dot; + } + switch (*p) { + case '.': { + p++; + goto s_n_llhttp__internal__n_res_http_minor; + } + default: { + goto s_n_llhttp__internal__n_span_end_llhttp__on_version_8; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_error_103: + s_n_llhttp__internal__n_error_103: { + state->error = 0x9; + state->reason = "Invalid major version"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_res_http_major: + s_n_llhttp__internal__n_res_http_major: { + if (p == endp) { + return s_n_llhttp__internal__n_res_http_major; + } + switch (*p) { + case '0': { + p++; + match = 0; + goto s_n_llhttp__internal__n_invoke_store_http_major_1; + } + case '1': { + p++; + match = 1; + goto s_n_llhttp__internal__n_invoke_store_http_major_1; + } + case '2': { + p++; + match = 2; + goto s_n_llhttp__internal__n_invoke_store_http_major_1; + } + case '3': { + p++; + match = 3; + goto s_n_llhttp__internal__n_invoke_store_http_major_1; + } + case '4': { + p++; + match = 4; + goto s_n_llhttp__internal__n_invoke_store_http_major_1; + } + case '5': { + p++; + match = 5; + goto s_n_llhttp__internal__n_invoke_store_http_major_1; + } + case '6': { + p++; + match = 6; + goto s_n_llhttp__internal__n_invoke_store_http_major_1; + } + case '7': { + p++; + match = 7; + goto s_n_llhttp__internal__n_invoke_store_http_major_1; + } + case '8': { + p++; + match = 8; + goto s_n_llhttp__internal__n_invoke_store_http_major_1; + } + case '9': { + p++; + match = 9; + goto s_n_llhttp__internal__n_invoke_store_http_major_1; + } + default: { + goto s_n_llhttp__internal__n_span_end_llhttp__on_version_9; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_span_start_llhttp__on_version_1: + s_n_llhttp__internal__n_span_start_llhttp__on_version_1: { + if (p == endp) { + return s_n_llhttp__internal__n_span_start_llhttp__on_version_1; + } + state->_span_pos0 = (void*) p; + state->_span_cb0 = llhttp__on_version; + goto s_n_llhttp__internal__n_res_http_major; + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_start_res: + s_n_llhttp__internal__n_start_res: { + llparse_match_t match_seq; + + if (p == endp) { + return s_n_llhttp__internal__n_start_res; + } + match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob57, 5); + p = match_seq.current; + switch (match_seq.status) { + case kMatchComplete: { + p++; + goto s_n_llhttp__internal__n_span_start_llhttp__on_version_1; + } + case kMatchPause: { + return s_n_llhttp__internal__n_start_res; + } + case kMatchMismatch: { + goto s_n_llhttp__internal__n_error_107; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_invoke_llhttp__on_method_complete: + s_n_llhttp__internal__n_invoke_llhttp__on_method_complete: { + switch (llhttp__on_method_complete(state, p, endp)) { + case 0: + goto s_n_llhttp__internal__n_req_first_space_before_url; + case 21: + goto s_n_llhttp__internal__n_pause_23; + default: + goto s_n_llhttp__internal__n_error_1; + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_req_or_res_method_2: + s_n_llhttp__internal__n_req_or_res_method_2: { + llparse_match_t match_seq; + + if (p == endp) { + return s_n_llhttp__internal__n_req_or_res_method_2; + } + match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob58, 2); + p = match_seq.current; + switch (match_seq.status) { + case kMatchComplete: { + p++; + match = 2; + goto s_n_llhttp__internal__n_invoke_store_method; + } + case kMatchPause: { + return s_n_llhttp__internal__n_req_or_res_method_2; + } + case kMatchMismatch: { + goto s_n_llhttp__internal__n_error_104; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_invoke_update_type_1: + s_n_llhttp__internal__n_invoke_update_type_1: { + switch (llhttp__internal__c_update_type_1(state, p, endp)) { + default: + goto s_n_llhttp__internal__n_span_start_llhttp__on_version_1; + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_req_or_res_method_3: + s_n_llhttp__internal__n_req_or_res_method_3: { + llparse_match_t match_seq; + + if (p == endp) { + return s_n_llhttp__internal__n_req_or_res_method_3; + } + match_seq = llparse__match_sequence_id(state, p, endp, llparse_blob59, 3); + p = match_seq.current; + switch (match_seq.status) { + case kMatchComplete: { + p++; + goto s_n_llhttp__internal__n_span_end_llhttp__on_method_1; + } + case kMatchPause: { + return s_n_llhttp__internal__n_req_or_res_method_3; + } + case kMatchMismatch: { + goto s_n_llhttp__internal__n_error_104; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_req_or_res_method_1: + s_n_llhttp__internal__n_req_or_res_method_1: { + if (p == endp) { + return s_n_llhttp__internal__n_req_or_res_method_1; + } + switch (*p) { + case 'E': { + p++; + goto s_n_llhttp__internal__n_req_or_res_method_2; + } + case 'T': { + p++; + goto s_n_llhttp__internal__n_req_or_res_method_3; + } + default: { + goto s_n_llhttp__internal__n_error_104; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_req_or_res_method: + s_n_llhttp__internal__n_req_or_res_method: { + if (p == endp) { + return s_n_llhttp__internal__n_req_or_res_method; + } + switch (*p) { + case 'H': { + p++; + goto s_n_llhttp__internal__n_req_or_res_method_1; + } + default: { + goto s_n_llhttp__internal__n_error_104; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_span_start_llhttp__on_method: + s_n_llhttp__internal__n_span_start_llhttp__on_method: { + if (p == endp) { + return s_n_llhttp__internal__n_span_start_llhttp__on_method; + } + state->_span_pos0 = (void*) p; + state->_span_cb0 = llhttp__on_method; + goto s_n_llhttp__internal__n_req_or_res_method; + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_start_req_or_res: + s_n_llhttp__internal__n_start_req_or_res: { + if (p == endp) { + return s_n_llhttp__internal__n_start_req_or_res; + } + switch (*p) { + case 'H': { + goto s_n_llhttp__internal__n_span_start_llhttp__on_method; + } + default: { + goto s_n_llhttp__internal__n_invoke_update_type_2; + } + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_invoke_load_type: + s_n_llhttp__internal__n_invoke_load_type: { + switch (llhttp__internal__c_load_type(state, p, endp)) { + case 1: + goto s_n_llhttp__internal__n_span_start_llhttp__on_method_1; + case 2: + goto s_n_llhttp__internal__n_start_res; + default: + goto s_n_llhttp__internal__n_start_req_or_res; + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_invoke_update_finish: + s_n_llhttp__internal__n_invoke_update_finish: { + switch (llhttp__internal__c_update_finish(state, p, endp)) { + default: + goto s_n_llhttp__internal__n_invoke_llhttp__on_message_begin; + } + /* UNREACHABLE */; + abort(); + } + case s_n_llhttp__internal__n_start: + s_n_llhttp__internal__n_start: { + if (p == endp) { + return s_n_llhttp__internal__n_start; + } + switch (*p) { + case 10: { + p++; + goto s_n_llhttp__internal__n_start; + } + case 13: { + p++; + goto s_n_llhttp__internal__n_start; + } + default: { + goto s_n_llhttp__internal__n_invoke_load_initial_message_completed; + } + } + /* UNREACHABLE */; + abort(); + } + default: + /* UNREACHABLE */ + abort(); + } + s_n_llhttp__internal__n_error_2: { + state->error = 0x7; + state->reason = "Invalid characters in url"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_update_finish_2: { + switch (llhttp__internal__c_update_finish_1(state, p, endp)) { + default: + goto s_n_llhttp__internal__n_start; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_update_initial_message_completed: { + switch (llhttp__internal__c_update_initial_message_completed(state, p, endp)) { + default: + goto s_n_llhttp__internal__n_invoke_update_finish_2; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_update_content_length: { + switch (llhttp__internal__c_update_content_length(state, p, endp)) { + default: + goto s_n_llhttp__internal__n_invoke_update_initial_message_completed; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_8: { + state->error = 0x5; + state->reason = "Data after `Connection: close`"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_test_lenient_flags_3: { + switch (llhttp__internal__c_test_lenient_flags_3(state, p, endp)) { + case 1: + goto s_n_llhttp__internal__n_closed; + default: + goto s_n_llhttp__internal__n_error_8; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_test_lenient_flags_2: { + switch (llhttp__internal__c_test_lenient_flags_2(state, p, endp)) { + case 1: + goto s_n_llhttp__internal__n_invoke_update_initial_message_completed; + default: + goto s_n_llhttp__internal__n_closed; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_update_finish_1: { + switch (llhttp__internal__c_update_finish_1(state, p, endp)) { + default: + goto s_n_llhttp__internal__n_invoke_test_lenient_flags_2; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_pause_13: { + state->error = 0x15; + state->reason = "on_message_complete pause"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_is_equal_upgrade; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_38: { + state->error = 0x12; + state->reason = "`on_message_complete` callback error"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_pause_15: { + state->error = 0x15; + state->reason = "on_chunk_complete pause"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_llhttp__on_message_complete_2; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_40: { + state->error = 0x14; + state->reason = "`on_chunk_complete` callback error"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_llhttp__on_chunk_complete_1: { + switch (llhttp__on_chunk_complete(state, p, endp)) { + case 0: + goto s_n_llhttp__internal__n_invoke_llhttp__on_message_complete_2; + case 21: + goto s_n_llhttp__internal__n_pause_15; + default: + goto s_n_llhttp__internal__n_error_40; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_pause_2: { + state->error = 0x15; + state->reason = "on_message_complete pause"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_pause_1; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_9: { + state->error = 0x12; + state->reason = "`on_message_complete` callback error"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_llhttp__on_message_complete_1: { + switch (llhttp__on_message_complete(state, p, endp)) { + case 0: + goto s_n_llhttp__internal__n_pause_1; + case 21: + goto s_n_llhttp__internal__n_pause_2; + default: + goto s_n_llhttp__internal__n_error_9; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_36: { + state->error = 0xc; + state->reason = "Chunk size overflow"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_10: { + state->error = 0xc; + state->reason = "Invalid character in chunk size"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_test_lenient_flags_4: { + switch (llhttp__internal__c_test_lenient_flags_4(state, p, endp)) { + case 1: + goto s_n_llhttp__internal__n_chunk_size_otherwise; + default: + goto s_n_llhttp__internal__n_error_10; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_pause_3: { + state->error = 0x15; + state->reason = "on_chunk_complete pause"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_update_content_length_1; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_14: { + state->error = 0x14; + state->reason = "`on_chunk_complete` callback error"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_llhttp__on_chunk_complete: { + switch (llhttp__on_chunk_complete(state, p, endp)) { + case 0: + goto s_n_llhttp__internal__n_invoke_update_content_length_1; + case 21: + goto s_n_llhttp__internal__n_pause_3; + default: + goto s_n_llhttp__internal__n_error_14; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_13: { + state->error = 0x19; + state->reason = "Missing expected CR after chunk data"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_test_lenient_flags_6: { + switch (llhttp__internal__c_test_lenient_flags_1(state, p, endp)) { + case 1: + goto s_n_llhttp__internal__n_invoke_llhttp__on_chunk_complete; + default: + goto s_n_llhttp__internal__n_error_13; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_15: { + state->error = 0x2; + state->reason = "Expected LF after chunk data"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_test_lenient_flags_7: { + switch (llhttp__internal__c_test_lenient_flags_7(state, p, endp)) { + case 1: + goto s_n_llhttp__internal__n_invoke_llhttp__on_chunk_complete; + default: + goto s_n_llhttp__internal__n_error_15; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_span_end_llhttp__on_body: { + const unsigned char* start; + int err; + + start = state->_span_pos0; + state->_span_pos0 = NULL; + err = llhttp__on_body(state, start, p); + if (err != 0) { + state->error = err; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_chunk_data_almost_done; + return s_error; + } + goto s_n_llhttp__internal__n_chunk_data_almost_done; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_or_flags: { + switch (llhttp__internal__c_or_flags(state, p, endp)) { + default: + goto s_n_llhttp__internal__n_header_field_start; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_pause_4: { + state->error = 0x15; + state->reason = "on_chunk_header pause"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_is_equal_content_length; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_12: { + state->error = 0x13; + state->reason = "`on_chunk_header` callback error"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_llhttp__on_chunk_header: { + switch (llhttp__on_chunk_header(state, p, endp)) { + case 0: + goto s_n_llhttp__internal__n_invoke_is_equal_content_length; + case 21: + goto s_n_llhttp__internal__n_pause_4; + default: + goto s_n_llhttp__internal__n_error_12; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_16: { + state->error = 0x2; + state->reason = "Expected LF after chunk size"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_test_lenient_flags_8: { + switch (llhttp__internal__c_test_lenient_flags_8(state, p, endp)) { + case 1: + goto s_n_llhttp__internal__n_invoke_llhttp__on_chunk_header; + default: + goto s_n_llhttp__internal__n_error_16; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_11: { + state->error = 0x19; + state->reason = "Missing expected CR after chunk size"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_test_lenient_flags_5: { + switch (llhttp__internal__c_test_lenient_flags_1(state, p, endp)) { + case 1: + goto s_n_llhttp__internal__n_chunk_size_almost_done; + default: + goto s_n_llhttp__internal__n_error_11; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_17: { + state->error = 0x2; + state->reason = "Invalid character in chunk extensions"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_18: { + state->error = 0x2; + state->reason = "Invalid character in chunk extensions"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_20: { + state->error = 0x19; + state->reason = "Missing expected CR after chunk extension name"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_pause_5: { + state->error = 0x15; + state->reason = "on_chunk_extension_name pause"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_test_lenient_flags_9; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_19: { + state->error = 0x22; + state->reason = "`on_chunk_extension_name` callback error"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_span_end_llhttp__on_chunk_extension_name: { + const unsigned char* start; + int err; + + start = state->_span_pos0; + state->_span_pos0 = NULL; + err = llhttp__on_chunk_extension_name(state, start, p); + if (err != 0) { + state->error = err; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_name_complete; + return s_error; + } + goto s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_name_complete; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_pause_6: { + state->error = 0x15; + state->reason = "on_chunk_extension_name pause"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_chunk_size_almost_done; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_21: { + state->error = 0x22; + state->reason = "`on_chunk_extension_name` callback error"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_span_end_llhttp__on_chunk_extension_name_1: { + const unsigned char* start; + int err; + + start = state->_span_pos0; + state->_span_pos0 = NULL; + err = llhttp__on_chunk_extension_name(state, start, p); + if (err != 0) { + state->error = err; + state->error_pos = (const char*) (p + 1); + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_name_complete_1; + return s_error; + } + p++; + goto s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_name_complete_1; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_pause_7: { + state->error = 0x15; + state->reason = "on_chunk_extension_name pause"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_chunk_extensions; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_22: { + state->error = 0x22; + state->reason = "`on_chunk_extension_name` callback error"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_span_end_llhttp__on_chunk_extension_name_2: { + const unsigned char* start; + int err; + + start = state->_span_pos0; + state->_span_pos0 = NULL; + err = llhttp__on_chunk_extension_name(state, start, p); + if (err != 0) { + state->error = err; + state->error_pos = (const char*) (p + 1); + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_name_complete_2; + return s_error; + } + p++; + goto s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_name_complete_2; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_25: { + state->error = 0x19; + state->reason = "Missing expected CR after chunk extension value"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_pause_8: { + state->error = 0x15; + state->reason = "on_chunk_extension_value pause"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_test_lenient_flags_10; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_24: { + state->error = 0x23; + state->reason = "`on_chunk_extension_value` callback error"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_span_end_llhttp__on_chunk_extension_value: { + const unsigned char* start; + int err; + + start = state->_span_pos0; + state->_span_pos0 = NULL; + err = llhttp__on_chunk_extension_value(state, start, p); + if (err != 0) { + state->error = err; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_value_complete; + return s_error; + } + goto s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_value_complete; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_pause_9: { + state->error = 0x15; + state->reason = "on_chunk_extension_value pause"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_chunk_size_almost_done; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_26: { + state->error = 0x23; + state->reason = "`on_chunk_extension_value` callback error"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_span_end_llhttp__on_chunk_extension_value_1: { + const unsigned char* start; + int err; + + start = state->_span_pos0; + state->_span_pos0 = NULL; + err = llhttp__on_chunk_extension_value(state, start, p); + if (err != 0) { + state->error = err; + state->error_pos = (const char*) (p + 1); + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_value_complete_1; + return s_error; + } + p++; + goto s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_value_complete_1; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_28: { + state->error = 0x19; + state->reason = "Missing expected CR after chunk extension value"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_test_lenient_flags_11: { + switch (llhttp__internal__c_test_lenient_flags_1(state, p, endp)) { + case 1: + goto s_n_llhttp__internal__n_chunk_size_almost_done; + default: + goto s_n_llhttp__internal__n_error_28; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_29: { + state->error = 0x2; + state->reason = "Invalid character in chunk extensions quote value"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_pause_10: { + state->error = 0x15; + state->reason = "on_chunk_extension_value pause"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_chunk_extension_quoted_value_done; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_27: { + state->error = 0x23; + state->reason = "`on_chunk_extension_value` callback error"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_span_end_llhttp__on_chunk_extension_value_2: { + const unsigned char* start; + int err; + + start = state->_span_pos0; + state->_span_pos0 = NULL; + err = llhttp__on_chunk_extension_value(state, start, p); + if (err != 0) { + state->error = err; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_value_complete_2; + return s_error; + } + goto s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_value_complete_2; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_span_end_llhttp__on_chunk_extension_value_3: { + const unsigned char* start; + int err; + + start = state->_span_pos0; + state->_span_pos0 = NULL; + err = llhttp__on_chunk_extension_value(state, start, p); + if (err != 0) { + state->error = err; + state->error_pos = (const char*) (p + 1); + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_error_30; + return s_error; + } + p++; + goto s_n_llhttp__internal__n_error_30; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_span_end_llhttp__on_chunk_extension_value_4: { + const unsigned char* start; + int err; + + start = state->_span_pos0; + state->_span_pos0 = NULL; + err = llhttp__on_chunk_extension_value(state, start, p); + if (err != 0) { + state->error = err; + state->error_pos = (const char*) (p + 1); + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_error_31; + return s_error; + } + p++; + goto s_n_llhttp__internal__n_error_31; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_pause_11: { + state->error = 0x15; + state->reason = "on_chunk_extension_value pause"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_chunk_extensions; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_32: { + state->error = 0x23; + state->reason = "`on_chunk_extension_value` callback error"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_span_end_llhttp__on_chunk_extension_value_5: { + const unsigned char* start; + int err; + + start = state->_span_pos0; + state->_span_pos0 = NULL; + err = llhttp__on_chunk_extension_value(state, start, p); + if (err != 0) { + state->error = err; + state->error_pos = (const char*) (p + 1); + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_value_complete_3; + return s_error; + } + p++; + goto s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_value_complete_3; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_span_end_llhttp__on_chunk_extension_value_6: { + const unsigned char* start; + int err; + + start = state->_span_pos0; + state->_span_pos0 = NULL; + err = llhttp__on_chunk_extension_value(state, start, p); + if (err != 0) { + state->error = err; + state->error_pos = (const char*) (p + 1); + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_error_33; + return s_error; + } + p++; + goto s_n_llhttp__internal__n_error_33; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_pause_12: { + state->error = 0x15; + state->reason = "on_chunk_extension_name pause"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_chunk_extension_value; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_23: { + state->error = 0x22; + state->reason = "`on_chunk_extension_name` callback error"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_llhttp__on_chunk_extension_name_complete_3: { + switch (llhttp__on_chunk_extension_name_complete(state, p, endp)) { + case 0: + goto s_n_llhttp__internal__n_chunk_extension_value; + case 21: + goto s_n_llhttp__internal__n_pause_12; + default: + goto s_n_llhttp__internal__n_error_23; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_span_end_llhttp__on_chunk_extension_name_3: { + const unsigned char* start; + int err; + + start = state->_span_pos0; + state->_span_pos0 = NULL; + err = llhttp__on_chunk_extension_name(state, start, p); + if (err != 0) { + state->error = err; + state->error_pos = (const char*) (p + 1); + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_span_start_llhttp__on_chunk_extension_value; + return s_error; + } + p++; + goto s_n_llhttp__internal__n_span_start_llhttp__on_chunk_extension_value; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_span_end_llhttp__on_chunk_extension_name_4: { + const unsigned char* start; + int err; + + start = state->_span_pos0; + state->_span_pos0 = NULL; + err = llhttp__on_chunk_extension_name(state, start, p); + if (err != 0) { + state->error = err; + state->error_pos = (const char*) (p + 1); + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_error_34; + return s_error; + } + p++; + goto s_n_llhttp__internal__n_error_34; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_35: { + state->error = 0xc; + state->reason = "Invalid character in chunk size"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_mul_add_content_length: { + switch (llhttp__internal__c_mul_add_content_length(state, p, endp, match)) { + case 1: + goto s_n_llhttp__internal__n_error_36; + default: + goto s_n_llhttp__internal__n_chunk_size; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_37: { + state->error = 0xc; + state->reason = "Invalid character in chunk size"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_span_end_llhttp__on_body_1: { + const unsigned char* start; + int err; + + start = state->_span_pos0; + state->_span_pos0 = NULL; + err = llhttp__on_body(state, start, p); + if (err != 0) { + state->error = err; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_llhttp__on_message_complete_2; + return s_error; + } + goto s_n_llhttp__internal__n_invoke_llhttp__on_message_complete_2; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_update_finish_3: { + switch (llhttp__internal__c_update_finish_3(state, p, endp)) { + default: + goto s_n_llhttp__internal__n_span_start_llhttp__on_body_2; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_39: { + state->error = 0xf; + state->reason = "Request has invalid `Transfer-Encoding`"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_pause: { + state->error = 0x15; + state->reason = "on_message_complete pause"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_llhttp__after_message_complete; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_7: { + state->error = 0x12; + state->reason = "`on_message_complete` callback error"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_llhttp__on_message_complete: { + switch (llhttp__on_message_complete(state, p, endp)) { + case 0: + goto s_n_llhttp__internal__n_invoke_llhttp__after_message_complete; + case 21: + goto s_n_llhttp__internal__n_pause; + default: + goto s_n_llhttp__internal__n_error_7; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_or_flags_1: { + switch (llhttp__internal__c_or_flags_1(state, p, endp)) { + default: + goto s_n_llhttp__internal__n_invoke_llhttp__after_headers_complete; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_or_flags_2: { + switch (llhttp__internal__c_or_flags_1(state, p, endp)) { + default: + goto s_n_llhttp__internal__n_invoke_llhttp__after_headers_complete; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_update_upgrade: { + switch (llhttp__internal__c_update_upgrade(state, p, endp)) { + default: + goto s_n_llhttp__internal__n_invoke_or_flags_2; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_pause_14: { + state->error = 0x15; + state->reason = "Paused by on_headers_complete"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_llhttp__after_headers_complete; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_6: { + state->error = 0x11; + state->reason = "User callback error"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_llhttp__on_headers_complete: { + switch (llhttp__on_headers_complete(state, p, endp)) { + case 0: + goto s_n_llhttp__internal__n_invoke_llhttp__after_headers_complete; + case 1: + goto s_n_llhttp__internal__n_invoke_or_flags_1; + case 2: + goto s_n_llhttp__internal__n_invoke_update_upgrade; + case 21: + goto s_n_llhttp__internal__n_pause_14; + default: + goto s_n_llhttp__internal__n_error_6; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_llhttp__before_headers_complete: { + switch (llhttp__before_headers_complete(state, p, endp)) { + default: + goto s_n_llhttp__internal__n_invoke_llhttp__on_headers_complete; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_test_flags: { + switch (llhttp__internal__c_test_flags(state, p, endp)) { + case 1: + goto s_n_llhttp__internal__n_invoke_llhttp__on_chunk_complete_1; + default: + goto s_n_llhttp__internal__n_invoke_llhttp__before_headers_complete; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_test_lenient_flags_1: { + switch (llhttp__internal__c_test_lenient_flags_1(state, p, endp)) { + case 1: + goto s_n_llhttp__internal__n_invoke_test_flags; + default: + goto s_n_llhttp__internal__n_error_5; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_pause_17: { + state->error = 0x15; + state->reason = "on_chunk_complete pause"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_llhttp__on_message_complete_2; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_42: { + state->error = 0x14; + state->reason = "`on_chunk_complete` callback error"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_llhttp__on_chunk_complete_2: { + switch (llhttp__on_chunk_complete(state, p, endp)) { + case 0: + goto s_n_llhttp__internal__n_invoke_llhttp__on_message_complete_2; + case 21: + goto s_n_llhttp__internal__n_pause_17; + default: + goto s_n_llhttp__internal__n_error_42; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_or_flags_3: { + switch (llhttp__internal__c_or_flags_1(state, p, endp)) { + default: + goto s_n_llhttp__internal__n_invoke_llhttp__after_headers_complete; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_or_flags_4: { + switch (llhttp__internal__c_or_flags_1(state, p, endp)) { + default: + goto s_n_llhttp__internal__n_invoke_llhttp__after_headers_complete; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_update_upgrade_1: { + switch (llhttp__internal__c_update_upgrade(state, p, endp)) { + default: + goto s_n_llhttp__internal__n_invoke_or_flags_4; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_pause_16: { + state->error = 0x15; + state->reason = "Paused by on_headers_complete"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_llhttp__after_headers_complete; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_41: { + state->error = 0x11; + state->reason = "User callback error"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_llhttp__on_headers_complete_1: { + switch (llhttp__on_headers_complete(state, p, endp)) { + case 0: + goto s_n_llhttp__internal__n_invoke_llhttp__after_headers_complete; + case 1: + goto s_n_llhttp__internal__n_invoke_or_flags_3; + case 2: + goto s_n_llhttp__internal__n_invoke_update_upgrade_1; + case 21: + goto s_n_llhttp__internal__n_pause_16; + default: + goto s_n_llhttp__internal__n_error_41; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_llhttp__before_headers_complete_1: { + switch (llhttp__before_headers_complete(state, p, endp)) { + default: + goto s_n_llhttp__internal__n_invoke_llhttp__on_headers_complete_1; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_test_flags_1: { + switch (llhttp__internal__c_test_flags(state, p, endp)) { + case 1: + goto s_n_llhttp__internal__n_invoke_llhttp__on_chunk_complete_2; + default: + goto s_n_llhttp__internal__n_invoke_llhttp__before_headers_complete_1; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_43: { + state->error = 0x2; + state->reason = "Expected LF after headers"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_test_lenient_flags_12: { + switch (llhttp__internal__c_test_lenient_flags_8(state, p, endp)) { + case 1: + goto s_n_llhttp__internal__n_invoke_test_flags_1; + default: + goto s_n_llhttp__internal__n_error_43; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_span_end_llhttp__on_header_field: { + const unsigned char* start; + int err; + + start = state->_span_pos0; + state->_span_pos0 = NULL; + err = llhttp__on_header_field(state, start, p); + if (err != 0) { + state->error = err; + state->error_pos = (const char*) (p + 1); + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_error_5; + return s_error; + } + p++; + goto s_n_llhttp__internal__n_error_5; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_test_lenient_flags_13: { + switch (llhttp__internal__c_test_lenient_flags(state, p, endp)) { + case 1: + goto s_n_llhttp__internal__n_header_field_colon_discard_ws; + default: + goto s_n_llhttp__internal__n_span_end_llhttp__on_header_field; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_58: { + state->error = 0xb; + state->reason = "Content-Length can't be present with Transfer-Encoding"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_46: { + state->error = 0xa; + state->reason = "Invalid header value char"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_test_lenient_flags_15: { + switch (llhttp__internal__c_test_lenient_flags(state, p, endp)) { + case 1: + goto s_n_llhttp__internal__n_header_value_discard_ws; + default: + goto s_n_llhttp__internal__n_error_46; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_48: { + state->error = 0xb; + state->reason = "Empty Content-Length"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_pause_18: { + state->error = 0x15; + state->reason = "on_header_value_complete pause"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_header_field_start; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_47: { + state->error = 0x1d; + state->reason = "`on_header_value_complete` callback error"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_span_end_llhttp__on_header_value: { + const unsigned char* start; + int err; + + start = state->_span_pos0; + state->_span_pos0 = NULL; + err = llhttp__on_header_value(state, start, p); + if (err != 0) { + state->error = err; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_llhttp__on_header_value_complete; + return s_error; + } + goto s_n_llhttp__internal__n_invoke_llhttp__on_header_value_complete; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_update_header_state: { + switch (llhttp__internal__c_update_header_state(state, p, endp)) { + default: + goto s_n_llhttp__internal__n_span_start_llhttp__on_header_value; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_or_flags_5: { + switch (llhttp__internal__c_or_flags_5(state, p, endp)) { + default: + goto s_n_llhttp__internal__n_invoke_update_header_state; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_or_flags_6: { + switch (llhttp__internal__c_or_flags_6(state, p, endp)) { + default: + goto s_n_llhttp__internal__n_invoke_update_header_state; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_or_flags_7: { + switch (llhttp__internal__c_or_flags_7(state, p, endp)) { + default: + goto s_n_llhttp__internal__n_invoke_update_header_state; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_or_flags_8: { + switch (llhttp__internal__c_or_flags_8(state, p, endp)) { + default: + goto s_n_llhttp__internal__n_span_start_llhttp__on_header_value; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_load_header_state_2: { + switch (llhttp__internal__c_load_header_state(state, p, endp)) { + case 5: + goto s_n_llhttp__internal__n_invoke_or_flags_5; + case 6: + goto s_n_llhttp__internal__n_invoke_or_flags_6; + case 7: + goto s_n_llhttp__internal__n_invoke_or_flags_7; + case 8: + goto s_n_llhttp__internal__n_invoke_or_flags_8; + default: + goto s_n_llhttp__internal__n_span_start_llhttp__on_header_value; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_load_header_state_1: { + switch (llhttp__internal__c_load_header_state(state, p, endp)) { + case 2: + goto s_n_llhttp__internal__n_error_48; + default: + goto s_n_llhttp__internal__n_invoke_load_header_state_2; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_45: { + state->error = 0xa; + state->reason = "Invalid header value char"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_test_lenient_flags_14: { + switch (llhttp__internal__c_test_lenient_flags_1(state, p, endp)) { + case 1: + goto s_n_llhttp__internal__n_header_value_discard_lws; + default: + goto s_n_llhttp__internal__n_error_45; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_49: { + state->error = 0x2; + state->reason = "Expected LF after CR"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_test_lenient_flags_16: { + switch (llhttp__internal__c_test_lenient_flags(state, p, endp)) { + case 1: + goto s_n_llhttp__internal__n_header_value_discard_lws; + default: + goto s_n_llhttp__internal__n_error_49; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_update_header_state_1: { + switch (llhttp__internal__c_update_header_state_1(state, p, endp)) { + default: + goto s_n_llhttp__internal__n_span_start_llhttp__on_header_value_1; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_load_header_state_4: { + switch (llhttp__internal__c_load_header_state(state, p, endp)) { + case 8: + goto s_n_llhttp__internal__n_invoke_update_header_state_1; + default: + goto s_n_llhttp__internal__n_span_start_llhttp__on_header_value_1; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_update_header_state_2: { + switch (llhttp__internal__c_update_header_state(state, p, endp)) { + default: + goto s_n_llhttp__internal__n_invoke_llhttp__on_header_value_complete; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_or_flags_9: { + switch (llhttp__internal__c_or_flags_5(state, p, endp)) { + default: + goto s_n_llhttp__internal__n_invoke_update_header_state_2; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_or_flags_10: { + switch (llhttp__internal__c_or_flags_6(state, p, endp)) { + default: + goto s_n_llhttp__internal__n_invoke_update_header_state_2; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_or_flags_11: { + switch (llhttp__internal__c_or_flags_7(state, p, endp)) { + default: + goto s_n_llhttp__internal__n_invoke_update_header_state_2; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_or_flags_12: { + switch (llhttp__internal__c_or_flags_8(state, p, endp)) { + default: + goto s_n_llhttp__internal__n_invoke_llhttp__on_header_value_complete; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_load_header_state_5: { + switch (llhttp__internal__c_load_header_state(state, p, endp)) { + case 5: + goto s_n_llhttp__internal__n_invoke_or_flags_9; + case 6: + goto s_n_llhttp__internal__n_invoke_or_flags_10; + case 7: + goto s_n_llhttp__internal__n_invoke_or_flags_11; + case 8: + goto s_n_llhttp__internal__n_invoke_or_flags_12; + default: + goto s_n_llhttp__internal__n_invoke_llhttp__on_header_value_complete; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_51: { + state->error = 0x3; + state->reason = "Missing expected LF after header value"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_50: { + state->error = 0x19; + state->reason = "Missing expected CR after header value"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_span_end_llhttp__on_header_value_1: { + const unsigned char* start; + int err; + + start = state->_span_pos0; + state->_span_pos0 = NULL; + err = llhttp__on_header_value(state, start, p); + if (err != 0) { + state->error = err; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_test_lenient_flags_17; + return s_error; + } + goto s_n_llhttp__internal__n_invoke_test_lenient_flags_17; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_span_end_llhttp__on_header_value_2: { + const unsigned char* start; + int err; + + start = state->_span_pos0; + state->_span_pos0 = NULL; + err = llhttp__on_header_value(state, start, p); + if (err != 0) { + state->error = err; + state->error_pos = (const char*) (p + 1); + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_header_value_almost_done; + return s_error; + } + p++; + goto s_n_llhttp__internal__n_header_value_almost_done; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_span_end_llhttp__on_header_value_4: { + const unsigned char* start; + int err; + + start = state->_span_pos0; + state->_span_pos0 = NULL; + err = llhttp__on_header_value(state, start, p); + if (err != 0) { + state->error = err; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_header_value_almost_done; + return s_error; + } + goto s_n_llhttp__internal__n_header_value_almost_done; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_span_end_llhttp__on_header_value_5: { + const unsigned char* start; + int err; + + start = state->_span_pos0; + state->_span_pos0 = NULL; + err = llhttp__on_header_value(state, start, p); + if (err != 0) { + state->error = err; + state->error_pos = (const char*) (p + 1); + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_header_value_almost_done; + return s_error; + } + p++; + goto s_n_llhttp__internal__n_header_value_almost_done; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_span_end_llhttp__on_header_value_3: { + const unsigned char* start; + int err; + + start = state->_span_pos0; + state->_span_pos0 = NULL; + err = llhttp__on_header_value(state, start, p); + if (err != 0) { + state->error = err; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_error_52; + return s_error; + } + goto s_n_llhttp__internal__n_error_52; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_test_lenient_flags_18: { + switch (llhttp__internal__c_test_lenient_flags(state, p, endp)) { + case 1: + goto s_n_llhttp__internal__n_header_value_lenient; + default: + goto s_n_llhttp__internal__n_span_end_llhttp__on_header_value_3; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_update_header_state_4: { + switch (llhttp__internal__c_update_header_state(state, p, endp)) { + default: + goto s_n_llhttp__internal__n_header_value_connection; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_or_flags_13: { + switch (llhttp__internal__c_or_flags_5(state, p, endp)) { + default: + goto s_n_llhttp__internal__n_invoke_update_header_state_4; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_or_flags_14: { + switch (llhttp__internal__c_or_flags_6(state, p, endp)) { + default: + goto s_n_llhttp__internal__n_invoke_update_header_state_4; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_or_flags_15: { + switch (llhttp__internal__c_or_flags_7(state, p, endp)) { + default: + goto s_n_llhttp__internal__n_invoke_update_header_state_4; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_or_flags_16: { + switch (llhttp__internal__c_or_flags_8(state, p, endp)) { + default: + goto s_n_llhttp__internal__n_header_value_connection; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_load_header_state_6: { + switch (llhttp__internal__c_load_header_state(state, p, endp)) { + case 5: + goto s_n_llhttp__internal__n_invoke_or_flags_13; + case 6: + goto s_n_llhttp__internal__n_invoke_or_flags_14; + case 7: + goto s_n_llhttp__internal__n_invoke_or_flags_15; + case 8: + goto s_n_llhttp__internal__n_invoke_or_flags_16; + default: + goto s_n_llhttp__internal__n_header_value_connection; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_update_header_state_5: { + switch (llhttp__internal__c_update_header_state_1(state, p, endp)) { + default: + goto s_n_llhttp__internal__n_header_value_connection_token; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_update_header_state_3: { + switch (llhttp__internal__c_update_header_state_3(state, p, endp)) { + default: + goto s_n_llhttp__internal__n_header_value_connection_ws; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_update_header_state_6: { + switch (llhttp__internal__c_update_header_state_6(state, p, endp)) { + default: + goto s_n_llhttp__internal__n_header_value_connection_ws; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_update_header_state_7: { + switch (llhttp__internal__c_update_header_state_7(state, p, endp)) { + default: + goto s_n_llhttp__internal__n_header_value_connection_ws; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_span_end_llhttp__on_header_value_6: { + const unsigned char* start; + int err; + + start = state->_span_pos0; + state->_span_pos0 = NULL; + err = llhttp__on_header_value(state, start, p); + if (err != 0) { + state->error = err; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_error_54; + return s_error; + } + goto s_n_llhttp__internal__n_error_54; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_mul_add_content_length_1: { + switch (llhttp__internal__c_mul_add_content_length_1(state, p, endp, match)) { + case 1: + goto s_n_llhttp__internal__n_span_end_llhttp__on_header_value_6; + default: + goto s_n_llhttp__internal__n_header_value_content_length; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_or_flags_17: { + switch (llhttp__internal__c_or_flags_17(state, p, endp)) { + default: + goto s_n_llhttp__internal__n_header_value_otherwise; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_span_end_llhttp__on_header_value_7: { + const unsigned char* start; + int err; + + start = state->_span_pos0; + state->_span_pos0 = NULL; + err = llhttp__on_header_value(state, start, p); + if (err != 0) { + state->error = err; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_error_55; + return s_error; + } + goto s_n_llhttp__internal__n_error_55; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_53: { + state->error = 0x4; + state->reason = "Duplicate Content-Length"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_test_flags_2: { + switch (llhttp__internal__c_test_flags_2(state, p, endp)) { + case 0: + goto s_n_llhttp__internal__n_header_value_content_length; + default: + goto s_n_llhttp__internal__n_error_53; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_span_end_llhttp__on_header_value_9: { + const unsigned char* start; + int err; + + start = state->_span_pos0; + state->_span_pos0 = NULL; + err = llhttp__on_header_value(state, start, p); + if (err != 0) { + state->error = err; + state->error_pos = (const char*) (p + 1); + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_error_57; + return s_error; + } + p++; + goto s_n_llhttp__internal__n_error_57; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_update_header_state_8: { + switch (llhttp__internal__c_update_header_state_8(state, p, endp)) { + default: + goto s_n_llhttp__internal__n_header_value_otherwise; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_span_end_llhttp__on_header_value_8: { + const unsigned char* start; + int err; + + start = state->_span_pos0; + state->_span_pos0 = NULL; + err = llhttp__on_header_value(state, start, p); + if (err != 0) { + state->error = err; + state->error_pos = (const char*) (p + 1); + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_error_56; + return s_error; + } + p++; + goto s_n_llhttp__internal__n_error_56; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_test_lenient_flags_19: { + switch (llhttp__internal__c_test_lenient_flags_19(state, p, endp)) { + case 0: + goto s_n_llhttp__internal__n_span_end_llhttp__on_header_value_8; + default: + goto s_n_llhttp__internal__n_header_value_te_chunked; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_load_type_1: { + switch (llhttp__internal__c_load_type(state, p, endp)) { + case 1: + goto s_n_llhttp__internal__n_invoke_test_lenient_flags_19; + default: + goto s_n_llhttp__internal__n_header_value_te_chunked; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_update_header_state_9: { + switch (llhttp__internal__c_update_header_state_1(state, p, endp)) { + default: + goto s_n_llhttp__internal__n_header_value; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_and_flags: { + switch (llhttp__internal__c_and_flags(state, p, endp)) { + default: + goto s_n_llhttp__internal__n_header_value_te_chunked; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_or_flags_19: { + switch (llhttp__internal__c_or_flags_18(state, p, endp)) { + default: + goto s_n_llhttp__internal__n_invoke_and_flags; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_test_lenient_flags_20: { + switch (llhttp__internal__c_test_lenient_flags_19(state, p, endp)) { + case 0: + goto s_n_llhttp__internal__n_span_end_llhttp__on_header_value_9; + default: + goto s_n_llhttp__internal__n_invoke_or_flags_19; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_load_type_2: { + switch (llhttp__internal__c_load_type(state, p, endp)) { + case 1: + goto s_n_llhttp__internal__n_invoke_test_lenient_flags_20; + default: + goto s_n_llhttp__internal__n_invoke_or_flags_19; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_or_flags_18: { + switch (llhttp__internal__c_or_flags_18(state, p, endp)) { + default: + goto s_n_llhttp__internal__n_invoke_and_flags; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_test_flags_3: { + switch (llhttp__internal__c_test_flags_3(state, p, endp)) { + case 1: + goto s_n_llhttp__internal__n_invoke_load_type_2; + default: + goto s_n_llhttp__internal__n_invoke_or_flags_18; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_or_flags_20: { + switch (llhttp__internal__c_or_flags_20(state, p, endp)) { + default: + goto s_n_llhttp__internal__n_invoke_update_header_state_9; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_load_header_state_3: { + switch (llhttp__internal__c_load_header_state(state, p, endp)) { + case 1: + goto s_n_llhttp__internal__n_header_value_connection; + case 2: + goto s_n_llhttp__internal__n_invoke_test_flags_2; + case 3: + goto s_n_llhttp__internal__n_invoke_test_flags_3; + case 4: + goto s_n_llhttp__internal__n_invoke_or_flags_20; + default: + goto s_n_llhttp__internal__n_header_value; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_test_lenient_flags_21: { + switch (llhttp__internal__c_test_lenient_flags_21(state, p, endp)) { + case 0: + goto s_n_llhttp__internal__n_error_58; + default: + goto s_n_llhttp__internal__n_header_value_discard_ws; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_test_flags_4: { + switch (llhttp__internal__c_test_flags_4(state, p, endp)) { + case 1: + goto s_n_llhttp__internal__n_invoke_test_lenient_flags_21; + default: + goto s_n_llhttp__internal__n_header_value_discard_ws; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_59: { + state->error = 0xf; + state->reason = "Transfer-Encoding can't be present with Content-Length"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_test_lenient_flags_22: { + switch (llhttp__internal__c_test_lenient_flags_21(state, p, endp)) { + case 0: + goto s_n_llhttp__internal__n_error_59; + default: + goto s_n_llhttp__internal__n_header_value_discard_ws; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_test_flags_5: { + switch (llhttp__internal__c_test_flags_2(state, p, endp)) { + case 1: + goto s_n_llhttp__internal__n_invoke_test_lenient_flags_22; + default: + goto s_n_llhttp__internal__n_header_value_discard_ws; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_pause_19: { + state->error = 0x15; + state->reason = "on_header_field_complete pause"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_load_header_state; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_44: { + state->error = 0x1c; + state->reason = "`on_header_field_complete` callback error"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_span_end_llhttp__on_header_field_1: { + const unsigned char* start; + int err; + + start = state->_span_pos0; + state->_span_pos0 = NULL; + err = llhttp__on_header_field(state, start, p); + if (err != 0) { + state->error = err; + state->error_pos = (const char*) (p + 1); + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_llhttp__on_header_field_complete; + return s_error; + } + p++; + goto s_n_llhttp__internal__n_invoke_llhttp__on_header_field_complete; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_span_end_llhttp__on_header_field_2: { + const unsigned char* start; + int err; + + start = state->_span_pos0; + state->_span_pos0 = NULL; + err = llhttp__on_header_field(state, start, p); + if (err != 0) { + state->error = err; + state->error_pos = (const char*) (p + 1); + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_llhttp__on_header_field_complete; + return s_error; + } + p++; + goto s_n_llhttp__internal__n_invoke_llhttp__on_header_field_complete; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_60: { + state->error = 0xa; + state->reason = "Invalid header token"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_update_header_state_10: { + switch (llhttp__internal__c_update_header_state_1(state, p, endp)) { + default: + goto s_n_llhttp__internal__n_header_field_general; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_store_header_state: { + switch (llhttp__internal__c_store_header_state(state, p, endp, match)) { + default: + goto s_n_llhttp__internal__n_header_field_colon; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_update_header_state_11: { + switch (llhttp__internal__c_update_header_state_1(state, p, endp)) { + default: + goto s_n_llhttp__internal__n_header_field_general; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_4: { + state->error = 0x1e; + state->reason = "Unexpected space after start line"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_test_lenient_flags: { + switch (llhttp__internal__c_test_lenient_flags(state, p, endp)) { + case 1: + goto s_n_llhttp__internal__n_header_field_start; + default: + goto s_n_llhttp__internal__n_error_4; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_pause_20: { + state->error = 0x15; + state->reason = "on_url_complete pause"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_headers_start; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_3: { + state->error = 0x1a; + state->reason = "`on_url_complete` callback error"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_llhttp__on_url_complete: { + switch (llhttp__on_url_complete(state, p, endp)) { + case 0: + goto s_n_llhttp__internal__n_headers_start; + case 21: + goto s_n_llhttp__internal__n_pause_20; + default: + goto s_n_llhttp__internal__n_error_3; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_update_http_minor: { + switch (llhttp__internal__c_update_http_minor(state, p, endp)) { + default: + goto s_n_llhttp__internal__n_invoke_llhttp__on_url_complete; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_update_http_major: { + switch (llhttp__internal__c_update_http_major(state, p, endp)) { + default: + goto s_n_llhttp__internal__n_invoke_update_http_minor; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_span_end_llhttp__on_url_3: { + const unsigned char* start; + int err; + + start = state->_span_pos0; + state->_span_pos0 = NULL; + err = llhttp__on_url(state, start, p); + if (err != 0) { + state->error = err; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_url_skip_to_http09; + return s_error; + } + goto s_n_llhttp__internal__n_url_skip_to_http09; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_61: { + state->error = 0x7; + state->reason = "Expected CRLF"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_span_end_llhttp__on_url_4: { + const unsigned char* start; + int err; + + start = state->_span_pos0; + state->_span_pos0 = NULL; + err = llhttp__on_url(state, start, p); + if (err != 0) { + state->error = err; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_url_skip_lf_to_http09; + return s_error; + } + goto s_n_llhttp__internal__n_url_skip_lf_to_http09; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_69: { + state->error = 0x17; + state->reason = "Pause on PRI/Upgrade"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_70: { + state->error = 0x9; + state->reason = "Expected HTTP/2 Connection Preface"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_67: { + state->error = 0x2; + state->reason = "Expected CRLF after version"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_test_lenient_flags_25: { + switch (llhttp__internal__c_test_lenient_flags_8(state, p, endp)) { + case 1: + goto s_n_llhttp__internal__n_headers_start; + default: + goto s_n_llhttp__internal__n_error_67; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_66: { + state->error = 0x9; + state->reason = "Expected CRLF after version"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_test_lenient_flags_24: { + switch (llhttp__internal__c_test_lenient_flags_1(state, p, endp)) { + case 1: + goto s_n_llhttp__internal__n_req_http_complete_crlf; + default: + goto s_n_llhttp__internal__n_error_66; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_68: { + state->error = 0x9; + state->reason = "Expected CRLF after version"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_pause_21: { + state->error = 0x15; + state->reason = "on_version_complete pause"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_load_method_1; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_65: { + state->error = 0x21; + state->reason = "`on_version_complete` callback error"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_span_end_llhttp__on_version_1: { + const unsigned char* start; + int err; + + start = state->_span_pos0; + state->_span_pos0 = NULL; + err = llhttp__on_version(state, start, p); + if (err != 0) { + state->error = err; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_llhttp__on_version_complete; + return s_error; + } + goto s_n_llhttp__internal__n_invoke_llhttp__on_version_complete; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_span_end_llhttp__on_version: { + const unsigned char* start; + int err; + + start = state->_span_pos0; + state->_span_pos0 = NULL; + err = llhttp__on_version(state, start, p); + if (err != 0) { + state->error = err; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_error_64; + return s_error; + } + goto s_n_llhttp__internal__n_error_64; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_load_http_minor: { + switch (llhttp__internal__c_load_http_minor(state, p, endp)) { + case 9: + goto s_n_llhttp__internal__n_span_end_llhttp__on_version_1; + default: + goto s_n_llhttp__internal__n_span_end_llhttp__on_version; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_load_http_minor_1: { + switch (llhttp__internal__c_load_http_minor(state, p, endp)) { + case 0: + goto s_n_llhttp__internal__n_span_end_llhttp__on_version_1; + case 1: + goto s_n_llhttp__internal__n_span_end_llhttp__on_version_1; + default: + goto s_n_llhttp__internal__n_span_end_llhttp__on_version; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_load_http_minor_2: { + switch (llhttp__internal__c_load_http_minor(state, p, endp)) { + case 0: + goto s_n_llhttp__internal__n_span_end_llhttp__on_version_1; + default: + goto s_n_llhttp__internal__n_span_end_llhttp__on_version; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_load_http_major: { + switch (llhttp__internal__c_load_http_major(state, p, endp)) { + case 0: + goto s_n_llhttp__internal__n_invoke_load_http_minor; + case 1: + goto s_n_llhttp__internal__n_invoke_load_http_minor_1; + case 2: + goto s_n_llhttp__internal__n_invoke_load_http_minor_2; + default: + goto s_n_llhttp__internal__n_span_end_llhttp__on_version; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_test_lenient_flags_23: { + switch (llhttp__internal__c_test_lenient_flags_23(state, p, endp)) { + case 1: + goto s_n_llhttp__internal__n_span_end_llhttp__on_version_1; + default: + goto s_n_llhttp__internal__n_invoke_load_http_major; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_store_http_minor: { + switch (llhttp__internal__c_store_http_minor(state, p, endp, match)) { + default: + goto s_n_llhttp__internal__n_invoke_test_lenient_flags_23; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_span_end_llhttp__on_version_2: { + const unsigned char* start; + int err; + + start = state->_span_pos0; + state->_span_pos0 = NULL; + err = llhttp__on_version(state, start, p); + if (err != 0) { + state->error = err; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_error_71; + return s_error; + } + goto s_n_llhttp__internal__n_error_71; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_span_end_llhttp__on_version_3: { + const unsigned char* start; + int err; + + start = state->_span_pos0; + state->_span_pos0 = NULL; + err = llhttp__on_version(state, start, p); + if (err != 0) { + state->error = err; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_error_72; + return s_error; + } + goto s_n_llhttp__internal__n_error_72; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_store_http_major: { + switch (llhttp__internal__c_store_http_major(state, p, endp, match)) { + default: + goto s_n_llhttp__internal__n_req_http_dot; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_span_end_llhttp__on_version_4: { + const unsigned char* start; + int err; + + start = state->_span_pos0; + state->_span_pos0 = NULL; + err = llhttp__on_version(state, start, p); + if (err != 0) { + state->error = err; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_error_73; + return s_error; + } + goto s_n_llhttp__internal__n_error_73; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_63: { + state->error = 0x8; + state->reason = "Invalid method for HTTP/x.x request"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_load_method: { + switch (llhttp__internal__c_load_method(state, p, endp)) { + case 0: + goto s_n_llhttp__internal__n_span_start_llhttp__on_version; + case 1: + goto s_n_llhttp__internal__n_span_start_llhttp__on_version; + case 2: + goto s_n_llhttp__internal__n_span_start_llhttp__on_version; + case 3: + goto s_n_llhttp__internal__n_span_start_llhttp__on_version; + case 4: + goto s_n_llhttp__internal__n_span_start_llhttp__on_version; + case 5: + goto s_n_llhttp__internal__n_span_start_llhttp__on_version; + case 6: + goto s_n_llhttp__internal__n_span_start_llhttp__on_version; + case 7: + goto s_n_llhttp__internal__n_span_start_llhttp__on_version; + case 8: + goto s_n_llhttp__internal__n_span_start_llhttp__on_version; + case 9: + goto s_n_llhttp__internal__n_span_start_llhttp__on_version; + case 10: + goto s_n_llhttp__internal__n_span_start_llhttp__on_version; + case 11: + goto s_n_llhttp__internal__n_span_start_llhttp__on_version; + case 12: + goto s_n_llhttp__internal__n_span_start_llhttp__on_version; + case 13: + goto s_n_llhttp__internal__n_span_start_llhttp__on_version; + case 14: + goto s_n_llhttp__internal__n_span_start_llhttp__on_version; + case 15: + goto s_n_llhttp__internal__n_span_start_llhttp__on_version; + case 16: + goto s_n_llhttp__internal__n_span_start_llhttp__on_version; + case 17: + goto s_n_llhttp__internal__n_span_start_llhttp__on_version; + case 18: + goto s_n_llhttp__internal__n_span_start_llhttp__on_version; + case 19: + goto s_n_llhttp__internal__n_span_start_llhttp__on_version; + case 20: + goto s_n_llhttp__internal__n_span_start_llhttp__on_version; + case 21: + goto s_n_llhttp__internal__n_span_start_llhttp__on_version; + case 22: + goto s_n_llhttp__internal__n_span_start_llhttp__on_version; + case 23: + goto s_n_llhttp__internal__n_span_start_llhttp__on_version; + case 24: + goto s_n_llhttp__internal__n_span_start_llhttp__on_version; + case 25: + goto s_n_llhttp__internal__n_span_start_llhttp__on_version; + case 26: + goto s_n_llhttp__internal__n_span_start_llhttp__on_version; + case 27: + goto s_n_llhttp__internal__n_span_start_llhttp__on_version; + case 28: + goto s_n_llhttp__internal__n_span_start_llhttp__on_version; + case 29: + goto s_n_llhttp__internal__n_span_start_llhttp__on_version; + case 30: + goto s_n_llhttp__internal__n_span_start_llhttp__on_version; + case 31: + goto s_n_llhttp__internal__n_span_start_llhttp__on_version; + case 32: + goto s_n_llhttp__internal__n_span_start_llhttp__on_version; + case 33: + goto s_n_llhttp__internal__n_span_start_llhttp__on_version; + case 34: + goto s_n_llhttp__internal__n_span_start_llhttp__on_version; + default: + goto s_n_llhttp__internal__n_error_63; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_76: { + state->error = 0x8; + state->reason = "Expected HTTP/"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_74: { + state->error = 0x8; + state->reason = "Expected SOURCE method for ICE/x.x request"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_load_method_2: { + switch (llhttp__internal__c_load_method(state, p, endp)) { + case 33: + goto s_n_llhttp__internal__n_span_start_llhttp__on_version; + default: + goto s_n_llhttp__internal__n_error_74; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_75: { + state->error = 0x8; + state->reason = "Invalid method for RTSP/x.x request"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_load_method_3: { + switch (llhttp__internal__c_load_method(state, p, endp)) { + case 1: + goto s_n_llhttp__internal__n_span_start_llhttp__on_version; + case 3: + goto s_n_llhttp__internal__n_span_start_llhttp__on_version; + case 6: + goto s_n_llhttp__internal__n_span_start_llhttp__on_version; + case 35: + goto s_n_llhttp__internal__n_span_start_llhttp__on_version; + case 36: + goto s_n_llhttp__internal__n_span_start_llhttp__on_version; + case 37: + goto s_n_llhttp__internal__n_span_start_llhttp__on_version; + case 38: + goto s_n_llhttp__internal__n_span_start_llhttp__on_version; + case 39: + goto s_n_llhttp__internal__n_span_start_llhttp__on_version; + case 40: + goto s_n_llhttp__internal__n_span_start_llhttp__on_version; + case 41: + goto s_n_llhttp__internal__n_span_start_llhttp__on_version; + case 42: + goto s_n_llhttp__internal__n_span_start_llhttp__on_version; + case 43: + goto s_n_llhttp__internal__n_span_start_llhttp__on_version; + case 44: + goto s_n_llhttp__internal__n_span_start_llhttp__on_version; + case 45: + goto s_n_llhttp__internal__n_span_start_llhttp__on_version; + default: + goto s_n_llhttp__internal__n_error_75; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_pause_22: { + state->error = 0x15; + state->reason = "on_url_complete pause"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_req_http_start; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_62: { + state->error = 0x1a; + state->reason = "`on_url_complete` callback error"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_llhttp__on_url_complete_1: { + switch (llhttp__on_url_complete(state, p, endp)) { + case 0: + goto s_n_llhttp__internal__n_req_http_start; + case 21: + goto s_n_llhttp__internal__n_pause_22; + default: + goto s_n_llhttp__internal__n_error_62; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_span_end_llhttp__on_url_5: { + const unsigned char* start; + int err; + + start = state->_span_pos0; + state->_span_pos0 = NULL; + err = llhttp__on_url(state, start, p); + if (err != 0) { + state->error = err; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_url_skip_to_http; + return s_error; + } + goto s_n_llhttp__internal__n_url_skip_to_http; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_span_end_llhttp__on_url_6: { + const unsigned char* start; + int err; + + start = state->_span_pos0; + state->_span_pos0 = NULL; + err = llhttp__on_url(state, start, p); + if (err != 0) { + state->error = err; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_url_skip_to_http09; + return s_error; + } + goto s_n_llhttp__internal__n_url_skip_to_http09; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_span_end_llhttp__on_url_7: { + const unsigned char* start; + int err; + + start = state->_span_pos0; + state->_span_pos0 = NULL; + err = llhttp__on_url(state, start, p); + if (err != 0) { + state->error = err; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_url_skip_lf_to_http09; + return s_error; + } + goto s_n_llhttp__internal__n_url_skip_lf_to_http09; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_span_end_llhttp__on_url_8: { + const unsigned char* start; + int err; + + start = state->_span_pos0; + state->_span_pos0 = NULL; + err = llhttp__on_url(state, start, p); + if (err != 0) { + state->error = err; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_url_skip_to_http; + return s_error; + } + goto s_n_llhttp__internal__n_url_skip_to_http; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_77: { + state->error = 0x7; + state->reason = "Invalid char in url fragment start"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_span_end_llhttp__on_url_9: { + const unsigned char* start; + int err; + + start = state->_span_pos0; + state->_span_pos0 = NULL; + err = llhttp__on_url(state, start, p); + if (err != 0) { + state->error = err; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_url_skip_to_http09; + return s_error; + } + goto s_n_llhttp__internal__n_url_skip_to_http09; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_span_end_llhttp__on_url_10: { + const unsigned char* start; + int err; + + start = state->_span_pos0; + state->_span_pos0 = NULL; + err = llhttp__on_url(state, start, p); + if (err != 0) { + state->error = err; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_url_skip_lf_to_http09; + return s_error; + } + goto s_n_llhttp__internal__n_url_skip_lf_to_http09; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_span_end_llhttp__on_url_11: { + const unsigned char* start; + int err; + + start = state->_span_pos0; + state->_span_pos0 = NULL; + err = llhttp__on_url(state, start, p); + if (err != 0) { + state->error = err; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_url_skip_to_http; + return s_error; + } + goto s_n_llhttp__internal__n_url_skip_to_http; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_78: { + state->error = 0x7; + state->reason = "Invalid char in url query"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_79: { + state->error = 0x7; + state->reason = "Invalid char in url path"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_span_end_llhttp__on_url: { + const unsigned char* start; + int err; + + start = state->_span_pos0; + state->_span_pos0 = NULL; + err = llhttp__on_url(state, start, p); + if (err != 0) { + state->error = err; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_url_skip_to_http09; + return s_error; + } + goto s_n_llhttp__internal__n_url_skip_to_http09; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_span_end_llhttp__on_url_1: { + const unsigned char* start; + int err; + + start = state->_span_pos0; + state->_span_pos0 = NULL; + err = llhttp__on_url(state, start, p); + if (err != 0) { + state->error = err; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_url_skip_lf_to_http09; + return s_error; + } + goto s_n_llhttp__internal__n_url_skip_lf_to_http09; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_span_end_llhttp__on_url_2: { + const unsigned char* start; + int err; + + start = state->_span_pos0; + state->_span_pos0 = NULL; + err = llhttp__on_url(state, start, p); + if (err != 0) { + state->error = err; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_url_skip_to_http; + return s_error; + } + goto s_n_llhttp__internal__n_url_skip_to_http; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_span_end_llhttp__on_url_12: { + const unsigned char* start; + int err; + + start = state->_span_pos0; + state->_span_pos0 = NULL; + err = llhttp__on_url(state, start, p); + if (err != 0) { + state->error = err; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_url_skip_to_http09; + return s_error; + } + goto s_n_llhttp__internal__n_url_skip_to_http09; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_span_end_llhttp__on_url_13: { + const unsigned char* start; + int err; + + start = state->_span_pos0; + state->_span_pos0 = NULL; + err = llhttp__on_url(state, start, p); + if (err != 0) { + state->error = err; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_url_skip_lf_to_http09; + return s_error; + } + goto s_n_llhttp__internal__n_url_skip_lf_to_http09; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_span_end_llhttp__on_url_14: { + const unsigned char* start; + int err; + + start = state->_span_pos0; + state->_span_pos0 = NULL; + err = llhttp__on_url(state, start, p); + if (err != 0) { + state->error = err; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_url_skip_to_http; + return s_error; + } + goto s_n_llhttp__internal__n_url_skip_to_http; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_80: { + state->error = 0x7; + state->reason = "Double @ in url"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_81: { + state->error = 0x7; + state->reason = "Unexpected char in url server"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_82: { + state->error = 0x7; + state->reason = "Unexpected char in url server"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_83: { + state->error = 0x7; + state->reason = "Unexpected char in url schema"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_84: { + state->error = 0x7; + state->reason = "Unexpected char in url schema"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_85: { + state->error = 0x7; + state->reason = "Unexpected start char in url"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_is_equal_method: { + switch (llhttp__internal__c_is_equal_method(state, p, endp)) { + case 0: + goto s_n_llhttp__internal__n_url_entry_normal; + default: + goto s_n_llhttp__internal__n_url_entry_connect; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_86: { + state->error = 0x6; + state->reason = "Expected space after method"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_pause_26: { + state->error = 0x15; + state->reason = "on_method_complete pause"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_req_first_space_before_url; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_105: { + state->error = 0x20; + state->reason = "`on_method_complete` callback error"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_span_end_llhttp__on_method_2: { + const unsigned char* start; + int err; + + start = state->_span_pos0; + state->_span_pos0 = NULL; + err = llhttp__on_method(state, start, p); + if (err != 0) { + state->error = err; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_llhttp__on_method_complete_1; + return s_error; + } + goto s_n_llhttp__internal__n_invoke_llhttp__on_method_complete_1; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_store_method_1: { + switch (llhttp__internal__c_store_method(state, p, endp, match)) { + default: + goto s_n_llhttp__internal__n_span_end_llhttp__on_method_2; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_106: { + state->error = 0x6; + state->reason = "Invalid method encountered"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_98: { + state->error = 0xd; + state->reason = "Invalid status code"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_96: { + state->error = 0xd; + state->reason = "Invalid status code"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_94: { + state->error = 0xd; + state->reason = "Invalid status code"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_pause_24: { + state->error = 0x15; + state->reason = "on_status_complete pause"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_headers_start; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_90: { + state->error = 0x1b; + state->reason = "`on_status_complete` callback error"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_llhttp__on_status_complete: { + switch (llhttp__on_status_complete(state, p, endp)) { + case 0: + goto s_n_llhttp__internal__n_headers_start; + case 21: + goto s_n_llhttp__internal__n_pause_24; + default: + goto s_n_llhttp__internal__n_error_90; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_89: { + state->error = 0xd; + state->reason = "Invalid response status"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_test_lenient_flags_27: { + switch (llhttp__internal__c_test_lenient_flags_1(state, p, endp)) { + case 1: + goto s_n_llhttp__internal__n_invoke_llhttp__on_status_complete; + default: + goto s_n_llhttp__internal__n_error_89; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_91: { + state->error = 0x2; + state->reason = "Expected LF after CR"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_test_lenient_flags_28: { + switch (llhttp__internal__c_test_lenient_flags_8(state, p, endp)) { + case 1: + goto s_n_llhttp__internal__n_invoke_llhttp__on_status_complete; + default: + goto s_n_llhttp__internal__n_error_91; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_92: { + state->error = 0x19; + state->reason = "Missing expected CR after response line"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_span_end_llhttp__on_status: { + const unsigned char* start; + int err; + + start = state->_span_pos0; + state->_span_pos0 = NULL; + err = llhttp__on_status(state, start, p); + if (err != 0) { + state->error = err; + state->error_pos = (const char*) (p + 1); + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_test_lenient_flags_29; + return s_error; + } + p++; + goto s_n_llhttp__internal__n_invoke_test_lenient_flags_29; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_span_end_llhttp__on_status_1: { + const unsigned char* start; + int err; + + start = state->_span_pos0; + state->_span_pos0 = NULL; + err = llhttp__on_status(state, start, p); + if (err != 0) { + state->error = err; + state->error_pos = (const char*) (p + 1); + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_res_line_almost_done; + return s_error; + } + p++; + goto s_n_llhttp__internal__n_res_line_almost_done; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_93: { + state->error = 0xd; + state->reason = "Invalid response status"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_mul_add_status_code_2: { + switch (llhttp__internal__c_mul_add_status_code(state, p, endp, match)) { + case 1: + goto s_n_llhttp__internal__n_error_94; + default: + goto s_n_llhttp__internal__n_res_status_code_otherwise; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_95: { + state->error = 0xd; + state->reason = "Invalid status code"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_mul_add_status_code_1: { + switch (llhttp__internal__c_mul_add_status_code(state, p, endp, match)) { + case 1: + goto s_n_llhttp__internal__n_error_96; + default: + goto s_n_llhttp__internal__n_res_status_code_digit_3; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_97: { + state->error = 0xd; + state->reason = "Invalid status code"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_mul_add_status_code: { + switch (llhttp__internal__c_mul_add_status_code(state, p, endp, match)) { + case 1: + goto s_n_llhttp__internal__n_error_98; + default: + goto s_n_llhttp__internal__n_res_status_code_digit_2; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_99: { + state->error = 0xd; + state->reason = "Invalid status code"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_update_status_code: { + switch (llhttp__internal__c_update_status_code(state, p, endp)) { + default: + goto s_n_llhttp__internal__n_res_status_code_digit_1; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_100: { + state->error = 0x9; + state->reason = "Expected space after version"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_pause_25: { + state->error = 0x15; + state->reason = "on_version_complete pause"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_res_after_version; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_88: { + state->error = 0x21; + state->reason = "`on_version_complete` callback error"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_span_end_llhttp__on_version_6: { + const unsigned char* start; + int err; + + start = state->_span_pos0; + state->_span_pos0 = NULL; + err = llhttp__on_version(state, start, p); + if (err != 0) { + state->error = err; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_llhttp__on_version_complete_1; + return s_error; + } + goto s_n_llhttp__internal__n_invoke_llhttp__on_version_complete_1; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_span_end_llhttp__on_version_5: { + const unsigned char* start; + int err; + + start = state->_span_pos0; + state->_span_pos0 = NULL; + err = llhttp__on_version(state, start, p); + if (err != 0) { + state->error = err; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_error_87; + return s_error; + } + goto s_n_llhttp__internal__n_error_87; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_load_http_minor_3: { + switch (llhttp__internal__c_load_http_minor(state, p, endp)) { + case 9: + goto s_n_llhttp__internal__n_span_end_llhttp__on_version_6; + default: + goto s_n_llhttp__internal__n_span_end_llhttp__on_version_5; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_load_http_minor_4: { + switch (llhttp__internal__c_load_http_minor(state, p, endp)) { + case 0: + goto s_n_llhttp__internal__n_span_end_llhttp__on_version_6; + case 1: + goto s_n_llhttp__internal__n_span_end_llhttp__on_version_6; + default: + goto s_n_llhttp__internal__n_span_end_llhttp__on_version_5; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_load_http_minor_5: { + switch (llhttp__internal__c_load_http_minor(state, p, endp)) { + case 0: + goto s_n_llhttp__internal__n_span_end_llhttp__on_version_6; + default: + goto s_n_llhttp__internal__n_span_end_llhttp__on_version_5; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_load_http_major_1: { + switch (llhttp__internal__c_load_http_major(state, p, endp)) { + case 0: + goto s_n_llhttp__internal__n_invoke_load_http_minor_3; + case 1: + goto s_n_llhttp__internal__n_invoke_load_http_minor_4; + case 2: + goto s_n_llhttp__internal__n_invoke_load_http_minor_5; + default: + goto s_n_llhttp__internal__n_span_end_llhttp__on_version_5; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_test_lenient_flags_26: { + switch (llhttp__internal__c_test_lenient_flags_23(state, p, endp)) { + case 1: + goto s_n_llhttp__internal__n_span_end_llhttp__on_version_6; + default: + goto s_n_llhttp__internal__n_invoke_load_http_major_1; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_store_http_minor_1: { + switch (llhttp__internal__c_store_http_minor(state, p, endp, match)) { + default: + goto s_n_llhttp__internal__n_invoke_test_lenient_flags_26; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_span_end_llhttp__on_version_7: { + const unsigned char* start; + int err; + + start = state->_span_pos0; + state->_span_pos0 = NULL; + err = llhttp__on_version(state, start, p); + if (err != 0) { + state->error = err; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_error_101; + return s_error; + } + goto s_n_llhttp__internal__n_error_101; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_span_end_llhttp__on_version_8: { + const unsigned char* start; + int err; + + start = state->_span_pos0; + state->_span_pos0 = NULL; + err = llhttp__on_version(state, start, p); + if (err != 0) { + state->error = err; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_error_102; + return s_error; + } + goto s_n_llhttp__internal__n_error_102; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_store_http_major_1: { + switch (llhttp__internal__c_store_http_major(state, p, endp, match)) { + default: + goto s_n_llhttp__internal__n_res_http_dot; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_span_end_llhttp__on_version_9: { + const unsigned char* start; + int err; + + start = state->_span_pos0; + state->_span_pos0 = NULL; + err = llhttp__on_version(state, start, p); + if (err != 0) { + state->error = err; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_error_103; + return s_error; + } + goto s_n_llhttp__internal__n_error_103; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_107: { + state->error = 0x8; + state->reason = "Expected HTTP/"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_pause_23: { + state->error = 0x15; + state->reason = "on_method_complete pause"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_req_first_space_before_url; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_1: { + state->error = 0x20; + state->reason = "`on_method_complete` callback error"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_span_end_llhttp__on_method: { + const unsigned char* start; + int err; + + start = state->_span_pos0; + state->_span_pos0 = NULL; + err = llhttp__on_method(state, start, p); + if (err != 0) { + state->error = err; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_llhttp__on_method_complete; + return s_error; + } + goto s_n_llhttp__internal__n_invoke_llhttp__on_method_complete; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_update_type: { + switch (llhttp__internal__c_update_type(state, p, endp)) { + default: + goto s_n_llhttp__internal__n_span_end_llhttp__on_method; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_store_method: { + switch (llhttp__internal__c_store_method(state, p, endp, match)) { + default: + goto s_n_llhttp__internal__n_invoke_update_type; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_104: { + state->error = 0x8; + state->reason = "Invalid word encountered"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_span_end_llhttp__on_method_1: { + const unsigned char* start; + int err; + + start = state->_span_pos0; + state->_span_pos0 = NULL; + err = llhttp__on_method(state, start, p); + if (err != 0) { + state->error = err; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_update_type_1; + return s_error; + } + goto s_n_llhttp__internal__n_invoke_update_type_1; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_update_type_2: { + switch (llhttp__internal__c_update_type(state, p, endp)) { + default: + goto s_n_llhttp__internal__n_span_start_llhttp__on_method_1; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_pause_27: { + state->error = 0x15; + state->reason = "on_message_begin pause"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_load_type; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error: { + state->error = 0x10; + state->reason = "`on_message_begin` callback error"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_llhttp__on_message_begin: { + switch (llhttp__on_message_begin(state, p, endp)) { + case 0: + goto s_n_llhttp__internal__n_invoke_load_type; + case 21: + goto s_n_llhttp__internal__n_pause_27; + default: + goto s_n_llhttp__internal__n_error; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_pause_28: { + state->error = 0x15; + state->reason = "on_reset pause"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_invoke_update_finish; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_error_108: { + state->error = 0x1f; + state->reason = "`on_reset` callback error"; + state->error_pos = (const char*) p; + state->_current = (void*) (intptr_t) s_error; + return s_error; + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_llhttp__on_reset: { + switch (llhttp__on_reset(state, p, endp)) { + case 0: + goto s_n_llhttp__internal__n_invoke_update_finish; + case 21: + goto s_n_llhttp__internal__n_pause_28; + default: + goto s_n_llhttp__internal__n_error_108; + } + /* UNREACHABLE */; + abort(); + } + s_n_llhttp__internal__n_invoke_load_initial_message_completed: { + switch (llhttp__internal__c_load_initial_message_completed(state, p, endp)) { + case 1: + goto s_n_llhttp__internal__n_invoke_llhttp__on_reset; + default: + goto s_n_llhttp__internal__n_invoke_update_finish; + } + /* UNREACHABLE */; + abort(); + } +} + +int llhttp__internal_execute(llhttp__internal_t* state, const char* p, const char* endp) { + llparse_state_t next; + + /* check lingering errors */ + if (state->error != 0) { + return state->error; + } + + /* restart spans */ + if (state->_span_pos0 != NULL) { + state->_span_pos0 = (void*) p; + } + + next = llhttp__internal__run(state, (const unsigned char*) p, (const unsigned char*) endp); + if (next == s_error) { + return state->error; + } + state->_current = (void*) (intptr_t) next; + + /* execute spans */ + if (state->_span_pos0 != NULL) { + int error; + + error = ((llhttp__internal__span_cb) state->_span_cb0)(state, state->_span_pos0, (const char*) endp); + if (error != 0) { + state->error = error; + state->error_pos = endp; + return error; + } + } + + return 0; +} \ No newline at end of file diff --git a/vendor/llhttp/build/llhttp.h b/vendor/llhttp/build/llhttp.h new file mode 100644 index 0000000..46a7213 --- /dev/null +++ b/vendor/llhttp/build/llhttp.h @@ -0,0 +1,898 @@ + +#ifndef INCLUDE_LLHTTP_H_ +#define INCLUDE_LLHTTP_H_ + +#define LLHTTP_VERSION_MAJOR 9 +#define LLHTTP_VERSION_MINOR 1 +#define LLHTTP_VERSION_PATCH 3 + +#ifndef INCLUDE_LLHTTP_ITSELF_H_ +#define INCLUDE_LLHTTP_ITSELF_H_ +#ifdef __cplusplus +extern "C" { +#endif + +#include + +typedef struct llhttp__internal_s llhttp__internal_t; +struct llhttp__internal_s { + int32_t _index; + void* _span_pos0; + void* _span_cb0; + int32_t error; + const char* reason; + const char* error_pos; + void* data; + void* _current; + uint64_t content_length; + uint8_t type; + uint8_t method; + uint8_t http_major; + uint8_t http_minor; + uint8_t header_state; + uint16_t lenient_flags; + uint8_t upgrade; + uint8_t finish; + uint16_t flags; + uint16_t status_code; + uint8_t initial_message_completed; + void* settings; +}; + +int llhttp__internal_init(llhttp__internal_t* s); +int llhttp__internal_execute(llhttp__internal_t* s, const char* p, const char* endp); + +#ifdef __cplusplus +} /* extern "C" */ +#endif +#endif /* INCLUDE_LLHTTP_ITSELF_H_ */ + + +#ifndef LLLLHTTP_C_HEADERS_ +#define LLLLHTTP_C_HEADERS_ +#ifdef __cplusplus +extern "C" { +#endif + +enum llhttp_errno { + HPE_OK = 0, + HPE_INTERNAL = 1, + HPE_STRICT = 2, + HPE_CR_EXPECTED = 25, + HPE_LF_EXPECTED = 3, + HPE_UNEXPECTED_CONTENT_LENGTH = 4, + HPE_UNEXPECTED_SPACE = 30, + HPE_CLOSED_CONNECTION = 5, + HPE_INVALID_METHOD = 6, + HPE_INVALID_URL = 7, + HPE_INVALID_CONSTANT = 8, + HPE_INVALID_VERSION = 9, + HPE_INVALID_HEADER_TOKEN = 10, + HPE_INVALID_CONTENT_LENGTH = 11, + HPE_INVALID_CHUNK_SIZE = 12, + HPE_INVALID_STATUS = 13, + HPE_INVALID_EOF_STATE = 14, + HPE_INVALID_TRANSFER_ENCODING = 15, + HPE_CB_MESSAGE_BEGIN = 16, + HPE_CB_HEADERS_COMPLETE = 17, + HPE_CB_MESSAGE_COMPLETE = 18, + HPE_CB_CHUNK_HEADER = 19, + HPE_CB_CHUNK_COMPLETE = 20, + HPE_PAUSED = 21, + HPE_PAUSED_UPGRADE = 22, + HPE_PAUSED_H2_UPGRADE = 23, + HPE_USER = 24, + HPE_CB_URL_COMPLETE = 26, + HPE_CB_STATUS_COMPLETE = 27, + HPE_CB_METHOD_COMPLETE = 32, + HPE_CB_VERSION_COMPLETE = 33, + HPE_CB_HEADER_FIELD_COMPLETE = 28, + HPE_CB_HEADER_VALUE_COMPLETE = 29, + HPE_CB_CHUNK_EXTENSION_NAME_COMPLETE = 34, + HPE_CB_CHUNK_EXTENSION_VALUE_COMPLETE = 35, + HPE_CB_RESET = 31 +}; +typedef enum llhttp_errno llhttp_errno_t; + +enum llhttp_flags { + F_CONNECTION_KEEP_ALIVE = 0x1, + F_CONNECTION_CLOSE = 0x2, + F_CONNECTION_UPGRADE = 0x4, + F_CHUNKED = 0x8, + F_UPGRADE = 0x10, + F_CONTENT_LENGTH = 0x20, + F_SKIPBODY = 0x40, + F_TRAILING = 0x80, + F_TRANSFER_ENCODING = 0x200 +}; +typedef enum llhttp_flags llhttp_flags_t; + +enum llhttp_lenient_flags { + LENIENT_HEADERS = 0x1, + LENIENT_CHUNKED_LENGTH = 0x2, + LENIENT_KEEP_ALIVE = 0x4, + LENIENT_TRANSFER_ENCODING = 0x8, + LENIENT_VERSION = 0x10, + LENIENT_DATA_AFTER_CLOSE = 0x20, + LENIENT_OPTIONAL_LF_AFTER_CR = 0x40, + LENIENT_OPTIONAL_CRLF_AFTER_CHUNK = 0x80, + LENIENT_OPTIONAL_CR_BEFORE_LF = 0x100, + LENIENT_SPACES_AFTER_CHUNK_SIZE = 0x200 +}; +typedef enum llhttp_lenient_flags llhttp_lenient_flags_t; + +enum llhttp_type { + HTTP_BOTH = 0, + HTTP_REQUEST = 1, + HTTP_RESPONSE = 2 +}; +typedef enum llhttp_type llhttp_type_t; + +enum llhttp_finish { + HTTP_FINISH_SAFE = 0, + HTTP_FINISH_SAFE_WITH_CB = 1, + HTTP_FINISH_UNSAFE = 2 +}; +typedef enum llhttp_finish llhttp_finish_t; + +enum llhttp_method { + HTTP_DELETE = 0, + HTTP_GET = 1, + HTTP_HEAD = 2, + HTTP_POST = 3, + HTTP_PUT = 4, + HTTP_CONNECT = 5, + HTTP_OPTIONS = 6, + HTTP_TRACE = 7, + HTTP_COPY = 8, + HTTP_LOCK = 9, + HTTP_MKCOL = 10, + HTTP_MOVE = 11, + HTTP_PROPFIND = 12, + HTTP_PROPPATCH = 13, + HTTP_SEARCH = 14, + HTTP_UNLOCK = 15, + HTTP_BIND = 16, + HTTP_REBIND = 17, + HTTP_UNBIND = 18, + HTTP_ACL = 19, + HTTP_REPORT = 20, + HTTP_MKACTIVITY = 21, + HTTP_CHECKOUT = 22, + HTTP_MERGE = 23, + HTTP_MSEARCH = 24, + HTTP_NOTIFY = 25, + HTTP_SUBSCRIBE = 26, + HTTP_UNSUBSCRIBE = 27, + HTTP_PATCH = 28, + HTTP_PURGE = 29, + HTTP_MKCALENDAR = 30, + HTTP_LINK = 31, + HTTP_UNLINK = 32, + HTTP_SOURCE = 33, + HTTP_PRI = 34, + HTTP_DESCRIBE = 35, + HTTP_ANNOUNCE = 36, + HTTP_SETUP = 37, + HTTP_PLAY = 38, + HTTP_PAUSE = 39, + HTTP_TEARDOWN = 40, + HTTP_GET_PARAMETER = 41, + HTTP_SET_PARAMETER = 42, + HTTP_REDIRECT = 43, + HTTP_RECORD = 44, + HTTP_FLUSH = 45 +}; +typedef enum llhttp_method llhttp_method_t; + +enum llhttp_status { + HTTP_STATUS_CONTINUE = 100, + HTTP_STATUS_SWITCHING_PROTOCOLS = 101, + HTTP_STATUS_PROCESSING = 102, + HTTP_STATUS_EARLY_HINTS = 103, + HTTP_STATUS_RESPONSE_IS_STALE = 110, + HTTP_STATUS_REVALIDATION_FAILED = 111, + HTTP_STATUS_DISCONNECTED_OPERATION = 112, + HTTP_STATUS_HEURISTIC_EXPIRATION = 113, + HTTP_STATUS_MISCELLANEOUS_WARNING = 199, + HTTP_STATUS_OK = 200, + HTTP_STATUS_CREATED = 201, + HTTP_STATUS_ACCEPTED = 202, + HTTP_STATUS_NON_AUTHORITATIVE_INFORMATION = 203, + HTTP_STATUS_NO_CONTENT = 204, + HTTP_STATUS_RESET_CONTENT = 205, + HTTP_STATUS_PARTIAL_CONTENT = 206, + HTTP_STATUS_MULTI_STATUS = 207, + HTTP_STATUS_ALREADY_REPORTED = 208, + HTTP_STATUS_TRANSFORMATION_APPLIED = 214, + HTTP_STATUS_IM_USED = 226, + HTTP_STATUS_MISCELLANEOUS_PERSISTENT_WARNING = 299, + HTTP_STATUS_MULTIPLE_CHOICES = 300, + HTTP_STATUS_MOVED_PERMANENTLY = 301, + HTTP_STATUS_FOUND = 302, + HTTP_STATUS_SEE_OTHER = 303, + HTTP_STATUS_NOT_MODIFIED = 304, + HTTP_STATUS_USE_PROXY = 305, + HTTP_STATUS_SWITCH_PROXY = 306, + HTTP_STATUS_TEMPORARY_REDIRECT = 307, + HTTP_STATUS_PERMANENT_REDIRECT = 308, + HTTP_STATUS_BAD_REQUEST = 400, + HTTP_STATUS_UNAUTHORIZED = 401, + HTTP_STATUS_PAYMENT_REQUIRED = 402, + HTTP_STATUS_FORBIDDEN = 403, + HTTP_STATUS_NOT_FOUND = 404, + HTTP_STATUS_METHOD_NOT_ALLOWED = 405, + HTTP_STATUS_NOT_ACCEPTABLE = 406, + HTTP_STATUS_PROXY_AUTHENTICATION_REQUIRED = 407, + HTTP_STATUS_REQUEST_TIMEOUT = 408, + HTTP_STATUS_CONFLICT = 409, + HTTP_STATUS_GONE = 410, + HTTP_STATUS_LENGTH_REQUIRED = 411, + HTTP_STATUS_PRECONDITION_FAILED = 412, + HTTP_STATUS_PAYLOAD_TOO_LARGE = 413, + HTTP_STATUS_URI_TOO_LONG = 414, + HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE = 415, + HTTP_STATUS_RANGE_NOT_SATISFIABLE = 416, + HTTP_STATUS_EXPECTATION_FAILED = 417, + HTTP_STATUS_IM_A_TEAPOT = 418, + HTTP_STATUS_PAGE_EXPIRED = 419, + HTTP_STATUS_ENHANCE_YOUR_CALM = 420, + HTTP_STATUS_MISDIRECTED_REQUEST = 421, + HTTP_STATUS_UNPROCESSABLE_ENTITY = 422, + HTTP_STATUS_LOCKED = 423, + HTTP_STATUS_FAILED_DEPENDENCY = 424, + HTTP_STATUS_TOO_EARLY = 425, + HTTP_STATUS_UPGRADE_REQUIRED = 426, + HTTP_STATUS_PRECONDITION_REQUIRED = 428, + HTTP_STATUS_TOO_MANY_REQUESTS = 429, + HTTP_STATUS_REQUEST_HEADER_FIELDS_TOO_LARGE_UNOFFICIAL = 430, + HTTP_STATUS_REQUEST_HEADER_FIELDS_TOO_LARGE = 431, + HTTP_STATUS_LOGIN_TIMEOUT = 440, + HTTP_STATUS_NO_RESPONSE = 444, + HTTP_STATUS_RETRY_WITH = 449, + HTTP_STATUS_BLOCKED_BY_PARENTAL_CONTROL = 450, + HTTP_STATUS_UNAVAILABLE_FOR_LEGAL_REASONS = 451, + HTTP_STATUS_CLIENT_CLOSED_LOAD_BALANCED_REQUEST = 460, + HTTP_STATUS_INVALID_X_FORWARDED_FOR = 463, + HTTP_STATUS_REQUEST_HEADER_TOO_LARGE = 494, + HTTP_STATUS_SSL_CERTIFICATE_ERROR = 495, + HTTP_STATUS_SSL_CERTIFICATE_REQUIRED = 496, + HTTP_STATUS_HTTP_REQUEST_SENT_TO_HTTPS_PORT = 497, + HTTP_STATUS_INVALID_TOKEN = 498, + HTTP_STATUS_CLIENT_CLOSED_REQUEST = 499, + HTTP_STATUS_INTERNAL_SERVER_ERROR = 500, + HTTP_STATUS_NOT_IMPLEMENTED = 501, + HTTP_STATUS_BAD_GATEWAY = 502, + HTTP_STATUS_SERVICE_UNAVAILABLE = 503, + HTTP_STATUS_GATEWAY_TIMEOUT = 504, + HTTP_STATUS_HTTP_VERSION_NOT_SUPPORTED = 505, + HTTP_STATUS_VARIANT_ALSO_NEGOTIATES = 506, + HTTP_STATUS_INSUFFICIENT_STORAGE = 507, + HTTP_STATUS_LOOP_DETECTED = 508, + HTTP_STATUS_BANDWIDTH_LIMIT_EXCEEDED = 509, + HTTP_STATUS_NOT_EXTENDED = 510, + HTTP_STATUS_NETWORK_AUTHENTICATION_REQUIRED = 511, + HTTP_STATUS_WEB_SERVER_UNKNOWN_ERROR = 520, + HTTP_STATUS_WEB_SERVER_IS_DOWN = 521, + HTTP_STATUS_CONNECTION_TIMEOUT = 522, + HTTP_STATUS_ORIGIN_IS_UNREACHABLE = 523, + HTTP_STATUS_TIMEOUT_OCCURED = 524, + HTTP_STATUS_SSL_HANDSHAKE_FAILED = 525, + HTTP_STATUS_INVALID_SSL_CERTIFICATE = 526, + HTTP_STATUS_RAILGUN_ERROR = 527, + HTTP_STATUS_SITE_IS_OVERLOADED = 529, + HTTP_STATUS_SITE_IS_FROZEN = 530, + HTTP_STATUS_IDENTITY_PROVIDER_AUTHENTICATION_ERROR = 561, + HTTP_STATUS_NETWORK_READ_TIMEOUT = 598, + HTTP_STATUS_NETWORK_CONNECT_TIMEOUT = 599 +}; +typedef enum llhttp_status llhttp_status_t; + +#define HTTP_ERRNO_MAP(XX) \ + XX(0, OK, OK) \ + XX(1, INTERNAL, INTERNAL) \ + XX(2, STRICT, STRICT) \ + XX(25, CR_EXPECTED, CR_EXPECTED) \ + XX(3, LF_EXPECTED, LF_EXPECTED) \ + XX(4, UNEXPECTED_CONTENT_LENGTH, UNEXPECTED_CONTENT_LENGTH) \ + XX(30, UNEXPECTED_SPACE, UNEXPECTED_SPACE) \ + XX(5, CLOSED_CONNECTION, CLOSED_CONNECTION) \ + XX(6, INVALID_METHOD, INVALID_METHOD) \ + XX(7, INVALID_URL, INVALID_URL) \ + XX(8, INVALID_CONSTANT, INVALID_CONSTANT) \ + XX(9, INVALID_VERSION, INVALID_VERSION) \ + XX(10, INVALID_HEADER_TOKEN, INVALID_HEADER_TOKEN) \ + XX(11, INVALID_CONTENT_LENGTH, INVALID_CONTENT_LENGTH) \ + XX(12, INVALID_CHUNK_SIZE, INVALID_CHUNK_SIZE) \ + XX(13, INVALID_STATUS, INVALID_STATUS) \ + XX(14, INVALID_EOF_STATE, INVALID_EOF_STATE) \ + XX(15, INVALID_TRANSFER_ENCODING, INVALID_TRANSFER_ENCODING) \ + XX(16, CB_MESSAGE_BEGIN, CB_MESSAGE_BEGIN) \ + XX(17, CB_HEADERS_COMPLETE, CB_HEADERS_COMPLETE) \ + XX(18, CB_MESSAGE_COMPLETE, CB_MESSAGE_COMPLETE) \ + XX(19, CB_CHUNK_HEADER, CB_CHUNK_HEADER) \ + XX(20, CB_CHUNK_COMPLETE, CB_CHUNK_COMPLETE) \ + XX(21, PAUSED, PAUSED) \ + XX(22, PAUSED_UPGRADE, PAUSED_UPGRADE) \ + XX(23, PAUSED_H2_UPGRADE, PAUSED_H2_UPGRADE) \ + XX(24, USER, USER) \ + XX(26, CB_URL_COMPLETE, CB_URL_COMPLETE) \ + XX(27, CB_STATUS_COMPLETE, CB_STATUS_COMPLETE) \ + XX(32, CB_METHOD_COMPLETE, CB_METHOD_COMPLETE) \ + XX(33, CB_VERSION_COMPLETE, CB_VERSION_COMPLETE) \ + XX(28, CB_HEADER_FIELD_COMPLETE, CB_HEADER_FIELD_COMPLETE) \ + XX(29, CB_HEADER_VALUE_COMPLETE, CB_HEADER_VALUE_COMPLETE) \ + XX(34, CB_CHUNK_EXTENSION_NAME_COMPLETE, CB_CHUNK_EXTENSION_NAME_COMPLETE) \ + XX(35, CB_CHUNK_EXTENSION_VALUE_COMPLETE, CB_CHUNK_EXTENSION_VALUE_COMPLETE) \ + XX(31, CB_RESET, CB_RESET) \ + + +#define HTTP_METHOD_MAP(XX) \ + XX(0, DELETE, DELETE) \ + XX(1, GET, GET) \ + XX(2, HEAD, HEAD) \ + XX(3, POST, POST) \ + XX(4, PUT, PUT) \ + XX(5, CONNECT, CONNECT) \ + XX(6, OPTIONS, OPTIONS) \ + XX(7, TRACE, TRACE) \ + XX(8, COPY, COPY) \ + XX(9, LOCK, LOCK) \ + XX(10, MKCOL, MKCOL) \ + XX(11, MOVE, MOVE) \ + XX(12, PROPFIND, PROPFIND) \ + XX(13, PROPPATCH, PROPPATCH) \ + XX(14, SEARCH, SEARCH) \ + XX(15, UNLOCK, UNLOCK) \ + XX(16, BIND, BIND) \ + XX(17, REBIND, REBIND) \ + XX(18, UNBIND, UNBIND) \ + XX(19, ACL, ACL) \ + XX(20, REPORT, REPORT) \ + XX(21, MKACTIVITY, MKACTIVITY) \ + XX(22, CHECKOUT, CHECKOUT) \ + XX(23, MERGE, MERGE) \ + XX(24, MSEARCH, M-SEARCH) \ + XX(25, NOTIFY, NOTIFY) \ + XX(26, SUBSCRIBE, SUBSCRIBE) \ + XX(27, UNSUBSCRIBE, UNSUBSCRIBE) \ + XX(28, PATCH, PATCH) \ + XX(29, PURGE, PURGE) \ + XX(30, MKCALENDAR, MKCALENDAR) \ + XX(31, LINK, LINK) \ + XX(32, UNLINK, UNLINK) \ + XX(33, SOURCE, SOURCE) \ + + +#define RTSP_METHOD_MAP(XX) \ + XX(1, GET, GET) \ + XX(3, POST, POST) \ + XX(6, OPTIONS, OPTIONS) \ + XX(35, DESCRIBE, DESCRIBE) \ + XX(36, ANNOUNCE, ANNOUNCE) \ + XX(37, SETUP, SETUP) \ + XX(38, PLAY, PLAY) \ + XX(39, PAUSE, PAUSE) \ + XX(40, TEARDOWN, TEARDOWN) \ + XX(41, GET_PARAMETER, GET_PARAMETER) \ + XX(42, SET_PARAMETER, SET_PARAMETER) \ + XX(43, REDIRECT, REDIRECT) \ + XX(44, RECORD, RECORD) \ + XX(45, FLUSH, FLUSH) \ + + +#define HTTP_ALL_METHOD_MAP(XX) \ + XX(0, DELETE, DELETE) \ + XX(1, GET, GET) \ + XX(2, HEAD, HEAD) \ + XX(3, POST, POST) \ + XX(4, PUT, PUT) \ + XX(5, CONNECT, CONNECT) \ + XX(6, OPTIONS, OPTIONS) \ + XX(7, TRACE, TRACE) \ + XX(8, COPY, COPY) \ + XX(9, LOCK, LOCK) \ + XX(10, MKCOL, MKCOL) \ + XX(11, MOVE, MOVE) \ + XX(12, PROPFIND, PROPFIND) \ + XX(13, PROPPATCH, PROPPATCH) \ + XX(14, SEARCH, SEARCH) \ + XX(15, UNLOCK, UNLOCK) \ + XX(16, BIND, BIND) \ + XX(17, REBIND, REBIND) \ + XX(18, UNBIND, UNBIND) \ + XX(19, ACL, ACL) \ + XX(20, REPORT, REPORT) \ + XX(21, MKACTIVITY, MKACTIVITY) \ + XX(22, CHECKOUT, CHECKOUT) \ + XX(23, MERGE, MERGE) \ + XX(24, MSEARCH, M-SEARCH) \ + XX(25, NOTIFY, NOTIFY) \ + XX(26, SUBSCRIBE, SUBSCRIBE) \ + XX(27, UNSUBSCRIBE, UNSUBSCRIBE) \ + XX(28, PATCH, PATCH) \ + XX(29, PURGE, PURGE) \ + XX(30, MKCALENDAR, MKCALENDAR) \ + XX(31, LINK, LINK) \ + XX(32, UNLINK, UNLINK) \ + XX(33, SOURCE, SOURCE) \ + XX(34, PRI, PRI) \ + XX(35, DESCRIBE, DESCRIBE) \ + XX(36, ANNOUNCE, ANNOUNCE) \ + XX(37, SETUP, SETUP) \ + XX(38, PLAY, PLAY) \ + XX(39, PAUSE, PAUSE) \ + XX(40, TEARDOWN, TEARDOWN) \ + XX(41, GET_PARAMETER, GET_PARAMETER) \ + XX(42, SET_PARAMETER, SET_PARAMETER) \ + XX(43, REDIRECT, REDIRECT) \ + XX(44, RECORD, RECORD) \ + XX(45, FLUSH, FLUSH) \ + + +#define HTTP_STATUS_MAP(XX) \ + XX(100, CONTINUE, CONTINUE) \ + XX(101, SWITCHING_PROTOCOLS, SWITCHING_PROTOCOLS) \ + XX(102, PROCESSING, PROCESSING) \ + XX(103, EARLY_HINTS, EARLY_HINTS) \ + XX(110, RESPONSE_IS_STALE, RESPONSE_IS_STALE) \ + XX(111, REVALIDATION_FAILED, REVALIDATION_FAILED) \ + XX(112, DISCONNECTED_OPERATION, DISCONNECTED_OPERATION) \ + XX(113, HEURISTIC_EXPIRATION, HEURISTIC_EXPIRATION) \ + XX(199, MISCELLANEOUS_WARNING, MISCELLANEOUS_WARNING) \ + XX(200, OK, OK) \ + XX(201, CREATED, CREATED) \ + XX(202, ACCEPTED, ACCEPTED) \ + XX(203, NON_AUTHORITATIVE_INFORMATION, NON_AUTHORITATIVE_INFORMATION) \ + XX(204, NO_CONTENT, NO_CONTENT) \ + XX(205, RESET_CONTENT, RESET_CONTENT) \ + XX(206, PARTIAL_CONTENT, PARTIAL_CONTENT) \ + XX(207, MULTI_STATUS, MULTI_STATUS) \ + XX(208, ALREADY_REPORTED, ALREADY_REPORTED) \ + XX(214, TRANSFORMATION_APPLIED, TRANSFORMATION_APPLIED) \ + XX(226, IM_USED, IM_USED) \ + XX(299, MISCELLANEOUS_PERSISTENT_WARNING, MISCELLANEOUS_PERSISTENT_WARNING) \ + XX(300, MULTIPLE_CHOICES, MULTIPLE_CHOICES) \ + XX(301, MOVED_PERMANENTLY, MOVED_PERMANENTLY) \ + XX(302, FOUND, FOUND) \ + XX(303, SEE_OTHER, SEE_OTHER) \ + XX(304, NOT_MODIFIED, NOT_MODIFIED) \ + XX(305, USE_PROXY, USE_PROXY) \ + XX(306, SWITCH_PROXY, SWITCH_PROXY) \ + XX(307, TEMPORARY_REDIRECT, TEMPORARY_REDIRECT) \ + XX(308, PERMANENT_REDIRECT, PERMANENT_REDIRECT) \ + XX(400, BAD_REQUEST, BAD_REQUEST) \ + XX(401, UNAUTHORIZED, UNAUTHORIZED) \ + XX(402, PAYMENT_REQUIRED, PAYMENT_REQUIRED) \ + XX(403, FORBIDDEN, FORBIDDEN) \ + XX(404, NOT_FOUND, NOT_FOUND) \ + XX(405, METHOD_NOT_ALLOWED, METHOD_NOT_ALLOWED) \ + XX(406, NOT_ACCEPTABLE, NOT_ACCEPTABLE) \ + XX(407, PROXY_AUTHENTICATION_REQUIRED, PROXY_AUTHENTICATION_REQUIRED) \ + XX(408, REQUEST_TIMEOUT, REQUEST_TIMEOUT) \ + XX(409, CONFLICT, CONFLICT) \ + XX(410, GONE, GONE) \ + XX(411, LENGTH_REQUIRED, LENGTH_REQUIRED) \ + XX(412, PRECONDITION_FAILED, PRECONDITION_FAILED) \ + XX(413, PAYLOAD_TOO_LARGE, PAYLOAD_TOO_LARGE) \ + XX(414, URI_TOO_LONG, URI_TOO_LONG) \ + XX(415, UNSUPPORTED_MEDIA_TYPE, UNSUPPORTED_MEDIA_TYPE) \ + XX(416, RANGE_NOT_SATISFIABLE, RANGE_NOT_SATISFIABLE) \ + XX(417, EXPECTATION_FAILED, EXPECTATION_FAILED) \ + XX(418, IM_A_TEAPOT, IM_A_TEAPOT) \ + XX(419, PAGE_EXPIRED, PAGE_EXPIRED) \ + XX(420, ENHANCE_YOUR_CALM, ENHANCE_YOUR_CALM) \ + XX(421, MISDIRECTED_REQUEST, MISDIRECTED_REQUEST) \ + XX(422, UNPROCESSABLE_ENTITY, UNPROCESSABLE_ENTITY) \ + XX(423, LOCKED, LOCKED) \ + XX(424, FAILED_DEPENDENCY, FAILED_DEPENDENCY) \ + XX(425, TOO_EARLY, TOO_EARLY) \ + XX(426, UPGRADE_REQUIRED, UPGRADE_REQUIRED) \ + XX(428, PRECONDITION_REQUIRED, PRECONDITION_REQUIRED) \ + XX(429, TOO_MANY_REQUESTS, TOO_MANY_REQUESTS) \ + XX(430, REQUEST_HEADER_FIELDS_TOO_LARGE_UNOFFICIAL, REQUEST_HEADER_FIELDS_TOO_LARGE_UNOFFICIAL) \ + XX(431, REQUEST_HEADER_FIELDS_TOO_LARGE, REQUEST_HEADER_FIELDS_TOO_LARGE) \ + XX(440, LOGIN_TIMEOUT, LOGIN_TIMEOUT) \ + XX(444, NO_RESPONSE, NO_RESPONSE) \ + XX(449, RETRY_WITH, RETRY_WITH) \ + XX(450, BLOCKED_BY_PARENTAL_CONTROL, BLOCKED_BY_PARENTAL_CONTROL) \ + XX(451, UNAVAILABLE_FOR_LEGAL_REASONS, UNAVAILABLE_FOR_LEGAL_REASONS) \ + XX(460, CLIENT_CLOSED_LOAD_BALANCED_REQUEST, CLIENT_CLOSED_LOAD_BALANCED_REQUEST) \ + XX(463, INVALID_X_FORWARDED_FOR, INVALID_X_FORWARDED_FOR) \ + XX(494, REQUEST_HEADER_TOO_LARGE, REQUEST_HEADER_TOO_LARGE) \ + XX(495, SSL_CERTIFICATE_ERROR, SSL_CERTIFICATE_ERROR) \ + XX(496, SSL_CERTIFICATE_REQUIRED, SSL_CERTIFICATE_REQUIRED) \ + XX(497, HTTP_REQUEST_SENT_TO_HTTPS_PORT, HTTP_REQUEST_SENT_TO_HTTPS_PORT) \ + XX(498, INVALID_TOKEN, INVALID_TOKEN) \ + XX(499, CLIENT_CLOSED_REQUEST, CLIENT_CLOSED_REQUEST) \ + XX(500, INTERNAL_SERVER_ERROR, INTERNAL_SERVER_ERROR) \ + XX(501, NOT_IMPLEMENTED, NOT_IMPLEMENTED) \ + XX(502, BAD_GATEWAY, BAD_GATEWAY) \ + XX(503, SERVICE_UNAVAILABLE, SERVICE_UNAVAILABLE) \ + XX(504, GATEWAY_TIMEOUT, GATEWAY_TIMEOUT) \ + XX(505, HTTP_VERSION_NOT_SUPPORTED, HTTP_VERSION_NOT_SUPPORTED) \ + XX(506, VARIANT_ALSO_NEGOTIATES, VARIANT_ALSO_NEGOTIATES) \ + XX(507, INSUFFICIENT_STORAGE, INSUFFICIENT_STORAGE) \ + XX(508, LOOP_DETECTED, LOOP_DETECTED) \ + XX(509, BANDWIDTH_LIMIT_EXCEEDED, BANDWIDTH_LIMIT_EXCEEDED) \ + XX(510, NOT_EXTENDED, NOT_EXTENDED) \ + XX(511, NETWORK_AUTHENTICATION_REQUIRED, NETWORK_AUTHENTICATION_REQUIRED) \ + XX(520, WEB_SERVER_UNKNOWN_ERROR, WEB_SERVER_UNKNOWN_ERROR) \ + XX(521, WEB_SERVER_IS_DOWN, WEB_SERVER_IS_DOWN) \ + XX(522, CONNECTION_TIMEOUT, CONNECTION_TIMEOUT) \ + XX(523, ORIGIN_IS_UNREACHABLE, ORIGIN_IS_UNREACHABLE) \ + XX(524, TIMEOUT_OCCURED, TIMEOUT_OCCURED) \ + XX(525, SSL_HANDSHAKE_FAILED, SSL_HANDSHAKE_FAILED) \ + XX(526, INVALID_SSL_CERTIFICATE, INVALID_SSL_CERTIFICATE) \ + XX(527, RAILGUN_ERROR, RAILGUN_ERROR) \ + XX(529, SITE_IS_OVERLOADED, SITE_IS_OVERLOADED) \ + XX(530, SITE_IS_FROZEN, SITE_IS_FROZEN) \ + XX(561, IDENTITY_PROVIDER_AUTHENTICATION_ERROR, IDENTITY_PROVIDER_AUTHENTICATION_ERROR) \ + XX(598, NETWORK_READ_TIMEOUT, NETWORK_READ_TIMEOUT) \ + XX(599, NETWORK_CONNECT_TIMEOUT, NETWORK_CONNECT_TIMEOUT) \ + + +#ifdef __cplusplus +} /* extern "C" */ +#endif +#endif /* LLLLHTTP_C_HEADERS_ */ + + +#ifndef INCLUDE_LLHTTP_API_H_ +#define INCLUDE_LLHTTP_API_H_ +#ifdef __cplusplus +extern "C" { +#endif +#include + +#if defined(__wasm__) +#define LLHTTP_EXPORT __attribute__((visibility("default"))) +#else +#define LLHTTP_EXPORT +#endif + +typedef llhttp__internal_t llhttp_t; +typedef struct llhttp_settings_s llhttp_settings_t; + +typedef int (*llhttp_data_cb)(llhttp_t*, const char *at, size_t length); +typedef int (*llhttp_cb)(llhttp_t*); + +struct llhttp_settings_s { + /* Possible return values 0, -1, `HPE_PAUSED` */ + llhttp_cb on_message_begin; + + /* Possible return values 0, -1, HPE_USER */ + llhttp_data_cb on_url; + llhttp_data_cb on_status; + llhttp_data_cb on_method; + llhttp_data_cb on_version; + llhttp_data_cb on_header_field; + llhttp_data_cb on_header_value; + llhttp_data_cb on_chunk_extension_name; + llhttp_data_cb on_chunk_extension_value; + + /* Possible return values: + * 0 - Proceed normally + * 1 - Assume that request/response has no body, and proceed to parsing the + * next message + * 2 - Assume absence of body (as above) and make `llhttp_execute()` return + * `HPE_PAUSED_UPGRADE` + * -1 - Error + * `HPE_PAUSED` + */ + llhttp_cb on_headers_complete; + + /* Possible return values 0, -1, HPE_USER */ + llhttp_data_cb on_body; + + /* Possible return values 0, -1, `HPE_PAUSED` */ + llhttp_cb on_message_complete; + llhttp_cb on_url_complete; + llhttp_cb on_status_complete; + llhttp_cb on_method_complete; + llhttp_cb on_version_complete; + llhttp_cb on_header_field_complete; + llhttp_cb on_header_value_complete; + llhttp_cb on_chunk_extension_name_complete; + llhttp_cb on_chunk_extension_value_complete; + + /* When on_chunk_header is called, the current chunk length is stored + * in parser->content_length. + * Possible return values 0, -1, `HPE_PAUSED` + */ + llhttp_cb on_chunk_header; + llhttp_cb on_chunk_complete; + llhttp_cb on_reset; +}; + +/* Initialize the parser with specific type and user settings. + * + * NOTE: lifetime of `settings` has to be at least the same as the lifetime of + * the `parser` here. In practice, `settings` has to be either a static + * variable or be allocated with `malloc`, `new`, etc. + */ +LLHTTP_EXPORT +void llhttp_init(llhttp_t* parser, llhttp_type_t type, + const llhttp_settings_t* settings); + +LLHTTP_EXPORT +llhttp_t* llhttp_alloc(llhttp_type_t type); + +LLHTTP_EXPORT +void llhttp_free(llhttp_t* parser); + +LLHTTP_EXPORT +uint8_t llhttp_get_type(llhttp_t* parser); + +LLHTTP_EXPORT +uint8_t llhttp_get_http_major(llhttp_t* parser); + +LLHTTP_EXPORT +uint8_t llhttp_get_http_minor(llhttp_t* parser); + +LLHTTP_EXPORT +uint8_t llhttp_get_method(llhttp_t* parser); + +LLHTTP_EXPORT +int llhttp_get_status_code(llhttp_t* parser); + +LLHTTP_EXPORT +uint8_t llhttp_get_upgrade(llhttp_t* parser); + +/* Reset an already initialized parser back to the start state, preserving the + * existing parser type, callback settings, user data, and lenient flags. + */ +LLHTTP_EXPORT +void llhttp_reset(llhttp_t* parser); + +/* Initialize the settings object */ +LLHTTP_EXPORT +void llhttp_settings_init(llhttp_settings_t* settings); + +/* Parse full or partial request/response, invoking user callbacks along the + * way. + * + * If any of `llhttp_data_cb` returns errno not equal to `HPE_OK` - the parsing + * interrupts, and such errno is returned from `llhttp_execute()`. If + * `HPE_PAUSED` was used as a errno, the execution can be resumed with + * `llhttp_resume()` call. + * + * In a special case of CONNECT/Upgrade request/response `HPE_PAUSED_UPGRADE` + * is returned after fully parsing the request/response. If the user wishes to + * continue parsing, they need to invoke `llhttp_resume_after_upgrade()`. + * + * NOTE: if this function ever returns a non-pause type error, it will continue + * to return the same error upon each successive call up until `llhttp_init()` + * is called. + */ +LLHTTP_EXPORT +llhttp_errno_t llhttp_execute(llhttp_t* parser, const char* data, size_t len); + +/* This method should be called when the other side has no further bytes to + * send (e.g. shutdown of readable side of the TCP connection.) + * + * Requests without `Content-Length` and other messages might require treating + * all incoming bytes as the part of the body, up to the last byte of the + * connection. This method will invoke `on_message_complete()` callback if the + * request was terminated safely. Otherwise a error code would be returned. + */ +LLHTTP_EXPORT +llhttp_errno_t llhttp_finish(llhttp_t* parser); + +/* Returns `1` if the incoming message is parsed until the last byte, and has + * to be completed by calling `llhttp_finish()` on EOF + */ +LLHTTP_EXPORT +int llhttp_message_needs_eof(const llhttp_t* parser); + +/* Returns `1` if there might be any other messages following the last that was + * successfully parsed. + */ +LLHTTP_EXPORT +int llhttp_should_keep_alive(const llhttp_t* parser); + +/* Make further calls of `llhttp_execute()` return `HPE_PAUSED` and set + * appropriate error reason. + * + * Important: do not call this from user callbacks! User callbacks must return + * `HPE_PAUSED` if pausing is required. + */ +LLHTTP_EXPORT +void llhttp_pause(llhttp_t* parser); + +/* Might be called to resume the execution after the pause in user's callback. + * See `llhttp_execute()` above for details. + * + * Call this only if `llhttp_execute()` returns `HPE_PAUSED`. + */ +LLHTTP_EXPORT +void llhttp_resume(llhttp_t* parser); + +/* Might be called to resume the execution after the pause in user's callback. + * See `llhttp_execute()` above for details. + * + * Call this only if `llhttp_execute()` returns `HPE_PAUSED_UPGRADE` + */ +LLHTTP_EXPORT +void llhttp_resume_after_upgrade(llhttp_t* parser); + +/* Returns the latest return error */ +LLHTTP_EXPORT +llhttp_errno_t llhttp_get_errno(const llhttp_t* parser); + +/* Returns the verbal explanation of the latest returned error. + * + * Note: User callback should set error reason when returning the error. See + * `llhttp_set_error_reason()` for details. + */ +LLHTTP_EXPORT +const char* llhttp_get_error_reason(const llhttp_t* parser); + +/* Assign verbal description to the returned error. Must be called in user + * callbacks right before returning the errno. + * + * Note: `HPE_USER` error code might be useful in user callbacks. + */ +LLHTTP_EXPORT +void llhttp_set_error_reason(llhttp_t* parser, const char* reason); + +/* Returns the pointer to the last parsed byte before the returned error. The + * pointer is relative to the `data` argument of `llhttp_execute()`. + * + * Note: this method might be useful for counting the number of parsed bytes. + */ +LLHTTP_EXPORT +const char* llhttp_get_error_pos(const llhttp_t* parser); + +/* Returns textual name of error code */ +LLHTTP_EXPORT +const char* llhttp_errno_name(llhttp_errno_t err); + +/* Returns textual name of HTTP method */ +LLHTTP_EXPORT +const char* llhttp_method_name(llhttp_method_t method); + +/* Returns textual name of HTTP status */ +LLHTTP_EXPORT +const char* llhttp_status_name(llhttp_status_t status); + +/* Enables/disables lenient header value parsing (disabled by default). + * + * Lenient parsing disables header value token checks, extending llhttp's + * protocol support to highly non-compliant clients/server. No + * `HPE_INVALID_HEADER_TOKEN` will be raised for incorrect header values when + * lenient parsing is "on". + * + * **Enabling this flag can pose a security issue since you will be exposed to + * request smuggling attacks. USE WITH CAUTION!** + */ +LLHTTP_EXPORT +void llhttp_set_lenient_headers(llhttp_t* parser, int enabled); + + +/* Enables/disables lenient handling of conflicting `Transfer-Encoding` and + * `Content-Length` headers (disabled by default). + * + * Normally `llhttp` would error when `Transfer-Encoding` is present in + * conjunction with `Content-Length`. This error is important to prevent HTTP + * request smuggling, but may be less desirable for small number of cases + * involving legacy servers. + * + * **Enabling this flag can pose a security issue since you will be exposed to + * request smuggling attacks. USE WITH CAUTION!** + */ +LLHTTP_EXPORT +void llhttp_set_lenient_chunked_length(llhttp_t* parser, int enabled); + + +/* Enables/disables lenient handling of `Connection: close` and HTTP/1.0 + * requests responses. + * + * Normally `llhttp` would error on (in strict mode) or discard (in loose mode) + * the HTTP request/response after the request/response with `Connection: close` + * and `Content-Length`. This is important to prevent cache poisoning attacks, + * but might interact badly with outdated and insecure clients. With this flag + * the extra request/response will be parsed normally. + * + * **Enabling this flag can pose a security issue since you will be exposed to + * poisoning attacks. USE WITH CAUTION!** + */ +LLHTTP_EXPORT +void llhttp_set_lenient_keep_alive(llhttp_t* parser, int enabled); + +/* Enables/disables lenient handling of `Transfer-Encoding` header. + * + * Normally `llhttp` would error when a `Transfer-Encoding` has `chunked` value + * and another value after it (either in a single header or in multiple + * headers whose value are internally joined using `, `). + * This is mandated by the spec to reliably determine request body size and thus + * avoid request smuggling. + * With this flag the extra value will be parsed normally. + * + * **Enabling this flag can pose a security issue since you will be exposed to + * request smuggling attacks. USE WITH CAUTION!** + */ +LLHTTP_EXPORT +void llhttp_set_lenient_transfer_encoding(llhttp_t* parser, int enabled); + +/* Enables/disables lenient handling of HTTP version. + * + * Normally `llhttp` would error when the HTTP version in the request or status line + * is not `0.9`, `1.0`, `1.1` or `2.0`. + * With this flag the invalid value will be parsed normally. + * + * **Enabling this flag can pose a security issue since you will allow unsupported + * HTTP versions. USE WITH CAUTION!** + */ +LLHTTP_EXPORT +void llhttp_set_lenient_version(llhttp_t* parser, int enabled); + +/* Enables/disables lenient handling of additional data received after a message ends + * and keep-alive is disabled. + * + * Normally `llhttp` would error when additional unexpected data is received if the message + * contains the `Connection` header with `close` value. + * With this flag the extra data will discarded without throwing an error. + * + * **Enabling this flag can pose a security issue since you will be exposed to + * poisoning attacks. USE WITH CAUTION!** + */ +LLHTTP_EXPORT +void llhttp_set_lenient_data_after_close(llhttp_t* parser, int enabled); + +/* Enables/disables lenient handling of incomplete CRLF sequences. + * + * Normally `llhttp` would error when a CR is not followed by LF when terminating the + * request line, the status line, the headers or a chunk header. + * With this flag only a CR is required to terminate such sections. + * + * **Enabling this flag can pose a security issue since you will be exposed to + * request smuggling attacks. USE WITH CAUTION!** + */ +LLHTTP_EXPORT +void llhttp_set_lenient_optional_lf_after_cr(llhttp_t* parser, int enabled); + +/* + * Enables/disables lenient handling of line separators. + * + * Normally `llhttp` would error when a LF is not preceded by CR when terminating the + * request line, the status line, the headers, a chunk header or a chunk data. + * With this flag only a LF is required to terminate such sections. + * + * **Enabling this flag can pose a security issue since you will be exposed to + * request smuggling attacks. USE WITH CAUTION!** + */ +LLHTTP_EXPORT +void llhttp_set_lenient_optional_cr_before_lf(llhttp_t* parser, int enabled); + +/* Enables/disables lenient handling of chunks not separated via CRLF. + * + * Normally `llhttp` would error when after a chunk data a CRLF is missing before + * starting a new chunk. + * With this flag the new chunk can start immediately after the previous one. + * + * **Enabling this flag can pose a security issue since you will be exposed to + * request smuggling attacks. USE WITH CAUTION!** + */ +LLHTTP_EXPORT +void llhttp_set_lenient_optional_crlf_after_chunk(llhttp_t* parser, int enabled); + +/* Enables/disables lenient handling of spaces after chunk size. + * + * Normally `llhttp` would error when after a chunk size is followed by one or more + * spaces are present instead of a CRLF or `;`. + * With this flag this check is disabled. + * + * **Enabling this flag can pose a security issue since you will be exposed to + * request smuggling attacks. USE WITH CAUTION!** + */ +LLHTTP_EXPORT +void llhttp_set_lenient_spaces_after_chunk_size(llhttp_t* parser, int enabled); + +#ifdef __cplusplus +} /* extern "C" */ +#endif +#endif /* INCLUDE_LLHTTP_API_H_ */ + + +#endif /* INCLUDE_LLHTTP_H_ */ diff --git a/vendor/llhttp/docs/releasing.md b/vendor/llhttp/docs/releasing.md new file mode 100644 index 0000000..f83e0f7 --- /dev/null +++ b/vendor/llhttp/docs/releasing.md @@ -0,0 +1,65 @@ +# How to release a new version of llhttp + +## What does releasing involves? + +These are the required steps to release a new version of llhttp: + +1. Increase the version number. +2. Build it locally. +3. Create a new build and push it to GitHub. +4. Create a new release on GitHub release. + +> Do not try to execute the commands in the Makefile manually. This is really error-prone! + +## Which commands to run? + +First of all, make sure you have [GitHub CLI](https://cli.github.com) installed and configured. While this is not strictly necessary, it will make your life way easier. + +As a preliminary check, run the build command and execute the test suite locally: + +``` +npm run build +npm test +``` + +If all goes good, you are ready to go! + +To release a new version of llhttp, first increase the version using `npm` and make sure it also execute the `postversion` script. Unless you have some very specific setup, this should happen automatically, which means the following command will suffice: + +``` +npm version [major|minor|patch] +``` + +The command will increase the version and then will create a new release branch on GitHub. + +> Even thought there is a package on NPM, it is not updated anymore. NEVER RUN `npm publish`! + +It's now time to create the release on GitHub. If you DON'T have GitHub CLI available, skip to the next section, otherwise run the following command: + +``` +npm run github-release +``` + +This command will create a draft release on GitHub and then show it in your browser so you can review and publish it. + +Congratulation, you are all set! + +## Create a GitHub release without GitHub CLI + +> From now on, `$VERSION` will be the new version you are trying to create, including the leading letter, for instance `v6.0.9`. + +If you don't want to or can't use GitHub CLI, you can still create the release on GitHub following this procedure. + +1. Go on GitHub and start creating a new release which targets tag `$VERSION`. Generate the notes using the `Generate release notes` button. + +2. At the bottom of the generated notes, make sure the previous and current version in the notes are correct. + + The last line should be something like this: `**Full Changelog**: https://github.com/nodejs/llhttp/compare/v6.0.8...v6.0.9` + + In this case it says we are creating release `v6.0.9` and we are showing the changes between `v6.0.8` and `v6.0.9`. + +3. Change the target of the release to point to tag `release/$VERSION`. + +4. Review and then publish the release. + +Congratulation, you are all set! \ No newline at end of file diff --git a/vendor/llhttp/examples/wasm.ts b/vendor/llhttp/examples/wasm.ts new file mode 100644 index 0000000..995fed8 --- /dev/null +++ b/vendor/llhttp/examples/wasm.ts @@ -0,0 +1,248 @@ +/** + * A minimal Parser that mimicks a small fraction of the Node.js parser + * API. + * To run: + * - `npm run build-wasm` + * - `npx ts-node examples/wasm.ts` + */ +import { readFileSync } from 'fs'; +import { resolve } from 'path'; +import * as constants from '../build/wasm/constants'; + +const bin = readFileSync(resolve(__dirname, '../build/wasm/llhttp.wasm')); +const mod = new WebAssembly.Module(bin); + +const REQUEST = constants.TYPE.REQUEST; +const RESPONSE = constants.TYPE.RESPONSE; +const kOnMessageBegin = 0; +const kOnHeaders = 1; +const kOnHeadersComplete = 2; +const kOnBody = 3; +const kOnMessageComplete = 4; +const kOnExecute = 5; + +const kPtr = Symbol('kPtr'); +const kUrl = Symbol('kUrl'); +const kStatusMessage = Symbol('kStatusMessage'); +const kHeadersFields = Symbol('kHeadersFields'); +const kHeadersValues = Symbol('kHeadersValues'); +const kBody = Symbol('kBody'); +const kReset = Symbol('kReset'); +const kCheckErr = Symbol('kCheckErr'); + +const cstr = (ptr: number, len: number): string => + Buffer.from(memory.buffer, ptr, len).toString(); + +const wasm_on_message_begin = (p: number) => { + const i = instMap.get(p); + i[kReset](); + return i[kOnMessageBegin](); +}; + +const wasm_on_url = (p: number, at: number, length: number) => { + instMap.get(p)[kUrl] = cstr(at, length); + return 0; +}; + +const wasm_on_status = (p: number, at: number, length: number) => { + instMap.get(p)[kStatusMessage] = cstr(at, length); + return 0; +}; + +const wasm_on_header_field = (p: number, at: number, length: number) => { + const i= instMap.get(p) + i[kHeadersFields].push(cstr(at, length)); + return 0; +}; + +const wasm_on_header_value = (p: number, at: number, length: number) => { + const i = instMap.get(p); + i[kHeadersValues].push(cstr(at, length)); + return 0; +}; + +const wasm_on_headers_complete = (p: number) => { + const i = instMap.get(p); + const type = get_type(p); + const versionMajor = get_version_major(p); + const versionMinor = get_version_minor(p); + const rawHeaders = []; + let method; + let url; + let statusCode; + let statusMessage; + const upgrade = get_upgrade(p); + const shouldKeepAlive = should_keep_alive(p); + + for (let c = 0; c < i[kHeadersFields].length; c++) { + rawHeaders.push(i[kHeadersFields][c], i[kHeadersValues][c]) + } + + if (type === HTTPParser.REQUEST) { + method = constants.METHODS[get_method(p)]; + url = i[kUrl]; + } else if (type === HTTPParser.RESPONSE) { + statusCode = get_status_code(p); + statusMessage = i[kStatusMessage]; + } + return i[kOnHeadersComplete](versionMajor, versionMinor, rawHeaders, method, +url, statusCode, statusMessage, upgrade, shouldKeepAlive); +}; + +const wasm_on_body = (p: number, at: number, length: number) => { + const i = instMap.get(p); + const body = Buffer.from(memory.buffer, at, length); + return i[kOnBody](body); +}; + +const wasm_on_message_complete = (p: number) => { + return instMap.get(p)[kOnMessageComplete](); +}; + +const instMap = new Map(); + +const inst = new WebAssembly.Instance(mod, { + env: { + wasm_on_message_begin, + wasm_on_url, + wasm_on_status, + wasm_on_header_field, + wasm_on_header_value, + wasm_on_headers_complete, + wasm_on_body, + wasm_on_message_complete, + }, +}); + +const memory = inst.exports.memory as any; +const alloc = inst.exports.llhttp_alloc as CallableFunction; +const malloc = inst.exports.malloc as CallableFunction; +const execute = inst.exports.llhttp_execute as CallableFunction; +const get_type = inst.exports.llhttp_get_type as CallableFunction; +const get_upgrade = inst.exports.llhttp_get_upgrade as CallableFunction; +const should_keep_alive = inst.exports.llhttp_should_keep_alive as CallableFunction; +const get_method = inst.exports.llhttp_get_method as CallableFunction; +const get_status_code = inst.exports.llhttp_get_status_code as CallableFunction; +const get_version_minor = inst.exports.llhttp_get_http_minor as CallableFunction; +const get_version_major = inst.exports.llhttp_get_http_major as CallableFunction; +const get_error_reason = inst.exports.llhttp_get_error_reason as CallableFunction; +const free = inst.exports.free as CallableFunction; +const initialize = inst.exports._initialize as CallableFunction; + +initialize(); // wasi reactor + +class HTTPParser { + static REQUEST = REQUEST; + static RESPONSE = RESPONSE; + static kOnMessageBegin = kOnMessageBegin; + static kOnHeaders = kOnHeaders; + static kOnHeadersComplete = kOnHeadersComplete; + static kOnBody = kOnBody; + static kOnMessageComplete = kOnMessageComplete; + static kOnExecute = kOnExecute; + + [kPtr]: number; + [kUrl]: string; + [kStatusMessage]: null|string; + [kHeadersFields]: []|[string]; + [kHeadersValues]: []|[string]; + [kBody]: null|Buffer; + + constructor(type: constants.TYPE) { + this[kPtr] = alloc(constants.TYPE[type]); + instMap.set(this[kPtr], this); + + this[kUrl] = ''; + this[kStatusMessage] = null; + this[kHeadersFields] = []; + this[kHeadersValues] = []; + this[kBody] = null; + } + + [kReset]() { + this[kUrl] = ''; + this[kStatusMessage] = null; + this[kHeadersFields] = []; + this[kHeadersValues] = []; + this[kBody] = null; + } + + [kOnMessageBegin]() { + return 0; + } + + [kOnHeaders](rawHeaders: [string]) {} + + [kOnHeadersComplete](versionMajor: number, versionMinor: number, rawHeaders: [string], method: string, + url: string, statusCode: number, statusMessage: string, upgrade: boolean, shouldKeepAlive: boolean) { + return 0; + } + + [kOnBody](body: Buffer) { + this[kBody] = body; + return 0; + } + + [kOnMessageComplete]() { + return 0; + } + + destroy() { + instMap.delete(this[kPtr]); + free(this[kPtr]); + } + + execute(data: Buffer) { + const ptr = malloc(data.byteLength); + const u8 = new Uint8Array(memory.buffer); + u8.set(data, ptr); + const ret = execute(this[kPtr], ptr, data.length); + free(ptr); + this[kCheckErr](ret); + return ret; + } + + [kCheckErr](n: number) { + if (n === constants.ERROR.OK) { + return; + } + const ptr = get_error_reason(this[kPtr]); + const u8 = new Uint8Array(memory.buffer); + const len = u8.indexOf(0, ptr) - ptr; + throw new Error(cstr(ptr, len)); + } +} + + +{ + const p = new HTTPParser(HTTPParser.REQUEST); + + p.execute(Buffer.from([ + 'POST /owo HTTP/1.1', + 'X: Y', + 'Content-Length: 9', + '', + 'uh, meow?', + '', + ].join('\r\n'))); + + console.log(p); + + p.destroy(); +} + +{ + const p = new HTTPParser(HTTPParser.RESPONSE); + + p.execute(Buffer.from([ + 'HTTP/1.1 200 OK', + 'X: Y', + 'Content-Length: 9', + '', + 'uh, meow?' + ].join('\r\n'))); + + console.log(p); + + p.destroy(); +} diff --git a/vendor/llhttp/images/http-loose-none.png b/vendor/llhttp/images/http-loose-none.png new file mode 100644 index 0000000..3187765 Binary files /dev/null and b/vendor/llhttp/images/http-loose-none.png differ diff --git a/vendor/llhttp/images/http-strict-none.png b/vendor/llhttp/images/http-strict-none.png new file mode 100644 index 0000000..8f2aacf Binary files /dev/null and b/vendor/llhttp/images/http-strict-none.png differ diff --git a/vendor/llhttp/libllhttp.pc.in b/vendor/llhttp/libllhttp.pc.in new file mode 100644 index 0000000..67d280a --- /dev/null +++ b/vendor/llhttp/libllhttp.pc.in @@ -0,0 +1,10 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=@CMAKE_INSTALL_PREFIX@ +libdir=@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_LIBDIR@ +includedir=@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_INCLUDEDIR@ + +Name: libllhttp +Description: Node.js llhttp Library +Version: @PROJECT_VERSION@ +Libs: -L${libdir} -lllhttp +Cflags: -I${includedir} \ No newline at end of file diff --git a/vendor/llhttp/package-lock.json b/vendor/llhttp/package-lock.json new file mode 100644 index 0000000..a49ed36 --- /dev/null +++ b/vendor/llhttp/package-lock.json @@ -0,0 +1,2995 @@ +{ + "name": "llhttp", + "version": "9.1.3", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "version": "9.1.3", + "license": "MIT", + "dependencies": { + "@types/semver": "^5.5.0", + "llparse": "^7.1.1", + "semver": "^5.7.1" + }, + "devDependencies": { + "@types/mocha": "^5.2.7", + "@types/node": "^10.17.52", + "javascript-stringify": "^2.0.1", + "llparse-dot": "^1.0.1", + "llparse-test-fixture": "^5.0.1", + "mdgator": "^1.1.2", + "mocha": "^10.2.0", + "ts-node": "^7.0.1", + "tslint": "^5.20.1", + "typescript": "^3.9.9" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz", + "integrity": "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.12.13" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", + "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==", + "dev": true + }, + "node_modules/@babel/highlight": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.0.tgz", + "integrity": "sha512-YSCOwxvTYEIMSGaBQb5kDDsCopDdiUGsqpatp3fOlI4+2HQSkTmEVWnVuySdAC5EWCqSWWTv0ib63RjR7dTBdg==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.14.0", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "node_modules/@types/debug": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.5.tgz", + "integrity": "sha512-Q1y515GcOdTHgagaVFhHnIFQ38ygs/kmxdNpvpou+raI9UO3YZcHDngBSYKQklcKlvA7iuQlmIKbzvmxcOE9CQ==" + }, + "node_modules/@types/markdown-it": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-0.0.4.tgz", + "integrity": "sha512-FWR7QB7EqBRq1s9BMk0ccOSOuRLfVEWYpHQYpFPaXtCoqN6dJx2ttdsdQbUxLLnAlKpYeVjveGGhQ3583TTa7g==", + "dev": true + }, + "node_modules/@types/mocha": { + "version": "5.2.7", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.7.tgz", + "integrity": "sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ==", + "dev": true + }, + "node_modules/@types/node": { + "version": "10.17.59", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.59.tgz", + "integrity": "sha512-7Uc8IRrL8yZz5ti45RaFxpbU8TxlzdC3HvxV+hOWo1EyLsuKv/w7y0n+TwZzwL3vdx3oZ2k3ubxPq131hNtXyg==", + "dev": true + }, + "node_modules/@types/semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-41qEJgBH/TWgo5NFSvBCJ1qkoi3Q6ONSF2avrHq1LVEZfYpdHmj0y9SuTK+u9ZhG1sYQKBL1AWXKyLWP4RaUoQ==" + }, + "node_modules/ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/binary-search": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/binary-search/-/binary-search-1.3.6.tgz", + "integrity": "sha512-nbE1WxOTTrUWIfsfZ4aHGYu5DOuNkbxGokjV6Z2kxfJK3uaAb8zNK1muzOeipoLHZjInT4Br88BHpzevc681xA==" + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "node_modules/buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "node_modules/builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/entities": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==", + "dev": true + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/esm": { + "version": "3.2.25", + "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz", + "integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "bin": { + "flat": "cli.js" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "bin": { + "he": "bin/he" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.4.0.tgz", + "integrity": "sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/javascript-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/javascript-stringify/-/javascript-stringify-2.1.0.tgz", + "integrity": "sha512-JVAfqNPTvNq3sB/VHQJAFxN/sPgKnsKrCwyRt15zwNCdrMMJDdcEOdubuy+DuJYYdm0ox1J4uzEuYKkN+9yhVg==", + "dev": true + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/linkify-it": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz", + "integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==", + "dev": true, + "dependencies": { + "uc.micro": "^1.0.1" + } + }, + "node_modules/llparse": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/llparse/-/llparse-7.1.1.tgz", + "integrity": "sha512-lBxN5O6sKq6KSOaRFIGczoVpO/U/37mHhjJioQbPuiXdfZmwzP1zC3txV9xx778TRNFENzeCM0Uoo+mE1rfJOA==", + "dependencies": { + "debug": "^4.2.0", + "llparse-frontend": "^3.0.0" + } + }, + "node_modules/llparse-builder": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/llparse-builder/-/llparse-builder-1.5.2.tgz", + "integrity": "sha512-i862UNC3YUEdlfK/NUCJxlKjtWjgAI9AJXDRgjcfRHfwFt4Sf8eFPTRsc91/2R9MBZ0kyFdfhi8SVhMsZf1gNQ==", + "dependencies": { + "@types/debug": "4.1.5 ", + "binary-search": "^1.3.6", + "debug": "^4.2.0" + } + }, + "node_modules/llparse-dot": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/llparse-dot/-/llparse-dot-1.0.1.tgz", + "integrity": "sha512-3e271C2LuDWBzhxaCUDzjpufamoEBuTYQz83QyMixI/i99BntCEk6ngHWOhhDb0XdtNNh6qAfRmXyjgNP+Nxpw==", + "dev": true, + "dependencies": { + "llparse-builder": "^1.0.0" + } + }, + "node_modules/llparse-frontend": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/llparse-frontend/-/llparse-frontend-3.0.0.tgz", + "integrity": "sha512-G/o0Po2C+G5OtP8MJeQDjDf5qwDxcO7K6x4r6jqGsJwxk7yblbJnRqpmye7G/lZ8dD0Hv5neY4/KB5BhDmEc9Q==", + "dependencies": { + "debug": "^3.2.6", + "llparse-builder": "^1.5.2" + } + }, + "node_modules/llparse-frontend/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/llparse-test-fixture": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/llparse-test-fixture/-/llparse-test-fixture-5.0.2.tgz", + "integrity": "sha512-61KI5J/b5uyRktD0y1EezleEW6UfaxhHkn1adLKNVemRZzklE+SpLakr251qo04kb9jN/ytk8lllgK+yFOj4cQ==", + "dev": true, + "dependencies": { + "esm": "^3.2.25", + "llparse": "^7.0.0", + "yargs": "^15.4.1" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-symbols/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-symbols/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/log-symbols/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/log-symbols/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/log-symbols/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/log-symbols/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "node_modules/markdown-it": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-8.4.2.tgz", + "integrity": "sha512-GcRz3AWTqSUphY3vsUqQSFMbgR38a4Lh3GWlHRh/7MRwz8mcu9n2IO7HOh+bXHrR9kOPDl5RNCaEsrneb+xhHQ==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "entities": "~1.1.1", + "linkify-it": "^2.0.0", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + }, + "bin": { + "markdown-it": "bin/markdown-it.js" + } + }, + "node_modules/mdgator": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/mdgator/-/mdgator-1.1.2.tgz", + "integrity": "sha512-S2GvsLIznUQ2McXfpe6BCD+IqhnRuHcBO7krqnvnsHgDpjjO1mLhr0vZtVa5ca4WZET037g3G+94DznpicKkOA==", + "dev": true, + "dependencies": { + "@types/markdown-it": "0.0.4", + "markdown-it": "^8.4.1" + } + }, + "node_modules/mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", + "dev": true + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", + "dev": true + }, + "node_modules/mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/mocha": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz", + "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==", + "dev": true, + "dependencies": { + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.5.3", + "debug": "4.3.4", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "7.2.0", + "he": "1.2.0", + "js-yaml": "4.1.0", + "log-symbols": "4.1.0", + "minimatch": "5.0.1", + "ms": "2.1.3", + "nanoid": "3.3.3", + "serialize-javascript": "6.0.0", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "workerpool": "6.2.1", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha.js" + }, + "engines": { + "node": ">= 14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mochajs" + } + }, + "node_modules/mocha/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/mocha/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/mocha/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/mocha/node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/mocha/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/mocha/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/mocha/node_modules/diff": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/mocha/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mocha/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/mocha/node_modules/minimatch": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", + "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mocha/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/mocha/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/mocha/node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/mocha/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/nanoid": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", + "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", + "dev": true, + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "node_modules/resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, + "dependencies": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/supports-color/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ts-node": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-7.0.1.tgz", + "integrity": "sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw==", + "dev": true, + "dependencies": { + "arrify": "^1.0.0", + "buffer-from": "^1.1.0", + "diff": "^3.1.0", + "make-error": "^1.1.1", + "minimist": "^1.2.0", + "mkdirp": "^0.5.1", + "source-map-support": "^0.5.6", + "yn": "^2.0.0" + }, + "bin": { + "ts-node": "dist/bin.js" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/tslint": { + "version": "5.20.1", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.20.1.tgz", + "integrity": "sha512-EcMxhzCFt8k+/UP5r8waCf/lzmeSyVlqxqMEDQE7rWYiQky8KpIBz1JAoYXfROHrPZ1XXd43q8yQnULOLiBRQg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "builtin-modules": "^1.1.1", + "chalk": "^2.3.0", + "commander": "^2.12.1", + "diff": "^4.0.1", + "glob": "^7.1.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "resolve": "^1.3.2", + "semver": "^5.3.0", + "tslib": "^1.8.0", + "tsutils": "^2.29.0" + }, + "bin": { + "tslint": "bin/tslint" + }, + "engines": { + "node": ">=4.8.0" + }, + "peerDependencies": { + "typescript": ">=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >=3.0.0-dev || >= 3.1.0-dev || >= 3.2.0-dev" + } + }, + "node_modules/tslint/node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/tsutils": { + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", + "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "peerDependencies": { + "typescript": ">=2.1.0 || >=2.1.0-dev || >=2.2.0-dev || >=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >= 3.0.0-dev || >= 3.1.0-dev" + } + }, + "node_modules/typescript": { + "version": "3.9.9", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.9.tgz", + "integrity": "sha512-kdMjTiekY+z/ubJCATUPlRDl39vXYiMV9iyeMuEuXZh2we6zz80uovNN2WlAxmmdE/Z/YQe+EbOEXB5RHEED3w==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/uc.micro": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", + "dev": true + }, + "node_modules/which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "node_modules/workerpool": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", + "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", + "dev": true + }, + "node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, + "node_modules/yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "dev": true, + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "dev": true, + "dependencies": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-unparser/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yargs-unparser/node_modules/decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yargs/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yn": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz", + "integrity": "sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz", + "integrity": "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==", + "dev": true, + "requires": { + "@babel/highlight": "^7.12.13" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", + "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==", + "dev": true + }, + "@babel/highlight": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.0.tgz", + "integrity": "sha512-YSCOwxvTYEIMSGaBQb5kDDsCopDdiUGsqpatp3fOlI4+2HQSkTmEVWnVuySdAC5EWCqSWWTv0ib63RjR7dTBdg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.14.0", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@types/debug": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.5.tgz", + "integrity": "sha512-Q1y515GcOdTHgagaVFhHnIFQ38ygs/kmxdNpvpou+raI9UO3YZcHDngBSYKQklcKlvA7iuQlmIKbzvmxcOE9CQ==" + }, + "@types/markdown-it": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-0.0.4.tgz", + "integrity": "sha512-FWR7QB7EqBRq1s9BMk0ccOSOuRLfVEWYpHQYpFPaXtCoqN6dJx2ttdsdQbUxLLnAlKpYeVjveGGhQ3583TTa7g==", + "dev": true + }, + "@types/mocha": { + "version": "5.2.7", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.7.tgz", + "integrity": "sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ==", + "dev": true + }, + "@types/node": { + "version": "10.17.59", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.59.tgz", + "integrity": "sha512-7Uc8IRrL8yZz5ti45RaFxpbU8TxlzdC3HvxV+hOWo1EyLsuKv/w7y0n+TwZzwL3vdx3oZ2k3ubxPq131hNtXyg==", + "dev": true + }, + "@types/semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-41qEJgBH/TWgo5NFSvBCJ1qkoi3Q6ONSF2avrHq1LVEZfYpdHmj0y9SuTK+u9ZhG1sYQKBL1AWXKyLWP4RaUoQ==" + }, + "ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true + }, + "binary-search": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/binary-search/-/binary-search-1.3.6.tgz", + "integrity": "sha512-nbE1WxOTTrUWIfsfZ4aHGYu5DOuNkbxGokjV6Z2kxfJK3uaAb8zNK1muzOeipoLHZjInT4Br88BHpzevc681xA==" + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + } + }, + "cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "entities": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==", + "dev": true + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "esm": { + "version": "3.2.25", + "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz", + "integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==", + "dev": true + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-core-module": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.4.0.tgz", + "integrity": "sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true + }, + "is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true + }, + "javascript-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/javascript-stringify/-/javascript-stringify-2.1.0.tgz", + "integrity": "sha512-JVAfqNPTvNq3sB/VHQJAFxN/sPgKnsKrCwyRt15zwNCdrMMJDdcEOdubuy+DuJYYdm0ox1J4uzEuYKkN+9yhVg==", + "dev": true + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "linkify-it": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz", + "integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==", + "dev": true, + "requires": { + "uc.micro": "^1.0.1" + } + }, + "llparse": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/llparse/-/llparse-7.1.1.tgz", + "integrity": "sha512-lBxN5O6sKq6KSOaRFIGczoVpO/U/37mHhjJioQbPuiXdfZmwzP1zC3txV9xx778TRNFENzeCM0Uoo+mE1rfJOA==", + "requires": { + "debug": "^4.2.0", + "llparse-frontend": "^3.0.0" + } + }, + "llparse-builder": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/llparse-builder/-/llparse-builder-1.5.2.tgz", + "integrity": "sha512-i862UNC3YUEdlfK/NUCJxlKjtWjgAI9AJXDRgjcfRHfwFt4Sf8eFPTRsc91/2R9MBZ0kyFdfhi8SVhMsZf1gNQ==", + "requires": { + "@types/debug": "4.1.5 ", + "binary-search": "^1.3.6", + "debug": "^4.2.0" + } + }, + "llparse-dot": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/llparse-dot/-/llparse-dot-1.0.1.tgz", + "integrity": "sha512-3e271C2LuDWBzhxaCUDzjpufamoEBuTYQz83QyMixI/i99BntCEk6ngHWOhhDb0XdtNNh6qAfRmXyjgNP+Nxpw==", + "dev": true, + "requires": { + "llparse-builder": "^1.0.0" + } + }, + "llparse-frontend": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/llparse-frontend/-/llparse-frontend-3.0.0.tgz", + "integrity": "sha512-G/o0Po2C+G5OtP8MJeQDjDf5qwDxcO7K6x4r6jqGsJwxk7yblbJnRqpmye7G/lZ8dD0Hv5neY4/KB5BhDmEc9Q==", + "requires": { + "debug": "^3.2.6", + "llparse-builder": "^1.5.2" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "llparse-test-fixture": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/llparse-test-fixture/-/llparse-test-fixture-5.0.2.tgz", + "integrity": "sha512-61KI5J/b5uyRktD0y1EezleEW6UfaxhHkn1adLKNVemRZzklE+SpLakr251qo04kb9jN/ytk8lllgK+yFOj4cQ==", + "dev": true, + "requires": { + "esm": "^3.2.25", + "llparse": "^7.0.0", + "yargs": "^15.4.1" + } + }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } + }, + "log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "requires": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "markdown-it": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-8.4.2.tgz", + "integrity": "sha512-GcRz3AWTqSUphY3vsUqQSFMbgR38a4Lh3GWlHRh/7MRwz8mcu9n2IO7HOh+bXHrR9kOPDl5RNCaEsrneb+xhHQ==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "entities": "~1.1.1", + "linkify-it": "^2.0.0", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + } + }, + "mdgator": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/mdgator/-/mdgator-1.1.2.tgz", + "integrity": "sha512-S2GvsLIznUQ2McXfpe6BCD+IqhnRuHcBO7krqnvnsHgDpjjO1mLhr0vZtVa5ca4WZET037g3G+94DznpicKkOA==", + "dev": true, + "requires": { + "@types/markdown-it": "0.0.4", + "markdown-it": "^8.4.1" + } + }, + "mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", + "dev": true + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", + "dev": true + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "mocha": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz", + "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==", + "dev": true, + "requires": { + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.5.3", + "debug": "4.3.4", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "7.2.0", + "he": "1.2.0", + "js-yaml": "4.1.0", + "log-symbols": "4.1.0", + "minimatch": "5.0.1", + "ms": "2.1.3", + "nanoid": "3.3.3", + "serialize-javascript": "6.0.0", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "workerpool": "6.2.1", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "diff": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "dev": true + }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, + "minimatch": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", + "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true + }, + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + } + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "nanoid": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", + "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", + "dev": true + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "requires": { + "p-limit": "^3.0.2" + }, + "dependencies": { + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + } + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, + "requires": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, + "semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==" + }, + "serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + } + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "ts-node": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-7.0.1.tgz", + "integrity": "sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw==", + "dev": true, + "requires": { + "arrify": "^1.0.0", + "buffer-from": "^1.1.0", + "diff": "^3.1.0", + "make-error": "^1.1.1", + "minimist": "^1.2.0", + "mkdirp": "^0.5.1", + "source-map-support": "^0.5.6", + "yn": "^2.0.0" + } + }, + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "tslint": { + "version": "5.20.1", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.20.1.tgz", + "integrity": "sha512-EcMxhzCFt8k+/UP5r8waCf/lzmeSyVlqxqMEDQE7rWYiQky8KpIBz1JAoYXfROHrPZ1XXd43q8yQnULOLiBRQg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "builtin-modules": "^1.1.1", + "chalk": "^2.3.0", + "commander": "^2.12.1", + "diff": "^4.0.1", + "glob": "^7.1.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "resolve": "^1.3.2", + "semver": "^5.3.0", + "tslib": "^1.8.0", + "tsutils": "^2.29.0" + }, + "dependencies": { + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true + } + } + }, + "tsutils": { + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", + "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + }, + "typescript": { + "version": "3.9.9", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.9.tgz", + "integrity": "sha512-kdMjTiekY+z/ubJCATUPlRDl39vXYiMV9iyeMuEuXZh2we6zz80uovNN2WlAxmmdE/Z/YQe+EbOEXB5RHEED3w==", + "dev": true + }, + "uc.micro": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", + "dev": true + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "workerpool": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", + "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", + "dev": true + }, + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, + "yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "dev": true, + "requires": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "dependencies": { + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, + "yargs-parser": { + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "dev": true + }, + "yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "dev": true, + "requires": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + }, + "dependencies": { + "camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true + }, + "decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true + } + } + }, + "yn": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz", + "integrity": "sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=", + "dev": true + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true + } + } +} diff --git a/vendor/llhttp/package.json b/vendor/llhttp/package.json new file mode 100644 index 0000000..be715b8 --- /dev/null +++ b/vendor/llhttp/package.json @@ -0,0 +1,60 @@ +{ + "name": "llhttp", + "version": "9.1.3", + "description": "HTTP parser in LLVM IR", + "main": "lib/llhttp.js", + "types": "lib/llhttp.d.ts", + "files": [ + "lib", + "src" + ], + "scripts": { + "bench": "ts-node bench/", + "build": "ts-node bin/generate.ts", + "build-ts": "tsc", + "prebuild-wasm": "npm run wasm -- --prebuild && npm run wasm -- --setup", + "build-wasm": "npm run wasm -- --docker", + "wasm": "ts-node bin/build_wasm.ts", + "clean": "rm -rf lib && rm -rf test/tmp", + "prepare": "npm run clean && npm run build-ts", + "lint": "tslint -c tslint.json bin/*.ts src/*.ts src/**/*.ts test/*.ts test/**/*.ts", + "lint-fix": "tslint --fix -c tslint.json bin/*.ts src/*.ts src/**/*.ts test/*.ts test/**/*.ts", + "mocha": "mocha --timeout=10000 -r ts-node/register/type-check --reporter progress test/*-test.ts", + "test": "npm run mocha && npm run lint", + "postversion": "RELEASE=`node -e \"process.stdout.write(require('./package').version)\"` make -B postversion", + "github-release": "RELEASE_V=`node -e \"process.stdout.write('v' + require('./package').version)\"` make github-release" + }, + "repository": { + "type": "git", + "url": "git+ssh://git@github.com/nodejs/llhttp.git" + }, + "keywords": [ + "http", + "llvm", + "ir", + "llparse" + ], + "author": "Fedor Indutny (http://darksi.de/)", + "license": "MIT", + "bugs": { + "url": "https://github.com/nodejs/llhttp/issues" + }, + "homepage": "https://github.com/nodejs/llhttp#readme", + "devDependencies": { + "@types/mocha": "^5.2.7", + "@types/node": "^10.17.52", + "javascript-stringify": "^2.0.1", + "llparse-dot": "^1.0.1", + "llparse-test-fixture": "^5.0.1", + "mdgator": "^1.1.2", + "mocha": "^10.2.0", + "ts-node": "^7.0.1", + "tslint": "^5.20.1", + "typescript": "^3.9.9" + }, + "dependencies": { + "@types/semver": "^5.5.0", + "llparse": "^7.1.1", + "semver": "^5.7.1" + } +} diff --git a/vendor/llhttp/src/common.gypi b/vendor/llhttp/src/common.gypi new file mode 100644 index 0000000..ef7549f --- /dev/null +++ b/vendor/llhttp/src/common.gypi @@ -0,0 +1,46 @@ +{ + 'target_defaults': { + 'default_configuration': 'Debug', + 'configurations': { + # TODO: hoist these out and put them somewhere common, because + # RuntimeLibrary MUST MATCH across the entire project + 'Debug': { + 'defines': [ 'DEBUG', '_DEBUG' ], + 'cflags': [ '-Wall', '-Wextra', '-O0', '-g', '-ftrapv' ], + 'msvs_settings': { + 'VCCLCompilerTool': { + 'RuntimeLibrary': 1, # static debug + }, + }, + }, + 'Release': { + 'defines': [ 'NDEBUG' ], + 'cflags': [ '-Wall', '-Wextra', '-O3' ], + 'msvs_settings': { + 'VCCLCompilerTool': { + 'RuntimeLibrary': 0, # static release + }, + }, + } + }, + 'msvs_settings': { + 'VCCLCompilerTool': { + # Compile as C++. llhttp.c is actually C99, but C++ is + # close enough in this case. + 'CompileAs': 2, + }, + 'VCLibrarianTool': { + }, + 'VCLinkerTool': { + 'GenerateDebugInformation': 'true', + }, + }, + 'conditions': [ + ['OS == "win"', { + 'defines': [ + 'WIN32' + ], + }] + ], + }, +} diff --git a/vendor/llhttp/src/llhttp.gyp b/vendor/llhttp/src/llhttp.gyp new file mode 100644 index 0000000..c7b8800 --- /dev/null +++ b/vendor/llhttp/src/llhttp.gyp @@ -0,0 +1,22 @@ +{ + 'variables': { + 'llhttp_sources': [ + 'src/llhttp.c', + 'src/api.c', + 'src/http.c', + ] + }, + 'targets': [ + { + 'target_name': 'llhttp', + 'type': 'static_library', + 'include_dirs': [ '.', 'include' ], + 'direct_dependent_settings': { + 'include_dirs': [ 'include' ], + }, + 'sources': [ + '<@(llhttp_sources)', + ], + }, + ] +} diff --git a/vendor/llhttp/src/llhttp.ts b/vendor/llhttp/src/llhttp.ts new file mode 100644 index 0000000..ba36b01 --- /dev/null +++ b/vendor/llhttp/src/llhttp.ts @@ -0,0 +1,7 @@ +import * as constants from './llhttp/constants'; + +export { constants }; + +export { HTTP } from './llhttp/http'; +export { URL } from './llhttp/url'; +export { CHeaders } from './llhttp/c-headers'; diff --git a/vendor/llhttp/src/llhttp/c-headers.ts b/vendor/llhttp/src/llhttp/c-headers.ts new file mode 100644 index 0000000..fad66de --- /dev/null +++ b/vendor/llhttp/src/llhttp/c-headers.ts @@ -0,0 +1,106 @@ +import * as constants from './constants'; +import { enumToMap, IEnumMap } from './utils'; + +type Encoding = 'none' | 'hex'; + +export class CHeaders { + public build(): string { + let res = ''; + + res += '#ifndef LLLLHTTP_C_HEADERS_\n'; + res += '#define LLLLHTTP_C_HEADERS_\n'; + + res += '#ifdef __cplusplus\n'; + res += 'extern "C" {\n'; + res += '#endif\n'; + + res += '\n'; + + const errorMap = enumToMap(constants.ERROR); + const methodMap = enumToMap(constants.METHODS); + const httpMethodMap = enumToMap(constants.METHODS, constants.METHODS_HTTP, [ + constants.METHODS.PRI, + ]); + const rtspMethodMap = enumToMap(constants.METHODS, constants.METHODS_RTSP); + const statusMap = enumToMap(constants.STATUSES, constants.STATUSES_HTTP); + + res += this.buildEnum('llhttp_errno', 'HPE', errorMap); + res += '\n'; + res += this.buildEnum('llhttp_flags', 'F', enumToMap(constants.FLAGS), + 'hex'); + res += '\n'; + res += this.buildEnum('llhttp_lenient_flags', 'LENIENT', + enumToMap(constants.LENIENT_FLAGS), 'hex'); + res += '\n'; + res += this.buildEnum('llhttp_type', 'HTTP', + enumToMap(constants.TYPE)); + res += '\n'; + res += this.buildEnum('llhttp_finish', 'HTTP_FINISH', + enumToMap(constants.FINISH)); + res += '\n'; + res += this.buildEnum('llhttp_method', 'HTTP', methodMap); + res += '\n'; + res += this.buildEnum('llhttp_status', 'HTTP_STATUS', statusMap); + + res += '\n'; + + res += this.buildMap('HTTP_ERRNO', errorMap); + res += '\n'; + res += this.buildMap('HTTP_METHOD', httpMethodMap); + res += '\n'; + res += this.buildMap('RTSP_METHOD', rtspMethodMap); + res += '\n'; + res += this.buildMap('HTTP_ALL_METHOD', methodMap); + res += '\n'; + res += this.buildMap('HTTP_STATUS', statusMap); + + res += '\n'; + + res += '#ifdef __cplusplus\n'; + res += '} /* extern "C" */\n'; + res += '#endif\n'; + res += '#endif /* LLLLHTTP_C_HEADERS_ */\n'; + + return res; + } + + private buildEnum(name: string, prefix: string, map: IEnumMap, + encoding: Encoding = 'none'): string { + let res = ''; + + res += `enum ${name} {\n`; + const keys = Object.keys(map); + const keysLength = keys.length; + for (let i = 0; i < keysLength; i++) { + const key = keys[i]; + const isLast = i === keysLength - 1; + + let value: number | string = map[key]; + + if (encoding === 'hex') { + value = `0x${value.toString(16)}`; + } + + res += ` ${prefix}_${key.replace(/-/g, '')} = ${value}`; + if (!isLast) { + res += ',\n'; + } + } + res += '\n};\n'; + res += `typedef enum ${name} ${name}_t;\n`; + + return res; + } + + private buildMap(name: string, map: IEnumMap): string { + let res = ''; + + res += `#define ${name}_MAP(XX) \\\n`; + for (const [key, value] of Object.entries(map)) { + res += ` XX(${value!}, ${key.replace(/-/g, '')}, ${key}) \\\n`; + } + res += '\n'; + + return res; + } +} diff --git a/vendor/llhttp/src/llhttp/constants.ts b/vendor/llhttp/src/llhttp/constants.ts new file mode 100644 index 0000000..00fc523 --- /dev/null +++ b/vendor/llhttp/src/llhttp/constants.ts @@ -0,0 +1,540 @@ +import { enumToMap, IEnumMap } from './utils'; + +// C headers + +export enum ERROR { + OK = 0, + INTERNAL = 1, + STRICT = 2, + CR_EXPECTED = 25, + LF_EXPECTED = 3, + UNEXPECTED_CONTENT_LENGTH = 4, + UNEXPECTED_SPACE = 30, + CLOSED_CONNECTION = 5, + INVALID_METHOD = 6, + INVALID_URL = 7, + INVALID_CONSTANT = 8, + INVALID_VERSION = 9, + INVALID_HEADER_TOKEN = 10, + INVALID_CONTENT_LENGTH = 11, + INVALID_CHUNK_SIZE = 12, + INVALID_STATUS = 13, + INVALID_EOF_STATE = 14, + INVALID_TRANSFER_ENCODING = 15, + + CB_MESSAGE_BEGIN = 16, + CB_HEADERS_COMPLETE = 17, + CB_MESSAGE_COMPLETE = 18, + CB_CHUNK_HEADER = 19, + CB_CHUNK_COMPLETE = 20, + + PAUSED = 21, + PAUSED_UPGRADE = 22, + PAUSED_H2_UPGRADE = 23, + + USER = 24, + + CB_URL_COMPLETE = 26, + CB_STATUS_COMPLETE = 27, + CB_METHOD_COMPLETE = 32, + CB_VERSION_COMPLETE = 33, + CB_HEADER_FIELD_COMPLETE = 28, + CB_HEADER_VALUE_COMPLETE = 29, + CB_CHUNK_EXTENSION_NAME_COMPLETE = 34, + CB_CHUNK_EXTENSION_VALUE_COMPLETE = 35, + CB_RESET = 31, +} + +export enum TYPE { + BOTH = 0, // default + REQUEST = 1, + RESPONSE = 2, +} + +export enum FLAGS { + CONNECTION_KEEP_ALIVE = 1 << 0, + CONNECTION_CLOSE = 1 << 1, + CONNECTION_UPGRADE = 1 << 2, + CHUNKED = 1 << 3, + UPGRADE = 1 << 4, + CONTENT_LENGTH = 1 << 5, + SKIPBODY = 1 << 6, + TRAILING = 1 << 7, + // 1 << 8 is unused + TRANSFER_ENCODING = 1 << 9, +} + +export enum LENIENT_FLAGS { + HEADERS = 1 << 0, + CHUNKED_LENGTH = 1 << 1, + KEEP_ALIVE = 1 << 2, + TRANSFER_ENCODING = 1 << 3, + VERSION = 1 << 4, + DATA_AFTER_CLOSE = 1 << 5, + OPTIONAL_LF_AFTER_CR = 1 << 6, + OPTIONAL_CRLF_AFTER_CHUNK = 1 << 7, + OPTIONAL_CR_BEFORE_LF = 1 << 8, + SPACES_AFTER_CHUNK_SIZE = 1 << 9, +} + +export enum METHODS { + DELETE = 0, + GET = 1, + HEAD = 2, + POST = 3, + PUT = 4, + /* pathological */ + CONNECT = 5, + OPTIONS = 6, + TRACE = 7, + /* WebDAV */ + COPY = 8, + LOCK = 9, + MKCOL = 10, + MOVE = 11, + PROPFIND = 12, + PROPPATCH = 13, + SEARCH = 14, + UNLOCK = 15, + BIND = 16, + REBIND = 17, + UNBIND = 18, + ACL = 19, + /* subversion */ + REPORT = 20, + MKACTIVITY = 21, + CHECKOUT = 22, + MERGE = 23, + /* upnp */ + 'M-SEARCH' = 24, + NOTIFY = 25, + SUBSCRIBE = 26, + UNSUBSCRIBE = 27, + /* RFC-5789 */ + PATCH = 28, + PURGE = 29, + /* CalDAV */ + MKCALENDAR = 30, + /* RFC-2068, section 19.6.1.2 */ + LINK = 31, + UNLINK = 32, + /* icecast */ + SOURCE = 33, + /* RFC-7540, section 11.6 */ + PRI = 34, + /* RFC-2326 RTSP */ + DESCRIBE = 35, + ANNOUNCE = 36, + SETUP = 37, + PLAY = 38, + PAUSE = 39, + TEARDOWN = 40, + GET_PARAMETER = 41, + SET_PARAMETER = 42, + REDIRECT = 43, + RECORD = 44, + /* RAOP */ + FLUSH = 45, +} + +export const METHODS_HTTP = [ + METHODS.DELETE, + METHODS.GET, + METHODS.HEAD, + METHODS.POST, + METHODS.PUT, + METHODS.CONNECT, + METHODS.OPTIONS, + METHODS.TRACE, + METHODS.COPY, + METHODS.LOCK, + METHODS.MKCOL, + METHODS.MOVE, + METHODS.PROPFIND, + METHODS.PROPPATCH, + METHODS.SEARCH, + METHODS.UNLOCK, + METHODS.BIND, + METHODS.REBIND, + METHODS.UNBIND, + METHODS.ACL, + METHODS.REPORT, + METHODS.MKACTIVITY, + METHODS.CHECKOUT, + METHODS.MERGE, + METHODS['M-SEARCH'], + METHODS.NOTIFY, + METHODS.SUBSCRIBE, + METHODS.UNSUBSCRIBE, + METHODS.PATCH, + METHODS.PURGE, + METHODS.MKCALENDAR, + METHODS.LINK, + METHODS.UNLINK, + METHODS.PRI, + + // TODO(indutny): should we allow it with HTTP? + METHODS.SOURCE, +]; + +export const METHODS_ICE = [ + METHODS.SOURCE, +]; + +export const METHODS_RTSP = [ + METHODS.OPTIONS, + METHODS.DESCRIBE, + METHODS.ANNOUNCE, + METHODS.SETUP, + METHODS.PLAY, + METHODS.PAUSE, + METHODS.TEARDOWN, + METHODS.GET_PARAMETER, + METHODS.SET_PARAMETER, + METHODS.REDIRECT, + METHODS.RECORD, + METHODS.FLUSH, + + // For AirPlay + METHODS.GET, + METHODS.POST, +]; + +export const METHOD_MAP = enumToMap(METHODS); +export const H_METHOD_MAP: IEnumMap = {}; + +for (const key of Object.keys(METHOD_MAP)) { + if (/^H/.test(key)) { + H_METHOD_MAP[key] = METHOD_MAP[key]; + } +} + +export enum STATUSES { + CONTINUE = 100, + SWITCHING_PROTOCOLS = 101, + PROCESSING = 102, + EARLY_HINTS = 103, + RESPONSE_IS_STALE = 110, // Unofficial + REVALIDATION_FAILED = 111, // Unofficial + DISCONNECTED_OPERATION = 112, // Unofficial + HEURISTIC_EXPIRATION = 113, // Unofficial + MISCELLANEOUS_WARNING = 199, // Unofficial + OK = 200, + CREATED = 201, + ACCEPTED = 202, + NON_AUTHORITATIVE_INFORMATION = 203, + NO_CONTENT = 204, + RESET_CONTENT = 205, + PARTIAL_CONTENT = 206, + MULTI_STATUS = 207, + ALREADY_REPORTED = 208, + TRANSFORMATION_APPLIED = 214, // Unofficial + IM_USED = 226, + MISCELLANEOUS_PERSISTENT_WARNING = 299, // Unofficial + MULTIPLE_CHOICES = 300, + MOVED_PERMANENTLY = 301, + FOUND = 302, + SEE_OTHER = 303, + NOT_MODIFIED = 304, + USE_PROXY = 305, + SWITCH_PROXY = 306, // No longer used + TEMPORARY_REDIRECT = 307, + PERMANENT_REDIRECT = 308, + BAD_REQUEST = 400, + UNAUTHORIZED = 401, + PAYMENT_REQUIRED = 402, + FORBIDDEN = 403, + NOT_FOUND = 404, + METHOD_NOT_ALLOWED = 405, + NOT_ACCEPTABLE = 406, + PROXY_AUTHENTICATION_REQUIRED = 407, + REQUEST_TIMEOUT = 408, + CONFLICT = 409, + GONE = 410, + LENGTH_REQUIRED = 411, + PRECONDITION_FAILED = 412, + PAYLOAD_TOO_LARGE = 413, + URI_TOO_LONG = 414, + UNSUPPORTED_MEDIA_TYPE = 415, + RANGE_NOT_SATISFIABLE = 416, + EXPECTATION_FAILED = 417, + IM_A_TEAPOT = 418, + PAGE_EXPIRED = 419, // Unofficial + ENHANCE_YOUR_CALM = 420, // Unofficial + MISDIRECTED_REQUEST = 421, + UNPROCESSABLE_ENTITY = 422, + LOCKED = 423, + FAILED_DEPENDENCY = 424, + TOO_EARLY = 425, + UPGRADE_REQUIRED = 426, + PRECONDITION_REQUIRED = 428, + TOO_MANY_REQUESTS = 429, + REQUEST_HEADER_FIELDS_TOO_LARGE_UNOFFICIAL = 430, // Unofficial + REQUEST_HEADER_FIELDS_TOO_LARGE = 431, + LOGIN_TIMEOUT = 440, // Unofficial + NO_RESPONSE = 444, // Unofficial + RETRY_WITH = 449, // Unofficial + BLOCKED_BY_PARENTAL_CONTROL = 450, // Unofficial + UNAVAILABLE_FOR_LEGAL_REASONS = 451, + CLIENT_CLOSED_LOAD_BALANCED_REQUEST = 460, // Unofficial + INVALID_X_FORWARDED_FOR = 463, // Unofficial + REQUEST_HEADER_TOO_LARGE = 494, // Unofficial + SSL_CERTIFICATE_ERROR = 495, // Unofficial + SSL_CERTIFICATE_REQUIRED = 496, // Unofficial + HTTP_REQUEST_SENT_TO_HTTPS_PORT = 497, // Unofficial + INVALID_TOKEN = 498, // Unofficial + CLIENT_CLOSED_REQUEST = 499, // Unofficial + INTERNAL_SERVER_ERROR = 500, + NOT_IMPLEMENTED = 501, + BAD_GATEWAY = 502, + SERVICE_UNAVAILABLE = 503, + GATEWAY_TIMEOUT = 504, + HTTP_VERSION_NOT_SUPPORTED = 505, + VARIANT_ALSO_NEGOTIATES = 506, + INSUFFICIENT_STORAGE = 507, + LOOP_DETECTED = 508, + BANDWIDTH_LIMIT_EXCEEDED = 509, + NOT_EXTENDED = 510, + NETWORK_AUTHENTICATION_REQUIRED = 511, + WEB_SERVER_UNKNOWN_ERROR = 520, // Unofficial + WEB_SERVER_IS_DOWN = 521, // Unofficial + CONNECTION_TIMEOUT = 522, // Unofficial + ORIGIN_IS_UNREACHABLE = 523, // Unofficial + TIMEOUT_OCCURED = 524, // Unofficial + SSL_HANDSHAKE_FAILED = 525, // Unofficial + INVALID_SSL_CERTIFICATE = 526, // Unofficial + RAILGUN_ERROR = 527, // Unofficial + SITE_IS_OVERLOADED = 529, // Unofficial + SITE_IS_FROZEN = 530, // Unofficial + IDENTITY_PROVIDER_AUTHENTICATION_ERROR = 561, // Unofficial + NETWORK_READ_TIMEOUT = 598, // Unofficial + NETWORK_CONNECT_TIMEOUT = 599, // Unofficial +} + +export const STATUSES_HTTP = [ + STATUSES.CONTINUE, + STATUSES.SWITCHING_PROTOCOLS, + STATUSES.PROCESSING, + STATUSES.EARLY_HINTS, + STATUSES.RESPONSE_IS_STALE, + STATUSES.REVALIDATION_FAILED, + STATUSES.DISCONNECTED_OPERATION, + STATUSES.HEURISTIC_EXPIRATION, + STATUSES.MISCELLANEOUS_WARNING, + STATUSES.OK, + STATUSES.CREATED, + STATUSES.ACCEPTED, + STATUSES.NON_AUTHORITATIVE_INFORMATION, + STATUSES.NO_CONTENT, + STATUSES.RESET_CONTENT, + STATUSES.PARTIAL_CONTENT, + STATUSES.MULTI_STATUS, + STATUSES.ALREADY_REPORTED, + STATUSES.TRANSFORMATION_APPLIED, + STATUSES.IM_USED, + STATUSES.MISCELLANEOUS_PERSISTENT_WARNING, + STATUSES.MULTIPLE_CHOICES, + STATUSES.MOVED_PERMANENTLY, + STATUSES.FOUND, + STATUSES.SEE_OTHER, + STATUSES.NOT_MODIFIED, + STATUSES.USE_PROXY, + STATUSES.SWITCH_PROXY, + STATUSES.TEMPORARY_REDIRECT, + STATUSES.PERMANENT_REDIRECT, + STATUSES.BAD_REQUEST, + STATUSES.UNAUTHORIZED, + STATUSES.PAYMENT_REQUIRED, + STATUSES.FORBIDDEN, + STATUSES.NOT_FOUND, + STATUSES.METHOD_NOT_ALLOWED, + STATUSES.NOT_ACCEPTABLE, + STATUSES.PROXY_AUTHENTICATION_REQUIRED, + STATUSES.REQUEST_TIMEOUT, + STATUSES.CONFLICT, + STATUSES.GONE, + STATUSES.LENGTH_REQUIRED, + STATUSES.PRECONDITION_FAILED, + STATUSES.PAYLOAD_TOO_LARGE, + STATUSES.URI_TOO_LONG, + STATUSES.UNSUPPORTED_MEDIA_TYPE, + STATUSES.RANGE_NOT_SATISFIABLE, + STATUSES.EXPECTATION_FAILED, + STATUSES.IM_A_TEAPOT, + STATUSES.PAGE_EXPIRED, + STATUSES.ENHANCE_YOUR_CALM, + STATUSES.MISDIRECTED_REQUEST, + STATUSES.UNPROCESSABLE_ENTITY, + STATUSES.LOCKED, + STATUSES.FAILED_DEPENDENCY, + STATUSES.TOO_EARLY, + STATUSES.UPGRADE_REQUIRED, + STATUSES.PRECONDITION_REQUIRED, + STATUSES.TOO_MANY_REQUESTS, + STATUSES.REQUEST_HEADER_FIELDS_TOO_LARGE_UNOFFICIAL, + STATUSES.REQUEST_HEADER_FIELDS_TOO_LARGE, + STATUSES.LOGIN_TIMEOUT, + STATUSES.NO_RESPONSE, + STATUSES.RETRY_WITH, + STATUSES.BLOCKED_BY_PARENTAL_CONTROL, + STATUSES.UNAVAILABLE_FOR_LEGAL_REASONS, + STATUSES.CLIENT_CLOSED_LOAD_BALANCED_REQUEST, + STATUSES.INVALID_X_FORWARDED_FOR, + STATUSES.REQUEST_HEADER_TOO_LARGE, + STATUSES.SSL_CERTIFICATE_ERROR, + STATUSES.SSL_CERTIFICATE_REQUIRED, + STATUSES.HTTP_REQUEST_SENT_TO_HTTPS_PORT, + STATUSES.INVALID_TOKEN, + STATUSES.CLIENT_CLOSED_REQUEST, + STATUSES.INTERNAL_SERVER_ERROR, + STATUSES.NOT_IMPLEMENTED, + STATUSES.BAD_GATEWAY, + STATUSES.SERVICE_UNAVAILABLE, + STATUSES.GATEWAY_TIMEOUT, + STATUSES.HTTP_VERSION_NOT_SUPPORTED, + STATUSES.VARIANT_ALSO_NEGOTIATES, + STATUSES.INSUFFICIENT_STORAGE, + STATUSES.LOOP_DETECTED, + STATUSES.BANDWIDTH_LIMIT_EXCEEDED, + STATUSES.NOT_EXTENDED, + STATUSES.NETWORK_AUTHENTICATION_REQUIRED, + STATUSES.WEB_SERVER_UNKNOWN_ERROR, + STATUSES.WEB_SERVER_IS_DOWN, + STATUSES.CONNECTION_TIMEOUT, + STATUSES.ORIGIN_IS_UNREACHABLE, + STATUSES.TIMEOUT_OCCURED, + STATUSES.SSL_HANDSHAKE_FAILED, + STATUSES.INVALID_SSL_CERTIFICATE, + STATUSES.RAILGUN_ERROR, + STATUSES.SITE_IS_OVERLOADED, + STATUSES.SITE_IS_FROZEN, + STATUSES.IDENTITY_PROVIDER_AUTHENTICATION_ERROR, + STATUSES.NETWORK_READ_TIMEOUT, + STATUSES.NETWORK_CONNECT_TIMEOUT, +]; + +export enum FINISH { + SAFE = 0, + SAFE_WITH_CB = 1, + UNSAFE = 2, +} + +// Internal + +export type CharList = Array; + +export const ALPHA: CharList = []; + +for (let i = 'A'.charCodeAt(0); i <= 'Z'.charCodeAt(0); i++) { + // Upper case + ALPHA.push(String.fromCharCode(i)); + + // Lower case + ALPHA.push(String.fromCharCode(i + 0x20)); +} + +export const NUM_MAP = { + 0: 0, 1: 1, 2: 2, 3: 3, 4: 4, + 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, +}; + +export const HEX_MAP = { + 0: 0, 1: 1, 2: 2, 3: 3, 4: 4, + 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, + A: 0XA, B: 0XB, C: 0XC, D: 0XD, E: 0XE, F: 0XF, + a: 0xa, b: 0xb, c: 0xc, d: 0xd, e: 0xe, f: 0xf, +}; + +export const NUM: CharList = [ + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', +]; + +export const ALPHANUM: CharList = ALPHA.concat(NUM); +export const MARK: CharList = [ '-', '_', '.', '!', '~', '*', '\'', '(', ')' ]; +export const USERINFO_CHARS: CharList = ALPHANUM + .concat(MARK) + .concat([ '%', ';', ':', '&', '=', '+', '$', ',' ]); + +// TODO(indutny): use RFC +export const URL_CHAR: CharList = ([ + '!', '"', '$', '%', '&', '\'', + '(', ')', '*', '+', ',', '-', '.', '/', + ':', ';', '<', '=', '>', + '@', '[', '\\', ']', '^', '_', + '`', + '{', '|', '}', '~', +] as CharList).concat(ALPHANUM); + +export const HEX: CharList = NUM.concat( + [ 'a', 'b', 'c', 'd', 'e', 'f', 'A', 'B', 'C', 'D', 'E', 'F' ]); + +/* Tokens as defined by rfc 2616. Also lowercases them. + * token = 1* + * separators = "(" | ")" | "<" | ">" | "@" + * | "," | ";" | ":" | "\" | <"> + * | "/" | "[" | "]" | "?" | "=" + * | "{" | "}" | SP | HT + */ +export const TOKEN: CharList = ([ + '!', '#', '$', '%', '&', '\'', + '*', '+', '-', '.', + '^', '_', '`', + '|', '~', +] as CharList).concat(ALPHANUM); + +/* + * Verify that a char is a valid visible (printable) US-ASCII + * character or %x80-FF + */ +export const HEADER_CHARS: CharList = [ '\t' ]; +for (let i = 32; i <= 255; i++) { + if (i !== 127) { + HEADER_CHARS.push(i); + } +} + +// ',' = \x44 +export const CONNECTION_TOKEN_CHARS: CharList = + HEADER_CHARS.filter((c: string | number) => c !== 44); + +export const QUOTED_STRING: CharList = [ '\t', ' ' ]; +for (let i = 0x21; i <= 0xff; i++) { + if (i !== 0x22 && i !== 0x5c) { // All characters in ASCII except \ and " + QUOTED_STRING.push(i); + } +} + +export const HTAB_SP_VCHAR_OBS_TEXT: CharList = [ '\t', ' ' ]; + +// VCHAR: https://tools.ietf.org/html/rfc5234#appendix-B.1 +for (let i = 0x21; i <= 0x7E; i++) { + HTAB_SP_VCHAR_OBS_TEXT.push(i); +} +// OBS_TEXT: https://datatracker.ietf.org/doc/html/rfc9110#name-collected-abnf +for (let i = 0x80; i <= 0xff; i++) { + HTAB_SP_VCHAR_OBS_TEXT.push(i); +} + +export const MAJOR = NUM_MAP; +export const MINOR = MAJOR; + +export enum HEADER_STATE { + GENERAL = 0, + CONNECTION = 1, + CONTENT_LENGTH = 2, + TRANSFER_ENCODING = 3, + UPGRADE = 4, + + CONNECTION_KEEP_ALIVE = 5, + CONNECTION_CLOSE = 6, + CONNECTION_UPGRADE = 7, + TRANSFER_ENCODING_CHUNKED = 8, +} + +export const SPECIAL_HEADERS = { + 'connection': HEADER_STATE.CONNECTION, + 'content-length': HEADER_STATE.CONTENT_LENGTH, + 'proxy-connection': HEADER_STATE.CONNECTION, + 'transfer-encoding': HEADER_STATE.TRANSFER_ENCODING, + 'upgrade': HEADER_STATE.UPGRADE, +}; diff --git a/vendor/llhttp/src/llhttp/http.ts b/vendor/llhttp/src/llhttp/http.ts new file mode 100644 index 0000000..d0bfd48 --- /dev/null +++ b/vendor/llhttp/src/llhttp/http.ts @@ -0,0 +1,1298 @@ +import * as assert from 'assert'; +import { LLParse, source } from 'llparse'; + +import Match = source.node.Match; +import Node = source.node.Node; + +import { + CharList, + CONNECTION_TOKEN_CHARS, ERROR, FINISH, FLAGS, H_METHOD_MAP, HEADER_CHARS, + HEADER_STATE, HEX_MAP, HTAB_SP_VCHAR_OBS_TEXT, + LENIENT_FLAGS, + MAJOR, METHOD_MAP, METHODS, METHODS_HTTP, METHODS_ICE, METHODS_RTSP, + MINOR, NUM_MAP, QUOTED_STRING, SPECIAL_HEADERS, + TOKEN, TYPE, +} from './constants'; +import { URL } from './url'; + +type MaybeNode = string | Match | Node; + +const NODES: ReadonlyArray = [ + 'start', + 'after_start', + 'start_req', + 'after_start_req', + 'start_res', + 'start_req_or_res', + + 'req_or_res_method', + + 'res_http_major', + 'res_http_dot', + 'res_http_minor', + 'res_http_end', + 'res_after_version', + 'res_status_code_digit_1', + 'res_status_code_digit_2', + 'res_status_code_digit_3', + 'res_status_code_otherwise', + 'res_status_start', + 'res_status', + 'res_line_almost_done', + + 'req_first_space_before_url', + 'req_spaces_before_url', + 'req_http_start', + 'req_http_version', + 'req_http_major', + 'req_http_dot', + 'req_http_minor', + 'req_http_end', + 'req_http_complete', + 'req_http_complete_crlf', + + 'req_pri_upgrade', + + 'headers_start', + 'header_field_start', + 'header_field', + 'header_field_colon', + 'header_field_colon_discard_ws', + 'header_field_general', + 'header_field_general_otherwise', + 'header_value_discard_ws', + 'header_value_discard_ws_almost_done', + 'header_value_discard_lws', + 'header_value_start', + 'header_value', + 'header_value_otherwise', + 'header_value_lenient', + 'header_value_lenient_failed', + 'header_value_lws', + 'header_value_te_chunked', + 'header_value_te_chunked_last', + 'header_value_te_token', + 'header_value_te_token_ows', + 'header_value_content_length_once', + 'header_value_content_length', + 'header_value_content_length_ws', + 'header_value_connection', + 'header_value_connection_ws', + 'header_value_connection_token', + 'header_value_almost_done', + + 'headers_almost_done', + 'headers_done', + + 'chunk_size_start', + 'chunk_size_digit', + 'chunk_size', + 'chunk_size_otherwise', + 'chunk_size_almost_done', + 'chunk_size_almost_done_lf', + 'chunk_extensions', + 'chunk_extension_name', + 'chunk_extension_value', + 'chunk_extension_quoted_value', + 'chunk_extension_quoted_value_quoted_pair', + 'chunk_extension_quoted_value_done', + 'chunk_data', + 'chunk_data_almost_done', + 'chunk_complete', + 'body_identity', + 'body_identity_eof', + + 'message_done', + + 'eof', + 'cleanup', + 'closed', + 'restart', +]; + +interface ISpanMap { + readonly status: source.Span; + readonly method: source.Span; + readonly version: source.Span; + readonly headerField: source.Span; + readonly headerValue: source.Span; + readonly chunkExtensionName: source.Span; + readonly chunkExtensionValue: source.Span; + readonly body: source.Span; +} + +interface ICallbackMap { + readonly onMessageBegin: source.code.Code; + readonly onUrlComplete: source.code.Code; + readonly onMethodComplete: source.code.Code; + readonly onVersionComplete: source.code.Code; + readonly onStatusComplete: source.code.Code; + readonly beforeHeadersComplete: source.code.Code; + readonly onHeaderFieldComplete: source.code.Code; + readonly onHeaderValueComplete: source.code.Code; + readonly onHeadersComplete: source.code.Code; + readonly afterHeadersComplete: source.code.Code; + readonly onChunkHeader: source.code.Code; + readonly onChunkExtensionName: source.code.Code; + readonly onChunkExtensionValue: source.code.Code; + readonly onChunkComplete: source.code.Code; + readonly onMessageComplete: source.code.Code; + readonly afterMessageComplete: source.code.Code; + readonly onReset: source.code.Code; +} + +interface IMulTargets { + readonly overflow: string | Node; + readonly success: string | Node; +} + +interface IMulOptions { + readonly base: number; + readonly max?: number; + readonly signed: boolean; +} + +interface IIsEqualTargets { + readonly equal: string | Node; + readonly notEqual: string | Node; +} + +export interface IHTTPResult { + readonly entry: Node; +} + +export class HTTP { + private readonly url: URL; + private readonly TOKEN: CharList; + private readonly span: ISpanMap; + private readonly callback: ICallbackMap; + private readonly nodes: Map = new Map(); + + constructor(private readonly llparse: LLParse) { + const p = llparse; + + this.url = new URL(p); + this.TOKEN = TOKEN; + + this.span = { + body: p.span(p.code.span('llhttp__on_body')), + chunkExtensionName: p.span(p.code.span('llhttp__on_chunk_extension_name')), + chunkExtensionValue: p.span(p.code.span('llhttp__on_chunk_extension_value')), + headerField: p.span(p.code.span('llhttp__on_header_field')), + headerValue: p.span(p.code.span('llhttp__on_header_value')), + method: p.span(p.code.span('llhttp__on_method')), + status: p.span(p.code.span('llhttp__on_status')), + version: p.span(p.code.span('llhttp__on_version')), + }; + + /* tslint:disable:object-literal-sort-keys */ + this.callback = { + // User callbacks + onUrlComplete: p.code.match('llhttp__on_url_complete'), + onStatusComplete: p.code.match('llhttp__on_status_complete'), + onMethodComplete: p.code.match('llhttp__on_method_complete'), + onVersionComplete: p.code.match('llhttp__on_version_complete'), + onHeaderFieldComplete: p.code.match('llhttp__on_header_field_complete'), + onHeaderValueComplete: p.code.match('llhttp__on_header_value_complete'), + onHeadersComplete: p.code.match('llhttp__on_headers_complete'), + onMessageBegin: p.code.match('llhttp__on_message_begin'), + onMessageComplete: p.code.match('llhttp__on_message_complete'), + onChunkHeader: p.code.match('llhttp__on_chunk_header'), + onChunkExtensionName: p.code.match('llhttp__on_chunk_extension_name_complete'), + onChunkExtensionValue: p.code.match('llhttp__on_chunk_extension_value_complete'), + onChunkComplete: p.code.match('llhttp__on_chunk_complete'), + onReset: p.code.match('llhttp__on_reset'), + + // Internal callbacks `src/http.c` + beforeHeadersComplete: + p.code.match('llhttp__before_headers_complete'), + afterHeadersComplete: p.code.match('llhttp__after_headers_complete'), + afterMessageComplete: p.code.match('llhttp__after_message_complete'), + }; + /* tslint:enable:object-literal-sort-keys */ + + for (const name of NODES) { + this.nodes.set(name, p.node(name) as Match); + } + } + + public build(): IHTTPResult { + const p = this.llparse; + + p.property('i64', 'content_length'); + p.property('i8', 'type'); + p.property('i8', 'method'); + p.property('i8', 'http_major'); + p.property('i8', 'http_minor'); + p.property('i8', 'header_state'); + p.property('i16', 'lenient_flags'); + p.property('i8', 'upgrade'); + p.property('i8', 'finish'); + p.property('i16', 'flags'); + p.property('i16', 'status_code'); + p.property('i8', 'initial_message_completed'); + + // Verify defaults + assert.strictEqual(FINISH.SAFE, 0); + assert.strictEqual(TYPE.BOTH, 0); + + // Shared settings (to be used in C wrapper) + p.property('ptr', 'settings'); + + this.buildLine(); + this.buildHeaders(); + + return { + entry: this.node('start'), + }; + } + + private buildLine(): void { + const p = this.llparse; + const span = this.span; + const n = (name: string): Match => this.node(name); + + const url = this.url.build(); + + const switchType = this.load('type', { + [TYPE.REQUEST]: n('start_req'), + [TYPE.RESPONSE]: n('start_res'), + }, n('start_req_or_res')); + + n('start') + .match([ '\r', '\n' ], n('start')) + .otherwise( + this.load('initial_message_completed', { + 1: this.invokePausable('on_reset', ERROR.CB_RESET, n('after_start')), + }, n('after_start')), + ); + + n('after_start').otherwise( + this.update( + 'finish', + FINISH.UNSAFE, + this.invokePausable('on_message_begin', ERROR.CB_MESSAGE_BEGIN, switchType), + ), + ); + + n('start_req_or_res') + .peek('H', this.span.method.start(n('req_or_res_method'))) + .otherwise(this.update('type', TYPE.REQUEST, 'start_req')); + + n('req_or_res_method') + .select(H_METHOD_MAP, this.store('method', + this.update('type', TYPE.REQUEST, this.span.method.end( + this.invokePausable('on_method_complete', ERROR.CB_METHOD_COMPLETE, n('req_first_space_before_url')), + )), + )) + .match('HTTP/', this.span.method.end(this.update('type', TYPE.RESPONSE, + this.span.version.start(n('res_http_major'))))) + .otherwise(p.error(ERROR.INVALID_CONSTANT, 'Invalid word encountered')); + + const checkVersion = (destination: string): Node => { + const node = n(destination); + const errorNode = this.span.version.end(p.error(ERROR.INVALID_VERSION, 'Invalid HTTP version')); + + return this.testLenientFlags(LENIENT_FLAGS.VERSION, + { + 1: node, + }, + this.load('http_major', { + 0: this.load('http_minor', { + 9: node, + }, errorNode), + 1: this.load('http_minor', { + 0: node, + 1: node, + }, errorNode), + 2: this.load('http_minor', { + 0: node, + }, errorNode), + }, errorNode), + ); + }; + + const checkIfAllowLFWithoutCR = (success: Node, failure: Node) => { + return this.testLenientFlags(LENIENT_FLAGS.OPTIONAL_CR_BEFORE_LF, { 1: success }, failure); + }; + + // Response + n('start_res') + .match('HTTP/', span.version.start(n('res_http_major'))) + .otherwise(p.error(ERROR.INVALID_CONSTANT, 'Expected HTTP/')); + + n('res_http_major') + .select(MAJOR, this.store('http_major', 'res_http_dot')) + .otherwise(this.span.version.end(p.error(ERROR.INVALID_VERSION, 'Invalid major version'))); + + n('res_http_dot') + .match('.', n('res_http_minor')) + .otherwise(this.span.version.end(p.error(ERROR.INVALID_VERSION, 'Expected dot'))); + + n('res_http_minor') + .select(MINOR, this.store('http_minor', checkVersion('res_http_end'))) + .otherwise(this.span.version.end(p.error(ERROR.INVALID_VERSION, 'Invalid minor version'))); + + n('res_http_end') + .otherwise(this.span.version.end( + this.invokePausable('on_version_complete', ERROR.CB_VERSION_COMPLETE, 'res_after_version'), + )); + + n('res_after_version') + .match(' ', this.update('status_code', 0, 'res_status_code_digit_1')) + .otherwise(p.error(ERROR.INVALID_VERSION, + 'Expected space after version')); + + n('res_status_code_digit_1') + .select(NUM_MAP, this.mulAdd('status_code', { + overflow: p.error(ERROR.INVALID_STATUS, 'Invalid status code'), + success: 'res_status_code_digit_2', + })) + .otherwise(p.error(ERROR.INVALID_STATUS, 'Invalid status code')); + + n('res_status_code_digit_2') + .select(NUM_MAP, this.mulAdd('status_code', { + overflow: p.error(ERROR.INVALID_STATUS, 'Invalid status code'), + success: 'res_status_code_digit_3', + })) + .otherwise(p.error(ERROR.INVALID_STATUS, 'Invalid status code')); + + n('res_status_code_digit_3') + .select(NUM_MAP, this.mulAdd('status_code', { + overflow: p.error(ERROR.INVALID_STATUS, 'Invalid status code'), + success: 'res_status_code_otherwise', + })) + .otherwise(p.error(ERROR.INVALID_STATUS, 'Invalid status code')); + + const onStatusComplete = this.invokePausable( + 'on_status_complete', ERROR.CB_STATUS_COMPLETE, n('headers_start'), + ); + + n('res_status_code_otherwise') + .match(' ', n('res_status_start')) + .match('\r', n('res_line_almost_done')) + .match( + '\n', + checkIfAllowLFWithoutCR( + onStatusComplete, + p.error(ERROR.INVALID_STATUS, 'Invalid response status'), + ), + ) + .otherwise(p.error(ERROR.INVALID_STATUS, 'Invalid response status')); + + n('res_status_start') + .otherwise(span.status.start(n('res_status'))); + + n('res_status') + .peek('\r', span.status.end().skipTo(n('res_line_almost_done'))) + .peek( + '\n', + span.status.end().skipTo( + checkIfAllowLFWithoutCR( + onStatusComplete, + p.error(ERROR.CR_EXPECTED, 'Missing expected CR after response line'), + ), + ), + ) + .skipTo(n('res_status')); + + n('res_line_almost_done') + .match(['\r', '\n'], onStatusComplete) + .otherwise(this.testLenientFlags(LENIENT_FLAGS.OPTIONAL_LF_AFTER_CR, { + 1: onStatusComplete, + }, p.error(ERROR.STRICT, 'Expected LF after CR'))); + + // Request + n('start_req').otherwise(this.span.method.start(n('after_start_req'))); + + n('after_start_req') + .select(METHOD_MAP, this.store('method', this.span.method.end( + this.invokePausable('on_method_complete', ERROR.CB_METHOD_COMPLETE, n('req_first_space_before_url'), + )))) + .otherwise(p.error(ERROR.INVALID_METHOD, 'Invalid method encountered')); + + n('req_first_space_before_url') + .match(' ', n('req_spaces_before_url')) + .otherwise(p.error(ERROR.INVALID_METHOD, 'Expected space after method')); + + n('req_spaces_before_url') + .match(' ', n('req_spaces_before_url')) + .otherwise(this.isEqual('method', METHODS.CONNECT, { + equal: url.entry.connect, + notEqual: url.entry.normal, + })); + + const onUrlCompleteHTTP = this.invokePausable( + 'on_url_complete', ERROR.CB_URL_COMPLETE, n('req_http_start'), + ); + + url.exit.toHTTP + .otherwise(onUrlCompleteHTTP); + + const onUrlCompleteHTTP09 = this.invokePausable( + 'on_url_complete', ERROR.CB_URL_COMPLETE, n('headers_start'), + ); + + url.exit.toHTTP09 + .otherwise( + this.update('http_major', 0, + this.update('http_minor', 9, onUrlCompleteHTTP09)), + ); + + const checkMethod = (methods: METHODS[], error: string): Node => { + const success = n('req_http_version'); + const failure = p.error(ERROR.INVALID_CONSTANT, error); + + const map: { [key: number]: Node } = {}; + for (const method of methods) { + map[method] = success; + } + + return this.load('method', map, failure); + }; + + n('req_http_start') + .match('HTTP/', checkMethod(METHODS_HTTP, + 'Invalid method for HTTP/x.x request')) + .match('RTSP/', checkMethod(METHODS_RTSP, + 'Invalid method for RTSP/x.x request')) + .match('ICE/', checkMethod(METHODS_ICE, + 'Expected SOURCE method for ICE/x.x request')) + .match(' ', n('req_http_start')) + .otherwise(p.error(ERROR.INVALID_CONSTANT, 'Expected HTTP/')); + + n('req_http_version').otherwise(span.version.start(n('req_http_major'))); + + n('req_http_major') + .select(MAJOR, this.store('http_major', 'req_http_dot')) + .otherwise(this.span.version.end(p.error(ERROR.INVALID_VERSION, 'Invalid major version'))); + + n('req_http_dot') + .match('.', n('req_http_minor')) + .otherwise(this.span.version.end(p.error(ERROR.INVALID_VERSION, 'Expected dot'))); + + n('req_http_minor') + .select(MINOR, this.store('http_minor', checkVersion('req_http_end'))) + .otherwise(this.span.version.end(p.error(ERROR.INVALID_VERSION, 'Invalid minor version'))); + + n('req_http_end').otherwise( + span.version.end( + this.invokePausable( + 'on_version_complete', + ERROR.CB_VERSION_COMPLETE, + this.load('method', { + [METHODS.PRI]: n('req_pri_upgrade'), + }, n('req_http_complete')), + ), + ), + ); + + n('req_http_complete') + .match('\r', n('req_http_complete_crlf')) + .match( + '\n', + checkIfAllowLFWithoutCR( + n('req_http_complete_crlf'), + p.error(ERROR.INVALID_VERSION, 'Expected CRLF after version'), + ), + ) + .otherwise(p.error(ERROR.INVALID_VERSION, 'Expected CRLF after version')); + + n('req_http_complete_crlf') + .match('\n', n('headers_start')) + .otherwise(this.testLenientFlags(LENIENT_FLAGS.OPTIONAL_LF_AFTER_CR, { + 1: n('headers_start'), + }, p.error(ERROR.STRICT, 'Expected CRLF after version'))); + + n('req_pri_upgrade') + .match('\r\n\r\nSM\r\n\r\n', + p.error(ERROR.PAUSED_H2_UPGRADE, 'Pause on PRI/Upgrade')) + .otherwise( + p.error(ERROR.INVALID_VERSION, 'Expected HTTP/2 Connection Preface')); + } + + private buildHeaders(): void { + this.buildHeaderField(); + this.buildHeaderValue(); + } + + private buildHeaderField(): void { + const p = this.llparse; + const span = this.span; + const n = (name: string): Match => this.node(name); + + const onInvalidHeaderFieldChar = + p.error(ERROR.INVALID_HEADER_TOKEN, 'Invalid header field char'); + + n('headers_start') + .match(' ', + this.testLenientFlags(LENIENT_FLAGS.HEADERS, { + 1: n('header_field_start'), + }, p.error(ERROR.UNEXPECTED_SPACE, 'Unexpected space after start line')), + ) + .otherwise(n('header_field_start')); + + n('header_field_start') + .match('\r', n('headers_almost_done')) + .match('\n', + this.testLenientFlags(LENIENT_FLAGS.OPTIONAL_CR_BEFORE_LF, { + 1: this.testFlags(FLAGS.TRAILING, { + 1: this.invokePausable('on_chunk_complete', + ERROR.CB_CHUNK_COMPLETE, 'message_done'), + }).otherwise(this.headersCompleted()), + }, onInvalidHeaderFieldChar), + ) + .otherwise(span.headerField.start(n('header_field'))); + + n('header_field') + .transform(p.transform.toLower()) + // Match headers that need special treatment + .select(SPECIAL_HEADERS, this.store('header_state', 'header_field_colon')) + .otherwise(this.resetHeaderState('header_field_general')); + + /* https://www.rfc-editor.org/rfc/rfc7230.html#section-3.3.3, paragraph 3. + * + * If a message is received with both a Transfer-Encoding and a + * Content-Length header field, the Transfer-Encoding overrides the + * Content-Length. Such a message might indicate an attempt to + * perform request smuggling (Section 9.5) or response splitting + * (Section 9.4) and **ought to be handled as an error**. A sender MUST + * remove the received Content-Length field prior to forwarding such + * a message downstream. + * + * Since llhttp 9, we go for the stricter approach and treat this as an error. + */ + const checkInvalidTransferEncoding = (otherwise: Node) => { + return this.testFlags(FLAGS.CONTENT_LENGTH, { + 1: this.testLenientFlags(LENIENT_FLAGS.CHUNKED_LENGTH, { + 0: p.error(ERROR.INVALID_TRANSFER_ENCODING, "Transfer-Encoding can't be present with Content-Length"), + }).otherwise(otherwise), + }).otherwise(otherwise); + }; + + const checkInvalidContentLength = (otherwise: Node) => { + return this.testFlags(FLAGS.TRANSFER_ENCODING, { + 1: this.testLenientFlags(LENIENT_FLAGS.CHUNKED_LENGTH, { + 0: p.error(ERROR.INVALID_CONTENT_LENGTH, "Content-Length can't be present with Transfer-Encoding"), + }).otherwise(otherwise), + }).otherwise(otherwise); + }; + + const onHeaderFieldComplete = this.invokePausable( + 'on_header_field_complete', ERROR.CB_HEADER_FIELD_COMPLETE, + this.load('header_state', { + [HEADER_STATE.TRANSFER_ENCODING]: checkInvalidTransferEncoding(n('header_value_discard_ws')), + [HEADER_STATE.CONTENT_LENGTH]: checkInvalidContentLength(n('header_value_discard_ws')), + }, 'header_value_discard_ws'), + ); + + const checkLenientFlagsOnColon = + this.testLenientFlags(LENIENT_FLAGS.HEADERS, { + 1: n('header_field_colon_discard_ws'), + }, span.headerField.end().skipTo(onInvalidHeaderFieldChar)); + + n('header_field_colon') + // https://datatracker.ietf.org/doc/html/rfc7230#section-3.2.4 + // Whitespace character is not allowed between the header field-name + // and colon. If the next token matches whitespace then throw an error. + // + // Add a check for the lenient flag. If the lenient flag is set, the + // whitespace token is allowed to support legacy code not following + // http specs. + .peek(' ', checkLenientFlagsOnColon) + .peek(':', span.headerField.end().skipTo(onHeaderFieldComplete)) + // Fallback to general header, there're additional characters: + // `Connection-Duration` instead of `Connection` and so on. + .otherwise(this.resetHeaderState('header_field_general')); + + n('header_field_colon_discard_ws') + .match(' ', n('header_field_colon_discard_ws')) + .otherwise(n('header_field_colon')); + + n('header_field_general') + .match(this.TOKEN, n('header_field_general')) + .otherwise(n('header_field_general_otherwise')); + + // Just a performance optimization, split the node so that the fast case + // remains in `header_field_general` + n('header_field_general_otherwise') + .peek(':', span.headerField.end().skipTo(onHeaderFieldComplete)) + .otherwise(p.error(ERROR.INVALID_HEADER_TOKEN, 'Invalid header token')); + } + + private buildHeaderValue(): void { + const p = this.llparse; + const span = this.span; + const callback = this.callback; + const n = (name: string): Match => this.node(name); + + const fallback = this.resetHeaderState('header_value'); + + n('header_value_discard_ws') + .match([ ' ', '\t' ], n('header_value_discard_ws')) + .match('\r', n('header_value_discard_ws_almost_done')) + .match('\n', this.testLenientFlags(LENIENT_FLAGS.OPTIONAL_CR_BEFORE_LF, { + 1: n('header_value_discard_lws'), + }, p.error(ERROR.INVALID_HEADER_TOKEN, 'Invalid header value char'))) + .otherwise(span.headerValue.start(n('header_value_start'))); + + n('header_value_discard_ws_almost_done') + .match('\n', n('header_value_discard_lws')) + .otherwise( + this.testLenientFlags(LENIENT_FLAGS.HEADERS, { + 1: n('header_value_discard_lws'), + }, p.error(ERROR.STRICT, 'Expected LF after CR')), + ); + + const onHeaderValueComplete = this.invokePausable( + 'on_header_value_complete', ERROR.CB_HEADER_VALUE_COMPLETE, n('header_field_start'), + ); + + const emptyContentLengthError = p.error( + ERROR.INVALID_CONTENT_LENGTH, 'Empty Content-Length'); + const checkContentLengthEmptiness = this.load('header_state', { + [HEADER_STATE.CONTENT_LENGTH]: emptyContentLengthError, + }, this.setHeaderFlags( + this.emptySpan(span.headerValue, onHeaderValueComplete))); + + n('header_value_discard_lws') + .match([ ' ', '\t' ], this.testLenientFlags(LENIENT_FLAGS.HEADERS, { + 1: n('header_value_discard_ws'), + }, p.error(ERROR.INVALID_HEADER_TOKEN, 'Invalid header value char'))) + .otherwise(checkContentLengthEmptiness); + + // Multiple `Transfer-Encoding` headers should be treated as one, but with + // values separate by a comma. + // + // See: https://tools.ietf.org/html/rfc7230#section-3.2.2 + const toTransferEncoding = this.unsetFlag( + FLAGS.CHUNKED, + 'header_value_te_chunked'); + + // Once chunked has been selected, no other encoding is possible in requests + // https://datatracker.ietf.org/doc/html/rfc7230#section-3.3.1 + const forbidAfterChunkedInRequest = (otherwise: Node) => { + return this.load('type', { + [TYPE.REQUEST]: this.testLenientFlags(LENIENT_FLAGS.TRANSFER_ENCODING, { + 0: span.headerValue.end().skipTo( + p.error(ERROR.INVALID_TRANSFER_ENCODING, 'Invalid `Transfer-Encoding` header value'), + ), + }).otherwise(otherwise), + }, otherwise); + }; + + n('header_value_start') + .otherwise(this.load('header_state', { + [HEADER_STATE.UPGRADE]: this.setFlag(FLAGS.UPGRADE, fallback), + [HEADER_STATE.TRANSFER_ENCODING]: this.testFlags( + FLAGS.CHUNKED, + { + 1: forbidAfterChunkedInRequest(this.setFlag(FLAGS.TRANSFER_ENCODING, toTransferEncoding)), + }, + this.setFlag(FLAGS.TRANSFER_ENCODING, toTransferEncoding)), + [HEADER_STATE.CONTENT_LENGTH]: n('header_value_content_length_once'), + [HEADER_STATE.CONNECTION]: n('header_value_connection'), + }, 'header_value')); + + // + // Transfer-Encoding + // + + n('header_value_te_chunked') + .transform(p.transform.toLowerUnsafe()) + .match( + 'chunked', + n('header_value_te_chunked_last'), + ) + .otherwise(n('header_value_te_token')); + + n('header_value_te_chunked_last') + .match(' ', n('header_value_te_chunked_last')) + .peek([ '\r', '\n' ], this.update('header_state', + HEADER_STATE.TRANSFER_ENCODING_CHUNKED, + 'header_value_otherwise')) + .peek(',', forbidAfterChunkedInRequest(n('header_value_te_chunked'))) + .otherwise(n('header_value_te_token')); + + n('header_value_te_token') + .match(',', n('header_value_te_token_ows')) + .match(CONNECTION_TOKEN_CHARS, n('header_value_te_token')) + .otherwise(fallback); + + n('header_value_te_token_ows') + .match([ ' ', '\t' ], n('header_value_te_token_ows')) + .otherwise(n('header_value_te_chunked')); + + // + // Content-Length + // + + const invalidContentLength = (reason: string): Node => { + // End span for easier testing + // TODO(indutny): minimize code size + return span.headerValue.end() + .otherwise(p.error(ERROR.INVALID_CONTENT_LENGTH, reason)); + }; + + n('header_value_content_length_once') + .otherwise(this.testFlags(FLAGS.CONTENT_LENGTH, { + 0: n('header_value_content_length'), + }, p.error(ERROR.UNEXPECTED_CONTENT_LENGTH, 'Duplicate Content-Length'))); + + n('header_value_content_length') + .select(NUM_MAP, this.mulAdd('content_length', { + overflow: invalidContentLength('Content-Length overflow'), + success: 'header_value_content_length', + })) + .otherwise(n('header_value_content_length_ws')); + + n('header_value_content_length_ws') + .match(' ', n('header_value_content_length_ws')) + .peek([ '\r', '\n' ], + this.setFlag(FLAGS.CONTENT_LENGTH, 'header_value_otherwise')) + .otherwise(invalidContentLength('Invalid character in Content-Length')); + + // + // Connection + // + + n('header_value_connection') + .transform(p.transform.toLower()) + // TODO(indutny): extra node for token back-edge? + // Skip lws + .match([ ' ', '\t' ], n('header_value_connection')) + .match( + 'close', + this.update('header_state', HEADER_STATE.CONNECTION_CLOSE, + 'header_value_connection_ws'), + ) + .match( + 'upgrade', + this.update('header_state', HEADER_STATE.CONNECTION_UPGRADE, + 'header_value_connection_ws'), + ) + .match( + 'keep-alive', + this.update('header_state', HEADER_STATE.CONNECTION_KEEP_ALIVE, + 'header_value_connection_ws'), + ) + .otherwise(n('header_value_connection_token')); + + n('header_value_connection_ws') + .match(',', this.setHeaderFlags('header_value_connection')) + .match(' ', n('header_value_connection_ws')) + .peek([ '\r', '\n' ], n('header_value_otherwise')) + .otherwise(this.resetHeaderState('header_value_connection_token')); + + n('header_value_connection_token') + .match(',', n('header_value_connection')) + .match(CONNECTION_TOKEN_CHARS, + n('header_value_connection_token')) + .otherwise(n('header_value_otherwise')); + + // Split for performance reasons + n('header_value') + .match(HEADER_CHARS, n('header_value')) + .otherwise(n('header_value_otherwise')); + + const checkIfAllowLFWithoutCR = (success: Node, failure: Node) => { + return this.testLenientFlags(LENIENT_FLAGS.OPTIONAL_CR_BEFORE_LF, { 1: success }, failure); + }; + + const checkLenient = this.testLenientFlags(LENIENT_FLAGS.HEADERS, { + 1: n('header_value_lenient'), + }, span.headerValue.end(p.error(ERROR.INVALID_HEADER_TOKEN, 'Invalid header value char'))); + + n('header_value_otherwise') + .peek('\r', span.headerValue.end().skipTo(n('header_value_almost_done'))) + .peek( + '\n', + span.headerValue.end( + checkIfAllowLFWithoutCR( + n('header_value_almost_done'), + p.error(ERROR.CR_EXPECTED, 'Missing expected CR after header value'), + ), + ), + ) + .otherwise(checkLenient); + + n('header_value_lenient') + .peek('\r', span.headerValue.end().skipTo(n('header_value_almost_done'))) + .peek('\n', span.headerValue.end(n('header_value_almost_done'))) + .skipTo(n('header_value_lenient')); + + n('header_value_almost_done') + .match('\n', n('header_value_lws')) + .otherwise(p.error(ERROR.LF_EXPECTED, + 'Missing expected LF after header value')); + + n('header_value_lws') + .peek([ ' ', '\t' ], + this.load('header_state', { + [HEADER_STATE.TRANSFER_ENCODING_CHUNKED]: + this.resetHeaderState(span.headerValue.start(n('header_value_start'))), + }, span.headerValue.start(n('header_value_start')))) + .otherwise(this.setHeaderFlags(onHeaderValueComplete)); + + const checkTrailing = this.testFlags(FLAGS.TRAILING, { + 1: this.invokePausable('on_chunk_complete', + ERROR.CB_CHUNK_COMPLETE, 'message_done'), + }).otherwise(this.headersCompleted()); + + n('headers_almost_done') + .match('\n', checkTrailing) + .otherwise( + this.testLenientFlags(LENIENT_FLAGS.OPTIONAL_LF_AFTER_CR, { + 1: checkTrailing, + }, p.error(ERROR.STRICT, 'Expected LF after headers'))); + + const upgradePause = p.pause(ERROR.PAUSED_UPGRADE, + 'Pause on CONNECT/Upgrade'); + + const afterHeadersComplete = p.invoke(callback.afterHeadersComplete, { + 1: this.invokePausable('on_message_complete', + ERROR.CB_MESSAGE_COMPLETE, upgradePause), + 2: n('chunk_size_start'), + 3: n('body_identity'), + 4: n('body_identity_eof'), + + // non-chunked `Transfer-Encoding` for request, see `src/native/http.c` + 5: p.error(ERROR.INVALID_TRANSFER_ENCODING, + 'Request has invalid `Transfer-Encoding`'), + }); + + n('headers_done') + .otherwise(afterHeadersComplete); + + upgradePause + .otherwise(n('cleanup')); + + afterHeadersComplete + .otherwise(this.invokePausable('on_message_complete', + ERROR.CB_MESSAGE_COMPLETE, 'cleanup')); + + n('body_identity') + .otherwise(span.body.start() + .otherwise(p.consume('content_length').otherwise( + span.body.end(n('message_done'))))); + + n('body_identity_eof') + .otherwise( + this.update('finish', FINISH.SAFE_WITH_CB, span.body.start(n('eof')))); + + // Just read everything until EOF + n('eof') + .skipTo(n('eof')); + + n('chunk_size_start') + .otherwise(this.update('content_length', 0, 'chunk_size_digit')); + + const addContentLength = this.mulAdd('content_length', { + overflow: p.error(ERROR.INVALID_CHUNK_SIZE, 'Chunk size overflow'), + success: 'chunk_size', + }, { signed: false, base: 0x10 }); + + n('chunk_size_digit') + .select(HEX_MAP, addContentLength) + .otherwise(p.error(ERROR.INVALID_CHUNK_SIZE, + 'Invalid character in chunk size')); + + n('chunk_size') + .select(HEX_MAP, addContentLength) + .otherwise(n('chunk_size_otherwise')); + + n('chunk_size_otherwise') + .match( + [ ' ', '\t' ], + this.testLenientFlags( + LENIENT_FLAGS.SPACES_AFTER_CHUNK_SIZE, + { + 1: n('chunk_size_otherwise'), + }, + p.error(ERROR.INVALID_CHUNK_SIZE, 'Invalid character in chunk size'), + ), + ) + .match('\r', n('chunk_size_almost_done')) + .match( + '\n', + checkIfAllowLFWithoutCR( + n('chunk_size_almost_done'), + p.error(ERROR.CR_EXPECTED, 'Missing expected CR after chunk size'), + ), + ) + .match(';', n('chunk_extensions')) + .otherwise(p.error(ERROR.INVALID_CHUNK_SIZE, + 'Invalid character in chunk size')); + + const onChunkExtensionNameCompleted = (destination: Node) => { + return this.invokePausable( + 'on_chunk_extension_name', ERROR.CB_CHUNK_EXTENSION_NAME_COMPLETE, destination); + }; + + const onChunkExtensionValueCompleted = (destination: Node) => { + return this.invokePausable( + 'on_chunk_extension_value', ERROR.CB_CHUNK_EXTENSION_VALUE_COMPLETE, destination); + }; + + n('chunk_extensions') + .match(' ', p.error(ERROR.STRICT, 'Invalid character in chunk extensions')) + .match('\r', p.error(ERROR.STRICT, 'Invalid character in chunk extensions')) + .otherwise(this.span.chunkExtensionName.start(n('chunk_extension_name'))); + + n('chunk_extension_name') + .match(TOKEN, n('chunk_extension_name')) + .peek('=', this.span.chunkExtensionName.end().skipTo( + this.span.chunkExtensionValue.start( + onChunkExtensionNameCompleted(n('chunk_extension_value')), + ), + )) + .peek(';', this.span.chunkExtensionName.end().skipTo( + onChunkExtensionNameCompleted(n('chunk_extensions')), + )) + .peek('\r', this.span.chunkExtensionName.end().skipTo( + onChunkExtensionNameCompleted(n('chunk_size_almost_done')), + )) + .peek('\n', this.span.chunkExtensionName.end( + onChunkExtensionNameCompleted( + checkIfAllowLFWithoutCR( + n('chunk_size_almost_done'), + p.error(ERROR.CR_EXPECTED, 'Missing expected CR after chunk extension name'), + ), + ), + )) + .otherwise(this.span.chunkExtensionName.end().skipTo( + p.error(ERROR.STRICT, 'Invalid character in chunk extensions name'), + )); + + n('chunk_extension_value') + .match('"', n('chunk_extension_quoted_value')) + .match(TOKEN, n('chunk_extension_value')) + .peek(';', this.span.chunkExtensionValue.end().skipTo( + onChunkExtensionValueCompleted(n('chunk_extensions')), + )) + .peek('\r', this.span.chunkExtensionValue.end().skipTo( + onChunkExtensionValueCompleted(n('chunk_size_almost_done')), + )) + .peek('\n', this.span.chunkExtensionValue.end( + onChunkExtensionValueCompleted( + checkIfAllowLFWithoutCR( + n('chunk_size_almost_done'), + p.error(ERROR.CR_EXPECTED, 'Missing expected CR after chunk extension value'), + ), + ), + )) + .otherwise(this.span.chunkExtensionValue.end().skipTo( + p.error(ERROR.STRICT, 'Invalid character in chunk extensions value'), + )); + + n('chunk_extension_quoted_value') + .match(QUOTED_STRING, n('chunk_extension_quoted_value')) + .match('"', this.span.chunkExtensionValue.end( + onChunkExtensionValueCompleted(n('chunk_extension_quoted_value_done')), + )) + .match('\\', n('chunk_extension_quoted_value_quoted_pair')) + .otherwise(this.span.chunkExtensionValue.end().skipTo( + p.error(ERROR.STRICT, 'Invalid character in chunk extensions quoted value'), + )); + + n('chunk_extension_quoted_value_quoted_pair') + .match(HTAB_SP_VCHAR_OBS_TEXT, n('chunk_extension_quoted_value')) + .otherwise(this.span.chunkExtensionValue.end().skipTo( + p.error(ERROR.STRICT, 'Invalid quoted-pair in chunk extensions quoted value'), + )); + + n('chunk_extension_quoted_value_done') + .match(';', n('chunk_extensions')) + .match('\r', n('chunk_size_almost_done')) + .peek( + '\n', + checkIfAllowLFWithoutCR( + n('chunk_size_almost_done'), + p.error(ERROR.CR_EXPECTED, 'Missing expected CR after chunk extension value'), + ), + ) + .otherwise(p.error(ERROR.STRICT, + 'Invalid character in chunk extensions quote value')); + + n('chunk_size_almost_done') + .match('\n', n('chunk_size_almost_done_lf')) + .otherwise( + this.testLenientFlags(LENIENT_FLAGS.OPTIONAL_LF_AFTER_CR, { + 1: n('chunk_size_almost_done_lf'), + }).otherwise(p.error(ERROR.STRICT, 'Expected LF after chunk size')), + ); + + const toChunk = this.isEqual('content_length', 0, { + equal: this.setFlag(FLAGS.TRAILING, 'header_field_start'), + notEqual: 'chunk_data', + }); + + n('chunk_size_almost_done_lf') + .otherwise(this.invokePausable('on_chunk_header', + ERROR.CB_CHUNK_HEADER, toChunk)); + + n('chunk_data') + .otherwise(span.body.start() + .otherwise(p.consume('content_length').otherwise( + span.body.end(n('chunk_data_almost_done'))))); + + n('chunk_data_almost_done') + .match('\r\n', n('chunk_complete')) + .match( + '\n', + checkIfAllowLFWithoutCR( + n('chunk_complete'), + p.error(ERROR.CR_EXPECTED, 'Missing expected CR after chunk data'), + ), + ) + .otherwise( + this.testLenientFlags(LENIENT_FLAGS.OPTIONAL_CRLF_AFTER_CHUNK, { + 1: n('chunk_complete'), + }).otherwise(p.error(ERROR.STRICT, 'Expected LF after chunk data')), + ); + + n('chunk_complete') + .otherwise(this.invokePausable('on_chunk_complete', + ERROR.CB_CHUNK_COMPLETE, 'chunk_size_start')); + + const upgradeAfterDone = this.isEqual('upgrade', 1, { + // Exit, the rest of the message is in a different protocol. + equal: upgradePause, + + // Restart + notEqual: 'cleanup', + }); + + n('message_done') + .otherwise(this.invokePausable('on_message_complete', + ERROR.CB_MESSAGE_COMPLETE, upgradeAfterDone)); + + const lenientClose = this.testLenientFlags(LENIENT_FLAGS.KEEP_ALIVE, { + 1: n('restart'), + }, n('closed')); + + // Check if we'd like to keep-alive + n('cleanup') + .otherwise(p.invoke(callback.afterMessageComplete, { + 1: this.update('content_length', 0, n('restart')), + }, this.update('finish', FINISH.SAFE, lenientClose))); + + const lenientDiscardAfterClose = this.testLenientFlags(LENIENT_FLAGS.DATA_AFTER_CLOSE, { + 1: n('closed'), + }, p.error(ERROR.CLOSED_CONNECTION, 'Data after `Connection: close`')); + + n('closed') + .match([ '\r', '\n' ], n('closed')) + .skipTo(lenientDiscardAfterClose); + + n('restart') + .otherwise( + this.update('initial_message_completed', 1, this.update('finish', FINISH.SAFE, n('start')), + )); + } + + private headersCompleted(): Node { + const p = this.llparse; + const callback = this.callback; + const n = (name: string): Match => this.node(name); + + // Set `upgrade` if needed + const beforeHeadersComplete = p.invoke(callback.beforeHeadersComplete); + + /* Here we call the headers_complete callback. This is somewhat + * different than other callbacks because if the user returns 1, we + * will interpret that as saying that this message has no body. This + * is needed for the annoying case of receiving a response to a HEAD + * request. + * + * We'd like to use CALLBACK_NOTIFY_NOADVANCE() here but we cannot, so + * we have to simulate it by handling a change in errno below. + */ + const onHeadersComplete = p.invoke(callback.onHeadersComplete, { + 0: n('headers_done'), + 1: this.setFlag(FLAGS.SKIPBODY, 'headers_done'), + 2: this.update('upgrade', 1, + this.setFlag(FLAGS.SKIPBODY, 'headers_done')), + [ERROR.PAUSED]: this.pause('Paused by on_headers_complete', + 'headers_done'), + }, p.error(ERROR.CB_HEADERS_COMPLETE, 'User callback error')); + + beforeHeadersComplete.otherwise(onHeadersComplete); + + return beforeHeadersComplete; + } + + private node(name: string | T): T { + if (name instanceof Node) { + return name; + } + + assert(this.nodes.has(name), `Unknown node with name "${name}"`); + return this.nodes.get(name)! as any; + } + + private load(field: string, map: { [key: number]: Node }, + next?: string | Node): Node { + const p = this.llparse; + + const res = p.invoke(p.code.load(field), map); + if (next !== undefined) { + res.otherwise(this.node(next)); + } + return res; + } + + private store(field: string, next?: string | Node): Node { + const p = this.llparse; + + const res = p.invoke(p.code.store(field)); + if (next !== undefined) { + res.otherwise(this.node(next)); + } + return res; + } + + private update(field: string, value: number, next?: string | Node): Node { + const p = this.llparse; + + const res = p.invoke(p.code.update(field, value)); + if (next !== undefined) { + res.otherwise(this.node(next)); + } + return res; + } + + private resetHeaderState(next: string | Node): Node { + return this.update('header_state', HEADER_STATE.GENERAL, next); + } + + private emptySpan(span: source.Span, next: string | Node): Node { + return span.start(span.end(this.node(next))); + } + + private unsetFlag(flag: FLAGS, next: string | Node): Node { + const p = this.llparse; + return p.invoke(p.code.and('flags', ~flag), this.node(next)); + } + + private setFlag(flag: FLAGS, next: string | Node): Node { + const p = this.llparse; + return p.invoke(p.code.or('flags', flag), this.node(next)); + } + + private testFlags(flag: FLAGS, map: { [key: number]: Node }, + next?: string | Node): Node { + const p = this.llparse; + const res = p.invoke(p.code.test('flags', flag), map); + if (next !== undefined) { + res.otherwise(this.node(next)); + } + return res; + } + + private testLenientFlags(flag: LENIENT_FLAGS, map: { [key: number]: Node }, + next?: string | Node): Node { + const p = this.llparse; + const res = p.invoke(p.code.test('lenient_flags', flag), map); + if (next !== undefined) { + res.otherwise(this.node(next)); + } + return res; + } + + private setHeaderFlags(next: string | Node): Node { + const HS = HEADER_STATE; + const F = FLAGS; + + const toConnection = + this.update('header_state', HEADER_STATE.CONNECTION, next); + + return this.load('header_state', { + [HS.CONNECTION_KEEP_ALIVE]: + this.setFlag(F.CONNECTION_KEEP_ALIVE, toConnection), + [HS.CONNECTION_CLOSE]: this.setFlag(F.CONNECTION_CLOSE, toConnection), + [HS.CONNECTION_UPGRADE]: this.setFlag(F.CONNECTION_UPGRADE, toConnection), + [HS.TRANSFER_ENCODING_CHUNKED]: this.setFlag(F.CHUNKED, next), + }, this.node(next)); + } + + private mulAdd(field: string, targets: IMulTargets, + options: IMulOptions = { base: 10, signed: false }): Node { + const p = this.llparse; + + return p.invoke(p.code.mulAdd(field, options), { + 1: this.node(targets.overflow), + }, this.node(targets.success)); + } + + private isEqual(field: string, value: number, map: IIsEqualTargets) { + const p = this.llparse; + return p.invoke(p.code.isEqual(field, value), { + 0: this.node(map.notEqual), + }, this.node(map.equal)); + } + + private pause(msg: string, next?: string | Node) { + const p = this.llparse; + const res = p.pause(ERROR.PAUSED, msg); + if (next !== undefined) { + res.otherwise(this.node(next)); + } + return res; + } + + private invokePausable(name: string, errorCode: ERROR, next: string | Node) + : Node { + let cb; + + switch (name) { + case 'on_message_begin': + cb = this.callback.onMessageBegin; + break; + case 'on_url_complete': + cb = this.callback.onUrlComplete; + break; + case 'on_status_complete': + cb = this.callback.onStatusComplete; + break; + case 'on_method_complete': + cb = this.callback.onMethodComplete; + break; + case 'on_version_complete': + cb = this.callback.onVersionComplete; + break; + case 'on_header_field_complete': + cb = this.callback.onHeaderFieldComplete; + break; + case 'on_header_value_complete': + cb = this.callback.onHeaderValueComplete; + break; + case 'on_message_complete': + cb = this.callback.onMessageComplete; + break; + case 'on_chunk_header': + cb = this.callback.onChunkHeader; + break; + case 'on_chunk_extension_name': + cb = this.callback.onChunkExtensionName; + break; + case 'on_chunk_extension_value': + cb = this.callback.onChunkExtensionValue; + break; + case 'on_chunk_complete': + cb = this.callback.onChunkComplete; + break; + case 'on_reset': + cb = this.callback.onReset; + break; + default: + throw new Error('Unknown callback: ' + name); + } + + const p = this.llparse; + return p.invoke(cb, { + 0: this.node(next), + [ERROR.PAUSED]: this.pause(`${name} pause`, next), + }, p.error(errorCode, `\`${name}\` callback error`)); + } +} diff --git a/vendor/llhttp/src/llhttp/url.ts b/vendor/llhttp/src/llhttp/url.ts new file mode 100644 index 0000000..c5fced9 --- /dev/null +++ b/vendor/llhttp/src/llhttp/url.ts @@ -0,0 +1,220 @@ +import { LLParse, source } from 'llparse'; + +import Match = source.node.Match; +import Node = source.node.Node; + +import { + ALPHA, + CharList, + ERROR, + URL_CHAR, + USERINFO_CHARS, +} from './constants'; + +type SpanName = 'schema' | 'host' | 'path' | 'query' | 'fragment' | 'url'; + +export interface IURLResult { + readonly entry: { + readonly normal: Node; + readonly connect: Node; + }; + readonly exit: { + readonly toHTTP: Node; + readonly toHTTP09: Node; + }; +} + +type SpanTable = Map; + +export class URL { + private readonly spanTable: SpanTable = new Map(); + private readonly errorInvalid: Node; + private readonly URL_CHAR: CharList; + + constructor(private readonly llparse: LLParse, separateSpans: boolean = false) { + const p = this.llparse; + + this.errorInvalid = p.error(ERROR.INVALID_URL, 'Invalid characters in url'); + + this.URL_CHAR = URL_CHAR; + + const table = this.spanTable; + if (separateSpans) { + table.set('schema', p.span(p.code.span('llhttp__on_url_schema'))); + table.set('host', p.span(p.code.span('llhttp__on_url_host'))); + table.set('path', p.span(p.code.span('llhttp__on_url_path'))); + table.set('query', p.span(p.code.span('llhttp__on_url_query'))); + table.set('fragment', + p.span(p.code.span('llhttp__on_url_fragment'))); + } else { + table.set('url', p.span(p.code.span('llhttp__on_url'))); + } + } + + public build(): IURLResult { + const p = this.llparse; + + const entry = { + connect: this.node('entry_connect'), + normal: this.node('entry_normal'), + }; + + const start = this.node('start'); + const path = this.node('path'); + const queryOrFragment = this.node('query_or_fragment'); + const schema = this.node('schema'); + const schemaDelim = this.node('schema_delim'); + const server = this.node('server'); + const queryStart = this.node('query_start'); + const query = this.node('query'); + const fragment = this.node('fragment'); + const serverWithAt = this.node('server_with_at'); + + entry.normal + .otherwise(this.spanStart('url', start)); + + entry.connect + .otherwise(this.spanStart('url', this.spanStart('host', server))); + + start + .peek([ '/', '*' ], this.spanStart('path').skipTo(path)) + .peek(ALPHA, this.spanStart('schema', schema)) + .otherwise(p.error(ERROR.INVALID_URL, 'Unexpected start char in url')); + + schema + .match(ALPHA, schema) + .peek(':', this.spanEnd('schema').skipTo(schemaDelim)) + .otherwise(p.error(ERROR.INVALID_URL, 'Unexpected char in url schema')); + + schemaDelim + .match('//', this.spanStart('host', server)) + .otherwise(p.error(ERROR.INVALID_URL, 'Unexpected char in url schema')); + + for (const node of [server, serverWithAt]) { + node + .peek('/', this.spanEnd('host', this.spanStart('path').skipTo(path))) + .match('?', this.spanEnd('host', this.spanStart('query', query))) + .match(USERINFO_CHARS, server) + .match([ '[', ']' ], server) + .otherwise(p.error(ERROR.INVALID_URL, 'Unexpected char in url server')); + + if (node !== serverWithAt) { + node.match('@', serverWithAt); + } + } + + serverWithAt + .match('@', p.error(ERROR.INVALID_URL, 'Double @ in url')); + + path + .match(this.URL_CHAR, path) + .otherwise(this.spanEnd('path', queryOrFragment)); + + // Performance optimization, split `path` so that the fast case remains + // there + queryOrFragment + .match('?', this.spanStart('query', query)) + .match('#', this.spanStart('fragment', fragment)) + .otherwise(p.error(ERROR.INVALID_URL, 'Invalid char in url path')); + + query + .match(this.URL_CHAR, query) + // Allow extra '?' in query string + .match('?', query) + .peek('#', this.spanEnd('query') + .skipTo(this.spanStart('fragment', fragment))) + .otherwise(p.error(ERROR.INVALID_URL, 'Invalid char in url query')); + + fragment + .match(this.URL_CHAR, fragment) + .match([ '?', '#' ], fragment) + .otherwise( + p.error(ERROR.INVALID_URL, 'Invalid char in url fragment start')); + + for (const node of [ start, schema, schemaDelim ]) { + /* No whitespace allowed here */ + node.match([ ' ', '\r', '\n' ], this.errorInvalid); + } + + // Adaptors + const toHTTP = this.node('to_http'); + const toHTTP09 = this.node('to_http_09'); + + const skipToHTTP = this.node('skip_to_http') + .skipTo(toHTTP); + + const skipToHTTP09 = this.node('skip_to_http09') + .skipTo(toHTTP09); + + const skipCRLF = this.node('skip_lf_to_http09') + .match('\r\n', toHTTP09) + .otherwise(p.error(ERROR.INVALID_URL, 'Expected CRLF')); + + for (const node of [server, serverWithAt, queryOrFragment, queryStart, query, fragment]) { + let spanName: SpanName | undefined; + + if (node === server || node === serverWithAt) { + spanName = 'host'; + } else if (node === queryStart || node === query) { + spanName = 'query'; + } else if (node === fragment) { + spanName = 'fragment'; + } + + const endTo = (target: Node): Node => { + let res: Node = this.spanEnd('url', target); + if (spanName !== undefined) { + res = this.spanEnd(spanName, res); + } + return res; + }; + + node.peek(' ', endTo(skipToHTTP)); + + node.peek('\r', endTo(skipCRLF)); + node.peek('\n', endTo(skipToHTTP09)); + } + + return { + entry, + exit: { + toHTTP, + toHTTP09, + }, + }; + } + + private spanStart(name: SpanName, otherwise?: Node): Node { + let res: Node; + if (this.spanTable.has(name)) { + res = this.spanTable.get(name)!.start(); + } else { + res = this.llparse.node('span_start_stub_' + name); + } + if (otherwise !== undefined) { + res.otherwise(otherwise); + } + return res; + } + + private spanEnd(name: SpanName, otherwise?: Node): Node { + let res: Node; + if (this.spanTable.has(name)) { + res = this.spanTable.get(name)!.end(); + } else { + res = this.llparse.node('span_end_stub_' + name); + } + if (otherwise !== undefined) { + res.otherwise(otherwise); + } + return res; + } + + private node(name: string): Match { + const res = this.llparse.node('url_' + name); + + res.match([ '\t', '\f' ], this.errorInvalid); + + return res; + } +} diff --git a/vendor/llhttp/src/llhttp/utils.ts b/vendor/llhttp/src/llhttp/utils.ts new file mode 100644 index 0000000..7c01d66 --- /dev/null +++ b/vendor/llhttp/src/llhttp/utils.ts @@ -0,0 +1,27 @@ +export interface IEnumMap { + [key: string]: number; +} + +export function enumToMap( + obj: any, + filter?: ReadonlyArray, + exceptions?: ReadonlyArray, +): IEnumMap { + const res: IEnumMap = {}; + + for (const key of Object.keys(obj)) { + const value = obj[key]; + if (typeof value !== 'number') { + continue; + } + if (filter && !filter.includes(value)) { + continue; + } + if (exceptions && exceptions.includes(value)) { + continue; + } + res[key] = value; + } + + return res; +} diff --git a/vendor/llhttp/src/native/api.c b/vendor/llhttp/src/native/api.c new file mode 100644 index 0000000..8c2ce3d --- /dev/null +++ b/vendor/llhttp/src/native/api.c @@ -0,0 +1,510 @@ +#include +#include +#include + +#include "llhttp.h" + +#define CALLBACK_MAYBE(PARSER, NAME) \ + do { \ + const llhttp_settings_t* settings; \ + settings = (const llhttp_settings_t*) (PARSER)->settings; \ + if (settings == NULL || settings->NAME == NULL) { \ + err = 0; \ + break; \ + } \ + err = settings->NAME((PARSER)); \ + } while (0) + +#define SPAN_CALLBACK_MAYBE(PARSER, NAME, START, LEN) \ + do { \ + const llhttp_settings_t* settings; \ + settings = (const llhttp_settings_t*) (PARSER)->settings; \ + if (settings == NULL || settings->NAME == NULL) { \ + err = 0; \ + break; \ + } \ + err = settings->NAME((PARSER), (START), (LEN)); \ + if (err == -1) { \ + err = HPE_USER; \ + llhttp_set_error_reason((PARSER), "Span callback error in " #NAME); \ + } \ + } while (0) + +void llhttp_init(llhttp_t* parser, llhttp_type_t type, + const llhttp_settings_t* settings) { + llhttp__internal_init(parser); + + parser->type = type; + parser->settings = (void*) settings; +} + + +#if defined(__wasm__) + +extern int wasm_on_message_begin(llhttp_t * p); +extern int wasm_on_url(llhttp_t* p, const char* at, size_t length); +extern int wasm_on_status(llhttp_t* p, const char* at, size_t length); +extern int wasm_on_header_field(llhttp_t* p, const char* at, size_t length); +extern int wasm_on_header_value(llhttp_t* p, const char* at, size_t length); +extern int wasm_on_headers_complete(llhttp_t * p, int status_code, + uint8_t upgrade, int should_keep_alive); +extern int wasm_on_body(llhttp_t* p, const char* at, size_t length); +extern int wasm_on_message_complete(llhttp_t * p); + +static int wasm_on_headers_complete_wrap(llhttp_t* p) { + return wasm_on_headers_complete(p, p->status_code, p->upgrade, + llhttp_should_keep_alive(p)); +} + +const llhttp_settings_t wasm_settings = { + wasm_on_message_begin, + wasm_on_url, + wasm_on_status, + NULL, + NULL, + wasm_on_header_field, + wasm_on_header_value, + NULL, + NULL, + wasm_on_headers_complete_wrap, + wasm_on_body, + wasm_on_message_complete, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, +}; + + +llhttp_t* llhttp_alloc(llhttp_type_t type) { + llhttp_t* parser = malloc(sizeof(llhttp_t)); + llhttp_init(parser, type, &wasm_settings); + return parser; +} + +void llhttp_free(llhttp_t* parser) { + free(parser); +} + +#endif // defined(__wasm__) + +/* Some getters required to get stuff from the parser */ + +uint8_t llhttp_get_type(llhttp_t* parser) { + return parser->type; +} + +uint8_t llhttp_get_http_major(llhttp_t* parser) { + return parser->http_major; +} + +uint8_t llhttp_get_http_minor(llhttp_t* parser) { + return parser->http_minor; +} + +uint8_t llhttp_get_method(llhttp_t* parser) { + return parser->method; +} + +int llhttp_get_status_code(llhttp_t* parser) { + return parser->status_code; +} + +uint8_t llhttp_get_upgrade(llhttp_t* parser) { + return parser->upgrade; +} + + +void llhttp_reset(llhttp_t* parser) { + llhttp_type_t type = parser->type; + const llhttp_settings_t* settings = parser->settings; + void* data = parser->data; + uint16_t lenient_flags = parser->lenient_flags; + + llhttp__internal_init(parser); + + parser->type = type; + parser->settings = (void*) settings; + parser->data = data; + parser->lenient_flags = lenient_flags; +} + + +llhttp_errno_t llhttp_execute(llhttp_t* parser, const char* data, size_t len) { + return llhttp__internal_execute(parser, data, data + len); +} + + +void llhttp_settings_init(llhttp_settings_t* settings) { + memset(settings, 0, sizeof(*settings)); +} + + +llhttp_errno_t llhttp_finish(llhttp_t* parser) { + int err; + + /* We're in an error state. Don't bother doing anything. */ + if (parser->error != 0) { + return 0; + } + + switch (parser->finish) { + case HTTP_FINISH_SAFE_WITH_CB: + CALLBACK_MAYBE(parser, on_message_complete); + if (err != HPE_OK) return err; + + /* FALLTHROUGH */ + case HTTP_FINISH_SAFE: + return HPE_OK; + case HTTP_FINISH_UNSAFE: + parser->reason = "Invalid EOF state"; + return HPE_INVALID_EOF_STATE; + default: + abort(); + } +} + + +void llhttp_pause(llhttp_t* parser) { + if (parser->error != HPE_OK) { + return; + } + + parser->error = HPE_PAUSED; + parser->reason = "Paused"; +} + + +void llhttp_resume(llhttp_t* parser) { + if (parser->error != HPE_PAUSED) { + return; + } + + parser->error = 0; +} + + +void llhttp_resume_after_upgrade(llhttp_t* parser) { + if (parser->error != HPE_PAUSED_UPGRADE) { + return; + } + + parser->error = 0; +} + + +llhttp_errno_t llhttp_get_errno(const llhttp_t* parser) { + return parser->error; +} + + +const char* llhttp_get_error_reason(const llhttp_t* parser) { + return parser->reason; +} + + +void llhttp_set_error_reason(llhttp_t* parser, const char* reason) { + parser->reason = reason; +} + + +const char* llhttp_get_error_pos(const llhttp_t* parser) { + return parser->error_pos; +} + + +const char* llhttp_errno_name(llhttp_errno_t err) { +#define HTTP_ERRNO_GEN(CODE, NAME, _) case HPE_##NAME: return "HPE_" #NAME; + switch (err) { + HTTP_ERRNO_MAP(HTTP_ERRNO_GEN) + default: abort(); + } +#undef HTTP_ERRNO_GEN +} + + +const char* llhttp_method_name(llhttp_method_t method) { +#define HTTP_METHOD_GEN(NUM, NAME, STRING) case HTTP_##NAME: return #STRING; + switch (method) { + HTTP_ALL_METHOD_MAP(HTTP_METHOD_GEN) + default: abort(); + } +#undef HTTP_METHOD_GEN +} + +const char* llhttp_status_name(llhttp_status_t status) { +#define HTTP_STATUS_GEN(NUM, NAME, STRING) case HTTP_STATUS_##NAME: return #STRING; + switch (status) { + HTTP_STATUS_MAP(HTTP_STATUS_GEN) + default: abort(); + } +#undef HTTP_STATUS_GEN +} + + +void llhttp_set_lenient_headers(llhttp_t* parser, int enabled) { + if (enabled) { + parser->lenient_flags |= LENIENT_HEADERS; + } else { + parser->lenient_flags &= ~LENIENT_HEADERS; + } +} + + +void llhttp_set_lenient_chunked_length(llhttp_t* parser, int enabled) { + if (enabled) { + parser->lenient_flags |= LENIENT_CHUNKED_LENGTH; + } else { + parser->lenient_flags &= ~LENIENT_CHUNKED_LENGTH; + } +} + + +void llhttp_set_lenient_keep_alive(llhttp_t* parser, int enabled) { + if (enabled) { + parser->lenient_flags |= LENIENT_KEEP_ALIVE; + } else { + parser->lenient_flags &= ~LENIENT_KEEP_ALIVE; + } +} + +void llhttp_set_lenient_transfer_encoding(llhttp_t* parser, int enabled) { + if (enabled) { + parser->lenient_flags |= LENIENT_TRANSFER_ENCODING; + } else { + parser->lenient_flags &= ~LENIENT_TRANSFER_ENCODING; + } +} + +void llhttp_set_lenient_version(llhttp_t* parser, int enabled) { + if (enabled) { + parser->lenient_flags |= LENIENT_VERSION; + } else { + parser->lenient_flags &= ~LENIENT_VERSION; + } +} + +void llhttp_set_lenient_data_after_close(llhttp_t* parser, int enabled) { + if (enabled) { + parser->lenient_flags |= LENIENT_DATA_AFTER_CLOSE; + } else { + parser->lenient_flags &= ~LENIENT_DATA_AFTER_CLOSE; + } +} + +void llhttp_set_lenient_optional_lf_after_cr(llhttp_t* parser, int enabled) { + if (enabled) { + parser->lenient_flags |= LENIENT_OPTIONAL_LF_AFTER_CR; + } else { + parser->lenient_flags &= ~LENIENT_OPTIONAL_LF_AFTER_CR; + } +} + +void llhttp_set_lenient_optional_crlf_after_chunk(llhttp_t* parser, int enabled) { + if (enabled) { + parser->lenient_flags |= LENIENT_OPTIONAL_CRLF_AFTER_CHUNK; + } else { + parser->lenient_flags &= ~LENIENT_OPTIONAL_CRLF_AFTER_CHUNK; + } +} + +void llhttp_set_lenient_optional_cr_before_lf(llhttp_t* parser, int enabled) { + if (enabled) { + parser->lenient_flags |= LENIENT_OPTIONAL_CR_BEFORE_LF; + } else { + parser->lenient_flags &= ~LENIENT_OPTIONAL_CR_BEFORE_LF; + } +} + +void llhttp_set_lenient_spaces_after_chunk_size(llhttp_t* parser, int enabled) { + if (enabled) { + parser->lenient_flags |= LENIENT_SPACES_AFTER_CHUNK_SIZE; + } else { + parser->lenient_flags &= ~LENIENT_SPACES_AFTER_CHUNK_SIZE; + } +} + +/* Callbacks */ + + +int llhttp__on_message_begin(llhttp_t* s, const char* p, const char* endp) { + int err; + CALLBACK_MAYBE(s, on_message_begin); + return err; +} + + +int llhttp__on_url(llhttp_t* s, const char* p, const char* endp) { + int err; + SPAN_CALLBACK_MAYBE(s, on_url, p, endp - p); + return err; +} + + +int llhttp__on_url_complete(llhttp_t* s, const char* p, const char* endp) { + int err; + CALLBACK_MAYBE(s, on_url_complete); + return err; +} + + +int llhttp__on_status(llhttp_t* s, const char* p, const char* endp) { + int err; + SPAN_CALLBACK_MAYBE(s, on_status, p, endp - p); + return err; +} + + +int llhttp__on_status_complete(llhttp_t* s, const char* p, const char* endp) { + int err; + CALLBACK_MAYBE(s, on_status_complete); + return err; +} + + +int llhttp__on_method(llhttp_t* s, const char* p, const char* endp) { + int err; + SPAN_CALLBACK_MAYBE(s, on_method, p, endp - p); + return err; +} + + +int llhttp__on_method_complete(llhttp_t* s, const char* p, const char* endp) { + int err; + CALLBACK_MAYBE(s, on_method_complete); + return err; +} + + +int llhttp__on_version(llhttp_t* s, const char* p, const char* endp) { + int err; + SPAN_CALLBACK_MAYBE(s, on_version, p, endp - p); + return err; +} + + +int llhttp__on_version_complete(llhttp_t* s, const char* p, const char* endp) { + int err; + CALLBACK_MAYBE(s, on_version_complete); + return err; +} + + +int llhttp__on_header_field(llhttp_t* s, const char* p, const char* endp) { + int err; + SPAN_CALLBACK_MAYBE(s, on_header_field, p, endp - p); + return err; +} + + +int llhttp__on_header_field_complete(llhttp_t* s, const char* p, const char* endp) { + int err; + CALLBACK_MAYBE(s, on_header_field_complete); + return err; +} + + +int llhttp__on_header_value(llhttp_t* s, const char* p, const char* endp) { + int err; + SPAN_CALLBACK_MAYBE(s, on_header_value, p, endp - p); + return err; +} + + +int llhttp__on_header_value_complete(llhttp_t* s, const char* p, const char* endp) { + int err; + CALLBACK_MAYBE(s, on_header_value_complete); + return err; +} + + +int llhttp__on_headers_complete(llhttp_t* s, const char* p, const char* endp) { + int err; + CALLBACK_MAYBE(s, on_headers_complete); + return err; +} + + +int llhttp__on_message_complete(llhttp_t* s, const char* p, const char* endp) { + int err; + CALLBACK_MAYBE(s, on_message_complete); + return err; +} + + +int llhttp__on_body(llhttp_t* s, const char* p, const char* endp) { + int err; + SPAN_CALLBACK_MAYBE(s, on_body, p, endp - p); + return err; +} + + +int llhttp__on_chunk_header(llhttp_t* s, const char* p, const char* endp) { + int err; + CALLBACK_MAYBE(s, on_chunk_header); + return err; +} + + +int llhttp__on_chunk_extension_name(llhttp_t* s, const char* p, const char* endp) { + int err; + SPAN_CALLBACK_MAYBE(s, on_chunk_extension_name, p, endp - p); + return err; +} + + +int llhttp__on_chunk_extension_name_complete(llhttp_t* s, const char* p, const char* endp) { + int err; + CALLBACK_MAYBE(s, on_chunk_extension_name_complete); + return err; +} + + +int llhttp__on_chunk_extension_value(llhttp_t* s, const char* p, const char* endp) { + int err; + SPAN_CALLBACK_MAYBE(s, on_chunk_extension_value, p, endp - p); + return err; +} + + +int llhttp__on_chunk_extension_value_complete(llhttp_t* s, const char* p, const char* endp) { + int err; + CALLBACK_MAYBE(s, on_chunk_extension_value_complete); + return err; +} + + +int llhttp__on_chunk_complete(llhttp_t* s, const char* p, const char* endp) { + int err; + CALLBACK_MAYBE(s, on_chunk_complete); + return err; +} + + +int llhttp__on_reset(llhttp_t* s, const char* p, const char* endp) { + int err; + CALLBACK_MAYBE(s, on_reset); + return err; +} + + +/* Private */ + + +void llhttp__debug(llhttp_t* s, const char* p, const char* endp, + const char* msg) { + if (p == endp) { + fprintf(stderr, "p=%p type=%d flags=%02x next=null debug=%s\n", s, s->type, + s->flags, msg); + } else { + fprintf(stderr, "p=%p type=%d flags=%02x next=%02x debug=%s\n", s, + s->type, s->flags, *p, msg); + } +} diff --git a/vendor/llhttp/src/native/api.h b/vendor/llhttp/src/native/api.h new file mode 100644 index 0000000..321879c --- /dev/null +++ b/vendor/llhttp/src/native/api.h @@ -0,0 +1,355 @@ +#ifndef INCLUDE_LLHTTP_API_H_ +#define INCLUDE_LLHTTP_API_H_ +#ifdef __cplusplus +extern "C" { +#endif +#include + +#if defined(__wasm__) +#define LLHTTP_EXPORT __attribute__((visibility("default"))) +#else +#define LLHTTP_EXPORT +#endif + +typedef llhttp__internal_t llhttp_t; +typedef struct llhttp_settings_s llhttp_settings_t; + +typedef int (*llhttp_data_cb)(llhttp_t*, const char *at, size_t length); +typedef int (*llhttp_cb)(llhttp_t*); + +struct llhttp_settings_s { + /* Possible return values 0, -1, `HPE_PAUSED` */ + llhttp_cb on_message_begin; + + /* Possible return values 0, -1, HPE_USER */ + llhttp_data_cb on_url; + llhttp_data_cb on_status; + llhttp_data_cb on_method; + llhttp_data_cb on_version; + llhttp_data_cb on_header_field; + llhttp_data_cb on_header_value; + llhttp_data_cb on_chunk_extension_name; + llhttp_data_cb on_chunk_extension_value; + + /* Possible return values: + * 0 - Proceed normally + * 1 - Assume that request/response has no body, and proceed to parsing the + * next message + * 2 - Assume absence of body (as above) and make `llhttp_execute()` return + * `HPE_PAUSED_UPGRADE` + * -1 - Error + * `HPE_PAUSED` + */ + llhttp_cb on_headers_complete; + + /* Possible return values 0, -1, HPE_USER */ + llhttp_data_cb on_body; + + /* Possible return values 0, -1, `HPE_PAUSED` */ + llhttp_cb on_message_complete; + llhttp_cb on_url_complete; + llhttp_cb on_status_complete; + llhttp_cb on_method_complete; + llhttp_cb on_version_complete; + llhttp_cb on_header_field_complete; + llhttp_cb on_header_value_complete; + llhttp_cb on_chunk_extension_name_complete; + llhttp_cb on_chunk_extension_value_complete; + + /* When on_chunk_header is called, the current chunk length is stored + * in parser->content_length. + * Possible return values 0, -1, `HPE_PAUSED` + */ + llhttp_cb on_chunk_header; + llhttp_cb on_chunk_complete; + llhttp_cb on_reset; +}; + +/* Initialize the parser with specific type and user settings. + * + * NOTE: lifetime of `settings` has to be at least the same as the lifetime of + * the `parser` here. In practice, `settings` has to be either a static + * variable or be allocated with `malloc`, `new`, etc. + */ +LLHTTP_EXPORT +void llhttp_init(llhttp_t* parser, llhttp_type_t type, + const llhttp_settings_t* settings); + +LLHTTP_EXPORT +llhttp_t* llhttp_alloc(llhttp_type_t type); + +LLHTTP_EXPORT +void llhttp_free(llhttp_t* parser); + +LLHTTP_EXPORT +uint8_t llhttp_get_type(llhttp_t* parser); + +LLHTTP_EXPORT +uint8_t llhttp_get_http_major(llhttp_t* parser); + +LLHTTP_EXPORT +uint8_t llhttp_get_http_minor(llhttp_t* parser); + +LLHTTP_EXPORT +uint8_t llhttp_get_method(llhttp_t* parser); + +LLHTTP_EXPORT +int llhttp_get_status_code(llhttp_t* parser); + +LLHTTP_EXPORT +uint8_t llhttp_get_upgrade(llhttp_t* parser); + +/* Reset an already initialized parser back to the start state, preserving the + * existing parser type, callback settings, user data, and lenient flags. + */ +LLHTTP_EXPORT +void llhttp_reset(llhttp_t* parser); + +/* Initialize the settings object */ +LLHTTP_EXPORT +void llhttp_settings_init(llhttp_settings_t* settings); + +/* Parse full or partial request/response, invoking user callbacks along the + * way. + * + * If any of `llhttp_data_cb` returns errno not equal to `HPE_OK` - the parsing + * interrupts, and such errno is returned from `llhttp_execute()`. If + * `HPE_PAUSED` was used as a errno, the execution can be resumed with + * `llhttp_resume()` call. + * + * In a special case of CONNECT/Upgrade request/response `HPE_PAUSED_UPGRADE` + * is returned after fully parsing the request/response. If the user wishes to + * continue parsing, they need to invoke `llhttp_resume_after_upgrade()`. + * + * NOTE: if this function ever returns a non-pause type error, it will continue + * to return the same error upon each successive call up until `llhttp_init()` + * is called. + */ +LLHTTP_EXPORT +llhttp_errno_t llhttp_execute(llhttp_t* parser, const char* data, size_t len); + +/* This method should be called when the other side has no further bytes to + * send (e.g. shutdown of readable side of the TCP connection.) + * + * Requests without `Content-Length` and other messages might require treating + * all incoming bytes as the part of the body, up to the last byte of the + * connection. This method will invoke `on_message_complete()` callback if the + * request was terminated safely. Otherwise a error code would be returned. + */ +LLHTTP_EXPORT +llhttp_errno_t llhttp_finish(llhttp_t* parser); + +/* Returns `1` if the incoming message is parsed until the last byte, and has + * to be completed by calling `llhttp_finish()` on EOF + */ +LLHTTP_EXPORT +int llhttp_message_needs_eof(const llhttp_t* parser); + +/* Returns `1` if there might be any other messages following the last that was + * successfully parsed. + */ +LLHTTP_EXPORT +int llhttp_should_keep_alive(const llhttp_t* parser); + +/* Make further calls of `llhttp_execute()` return `HPE_PAUSED` and set + * appropriate error reason. + * + * Important: do not call this from user callbacks! User callbacks must return + * `HPE_PAUSED` if pausing is required. + */ +LLHTTP_EXPORT +void llhttp_pause(llhttp_t* parser); + +/* Might be called to resume the execution after the pause in user's callback. + * See `llhttp_execute()` above for details. + * + * Call this only if `llhttp_execute()` returns `HPE_PAUSED`. + */ +LLHTTP_EXPORT +void llhttp_resume(llhttp_t* parser); + +/* Might be called to resume the execution after the pause in user's callback. + * See `llhttp_execute()` above for details. + * + * Call this only if `llhttp_execute()` returns `HPE_PAUSED_UPGRADE` + */ +LLHTTP_EXPORT +void llhttp_resume_after_upgrade(llhttp_t* parser); + +/* Returns the latest return error */ +LLHTTP_EXPORT +llhttp_errno_t llhttp_get_errno(const llhttp_t* parser); + +/* Returns the verbal explanation of the latest returned error. + * + * Note: User callback should set error reason when returning the error. See + * `llhttp_set_error_reason()` for details. + */ +LLHTTP_EXPORT +const char* llhttp_get_error_reason(const llhttp_t* parser); + +/* Assign verbal description to the returned error. Must be called in user + * callbacks right before returning the errno. + * + * Note: `HPE_USER` error code might be useful in user callbacks. + */ +LLHTTP_EXPORT +void llhttp_set_error_reason(llhttp_t* parser, const char* reason); + +/* Returns the pointer to the last parsed byte before the returned error. The + * pointer is relative to the `data` argument of `llhttp_execute()`. + * + * Note: this method might be useful for counting the number of parsed bytes. + */ +LLHTTP_EXPORT +const char* llhttp_get_error_pos(const llhttp_t* parser); + +/* Returns textual name of error code */ +LLHTTP_EXPORT +const char* llhttp_errno_name(llhttp_errno_t err); + +/* Returns textual name of HTTP method */ +LLHTTP_EXPORT +const char* llhttp_method_name(llhttp_method_t method); + +/* Returns textual name of HTTP status */ +LLHTTP_EXPORT +const char* llhttp_status_name(llhttp_status_t status); + +/* Enables/disables lenient header value parsing (disabled by default). + * + * Lenient parsing disables header value token checks, extending llhttp's + * protocol support to highly non-compliant clients/server. No + * `HPE_INVALID_HEADER_TOKEN` will be raised for incorrect header values when + * lenient parsing is "on". + * + * **Enabling this flag can pose a security issue since you will be exposed to + * request smuggling attacks. USE WITH CAUTION!** + */ +LLHTTP_EXPORT +void llhttp_set_lenient_headers(llhttp_t* parser, int enabled); + + +/* Enables/disables lenient handling of conflicting `Transfer-Encoding` and + * `Content-Length` headers (disabled by default). + * + * Normally `llhttp` would error when `Transfer-Encoding` is present in + * conjunction with `Content-Length`. This error is important to prevent HTTP + * request smuggling, but may be less desirable for small number of cases + * involving legacy servers. + * + * **Enabling this flag can pose a security issue since you will be exposed to + * request smuggling attacks. USE WITH CAUTION!** + */ +LLHTTP_EXPORT +void llhttp_set_lenient_chunked_length(llhttp_t* parser, int enabled); + + +/* Enables/disables lenient handling of `Connection: close` and HTTP/1.0 + * requests responses. + * + * Normally `llhttp` would error on (in strict mode) or discard (in loose mode) + * the HTTP request/response after the request/response with `Connection: close` + * and `Content-Length`. This is important to prevent cache poisoning attacks, + * but might interact badly with outdated and insecure clients. With this flag + * the extra request/response will be parsed normally. + * + * **Enabling this flag can pose a security issue since you will be exposed to + * poisoning attacks. USE WITH CAUTION!** + */ +LLHTTP_EXPORT +void llhttp_set_lenient_keep_alive(llhttp_t* parser, int enabled); + +/* Enables/disables lenient handling of `Transfer-Encoding` header. + * + * Normally `llhttp` would error when a `Transfer-Encoding` has `chunked` value + * and another value after it (either in a single header or in multiple + * headers whose value are internally joined using `, `). + * This is mandated by the spec to reliably determine request body size and thus + * avoid request smuggling. + * With this flag the extra value will be parsed normally. + * + * **Enabling this flag can pose a security issue since you will be exposed to + * request smuggling attacks. USE WITH CAUTION!** + */ +LLHTTP_EXPORT +void llhttp_set_lenient_transfer_encoding(llhttp_t* parser, int enabled); + +/* Enables/disables lenient handling of HTTP version. + * + * Normally `llhttp` would error when the HTTP version in the request or status line + * is not `0.9`, `1.0`, `1.1` or `2.0`. + * With this flag the invalid value will be parsed normally. + * + * **Enabling this flag can pose a security issue since you will allow unsupported + * HTTP versions. USE WITH CAUTION!** + */ +LLHTTP_EXPORT +void llhttp_set_lenient_version(llhttp_t* parser, int enabled); + +/* Enables/disables lenient handling of additional data received after a message ends + * and keep-alive is disabled. + * + * Normally `llhttp` would error when additional unexpected data is received if the message + * contains the `Connection` header with `close` value. + * With this flag the extra data will discarded without throwing an error. + * + * **Enabling this flag can pose a security issue since you will be exposed to + * poisoning attacks. USE WITH CAUTION!** + */ +LLHTTP_EXPORT +void llhttp_set_lenient_data_after_close(llhttp_t* parser, int enabled); + +/* Enables/disables lenient handling of incomplete CRLF sequences. + * + * Normally `llhttp` would error when a CR is not followed by LF when terminating the + * request line, the status line, the headers or a chunk header. + * With this flag only a CR is required to terminate such sections. + * + * **Enabling this flag can pose a security issue since you will be exposed to + * request smuggling attacks. USE WITH CAUTION!** + */ +LLHTTP_EXPORT +void llhttp_set_lenient_optional_lf_after_cr(llhttp_t* parser, int enabled); + +/* + * Enables/disables lenient handling of line separators. + * + * Normally `llhttp` would error when a LF is not preceded by CR when terminating the + * request line, the status line, the headers, a chunk header or a chunk data. + * With this flag only a LF is required to terminate such sections. + * + * **Enabling this flag can pose a security issue since you will be exposed to + * request smuggling attacks. USE WITH CAUTION!** + */ +LLHTTP_EXPORT +void llhttp_set_lenient_optional_cr_before_lf(llhttp_t* parser, int enabled); + +/* Enables/disables lenient handling of chunks not separated via CRLF. + * + * Normally `llhttp` would error when after a chunk data a CRLF is missing before + * starting a new chunk. + * With this flag the new chunk can start immediately after the previous one. + * + * **Enabling this flag can pose a security issue since you will be exposed to + * request smuggling attacks. USE WITH CAUTION!** + */ +LLHTTP_EXPORT +void llhttp_set_lenient_optional_crlf_after_chunk(llhttp_t* parser, int enabled); + +/* Enables/disables lenient handling of spaces after chunk size. + * + * Normally `llhttp` would error when after a chunk size is followed by one or more + * spaces are present instead of a CRLF or `;`. + * With this flag this check is disabled. + * + * **Enabling this flag can pose a security issue since you will be exposed to + * request smuggling attacks. USE WITH CAUTION!** + */ +LLHTTP_EXPORT +void llhttp_set_lenient_spaces_after_chunk_size(llhttp_t* parser, int enabled); + +#ifdef __cplusplus +} /* extern "C" */ +#endif +#endif /* INCLUDE_LLHTTP_API_H_ */ diff --git a/vendor/llhttp/src/native/http.c b/vendor/llhttp/src/native/http.c new file mode 100644 index 0000000..1ab91a5 --- /dev/null +++ b/vendor/llhttp/src/native/http.c @@ -0,0 +1,170 @@ +#include +#ifndef LLHTTP__TEST +# include "llhttp.h" +#else +# define llhttp_t llparse_t +#endif /* */ + +int llhttp_message_needs_eof(const llhttp_t* parser); +int llhttp_should_keep_alive(const llhttp_t* parser); + +int llhttp__before_headers_complete(llhttp_t* parser, const char* p, + const char* endp) { + /* Set this here so that on_headers_complete() callbacks can see it */ + if ((parser->flags & F_UPGRADE) && + (parser->flags & F_CONNECTION_UPGRADE)) { + /* For responses, "Upgrade: foo" and "Connection: upgrade" are + * mandatory only when it is a 101 Switching Protocols response, + * otherwise it is purely informational, to announce support. + */ + parser->upgrade = + (parser->type == HTTP_REQUEST || parser->status_code == 101); + } else { + parser->upgrade = (parser->method == HTTP_CONNECT); + } + return 0; +} + + +/* Return values: + * 0 - No body, `restart`, message_complete + * 1 - CONNECT request, `restart`, message_complete, and pause + * 2 - chunk_size_start + * 3 - body_identity + * 4 - body_identity_eof + * 5 - invalid transfer-encoding for request + */ +int llhttp__after_headers_complete(llhttp_t* parser, const char* p, + const char* endp) { + int hasBody; + + hasBody = parser->flags & F_CHUNKED || parser->content_length > 0; + if ( + (parser->upgrade && (parser->method == HTTP_CONNECT || + (parser->flags & F_SKIPBODY) || !hasBody)) || + /* See RFC 2616 section 4.4 - 1xx e.g. Continue */ + (parser->type == HTTP_RESPONSE && parser->status_code == 101) + ) { + /* Exit, the rest of the message is in a different protocol. */ + return 1; + } + + if (parser->type == HTTP_RESPONSE && parser->status_code == 100) { + /* No body, restart as the message is complete */ + return 0; + } + + /* See RFC 2616 section 4.4 */ + if ( + parser->flags & F_SKIPBODY || /* response to a HEAD request */ + ( + parser->type == HTTP_RESPONSE && ( + parser->status_code == 102 || /* Processing */ + parser->status_code == 103 || /* Early Hints */ + parser->status_code == 204 || /* No Content */ + parser->status_code == 304 /* Not Modified */ + ) + ) + ) { + return 0; + } else if (parser->flags & F_CHUNKED) { + /* chunked encoding - ignore Content-Length header, prepare for a chunk */ + return 2; + } else if (parser->flags & F_TRANSFER_ENCODING) { + if (parser->type == HTTP_REQUEST && + (parser->lenient_flags & LENIENT_CHUNKED_LENGTH) == 0 && + (parser->lenient_flags & LENIENT_TRANSFER_ENCODING) == 0) { + /* RFC 7230 3.3.3 */ + + /* If a Transfer-Encoding header field + * is present in a request and the chunked transfer coding is not + * the final encoding, the message body length cannot be determined + * reliably; the server MUST respond with the 400 (Bad Request) + * status code and then close the connection. + */ + return 5; + } else { + /* RFC 7230 3.3.3 */ + + /* If a Transfer-Encoding header field is present in a response and + * the chunked transfer coding is not the final encoding, the + * message body length is determined by reading the connection until + * it is closed by the server. + */ + return 4; + } + } else { + if (!(parser->flags & F_CONTENT_LENGTH)) { + if (!llhttp_message_needs_eof(parser)) { + /* Assume content-length 0 - read the next */ + return 0; + } else { + /* Read body until EOF */ + return 4; + } + } else if (parser->content_length == 0) { + /* Content-Length header given but zero: Content-Length: 0\r\n */ + return 0; + } else { + /* Content-Length header given and non-zero */ + return 3; + } + } +} + + +int llhttp__after_message_complete(llhttp_t* parser, const char* p, + const char* endp) { + int should_keep_alive; + + should_keep_alive = llhttp_should_keep_alive(parser); + parser->finish = HTTP_FINISH_SAFE; + parser->flags = 0; + + /* NOTE: this is ignored in loose parsing mode */ + return should_keep_alive; +} + + +int llhttp_message_needs_eof(const llhttp_t* parser) { + if (parser->type == HTTP_REQUEST) { + return 0; + } + + /* See RFC 2616 section 4.4 */ + if (parser->status_code / 100 == 1 || /* 1xx e.g. Continue */ + parser->status_code == 204 || /* No Content */ + parser->status_code == 304 || /* Not Modified */ + (parser->flags & F_SKIPBODY)) { /* response to a HEAD request */ + return 0; + } + + /* RFC 7230 3.3.3, see `llhttp__after_headers_complete` */ + if ((parser->flags & F_TRANSFER_ENCODING) && + (parser->flags & F_CHUNKED) == 0) { + return 1; + } + + if (parser->flags & (F_CHUNKED | F_CONTENT_LENGTH)) { + return 0; + } + + return 1; +} + + +int llhttp_should_keep_alive(const llhttp_t* parser) { + if (parser->http_major > 0 && parser->http_minor > 0) { + /* HTTP/1.1 */ + if (parser->flags & F_CONNECTION_CLOSE) { + return 0; + } + } else { + /* HTTP/1.0 or earlier */ + if (!(parser->flags & F_CONNECTION_KEEP_ALIVE)) { + return 0; + } + } + + return !llhttp_message_needs_eof(parser); +} diff --git a/vendor/llhttp/test/fixtures/extra.c b/vendor/llhttp/test/fixtures/extra.c new file mode 100644 index 0000000..dadf8dc --- /dev/null +++ b/vendor/llhttp/test/fixtures/extra.c @@ -0,0 +1,457 @@ +#include + +#include "fixture.h" + +int llhttp__on_url(llparse_t* s, const char* p, const char* endp) { + if (llparse__in_bench) + return 0; + + return llparse__print_span("url", p, endp); +} + + +int llhttp__on_url_complete(llparse_t* s, const char* p, const char* endp) { + if (llparse__in_bench) + return 0; + + llparse__print(p, endp, "url complete"); + + #ifdef LLHTTP__TEST_PAUSE_ON_URL_COMPLETE + return LLPARSE__ERROR_PAUSE; + #else + return 0; + #endif +} + + +int llhttp__on_url_schema(llparse_t* s, const char* p, const char* endp) { + if (llparse__in_bench) + return 0; + + return llparse__print_span("url.schema", p, endp); +} + + +int llhttp__on_url_host(llparse_t* s, const char* p, const char* endp) { + if (llparse__in_bench) + return 0; + + return llparse__print_span("url.host", p, endp); +} + + +int llhttp__on_url_path(llparse_t* s, const char* p, const char* endp) { + if (llparse__in_bench) + return 0; + + return llparse__print_span("url.path", p, endp); +} + + +int llhttp__on_url_query(llparse_t* s, const char* p, const char* endp) { + if (llparse__in_bench) + return 0; + + return llparse__print_span("url.query", p, endp); +} + + +int llhttp__on_url_fragment(llparse_t* s, const char* p, const char* endp) { + if (llparse__in_bench) + return 0; + + return llparse__print_span("url.fragment", p, endp); +} + + +#ifdef LLHTTP__TEST_HTTP + +void llhttp__test_init_request(llparse_t* s) { + s->type = HTTP_REQUEST; +} + + +void llhttp__test_init_response(llparse_t* s) { + s->type = HTTP_RESPONSE; +} + + +void llhttp__test_init_request_lenient_all(llparse_t* s) { + llhttp__test_init_request(s); + s->lenient_flags |= + LENIENT_HEADERS | LENIENT_CHUNKED_LENGTH | LENIENT_KEEP_ALIVE | + LENIENT_TRANSFER_ENCODING | LENIENT_VERSION | LENIENT_DATA_AFTER_CLOSE | + LENIENT_OPTIONAL_LF_AFTER_CR | LENIENT_OPTIONAL_CR_BEFORE_LF | + LENIENT_OPTIONAL_CRLF_AFTER_CHUNK; +} + + +void llhttp__test_init_response_lenient_all(llparse_t* s) { + llhttp__test_init_response(s); + s->lenient_flags |= + LENIENT_HEADERS | LENIENT_CHUNKED_LENGTH | LENIENT_KEEP_ALIVE | + LENIENT_TRANSFER_ENCODING | LENIENT_VERSION | LENIENT_DATA_AFTER_CLOSE | + LENIENT_OPTIONAL_LF_AFTER_CR | LENIENT_OPTIONAL_CR_BEFORE_LF | + LENIENT_OPTIONAL_CRLF_AFTER_CHUNK; +} + + +void llhttp__test_init_request_lenient_headers(llparse_t* s) { + llhttp__test_init_request(s); + s->lenient_flags |= LENIENT_HEADERS; +} + + +void llhttp__test_init_request_lenient_chunked_length(llparse_t* s) { + llhttp__test_init_request(s); + s->lenient_flags |= LENIENT_CHUNKED_LENGTH; +} + + +void llhttp__test_init_request_lenient_keep_alive(llparse_t* s) { + llhttp__test_init_request(s); + s->lenient_flags |= LENIENT_KEEP_ALIVE; +} + +void llhttp__test_init_request_lenient_transfer_encoding(llparse_t* s) { + llhttp__test_init_request(s); + s->lenient_flags |= LENIENT_TRANSFER_ENCODING; +} + + +void llhttp__test_init_request_lenient_version(llparse_t* s) { + llhttp__test_init_request(s); + s->lenient_flags |= LENIENT_VERSION; +} + + +void llhttp__test_init_response_lenient_keep_alive(llparse_t* s) { + llhttp__test_init_response(s); + s->lenient_flags |= LENIENT_KEEP_ALIVE; +} + +void llhttp__test_init_response_lenient_version(llparse_t* s) { + llhttp__test_init_response(s); + s->lenient_flags |= LENIENT_VERSION; +} + + +void llhttp__test_init_response_lenient_headers(llparse_t* s) { + llhttp__test_init_response(s); + s->lenient_flags |= LENIENT_HEADERS; +} + +void llhttp__test_init_request_lenient_data_after_close(llparse_t* s) { + llhttp__test_init_request(s); + s->lenient_flags |= LENIENT_DATA_AFTER_CLOSE; +} + +void llhttp__test_init_response_lenient_data_after_close(llparse_t* s) { + llhttp__test_init_response(s); + s->lenient_flags |= LENIENT_DATA_AFTER_CLOSE; +} + +void llhttp__test_init_request_lenient_optional_lf_after_cr(llparse_t* s) { + llhttp__test_init_request(s); + s->lenient_flags |= LENIENT_OPTIONAL_LF_AFTER_CR; +} + +void llhttp__test_init_response_lenient_optional_lf_after_cr(llparse_t* s) { + llhttp__test_init_response(s); + s->lenient_flags |= LENIENT_OPTIONAL_LF_AFTER_CR; +} + +void llhttp__test_init_request_lenient_optional_cr_before_lf(llparse_t* s) { + llhttp__test_init_request(s); + s->lenient_flags |= LENIENT_OPTIONAL_CR_BEFORE_LF; +} + +void llhttp__test_init_response_lenient_optional_cr_before_lf(llparse_t* s) { + llhttp__test_init_response(s); + s->lenient_flags |= LENIENT_OPTIONAL_CR_BEFORE_LF; +} + +void llhttp__test_init_request_lenient_optional_crlf_after_chunk(llparse_t* s) { + llhttp__test_init_request(s); + s->lenient_flags |= LENIENT_OPTIONAL_CRLF_AFTER_CHUNK; +} + +void llhttp__test_init_response_lenient_optional_crlf_after_chunk(llparse_t* s) { + llhttp__test_init_response(s); + s->lenient_flags |= LENIENT_OPTIONAL_CRLF_AFTER_CHUNK; +} + +void llhttp__test_init_request_lenient_spaces_after_chunk_size(llparse_t* s) { + llhttp__test_init_request(s); + s->lenient_flags |= LENIENT_SPACES_AFTER_CHUNK_SIZE; +} + +void llhttp__test_init_response_lenient_spaces_after_chunk_size(llparse_t* s) { + llhttp__test_init_response(s); + s->lenient_flags |= LENIENT_SPACES_AFTER_CHUNK_SIZE; +} + + +void llhttp__test_finish(llparse_t* s) { + llparse__print(NULL, NULL, "finish=%d", s->finish); +} + + +int llhttp__on_message_begin(llparse_t* s, const char* p, const char* endp) { + if (llparse__in_bench) + return 0; + + llparse__print(p, endp, "message begin"); + + #ifdef LLHTTP__TEST_PAUSE_ON_MESSAGE_BEGIN + return LLPARSE__ERROR_PAUSE; + #else + return 0; + #endif +} + + +int llhttp__on_message_complete(llparse_t* s, const char* p, const char* endp) { + if (llparse__in_bench) + return 0; + + llparse__print(p, endp, "message complete"); + + #ifdef LLHTTP__TEST_PAUSE_ON_MESSAGE_COMPLETE + return LLPARSE__ERROR_PAUSE; + #else + return 0; + #endif +} + + +int llhttp__on_status(llparse_t* s, const char* p, const char* endp) { + if (llparse__in_bench) + return 0; + + return llparse__print_span("status", p, endp); +} + + +int llhttp__on_status_complete(llparse_t* s, const char* p, const char* endp) { + if (llparse__in_bench) + return 0; + + llparse__print(p, endp, "status complete"); + + #ifdef LLHTTP__TEST_PAUSE_ON_STATUS_COMPLETE + return LLPARSE__ERROR_PAUSE; + #else + return 0; + #endif +} + + +int llhttp__on_method(llparse_t* s, const char* p, const char* endp) { + if (llparse__in_bench || s->type != HTTP_REQUEST) + return 0; + + return llparse__print_span("method", p, endp); +} + + +int llhttp__on_method_complete(llparse_t* s, const char* p, const char* endp) { + if (llparse__in_bench) + return 0; + + llparse__print(p, endp, "method complete"); + + #ifdef LLHTTP__TEST_PAUSE_ON_METHOD_COMPLETE + return LLPARSE__ERROR_PAUSE; + #else + return 0; + #endif +} + + +int llhttp__on_version(llparse_t* s, const char* p, const char* endp) { + if (llparse__in_bench) + return 0; + + return llparse__print_span("version", p, endp); +} + + +int llhttp__on_version_complete(llparse_t* s, const char* p, const char* endp) { + if (llparse__in_bench) + return 0; + + llparse__print(p, endp, "version complete"); + + #ifdef LLHTTP__TEST_PAUSE_ON_VERSION_COMPLETE + return LLPARSE__ERROR_PAUSE; + #else + return 0; + #endif +} + +int llhttp__on_header_field(llparse_t* s, const char* p, const char* endp) { + if (llparse__in_bench) + return 0; + + return llparse__print_span("header_field", p, endp); +} + + +int llhttp__on_header_field_complete(llparse_t* s, const char* p, const char* endp) { + if (llparse__in_bench) + return 0; + + llparse__print(p, endp, "header_field complete"); + + #ifdef LLHTTP__TEST_PAUSE_ON_HEADER_FIELD_COMPLETE + return LLPARSE__ERROR_PAUSE; + #else + return 0; + #endif +} + + +int llhttp__on_header_value(llparse_t* s, const char* p, const char* endp) { + if (llparse__in_bench) + return 0; + + return llparse__print_span("header_value", p, endp); +} + + +int llhttp__on_header_value_complete(llparse_t* s, const char* p, const char* endp) { + if (llparse__in_bench) + return 0; + + llparse__print(p, endp, "header_value complete"); + + #ifdef LLHTTP__TEST_PAUSE_ON_HEADER_VALUE_COMPLETE + return LLPARSE__ERROR_PAUSE; + #else + return 0; + #endif +} + + +int llhttp__on_headers_complete(llparse_t* s, const char* p, const char* endp) { + if (llparse__in_bench) + return 0; + + if (s->type == HTTP_REQUEST) { + llparse__print(p, endp, + "headers complete method=%d v=%d/%d flags=%x content_length=%llu", + s->method, s->http_major, s->http_minor, s->flags, s->content_length); + } else if (s->type == HTTP_RESPONSE) { + llparse__print(p, endp, + "headers complete status=%d v=%d/%d flags=%x content_length=%llu", + s->status_code, s->http_major, s->http_minor, s->flags, + s->content_length); + } else { + llparse__print(p, endp, "invalid headers complete"); + } + + #ifdef LLHTTP__TEST_PAUSE_ON_HEADERS_COMPLETE + return LLPARSE__ERROR_PAUSE; + #elif defined(LLHTTP__TEST_SKIP_BODY) + llparse__print(p, endp, "skip body"); + return 1; + #else + return 0; + #endif +} + + +int llhttp__on_body(llparse_t* s, const char* p, const char* endp) { + if (llparse__in_bench) + return 0; + + return llparse__print_span("body", p, endp); +} + + +int llhttp__on_chunk_header(llparse_t* s, const char* p, const char* endp) { + if (llparse__in_bench) + return 0; + + llparse__print(p, endp, "chunk header len=%d", (int) s->content_length); + + #ifdef LLHTTP__TEST_PAUSE_ON_CHUNK_HEADER + return LLPARSE__ERROR_PAUSE; + #else + return 0; + #endif +} + + +int llhttp__on_chunk_extension_name(llparse_t* s, const char* p, const char* endp) { + if (llparse__in_bench) + return 0; + + return llparse__print_span("chunk_extension_name", p, endp); +} + + +int llhttp__on_chunk_extension_name_complete(llparse_t* s, const char* p, const char* endp) { + if (llparse__in_bench) + return 0; + + llparse__print(p, endp, "chunk_extension_name complete"); + + #ifdef LLHTTP__TEST_PAUSE_ON_CHUNK_EXTENSION_NAME + return LLPARSE__ERROR_PAUSE; + #else + return 0; + #endif +} + + +int llhttp__on_chunk_extension_value(llparse_t* s, const char* p, const char* endp) { + if (llparse__in_bench) + return 0; + + return llparse__print_span("chunk_extension_value", p, endp); +} + + +int llhttp__on_chunk_extension_value_complete(llparse_t* s, const char* p, const char* endp) { + if (llparse__in_bench) + return 0; + + llparse__print(p, endp, "chunk_extension_value complete"); + + #ifdef LLHTTP__TEST_PAUSE_ON_CHUNK_EXTENSION_VALUE + return LLPARSE__ERROR_PAUSE; + #else + return 0; + #endif +} + + +int llhttp__on_chunk_complete(llparse_t* s, const char* p, const char* endp) { + if (llparse__in_bench) + return 0; + + llparse__print(p, endp, "chunk complete"); + + #ifdef LLHTTP__TEST_PAUSE_ON_CHUNK_COMPLETE + return LLPARSE__ERROR_PAUSE; + #else + return 0; + #endif +} + +int llhttp__on_reset(llparse_t* s, const char* p, const char* endp) { + if (llparse__in_bench) + return 0; + + llparse__print(p, endp, "reset"); + + #ifdef LLHTTP__TEST_PAUSE_ON_RESET + return LLPARSE__ERROR_PAUSE; + #else + return 0; + #endif +} + +#endif /* LLHTTP__TEST_HTTP */ diff --git a/vendor/llhttp/test/fixtures/index.ts b/vendor/llhttp/test/fixtures/index.ts new file mode 100644 index 0000000..1571f9d --- /dev/null +++ b/vendor/llhttp/test/fixtures/index.ts @@ -0,0 +1,116 @@ +import * as fs from 'fs'; +import { ICompilerResult, LLParse } from 'llparse'; +import { Dot } from 'llparse-dot'; +import { + Fixture, FixtureResult, IFixtureBuildOptions, +} from 'llparse-test-fixture'; +import * as path from 'path'; + +import * as llhttp from '../../src/llhttp'; + +export { FixtureResult }; + +export type TestType = 'request' | 'response' | 'request-finish' | 'response-finish' | + 'request-lenient-all' | 'response-lenient-all' | + 'request-lenient-headers' | 'response-lenient-headers' | + 'request-lenient-chunked-length' | 'request-lenient-transfer-encoding' | + 'request-lenient-keep-alive' | 'response-lenient-keep-alive' | + 'request-lenient-version' | 'response-lenient-version' | + 'request-lenient-data-after-close' | 'response-lenient-data-after-close' | + 'request-lenient-optional-lf-after-cr' | 'response-lenient-optional-lf-after-cr' | + 'request-lenient-optional-cr-before-lf' | 'response-lenient-optional-cr-before-lf' | + 'request-lenient-optional-crlf-after-chunk' | 'response-lenient-optional-crlf-after-chunk' | + 'request-lenient-spaces-after-chunk-size' | 'response-lenient-spaces-after-chunk-size' | + 'none' | 'url'; + +export const allowedTypes: TestType[] = [ + 'request', + 'response', + 'request-finish', + 'response-finish', + 'request-lenient-all', + 'response-lenient-all', + 'request-lenient-headers', + 'response-lenient-headers', + 'request-lenient-keep-alive', + 'response-lenient-keep-alive', + 'request-lenient-chunked-length', + 'request-lenient-transfer-encoding', + 'request-lenient-version', + 'response-lenient-version', + 'request-lenient-data-after-close', + 'response-lenient-data-after-close', + 'request-lenient-optional-lf-after-cr', + 'response-lenient-optional-lf-after-cr', + 'request-lenient-optional-cr-before-lf', + 'response-lenient-optional-cr-before-lf', + 'request-lenient-optional-crlf-after-chunk', + 'response-lenient-optional-crlf-after-chunk', + 'request-lenient-spaces-after-chunk-size', + 'response-lenient-spaces-after-chunk-size', +]; + +const BUILD_DIR = path.join(__dirname, '..', 'tmp'); +const CHEADERS_FILE = path.join(BUILD_DIR, 'cheaders.h'); + +const cheaders = new llhttp.CHeaders().build(); +try { + fs.mkdirSync(BUILD_DIR); +} catch (e) { + // no-op +} +fs.writeFileSync(CHEADERS_FILE, cheaders); + +const fixtures = new Fixture({ + buildDir: path.join(__dirname, '..', 'tmp'), + extra: [ + '-msse4.2', + '-DLLHTTP__TEST', + '-DLLPARSE__ERROR_PAUSE=' + llhttp.constants.ERROR.PAUSED, + '-include', CHEADERS_FILE, + path.join(__dirname, 'extra.c'), + ], + maxParallel: process.env.LLPARSE_DEBUG ? 1 : undefined, +}); + +const cache: Map = new Map(); + +export async function build( + llparse: LLParse, node: any, outFile: string, + options: IFixtureBuildOptions = {}, + ty: TestType = 'none'): Promise { + const dot = new Dot(); + fs.writeFileSync(path.join(BUILD_DIR, outFile + '.dot'), + dot.build(node)); + + let artifacts: ICompilerResult; + if (cache.has(node)) { + artifacts = cache.get(node)!; + } else { + artifacts = llparse.build(node, { + c: { header: outFile }, + debug: process.env.LLPARSE_DEBUG ? 'llparse__debug' : undefined, + }); + cache.set(node, artifacts); + } + + const extra = options.extra === undefined ? [] : options.extra.slice(); + + if (allowedTypes.includes(ty)) { + extra.push( + `-DLLPARSE__TEST_INIT=llhttp__test_init_${ty.replace(/-/g, '_')}`); + } + + if (ty === 'request-finish' || ty === 'response-finish') { + if (ty === 'request-finish') { + extra.push('-DLLPARSE__TEST_INIT=llhttp__test_init_request'); + } else { + extra.push('-DLLPARSE__TEST_INIT=llhttp__test_init_response'); + } + extra.push('-DLLPARSE__TEST_FINISH=llhttp__test_finish'); + } + + return await fixtures.build(artifacts, outFile, Object.assign(options, { + extra, + })); +} diff --git a/vendor/llhttp/test/fuzzers/fuzz_parser.c b/vendor/llhttp/test/fuzzers/fuzz_parser.c new file mode 100644 index 0000000..60d00ae --- /dev/null +++ b/vendor/llhttp/test/fuzzers/fuzz_parser.c @@ -0,0 +1,45 @@ +#include "llhttp.h" +#include +#include +#include + +int handle_on_message_complete(llhttp_t *arg) { return 0; } + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + llhttp_t parser; + llhttp_settings_t settings; + llhttp_type_t http_type; + + /* We need four bytes to determine variable parameters */ + if (size < 4) { + return 0; + } + + int headers = (data[0] & 0x01) == 1; + int chunked_length = (data[1] & 0x01) == 1; + int keep_alive = (data[2] & 0x01) == 1; + if (data[0] % 3 == 0) { + http_type = HTTP_BOTH; + } else if (data[0] % 3 == 1) { + http_type = HTTP_REQUEST; + } else { + http_type = HTTP_RESPONSE; + } + data += 4; + size -= 4; + + /* Initialize user callbacks and settings */ + llhttp_settings_init(&settings); + + /* Set user callback */ + settings.on_message_complete = handle_on_message_complete; + + llhttp_init(&parser, http_type, &settings); + llhttp_set_lenient_headers(&parser, headers); + llhttp_set_lenient_chunked_length(&parser, chunked_length); + llhttp_set_lenient_keep_alive(&parser, keep_alive); + + llhttp_execute(&parser, data, size); + + return 0; +} diff --git a/vendor/llhttp/test/md-test.ts b/vendor/llhttp/test/md-test.ts new file mode 100644 index 0000000..0c24e18 --- /dev/null +++ b/vendor/llhttp/test/md-test.ts @@ -0,0 +1,269 @@ +import * as assert from 'assert'; +import * as fs from 'fs'; +import { LLParse } from 'llparse'; +import { Group, MDGator, Metadata, Test } from 'mdgator'; +import * as path from 'path'; +import * as vm from 'vm'; + +import * as llhttp from '../src/llhttp'; +import {IHTTPResult} from '../src/llhttp/http'; +import {IURLResult} from '../src/llhttp/url'; +import { allowedTypes, build, FixtureResult, TestType } from './fixtures'; + +// +// Cache nodes/llparse instances ahead of time +// (different types of tests will re-use them) +// + +interface INodeCacheEntry { + llparse: LLParse; + entry: IHTTPResult['entry']; +} + +interface IUrlCacheEntry { + llparse: LLParse; + entry: IURLResult['entry']['normal']; +} + +const modeCache = new Map(); + +function buildNode() { + const p = new LLParse(); + const instance = new llhttp.HTTP(p); + + return { llparse: p, entry: instance.build().entry }; +} + +function buildURL() { + const p = new LLParse(); + const instance = new llhttp.URL(p, true); + + const node = instance.build(); + + // Loop + node.exit.toHTTP.otherwise(node.entry.normal); + node.exit.toHTTP09.otherwise(node.entry.normal); + + return { llparse: p, entry: node.entry.normal }; +} + +// +// Build binaries using cached nodes/llparse +// + +async function buildMode(ty: TestType, meta: any) + : Promise { + + const cacheKey = `${ty}:${JSON.stringify(meta || {})}`; + let entry = modeCache.get(cacheKey); + + if (entry) { + return entry; + } + + let node; + let prefix: string; + let extra: string[]; + if (ty === 'url') { + node = buildURL(); + prefix = 'url'; + extra = []; + } else { + node = buildNode(); + prefix = 'http'; + extra = [ + '-DLLHTTP__TEST_HTTP', + path.join(__dirname, '..', 'src', 'native', 'http.c'), + ]; + } + + if (meta.pause) { + extra.push(`-DLLHTTP__TEST_PAUSE_${meta.pause.toUpperCase()}=1`); + } + + if (meta.skipBody) { + extra.push('-DLLHTTP__TEST_SKIP_BODY=1'); + } + + entry = await build(node.llparse, node.entry, `${prefix}-${ty}`, { + extra, + }, ty); + + modeCache.set(cacheKey, entry); + return entry; +} + +interface IFixtureMap { + [key: string]: { [key: string]: Promise }; +} + +// +// Run test suite +// + +function run(name: string): void { + const md = new MDGator(); + + const raw = fs.readFileSync(path.join(__dirname, name + '.md')).toString(); + const groups = md.parse(raw); + + function runSingleTest(ty: TestType, meta: any, + input: string, + expected: ReadonlyArray): void { + it(`should pass for type="${ty}"`, async () => { + const binary = await buildMode(ty, meta); + await binary.check(input, expected, { + noScan: meta.noScan === true, + }); + }); + } + + function runTest(test: Test) { + describe(test.name + ` at ${name}.md:${test.line + 1}`, () => { + let types: TestType[] = []; + + const isURL = test.values.has('url'); + const inputKey = isURL ? 'url' : 'http'; + + assert(test.values.has(inputKey), + `Missing "${inputKey}" code in md file`); + assert.strictEqual(test.values.get(inputKey)!.length, 1, + `Expected just one "${inputKey}" input`); + + let meta: Metadata; + if (test.meta.has(inputKey)) { + meta = test.meta.get(inputKey)![0]!; + } else { + assert(isURL, 'Missing required http metadata'); + meta = {}; + } + + if (isURL) { + types = [ 'url' ]; + } else { + assert(meta.hasOwnProperty('type'), 'Missing required `type` metadata'); + + if (meta.type) { + if (!allowedTypes.includes(meta.type)) { + throw new Error(`Invalid value of \`type\` metadata: "${meta.type}"`); + } + + types.push(meta.type); + } + } + + assert(test.values.has('log'), 'Missing `log` code in md file'); + + assert.strictEqual(test.values.get('log')!.length, 1, + 'Expected just one output'); + + let input: string = test.values.get(inputKey)![0]; + let expected: string = test.values.get('log')![0]; + + // Remove trailing newline + input = input.replace(/\n$/, ''); + + // Remove escaped newlines + input = input.replace(/\\(\r\n|\r|\n)/g, ''); + + // Normalize all newlines + input = input.replace(/\r\n|\r|\n/g, '\r\n'); + + // Replace escaped CRLF, tabs, form-feed + input = input.replace(/\\r/g, '\r'); + input = input.replace(/\\n/g, '\n'); + input = input.replace(/\\t/g, '\t'); + input = input.replace(/\\f/g, '\f'); + input = input.replace(/\\x([0-9a-fA-F]+)/g, (all, hex) => { + return String.fromCharCode(parseInt(hex, 16)); + }); + + // Useful in token tests + input = input.replace(/\\([0-7]{1,3})/g, (_, digits) => { + return String.fromCharCode(parseInt(digits, 8)); + }); + + // Evaluate inline JavaScript + input = input.replace(/\$\{(.+?)\}/g, (_, code) => { + return vm.runInNewContext(code) + ''; + }); + + // Escape first symbol `\r` or `\n`, `|`, `&` for Windows + if (process.platform === 'win32') { + const firstByte = Buffer.from(input)[0]; + if (firstByte === 0x0a || firstByte === 0x0d) { + input = '\\' + input; + } + + input = input.replace(/\|/g, '^|'); + input = input.replace(/&/g, '^&'); + } + + // Replace escaped tabs/form-feed in expected too + expected = expected.replace(/\\t/g, '\t'); + expected = expected.replace(/\\f/g, '\f'); + + // Split + const expectedLines = expected.split(/\n/g).slice(0, -1); + + const fullExpected = expectedLines.map((line) => { + if (line.startsWith('/')) { + return new RegExp(line.trim().slice(1, -1)); + } else { + return line; + } + }); + + for (const ty of types) { + if (meta.skip === true || (process.env.ONLY === 'true' && !meta.only)) { + continue; + } + + runSingleTest(ty, meta, input, fullExpected); + } + }); + } + + function runGroup(group: Group) { + describe(group.name + ` at ${name}.md:${group.line + 1}`, function() { + this.timeout(60000); + + for (const child of group.children) { + runGroup(child); + } + + for (const test of group.tests) { + runTest(test); + } + }); + } + + for (const group of groups) { + runGroup(group); + } +} + +run('request/sample'); +run('request/lenient-headers'); +run('request/lenient-version'); +run('request/method'); +run('request/uri'); +run('request/connection'); +run('request/content-length'); +run('request/transfer-encoding'); +run('request/invalid'); +run('request/finish'); +run('request/pausing'); +run('request/pipelining'); + +run('response/sample'); +run('response/connection'); +run('response/content-length'); +run('response/transfer-encoding'); +run('response/invalid'); +run('response/finish'); +run('response/lenient-version'); +run('response/pausing'); +run('response/pipelining'); + +run('url'); diff --git a/vendor/llhttp/test/request/connection.md b/vendor/llhttp/test/request/connection.md new file mode 100644 index 0000000..a03242e --- /dev/null +++ b/vendor/llhttp/test/request/connection.md @@ -0,0 +1,732 @@ +Connection header +================= + +## `keep-alive` + +### Setting flag + + +```http +PUT /url HTTP/1.1 +Connection: keep-alive + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="PUT" +off=3 method complete +off=4 len=4 span[url]="/url" +off=9 url complete +off=14 len=3 span[version]="1.1" +off=17 version complete +off=19 len=10 span[header_field]="Connection" +off=30 header_field complete +off=31 len=10 span[header_value]="keep-alive" +off=43 header_value complete +off=45 headers complete method=4 v=1/1 flags=1 content_length=0 +off=45 message complete +``` + +### Restarting when keep-alive is explicitly + + +```http +PUT /url HTTP/1.1 +Connection: keep-alive + +PUT /url HTTP/1.1 +Connection: keep-alive + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="PUT" +off=3 method complete +off=4 len=4 span[url]="/url" +off=9 url complete +off=14 len=3 span[version]="1.1" +off=17 version complete +off=19 len=10 span[header_field]="Connection" +off=30 header_field complete +off=31 len=10 span[header_value]="keep-alive" +off=43 header_value complete +off=45 headers complete method=4 v=1/1 flags=1 content_length=0 +off=45 message complete +off=45 reset +off=45 message begin +off=45 len=3 span[method]="PUT" +off=48 method complete +off=49 len=4 span[url]="/url" +off=54 url complete +off=59 len=3 span[version]="1.1" +off=62 version complete +off=64 len=10 span[header_field]="Connection" +off=75 header_field complete +off=76 len=10 span[header_value]="keep-alive" +off=88 header_value complete +off=90 headers complete method=4 v=1/1 flags=1 content_length=0 +off=90 message complete +``` + +### No restart when keep-alive is off (1.0) + + +```http +PUT /url HTTP/1.0 + +PUT /url HTTP/1.1 + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="PUT" +off=3 method complete +off=4 len=4 span[url]="/url" +off=9 url complete +off=14 len=3 span[version]="1.0" +off=17 version complete +off=21 headers complete method=4 v=1/0 flags=0 content_length=0 +off=21 message complete +off=22 error code=5 reason="Data after `Connection: close`" +``` + +### Resetting flags when keep-alive is off (1.0, lenient) + +Even though we allow restarts in loose mode, the flags should be still set to +`0` upon restart. + + +```http +PUT /url HTTP/1.0 +Content-Length: 0 + +PUT /url HTTP/1.1 +Transfer-Encoding: chunked + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="PUT" +off=3 method complete +off=4 len=4 span[url]="/url" +off=9 url complete +off=14 len=3 span[version]="1.0" +off=17 version complete +off=19 len=14 span[header_field]="Content-Length" +off=34 header_field complete +off=35 len=1 span[header_value]="0" +off=38 header_value complete +off=40 headers complete method=4 v=1/0 flags=20 content_length=0 +off=40 message complete +off=40 reset +off=40 message begin +off=40 len=3 span[method]="PUT" +off=43 method complete +off=44 len=4 span[url]="/url" +off=49 url complete +off=54 len=3 span[version]="1.1" +off=57 version complete +off=59 len=17 span[header_field]="Transfer-Encoding" +off=77 header_field complete +off=78 len=7 span[header_value]="chunked" +off=87 header_value complete +off=89 headers complete method=4 v=1/1 flags=208 content_length=0 +``` + +### CRLF between requests, implicit `keep-alive` + + +```http +POST / HTTP/1.1 +Host: www.example.com +Content-Type: application/x-www-form-urlencoded +Content-Length: 4 + +q=42 + +GET / HTTP/1.1 +``` +_Note the trailing CRLF above_ + +```log +off=0 message begin +off=0 len=4 span[method]="POST" +off=4 method complete +off=5 len=1 span[url]="/" +off=7 url complete +off=12 len=3 span[version]="1.1" +off=15 version complete +off=17 len=4 span[header_field]="Host" +off=22 header_field complete +off=23 len=15 span[header_value]="www.example.com" +off=40 header_value complete +off=40 len=12 span[header_field]="Content-Type" +off=53 header_field complete +off=54 len=33 span[header_value]="application/x-www-form-urlencoded" +off=89 header_value complete +off=89 len=14 span[header_field]="Content-Length" +off=104 header_field complete +off=105 len=1 span[header_value]="4" +off=108 header_value complete +off=110 headers complete method=3 v=1/1 flags=20 content_length=4 +off=110 len=4 span[body]="q=42" +off=114 message complete +off=118 reset +off=118 message begin +off=118 len=3 span[method]="GET" +off=121 method complete +off=122 len=1 span[url]="/" +off=124 url complete +off=129 len=3 span[version]="1.1" +off=132 version complete +``` + +### Not treating `\r` as `-` + + +```http +PUT /url HTTP/1.1 +Connection: keep\ralive + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="PUT" +off=3 method complete +off=4 len=4 span[url]="/url" +off=9 url complete +off=14 len=3 span[version]="1.1" +off=17 version complete +off=19 len=10 span[header_field]="Connection" +off=30 header_field complete +off=31 len=4 span[header_value]="keep" +off=36 error code=3 reason="Missing expected LF after header value" +``` + +## `close` + +### Setting flag on `close` + + +```http +PUT /url HTTP/1.1 +Connection: close + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="PUT" +off=3 method complete +off=4 len=4 span[url]="/url" +off=9 url complete +off=14 len=3 span[version]="1.1" +off=17 version complete +off=19 len=10 span[header_field]="Connection" +off=30 header_field complete +off=31 len=5 span[header_value]="close" +off=38 header_value complete +off=40 headers complete method=4 v=1/1 flags=2 content_length=0 +off=40 message complete +``` + +### CRLF between requests, explicit `close` + +`close` means closed connection + + +```http +POST / HTTP/1.1 +Host: www.example.com +Content-Type: application/x-www-form-urlencoded +Content-Length: 4 +Connection: close + +q=42 + +GET / HTTP/1.1 +``` +_Note the trailing CRLF above_ + +```log +off=0 message begin +off=0 len=4 span[method]="POST" +off=4 method complete +off=5 len=1 span[url]="/" +off=7 url complete +off=12 len=3 span[version]="1.1" +off=15 version complete +off=17 len=4 span[header_field]="Host" +off=22 header_field complete +off=23 len=15 span[header_value]="www.example.com" +off=40 header_value complete +off=40 len=12 span[header_field]="Content-Type" +off=53 header_field complete +off=54 len=33 span[header_value]="application/x-www-form-urlencoded" +off=89 header_value complete +off=89 len=14 span[header_field]="Content-Length" +off=104 header_field complete +off=105 len=1 span[header_value]="4" +off=108 header_value complete +off=108 len=10 span[header_field]="Connection" +off=119 header_field complete +off=120 len=5 span[header_value]="close" +off=127 header_value complete +off=129 headers complete method=3 v=1/1 flags=22 content_length=4 +off=129 len=4 span[body]="q=42" +off=133 message complete +off=138 error code=5 reason="Data after `Connection: close`" +``` + +### CRLF between requests, explicit `close` (lenient) + +Loose mode is more lenient, and allows further requests. + + +```http +POST / HTTP/1.1 +Host: www.example.com +Content-Type: application/x-www-form-urlencoded +Content-Length: 4 +Connection: close + +q=42 + +GET / HTTP/1.1 +``` +_Note the trailing CRLF above_ + +```log +off=0 message begin +off=0 len=4 span[method]="POST" +off=4 method complete +off=5 len=1 span[url]="/" +off=7 url complete +off=12 len=3 span[version]="1.1" +off=15 version complete +off=17 len=4 span[header_field]="Host" +off=22 header_field complete +off=23 len=15 span[header_value]="www.example.com" +off=40 header_value complete +off=40 len=12 span[header_field]="Content-Type" +off=53 header_field complete +off=54 len=33 span[header_value]="application/x-www-form-urlencoded" +off=89 header_value complete +off=89 len=14 span[header_field]="Content-Length" +off=104 header_field complete +off=105 len=1 span[header_value]="4" +off=108 header_value complete +off=108 len=10 span[header_field]="Connection" +off=119 header_field complete +off=120 len=5 span[header_value]="close" +off=127 header_value complete +off=129 headers complete method=3 v=1/1 flags=22 content_length=4 +off=129 len=4 span[body]="q=42" +off=133 message complete +off=137 reset +off=137 message begin +off=137 len=3 span[method]="GET" +off=140 method complete +off=141 len=1 span[url]="/" +off=143 url complete +off=148 len=3 span[version]="1.1" +off=151 version complete +``` + +## Parsing multiple tokens + +### Sample + + +```http +PUT /url HTTP/1.1 +Connection: close, token, upgrade, token, keep-alive + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="PUT" +off=3 method complete +off=4 len=4 span[url]="/url" +off=9 url complete +off=14 len=3 span[version]="1.1" +off=17 version complete +off=19 len=10 span[header_field]="Connection" +off=30 header_field complete +off=31 len=40 span[header_value]="close, token, upgrade, token, keep-alive" +off=73 header_value complete +off=75 headers complete method=4 v=1/1 flags=7 content_length=0 +off=75 message complete +``` + +### Multiple tokens with folding + + +```http +GET /demo HTTP/1.1 +Host: example.com +Connection: Something, + Upgrade, ,Keep-Alive +Sec-WebSocket-Key2: 12998 5 Y3 1 .P00 +Sec-WebSocket-Protocol: sample +Upgrade: WebSocket +Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5 +Origin: http://example.com + +Hot diggity dogg +``` + +```log +off=0 message begin +off=0 len=3 span[method]="GET" +off=3 method complete +off=4 len=5 span[url]="/demo" +off=10 url complete +off=15 len=3 span[version]="1.1" +off=18 version complete +off=20 len=4 span[header_field]="Host" +off=25 header_field complete +off=26 len=11 span[header_value]="example.com" +off=39 header_value complete +off=39 len=10 span[header_field]="Connection" +off=50 header_field complete +off=51 len=10 span[header_value]="Something," +off=63 len=21 span[header_value]=" Upgrade, ,Keep-Alive" +off=86 header_value complete +off=86 len=18 span[header_field]="Sec-WebSocket-Key2" +off=105 header_field complete +off=106 len=18 span[header_value]="12998 5 Y3 1 .P00" +off=126 header_value complete +off=126 len=22 span[header_field]="Sec-WebSocket-Protocol" +off=149 header_field complete +off=150 len=6 span[header_value]="sample" +off=158 header_value complete +off=158 len=7 span[header_field]="Upgrade" +off=166 header_field complete +off=167 len=9 span[header_value]="WebSocket" +off=178 header_value complete +off=178 len=18 span[header_field]="Sec-WebSocket-Key1" +off=197 header_field complete +off=198 len=20 span[header_value]="4 @1 46546xW%0l 1 5" +off=220 header_value complete +off=220 len=6 span[header_field]="Origin" +off=227 header_field complete +off=228 len=18 span[header_value]="http://example.com" +off=248 header_value complete +off=250 headers complete method=1 v=1/1 flags=15 content_length=0 +off=250 message complete +off=250 error code=22 reason="Pause on CONNECT/Upgrade" +``` + +### Multiple tokens with folding and LWS + + +```http +GET /demo HTTP/1.1 +Connection: keep-alive, upgrade +Upgrade: WebSocket + +Hot diggity dogg +``` + +```log +off=0 message begin +off=0 len=3 span[method]="GET" +off=3 method complete +off=4 len=5 span[url]="/demo" +off=10 url complete +off=15 len=3 span[version]="1.1" +off=18 version complete +off=20 len=10 span[header_field]="Connection" +off=31 header_field complete +off=32 len=19 span[header_value]="keep-alive, upgrade" +off=53 header_value complete +off=53 len=7 span[header_field]="Upgrade" +off=61 header_field complete +off=62 len=9 span[header_value]="WebSocket" +off=73 header_value complete +off=75 headers complete method=1 v=1/1 flags=15 content_length=0 +off=75 message complete +off=75 error code=22 reason="Pause on CONNECT/Upgrade" +``` + +### Multiple tokens with folding, LWS, and CRLF + + +```http +GET /demo HTTP/1.1 +Connection: keep-alive, \r\n upgrade +Upgrade: WebSocket + +Hot diggity dogg +``` + +```log +off=0 message begin +off=0 len=3 span[method]="GET" +off=3 method complete +off=4 len=5 span[url]="/demo" +off=10 url complete +off=15 len=3 span[version]="1.1" +off=18 version complete +off=20 len=10 span[header_field]="Connection" +off=31 header_field complete +off=32 len=12 span[header_value]="keep-alive, " +off=46 len=8 span[header_value]=" upgrade" +off=56 header_value complete +off=56 len=7 span[header_field]="Upgrade" +off=64 header_field complete +off=65 len=9 span[header_value]="WebSocket" +off=76 header_value complete +off=78 headers complete method=1 v=1/1 flags=15 content_length=0 +off=78 message complete +off=78 error code=22 reason="Pause on CONNECT/Upgrade" +``` + +### Invalid whitespace token with `Connection` header field + + +```http +PUT /url HTTP/1.1 +Connection : upgrade +Content-Length: 4 +Upgrade: ws + +abcdefgh +``` + +```log +off=0 message begin +off=0 len=3 span[method]="PUT" +off=3 method complete +off=4 len=4 span[url]="/url" +off=9 url complete +off=14 len=3 span[version]="1.1" +off=17 version complete +off=19 len=10 span[header_field]="Connection" +off=30 error code=10 reason="Invalid header field char" +``` + +### Invalid whitespace token with `Connection` header field (lenient) + + +```http +PUT /url HTTP/1.1 +Connection : upgrade +Content-Length: 4 +Upgrade: ws + +abcdefgh +``` + +```log +off=0 message begin +off=0 len=3 span[method]="PUT" +off=3 method complete +off=4 len=4 span[url]="/url" +off=9 url complete +off=14 len=3 span[version]="1.1" +off=17 version complete +off=19 len=11 span[header_field]="Connection " +off=31 header_field complete +off=32 len=7 span[header_value]="upgrade" +off=41 header_value complete +off=41 len=14 span[header_field]="Content-Length" +off=56 header_field complete +off=57 len=1 span[header_value]="4" +off=60 header_value complete +off=60 len=7 span[header_field]="Upgrade" +off=68 header_field complete +off=69 len=2 span[header_value]="ws" +off=73 header_value complete +off=75 headers complete method=4 v=1/1 flags=34 content_length=4 +off=75 len=4 span[body]="abcd" +off=79 message complete +off=79 error code=22 reason="Pause on CONNECT/Upgrade" +``` + +## `upgrade` + +### Setting a flag and pausing + + +```http +PUT /url HTTP/1.1 +Connection: upgrade +Upgrade: ws + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="PUT" +off=3 method complete +off=4 len=4 span[url]="/url" +off=9 url complete +off=14 len=3 span[version]="1.1" +off=17 version complete +off=19 len=10 span[header_field]="Connection" +off=30 header_field complete +off=31 len=7 span[header_value]="upgrade" +off=40 header_value complete +off=40 len=7 span[header_field]="Upgrade" +off=48 header_field complete +off=49 len=2 span[header_value]="ws" +off=53 header_value complete +off=55 headers complete method=4 v=1/1 flags=14 content_length=0 +off=55 message complete +off=55 error code=22 reason="Pause on CONNECT/Upgrade" +``` + +### Emitting part of body and pausing + + +```http +PUT /url HTTP/1.1 +Connection: upgrade +Content-Length: 4 +Upgrade: ws + +abcdefgh +``` + +```log +off=0 message begin +off=0 len=3 span[method]="PUT" +off=3 method complete +off=4 len=4 span[url]="/url" +off=9 url complete +off=14 len=3 span[version]="1.1" +off=17 version complete +off=19 len=10 span[header_field]="Connection" +off=30 header_field complete +off=31 len=7 span[header_value]="upgrade" +off=40 header_value complete +off=40 len=14 span[header_field]="Content-Length" +off=55 header_field complete +off=56 len=1 span[header_value]="4" +off=59 header_value complete +off=59 len=7 span[header_field]="Upgrade" +off=67 header_field complete +off=68 len=2 span[header_value]="ws" +off=72 header_value complete +off=74 headers complete method=4 v=1/1 flags=34 content_length=4 +off=74 len=4 span[body]="abcd" +off=78 message complete +off=78 error code=22 reason="Pause on CONNECT/Upgrade" +``` + +### Upgrade GET request + + +```http +GET /demo HTTP/1.1 +Host: example.com +Connection: Upgrade +Sec-WebSocket-Key2: 12998 5 Y3 1 .P00 +Sec-WebSocket-Protocol: sample +Upgrade: WebSocket +Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5 +Origin: http://example.com + +Hot diggity dogg +``` + +```log +off=0 message begin +off=0 len=3 span[method]="GET" +off=3 method complete +off=4 len=5 span[url]="/demo" +off=10 url complete +off=15 len=3 span[version]="1.1" +off=18 version complete +off=20 len=4 span[header_field]="Host" +off=25 header_field complete +off=26 len=11 span[header_value]="example.com" +off=39 header_value complete +off=39 len=10 span[header_field]="Connection" +off=50 header_field complete +off=51 len=7 span[header_value]="Upgrade" +off=60 header_value complete +off=60 len=18 span[header_field]="Sec-WebSocket-Key2" +off=79 header_field complete +off=80 len=18 span[header_value]="12998 5 Y3 1 .P00" +off=100 header_value complete +off=100 len=22 span[header_field]="Sec-WebSocket-Protocol" +off=123 header_field complete +off=124 len=6 span[header_value]="sample" +off=132 header_value complete +off=132 len=7 span[header_field]="Upgrade" +off=140 header_field complete +off=141 len=9 span[header_value]="WebSocket" +off=152 header_value complete +off=152 len=18 span[header_field]="Sec-WebSocket-Key1" +off=171 header_field complete +off=172 len=20 span[header_value]="4 @1 46546xW%0l 1 5" +off=194 header_value complete +off=194 len=6 span[header_field]="Origin" +off=201 header_field complete +off=202 len=18 span[header_value]="http://example.com" +off=222 header_value complete +off=224 headers complete method=1 v=1/1 flags=14 content_length=0 +off=224 message complete +off=224 error code=22 reason="Pause on CONNECT/Upgrade" +``` + +### Upgrade POST request + + +```http +POST /demo HTTP/1.1 +Host: example.com +Connection: Upgrade +Upgrade: HTTP/2.0 +Content-Length: 15 + +sweet post body\ +Hot diggity dogg +``` + +```log +off=0 message begin +off=0 len=4 span[method]="POST" +off=4 method complete +off=5 len=5 span[url]="/demo" +off=11 url complete +off=16 len=3 span[version]="1.1" +off=19 version complete +off=21 len=4 span[header_field]="Host" +off=26 header_field complete +off=27 len=11 span[header_value]="example.com" +off=40 header_value complete +off=40 len=10 span[header_field]="Connection" +off=51 header_field complete +off=52 len=7 span[header_value]="Upgrade" +off=61 header_value complete +off=61 len=7 span[header_field]="Upgrade" +off=69 header_field complete +off=70 len=8 span[header_value]="HTTP/2.0" +off=80 header_value complete +off=80 len=14 span[header_field]="Content-Length" +off=95 header_field complete +off=96 len=2 span[header_value]="15" +off=100 header_value complete +off=102 headers complete method=3 v=1/1 flags=34 content_length=15 +off=102 len=15 span[body]="sweet post body" +off=117 message complete +off=117 error code=22 reason="Pause on CONNECT/Upgrade" +``` diff --git a/vendor/llhttp/test/request/content-length.md b/vendor/llhttp/test/request/content-length.md new file mode 100644 index 0000000..524d183 --- /dev/null +++ b/vendor/llhttp/test/request/content-length.md @@ -0,0 +1,482 @@ +Content-Length header +===================== + +## `Content-Length` with zeroes + + +```http +PUT /url HTTP/1.1 +Content-Length: 003 + +abc +``` + +```log +off=0 message begin +off=0 len=3 span[method]="PUT" +off=3 method complete +off=4 len=4 span[url]="/url" +off=9 url complete +off=14 len=3 span[version]="1.1" +off=17 version complete +off=19 len=14 span[header_field]="Content-Length" +off=34 header_field complete +off=35 len=3 span[header_value]="003" +off=40 header_value complete +off=42 headers complete method=4 v=1/1 flags=20 content_length=3 +off=42 len=3 span[body]="abc" +off=45 message complete +``` + +## `Content-Length` with follow-up headers + +The way the parser works is that special headers (like `Content-Length`) first +set `header_state` to appropriate value, and then apply custom parsing using +that value. For `Content-Length`, in particular, the `header_state` is used for +setting the flag too. + +Make sure that `header_state` is reset to `0`, so that the flag won't be +attempted to set twice (and error). + + +```http +PUT /url HTTP/1.1 +Content-Length: 003 +Ohai: world + +abc +``` + +```log +off=0 message begin +off=0 len=3 span[method]="PUT" +off=3 method complete +off=4 len=4 span[url]="/url" +off=9 url complete +off=14 len=3 span[version]="1.1" +off=17 version complete +off=19 len=14 span[header_field]="Content-Length" +off=34 header_field complete +off=35 len=3 span[header_value]="003" +off=40 header_value complete +off=40 len=4 span[header_field]="Ohai" +off=45 header_field complete +off=46 len=5 span[header_value]="world" +off=53 header_value complete +off=55 headers complete method=4 v=1/1 flags=20 content_length=3 +off=55 len=3 span[body]="abc" +off=58 message complete +``` + +## Error on `Content-Length` overflow + + +```http +PUT /url HTTP/1.1 +Content-Length: 1000000000000000000000 + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="PUT" +off=3 method complete +off=4 len=4 span[url]="/url" +off=9 url complete +off=14 len=3 span[version]="1.1" +off=17 version complete +off=19 len=14 span[header_field]="Content-Length" +off=34 header_field complete +off=35 len=21 span[header_value]="100000000000000000000" +off=56 error code=11 reason="Content-Length overflow" +``` + +## Error on duplicate `Content-Length` + + +```http +PUT /url HTTP/1.1 +Content-Length: 1 +Content-Length: 2 + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="PUT" +off=3 method complete +off=4 len=4 span[url]="/url" +off=9 url complete +off=14 len=3 span[version]="1.1" +off=17 version complete +off=19 len=14 span[header_field]="Content-Length" +off=34 header_field complete +off=35 len=1 span[header_value]="1" +off=38 header_value complete +off=38 len=14 span[header_field]="Content-Length" +off=53 header_field complete +off=54 error code=4 reason="Duplicate Content-Length" +``` + +## Error on simultaneous `Content-Length` and `Transfer-Encoding: identity` + + +```http +PUT /url HTTP/1.1 +Content-Length: 1 +Transfer-Encoding: identity + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="PUT" +off=3 method complete +off=4 len=4 span[url]="/url" +off=9 url complete +off=14 len=3 span[version]="1.1" +off=17 version complete +off=19 len=14 span[header_field]="Content-Length" +off=34 header_field complete +off=35 len=1 span[header_value]="1" +off=38 header_value complete +off=38 len=17 span[header_field]="Transfer-Encoding" +off=56 header_field complete +off=56 error code=15 reason="Transfer-Encoding can't be present with Content-Length" +``` + +## Invalid whitespace token with `Content-Length` header field + + +```http +PUT /url HTTP/1.1 +Connection: upgrade +Content-Length : 4 +Upgrade: ws + +abcdefgh +``` + +```log +off=0 message begin +off=0 len=3 span[method]="PUT" +off=3 method complete +off=4 len=4 span[url]="/url" +off=9 url complete +off=14 len=3 span[version]="1.1" +off=17 version complete +off=19 len=10 span[header_field]="Connection" +off=30 header_field complete +off=31 len=7 span[header_value]="upgrade" +off=40 header_value complete +off=40 len=14 span[header_field]="Content-Length" +off=55 error code=10 reason="Invalid header field char" +``` + +## Invalid whitespace token with `Content-Length` header field (lenient) + + +```http +PUT /url HTTP/1.1 +Connection: upgrade +Content-Length : 4 +Upgrade: ws + +abcdefgh +``` + +```log +off=0 message begin +off=0 len=3 span[method]="PUT" +off=3 method complete +off=4 len=4 span[url]="/url" +off=9 url complete +off=14 len=3 span[version]="1.1" +off=17 version complete +off=19 len=10 span[header_field]="Connection" +off=30 header_field complete +off=31 len=7 span[header_value]="upgrade" +off=40 header_value complete +off=40 len=15 span[header_field]="Content-Length " +off=56 header_field complete +off=57 len=1 span[header_value]="4" +off=60 header_value complete +off=60 len=7 span[header_field]="Upgrade" +off=68 header_field complete +off=69 len=2 span[header_value]="ws" +off=73 header_value complete +off=75 headers complete method=4 v=1/1 flags=34 content_length=4 +off=75 len=4 span[body]="abcd" +off=79 message complete +off=79 error code=22 reason="Pause on CONNECT/Upgrade" +``` + +## No error on simultaneous `Content-Length` and `Transfer-Encoding: identity` (lenient) + + +```http +PUT /url HTTP/1.1 +Content-Length: 1 +Transfer-Encoding: identity + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="PUT" +off=3 method complete +off=4 len=4 span[url]="/url" +off=9 url complete +off=14 len=3 span[version]="1.1" +off=17 version complete +off=19 len=14 span[header_field]="Content-Length" +off=34 header_field complete +off=35 len=1 span[header_value]="1" +off=38 header_value complete +off=38 len=17 span[header_field]="Transfer-Encoding" +off=56 header_field complete +off=57 len=8 span[header_value]="identity" +off=67 header_value complete +off=69 headers complete method=4 v=1/1 flags=220 content_length=1 +``` + +## Funky `Content-Length` with body + + +```http +GET /get_funky_content_length_body_hello HTTP/1.0 +conTENT-Length: 5 + +HELLO +``` + +```log +off=0 message begin +off=0 len=3 span[method]="GET" +off=3 method complete +off=4 len=36 span[url]="/get_funky_content_length_body_hello" +off=41 url complete +off=46 len=3 span[version]="1.0" +off=49 version complete +off=51 len=14 span[header_field]="conTENT-Length" +off=66 header_field complete +off=67 len=1 span[header_value]="5" +off=70 header_value complete +off=72 headers complete method=1 v=1/0 flags=20 content_length=5 +off=72 len=5 span[body]="HELLO" +off=77 message complete +``` + +## Spaces in `Content-Length` (surrounding) + + +```http +POST / HTTP/1.1 +Content-Length: 42 + + +``` + +```log +off=0 message begin +off=0 len=4 span[method]="POST" +off=4 method complete +off=5 len=1 span[url]="/" +off=7 url complete +off=12 len=3 span[version]="1.1" +off=15 version complete +off=17 len=14 span[header_field]="Content-Length" +off=32 header_field complete +off=34 len=3 span[header_value]="42 " +off=39 header_value complete +off=41 headers complete method=3 v=1/1 flags=20 content_length=42 +``` + +### Spaces in `Content-Length` #2 + + +```http +POST / HTTP/1.1 +Content-Length: 4 2 + + +``` + +```log +off=0 message begin +off=0 len=4 span[method]="POST" +off=4 method complete +off=5 len=1 span[url]="/" +off=7 url complete +off=12 len=3 span[version]="1.1" +off=15 version complete +off=17 len=14 span[header_field]="Content-Length" +off=32 header_field complete +off=33 len=2 span[header_value]="4 " +off=35 error code=11 reason="Invalid character in Content-Length" +``` + +### Spaces in `Content-Length` #3 + + +```http +POST / HTTP/1.1 +Content-Length: 13 37 + + +``` + +```log +off=0 message begin +off=0 len=4 span[method]="POST" +off=4 method complete +off=5 len=1 span[url]="/" +off=7 url complete +off=12 len=3 span[version]="1.1" +off=15 version complete +off=17 len=14 span[header_field]="Content-Length" +off=32 header_field complete +off=33 len=3 span[header_value]="13 " +off=36 error code=11 reason="Invalid character in Content-Length" +``` + +### Empty `Content-Length` + + +```http +POST / HTTP/1.1 +Content-Length: + + +``` + +```log +off=0 message begin +off=0 len=4 span[method]="POST" +off=4 method complete +off=5 len=1 span[url]="/" +off=7 url complete +off=12 len=3 span[version]="1.1" +off=15 version complete +off=17 len=14 span[header_field]="Content-Length" +off=32 header_field complete +off=34 error code=11 reason="Empty Content-Length" +``` + +## `Content-Length` with CR instead of dash + + +```http +PUT /url HTTP/1.1 +Content\rLength: 003 + +abc +``` + +```log +off=0 message begin +off=0 len=3 span[method]="PUT" +off=3 method complete +off=4 len=4 span[url]="/url" +off=9 url complete +off=14 len=3 span[version]="1.1" +off=17 version complete +off=26 error code=10 reason="Invalid header token" +``` + +## Content-Length reset when no body is received + + +```http +PUT /url HTTP/1.1 +Content-Length: 123 + +POST /url HTTP/1.1 +Content-Length: 456 + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="PUT" +off=3 method complete +off=4 len=4 span[url]="/url" +off=9 url complete +off=14 len=3 span[version]="1.1" +off=17 version complete +off=19 len=14 span[header_field]="Content-Length" +off=34 header_field complete +off=35 len=3 span[header_value]="123" +off=40 header_value complete +off=42 headers complete method=4 v=1/1 flags=20 content_length=123 +off=42 skip body +off=42 message complete +off=42 reset +off=42 message begin +off=42 len=4 span[method]="POST" +off=46 method complete +off=47 len=4 span[url]="/url" +off=52 url complete +off=57 len=3 span[version]="1.1" +off=60 version complete +off=62 len=14 span[header_field]="Content-Length" +off=77 header_field complete +off=78 len=3 span[header_value]="456" +off=83 header_value complete +off=85 headers complete method=3 v=1/1 flags=20 content_length=456 +off=85 skip body +off=85 message complete +``` + +## Missing CRLF-CRLF before body + + +```http +PUT /url HTTP/1.1 +Content-Length: 3 +\rabc +``` + +```log +off=0 message begin +off=0 len=3 span[method]="PUT" +off=3 method complete +off=4 len=4 span[url]="/url" +off=9 url complete +off=14 len=3 span[version]="1.1" +off=17 version complete +off=19 len=14 span[header_field]="Content-Length" +off=34 header_field complete +off=35 len=1 span[header_value]="3" +off=38 header_value complete +off=39 error code=2 reason="Expected LF after headers" +``` + +## Missing CRLF-CRLF before body (lenient) + + +```http +PUT /url HTTP/1.1 +Content-Length: 3 +\rabc +``` + +```log +off=0 message begin +off=0 len=3 span[method]="PUT" +off=3 method complete +off=4 len=4 span[url]="/url" +off=9 url complete +off=14 len=3 span[version]="1.1" +off=17 version complete +off=19 len=14 span[header_field]="Content-Length" +off=34 header_field complete +off=35 len=1 span[header_value]="3" +off=38 header_value complete +off=39 headers complete method=4 v=1/1 flags=20 content_length=3 +off=39 len=3 span[body]="abc" +off=42 message complete +``` \ No newline at end of file diff --git a/vendor/llhttp/test/request/finish.md b/vendor/llhttp/test/request/finish.md new file mode 100644 index 0000000..710daa5 --- /dev/null +++ b/vendor/llhttp/test/request/finish.md @@ -0,0 +1,69 @@ +Finish +====== + +Those tests check the return codes and the behavior of `llhttp_finish()` C API. + +## It should be safe to finish after GET request + + +```http +GET / HTTP/1.1 + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="GET" +off=3 method complete +off=4 len=1 span[url]="/" +off=6 url complete +off=11 len=3 span[version]="1.1" +off=14 version complete +off=18 headers complete method=1 v=1/1 flags=0 content_length=0 +off=18 message complete +off=NULL finish=0 +``` + +## It should be unsafe to finish after incomplete PUT request + + +```http +PUT / HTTP/1.1 +Content-Length: 100 + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="PUT" +off=3 method complete +off=4 len=1 span[url]="/" +off=6 url complete +off=11 len=3 span[version]="1.1" +off=14 version complete +off=16 len=14 span[header_field]="Content-Length" +off=31 header_field complete +off=32 len=3 span[header_value]="100" +off=NULL finish=2 +``` + +## It should be unsafe to finish inside of the header + + +```http +PUT / HTTP/1.1 +Content-Leng +``` + +```log +off=0 message begin +off=0 len=3 span[method]="PUT" +off=3 method complete +off=4 len=1 span[url]="/" +off=6 url complete +off=11 len=3 span[version]="1.1" +off=14 version complete +off=16 len=12 span[header_field]="Content-Leng" +off=NULL finish=2 +``` diff --git a/vendor/llhttp/test/request/invalid.md b/vendor/llhttp/test/request/invalid.md new file mode 100644 index 0000000..8eadacf --- /dev/null +++ b/vendor/llhttp/test/request/invalid.md @@ -0,0 +1,586 @@ +Invalid requests +================ + +### ICE protocol and GET method + + +```http +GET /music/sweet/music ICE/1.0 +Host: example.com + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="GET" +off=3 method complete +off=4 len=18 span[url]="/music/sweet/music" +off=23 url complete +off=27 error code=8 reason="Expected SOURCE method for ICE/x.x request" +``` + +### ICE protocol, but not really + + +```http +GET /music/sweet/music IHTTP/1.0 +Host: example.com + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="GET" +off=3 method complete +off=4 len=18 span[url]="/music/sweet/music" +off=23 url complete +off=24 error code=8 reason="Expected HTTP/" +``` + +### RTSP protocol and PUT method + + +```http +PUT /music/sweet/music RTSP/1.0 +Host: example.com + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="PUT" +off=3 method complete +off=4 len=18 span[url]="/music/sweet/music" +off=23 url complete +off=28 error code=8 reason="Invalid method for RTSP/x.x request" +``` + +### HTTP protocol and ANNOUNCE method + + +```http +ANNOUNCE /music/sweet/music HTTP/1.0 +Host: example.com + + +``` + +```log +off=0 message begin +off=0 len=8 span[method]="ANNOUNCE" +off=8 method complete +off=9 len=18 span[url]="/music/sweet/music" +off=28 url complete +off=33 error code=8 reason="Invalid method for HTTP/x.x request" +``` + +### Headers separated by CR + + +```http +GET / HTTP/1.1 +Foo: 1\rBar: 2 + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="GET" +off=3 method complete +off=4 len=1 span[url]="/" +off=6 url complete +off=11 len=3 span[version]="1.1" +off=14 version complete +off=16 len=3 span[header_field]="Foo" +off=20 header_field complete +off=21 len=1 span[header_value]="1" +off=23 error code=3 reason="Missing expected LF after header value" +``` + +### Headers separated by LF + + +```http +POST / HTTP/1.1 +Host: localhost:5000 +x:x\nTransfer-Encoding: chunked + +1 +A +0 + +``` + +```log +off=0 message begin +off=0 len=4 span[method]="POST" +off=4 method complete +off=5 len=1 span[url]="/" +off=7 url complete +off=12 len=3 span[version]="1.1" +off=15 version complete +off=17 len=4 span[header_field]="Host" +off=22 header_field complete +off=23 len=14 span[header_value]="localhost:5000" +off=39 header_value complete +off=39 len=1 span[header_field]="x" +off=41 header_field complete +off=41 len=1 span[header_value]="x" +off=42 error code=25 reason="Missing expected CR after header value" +``` + +### Headers separated by dummy characters + + +```http +GET / HTTP/1.1 +Connection: close +Host: a +\rZGET /evil: HTTP/1.1 +Host: a + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="GET" +off=3 method complete +off=4 len=1 span[url]="/" +off=6 url complete +off=11 len=3 span[version]="1.1" +off=14 version complete +off=16 len=10 span[header_field]="Connection" +off=27 header_field complete +off=28 len=5 span[header_value]="close" +off=35 header_value complete +off=35 len=4 span[header_field]="Host" +off=40 header_field complete +off=41 len=1 span[header_value]="a" +off=44 header_value complete +off=45 error code=2 reason="Expected LF after headers" +``` + + +### Headers separated by dummy characters (lenient) + + +```http +GET / HTTP/1.1 +Connection: close +Host: a +\rZGET /evil: HTTP/1.1 +Host: a + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="GET" +off=3 method complete +off=4 len=1 span[url]="/" +off=6 url complete +off=11 len=3 span[version]="1.1" +off=14 version complete +off=16 len=10 span[header_field]="Connection" +off=27 header_field complete +off=28 len=5 span[header_value]="close" +off=35 header_value complete +off=35 len=4 span[header_field]="Host" +off=40 header_field complete +off=41 len=1 span[header_value]="a" +off=44 header_value complete +off=45 headers complete method=1 v=1/1 flags=2 content_length=0 +off=45 message complete +off=46 error code=5 reason="Data after `Connection: close`" +``` + +### Empty headers separated by CR + + +```http +POST / HTTP/1.1 +Connection: Close +Host: localhost:5000 +x:\rTransfer-Encoding: chunked + +1 +A +0 + +``` + +```log +off=0 message begin +off=0 len=4 span[method]="POST" +off=4 method complete +off=5 len=1 span[url]="/" +off=7 url complete +off=12 len=3 span[version]="1.1" +off=15 version complete +off=17 len=10 span[header_field]="Connection" +off=28 header_field complete +off=29 len=5 span[header_value]="Close" +off=36 header_value complete +off=36 len=4 span[header_field]="Host" +off=41 header_field complete +off=42 len=14 span[header_value]="localhost:5000" +off=58 header_value complete +off=58 len=1 span[header_field]="x" +off=60 header_field complete +off=61 error code=2 reason="Expected LF after CR" +``` + +### Empty headers separated by LF + + +```http +POST / HTTP/1.1 +Host: localhost:5000 +x:\nTransfer-Encoding: chunked + +1 +A +0 + +``` + +```log +off=0 message begin +off=0 len=4 span[method]="POST" +off=4 method complete +off=5 len=1 span[url]="/" +off=7 url complete +off=12 len=3 span[version]="1.1" +off=15 version complete +off=17 len=4 span[header_field]="Host" +off=22 header_field complete +off=23 len=14 span[header_value]="localhost:5000" +off=39 header_value complete +off=39 len=1 span[header_field]="x" +off=41 header_field complete +off=42 error code=10 reason="Invalid header value char" +``` + +### Invalid header token #1 + + +```http +GET / HTTP/1.1 +Fo@: Failure + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="GET" +off=3 method complete +off=4 len=1 span[url]="/" +off=6 url complete +off=11 len=3 span[version]="1.1" +off=14 version complete +off=18 error code=10 reason="Invalid header token" +``` + +### Invalid header token #2 + + +```http +GET / HTTP/1.1 +Foo\01\test: Bar + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="GET" +off=3 method complete +off=4 len=1 span[url]="/" +off=6 url complete +off=11 len=3 span[version]="1.1" +off=14 version complete +off=19 error code=10 reason="Invalid header token" +``` + +### Invalid method + + +```http +MKCOLA / HTTP/1.1 + + +``` + +```log +off=0 message begin +off=0 len=5 span[method]="MKCOL" +off=5 method complete +off=5 error code=6 reason="Expected space after method" +``` + +### Illegal header field name line folding + + +```http +GET / HTTP/1.1 +name + : value + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="GET" +off=3 method complete +off=4 len=1 span[url]="/" +off=6 url complete +off=11 len=3 span[version]="1.1" +off=14 version complete +off=20 error code=10 reason="Invalid header token" +``` + +### Corrupted Connection header + + +```http +GET / HTTP/1.1 +Host: www.example.com +Connection\r\033\065\325eep-Alive +Accept-Encoding: gzip + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="GET" +off=3 method complete +off=4 len=1 span[url]="/" +off=6 url complete +off=11 len=3 span[version]="1.1" +off=14 version complete +off=16 len=4 span[header_field]="Host" +off=21 header_field complete +off=22 len=15 span[header_value]="www.example.com" +off=39 header_value complete +off=49 error code=10 reason="Invalid header token" +``` + +### Corrupted header name + + +```http +GET / HTTP/1.1 +Host: www.example.com +X-Some-Header\r\033\065\325eep-Alive +Accept-Encoding: gzip + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="GET" +off=3 method complete +off=4 len=1 span[url]="/" +off=6 url complete +off=11 len=3 span[version]="1.1" +off=14 version complete +off=16 len=4 span[header_field]="Host" +off=21 header_field complete +off=22 len=15 span[header_value]="www.example.com" +off=39 header_value complete +off=52 error code=10 reason="Invalid header token" +``` + +### Missing CR between headers + + + +```http +GET / HTTP/1.1 +Host: localhost +Dummy: x\nContent-Length: 23 + +GET / HTTP/1.1 +Dummy: GET /admin HTTP/1.1 +Host: localhost + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="GET" +off=3 method complete +off=4 len=1 span[url]="/" +off=6 url complete +off=11 len=3 span[version]="1.1" +off=14 version complete +off=16 len=4 span[header_field]="Host" +off=21 header_field complete +off=22 len=9 span[header_value]="localhost" +off=33 header_value complete +off=33 len=5 span[header_field]="Dummy" +off=39 header_field complete +off=40 len=1 span[header_value]="x" +off=41 error code=25 reason="Missing expected CR after header value" +``` + +### Invalid HTTP version + + +```http +GET / HTTP/5.6 +``` + +```log +off=0 message begin +off=0 len=3 span[method]="GET" +off=3 method complete +off=4 len=1 span[url]="/" +off=6 url complete +off=11 len=3 span[version]="5.6" +off=14 error code=9 reason="Invalid HTTP version" +``` + +## Invalid space after start line + + +```http +GET / HTTP/1.1 + Host: foo +``` + +```log +off=0 message begin +off=0 len=3 span[method]="GET" +off=3 method complete +off=4 len=1 span[url]="/" +off=6 url complete +off=11 len=3 span[version]="1.1" +off=14 version complete +off=17 error code=30 reason="Unexpected space after start line" +``` + + +### Only LFs present + + +```http +POST / HTTP/1.1\n\ +Transfer-Encoding: chunked\n\ +Trailer: Baz +Foo: abc\n\ +Bar: def\n\ +\n\ +1\n\ +A\n\ +1;abc\n\ +B\n\ +1;def=ghi\n\ +C\n\ +1;jkl="mno"\n\ +D\n\ +0\n\ +\n\ +Baz: ghi\n\ +\n\ +``` + +```log +off=0 message begin +off=0 len=4 span[method]="POST" +off=4 method complete +off=5 len=1 span[url]="/" +off=7 url complete +off=12 len=3 span[version]="1.1" +off=15 version complete +off=16 error code=9 reason="Expected CRLF after version" +``` + +### Only LFs present (lenient) + + +```http +POST / HTTP/1.1\n\ +Transfer-Encoding: chunked\n\ +Trailer: Baz +Foo: abc\n\ +Bar: def\n\ +\n\ +1\n\ +A\n\ +1;abc\n\ +B\n\ +1;def=ghi\n\ +C\n\ +1;jkl="mno"\n\ +D\n\ +0\n\ +\n\ +Baz: ghi\n\ +\n +``` + +```log +off=0 message begin +off=0 len=4 span[method]="POST" +off=4 method complete +off=5 len=1 span[url]="/" +off=7 url complete +off=12 len=3 span[version]="1.1" +off=15 version complete +off=16 len=17 span[header_field]="Transfer-Encoding" +off=34 header_field complete +off=35 len=7 span[header_value]="chunked" +off=43 header_value complete +off=43 len=7 span[header_field]="Trailer" +off=51 header_field complete +off=52 len=3 span[header_value]="Baz" +off=57 header_value complete +off=57 len=3 span[header_field]="Foo" +off=61 header_field complete +off=62 len=3 span[header_value]="abc" +off=66 header_value complete +off=66 len=3 span[header_field]="Bar" +off=70 header_field complete +off=71 len=3 span[header_value]="def" +off=75 header_value complete +off=76 headers complete method=3 v=1/1 flags=208 content_length=0 +off=78 chunk header len=1 +off=78 len=1 span[body]="A" +off=80 chunk complete +off=82 len=3 span[chunk_extension_name]="abc" +off=85 chunk_extension_name complete +off=86 chunk header len=1 +off=86 len=1 span[body]="B" +off=88 chunk complete +off=90 len=3 span[chunk_extension_name]="def" +off=94 chunk_extension_name complete +off=94 len=3 span[chunk_extension_value]="ghi" +off=97 chunk_extension_value complete +off=98 chunk header len=1 +off=98 len=1 span[body]="C" +off=100 chunk complete +off=102 len=3 span[chunk_extension_name]="jkl" +off=106 chunk_extension_name complete +off=106 len=5 span[chunk_extension_value]=""mno"" +off=111 chunk_extension_value complete +off=112 chunk header len=1 +off=112 len=1 span[body]="D" +off=114 chunk complete +off=117 chunk header len=0 +off=117 len=3 span[header_field]="Baz" +off=121 header_field complete +off=122 len=3 span[header_value]="ghi" +off=126 header_value complete +off=127 chunk complete +off=127 message complete +``` \ No newline at end of file diff --git a/vendor/llhttp/test/request/lenient-headers.md b/vendor/llhttp/test/request/lenient-headers.md new file mode 100644 index 0000000..05e105f --- /dev/null +++ b/vendor/llhttp/test/request/lenient-headers.md @@ -0,0 +1,145 @@ +Lenient header value parsing +============================ + +Parsing with header value token checks off. + +## Header value (lenient) + + +```http +GET /url HTTP/1.1 +Header1: \f + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="GET" +off=3 method complete +off=4 len=4 span[url]="/url" +off=9 url complete +off=14 len=3 span[version]="1.1" +off=17 version complete +off=19 len=7 span[header_field]="Header1" +off=27 header_field complete +off=28 len=1 span[header_value]="\f" +off=31 header_value complete +off=33 headers complete method=1 v=1/1 flags=0 content_length=0 +off=33 message complete +``` + +## Second request header value (lenient) + + +```http +GET /url HTTP/1.1 +Header1: Okay + + +GET /url HTTP/1.1 +Header1: \f + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="GET" +off=3 method complete +off=4 len=4 span[url]="/url" +off=9 url complete +off=14 len=3 span[version]="1.1" +off=17 version complete +off=19 len=7 span[header_field]="Header1" +off=27 header_field complete +off=28 len=4 span[header_value]="Okay" +off=34 header_value complete +off=36 headers complete method=1 v=1/1 flags=0 content_length=0 +off=36 message complete +off=38 reset +off=38 message begin +off=38 len=3 span[method]="GET" +off=41 method complete +off=42 len=4 span[url]="/url" +off=47 url complete +off=52 len=3 span[version]="1.1" +off=55 version complete +off=57 len=7 span[header_field]="Header1" +off=65 header_field complete +off=66 len=1 span[header_value]="\f" +off=69 header_value complete +off=71 headers complete method=1 v=1/1 flags=0 content_length=0 +off=71 message complete +``` + +## Header value + + +```http +GET /url HTTP/1.1 +Header1: \f + + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="GET" +off=3 method complete +off=4 len=4 span[url]="/url" +off=9 url complete +off=14 len=3 span[version]="1.1" +off=17 version complete +off=19 len=7 span[header_field]="Header1" +off=27 header_field complete +off=28 len=0 span[header_value]="" +off=28 error code=10 reason="Invalid header value char" +``` + +### Empty headers separated by CR (lenient) + + +```http +POST / HTTP/1.1 +Connection: Close +Host: localhost:5000 +x:\rTransfer-Encoding: chunked + +1 +A +0 + +``` + +```log +off=0 message begin +off=0 len=4 span[method]="POST" +off=4 method complete +off=5 len=1 span[url]="/" +off=7 url complete +off=12 len=3 span[version]="1.1" +off=15 version complete +off=17 len=10 span[header_field]="Connection" +off=28 header_field complete +off=29 len=5 span[header_value]="Close" +off=36 header_value complete +off=36 len=4 span[header_field]="Host" +off=41 header_field complete +off=42 len=14 span[header_value]="localhost:5000" +off=58 header_value complete +off=58 len=1 span[header_field]="x" +off=60 header_field complete +off=61 len=0 span[header_value]="" +off=61 header_value complete +off=61 len=17 span[header_field]="Transfer-Encoding" +off=79 header_field complete +off=80 len=7 span[header_value]="chunked" +off=89 header_value complete +off=91 headers complete method=3 v=1/1 flags=20a content_length=0 +off=94 chunk header len=1 +off=94 len=1 span[body]="A" +off=97 chunk complete +off=100 chunk header len=0 +``` \ No newline at end of file diff --git a/vendor/llhttp/test/request/lenient-version.md b/vendor/llhttp/test/request/lenient-version.md new file mode 100644 index 0000000..4185556 --- /dev/null +++ b/vendor/llhttp/test/request/lenient-version.md @@ -0,0 +1,23 @@ +Lenient HTTP version parsing +============================ + +### Invalid HTTP version (lenient) + + +```http +GET / HTTP/5.6 + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="GET" +off=3 method complete +off=4 len=1 span[url]="/" +off=6 url complete +off=11 len=3 span[version]="5.6" +off=14 version complete +off=18 headers complete method=1 v=5/6 flags=0 content_length=0 +off=18 message complete +``` \ No newline at end of file diff --git a/vendor/llhttp/test/request/method.md b/vendor/llhttp/test/request/method.md new file mode 100644 index 0000000..dce262e --- /dev/null +++ b/vendor/llhttp/test/request/method.md @@ -0,0 +1,450 @@ +Methods +======= + +### REPORT request + + +```http +REPORT /test HTTP/1.1 + + +``` + +```log +off=0 message begin +off=0 len=6 span[method]="REPORT" +off=6 method complete +off=7 len=5 span[url]="/test" +off=13 url complete +off=18 len=3 span[version]="1.1" +off=21 version complete +off=25 headers complete method=20 v=1/1 flags=0 content_length=0 +off=25 message complete +``` + +### CONNECT request + + +```http +CONNECT 0-home0.netscape.com:443 HTTP/1.0 +User-agent: Mozilla/1.1N +Proxy-authorization: basic aGVsbG86d29ybGQ= + +some data +and yet even more data +``` + +```log +off=0 message begin +off=0 len=7 span[method]="CONNECT" +off=7 method complete +off=8 len=24 span[url]="0-home0.netscape.com:443" +off=33 url complete +off=38 len=3 span[version]="1.0" +off=41 version complete +off=43 len=10 span[header_field]="User-agent" +off=54 header_field complete +off=55 len=12 span[header_value]="Mozilla/1.1N" +off=69 header_value complete +off=69 len=19 span[header_field]="Proxy-authorization" +off=89 header_field complete +off=90 len=22 span[header_value]="basic aGVsbG86d29ybGQ=" +off=114 header_value complete +off=116 headers complete method=5 v=1/0 flags=0 content_length=0 +off=116 message complete +off=116 error code=22 reason="Pause on CONNECT/Upgrade" +``` + +### CONNECT request with CAPS + + +```http +CONNECT HOME0.NETSCAPE.COM:443 HTTP/1.0 +User-agent: Mozilla/1.1N +Proxy-authorization: basic aGVsbG86d29ybGQ= + + +``` + +```log +off=0 message begin +off=0 len=7 span[method]="CONNECT" +off=7 method complete +off=8 len=22 span[url]="HOME0.NETSCAPE.COM:443" +off=31 url complete +off=36 len=3 span[version]="1.0" +off=39 version complete +off=41 len=10 span[header_field]="User-agent" +off=52 header_field complete +off=53 len=12 span[header_value]="Mozilla/1.1N" +off=67 header_value complete +off=67 len=19 span[header_field]="Proxy-authorization" +off=87 header_field complete +off=88 len=22 span[header_value]="basic aGVsbG86d29ybGQ=" +off=112 header_value complete +off=114 headers complete method=5 v=1/0 flags=0 content_length=0 +off=114 message complete +off=114 error code=22 reason="Pause on CONNECT/Upgrade" +``` + +### CONNECT with body + + +```http +CONNECT foo.bar.com:443 HTTP/1.0 +User-agent: Mozilla/1.1N +Proxy-authorization: basic aGVsbG86d29ybGQ= +Content-Length: 10 + +blarfcicle" +``` + +```log +off=0 message begin +off=0 len=7 span[method]="CONNECT" +off=7 method complete +off=8 len=15 span[url]="foo.bar.com:443" +off=24 url complete +off=29 len=3 span[version]="1.0" +off=32 version complete +off=34 len=10 span[header_field]="User-agent" +off=45 header_field complete +off=46 len=12 span[header_value]="Mozilla/1.1N" +off=60 header_value complete +off=60 len=19 span[header_field]="Proxy-authorization" +off=80 header_field complete +off=81 len=22 span[header_value]="basic aGVsbG86d29ybGQ=" +off=105 header_value complete +off=105 len=14 span[header_field]="Content-Length" +off=120 header_field complete +off=121 len=2 span[header_value]="10" +off=125 header_value complete +off=127 headers complete method=5 v=1/0 flags=20 content_length=10 +off=127 message complete +off=127 error code=22 reason="Pause on CONNECT/Upgrade" +``` + +### M-SEARCH request + + +```http +M-SEARCH * HTTP/1.1 +HOST: 239.255.255.250:1900 +MAN: "ssdp:discover" +ST: "ssdp:all" + + +``` + +```log +off=0 message begin +off=0 len=8 span[method]="M-SEARCH" +off=8 method complete +off=9 len=1 span[url]="*" +off=11 url complete +off=16 len=3 span[version]="1.1" +off=19 version complete +off=21 len=4 span[header_field]="HOST" +off=26 header_field complete +off=27 len=20 span[header_value]="239.255.255.250:1900" +off=49 header_value complete +off=49 len=3 span[header_field]="MAN" +off=53 header_field complete +off=54 len=15 span[header_value]=""ssdp:discover"" +off=71 header_value complete +off=71 len=2 span[header_field]="ST" +off=74 header_field complete +off=75 len=10 span[header_value]=""ssdp:all"" +off=87 header_value complete +off=89 headers complete method=24 v=1/1 flags=0 content_length=0 +off=89 message complete +``` + +### PATCH request + + +```http +PATCH /file.txt HTTP/1.1 +Host: www.example.com +Content-Type: application/example +If-Match: "e0023aa4e" +Content-Length: 10 + +cccccccccc +``` + +```log +off=0 message begin +off=0 len=5 span[method]="PATCH" +off=5 method complete +off=6 len=9 span[url]="/file.txt" +off=16 url complete +off=21 len=3 span[version]="1.1" +off=24 version complete +off=26 len=4 span[header_field]="Host" +off=31 header_field complete +off=32 len=15 span[header_value]="www.example.com" +off=49 header_value complete +off=49 len=12 span[header_field]="Content-Type" +off=62 header_field complete +off=63 len=19 span[header_value]="application/example" +off=84 header_value complete +off=84 len=8 span[header_field]="If-Match" +off=93 header_field complete +off=94 len=11 span[header_value]=""e0023aa4e"" +off=107 header_value complete +off=107 len=14 span[header_field]="Content-Length" +off=122 header_field complete +off=123 len=2 span[header_value]="10" +off=127 header_value complete +off=129 headers complete method=28 v=1/1 flags=20 content_length=10 +off=129 len=10 span[body]="cccccccccc" +off=139 message complete +``` + +### PURGE request + + +```http +PURGE /file.txt HTTP/1.1 +Host: www.example.com + + +``` + +```log +off=0 message begin +off=0 len=5 span[method]="PURGE" +off=5 method complete +off=6 len=9 span[url]="/file.txt" +off=16 url complete +off=21 len=3 span[version]="1.1" +off=24 version complete +off=26 len=4 span[header_field]="Host" +off=31 header_field complete +off=32 len=15 span[header_value]="www.example.com" +off=49 header_value complete +off=51 headers complete method=29 v=1/1 flags=0 content_length=0 +off=51 message complete +``` + +### SEARCH request + + +```http +SEARCH / HTTP/1.1 +Host: www.example.com + + +``` + +```log +off=0 message begin +off=0 len=6 span[method]="SEARCH" +off=6 method complete +off=7 len=1 span[url]="/" +off=9 url complete +off=14 len=3 span[version]="1.1" +off=17 version complete +off=19 len=4 span[header_field]="Host" +off=24 header_field complete +off=25 len=15 span[header_value]="www.example.com" +off=42 header_value complete +off=44 headers complete method=14 v=1/1 flags=0 content_length=0 +off=44 message complete +``` + +### LINK request + + +```http +LINK /images/my_dog.jpg HTTP/1.1 +Host: example.com +Link: ; rel="tag" +Link: ; rel="tag" + + +``` + +```log +off=0 message begin +off=0 len=4 span[method]="LINK" +off=4 method complete +off=5 len=18 span[url]="/images/my_dog.jpg" +off=24 url complete +off=29 len=3 span[version]="1.1" +off=32 version complete +off=34 len=4 span[header_field]="Host" +off=39 header_field complete +off=40 len=11 span[header_value]="example.com" +off=53 header_value complete +off=53 len=4 span[header_field]="Link" +off=58 header_field complete +off=59 len=44 span[header_value]="; rel="tag"" +off=105 header_value complete +off=105 len=4 span[header_field]="Link" +off=110 header_field complete +off=111 len=46 span[header_value]="; rel="tag"" +off=159 header_value complete +off=161 headers complete method=31 v=1/1 flags=0 content_length=0 +off=161 message complete +``` + +### LINK request + + +```http +UNLINK /images/my_dog.jpg HTTP/1.1 +Host: example.com +Link: ; rel="tag" + + +``` + +```log +off=0 message begin +off=0 len=6 span[method]="UNLINK" +off=6 method complete +off=7 len=18 span[url]="/images/my_dog.jpg" +off=26 url complete +off=31 len=3 span[version]="1.1" +off=34 version complete +off=36 len=4 span[header_field]="Host" +off=41 header_field complete +off=42 len=11 span[header_value]="example.com" +off=55 header_value complete +off=55 len=4 span[header_field]="Link" +off=60 header_field complete +off=61 len=46 span[header_value]="; rel="tag"" +off=109 header_value complete +off=111 headers complete method=32 v=1/1 flags=0 content_length=0 +off=111 message complete +``` + +### SOURCE request + + +```http +SOURCE /music/sweet/music HTTP/1.1 +Host: example.com + + +``` + +```log +off=0 message begin +off=0 len=6 span[method]="SOURCE" +off=6 method complete +off=7 len=18 span[url]="/music/sweet/music" +off=26 url complete +off=31 len=3 span[version]="1.1" +off=34 version complete +off=36 len=4 span[header_field]="Host" +off=41 header_field complete +off=42 len=11 span[header_value]="example.com" +off=55 header_value complete +off=57 headers complete method=33 v=1/1 flags=0 content_length=0 +off=57 message complete +``` + +### SOURCE request with ICE + + +```http +SOURCE /music/sweet/music ICE/1.0 +Host: example.com + + +``` + +```log +off=0 message begin +off=0 len=6 span[method]="SOURCE" +off=6 method complete +off=7 len=18 span[url]="/music/sweet/music" +off=26 url complete +off=30 len=3 span[version]="1.0" +off=33 version complete +off=35 len=4 span[header_field]="Host" +off=40 header_field complete +off=41 len=11 span[header_value]="example.com" +off=54 header_value complete +off=56 headers complete method=33 v=1/0 flags=0 content_length=0 +off=56 message complete +``` + +### OPTIONS request with RTSP + +NOTE: `OPTIONS` is a valid HTTP metho too. + + +```http +OPTIONS /music/sweet/music RTSP/1.0 +Host: example.com + + +``` + +```log +off=0 message begin +off=0 len=7 span[method]="OPTIONS" +off=7 method complete +off=8 len=18 span[url]="/music/sweet/music" +off=27 url complete +off=32 len=3 span[version]="1.0" +off=35 version complete +off=37 len=4 span[header_field]="Host" +off=42 header_field complete +off=43 len=11 span[header_value]="example.com" +off=56 header_value complete +off=58 headers complete method=6 v=1/0 flags=0 content_length=0 +off=58 message complete +``` + +### ANNOUNCE request with RTSP + + +```http +ANNOUNCE /music/sweet/music RTSP/1.0 +Host: example.com + + +``` + +```log +off=0 message begin +off=0 len=8 span[method]="ANNOUNCE" +off=8 method complete +off=9 len=18 span[url]="/music/sweet/music" +off=28 url complete +off=33 len=3 span[version]="1.0" +off=36 version complete +off=38 len=4 span[header_field]="Host" +off=43 header_field complete +off=44 len=11 span[header_value]="example.com" +off=57 header_value complete +off=59 headers complete method=36 v=1/0 flags=0 content_length=0 +off=59 message complete +``` + +### PRI request HTTP2 + + +```http +PRI * HTTP/1.1 + +SM + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="PRI" +off=3 method complete +off=4 len=1 span[url]="*" +off=6 url complete +off=11 len=3 span[version]="1.1" +off=14 version complete +off=24 error code=23 reason="Pause on PRI/Upgrade" +``` diff --git a/vendor/llhttp/test/request/pausing.md b/vendor/llhttp/test/request/pausing.md new file mode 100644 index 0000000..8e501e3 --- /dev/null +++ b/vendor/llhttp/test/request/pausing.md @@ -0,0 +1,381 @@ +Pausing +======= + +### on_message_begin + + +```http +POST / HTTP/1.1 +Content-Length: 3 + +abc +``` + +```log +off=0 message begin +off=0 pause +off=0 len=4 span[method]="POST" +off=4 method complete +off=5 len=1 span[url]="/" +off=7 url complete +off=12 len=3 span[version]="1.1" +off=15 version complete +off=17 len=14 span[header_field]="Content-Length" +off=32 header_field complete +off=33 len=1 span[header_value]="3" +off=36 header_value complete +off=38 headers complete method=3 v=1/1 flags=20 content_length=3 +off=38 len=3 span[body]="abc" +off=41 message complete +``` + +### on_message_complete + + +```http +POST / HTTP/1.1 +Content-Length: 3 + +abc +``` + +```log +off=0 message begin +off=0 len=4 span[method]="POST" +off=4 method complete +off=5 len=1 span[url]="/" +off=7 url complete +off=12 len=3 span[version]="1.1" +off=15 version complete +off=17 len=14 span[header_field]="Content-Length" +off=32 header_field complete +off=33 len=1 span[header_value]="3" +off=36 header_value complete +off=38 headers complete method=3 v=1/1 flags=20 content_length=3 +off=38 len=3 span[body]="abc" +off=41 message complete +off=41 pause +``` + +### on_method_complete + + +```http +POST / HTTP/1.1 +Content-Length: 3 + +abc +``` + +```log +off=0 message begin +off=0 len=4 span[method]="POST" +off=4 method complete +off=4 pause +off=5 len=1 span[url]="/" +off=7 url complete +off=12 len=3 span[version]="1.1" +off=15 version complete +off=17 len=14 span[header_field]="Content-Length" +off=32 header_field complete +off=33 len=1 span[header_value]="3" +off=36 header_value complete +off=38 headers complete method=3 v=1/1 flags=20 content_length=3 +off=38 len=3 span[body]="abc" +off=41 message complete +``` + +### on_url_complete + + +```http +POST / HTTP/1.1 +Content-Length: 3 + +abc +``` + +```log +off=0 message begin +off=0 len=4 span[method]="POST" +off=4 method complete +off=5 len=1 span[url]="/" +off=7 url complete +off=7 pause +off=12 len=3 span[version]="1.1" +off=15 version complete +off=17 len=14 span[header_field]="Content-Length" +off=32 header_field complete +off=33 len=1 span[header_value]="3" +off=36 header_value complete +off=38 headers complete method=3 v=1/1 flags=20 content_length=3 +off=38 len=3 span[body]="abc" +off=41 message complete +``` + +### on_version_complete + + +```http +POST / HTTP/1.1 +Content-Length: 3 + +abc +``` + +```log +off=0 message begin +off=0 len=4 span[method]="POST" +off=4 method complete +off=5 len=1 span[url]="/" +off=7 url complete +off=12 len=3 span[version]="1.1" +off=15 version complete +off=15 pause +off=17 len=14 span[header_field]="Content-Length" +off=32 header_field complete +off=33 len=1 span[header_value]="3" +off=36 header_value complete +off=38 headers complete method=3 v=1/1 flags=20 content_length=3 +off=38 len=3 span[body]="abc" +off=41 message complete +``` + +### on_header_field_complete + + +```http +POST / HTTP/1.1 +Content-Length: 3 + +abc +``` + +```log +off=0 message begin +off=0 len=4 span[method]="POST" +off=4 method complete +off=5 len=1 span[url]="/" +off=7 url complete +off=12 len=3 span[version]="1.1" +off=15 version complete +off=17 len=14 span[header_field]="Content-Length" +off=32 header_field complete +off=32 pause +off=33 len=1 span[header_value]="3" +off=36 header_value complete +off=38 headers complete method=3 v=1/1 flags=20 content_length=3 +off=38 len=3 span[body]="abc" +off=41 message complete +``` + +### on_header_value_complete + + +```http +POST / HTTP/1.1 +Content-Length: 3 + +abc +``` + +```log +off=0 message begin +off=0 len=4 span[method]="POST" +off=4 method complete +off=5 len=1 span[url]="/" +off=7 url complete +off=12 len=3 span[version]="1.1" +off=15 version complete +off=17 len=14 span[header_field]="Content-Length" +off=32 header_field complete +off=33 len=1 span[header_value]="3" +off=36 header_value complete +off=36 pause +off=38 headers complete method=3 v=1/1 flags=20 content_length=3 +off=38 len=3 span[body]="abc" +off=41 message complete +``` + +### on_headers_complete + + +```http +POST / HTTP/1.1 +Content-Length: 3 + +abc +``` + +```log +off=0 message begin +off=0 len=4 span[method]="POST" +off=4 method complete +off=5 len=1 span[url]="/" +off=7 url complete +off=12 len=3 span[version]="1.1" +off=15 version complete +off=17 len=14 span[header_field]="Content-Length" +off=32 header_field complete +off=33 len=1 span[header_value]="3" +off=36 header_value complete +off=38 headers complete method=3 v=1/1 flags=20 content_length=3 +off=38 pause +off=38 len=3 span[body]="abc" +off=41 message complete +``` + +### on_chunk_header + + +```http +PUT / HTTP/1.1 +Transfer-Encoding: chunked + +a +0123456789 +0 + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="PUT" +off=3 method complete +off=4 len=1 span[url]="/" +off=6 url complete +off=11 len=3 span[version]="1.1" +off=14 version complete +off=16 len=17 span[header_field]="Transfer-Encoding" +off=34 header_field complete +off=35 len=7 span[header_value]="chunked" +off=44 header_value complete +off=46 headers complete method=4 v=1/1 flags=208 content_length=0 +off=49 chunk header len=10 +off=49 pause +off=49 len=10 span[body]="0123456789" +off=61 chunk complete +off=64 chunk header len=0 +off=64 pause +off=66 chunk complete +off=66 message complete +``` + +### on_chunk_extension_name + + +```http +PUT / HTTP/1.1 +Transfer-Encoding: chunked + +a;foo=bar +0123456789 +0 + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="PUT" +off=3 method complete +off=4 len=1 span[url]="/" +off=6 url complete +off=11 len=3 span[version]="1.1" +off=14 version complete +off=16 len=17 span[header_field]="Transfer-Encoding" +off=34 header_field complete +off=35 len=7 span[header_value]="chunked" +off=44 header_value complete +off=46 headers complete method=4 v=1/1 flags=208 content_length=0 +off=48 len=3 span[chunk_extension_name]="foo" +off=52 chunk_extension_name complete +off=52 pause +off=52 len=3 span[chunk_extension_value]="bar" +off=56 chunk_extension_value complete +off=57 chunk header len=10 +off=57 len=10 span[body]="0123456789" +off=69 chunk complete +off=72 chunk header len=0 +off=74 chunk complete +off=74 message complete +``` + +### on_chunk_extension_value + + +```http +PUT / HTTP/1.1 +Transfer-Encoding: chunked + +a;foo=bar +0123456789 +0 + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="PUT" +off=3 method complete +off=4 len=1 span[url]="/" +off=6 url complete +off=11 len=3 span[version]="1.1" +off=14 version complete +off=16 len=17 span[header_field]="Transfer-Encoding" +off=34 header_field complete +off=35 len=7 span[header_value]="chunked" +off=44 header_value complete +off=46 headers complete method=4 v=1/1 flags=208 content_length=0 +off=48 len=3 span[chunk_extension_name]="foo" +off=52 chunk_extension_name complete +off=52 len=3 span[chunk_extension_value]="bar" +off=56 chunk_extension_value complete +off=56 pause +off=57 chunk header len=10 +off=57 len=10 span[body]="0123456789" +off=69 chunk complete +off=72 chunk header len=0 +off=74 chunk complete +off=74 message complete +``` + + +### on_chunk_complete + + +```http +PUT / HTTP/1.1 +Transfer-Encoding: chunked + +a +0123456789 +0 + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="PUT" +off=3 method complete +off=4 len=1 span[url]="/" +off=6 url complete +off=11 len=3 span[version]="1.1" +off=14 version complete +off=16 len=17 span[header_field]="Transfer-Encoding" +off=34 header_field complete +off=35 len=7 span[header_value]="chunked" +off=44 header_value complete +off=46 headers complete method=4 v=1/1 flags=208 content_length=0 +off=49 chunk header len=10 +off=49 len=10 span[body]="0123456789" +off=61 chunk complete +off=61 pause +off=64 chunk header len=0 +off=66 chunk complete +off=66 pause +off=66 message complete +``` diff --git a/vendor/llhttp/test/request/pipelining.md b/vendor/llhttp/test/request/pipelining.md new file mode 100644 index 0000000..bdfe6ab --- /dev/null +++ b/vendor/llhttp/test/request/pipelining.md @@ -0,0 +1,66 @@ +Pipelining +========== + +## Should parse multiple events + + +```http +POST /aaa HTTP/1.1 +Content-Length: 3 + +AAA +PUT /bbb HTTP/1.1 +Content-Length: 4 + +BBBB +PATCH /ccc HTTP/1.1 +Content-Length: 5 + +CCCC +``` + +```log +off=0 message begin +off=0 len=4 span[method]="POST" +off=4 method complete +off=5 len=4 span[url]="/aaa" +off=10 url complete +off=15 len=3 span[version]="1.1" +off=18 version complete +off=20 len=14 span[header_field]="Content-Length" +off=35 header_field complete +off=36 len=1 span[header_value]="3" +off=39 header_value complete +off=41 headers complete method=3 v=1/1 flags=20 content_length=3 +off=41 len=3 span[body]="AAA" +off=44 message complete +off=46 reset +off=46 message begin +off=46 len=3 span[method]="PUT" +off=49 method complete +off=50 len=4 span[url]="/bbb" +off=55 url complete +off=60 len=3 span[version]="1.1" +off=63 version complete +off=65 len=14 span[header_field]="Content-Length" +off=80 header_field complete +off=81 len=1 span[header_value]="4" +off=84 header_value complete +off=86 headers complete method=4 v=1/1 flags=20 content_length=4 +off=86 len=4 span[body]="BBBB" +off=90 message complete +off=92 reset +off=92 message begin +off=92 len=5 span[method]="PATCH" +off=97 method complete +off=98 len=4 span[url]="/ccc" +off=103 url complete +off=108 len=3 span[version]="1.1" +off=111 version complete +off=113 len=14 span[header_field]="Content-Length" +off=128 header_field complete +off=129 len=1 span[header_value]="5" +off=132 header_value complete +off=134 headers complete method=28 v=1/1 flags=20 content_length=5 +off=134 len=4 span[body]="CCCC" +``` \ No newline at end of file diff --git a/vendor/llhttp/test/request/sample.md b/vendor/llhttp/test/request/sample.md new file mode 100644 index 0000000..f0a5d44 --- /dev/null +++ b/vendor/llhttp/test/request/sample.md @@ -0,0 +1,629 @@ +Sample requests +=============== + +Lots of sample requests, most ported from [http_parser][0] test suite. + +## Simple request + + +```http +OPTIONS /url HTTP/1.1 +Header1: Value1 +Header2:\t Value2 + + +``` + +```log +off=0 message begin +off=0 len=7 span[method]="OPTIONS" +off=7 method complete +off=8 len=4 span[url]="/url" +off=13 url complete +off=18 len=3 span[version]="1.1" +off=21 version complete +off=23 len=7 span[header_field]="Header1" +off=31 header_field complete +off=32 len=6 span[header_value]="Value1" +off=40 header_value complete +off=40 len=7 span[header_field]="Header2" +off=48 header_field complete +off=50 len=6 span[header_value]="Value2" +off=58 header_value complete +off=60 headers complete method=6 v=1/1 flags=0 content_length=0 +off=60 message complete +``` + +## Request with method starting with `H` + +There's a optimization in `start_req_or_res` that passes execution to +`start_req` when the first character is not `H` (because response must start +with `HTTP/`). However, there're still methods like `HEAD` that should get +to `start_req`. Verify that it still works after optimization. + + +```http +HEAD /url HTTP/1.1 + + +``` + +```log +off=0 message begin +off=0 len=4 span[method]="HEAD" +off=4 method complete +off=5 len=4 span[url]="/url" +off=10 url complete +off=15 len=3 span[version]="1.1" +off=18 version complete +off=22 headers complete method=2 v=1/1 flags=0 content_length=0 +off=22 message complete +``` + +## curl GET + + +```http +GET /test HTTP/1.1 +User-Agent: curl/7.18.0 (i486-pc-linux-gnu) libcurl/7.18.0 OpenSSL/0.9.8g zlib/1.2.3.3 libidn/1.1 +Host: 0.0.0.0=5000 +Accept: */* + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="GET" +off=3 method complete +off=4 len=5 span[url]="/test" +off=10 url complete +off=15 len=3 span[version]="1.1" +off=18 version complete +off=20 len=10 span[header_field]="User-Agent" +off=31 header_field complete +off=32 len=85 span[header_value]="curl/7.18.0 (i486-pc-linux-gnu) libcurl/7.18.0 OpenSSL/0.9.8g zlib/1.2.3.3 libidn/1.1" +off=119 header_value complete +off=119 len=4 span[header_field]="Host" +off=124 header_field complete +off=125 len=12 span[header_value]="0.0.0.0=5000" +off=139 header_value complete +off=139 len=6 span[header_field]="Accept" +off=146 header_field complete +off=147 len=3 span[header_value]="*/*" +off=152 header_value complete +off=154 headers complete method=1 v=1/1 flags=0 content_length=0 +off=154 message complete +``` + +## Firefox GET + + +```http +GET /favicon.ico HTTP/1.1 +Host: 0.0.0.0=5000 +User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9) Gecko/2008061015 Firefox/3.0 +Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 +Accept-Language: en-us,en;q=0.5 +Accept-Encoding: gzip,deflate +Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 +Keep-Alive: 300 +Connection: keep-alive + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="GET" +off=3 method complete +off=4 len=12 span[url]="/favicon.ico" +off=17 url complete +off=22 len=3 span[version]="1.1" +off=25 version complete +off=27 len=4 span[header_field]="Host" +off=32 header_field complete +off=33 len=12 span[header_value]="0.0.0.0=5000" +off=47 header_value complete +off=47 len=10 span[header_field]="User-Agent" +off=58 header_field complete +off=59 len=76 span[header_value]="Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9) Gecko/2008061015 Firefox/3.0" +off=137 header_value complete +off=137 len=6 span[header_field]="Accept" +off=144 header_field complete +off=145 len=63 span[header_value]="text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" +off=210 header_value complete +off=210 len=15 span[header_field]="Accept-Language" +off=226 header_field complete +off=227 len=14 span[header_value]="en-us,en;q=0.5" +off=243 header_value complete +off=243 len=15 span[header_field]="Accept-Encoding" +off=259 header_field complete +off=260 len=12 span[header_value]="gzip,deflate" +off=274 header_value complete +off=274 len=14 span[header_field]="Accept-Charset" +off=289 header_field complete +off=290 len=30 span[header_value]="ISO-8859-1,utf-8;q=0.7,*;q=0.7" +off=322 header_value complete +off=322 len=10 span[header_field]="Keep-Alive" +off=333 header_field complete +off=334 len=3 span[header_value]="300" +off=339 header_value complete +off=339 len=10 span[header_field]="Connection" +off=350 header_field complete +off=351 len=10 span[header_value]="keep-alive" +off=363 header_value complete +off=365 headers complete method=1 v=1/1 flags=1 content_length=0 +off=365 message complete +``` + +## DUMBPACK + + +```http +GET /dumbpack HTTP/1.1 +aaaaaaaaaaaaa:++++++++++ + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="GET" +off=3 method complete +off=4 len=9 span[url]="/dumbpack" +off=14 url complete +off=19 len=3 span[version]="1.1" +off=22 version complete +off=24 len=13 span[header_field]="aaaaaaaaaaaaa" +off=38 header_field complete +off=38 len=10 span[header_value]="++++++++++" +off=50 header_value complete +off=52 headers complete method=1 v=1/1 flags=0 content_length=0 +off=52 message complete +``` + +## No headers and no body + + +```http +GET /get_no_headers_no_body/world HTTP/1.1 + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="GET" +off=3 method complete +off=4 len=29 span[url]="/get_no_headers_no_body/world" +off=34 url complete +off=39 len=3 span[version]="1.1" +off=42 version complete +off=46 headers complete method=1 v=1/1 flags=0 content_length=0 +off=46 message complete +``` + +## One header and no body + + +```http +GET /get_one_header_no_body HTTP/1.1 +Accept: */* + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="GET" +off=3 method complete +off=4 len=23 span[url]="/get_one_header_no_body" +off=28 url complete +off=33 len=3 span[version]="1.1" +off=36 version complete +off=38 len=6 span[header_field]="Accept" +off=45 header_field complete +off=46 len=3 span[header_value]="*/*" +off=51 header_value complete +off=53 headers complete method=1 v=1/1 flags=0 content_length=0 +off=53 message complete +``` + +## Apache bench GET + +The server receiving this request SHOULD NOT wait for EOF to know that +`Content-Length == 0`. + + +```http +GET /test HTTP/1.0 +Host: 0.0.0.0:5000 +User-Agent: ApacheBench/2.3 +Accept: */* + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="GET" +off=3 method complete +off=4 len=5 span[url]="/test" +off=10 url complete +off=15 len=3 span[version]="1.0" +off=18 version complete +off=20 len=4 span[header_field]="Host" +off=25 header_field complete +off=26 len=12 span[header_value]="0.0.0.0:5000" +off=40 header_value complete +off=40 len=10 span[header_field]="User-Agent" +off=51 header_field complete +off=52 len=15 span[header_value]="ApacheBench/2.3" +off=69 header_value complete +off=69 len=6 span[header_field]="Accept" +off=76 header_field complete +off=77 len=3 span[header_value]="*/*" +off=82 header_value complete +off=84 headers complete method=1 v=1/0 flags=0 content_length=0 +off=84 message complete +``` + +## Prefix newline + +Some clients, especially after a POST in a keep-alive connection, +will send an extra CRLF before the next request. + + +```http +\r\nGET /test HTTP/1.1 + + +``` + +```log +off=2 message begin +off=2 len=3 span[method]="GET" +off=5 method complete +off=6 len=5 span[url]="/test" +off=12 url complete +off=17 len=3 span[version]="1.1" +off=20 version complete +off=24 headers complete method=1 v=1/1 flags=0 content_length=0 +off=24 message complete +``` + +## No HTTP version + + +```http +GET / + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="GET" +off=3 method complete +off=4 len=1 span[url]="/" +off=7 url complete +off=9 headers complete method=1 v=0/9 flags=0 content_length=0 +off=9 message complete +``` + +## Line folding in header value with CRLF + + +```http +GET / HTTP/1.1 +Line1: abc +\tdef + ghi +\t\tjkl + mno +\t \tqrs +Line2: \t line2\t +Line3: + line3 +Line4: + +Connection: + close + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="GET" +off=3 method complete +off=4 len=1 span[url]="/" +off=6 url complete +off=11 len=3 span[version]="1.1" +off=14 version complete +off=16 len=5 span[header_field]="Line1" +off=22 header_field complete +off=25 len=3 span[header_value]="abc" +off=30 len=4 span[header_value]="\tdef" +off=36 len=4 span[header_value]=" ghi" +off=42 len=5 span[header_value]="\t\tjkl" +off=49 len=6 span[header_value]=" mno " +off=57 len=6 span[header_value]="\t \tqrs" +off=65 header_value complete +off=65 len=5 span[header_field]="Line2" +off=71 header_field complete +off=74 len=6 span[header_value]="line2\t" +off=82 header_value complete +off=82 len=5 span[header_field]="Line3" +off=88 header_field complete +off=91 len=5 span[header_value]="line3" +off=98 header_value complete +off=98 len=5 span[header_field]="Line4" +off=104 header_field complete +off=110 len=0 span[header_value]="" +off=110 header_value complete +off=110 len=10 span[header_field]="Connection" +off=121 header_field complete +off=124 len=5 span[header_value]="close" +off=131 header_value complete +off=133 headers complete method=1 v=1/1 flags=2 content_length=0 +off=133 message complete +``` + +## Line folding in header value with LF + + + +```http +GET / HTTP/1.1 +Line1: abc\n\ +\tdef\n\ + ghi\n\ +\t\tjkl\n\ + mno \n\ +\t \tqrs\n\ +Line2: \t line2\t\n\ +Line3:\n\ + line3\n\ +Line4: \n\ + \n\ +Connection:\n\ + close\n\ +\n +``` + +```log +off=0 message begin +off=0 len=3 span[method]="GET" +off=3 method complete +off=4 len=1 span[url]="/" +off=6 url complete +off=11 len=3 span[version]="1.1" +off=14 version complete +off=16 len=5 span[header_field]="Line1" +off=22 header_field complete +off=25 len=3 span[header_value]="abc" +off=28 error code=25 reason="Missing expected CR after header value" +``` + +## No LF after CR + + + +```http +GET / HTTP/1.1\rLine: 1 + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="GET" +off=3 method complete +off=4 len=1 span[url]="/" +off=6 url complete +off=11 len=3 span[version]="1.1" +off=14 version complete +off=15 error code=2 reason="Expected CRLF after version" +``` + +## No LF after CR (lenient) + + + +```http +GET / HTTP/1.1\rLine: 1 + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="GET" +off=3 method complete +off=4 len=1 span[url]="/" +off=6 url complete +off=11 len=3 span[version]="1.1" +off=14 version complete +off=15 len=4 span[header_field]="Line" +off=20 header_field complete +off=21 len=1 span[header_value]="1" +``` + +## Request starting with CRLF + + +```http +\r\nGET /url HTTP/1.1 +Header1: Value1 + + +``` + +```log +off=2 message begin +off=2 len=3 span[method]="GET" +off=5 method complete +off=6 len=4 span[url]="/url" +off=11 url complete +off=16 len=3 span[version]="1.1" +off=19 version complete +off=21 len=7 span[header_field]="Header1" +off=29 header_field complete +off=30 len=6 span[header_value]="Value1" +off=38 header_value complete +off=40 headers complete method=1 v=1/1 flags=0 content_length=0 +off=40 message complete +``` + +## Extended Characters + +See nodejs/test/parallel/test-http-headers-obstext.js + + +```http +GET / HTTP/1.1 +Test: Düsseldorf + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="GET" +off=3 method complete +off=4 len=1 span[url]="/" +off=6 url complete +off=11 len=3 span[version]="1.1" +off=14 version complete +off=16 len=4 span[header_field]="Test" +off=21 header_field complete +off=22 len=11 span[header_value]="Düsseldorf" +off=35 header_value complete +off=37 headers complete method=1 v=1/1 flags=0 content_length=0 +off=37 message complete +``` + +## 255 ASCII in header value + +Note: `Buffer.from([ 0xff ]).toString('latin1') === 'ÿ'`. + + +```http +OPTIONS /url HTTP/1.1 +Header1: Value1 +Header2: \xffValue2 + + +``` + +```log +off=0 message begin +off=0 len=7 span[method]="OPTIONS" +off=7 method complete +off=8 len=4 span[url]="/url" +off=13 url complete +off=18 len=3 span[version]="1.1" +off=21 version complete +off=23 len=7 span[header_field]="Header1" +off=31 header_field complete +off=32 len=6 span[header_value]="Value1" +off=40 header_value complete +off=40 len=7 span[header_field]="Header2" +off=48 header_field complete +off=49 len=8 span[header_value]="ÿValue2" +off=59 header_value complete +off=61 headers complete method=6 v=1/1 flags=0 content_length=0 +off=61 message complete +``` + +## X-SSL-Nonsense + +See nodejs/test/parallel/test-http-headers-obstext.js + + +```http +GET / HTTP/1.1 +X-SSL-Nonsense: -----BEGIN CERTIFICATE----- +\tMIIFbTCCBFWgAwIBAgICH4cwDQYJKoZIhvcNAQEFBQAwcDELMAkGA1UEBhMCVUsx +\tETAPBgNVBAoTCGVTY2llbmNlMRIwEAYDVQQLEwlBdXRob3JpdHkxCzAJBgNVBAMT +\tAkNBMS0wKwYJKoZIhvcNAQkBFh5jYS1vcGVyYXRvckBncmlkLXN1cHBvcnQuYWMu +\tdWswHhcNMDYwNzI3MTQxMzI4WhcNMDcwNzI3MTQxMzI4WjBbMQswCQYDVQQGEwJV +\tSzERMA8GA1UEChMIZVNjaWVuY2UxEzARBgNVBAsTCk1hbmNoZXN0ZXIxCzAJBgNV +\tBAcTmrsogriqMWLAk1DMRcwFQYDVQQDEw5taWNoYWVsIHBhcmQYJKoZIhvcNAQEB +\tBQADggEPADCCAQoCggEBANPEQBgl1IaKdSS1TbhF3hEXSl72G9J+WC/1R64fAcEF +\tW51rEyFYiIeZGx/BVzwXbeBoNUK41OK65sxGuflMo5gLflbwJtHBRIEKAfVVp3YR +\tgW7cMA/s/XKgL1GEC7rQw8lIZT8RApukCGqOVHSi/F1SiFlPDxuDfmdiNzL31+sL +\t0iwHDdNkGjy5pyBSB8Y79dsSJtCW/iaLB0/n8Sj7HgvvZJ7x0fr+RQjYOUUfrePP +\tu2MSpFyf+9BbC/aXgaZuiCvSR+8Snv3xApQY+fULK/xY8h8Ua51iXoQ5jrgu2SqR +\twgA7BUi3G8LFzMBl8FRCDYGUDy7M6QaHXx1ZWIPWNKsCAwEAAaOCAiQwggIgMAwG +\tA1UdEwEB/wQCMAAwEQYJYIZIAYb4QgHTTPAQDAgWgMA4GA1UdDwEB/wQEAwID6DAs +\tBglghkgBhvhCAQ0EHxYdVUsgZS1TY2llbmNlIFVzZXIgQ2VydGlmaWNhdGUwHQYD +\tVR0OBBYEFDTt/sf9PeMaZDHkUIldrDYMNTBZMIGaBgNVHSMEgZIwgY+AFAI4qxGj +\tloCLDdMVKwiljjDastqooXSkcjBwMQswCQYDVQQGEwJVSzERMA8GA1UEChMIZVNj +\taWVuY2UxEjAQBgNVBAsTCUF1dGhvcml0eTELMAkGA1UEAxMCQ0ExLTArBgkqhkiG +\t9w0BCQEWHmNhLW9wZXJhdG9yQGdyaWQtc3VwcG9ydC5hYy51a4IBADApBgNVHRIE +\tIjAggR5jYS1vcGVyYXRvckBncmlkLXN1cHBvcnQuYWMudWswGQYDVR0gBBIwEDAO +\tBgwrBgEEAdkvAQEBAQYwPQYJYIZIAYb4QgEEBDAWLmh0dHA6Ly9jYS5ncmlkLXN1 +\tcHBvcnQuYWMudmT4sopwqlBWsvcHViL2NybC9jYWNybC5jcmwwPQYJYIZIAYb4QgEDBDAWLmh0 +\tdHA6Ly9jYS5ncmlkLXN1cHBvcnQuYWMudWsvcHViL2NybC9jYWNybC5jcmwwPwYD +\tVR0fBDgwNjA0oDKgMIYuaHR0cDovL2NhLmdyaWQt5hYy51ay9wdWIv +\tY3JsL2NhY3JsLmNybDANBgkqhkiG9w0BAQUFAAOCAQEAS/U4iiooBENGW/Hwmmd3 +\tXCy6Zrt08YjKCzGNjorT98g8uGsqYjSxv/hmi0qlnlHs+k/3Iobc3LjS5AMYr5L8 +\tUO7OSkgFFlLHQyC9JzPfmLCAugvzEbyv4Olnsr8hbxF1MbKZoQxUZtMVu29wjfXk +\thTeApBv7eaKCWpSp7MCbvgzm74izKhu3vlDk9w6qVrxePfGgpKPqfHiOoGhFnbTK +\twTC6o2xq5y0qZ03JonF7OJspEd3I5zKY3E+ov7/ZhW6DqT8UFvsAdjvQbXyhV8Eu +\tYhixw1aKEPzNjNowuIseVogKOLXxWI5vAi5HgXdS0/ES5gDGsABo4fqovUKlgop3 +\tRA== +\t-----END CERTIFICATE----- + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="GET" +off=3 method complete +off=4 len=1 span[url]="/" +off=6 url complete +off=11 len=3 span[version]="1.1" +off=14 version complete +off=16 len=14 span[header_field]="X-SSL-Nonsense" +off=31 header_field complete +off=34 len=27 span[header_value]="-----BEGIN CERTIFICATE-----" +off=63 len=65 span[header_value]="\tMIIFbTCCBFWgAwIBAgICH4cwDQYJKoZIhvcNAQEFBQAwcDELMAkGA1UEBhMCVUsx" +off=130 len=65 span[header_value]="\tETAPBgNVBAoTCGVTY2llbmNlMRIwEAYDVQQLEwlBdXRob3JpdHkxCzAJBgNVBAMT" +off=197 len=65 span[header_value]="\tAkNBMS0wKwYJKoZIhvcNAQkBFh5jYS1vcGVyYXRvckBncmlkLXN1cHBvcnQuYWMu" +off=264 len=65 span[header_value]="\tdWswHhcNMDYwNzI3MTQxMzI4WhcNMDcwNzI3MTQxMzI4WjBbMQswCQYDVQQGEwJV" +off=331 len=65 span[header_value]="\tSzERMA8GA1UEChMIZVNjaWVuY2UxEzARBgNVBAsTCk1hbmNoZXN0ZXIxCzAJBgNV" +off=398 len=65 span[header_value]="\tBAcTmrsogriqMWLAk1DMRcwFQYDVQQDEw5taWNoYWVsIHBhcmQYJKoZIhvcNAQEB" +off=465 len=65 span[header_value]="\tBQADggEPADCCAQoCggEBANPEQBgl1IaKdSS1TbhF3hEXSl72G9J+WC/1R64fAcEF" +off=532 len=65 span[header_value]="\tW51rEyFYiIeZGx/BVzwXbeBoNUK41OK65sxGuflMo5gLflbwJtHBRIEKAfVVp3YR" +off=599 len=65 span[header_value]="\tgW7cMA/s/XKgL1GEC7rQw8lIZT8RApukCGqOVHSi/F1SiFlPDxuDfmdiNzL31+sL" +off=666 len=65 span[header_value]="\t0iwHDdNkGjy5pyBSB8Y79dsSJtCW/iaLB0/n8Sj7HgvvZJ7x0fr+RQjYOUUfrePP" +off=733 len=65 span[header_value]="\tu2MSpFyf+9BbC/aXgaZuiCvSR+8Snv3xApQY+fULK/xY8h8Ua51iXoQ5jrgu2SqR" +off=800 len=65 span[header_value]="\twgA7BUi3G8LFzMBl8FRCDYGUDy7M6QaHXx1ZWIPWNKsCAwEAAaOCAiQwggIgMAwG" +off=867 len=66 span[header_value]="\tA1UdEwEB/wQCMAAwEQYJYIZIAYb4QgHTTPAQDAgWgMA4GA1UdDwEB/wQEAwID6DAs" +off=935 len=65 span[header_value]="\tBglghkgBhvhCAQ0EHxYdVUsgZS1TY2llbmNlIFVzZXIgQ2VydGlmaWNhdGUwHQYD" +off=1002 len=65 span[header_value]="\tVR0OBBYEFDTt/sf9PeMaZDHkUIldrDYMNTBZMIGaBgNVHSMEgZIwgY+AFAI4qxGj" +off=1069 len=65 span[header_value]="\tloCLDdMVKwiljjDastqooXSkcjBwMQswCQYDVQQGEwJVSzERMA8GA1UEChMIZVNj" +off=1136 len=65 span[header_value]="\taWVuY2UxEjAQBgNVBAsTCUF1dGhvcml0eTELMAkGA1UEAxMCQ0ExLTArBgkqhkiG" +off=1203 len=65 span[header_value]="\t9w0BCQEWHmNhLW9wZXJhdG9yQGdyaWQtc3VwcG9ydC5hYy51a4IBADApBgNVHRIE" +off=1270 len=65 span[header_value]="\tIjAggR5jYS1vcGVyYXRvckBncmlkLXN1cHBvcnQuYWMudWswGQYDVR0gBBIwEDAO" +off=1337 len=65 span[header_value]="\tBgwrBgEEAdkvAQEBAQYwPQYJYIZIAYb4QgEEBDAWLmh0dHA6Ly9jYS5ncmlkLXN1" +off=1404 len=75 span[header_value]="\tcHBvcnQuYWMudmT4sopwqlBWsvcHViL2NybC9jYWNybC5jcmwwPQYJYIZIAYb4QgEDBDAWLmh0" +off=1481 len=65 span[header_value]="\tdHA6Ly9jYS5ncmlkLXN1cHBvcnQuYWMudWsvcHViL2NybC9jYWNybC5jcmwwPwYD" +off=1548 len=55 span[header_value]="\tVR0fBDgwNjA0oDKgMIYuaHR0cDovL2NhLmdyaWQt5hYy51ay9wdWIv" +off=1605 len=65 span[header_value]="\tY3JsL2NhY3JsLmNybDANBgkqhkiG9w0BAQUFAAOCAQEAS/U4iiooBENGW/Hwmmd3" +off=1672 len=65 span[header_value]="\tXCy6Zrt08YjKCzGNjorT98g8uGsqYjSxv/hmi0qlnlHs+k/3Iobc3LjS5AMYr5L8" +off=1739 len=65 span[header_value]="\tUO7OSkgFFlLHQyC9JzPfmLCAugvzEbyv4Olnsr8hbxF1MbKZoQxUZtMVu29wjfXk" +off=1806 len=65 span[header_value]="\thTeApBv7eaKCWpSp7MCbvgzm74izKhu3vlDk9w6qVrxePfGgpKPqfHiOoGhFnbTK" +off=1873 len=65 span[header_value]="\twTC6o2xq5y0qZ03JonF7OJspEd3I5zKY3E+ov7/ZhW6DqT8UFvsAdjvQbXyhV8Eu" +off=1940 len=65 span[header_value]="\tYhixw1aKEPzNjNowuIseVogKOLXxWI5vAi5HgXdS0/ES5gDGsABo4fqovUKlgop3" +off=2007 len=5 span[header_value]="\tRA==" +off=2014 len=26 span[header_value]="\t-----END CERTIFICATE-----" +off=2042 header_value complete +off=2044 headers complete method=1 v=1/1 flags=0 content_length=0 +off=2044 message complete +``` + +[0]: https://github.com/nodejs/http-parser diff --git a/vendor/llhttp/test/request/transfer-encoding.md b/vendor/llhttp/test/request/transfer-encoding.md new file mode 100644 index 0000000..0f839bc --- /dev/null +++ b/vendor/llhttp/test/request/transfer-encoding.md @@ -0,0 +1,1187 @@ +Transfer-Encoding header +======================== + +## `chunked` + +### Parsing and setting flag + + +```http +PUT /url HTTP/1.1 +Transfer-Encoding: chunked + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="PUT" +off=3 method complete +off=4 len=4 span[url]="/url" +off=9 url complete +off=14 len=3 span[version]="1.1" +off=17 version complete +off=19 len=17 span[header_field]="Transfer-Encoding" +off=37 header_field complete +off=38 len=7 span[header_value]="chunked" +off=47 header_value complete +off=49 headers complete method=4 v=1/1 flags=208 content_length=0 +``` + +### Parse chunks with lowercase size + + +```http +PUT /url HTTP/1.1 +Transfer-Encoding: chunked + +a +0123456789 +0 + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="PUT" +off=3 method complete +off=4 len=4 span[url]="/url" +off=9 url complete +off=14 len=3 span[version]="1.1" +off=17 version complete +off=19 len=17 span[header_field]="Transfer-Encoding" +off=37 header_field complete +off=38 len=7 span[header_value]="chunked" +off=47 header_value complete +off=49 headers complete method=4 v=1/1 flags=208 content_length=0 +off=52 chunk header len=10 +off=52 len=10 span[body]="0123456789" +off=64 chunk complete +off=67 chunk header len=0 +off=69 chunk complete +off=69 message complete +``` + +### Parse chunks with uppercase size + + +```http +PUT /url HTTP/1.1 +Transfer-Encoding: chunked + +A +0123456789 +0 + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="PUT" +off=3 method complete +off=4 len=4 span[url]="/url" +off=9 url complete +off=14 len=3 span[version]="1.1" +off=17 version complete +off=19 len=17 span[header_field]="Transfer-Encoding" +off=37 header_field complete +off=38 len=7 span[header_value]="chunked" +off=47 header_value complete +off=49 headers complete method=4 v=1/1 flags=208 content_length=0 +off=52 chunk header len=10 +off=52 len=10 span[body]="0123456789" +off=64 chunk complete +off=67 chunk header len=0 +off=69 chunk complete +off=69 message complete +``` + +### POST with `Transfer-Encoding: chunked` + + +```http +POST /post_chunked_all_your_base HTTP/1.1 +Transfer-Encoding: chunked + +1e +all your base are belong to us +0 + + +``` + +```log +off=0 message begin +off=0 len=4 span[method]="POST" +off=4 method complete +off=5 len=27 span[url]="/post_chunked_all_your_base" +off=33 url complete +off=38 len=3 span[version]="1.1" +off=41 version complete +off=43 len=17 span[header_field]="Transfer-Encoding" +off=61 header_field complete +off=62 len=7 span[header_value]="chunked" +off=71 header_value complete +off=73 headers complete method=3 v=1/1 flags=208 content_length=0 +off=77 chunk header len=30 +off=77 len=30 span[body]="all your base are belong to us" +off=109 chunk complete +off=112 chunk header len=0 +off=114 chunk complete +off=114 message complete +``` + +### Two chunks and triple zero prefixed end chunk + + +```http +POST /two_chunks_mult_zero_end HTTP/1.1 +Transfer-Encoding: chunked + +5 +hello +6 + world +000 + + +``` + +```log +off=0 message begin +off=0 len=4 span[method]="POST" +off=4 method complete +off=5 len=25 span[url]="/two_chunks_mult_zero_end" +off=31 url complete +off=36 len=3 span[version]="1.1" +off=39 version complete +off=41 len=17 span[header_field]="Transfer-Encoding" +off=59 header_field complete +off=60 len=7 span[header_value]="chunked" +off=69 header_value complete +off=71 headers complete method=3 v=1/1 flags=208 content_length=0 +off=74 chunk header len=5 +off=74 len=5 span[body]="hello" +off=81 chunk complete +off=84 chunk header len=6 +off=84 len=6 span[body]=" world" +off=92 chunk complete +off=97 chunk header len=0 +off=99 chunk complete +off=99 message complete +``` + +### Trailing headers + + +```http +POST /chunked_w_trailing_headers HTTP/1.1 +Transfer-Encoding: chunked + +5 +hello +6 + world +0 +Vary: * +Content-Type: text/plain + + +``` + +```log +off=0 message begin +off=0 len=4 span[method]="POST" +off=4 method complete +off=5 len=27 span[url]="/chunked_w_trailing_headers" +off=33 url complete +off=38 len=3 span[version]="1.1" +off=41 version complete +off=43 len=17 span[header_field]="Transfer-Encoding" +off=61 header_field complete +off=62 len=7 span[header_value]="chunked" +off=71 header_value complete +off=73 headers complete method=3 v=1/1 flags=208 content_length=0 +off=76 chunk header len=5 +off=76 len=5 span[body]="hello" +off=83 chunk complete +off=86 chunk header len=6 +off=86 len=6 span[body]=" world" +off=94 chunk complete +off=97 chunk header len=0 +off=97 len=4 span[header_field]="Vary" +off=102 header_field complete +off=103 len=1 span[header_value]="*" +off=106 header_value complete +off=106 len=12 span[header_field]="Content-Type" +off=119 header_field complete +off=120 len=10 span[header_value]="text/plain" +off=132 header_value complete +off=134 chunk complete +off=134 message complete +``` + +### Chunk extensions + + +```http +POST /chunked_w_unicorns_after_length HTTP/1.1 +Transfer-Encoding: chunked + +5;ilovew3;somuchlove=aretheseparametersfor;another=withvalue +hello +6;blahblah;blah + world +0 + +``` + +```log +off=0 message begin +off=0 len=4 span[method]="POST" +off=4 method complete +off=5 len=32 span[url]="/chunked_w_unicorns_after_length" +off=38 url complete +off=43 len=3 span[version]="1.1" +off=46 version complete +off=48 len=17 span[header_field]="Transfer-Encoding" +off=66 header_field complete +off=67 len=7 span[header_value]="chunked" +off=76 header_value complete +off=78 headers complete method=3 v=1/1 flags=208 content_length=0 +off=80 len=7 span[chunk_extension_name]="ilovew3" +off=88 chunk_extension_name complete +off=88 len=10 span[chunk_extension_name]="somuchlove" +off=99 chunk_extension_name complete +off=99 len=21 span[chunk_extension_value]="aretheseparametersfor" +off=121 chunk_extension_value complete +off=121 len=7 span[chunk_extension_name]="another" +off=129 chunk_extension_name complete +off=129 len=9 span[chunk_extension_value]="withvalue" +off=139 chunk_extension_value complete +off=140 chunk header len=5 +off=140 len=5 span[body]="hello" +off=147 chunk complete +off=149 len=8 span[chunk_extension_name]="blahblah" +off=158 chunk_extension_name complete +off=158 len=4 span[chunk_extension_name]="blah" +off=163 chunk_extension_name complete +off=164 chunk header len=6 +off=164 len=6 span[body]=" world" +off=172 chunk complete +off=175 chunk header len=0 +``` + +### No semicolon before chunk extensions + + +```http +POST /chunked_w_unicorns_after_length HTTP/1.1 +Host: localhost +Transfer-encoding: chunked + +2 erfrferferf +aa +0 rrrr + + +``` + +```log +off=0 message begin +off=0 len=4 span[method]="POST" +off=4 method complete +off=5 len=32 span[url]="/chunked_w_unicorns_after_length" +off=38 url complete +off=43 len=3 span[version]="1.1" +off=46 version complete +off=48 len=4 span[header_field]="Host" +off=53 header_field complete +off=54 len=9 span[header_value]="localhost" +off=65 header_value complete +off=65 len=17 span[header_field]="Transfer-encoding" +off=83 header_field complete +off=84 len=7 span[header_value]="chunked" +off=93 header_value complete +off=95 headers complete method=3 v=1/1 flags=208 content_length=0 +off=97 error code=12 reason="Invalid character in chunk size" +``` + +### No extension after semicolon + + +```http +POST /chunked_w_unicorns_after_length HTTP/1.1 +Host: localhost +Transfer-encoding: chunked + +2; +aa +0 + + +``` + +```log +off=0 message begin +off=0 len=4 span[method]="POST" +off=4 method complete +off=5 len=32 span[url]="/chunked_w_unicorns_after_length" +off=38 url complete +off=43 len=3 span[version]="1.1" +off=46 version complete +off=48 len=4 span[header_field]="Host" +off=53 header_field complete +off=54 len=9 span[header_value]="localhost" +off=65 header_value complete +off=65 len=17 span[header_field]="Transfer-encoding" +off=83 header_field complete +off=84 len=7 span[header_value]="chunked" +off=93 header_value complete +off=95 headers complete method=3 v=1/1 flags=208 content_length=0 +off=98 error code=2 reason="Invalid character in chunk extensions" +``` + + +### Chunk extensions quoting + + +```http +POST /chunked_w_unicorns_after_length HTTP/1.1 +Transfer-Encoding: chunked + +5;ilovew3="I \"love\"; \\extensions\\";somuchlove="aretheseparametersfor";blah;foo=bar +hello +6;blahblah;blah + world +0 + +``` + +```log +off=0 message begin +off=0 len=4 span[method]="POST" +off=4 method complete +off=5 len=32 span[url]="/chunked_w_unicorns_after_length" +off=38 url complete +off=43 len=3 span[version]="1.1" +off=46 version complete +off=48 len=17 span[header_field]="Transfer-Encoding" +off=66 header_field complete +off=67 len=7 span[header_value]="chunked" +off=76 header_value complete +off=78 headers complete method=3 v=1/1 flags=208 content_length=0 +off=80 len=7 span[chunk_extension_name]="ilovew3" +off=88 chunk_extension_name complete +off=88 len=28 span[chunk_extension_value]=""I \"love\"; \\extensions\\"" +off=116 chunk_extension_value complete +off=117 len=10 span[chunk_extension_name]="somuchlove" +off=128 chunk_extension_name complete +off=128 len=23 span[chunk_extension_value]=""aretheseparametersfor"" +off=151 chunk_extension_value complete +off=152 len=4 span[chunk_extension_name]="blah" +off=157 chunk_extension_name complete +off=157 len=3 span[chunk_extension_name]="foo" +off=161 chunk_extension_name complete +off=161 len=3 span[chunk_extension_value]="bar" +off=165 chunk_extension_value complete +off=166 chunk header len=5 +off=166 len=5 span[body]="hello" +off=173 chunk complete +off=175 len=8 span[chunk_extension_name]="blahblah" +off=184 chunk_extension_name complete +off=184 len=4 span[chunk_extension_name]="blah" +off=189 chunk_extension_name complete +off=190 chunk header len=6 +off=190 len=6 span[body]=" world" +off=198 chunk complete +off=201 chunk header len=0 +``` + + +### Unbalanced chunk extensions quoting + + +```http +POST /chunked_w_unicorns_after_length HTTP/1.1 +Transfer-Encoding: chunked + +5;ilovew3="abc";somuchlove="def; ghi +hello +6;blahblah;blah + world +0 + +``` + +```log +off=0 message begin +off=0 len=4 span[method]="POST" +off=4 method complete +off=5 len=32 span[url]="/chunked_w_unicorns_after_length" +off=38 url complete +off=43 len=3 span[version]="1.1" +off=46 version complete +off=48 len=17 span[header_field]="Transfer-Encoding" +off=66 header_field complete +off=67 len=7 span[header_value]="chunked" +off=76 header_value complete +off=78 headers complete method=3 v=1/1 flags=208 content_length=0 +off=80 len=7 span[chunk_extension_name]="ilovew3" +off=88 chunk_extension_name complete +off=88 len=5 span[chunk_extension_value]=""abc"" +off=93 chunk_extension_value complete +off=94 len=10 span[chunk_extension_name]="somuchlove" +off=105 chunk_extension_name complete +off=105 len=9 span[chunk_extension_value]=""def; ghi" +off=115 error code=2 reason="Invalid character in chunk extensions quoted value" +``` + +## Ignoring `pigeons` + +Requests cannot have invalid `Transfer-Encoding`. It is impossible to determine +their body size. Not erroring would make HTTP smuggling attacks possible. + + +```http +PUT /url HTTP/1.1 +Transfer-Encoding: pigeons + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="PUT" +off=3 method complete +off=4 len=4 span[url]="/url" +off=9 url complete +off=14 len=3 span[version]="1.1" +off=17 version complete +off=19 len=17 span[header_field]="Transfer-Encoding" +off=37 header_field complete +off=38 len=7 span[header_value]="pigeons" +off=47 header_value complete +off=49 headers complete method=4 v=1/1 flags=200 content_length=0 +off=49 error code=15 reason="Request has invalid `Transfer-Encoding`" +``` + +## POST with `Transfer-Encoding` and `Content-Length` + + +```http +POST /post_identity_body_world?q=search#hey HTTP/1.1 +Accept: */* +Transfer-Encoding: identity +Content-Length: 5 + +World +``` + +```log +off=0 message begin +off=0 len=4 span[method]="POST" +off=4 method complete +off=5 len=38 span[url]="/post_identity_body_world?q=search#hey" +off=44 url complete +off=49 len=3 span[version]="1.1" +off=52 version complete +off=54 len=6 span[header_field]="Accept" +off=61 header_field complete +off=62 len=3 span[header_value]="*/*" +off=67 header_value complete +off=67 len=17 span[header_field]="Transfer-Encoding" +off=85 header_field complete +off=86 len=8 span[header_value]="identity" +off=96 header_value complete +off=96 len=14 span[header_field]="Content-Length" +off=111 header_field complete +off=111 error code=11 reason="Content-Length can't be present with Transfer-Encoding" +``` + +## POST with `Transfer-Encoding` and `Content-Length` (lenient) + +TODO(indutny): should we allow it even in lenient mode? (Consider disabling +this). + +NOTE: `Content-Length` is ignored when `Transfer-Encoding` is present. Messages +(in lenient mode) are read until EOF. + + +```http +POST /post_identity_body_world?q=search#hey HTTP/1.1 +Accept: */* +Transfer-Encoding: identity +Content-Length: 1 + +World +``` + +```log +off=0 message begin +off=0 len=4 span[method]="POST" +off=4 method complete +off=5 len=38 span[url]="/post_identity_body_world?q=search#hey" +off=44 url complete +off=49 len=3 span[version]="1.1" +off=52 version complete +off=54 len=6 span[header_field]="Accept" +off=61 header_field complete +off=62 len=3 span[header_value]="*/*" +off=67 header_value complete +off=67 len=17 span[header_field]="Transfer-Encoding" +off=85 header_field complete +off=86 len=8 span[header_value]="identity" +off=96 header_value complete +off=96 len=14 span[header_field]="Content-Length" +off=111 header_field complete +off=112 len=1 span[header_value]="1" +off=115 header_value complete +off=117 headers complete method=3 v=1/1 flags=220 content_length=1 +off=117 len=5 span[body]="World" +``` + +## POST with empty `Transfer-Encoding` and `Content-Length` (lenient) + + +```http +POST / HTTP/1.1 +Host: foo +Content-Length: 10 +Transfer-Encoding: +Transfer-Encoding: +Transfer-Encoding: + +2 +AA +0 +``` + +```log +off=0 message begin +off=0 len=4 span[method]="POST" +off=4 method complete +off=5 len=1 span[url]="/" +off=7 url complete +off=12 len=3 span[version]="1.1" +off=15 version complete +off=17 len=4 span[header_field]="Host" +off=22 header_field complete +off=23 len=3 span[header_value]="foo" +off=28 header_value complete +off=28 len=14 span[header_field]="Content-Length" +off=43 header_field complete +off=44 len=2 span[header_value]="10" +off=48 header_value complete +off=48 len=17 span[header_field]="Transfer-Encoding" +off=66 header_field complete +off=66 error code=15 reason="Transfer-Encoding can't be present with Content-Length" +``` + +## POST with `chunked` before other transfer coding names + + +```http +POST /post_identity_body_world?q=search#hey HTTP/1.1 +Accept: */* +Transfer-Encoding: chunked, deflate + +World +``` + +```log +off=0 message begin +off=0 len=4 span[method]="POST" +off=4 method complete +off=5 len=38 span[url]="/post_identity_body_world?q=search#hey" +off=44 url complete +off=49 len=3 span[version]="1.1" +off=52 version complete +off=54 len=6 span[header_field]="Accept" +off=61 header_field complete +off=62 len=3 span[header_value]="*/*" +off=67 header_value complete +off=67 len=17 span[header_field]="Transfer-Encoding" +off=85 header_field complete +off=86 len=7 span[header_value]="chunked" +off=94 error code=15 reason="Invalid `Transfer-Encoding` header value" +``` + +## POST with `chunked` and duplicate transfer-encoding + + +```http +POST /post_identity_body_world?q=search#hey HTTP/1.1 +Accept: */* +Transfer-Encoding: chunked +Transfer-Encoding: deflate + +World +``` + +```log +off=0 message begin +off=0 len=4 span[method]="POST" +off=4 method complete +off=5 len=38 span[url]="/post_identity_body_world?q=search#hey" +off=44 url complete +off=49 len=3 span[version]="1.1" +off=52 version complete +off=54 len=6 span[header_field]="Accept" +off=61 header_field complete +off=62 len=3 span[header_value]="*/*" +off=67 header_value complete +off=67 len=17 span[header_field]="Transfer-Encoding" +off=85 header_field complete +off=86 len=7 span[header_value]="chunked" +off=95 header_value complete +off=95 len=17 span[header_field]="Transfer-Encoding" +off=113 header_field complete +off=114 len=0 span[header_value]="" +off=115 error code=15 reason="Invalid `Transfer-Encoding` header value" +``` + +## POST with `chunked` before other transfer-coding (lenient) + + +```http +POST /post_identity_body_world?q=search#hey HTTP/1.1 +Accept: */* +Transfer-Encoding: chunked, deflate + +World +``` + +```log +off=0 message begin +off=0 len=4 span[method]="POST" +off=4 method complete +off=5 len=38 span[url]="/post_identity_body_world?q=search#hey" +off=44 url complete +off=49 len=3 span[version]="1.1" +off=52 version complete +off=54 len=6 span[header_field]="Accept" +off=61 header_field complete +off=62 len=3 span[header_value]="*/*" +off=67 header_value complete +off=67 len=17 span[header_field]="Transfer-Encoding" +off=85 header_field complete +off=86 len=16 span[header_value]="chunked, deflate" +off=104 header_value complete +off=106 headers complete method=3 v=1/1 flags=200 content_length=0 +off=106 len=5 span[body]="World" +``` + +## POST with `chunked` and duplicate transfer-encoding (lenient) + + +```http +POST /post_identity_body_world?q=search#hey HTTP/1.1 +Accept: */* +Transfer-Encoding: chunked +Transfer-Encoding: deflate + +World +``` + +```log +off=0 message begin +off=0 len=4 span[method]="POST" +off=4 method complete +off=5 len=38 span[url]="/post_identity_body_world?q=search#hey" +off=44 url complete +off=49 len=3 span[version]="1.1" +off=52 version complete +off=54 len=6 span[header_field]="Accept" +off=61 header_field complete +off=62 len=3 span[header_value]="*/*" +off=67 header_value complete +off=67 len=17 span[header_field]="Transfer-Encoding" +off=85 header_field complete +off=86 len=7 span[header_value]="chunked" +off=95 header_value complete +off=95 len=17 span[header_field]="Transfer-Encoding" +off=113 header_field complete +off=114 len=7 span[header_value]="deflate" +off=123 header_value complete +off=125 headers complete method=3 v=1/1 flags=200 content_length=0 +off=125 len=5 span[body]="World" +``` + +## POST with `chunked` as last transfer-encoding + + +```http +POST /post_identity_body_world?q=search#hey HTTP/1.1 +Accept: */* +Transfer-Encoding: deflate, chunked + +5 +World +0 + + +``` + +```log +off=0 message begin +off=0 len=4 span[method]="POST" +off=4 method complete +off=5 len=38 span[url]="/post_identity_body_world?q=search#hey" +off=44 url complete +off=49 len=3 span[version]="1.1" +off=52 version complete +off=54 len=6 span[header_field]="Accept" +off=61 header_field complete +off=62 len=3 span[header_value]="*/*" +off=67 header_value complete +off=67 len=17 span[header_field]="Transfer-Encoding" +off=85 header_field complete +off=86 len=16 span[header_value]="deflate, chunked" +off=104 header_value complete +off=106 headers complete method=3 v=1/1 flags=208 content_length=0 +off=109 chunk header len=5 +off=109 len=5 span[body]="World" +off=116 chunk complete +off=119 chunk header len=0 +off=121 chunk complete +off=121 message complete +``` + +## POST with `chunked` as last transfer-encoding (multiple headers) + + +```http +POST /post_identity_body_world?q=search#hey HTTP/1.1 +Accept: */* +Transfer-Encoding: deflate +Transfer-Encoding: chunked + +5 +World +0 + + +``` + +```log +off=0 message begin +off=0 len=4 span[method]="POST" +off=4 method complete +off=5 len=38 span[url]="/post_identity_body_world?q=search#hey" +off=44 url complete +off=49 len=3 span[version]="1.1" +off=52 version complete +off=54 len=6 span[header_field]="Accept" +off=61 header_field complete +off=62 len=3 span[header_value]="*/*" +off=67 header_value complete +off=67 len=17 span[header_field]="Transfer-Encoding" +off=85 header_field complete +off=86 len=7 span[header_value]="deflate" +off=95 header_value complete +off=95 len=17 span[header_field]="Transfer-Encoding" +off=113 header_field complete +off=114 len=7 span[header_value]="chunked" +off=123 header_value complete +off=125 headers complete method=3 v=1/1 flags=208 content_length=0 +off=128 chunk header len=5 +off=128 len=5 span[body]="World" +off=135 chunk complete +off=138 chunk header len=0 +off=140 chunk complete +off=140 message complete +``` + +## POST with `chunkedchunked` as transfer-encoding + + +```http +POST /post_identity_body_world?q=search#hey HTTP/1.1 +Accept: */* +Transfer-Encoding: chunkedchunked + +5 +World +0 + + +``` + +```log +off=0 message begin +off=0 len=4 span[method]="POST" +off=4 method complete +off=5 len=38 span[url]="/post_identity_body_world?q=search#hey" +off=44 url complete +off=49 len=3 span[version]="1.1" +off=52 version complete +off=54 len=6 span[header_field]="Accept" +off=61 header_field complete +off=62 len=3 span[header_value]="*/*" +off=67 header_value complete +off=67 len=17 span[header_field]="Transfer-Encoding" +off=85 header_field complete +off=86 len=14 span[header_value]="chunkedchunked" +off=102 header_value complete +off=104 headers complete method=3 v=1/1 flags=200 content_length=0 +off=104 error code=15 reason="Request has invalid `Transfer-Encoding`" +``` + +## Missing last-chunk + + +```http +PUT /url HTTP/1.1 +Transfer-Encoding: chunked + +3 +foo + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="PUT" +off=3 method complete +off=4 len=4 span[url]="/url" +off=9 url complete +off=14 len=3 span[version]="1.1" +off=17 version complete +off=19 len=17 span[header_field]="Transfer-Encoding" +off=37 header_field complete +off=38 len=7 span[header_value]="chunked" +off=47 header_value complete +off=49 headers complete method=4 v=1/1 flags=208 content_length=0 +off=52 chunk header len=3 +off=52 len=3 span[body]="foo" +off=57 chunk complete +off=57 error code=12 reason="Invalid character in chunk size" +``` + +## Validate chunk parameters + + +```http +PUT /url HTTP/1.1 +Transfer-Encoding: chunked + +3 \n \r\n\ +foo + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="PUT" +off=3 method complete +off=4 len=4 span[url]="/url" +off=9 url complete +off=14 len=3 span[version]="1.1" +off=17 version complete +off=19 len=17 span[header_field]="Transfer-Encoding" +off=37 header_field complete +off=38 len=7 span[header_value]="chunked" +off=47 header_value complete +off=49 headers complete method=4 v=1/1 flags=208 content_length=0 +off=51 error code=12 reason="Invalid character in chunk size" +``` + +## Invalid OBS fold after chunked value + + +```http +PUT /url HTTP/1.1 +Transfer-Encoding: chunked + abc + +5 +World +0 + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="PUT" +off=3 method complete +off=4 len=4 span[url]="/url" +off=9 url complete +off=14 len=3 span[version]="1.1" +off=17 version complete +off=19 len=17 span[header_field]="Transfer-Encoding" +off=37 header_field complete +off=38 len=7 span[header_value]="chunked" +off=47 len=5 span[header_value]=" abc" +off=54 header_value complete +off=56 headers complete method=4 v=1/1 flags=200 content_length=0 +off=56 error code=15 reason="Request has invalid `Transfer-Encoding`" +``` + +### Chunk header not terminated by CRLF + + + +```http +GET / HTTP/1.1 +Host: a +Connection: close +Transfer-Encoding: chunked + +5\r\r;ABCD +34 +E +0 + +GET / HTTP/1.1 +Host: a +Content-Length: 5 + +0 + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="GET" +off=3 method complete +off=4 len=1 span[url]="/" +off=6 url complete +off=11 len=3 span[version]="1.1" +off=14 version complete +off=16 len=4 span[header_field]="Host" +off=21 header_field complete +off=22 len=1 span[header_value]="a" +off=25 header_value complete +off=25 len=10 span[header_field]="Connection" +off=36 header_field complete +off=37 len=6 span[header_value]="close " +off=45 header_value complete +off=45 len=17 span[header_field]="Transfer-Encoding" +off=63 header_field complete +off=64 len=8 span[header_value]="chunked " +off=74 header_value complete +off=76 headers complete method=1 v=1/1 flags=20a content_length=0 +off=78 error code=2 reason="Expected LF after chunk size" +``` + +### Chunk header not terminated by CRLF (lenient) + + + +```http +GET / HTTP/1.1 +Host: a +Connection: close +Transfer-Encoding: chunked + +6\r\r;ABCD +33 +E +0 + +GET / HTTP/1.1 +Host: a +Content-Length: 5 +0 + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="GET" +off=3 method complete +off=4 len=1 span[url]="/" +off=6 url complete +off=11 len=3 span[version]="1.1" +off=14 version complete +off=16 len=4 span[header_field]="Host" +off=21 header_field complete +off=22 len=1 span[header_value]="a" +off=25 header_value complete +off=25 len=10 span[header_field]="Connection" +off=36 header_field complete +off=37 len=6 span[header_value]="close " +off=45 header_value complete +off=45 len=17 span[header_field]="Transfer-Encoding" +off=63 header_field complete +off=64 len=8 span[header_value]="chunked " +off=74 header_value complete +off=76 headers complete method=1 v=1/1 flags=20a content_length=0 +off=78 chunk header len=6 +off=78 len=1 span[body]=cr +off=79 len=5 span[body]=";ABCD" +off=86 chunk complete +off=90 chunk header len=51 +off=90 len=1 span[body]="E" +off=91 len=1 span[body]=cr +off=92 len=1 span[body]=lf +off=93 len=1 span[body]="0" +off=94 len=1 span[body]=cr +off=95 len=1 span[body]=lf +off=96 len=1 span[body]=cr +off=97 len=1 span[body]=lf +off=98 len=15 span[body]="GET / HTTP/1.1 " +off=113 len=1 span[body]=cr +off=114 len=1 span[body]=lf +off=115 len=7 span[body]="Host: a" +off=122 len=1 span[body]=cr +off=123 len=1 span[body]=lf +off=124 len=17 span[body]="Content-Length: 5" +off=143 chunk complete +off=146 chunk header len=0 +off=148 chunk complete +off=148 message complete +``` + +### Chunk data not terminated by CRLF + + + +```http +GET / HTTP/1.1 +Host: a +Connection: close +Transfer-Encoding: chunked + +5 +ABCDE0 + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="GET" +off=3 method complete +off=4 len=1 span[url]="/" +off=6 url complete +off=11 len=3 span[version]="1.1" +off=14 version complete +off=16 len=4 span[header_field]="Host" +off=21 header_field complete +off=22 len=1 span[header_value]="a" +off=25 header_value complete +off=25 len=10 span[header_field]="Connection" +off=36 header_field complete +off=37 len=6 span[header_value]="close " +off=45 header_value complete +off=45 len=17 span[header_field]="Transfer-Encoding" +off=63 header_field complete +off=64 len=8 span[header_value]="chunked " +off=74 header_value complete +off=76 headers complete method=1 v=1/1 flags=20a content_length=0 +off=79 chunk header len=5 +off=79 len=5 span[body]="ABCDE" +off=84 error code=2 reason="Expected LF after chunk data" +``` + +### Chunk data not terminated by CRLF (lenient) + + + +```http +GET / HTTP/1.1 +Host: a +Connection: close +Transfer-Encoding: chunked + +5 +ABCDE0 + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="GET" +off=3 method complete +off=4 len=1 span[url]="/" +off=6 url complete +off=11 len=3 span[version]="1.1" +off=14 version complete +off=16 len=4 span[header_field]="Host" +off=21 header_field complete +off=22 len=1 span[header_value]="a" +off=25 header_value complete +off=25 len=10 span[header_field]="Connection" +off=36 header_field complete +off=37 len=6 span[header_value]="close " +off=45 header_value complete +off=45 len=17 span[header_field]="Transfer-Encoding" +off=63 header_field complete +off=64 len=8 span[header_value]="chunked " +off=74 header_value complete +off=76 headers complete method=1 v=1/1 flags=20a content_length=0 +off=79 chunk header len=5 +off=79 len=5 span[body]="ABCDE" +off=84 chunk complete +off=87 chunk header len=0 +``` + +## Space after chunk header + + +```http +PUT /url HTTP/1.1 +Transfer-Encoding: chunked + +a \r\n0123456789 +0 + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="PUT" +off=3 method complete +off=4 len=4 span[url]="/url" +off=9 url complete +off=14 len=3 span[version]="1.1" +off=17 version complete +off=19 len=17 span[header_field]="Transfer-Encoding" +off=37 header_field complete +off=38 len=7 span[header_value]="chunked" +off=47 header_value complete +off=49 headers complete method=4 v=1/1 flags=208 content_length=0 +off=51 error code=12 reason="Invalid character in chunk size" +``` + +## Space after chunk header (lenient) + + +```http +PUT /url HTTP/1.1 +Transfer-Encoding: chunked + +a \r\n0123456789 +0 + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="PUT" +off=3 method complete +off=4 len=4 span[url]="/url" +off=9 url complete +off=14 len=3 span[version]="1.1" +off=17 version complete +off=19 len=17 span[header_field]="Transfer-Encoding" +off=37 header_field complete +off=38 len=7 span[header_value]="chunked" +off=47 header_value complete +off=49 headers complete method=4 v=1/1 flags=208 content_length=0 +off=53 chunk header len=10 +off=53 len=10 span[body]="0123456789" +off=65 chunk complete +off=68 chunk header len=0 +off=70 chunk complete +off=70 message complete +``` diff --git a/vendor/llhttp/test/request/uri.md b/vendor/llhttp/test/request/uri.md new file mode 100644 index 0000000..f7f12b0 --- /dev/null +++ b/vendor/llhttp/test/request/uri.md @@ -0,0 +1,243 @@ +URI +=== + +## Quotes in URI + + +```http +GET /with_"lovely"_quotes?foo=\"bar\" HTTP/1.1 + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="GET" +off=3 method complete +off=4 len=33 span[url]="/with_"lovely"_quotes?foo=\"bar\"" +off=38 url complete +off=43 len=3 span[version]="1.1" +off=46 version complete +off=50 headers complete method=1 v=1/1 flags=0 content_length=0 +off=50 message complete +``` + +## Query URL with question mark + +Some clients include `?` characters in query strings. + + +```http +GET /test.cgi?foo=bar?baz HTTP/1.1 + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="GET" +off=3 method complete +off=4 len=21 span[url]="/test.cgi?foo=bar?baz" +off=26 url complete +off=31 len=3 span[version]="1.1" +off=34 version complete +off=38 headers complete method=1 v=1/1 flags=0 content_length=0 +off=38 message complete +``` + +## Host terminated by a query string + + +```http +GET http://hypnotoad.org?hail=all HTTP/1.1\r\n + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="GET" +off=3 method complete +off=4 len=29 span[url]="http://hypnotoad.org?hail=all" +off=34 url complete +off=39 len=3 span[version]="1.1" +off=42 version complete +off=46 headers complete method=1 v=1/1 flags=0 content_length=0 +off=46 message complete +``` + +## `host:port` terminated by a query string + + +```http +GET http://hypnotoad.org:1234?hail=all HTTP/1.1 + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="GET" +off=3 method complete +off=4 len=34 span[url]="http://hypnotoad.org:1234?hail=all" +off=39 url complete +off=44 len=3 span[version]="1.1" +off=47 version complete +off=51 headers complete method=1 v=1/1 flags=0 content_length=0 +off=51 message complete +``` + +## Query URL with vertical bar character + +It should be allowed to have vertical bar symbol in URI: `|`. + +See: https://github.com/nodejs/node/issues/27584 + + +```http +GET /test.cgi?query=| HTTP/1.1 + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="GET" +off=3 method complete +off=4 len=17 span[url]="/test.cgi?query=|" +off=22 url complete +off=27 len=3 span[version]="1.1" +off=30 version complete +off=34 headers complete method=1 v=1/1 flags=0 content_length=0 +off=34 message complete +``` + +## `host:port` terminated by a space + + +```http +GET http://hypnotoad.org:1234 HTTP/1.1 + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="GET" +off=3 method complete +off=4 len=25 span[url]="http://hypnotoad.org:1234" +off=30 url complete +off=35 len=3 span[version]="1.1" +off=38 version complete +off=42 headers complete method=1 v=1/1 flags=0 content_length=0 +off=42 message complete +``` + +## Disallow UTF-8 in URI path in strict mode + + +```http +GET /δ¶/δt/pope?q=1#narf HTTP/1.1 +Host: github.com + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="GET" +off=3 method complete +off=5 error code=7 reason="Invalid char in url path" +``` + +## Fragment in URI + + +```http +GET /forums/1/topics/2375?page=1#posts-17408 HTTP/1.1 + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="GET" +off=3 method complete +off=4 len=40 span[url]="/forums/1/topics/2375?page=1#posts-17408" +off=45 url complete +off=50 len=3 span[version]="1.1" +off=53 version complete +off=57 headers complete method=1 v=1/1 flags=0 content_length=0 +off=57 message complete +``` + +## Underscore in hostname + + +```http +CONNECT home_0.netscape.com:443 HTTP/1.0 +User-agent: Mozilla/1.1N +Proxy-authorization: basic aGVsbG86d29ybGQ= + + +``` + +```log +off=0 message begin +off=0 len=7 span[method]="CONNECT" +off=7 method complete +off=8 len=23 span[url]="home_0.netscape.com:443" +off=32 url complete +off=37 len=3 span[version]="1.0" +off=40 version complete +off=42 len=10 span[header_field]="User-agent" +off=53 header_field complete +off=54 len=12 span[header_value]="Mozilla/1.1N" +off=68 header_value complete +off=68 len=19 span[header_field]="Proxy-authorization" +off=88 header_field complete +off=89 len=22 span[header_value]="basic aGVsbG86d29ybGQ=" +off=113 header_value complete +off=115 headers complete method=5 v=1/0 flags=0 content_length=0 +off=115 message complete +off=115 error code=22 reason="Pause on CONNECT/Upgrade" +``` + +## `host:port` and basic auth + + +```http +GET http://a%12:b!&*$@hypnotoad.org:1234/toto HTTP/1.1 + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="GET" +off=3 method complete +off=4 len=41 span[url]="http://a%12:b!&*$@hypnotoad.org:1234/toto" +off=46 url complete +off=51 len=3 span[version]="1.1" +off=54 version complete +off=58 headers complete method=1 v=1/1 flags=0 content_length=0 +off=58 message complete +``` + +## Space in URI + + +```http +GET /foo bar/ HTTP/1.1 + + +``` + +```log +off=0 message begin +off=0 len=3 span[method]="GET" +off=3 method complete +off=4 len=4 span[url]="/foo" +off=9 url complete +off=9 error code=8 reason="Expected HTTP/" +``` diff --git a/vendor/llhttp/test/response/connection.md b/vendor/llhttp/test/response/connection.md new file mode 100644 index 0000000..11f9eb6 --- /dev/null +++ b/vendor/llhttp/test/response/connection.md @@ -0,0 +1,647 @@ +Connection header +================= + +## Proxy-Connection + + +```http +HTTP/1.1 200 OK +Content-Type: text/html; charset=UTF-8 +Content-Length: 11 +Proxy-Connection: close +Date: Thu, 31 Dec 2009 20:55:48 +0000 + +hello world +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=2 span[status]="OK" +off=17 status complete +off=17 len=12 span[header_field]="Content-Type" +off=30 header_field complete +off=31 len=24 span[header_value]="text/html; charset=UTF-8" +off=57 header_value complete +off=57 len=14 span[header_field]="Content-Length" +off=72 header_field complete +off=73 len=2 span[header_value]="11" +off=77 header_value complete +off=77 len=16 span[header_field]="Proxy-Connection" +off=94 header_field complete +off=95 len=5 span[header_value]="close" +off=102 header_value complete +off=102 len=4 span[header_field]="Date" +off=107 header_field complete +off=108 len=31 span[header_value]="Thu, 31 Dec 2009 20:55:48 +0000" +off=141 header_value complete +off=143 headers complete status=200 v=1/1 flags=22 content_length=11 +off=143 len=11 span[body]="hello world" +off=154 message complete +``` + +## HTTP/1.0 with keep-alive and EOF-terminated 200 status + +There is no `Content-Length` in this response, so even though the +`keep-alive` is on - it should read until EOF. + + +```http +HTTP/1.0 200 OK +Connection: keep-alive + +HTTP/1.0 200 OK +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.0" +off=8 version complete +off=13 len=2 span[status]="OK" +off=17 status complete +off=17 len=10 span[header_field]="Connection" +off=28 header_field complete +off=29 len=10 span[header_value]="keep-alive" +off=41 header_value complete +off=43 headers complete status=200 v=1/0 flags=1 content_length=0 +off=43 len=15 span[body]="HTTP/1.0 200 OK" +``` + +## HTTP/1.0 with keep-alive and 204 status + +Responses with `204` status cannot have a body. + + +```http +HTTP/1.0 204 No content +Connection: keep-alive + +HTTP/1.0 200 OK +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.0" +off=8 version complete +off=13 len=10 span[status]="No content" +off=25 status complete +off=25 len=10 span[header_field]="Connection" +off=36 header_field complete +off=37 len=10 span[header_value]="keep-alive" +off=49 header_value complete +off=51 headers complete status=204 v=1/0 flags=1 content_length=0 +off=51 message complete +off=51 reset +off=51 message begin +off=56 len=3 span[version]="1.0" +off=59 version complete +off=64 len=2 span[status]="OK" +``` + +## HTTP/1.1 with EOF-terminated 200 status + +There is no `Content-Length` in this response, so even though the +`keep-alive` is on (implicitly in HTTP 1.1) - it should read until EOF. + + +```http +HTTP/1.1 200 OK + +HTTP/1.1 200 OK +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=2 span[status]="OK" +off=17 status complete +off=19 headers complete status=200 v=1/1 flags=0 content_length=0 +off=19 len=15 span[body]="HTTP/1.1 200 OK" +``` + +## HTTP/1.1 with 204 status + +Responses with `204` status cannot have a body. + + +```http +HTTP/1.1 204 No content + +HTTP/1.1 200 OK +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=10 span[status]="No content" +off=25 status complete +off=27 headers complete status=204 v=1/1 flags=0 content_length=0 +off=27 message complete +off=27 reset +off=27 message begin +off=32 len=3 span[version]="1.1" +off=35 version complete +off=40 len=2 span[status]="OK" +``` + +## HTTP/1.1 with keep-alive disabled and 204 status + + +```http +HTTP/1.1 204 No content +Connection: close + +HTTP/1.1 200 OK +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=10 span[status]="No content" +off=25 status complete +off=25 len=10 span[header_field]="Connection" +off=36 header_field complete +off=37 len=5 span[header_value]="close" +off=44 header_value complete +off=46 headers complete status=204 v=1/1 flags=2 content_length=0 +off=46 message complete +off=47 error code=5 reason="Data after `Connection: close`" +``` + +## HTTP/1.1 with keep-alive disabled, content-length (lenient) + +Parser should discard extra request in lenient mode. + + +```http +HTTP/1.1 200 No content +Content-Length: 5 +Connection: close + +2ad731e3-4dcd-4f70-b871-0ad284b29ffc +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=10 span[status]="No content" +off=25 status complete +off=25 len=14 span[header_field]="Content-Length" +off=40 header_field complete +off=41 len=1 span[header_value]="5" +off=44 header_value complete +off=44 len=10 span[header_field]="Connection" +off=55 header_field complete +off=56 len=5 span[header_value]="close" +off=63 header_value complete +off=65 headers complete status=200 v=1/1 flags=22 content_length=5 +off=65 len=5 span[body]="2ad73" +off=70 message complete +``` + +## HTTP/1.1 with keep-alive disabled, content-length + +Parser should discard extra request in strict mode. + + +```http +HTTP/1.1 200 No content +Content-Length: 5 +Connection: close + +2ad731e3-4dcd-4f70-b871-0ad284b29ffc +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=10 span[status]="No content" +off=25 status complete +off=25 len=14 span[header_field]="Content-Length" +off=40 header_field complete +off=41 len=1 span[header_value]="5" +off=44 header_value complete +off=44 len=10 span[header_field]="Connection" +off=55 header_field complete +off=56 len=5 span[header_value]="close" +off=63 header_value complete +off=65 headers complete status=200 v=1/1 flags=22 content_length=5 +off=65 len=5 span[body]="2ad73" +off=70 message complete +off=71 error code=5 reason="Data after `Connection: close`" +``` + +## HTTP/1.1 with keep-alive disabled and 204 status (lenient) + + +```http +HTTP/1.1 204 No content +Connection: close + +HTTP/1.1 200 OK +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=10 span[status]="No content" +off=25 status complete +off=25 len=10 span[header_field]="Connection" +off=36 header_field complete +off=37 len=5 span[header_value]="close" +off=44 header_value complete +off=46 headers complete status=204 v=1/1 flags=2 content_length=0 +off=46 message complete +off=46 reset +off=46 message begin +off=51 len=3 span[version]="1.1" +off=54 version complete +off=59 len=2 span[status]="OK" +``` + +## HTTP 101 response with Upgrade and Content-Length header + + +```http +HTTP/1.1 101 Switching Protocols +Connection: upgrade +Upgrade: h2c +Content-Length: 4 + +body\ +proto +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=19 span[status]="Switching Protocols" +off=34 status complete +off=34 len=10 span[header_field]="Connection" +off=45 header_field complete +off=46 len=7 span[header_value]="upgrade" +off=55 header_value complete +off=55 len=7 span[header_field]="Upgrade" +off=63 header_field complete +off=64 len=3 span[header_value]="h2c" +off=69 header_value complete +off=69 len=14 span[header_field]="Content-Length" +off=84 header_field complete +off=85 len=1 span[header_value]="4" +off=88 header_value complete +off=90 headers complete status=101 v=1/1 flags=34 content_length=4 +off=90 message complete +off=90 error code=22 reason="Pause on CONNECT/Upgrade" +``` + +## HTTP 101 response with Upgrade and Transfer-Encoding header + + +```http +HTTP/1.1 101 Switching Protocols +Connection: upgrade +Upgrade: h2c +Transfer-Encoding: chunked + +2 +bo +2 +dy +0 + +proto +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=19 span[status]="Switching Protocols" +off=34 status complete +off=34 len=10 span[header_field]="Connection" +off=45 header_field complete +off=46 len=7 span[header_value]="upgrade" +off=55 header_value complete +off=55 len=7 span[header_field]="Upgrade" +off=63 header_field complete +off=64 len=3 span[header_value]="h2c" +off=69 header_value complete +off=69 len=17 span[header_field]="Transfer-Encoding" +off=87 header_field complete +off=88 len=7 span[header_value]="chunked" +off=97 header_value complete +off=99 headers complete status=101 v=1/1 flags=21c content_length=0 +off=99 message complete +off=99 error code=22 reason="Pause on CONNECT/Upgrade" +``` + +## HTTP 200 response with Upgrade header + + +```http +HTTP/1.1 200 OK +Connection: upgrade +Upgrade: h2c + +body +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=2 span[status]="OK" +off=17 status complete +off=17 len=10 span[header_field]="Connection" +off=28 header_field complete +off=29 len=7 span[header_value]="upgrade" +off=38 header_value complete +off=38 len=7 span[header_field]="Upgrade" +off=46 header_field complete +off=47 len=3 span[header_value]="h2c" +off=52 header_value complete +off=54 headers complete status=200 v=1/1 flags=14 content_length=0 +off=54 len=4 span[body]="body" +``` + +## HTTP 200 response with Upgrade header and Content-Length + + +```http +HTTP/1.1 200 OK +Connection: upgrade +Upgrade: h2c +Content-Length: 4 + +body +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=2 span[status]="OK" +off=17 status complete +off=17 len=10 span[header_field]="Connection" +off=28 header_field complete +off=29 len=7 span[header_value]="upgrade" +off=38 header_value complete +off=38 len=7 span[header_field]="Upgrade" +off=46 header_field complete +off=47 len=3 span[header_value]="h2c" +off=52 header_value complete +off=52 len=14 span[header_field]="Content-Length" +off=67 header_field complete +off=68 len=1 span[header_value]="4" +off=71 header_value complete +off=73 headers complete status=200 v=1/1 flags=34 content_length=4 +off=73 len=4 span[body]="body" +off=77 message complete +``` + +## HTTP 200 response with Upgrade header and Transfer-Encoding + + +```http +HTTP/1.1 200 OK +Connection: upgrade +Upgrade: h2c +Transfer-Encoding: chunked + +2 +bo +2 +dy +0 + + +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=2 span[status]="OK" +off=17 status complete +off=17 len=10 span[header_field]="Connection" +off=28 header_field complete +off=29 len=7 span[header_value]="upgrade" +off=38 header_value complete +off=38 len=7 span[header_field]="Upgrade" +off=46 header_field complete +off=47 len=3 span[header_value]="h2c" +off=52 header_value complete +off=52 len=17 span[header_field]="Transfer-Encoding" +off=70 header_field complete +off=71 len=7 span[header_value]="chunked" +off=80 header_value complete +off=82 headers complete status=200 v=1/1 flags=21c content_length=0 +off=85 chunk header len=2 +off=85 len=2 span[body]="bo" +off=89 chunk complete +off=92 chunk header len=2 +off=92 len=2 span[body]="dy" +off=96 chunk complete +off=99 chunk header len=0 +off=101 chunk complete +off=101 message complete +``` + +## HTTP 304 with Content-Length + + +```http +HTTP/1.1 304 Not Modified +Content-Length: 10 + + +HTTP/1.1 200 OK +Content-Length: 5 + +hello +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=12 span[status]="Not Modified" +off=27 status complete +off=27 len=14 span[header_field]="Content-Length" +off=42 header_field complete +off=43 len=2 span[header_value]="10" +off=47 header_value complete +off=49 headers complete status=304 v=1/1 flags=20 content_length=10 +off=49 message complete +off=51 reset +off=51 message begin +off=56 len=3 span[version]="1.1" +off=59 version complete +off=64 len=2 span[status]="OK" +off=68 status complete +off=68 len=14 span[header_field]="Content-Length" +off=83 header_field complete +off=84 len=1 span[header_value]="5" +off=87 header_value complete +off=89 headers complete status=200 v=1/1 flags=20 content_length=5 +off=89 len=5 span[body]="hello" +off=94 message complete +``` + +## HTTP 304 with Transfer-Encoding + + +```http +HTTP/1.1 304 Not Modified +Transfer-Encoding: chunked + +HTTP/1.1 200 OK +Transfer-Encoding: chunked + +5 +hello +0 + +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=12 span[status]="Not Modified" +off=27 status complete +off=27 len=17 span[header_field]="Transfer-Encoding" +off=45 header_field complete +off=46 len=7 span[header_value]="chunked" +off=55 header_value complete +off=57 headers complete status=304 v=1/1 flags=208 content_length=0 +off=57 message complete +off=57 reset +off=57 message begin +off=62 len=3 span[version]="1.1" +off=65 version complete +off=70 len=2 span[status]="OK" +off=74 status complete +off=74 len=17 span[header_field]="Transfer-Encoding" +off=92 header_field complete +off=93 len=7 span[header_value]="chunked" +off=102 header_value complete +off=104 headers complete status=200 v=1/1 flags=208 content_length=0 +off=107 chunk header len=5 +off=107 len=5 span[body]="hello" +off=114 chunk complete +off=117 chunk header len=0 +``` + +## HTTP 100 first, then 400 + + +```http +HTTP/1.1 100 Continue + + +HTTP/1.1 404 Not Found +Content-Type: text/plain; charset=utf-8 +Content-Length: 14 +Date: Fri, 15 Sep 2023 19:47:23 GMT +Server: Python/3.10 aiohttp/4.0.0a2.dev0 + +404: Not Found +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=8 span[status]="Continue" +off=23 status complete +off=25 headers complete status=100 v=1/1 flags=0 content_length=0 +off=25 message complete +off=27 reset +off=27 message begin +off=32 len=3 span[version]="1.1" +off=35 version complete +off=40 len=9 span[status]="Not Found" +off=51 status complete +off=51 len=12 span[header_field]="Content-Type" +off=64 header_field complete +off=65 len=25 span[header_value]="text/plain; charset=utf-8" +off=92 header_value complete +off=92 len=14 span[header_field]="Content-Length" +off=107 header_field complete +off=108 len=2 span[header_value]="14" +off=112 header_value complete +off=112 len=4 span[header_field]="Date" +off=117 header_field complete +off=118 len=29 span[header_value]="Fri, 15 Sep 2023 19:47:23 GMT" +off=149 header_value complete +off=149 len=6 span[header_field]="Server" +off=156 header_field complete +off=157 len=32 span[header_value]="Python/3.10 aiohttp/4.0.0a2.dev0" +off=191 header_value complete +off=193 headers complete status=404 v=1/1 flags=20 content_length=14 +off=193 len=14 span[body]="404: Not Found" +off=207 message complete +``` + +## HTTP 103 first, then 200 + + +```http +HTTP/1.1 103 Early Hints +Link: ; rel=preload; as=style + +HTTP/1.1 200 OK +Date: Wed, 13 Sep 2023 11:09:41 GMT +Connection: keep-alive +Keep-Alive: timeout=5 +Content-Length: 17 + +response content +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=11 span[status]="Early Hints" +off=26 status complete +off=26 len=4 span[header_field]="Link" +off=31 header_field complete +off=32 len=36 span[header_value]="; rel=preload; as=style" +off=70 header_value complete +off=72 headers complete status=103 v=1/1 flags=0 content_length=0 +off=72 message complete +off=72 reset +off=72 message begin +off=77 len=3 span[version]="1.1" +off=80 version complete +off=85 len=2 span[status]="OK" +off=89 status complete +off=89 len=4 span[header_field]="Date" +off=94 header_field complete +off=95 len=29 span[header_value]="Wed, 13 Sep 2023 11:09:41 GMT" +off=126 header_value complete +off=126 len=10 span[header_field]="Connection" +off=137 header_field complete +off=138 len=10 span[header_value]="keep-alive" +off=150 header_value complete +off=150 len=10 span[header_field]="Keep-Alive" +off=161 header_field complete +off=162 len=9 span[header_value]="timeout=5" +off=173 header_value complete +off=173 len=14 span[header_field]="Content-Length" +off=188 header_field complete +off=189 len=2 span[header_value]="17" +off=193 header_value complete +off=195 headers complete status=200 v=1/1 flags=21 content_length=17 +off=195 len=16 span[body]="response content" +``` \ No newline at end of file diff --git a/vendor/llhttp/test/response/content-length.md b/vendor/llhttp/test/response/content-length.md new file mode 100644 index 0000000..6c33924 --- /dev/null +++ b/vendor/llhttp/test/response/content-length.md @@ -0,0 +1,158 @@ +Content-Length header +===================== + +## Response without `Content-Length`, but with body + +The client should wait for the server's EOF. That is, when +`Content-Length` is not specified, and `Connection: close`, the end of body is +specified by the EOF. + +_(Compare with APACHEBENCH_GET)_ + + +```http +HTTP/1.1 200 OK +Date: Tue, 04 Aug 2009 07:59:32 GMT +Server: Apache +X-Powered-By: Servlet/2.5 JSP/2.1 +Content-Type: text/xml; charset=utf-8 +Connection: close + +\n\ +\n\ + \n\ + \n\ + SOAP-ENV:Client\n\ + Client Error\n\ + \n\ + \n\ + +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=2 span[status]="OK" +off=17 status complete +off=17 len=4 span[header_field]="Date" +off=22 header_field complete +off=23 len=29 span[header_value]="Tue, 04 Aug 2009 07:59:32 GMT" +off=54 header_value complete +off=54 len=6 span[header_field]="Server" +off=61 header_field complete +off=62 len=6 span[header_value]="Apache" +off=70 header_value complete +off=70 len=12 span[header_field]="X-Powered-By" +off=83 header_field complete +off=84 len=19 span[header_value]="Servlet/2.5 JSP/2.1" +off=105 header_value complete +off=105 len=12 span[header_field]="Content-Type" +off=118 header_field complete +off=119 len=23 span[header_value]="text/xml; charset=utf-8" +off=144 header_value complete +off=144 len=10 span[header_field]="Connection" +off=155 header_field complete +off=156 len=5 span[header_value]="close" +off=163 header_value complete +off=165 headers complete status=200 v=1/1 flags=2 content_length=0 +off=165 len=42 span[body]="" +off=207 len=1 span[body]=lf +off=208 len=80 span[body]="" +off=288 len=1 span[body]=lf +off=289 len=17 span[body]=" " +off=306 len=1 span[body]=lf +off=307 len=20 span[body]=" " +off=327 len=1 span[body]=lf +off=328 len=45 span[body]=" SOAP-ENV:Client" +off=373 len=1 span[body]=lf +off=374 len=46 span[body]=" Client Error" +off=420 len=1 span[body]=lf +off=421 len=21 span[body]=" " +off=442 len=1 span[body]=lf +off=443 len=18 span[body]=" " +off=461 len=1 span[body]=lf +off=462 len=20 span[body]="" +``` + +## Content-Length-X + +The header that starts with `Content-Length*` should not be treated as +`Content-Length`. + + +```http +HTTP/1.1 200 OK +Content-Length-X: 0 +Transfer-Encoding: chunked + +2 +OK +0 + + +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=2 span[status]="OK" +off=17 status complete +off=17 len=16 span[header_field]="Content-Length-X" +off=34 header_field complete +off=35 len=1 span[header_value]="0" +off=38 header_value complete +off=38 len=17 span[header_field]="Transfer-Encoding" +off=56 header_field complete +off=57 len=7 span[header_value]="chunked" +off=66 header_value complete +off=68 headers complete status=200 v=1/1 flags=208 content_length=0 +off=71 chunk header len=2 +off=71 len=2 span[body]="OK" +off=75 chunk complete +off=78 chunk header len=0 +off=80 chunk complete +off=80 message complete +``` + +## Content-Length reset when no body is received + + +```http +HTTP/1.1 200 OK +Content-Length: 123 + +HTTP/1.1 200 OK +Content-Length: 456 + + +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=2 span[status]="OK" +off=17 status complete +off=17 len=14 span[header_field]="Content-Length" +off=32 header_field complete +off=33 len=3 span[header_value]="123" +off=38 header_value complete +off=40 headers complete status=200 v=1/1 flags=20 content_length=123 +off=40 skip body +off=40 message complete +off=40 reset +off=40 message begin +off=45 len=3 span[version]="1.1" +off=48 version complete +off=53 len=2 span[status]="OK" +off=57 status complete +off=57 len=14 span[header_field]="Content-Length" +off=72 header_field complete +off=73 len=3 span[header_value]="456" +off=78 header_value complete +off=80 headers complete status=200 v=1/1 flags=20 content_length=456 +off=80 skip body +off=80 message complete +``` diff --git a/vendor/llhttp/test/response/finish.md b/vendor/llhttp/test/response/finish.md new file mode 100644 index 0000000..2938b83 --- /dev/null +++ b/vendor/llhttp/test/response/finish.md @@ -0,0 +1,23 @@ +Finish +====== + +Those tests check the return codes and the behavior of `llhttp_finish()` C API. + +## It should be safe to finish with cb after empty response + + +```http +HTTP/1.1 200 OK + + +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=2 span[status]="OK" +off=17 status complete +off=19 headers complete status=200 v=1/1 flags=0 content_length=0 +off=NULL finish=1 +``` diff --git a/vendor/llhttp/test/response/invalid.md b/vendor/llhttp/test/response/invalid.md new file mode 100644 index 0000000..034fc4d --- /dev/null +++ b/vendor/llhttp/test/response/invalid.md @@ -0,0 +1,285 @@ +Invalid responses +================= + +### Incomplete HTTP protocol + + +```http +HTP/1.1 200 OK + + +``` + +```log +off=0 message begin +off=2 error code=8 reason="Expected HTTP/" +``` + +### Extra digit in HTTP major version + + +```http +HTTP/01.1 200 OK + + +``` + +```log +off=0 message begin +off=5 len=1 span[version]="0" +off=6 error code=9 reason="Expected dot" +``` + +### Extra digit in HTTP major version #2 + + +```http +HTTP/11.1 200 OK + + +``` + +```log +off=0 message begin +off=5 len=1 span[version]="1" +off=6 error code=9 reason="Expected dot" +``` + +### Extra digit in HTTP minor version + + +```http +HTTP/1.01 200 OK + + +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.0" +off=8 version complete +off=8 error code=9 reason="Expected space after version" +``` +--> + +### Tab after HTTP version + + +```http +HTTP/1.1\t200 OK + + +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=8 error code=9 reason="Expected space after version" +``` + +### CR before response and tab after HTTP version + + +```http +\rHTTP/1.1\t200 OK + + +``` + +```log +off=1 message begin +off=6 len=3 span[version]="1.1" +off=9 version complete +off=9 error code=9 reason="Expected space after version" +``` + +### Headers separated by CR + + +```http +HTTP/1.1 200 OK +Foo: 1\rBar: 2 + + +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=2 span[status]="OK" +off=17 status complete +off=17 len=3 span[header_field]="Foo" +off=21 header_field complete +off=22 len=1 span[header_value]="1" +off=24 error code=3 reason="Missing expected LF after header value" +``` + +### Invalid HTTP version + + +```http +HTTP/5.6 200 OK + + +``` + +```log +off=0 message begin +off=5 len=3 span[version]="5.6" +off=8 error code=9 reason="Invalid HTTP version" +``` + +## Invalid space after start line + + +```http +HTTP/1.1 200 OK + Host: foo +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=2 span[status]="OK" +off=17 status complete +off=18 error code=30 reason="Unexpected space after start line" +``` + +### Extra space between HTTP version and status code + + +```http +HTTP/1.1 200 OK + + +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=9 error code=13 reason="Invalid status code" +``` + +### Extra space between status code and reason + + +```http +HTTP/1.1 200 OK + + +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=3 span[status]=" OK" +off=18 status complete +off=20 headers complete status=200 v=1/1 flags=0 content_length=0 +``` + +### One-digit status code + + +```http +HTTP/1.1 2 OK + + +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=10 error code=13 reason="Invalid status code" +``` + +### Only LFs present and no body + + +```http +HTTP/1.1 200 OK\nContent-Length: 0\n\n +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=2 span[status]="OK" +off=16 error code=25 reason="Missing expected CR after response line" +``` + +### Only LFs present and no body (lenient) + + +```http +HTTP/1.1 200 OK\nContent-Length: 0\n\n +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=2 span[status]="OK" +off=16 status complete +off=16 len=14 span[header_field]="Content-Length" +off=31 header_field complete +off=32 len=1 span[header_value]="0" +off=34 header_value complete +off=35 headers complete status=200 v=1/1 flags=20 content_length=0 +off=35 message complete +``` + +### Only LFs present + + +```http +HTTP/1.1 200 OK\n\ +Foo: abc\n\ +Bar: def\n\ +\n\ +BODY\n\ +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=2 span[status]="OK" +off=16 error code=25 reason="Missing expected CR after response line" +``` + +### Only LFs present (lenient) + + +```http +HTTP/1.1 200 OK\n\ +Foo: abc\n\ +Bar: def\n\ +\n\ +BODY\n\ +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=2 span[status]="OK" +off=16 status complete +off=16 len=3 span[header_field]="Foo" +off=20 header_field complete +off=21 len=3 span[header_value]="abc" +off=25 header_value complete +off=25 len=3 span[header_field]="Bar" +off=29 header_field complete +off=30 len=3 span[header_value]="def" +off=34 header_value complete +off=35 headers complete status=200 v=1/1 flags=0 content_length=0 +off=35 len=4 span[body]="BODY" +off=39 len=1 span[body]=lf +off=40 len=1 span[body]="\" +``` \ No newline at end of file diff --git a/vendor/llhttp/test/response/lenient-version.md b/vendor/llhttp/test/response/lenient-version.md new file mode 100644 index 0000000..86c6ede --- /dev/null +++ b/vendor/llhttp/test/response/lenient-version.md @@ -0,0 +1,20 @@ +Lenient HTTP version parsing +============================ + +### Invalid HTTP version (lenient) + + +```http +HTTP/5.6 200 OK + + +``` + +```log +off=0 message begin +off=5 len=3 span[version]="5.6" +off=8 version complete +off=13 len=2 span[status]="OK" +off=17 status complete +off=19 headers complete status=200 v=5/6 flags=0 content_length=0 +``` diff --git a/vendor/llhttp/test/response/pausing.md b/vendor/llhttp/test/response/pausing.md new file mode 100644 index 0000000..d2e870b --- /dev/null +++ b/vendor/llhttp/test/response/pausing.md @@ -0,0 +1,330 @@ +Pausing +======= + +### on_message_begin + + +```http +HTTP/1.1 200 OK +Content-Length: 3 + +abc +``` + +```log +off=0 message begin +off=0 pause +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=2 span[status]="OK" +off=17 status complete +off=17 len=14 span[header_field]="Content-Length" +off=32 header_field complete +off=33 len=1 span[header_value]="3" +off=36 header_value complete +off=38 headers complete status=200 v=1/1 flags=20 content_length=3 +off=38 len=3 span[body]="abc" +off=41 message complete +``` + +### on_message_complete + + +```http +HTTP/1.1 200 OK +Content-Length: 3 + +abc +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=2 span[status]="OK" +off=17 status complete +off=17 len=14 span[header_field]="Content-Length" +off=32 header_field complete +off=33 len=1 span[header_value]="3" +off=36 header_value complete +off=38 headers complete status=200 v=1/1 flags=20 content_length=3 +off=38 len=3 span[body]="abc" +off=41 message complete +off=41 pause +``` + +### on_version_complete + + +```http +HTTP/1.1 200 OK +Content-Length: 3 + +abc +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=8 pause +off=13 len=2 span[status]="OK" +off=17 status complete +off=17 len=14 span[header_field]="Content-Length" +off=32 header_field complete +off=33 len=1 span[header_value]="3" +off=36 header_value complete +off=38 headers complete status=200 v=1/1 flags=20 content_length=3 +off=38 len=3 span[body]="abc" +off=41 message complete +``` + +### on_status_complete + + +```http +HTTP/1.1 200 OK +Content-Length: 3 + +abc +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=2 span[status]="OK" +off=17 status complete +off=17 pause +off=17 len=14 span[header_field]="Content-Length" +off=32 header_field complete +off=33 len=1 span[header_value]="3" +off=36 header_value complete +off=38 headers complete status=200 v=1/1 flags=20 content_length=3 +off=38 len=3 span[body]="abc" +off=41 message complete +``` + +### on_header_field_complete + + +```http +HTTP/1.1 200 OK +Content-Length: 3 + +abc +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=2 span[status]="OK" +off=17 status complete +off=17 len=14 span[header_field]="Content-Length" +off=32 header_field complete +off=32 pause +off=33 len=1 span[header_value]="3" +off=36 header_value complete +off=38 headers complete status=200 v=1/1 flags=20 content_length=3 +off=38 len=3 span[body]="abc" +off=41 message complete +``` + +### on_header_value_complete + + +```http +HTTP/1.1 200 OK +Content-Length: 3 + +abc +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=2 span[status]="OK" +off=17 status complete +off=17 len=14 span[header_field]="Content-Length" +off=32 header_field complete +off=33 len=1 span[header_value]="3" +off=36 header_value complete +off=36 pause +off=38 headers complete status=200 v=1/1 flags=20 content_length=3 +off=38 len=3 span[body]="abc" +off=41 message complete +``` + +### on_headers_complete + + +```http +HTTP/1.1 200 OK +Content-Length: 3 + +abc +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=2 span[status]="OK" +off=17 status complete +off=17 len=14 span[header_field]="Content-Length" +off=32 header_field complete +off=33 len=1 span[header_value]="3" +off=36 header_value complete +off=38 headers complete status=200 v=1/1 flags=20 content_length=3 +off=38 pause +off=38 len=3 span[body]="abc" +off=41 message complete +``` + +### on_chunk_header + + +```http +HTTP/1.1 200 OK +Transfer-Encoding: chunked + +a +0123456789 +0 + + +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=2 span[status]="OK" +off=17 status complete +off=17 len=17 span[header_field]="Transfer-Encoding" +off=35 header_field complete +off=36 len=7 span[header_value]="chunked" +off=45 header_value complete +off=47 headers complete status=200 v=1/1 flags=208 content_length=0 +off=50 chunk header len=10 +off=50 pause +off=50 len=10 span[body]="0123456789" +off=62 chunk complete +off=65 chunk header len=0 +off=65 pause +off=67 chunk complete +off=67 message complete +``` + +### on_chunk_extension_name + + +```http +HTTP/1.1 200 OK +Transfer-Encoding: chunked + +a;foo=bar +0123456789 +0 + + +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=2 span[status]="OK" +off=17 status complete +off=17 len=17 span[header_field]="Transfer-Encoding" +off=35 header_field complete +off=36 len=7 span[header_value]="chunked" +off=45 header_value complete +off=47 headers complete status=200 v=1/1 flags=208 content_length=0 +off=49 len=3 span[chunk_extension_name]="foo" +off=53 chunk_extension_name complete +off=53 pause +off=53 len=3 span[chunk_extension_value]="bar" +off=57 chunk_extension_value complete +off=58 chunk header len=10 +off=58 len=10 span[body]="0123456789" +off=70 chunk complete +off=73 chunk header len=0 +off=75 chunk complete +off=75 message complete +``` + +### on_chunk_extension_value + + +```http +HTTP/1.1 200 OK +Transfer-Encoding: chunked + +a;foo=bar +0123456789 +0 + + +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=2 span[status]="OK" +off=17 status complete +off=17 len=17 span[header_field]="Transfer-Encoding" +off=35 header_field complete +off=36 len=7 span[header_value]="chunked" +off=45 header_value complete +off=47 headers complete status=200 v=1/1 flags=208 content_length=0 +off=49 len=3 span[chunk_extension_name]="foo" +off=53 chunk_extension_name complete +off=53 len=3 span[chunk_extension_value]="bar" +off=57 chunk_extension_value complete +off=57 pause +off=58 chunk header len=10 +off=58 len=10 span[body]="0123456789" +off=70 chunk complete +off=73 chunk header len=0 +off=75 chunk complete +off=75 message complete +``` + +### on_chunk_complete + + +```http +HTTP/1.1 200 OK +Transfer-Encoding: chunked + +a +0123456789 +0 + + +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=2 span[status]="OK" +off=17 status complete +off=17 len=17 span[header_field]="Transfer-Encoding" +off=35 header_field complete +off=36 len=7 span[header_value]="chunked" +off=45 header_value complete +off=47 headers complete status=200 v=1/1 flags=208 content_length=0 +off=50 chunk header len=10 +off=50 len=10 span[body]="0123456789" +off=62 chunk complete +off=62 pause +off=65 chunk header len=0 +off=67 chunk complete +off=67 pause +off=67 message complete +``` diff --git a/vendor/llhttp/test/response/pipelining.md b/vendor/llhttp/test/response/pipelining.md new file mode 100644 index 0000000..01e007a --- /dev/null +++ b/vendor/llhttp/test/response/pipelining.md @@ -0,0 +1,60 @@ +Pipelining +========== + +## Should parse multiple events + + +```http +HTTP/1.1 200 OK +Content-Length: 3 + +AAA +HTTP/1.1 201 Created +Content-Length: 4 + +BBBB +HTTP/1.1 202 Accepted +Content-Length: 5 + +CCCC +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=2 span[status]="OK" +off=17 status complete +off=17 len=14 span[header_field]="Content-Length" +off=32 header_field complete +off=33 len=1 span[header_value]="3" +off=36 header_value complete +off=38 headers complete status=200 v=1/1 flags=20 content_length=3 +off=38 len=3 span[body]="AAA" +off=41 message complete +off=43 reset +off=43 message begin +off=48 len=3 span[version]="1.1" +off=51 version complete +off=56 len=7 span[status]="Created" +off=65 status complete +off=65 len=14 span[header_field]="Content-Length" +off=80 header_field complete +off=81 len=1 span[header_value]="4" +off=84 header_value complete +off=86 headers complete status=201 v=1/1 flags=20 content_length=4 +off=86 len=4 span[body]="BBBB" +off=90 message complete +off=92 reset +off=92 message begin +off=97 len=3 span[version]="1.1" +off=100 version complete +off=105 len=8 span[status]="Accepted" +off=115 status complete +off=115 len=14 span[header_field]="Content-Length" +off=130 header_field complete +off=131 len=1 span[header_value]="5" +off=134 header_value complete +off=136 headers complete status=202 v=1/1 flags=20 content_length=5 +off=136 len=4 span[body]="CCCC" +``` \ No newline at end of file diff --git a/vendor/llhttp/test/response/sample.md b/vendor/llhttp/test/response/sample.md new file mode 100644 index 0000000..be2e82d --- /dev/null +++ b/vendor/llhttp/test/response/sample.md @@ -0,0 +1,653 @@ +Sample responses +================ + +## Simple response + + +```http +HTTP/1.1 200 OK +Header1: Value1 +Header2:\t Value2 +Content-Length: 0 + + +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=2 span[status]="OK" +off=17 status complete +off=17 len=7 span[header_field]="Header1" +off=25 header_field complete +off=26 len=6 span[header_value]="Value1" +off=34 header_value complete +off=34 len=7 span[header_field]="Header2" +off=42 header_field complete +off=44 len=6 span[header_value]="Value2" +off=52 header_value complete +off=52 len=14 span[header_field]="Content-Length" +off=67 header_field complete +off=68 len=1 span[header_value]="0" +off=71 header_value complete +off=73 headers complete status=200 v=1/1 flags=20 content_length=0 +off=73 message complete +``` + +## Error on invalid response start + +Every response must start with `HTTP/`. + + +```http +HTTPER/1.1 200 OK + + +``` + +```log +off=0 message begin +off=4 error code=8 reason="Expected HTTP/" +``` + +## Empty body should not trigger spurious span callbacks + + +```http +HTTP/1.1 200 OK + + +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=2 span[status]="OK" +off=17 status complete +off=19 headers complete status=200 v=1/1 flags=0 content_length=0 +``` + +## Google 301 + + +```http +HTTP/1.1 301 Moved Permanently +Location: http://www.google.com/ +Content-Type: text/html; charset=UTF-8 +Date: Sun, 26 Apr 2009 11:11:49 GMT +Expires: Tue, 26 May 2009 11:11:49 GMT +X-$PrototypeBI-Version: 1.6.0.3 +Cache-Control: public, max-age=2592000 +Server: gws +Content-Length: 219 + +\n\ +301 Moved\n\ +

301 Moved

\n\ +The document has moved\n\ +here. + +``` +_(Note the `$` char in header field)_ + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=17 span[status]="Moved Permanently" +off=32 status complete +off=32 len=8 span[header_field]="Location" +off=41 header_field complete +off=42 len=22 span[header_value]="http://www.google.com/" +off=66 header_value complete +off=66 len=12 span[header_field]="Content-Type" +off=79 header_field complete +off=80 len=24 span[header_value]="text/html; charset=UTF-8" +off=106 header_value complete +off=106 len=4 span[header_field]="Date" +off=111 header_field complete +off=112 len=29 span[header_value]="Sun, 26 Apr 2009 11:11:49 GMT" +off=143 header_value complete +off=143 len=7 span[header_field]="Expires" +off=151 header_field complete +off=152 len=29 span[header_value]="Tue, 26 May 2009 11:11:49 GMT" +off=183 header_value complete +off=183 len=22 span[header_field]="X-$PrototypeBI-Version" +off=206 header_field complete +off=207 len=7 span[header_value]="1.6.0.3" +off=216 header_value complete +off=216 len=13 span[header_field]="Cache-Control" +off=230 header_field complete +off=231 len=23 span[header_value]="public, max-age=2592000" +off=256 header_value complete +off=256 len=6 span[header_field]="Server" +off=263 header_field complete +off=264 len=3 span[header_value]="gws" +off=269 header_value complete +off=269 len=14 span[header_field]="Content-Length" +off=284 header_field complete +off=286 len=5 span[header_value]="219 " +off=293 header_value complete +off=295 headers complete status=301 v=1/1 flags=20 content_length=219 +off=295 len=74 span[body]="" +off=369 len=1 span[body]=lf +off=370 len=37 span[body]="301 Moved" +off=407 len=1 span[body]=lf +off=408 len=18 span[body]="

301 Moved

" +off=426 len=1 span[body]=lf +off=427 len=22 span[body]="The document has moved" +off=449 len=1 span[body]=lf +off=450 len=42 span[body]="here." +off=492 len=1 span[body]=cr +off=493 len=1 span[body]=lf +off=494 len=14 span[body]="" +``` + +## amazon.com + + +```http +HTTP/1.1 301 MovedPermanently +Date: Wed, 15 May 2013 17:06:33 GMT +Server: Server +x-amz-id-1: 0GPHKXSJQ826RK7GZEB2 +p3p: policyref="http://www.amazon.com/w3c/p3p.xml",CP="CAO DSP LAW CUR ADM IVAo IVDo CONo OTPo OUR DELi PUBi OTRi BUS PHY ONL UNI PUR FIN COM NAV INT DEM CNT STA HEA PRE LOC GOV OTC " +x-amz-id-2: STN69VZxIFSz9YJLbz1GDbxpbjG6Qjmmq5E3DxRhOUw+Et0p4hr7c/Q8qNcx4oAD +Location: http://www.amazon.com/Dan-Brown/e/B000AP9DSU/ref=s9_pop_gw_al1?_encoding=UTF8&refinementId=618073011&pf_rd_m=ATVPDKIKX0DER&pf_rd_s=center-2&pf_rd_r=0SHYY5BZXN3KR20BNFAY&pf_rd_t=101&pf_rd_p=1263340922&pf_rd_i=507846 +Vary: Accept-Encoding,User-Agent +Content-Type: text/html; charset=ISO-8859-1 +Transfer-Encoding: chunked + +1 +\n +0 + + +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=16 span[status]="MovedPermanently" +off=31 status complete +off=31 len=4 span[header_field]="Date" +off=36 header_field complete +off=37 len=29 span[header_value]="Wed, 15 May 2013 17:06:33 GMT" +off=68 header_value complete +off=68 len=6 span[header_field]="Server" +off=75 header_field complete +off=76 len=6 span[header_value]="Server" +off=84 header_value complete +off=84 len=10 span[header_field]="x-amz-id-1" +off=95 header_field complete +off=96 len=20 span[header_value]="0GPHKXSJQ826RK7GZEB2" +off=118 header_value complete +off=118 len=3 span[header_field]="p3p" +off=122 header_field complete +off=123 len=178 span[header_value]="policyref="http://www.amazon.com/w3c/p3p.xml",CP="CAO DSP LAW CUR ADM IVAo IVDo CONo OTPo OUR DELi PUBi OTRi BUS PHY ONL UNI PUR FIN COM NAV INT DEM CNT STA HEA PRE LOC GOV OTC "" +off=303 header_value complete +off=303 len=10 span[header_field]="x-amz-id-2" +off=314 header_field complete +off=315 len=64 span[header_value]="STN69VZxIFSz9YJLbz1GDbxpbjG6Qjmmq5E3DxRhOUw+Et0p4hr7c/Q8qNcx4oAD" +off=381 header_value complete +off=381 len=8 span[header_field]="Location" +off=390 header_field complete +off=391 len=214 span[header_value]="http://www.amazon.com/Dan-Brown/e/B000AP9DSU/ref=s9_pop_gw_al1?_encoding=UTF8&refinementId=618073011&pf_rd_m=ATVPDKIKX0DER&pf_rd_s=center-2&pf_rd_r=0SHYY5BZXN3KR20BNFAY&pf_rd_t=101&pf_rd_p=1263340922&pf_rd_i=507846" +off=607 header_value complete +off=607 len=4 span[header_field]="Vary" +off=612 header_field complete +off=613 len=26 span[header_value]="Accept-Encoding,User-Agent" +off=641 header_value complete +off=641 len=12 span[header_field]="Content-Type" +off=654 header_field complete +off=655 len=29 span[header_value]="text/html; charset=ISO-8859-1" +off=686 header_value complete +off=686 len=17 span[header_field]="Transfer-Encoding" +off=704 header_field complete +off=705 len=7 span[header_value]="chunked" +off=714 header_value complete +off=716 headers complete status=301 v=1/1 flags=208 content_length=0 +off=719 chunk header len=1 +off=719 len=1 span[body]=lf +off=722 chunk complete +off=725 chunk header len=0 +off=727 chunk complete +off=727 message complete +``` + +## No headers and no body + + +```http +HTTP/1.1 404 Not Found + + +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=9 span[status]="Not Found" +off=24 status complete +off=26 headers complete status=404 v=1/1 flags=0 content_length=0 +``` + +## No reason phrase + + +```http +HTTP/1.1 301 + + +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=14 status complete +off=16 headers complete status=301 v=1/1 flags=0 content_length=0 +``` + +## Empty reason phrase after space + + +```http +HTTP/1.1 200 \r\n\ + + +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=0 span[status]="" +off=15 status complete +off=17 headers complete status=200 v=1/1 flags=0 content_length=0 +``` + +## No carriage ret + + +```http +HTTP/1.1 200 OK\n\ +Content-Type: text/html; charset=utf-8\n\ +Connection: close\n\ +\n\ +these headers are from http://news.ycombinator.com/ +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=2 span[status]="OK" +off=16 error code=25 reason="Missing expected CR after response line" +``` + +## No carriage ret (lenient) + + +```http +HTTP/1.1 200 OK\n\ +Content-Type: text/html; charset=utf-8\n\ +Connection: close\n\ +\n\ +these headers are from http://news.ycombinator.com/ +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=2 span[status]="OK" +off=16 status complete +off=16 len=12 span[header_field]="Content-Type" +off=29 header_field complete +off=30 len=24 span[header_value]="text/html; charset=utf-8" +off=55 header_value complete +off=55 len=10 span[header_field]="Connection" +off=66 header_field complete +off=67 len=5 span[header_value]="close" +off=73 header_value complete +off=74 headers complete status=200 v=1/1 flags=2 content_length=0 +off=74 len=51 span[body]="these headers are from http://news.ycombinator.com/" +``` + +## Underscore in header key + +Shown by: `curl -o /dev/null -v "http://ad.doubleclick.net/pfadx/DARTSHELLCONFIGXML;dcmt=text/xml;"` + + +```http +HTTP/1.1 200 OK +Server: DCLK-AdSvr +Content-Type: text/xml +Content-Length: 0 +DCLK_imp: v7;x;114750856;0-0;0;17820020;0/0;21603567/21621457/1;;~okv=;dcmt=text/xml;;~cs=o + + +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=2 span[status]="OK" +off=17 status complete +off=17 len=6 span[header_field]="Server" +off=24 header_field complete +off=25 len=10 span[header_value]="DCLK-AdSvr" +off=37 header_value complete +off=37 len=12 span[header_field]="Content-Type" +off=50 header_field complete +off=51 len=8 span[header_value]="text/xml" +off=61 header_value complete +off=61 len=14 span[header_field]="Content-Length" +off=76 header_field complete +off=77 len=1 span[header_value]="0" +off=80 header_value complete +off=80 len=8 span[header_field]="DCLK_imp" +off=89 header_field complete +off=90 len=81 span[header_value]="v7;x;114750856;0-0;0;17820020;0/0;21603567/21621457/1;;~okv=;dcmt=text/xml;;~cs=o" +off=173 header_value complete +off=175 headers complete status=200 v=1/1 flags=20 content_length=0 +off=175 message complete +``` + +## bonjourmadame.fr + +The client should not merge two headers fields when the first one doesn't +have a value. + + +```http +HTTP/1.0 301 Moved Permanently +Date: Thu, 03 Jun 2010 09:56:32 GMT +Server: Apache/2.2.3 (Red Hat) +Cache-Control: public +Pragma: \r\n\ +Location: http://www.bonjourmadame.fr/ +Vary: Accept-Encoding +Content-Length: 0 +Content-Type: text/html; charset=UTF-8 +Connection: keep-alive + + +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.0" +off=8 version complete +off=13 len=17 span[status]="Moved Permanently" +off=32 status complete +off=32 len=4 span[header_field]="Date" +off=37 header_field complete +off=38 len=29 span[header_value]="Thu, 03 Jun 2010 09:56:32 GMT" +off=69 header_value complete +off=69 len=6 span[header_field]="Server" +off=76 header_field complete +off=77 len=22 span[header_value]="Apache/2.2.3 (Red Hat)" +off=101 header_value complete +off=101 len=13 span[header_field]="Cache-Control" +off=115 header_field complete +off=116 len=6 span[header_value]="public" +off=124 header_value complete +off=124 len=6 span[header_field]="Pragma" +off=131 header_field complete +off=134 len=0 span[header_value]="" +off=134 header_value complete +off=134 len=8 span[header_field]="Location" +off=143 header_field complete +off=144 len=28 span[header_value]="http://www.bonjourmadame.fr/" +off=174 header_value complete +off=174 len=4 span[header_field]="Vary" +off=179 header_field complete +off=180 len=15 span[header_value]="Accept-Encoding" +off=197 header_value complete +off=197 len=14 span[header_field]="Content-Length" +off=212 header_field complete +off=213 len=1 span[header_value]="0" +off=216 header_value complete +off=216 len=12 span[header_field]="Content-Type" +off=229 header_field complete +off=230 len=24 span[header_value]="text/html; charset=UTF-8" +off=256 header_value complete +off=256 len=10 span[header_field]="Connection" +off=267 header_field complete +off=268 len=10 span[header_value]="keep-alive" +off=280 header_value complete +off=282 headers complete status=301 v=1/0 flags=21 content_length=0 +off=282 message complete +``` + +## Spaces in header value + + +```http +HTTP/1.1 200 OK +Date: Tue, 28 Sep 2010 01:14:13 GMT +Server: Apache +Cache-Control: no-cache, must-revalidate +Expires: Mon, 26 Jul 1997 05:00:00 GMT +.et-Cookie: PlaxoCS=1274804622353690521; path=/; domain=.plaxo.com +Vary: Accept-Encoding +_eep-Alive: timeout=45 +_onnection: Keep-Alive +Transfer-Encoding: chunked +Content-Type: text/html +Connection: close + +0 + + +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=2 span[status]="OK" +off=17 status complete +off=17 len=4 span[header_field]="Date" +off=22 header_field complete +off=23 len=29 span[header_value]="Tue, 28 Sep 2010 01:14:13 GMT" +off=54 header_value complete +off=54 len=6 span[header_field]="Server" +off=61 header_field complete +off=62 len=6 span[header_value]="Apache" +off=70 header_value complete +off=70 len=13 span[header_field]="Cache-Control" +off=84 header_field complete +off=85 len=25 span[header_value]="no-cache, must-revalidate" +off=112 header_value complete +off=112 len=7 span[header_field]="Expires" +off=120 header_field complete +off=121 len=29 span[header_value]="Mon, 26 Jul 1997 05:00:00 GMT" +off=152 header_value complete +off=152 len=10 span[header_field]=".et-Cookie" +off=163 header_field complete +off=164 len=54 span[header_value]="PlaxoCS=1274804622353690521; path=/; domain=.plaxo.com" +off=220 header_value complete +off=220 len=4 span[header_field]="Vary" +off=225 header_field complete +off=226 len=15 span[header_value]="Accept-Encoding" +off=243 header_value complete +off=243 len=10 span[header_field]="_eep-Alive" +off=254 header_field complete +off=255 len=10 span[header_value]="timeout=45" +off=267 header_value complete +off=267 len=10 span[header_field]="_onnection" +off=278 header_field complete +off=279 len=10 span[header_value]="Keep-Alive" +off=291 header_value complete +off=291 len=17 span[header_field]="Transfer-Encoding" +off=309 header_field complete +off=310 len=7 span[header_value]="chunked" +off=319 header_value complete +off=319 len=12 span[header_field]="Content-Type" +off=332 header_field complete +off=333 len=9 span[header_value]="text/html" +off=344 header_value complete +off=344 len=10 span[header_field]="Connection" +off=355 header_field complete +off=356 len=5 span[header_value]="close" +off=363 header_value complete +off=365 headers complete status=200 v=1/1 flags=20a content_length=0 +off=368 chunk header len=0 +off=370 chunk complete +off=370 message complete +``` + +## Spaces in header name + + +```http +HTTP/1.1 200 OK +Server: Microsoft-IIS/6.0 +X-Powered-By: ASP.NET +en-US Content-Type: text/xml +Content-Type: text/xml +Content-Length: 16 +Date: Fri, 23 Jul 2010 18:45:38 GMT +Connection: keep-alive + +hello +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=2 span[status]="OK" +off=17 status complete +off=17 len=6 span[header_field]="Server" +off=24 header_field complete +off=25 len=17 span[header_value]="Microsoft-IIS/6.0" +off=44 header_value complete +off=44 len=12 span[header_field]="X-Powered-By" +off=57 header_field complete +off=58 len=7 span[header_value]="ASP.NET" +off=67 header_value complete +off=72 error code=10 reason="Invalid header token" +``` + +## Non ASCII in status line + + +```http +HTTP/1.1 500 Oriëntatieprobleem +Date: Fri, 5 Nov 2010 23:07:12 GMT+2 +Content-Length: 0 +Connection: close + + +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=19 span[status]="Oriëntatieprobleem" +off=34 status complete +off=34 len=4 span[header_field]="Date" +off=39 header_field complete +off=40 len=30 span[header_value]="Fri, 5 Nov 2010 23:07:12 GMT+2" +off=72 header_value complete +off=72 len=14 span[header_field]="Content-Length" +off=87 header_field complete +off=88 len=1 span[header_value]="0" +off=91 header_value complete +off=91 len=10 span[header_field]="Connection" +off=102 header_field complete +off=103 len=5 span[header_value]="close" +off=110 header_value complete +off=112 headers complete status=500 v=1/1 flags=22 content_length=0 +off=112 message complete +``` + +## HTTP version 0.9 + + +```http +HTTP/0.9 200 OK + + +``` + +```log +off=0 message begin +off=5 len=3 span[version]="0.9" +off=8 version complete +off=13 len=2 span[status]="OK" +off=17 status complete +off=19 headers complete status=200 v=0/9 flags=0 content_length=0 +``` + +## No Content-Length, no Transfer-Encoding + +The client should wait for the server's EOF. That is, when neither +content-length nor transfer-encoding is specified, the end of body +is specified by the EOF. + + +```http +HTTP/1.1 200 OK +Content-Type: text/plain + +hello world +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=2 span[status]="OK" +off=17 status complete +off=17 len=12 span[header_field]="Content-Type" +off=30 header_field complete +off=31 len=10 span[header_value]="text/plain" +off=43 header_value complete +off=45 headers complete status=200 v=1/1 flags=0 content_length=0 +off=45 len=11 span[body]="hello world" +``` + +## Response starting with CRLF + + +```http +\r\nHTTP/1.1 200 OK +Header1: Value1 +Header2:\t Value2 +Content-Length: 0 + + +``` + +```log +off=2 message begin +off=7 len=3 span[version]="1.1" +off=10 version complete +off=15 len=2 span[status]="OK" +off=19 status complete +off=19 len=7 span[header_field]="Header1" +off=27 header_field complete +off=28 len=6 span[header_value]="Value1" +off=36 header_value complete +off=36 len=7 span[header_field]="Header2" +off=44 header_field complete +off=46 len=6 span[header_value]="Value2" +off=54 header_value complete +off=54 len=14 span[header_field]="Content-Length" +off=69 header_field complete +off=70 len=1 span[header_value]="0" +off=73 header_value complete +off=75 headers complete status=200 v=1/1 flags=20 content_length=0 +off=75 message complete +``` diff --git a/vendor/llhttp/test/response/transfer-encoding.md b/vendor/llhttp/test/response/transfer-encoding.md new file mode 100644 index 0000000..e1fd10a --- /dev/null +++ b/vendor/llhttp/test/response/transfer-encoding.md @@ -0,0 +1,410 @@ +Transfer-Encoding header +======================== + +## Trailing space on chunked body + + +```http +HTTP/1.1 200 OK +Content-Type: text/plain +Transfer-Encoding: chunked + +25 \r\n\ +This is the data in the first chunk + +1C +and this is the second one + +0 \r\n\ + + +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=2 span[status]="OK" +off=17 status complete +off=17 len=12 span[header_field]="Content-Type" +off=30 header_field complete +off=31 len=10 span[header_value]="text/plain" +off=43 header_value complete +off=43 len=17 span[header_field]="Transfer-Encoding" +off=61 header_field complete +off=62 len=7 span[header_value]="chunked" +off=71 header_value complete +off=73 headers complete status=200 v=1/1 flags=208 content_length=0 +off=76 error code=12 reason="Invalid character in chunk size" +``` + +## `chunked` before other transfer-encoding + + +```http +HTTP/1.1 200 OK +Accept: */* +Transfer-Encoding: chunked, deflate + +World +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=2 span[status]="OK" +off=17 status complete +off=17 len=6 span[header_field]="Accept" +off=24 header_field complete +off=25 len=3 span[header_value]="*/*" +off=30 header_value complete +off=30 len=17 span[header_field]="Transfer-Encoding" +off=48 header_field complete +off=49 len=16 span[header_value]="chunked, deflate" +off=67 header_value complete +off=69 headers complete status=200 v=1/1 flags=200 content_length=0 +off=69 len=5 span[body]="World" +``` + +## multiple transfer-encoding where chunked is not the last one + + +```http +HTTP/1.1 200 OK +Accept: */* +Transfer-Encoding: chunked +Transfer-Encoding: identity + +World +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=2 span[status]="OK" +off=17 status complete +off=17 len=6 span[header_field]="Accept" +off=24 header_field complete +off=25 len=3 span[header_value]="*/*" +off=30 header_value complete +off=30 len=17 span[header_field]="Transfer-Encoding" +off=48 header_field complete +off=49 len=7 span[header_value]="chunked" +off=58 header_value complete +off=58 len=17 span[header_field]="Transfer-Encoding" +off=76 header_field complete +off=77 len=8 span[header_value]="identity" +off=87 header_value complete +off=89 headers complete status=200 v=1/1 flags=200 content_length=0 +off=89 len=5 span[body]="World" +``` + +## `chunkedchunked` transfer-encoding does not enable chunked enconding + +This check that the word `chunked` repeat more than once (with or without spaces) does not mistakenly enables chunked encoding. + + +```http +HTTP/1.1 200 OK +Accept: */* +Transfer-Encoding: chunkedchunked + +2 +OK +0 + + +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=2 span[status]="OK" +off=17 status complete +off=17 len=6 span[header_field]="Accept" +off=24 header_field complete +off=25 len=3 span[header_value]="*/*" +off=30 header_value complete +off=30 len=17 span[header_field]="Transfer-Encoding" +off=48 header_field complete +off=49 len=14 span[header_value]="chunkedchunked" +off=65 header_value complete +off=67 headers complete status=200 v=1/1 flags=200 content_length=0 +off=67 len=1 span[body]="2" +off=68 len=1 span[body]=cr +off=69 len=1 span[body]=lf +off=70 len=2 span[body]="OK" +off=72 len=1 span[body]=cr +off=73 len=1 span[body]=lf +off=74 len=1 span[body]="0" +off=75 len=1 span[body]=cr +off=76 len=1 span[body]=lf +off=77 len=1 span[body]=cr +off=78 len=1 span[body]=lf +``` + +## Chunk extensions + + +```http +HTTP/1.1 200 OK +Host: localhost +Transfer-encoding: chunked + +5;ilovew3;somuchlove=aretheseparametersfor +hello +6;blahblah;blah + world +0 + + +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=2 span[status]="OK" +off=17 status complete +off=17 len=4 span[header_field]="Host" +off=22 header_field complete +off=23 len=9 span[header_value]="localhost" +off=34 header_value complete +off=34 len=17 span[header_field]="Transfer-encoding" +off=52 header_field complete +off=53 len=7 span[header_value]="chunked" +off=62 header_value complete +off=64 headers complete status=200 v=1/1 flags=208 content_length=0 +off=66 len=7 span[chunk_extension_name]="ilovew3" +off=74 chunk_extension_name complete +off=74 len=10 span[chunk_extension_name]="somuchlove" +off=85 chunk_extension_name complete +off=85 len=21 span[chunk_extension_value]="aretheseparametersfor" +off=107 chunk_extension_value complete +off=108 chunk header len=5 +off=108 len=5 span[body]="hello" +off=115 chunk complete +off=117 len=8 span[chunk_extension_name]="blahblah" +off=126 chunk_extension_name complete +off=126 len=4 span[chunk_extension_name]="blah" +off=131 chunk_extension_name complete +off=132 chunk header len=6 +off=132 len=6 span[body]=" world" +off=140 chunk complete +off=143 chunk header len=0 +off=145 chunk complete +off=145 message complete +``` + +## No semicolon before chunk extensions + + +```http +HTTP/1.1 200 OK +Host: localhost +Transfer-encoding: chunked + +2 erfrferferf +aa +0 rrrr + + +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=2 span[status]="OK" +off=17 status complete +off=17 len=4 span[header_field]="Host" +off=22 header_field complete +off=23 len=9 span[header_value]="localhost" +off=34 header_value complete +off=34 len=17 span[header_field]="Transfer-encoding" +off=52 header_field complete +off=53 len=7 span[header_value]="chunked" +off=62 header_value complete +off=64 headers complete status=200 v=1/1 flags=208 content_length=0 +off=66 error code=12 reason="Invalid character in chunk size" +``` + + +## No extension after semicolon + + +```http +HTTP/1.1 200 OK +Host: localhost +Transfer-encoding: chunked + +2; +aa +0 + + +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=2 span[status]="OK" +off=17 status complete +off=17 len=4 span[header_field]="Host" +off=22 header_field complete +off=23 len=9 span[header_value]="localhost" +off=34 header_value complete +off=34 len=17 span[header_field]="Transfer-encoding" +off=52 header_field complete +off=53 len=7 span[header_value]="chunked" +off=62 header_value complete +off=64 headers complete status=200 v=1/1 flags=208 content_length=0 +off=67 error code=2 reason="Invalid character in chunk extensions" +``` + + +## Chunk extensions quoting + + +```http +HTTP/1.1 200 OK +Host: localhost +Transfer-Encoding: chunked + +5;ilovew3="I love; extensions";somuchlove="aretheseparametersfor";blah;foo=bar +hello +6;blahblah;blah + world +0 + +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=2 span[status]="OK" +off=17 status complete +off=17 len=4 span[header_field]="Host" +off=22 header_field complete +off=23 len=9 span[header_value]="localhost" +off=34 header_value complete +off=34 len=17 span[header_field]="Transfer-Encoding" +off=52 header_field complete +off=53 len=7 span[header_value]="chunked" +off=62 header_value complete +off=64 headers complete status=200 v=1/1 flags=208 content_length=0 +off=66 len=7 span[chunk_extension_name]="ilovew3" +off=74 chunk_extension_name complete +off=74 len=20 span[chunk_extension_value]=""I love; extensions"" +off=94 chunk_extension_value complete +off=95 len=10 span[chunk_extension_name]="somuchlove" +off=106 chunk_extension_name complete +off=106 len=23 span[chunk_extension_value]=""aretheseparametersfor"" +off=129 chunk_extension_value complete +off=130 len=4 span[chunk_extension_name]="blah" +off=135 chunk_extension_name complete +off=135 len=3 span[chunk_extension_name]="foo" +off=139 chunk_extension_name complete +off=139 len=3 span[chunk_extension_value]="bar" +off=143 chunk_extension_value complete +off=144 chunk header len=5 +off=144 len=5 span[body]="hello" +off=151 chunk complete +off=153 len=8 span[chunk_extension_name]="blahblah" +off=162 chunk_extension_name complete +off=162 len=4 span[chunk_extension_name]="blah" +off=167 chunk_extension_name complete +off=168 chunk header len=6 +off=168 len=6 span[body]=" world" +off=176 chunk complete +off=179 chunk header len=0 +``` + + +## Unbalanced chunk extensions quoting + + +```http +HTTP/1.1 200 OK +Host: localhost +Transfer-Encoding: chunked + +5;ilovew3="abc";somuchlove="def; ghi +hello +6;blahblah;blah + world +0 + +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=2 span[status]="OK" +off=17 status complete +off=17 len=4 span[header_field]="Host" +off=22 header_field complete +off=23 len=9 span[header_value]="localhost" +off=34 header_value complete +off=34 len=17 span[header_field]="Transfer-Encoding" +off=52 header_field complete +off=53 len=7 span[header_value]="chunked" +off=62 header_value complete +off=64 headers complete status=200 v=1/1 flags=208 content_length=0 +off=66 len=7 span[chunk_extension_name]="ilovew3" +off=74 chunk_extension_name complete +off=74 len=5 span[chunk_extension_value]=""abc"" +off=79 chunk_extension_value complete +off=80 len=10 span[chunk_extension_name]="somuchlove" +off=91 chunk_extension_name complete +off=91 len=9 span[chunk_extension_value]=""def; ghi" +off=101 error code=2 reason="Invalid character in chunk extensions quoted value" +``` + + +## Invalid OBS fold after chunked value + + +```http +HTTP/1.1 200 OK +Transfer-Encoding: chunked + abc + +5 +World +0 + + +``` + +```log +off=0 message begin +off=5 len=3 span[version]="1.1" +off=8 version complete +off=13 len=2 span[status]="OK" +off=17 status complete +off=17 len=17 span[header_field]="Transfer-Encoding" +off=35 header_field complete +off=36 len=7 span[header_value]="chunked" +off=45 len=5 span[header_value]=" abc" +off=52 header_value complete +off=54 headers complete status=200 v=1/1 flags=200 content_length=0 +off=54 len=1 span[body]="5" +off=55 len=1 span[body]=cr +off=56 len=1 span[body]=lf +off=57 len=5 span[body]="World" +off=62 len=1 span[body]=cr +off=63 len=1 span[body]=lf +off=64 len=1 span[body]="0" +off=65 len=1 span[body]=cr +off=66 len=1 span[body]=lf +off=67 len=1 span[body]=cr +off=68 len=1 span[body]=lf +``` + diff --git a/vendor/llhttp/test/url.md b/vendor/llhttp/test/url.md new file mode 100644 index 0000000..13a1b01 --- /dev/null +++ b/vendor/llhttp/test/url.md @@ -0,0 +1,261 @@ +# URL tests + +## Absolute URL + +```url +http://example.com/path?query=value#schema +``` + +```log +off=0 len=4 span[url.schema]="http" +off=7 len=11 span[url.host]="example.com" +off=18 len=5 span[url.path]="/path" +off=24 len=11 span[url.query]="query=value" +off=36 len=6 span[url.fragment]="schema" +``` + +## Relative URL + +```url +/path?query=value#schema +``` + +```log +off=0 len=5 span[url.path]="/path" +off=6 len=11 span[url.query]="query=value" +off=18 len=6 span[url.fragment]="schema" +``` + +## Failing on broken schema + + +```url +schema:/path?query=value#schema +``` + +```log +off=0 len=6 span[url.schema]="schema" +off=8 error code=7 reason="Unexpected char in url schema" +``` + +## Proxy request + +```url +http://hostname/ +``` + +```log +off=0 len=4 span[url.schema]="http" +off=7 len=8 span[url.host]="hostname" +off=15 len=1 span[url.path]="/" +``` + +## Proxy request with port + +```url +http://hostname:444/ +``` + +```log +off=0 len=4 span[url.schema]="http" +off=7 len=12 span[url.host]="hostname:444" +off=19 len=1 span[url.path]="/" +``` + +## Proxy IPv6 request + +```url +http://[1:2::3:4]/ +``` + +```log +off=0 len=4 span[url.schema]="http" +off=7 len=10 span[url.host]="[1:2::3:4]" +off=17 len=1 span[url.path]="/" +``` + +## Proxy IPv6 request with port + +```url +http://[1:2::3:4]:67/ +``` + +```log +off=0 len=4 span[url.schema]="http" +off=7 len=13 span[url.host]="[1:2::3:4]:67" +off=20 len=1 span[url.path]="/" +``` + +## IPv4 in IPv6 address + +```url +http://[2001:0000:0000:0000:0000:0000:1.9.1.1]/ +``` + +```log +off=0 len=4 span[url.schema]="http" +off=7 len=39 span[url.host]="[2001:0000:0000:0000:0000:0000:1.9.1.1]" +off=46 len=1 span[url.path]="/" +``` + +## Extra `?` in query string + +```url +http://a.tbcdn.cn/p/fp/2010c/??fp-header-min.css,fp-base-min.css,\ +fp-channel-min.css,fp-product-min.css,fp-mall-min.css,fp-category-min.css,\ +fp-sub-min.css,fp-gdp4p-min.css,fp-css3-min.css,fp-misc-min.css?t=20101022.css +``` + +```log +off=0 len=4 span[url.schema]="http" +off=7 len=10 span[url.host]="a.tbcdn.cn" +off=17 len=12 span[url.path]="/p/fp/2010c/" +off=30 len=187 span[url.query]="?fp-header-min.css,fp-base-min.css,fp-channel-min.css,fp-product-min.css,fp-mall-min.css,fp-category-min.css,fp-sub-min.css,fp-gdp4p-min.css,fp-css3-min.css,fp-misc-min.css?t=20101022.css" +``` + +## URL encoded space + +```url +/toto.html?toto=a%20b +``` + +```log +off=0 len=10 span[url.path]="/toto.html" +off=11 len=10 span[url.query]="toto=a%20b" +``` + +## URL fragment + +```url +/toto.html#titi +``` + +```log +off=0 len=10 span[url.path]="/toto.html" +off=11 len=4 span[url.fragment]="titi" +``` + +## Complex URL fragment + +```url +http://www.webmasterworld.com/r.cgi?f=21&d=8405&url=\ +http://www.example.com/index.html?foo=bar&hello=world#midpage +``` + +```log +off=0 len=4 span[url.schema]="http" +off=7 len=22 span[url.host]="www.webmasterworld.com" +off=29 len=6 span[url.path]="/r.cgi" +off=36 len=69 span[url.query]="f=21&d=8405&url=http://www.example.com/index.html?foo=bar&hello=world" +off=106 len=7 span[url.fragment]="midpage" +``` + +## Complex URL from node.js url parser doc + +```url +http://host.com:8080/p/a/t/h?query=string#hash +``` + +```log +off=0 len=4 span[url.schema]="http" +off=7 len=13 span[url.host]="host.com:8080" +off=20 len=8 span[url.path]="/p/a/t/h" +off=29 len=12 span[url.query]="query=string" +off=42 len=4 span[url.fragment]="hash" +``` + +## Complex URL with basic auth from node.js url parser doc + +```url +http://a:b@host.com:8080/p/a/t/h?query=string#hash +``` + +```log +off=0 len=4 span[url.schema]="http" +off=7 len=17 span[url.host]="a:b@host.com:8080" +off=24 len=8 span[url.path]="/p/a/t/h" +off=33 len=12 span[url.query]="query=string" +off=46 len=4 span[url.fragment]="hash" +``` + +## Double `@` + + +```url +http://a:b@@hostname:443/ +``` + +```log +off=0 len=4 span[url.schema]="http" +off=12 error code=7 reason="Double @ in url" +``` + +## Proxy basic auth with url encoded space + +```url +http://a%20:b@host.com/ +``` + +```log +off=0 len=4 span[url.schema]="http" +off=7 len=15 span[url.host]="a%20:b@host.com" +off=22 len=1 span[url.path]="/" +``` + +## Proxy basic auth with unreserved chars + +```url +http://a!;-_!=+$@host.com/ +``` + +```log +off=0 len=4 span[url.schema]="http" +off=7 len=18 span[url.host]="a!;-_!=+$@host.com" +off=25 len=1 span[url.path]="/" +``` + +## IPv6 address with Zone ID + +```url +http://[fe80::a%25eth0]/ +``` + +```log +off=0 len=4 span[url.schema]="http" +off=7 len=16 span[url.host]="[fe80::a%25eth0]" +off=23 len=1 span[url.path]="/" +``` + +## IPv6 address with Zone ID, but `%` is not percent-encoded + +```url +http://[fe80::a%eth0]/ +``` + +```log +off=0 len=4 span[url.schema]="http" +off=7 len=14 span[url.host]="[fe80::a%eth0]" +off=21 len=1 span[url.path]="/" +``` + +## Disallow tab in URL + + +```url +/foo\tbar/ +``` + +```log +off=5 error code=7 reason="Invalid characters in url" +``` + +## Disallow form-feed in URL + + +```url +/foo\fbar/ +``` + +```log +off=5 error code=7 reason="Invalid characters in url" +``` diff --git a/vendor/llhttp/tsconfig.json b/vendor/llhttp/tsconfig.json new file mode 100644 index 0000000..01ec7c2 --- /dev/null +++ b/vendor/llhttp/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "strict": true, + "target": "es2017", + "module": "commonjs", + "moduleResolution": "node", + "outDir": "./lib", + "declaration": true, + "pretty": true, + "sourceMap": true + }, + "include": [ + "src/**/*.ts" + ] +} diff --git a/vendor/llhttp/tslint.json b/vendor/llhttp/tslint.json new file mode 100644 index 0000000..b0aaf97 --- /dev/null +++ b/vendor/llhttp/tslint.json @@ -0,0 +1,14 @@ +{ + "defaultSeverity": "error", + "extends": [ + "tslint:recommended" + ], + "jsRules": {}, + "rules": { + "no-bitwise": null, + "quotemark": [ + true, "single", "avoid-escape", "avoid-template" + ] + }, + "rulesDirectory": [] +}