Closed kenballus closed 1 month ago
That error is from the Python parser. With llhttp, you get the more accurate: Data after Connection: close:
.
A client that sends a "close" connection option MUST NOT send further requests on that connection (after the one containing the "close") https://www.rfc-editor.org/rfc/rfc9112#section-9.6-5
For the server, it merely says that it should not process further requests. It does not say it should process the previous request. So, I think tweaking the Python parser to match the llhttp error is fine.
For the server, it merely says that it should not process further requests. It does not say it should process the previous request.
I suppose this might be technically allowable, but it's pretty unintuitive in my opinion. I would assume that data received after a connection has been declared closed should not invalidate previous valid messages sent on that connection.
I've since tested this on many more HTTP implementations.
These ones reject the second request without responding to the first:
These ones respond to the first request and ignore the second because the connection is closed: (Mongoose and Uvicorn have changed sides on this because of reports that I submitted, so feel free to ignore those two)
Given the behavior of other implementations, it's probably worth at least documenting that AIOHTTP handles things differently.
As we use llhttp, if you convince Node.js to change behaviour, then we'll update the Python parser to match. But, it'd be weird to have different behaviour depending on the parser used.
Given that the client in this case has violated the HTTP protocol, I don't think it really matters whether the behaviour is intuitive or not, it should never be encountered by an HTTP client.
Describe the bug
From RFC 9112, section 9.6:
When aiohttp receives a pipeline with a request containing
Connection: close
, followed by an invalid request, aiohttp responds only to the second (invalid) request, even though the standard requires that aiohttp respond only to the first one.To Reproduce
async def respond(request): return web.Response(text="hello world")
app = web.Application() app.add_routes([web.route("", "/{whatever:.}", respond)]) web.run_app(app, port=8080)
Bad status line 'Invalid'
Python Version
aiohttp Version
multidict Version
yarl Version
OS
Debian 12 (running in Docker on Arch Linux) Linux 6.7.2
Related component
Server
Additional context
Some other HTTP implementations that handle this correctly: Apache httpd, Boost::Beast, Daphne, H2O, Lighttpd, Nginx, Tornado, OpenWrt uhttpd, Waitress
Some other HTTP implementations that also have this bug: Mongoose, Uvicorn
Code of Conduct