aio-libs / aiohttp

Asynchronous HTTP client/server framework for asyncio and Python
https://docs.aiohttp.org
Other
15.11k stars 2.02k forks source link

Handle exceptions? #5358

Closed fpgamaster closed 2 months ago

fpgamaster commented 3 years ago

🐞 Describe the bug The following exception happens when trying to connect to http server using https client: Traceback (most recent call last): File "/usr/local/lib/python3.7/site-packages/aiohttp/web_protocol.py", line 314, in data_received messages, upgraded, tail = self._request_parser.feed_data(data) File "aiohttp/_http_parser.pyx", line 546, in aiohttp._http_parser.HttpParser.feed_data aiohttp.http_exceptions.BadStatusLine: 400, message="Bad status line 'invalid HTTP method'"

💡 To Reproduce Start an http server and connect to it using any browser or client using https

💡 Expected behavior A way to handle this exception. It cannot be handled using middlewares.

📋 Logs/tracebacks Traceback (most recent call last): File "/usr/local/lib/python3.7/site-packages/aiohttp/web_protocol.py", line 314, in data_received messages, upgraded, tail = self._request_parser.feed_data(data) File "aiohttp/_http_parser.pyx", line 546, in aiohttp._http_parser.HttpParser.feed_data aiohttp.http_exceptions.BadStatusLine: 400, message="Bad status line 'invalid HTTP method'"



📋 **Your version of the Python**
$ python --version
Python 2.7.18

📋 **Your version of the aiohttp/yarl/multidict distributions**
$ python -m pip show aiohttp
Name: aiohttp
Version: 3.7.3
Summary: Async http client/server framework (asyncio)
Home-page: https://github.com/aio-libs/aiohttp
Author: Nikolay Kim
Author-email: fafhrd91@gmail.com
License: Apache 2
Location: /usr/local/lib/python3.7/site-packages
Requires: chardet, typing-extensions, multidict, yarl, async-timeout, attrs

$ python -m pip show multidict
Name: multidict
Version: 4.7.6
Summary: multidict implementation
Home-page: https://github.com/aio-libs/multidict
Author: Andrew Svetlov
Author-email: andrew.svetlov@gmail.com
License: Apache 2
Location: /usr/local/lib/python3.7/site-packages
Requires:
Required-by: yarl, aiohttp

$ python -m pip show yarl
Name: yarl
Version: 1.6.0
Summary: Yet another URL library
Home-page: https://github.com/aio-libs/yarl/
Author: Andrew Svetlov
Author-email: andrew.svetlov@gmail.com
License: Apache 2
Location: /usr/local/lib/python3.7/site-packages
Requires: multidict, idna, typing-extensions
Required-by: aiohttp

📋 **Additional context**
Server, HTTP
derlih commented 3 years ago

Looks like a dup of #3287 @fpgamaster take a look onto @asvetlov comment

There is no well-formed request exists, no middleware is affected. The error happens on the HTTP protocol level, even before aiohttp routing starts to work. In other words, middlewares/signals are not called if the HTTP protocol is broken. There is no peer to send a response at all etc.

The only thing we can do is the conversion of exception with the attached stacktrace into a logged warning. A volunteer is welcome!

fpgamaster commented 3 years ago

Hi @derlih , Yeah, it is pretty common to use http services on public IPs and to get invalid requests like https requests to an http server. There should be a way to handle such exceptions! I can add an http proxy in front of aiohttp server but it is a dirty solution :(

Best regards

derlih commented 3 years ago

Hi @fpgamaster , Do you want to handle the connection with non-HTTP traffic with aiohttp?

fpgamaster commented 3 years ago

Hi @derlih , No, just want to handle these exceptions related to a possible non-HTTP traffic.

Best regards

derlih commented 3 years ago

Hi @fpgamaster , So if you would have this handler, what do you want to do there? Imaging the following code:

def handler(connection):
  try:
    server.handle_http(connection)
  except aiohttp.BadHTTP:
    pass  # What should be here?
fpgamaster commented 3 years ago

Hi @derlih , At least it will not fill my logs with junk.

Best regards

Dreamsorcerer commented 3 years ago

I think as mentioned in the duplicate issue, we just want to send a 400 response (if/when possible), and probably log the error somewhere.

morgverd commented 3 years ago

Is there still no found way of handling this exception? Any HTTPS request on a public HTTP API exposes this error.

km445 commented 3 years ago

Hello. My two cents on the issue: if aiohttp throws an exception i would like an option to handle the response. Suppose you send a GET request with too long query string, aiohttp throws an exception: aiohttp.http_exceptions.LineTooLong: 400, message='Got more than 8190 bytes (10235) when reading Status line is too long.' which is completely fine.

However i would like an option to respond with something like Status: 414 Body: {"data": null, "message": "URI Too Long"}

Yes, in production web server/nginx would cut off a malformed request and it would not make it to aiohttp. Best regards.

webknjaz commented 3 years ago

However i would like an option to respond with something like Status: 414 Body: {"data": null, "message": "URI Too Long"}

@km445 this does not sound right. Per HTTP specs, an HTTP response is to be sent after receiving an HTTP request. So if the client is still in a state of sending the request over the wire, I would expect it to get confused if you send back something like this w/o first consuming the request.

Dreamsorcerer commented 2 months ago

I'm going to close this one in favour of the duplicate issue (#3287).