-
-
Notifications
You must be signed in to change notification settings - Fork 753
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
close request connection if h11 sets client state as MUST_CLOSE #2375
Conversation
Please let me know where the documentation is required to be updated. Thanks! |
Hi @Kludex , can you please review this PR |
tests/protocols/test_http.py
Outdated
async def test_close_connection_with_multiple_requests(http_protocol_cls: HTTPProtocol): | ||
app = Response("Hello, world", media_type="text/plain") | ||
|
||
protocol = get_connected_protocol(app, http_protocol_cls) | ||
protocol.data_received(REQEUST_AFTER_CONNECTION_CLOSE) | ||
await protocol.loop.run_one() | ||
assert b"HTTP/1.1 200 OK" in protocol.transport.buffer | ||
assert b"content-type: text/plain" in protocol.transport.buffer | ||
assert b"content-length: 12" in protocol.transport.buffer | ||
# NOTE: We need to use `.lower()` because H11 implementation doesn't allow Uvicorn | ||
# to lowercase them. See: https://github.com/python-hyper/h11/issues/156 | ||
assert b"connection: close" in protocol.transport.buffer.lower() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test passes without the changes on this PR. Can we have a better test?
Is it the first request that doesn't send the response, or the second? 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ummm... well the test case is failing if I remove the change made with this PR.
Below are the results:
- with fix:
scripts/test tests/protocols/test_http.py -k test_close_connection_with_multiple_requests
tests/protocols/test_http.py .. [100%]
===================================================== 2 passed, 118 deselected in 0.11s ======================================================
- without fix (commented the fix from
uvicorn/protocols/http/h11_impl.py
file):
scripts/test tests/protocols/test_http.py -k test_close_connection_with_multiple_requests
tests/protocols/test_http.py .F [100%]
================================================ 1 failed, 1 passed, 118 deselected in 0.31s =================================================
The error raised by failed test case:
E h11._util.LocalProtocolError: can't handle event type Response when role=SERVER and state=MUST_CLOSE
After the fix, the second request should not send the response, since the first request has the Connection: close
header.
Removed newly introduced variable |
Ah, it was a mistake on my side. I see the test failing now. Can we have the As more important: we are accessing private attributes from h11. Does this means that the problem is actually with h11? Is there something missing on h11 that we can't use in uvicorn? I would prefer to not use private attributes. |
Sure, will keep them as separate test cases. While for the fix done, which is overriding the private variable of another library, I agree that we should not be doing so. It was the quickest and simplest way to do the fix when I had explored the issue, sorry for that. While talking about the culprit here, I think improvement is needed in
Let me know what you think of this approach. And for the current fix, we could just replace the entire if self.conn.their_state == h11.MUST_CLOSE:
break |
Great job. 👍 Thanks @theyashl :) |
Server is not responding after upgrade on
UVicorn startup command:
import os
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter
from channels.routing import URLRouter
from django.core.asgi import get_asgi_application
from django.urls import path
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'settings.local')
django_asgi_app = get_asgi_application()
application = ProtocolTypeRouter({
'http': django_asgi_app,
'websocket': AuthMiddlewareStack(
URLRouter([
...
])
)
}) |
Hi @bashkirtsevich , I am not able to reproduce this behavior. When tested with django's default Used command: pip freeze:
Default import os
from django.core.asgi import get_asgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'testme.settings')
application = get_asgi_application() Can you please share the server bootup logs for further debugging? |
I have issues when upgrading as well. |
Hi @plagree, Can you please share a reproducible sample of code using which I can debug this issue? In the meantime, I'll try to execute following scenarios on my own:
Just for confirmation, please check if the request headers for backend server does not contains |
Did some analysis around this side effect caused by the fix present in 0.30.4 Steps to reproduce the issue:
import uvicorn
async def app(scope, receive, send):
assert scope['type'] == 'http'
await send({
'type': 'http.response.start',
'status': 200,
'headers': [
(b'content-type', b'text/plain'),
],
})
await receive()
await send({
'type': 'http.response.body',
'body': b'{"status": "ok"}',
})
if __name__ == '__main__':
uvicorn.run("example:app", port=8080, http='h11')
printf 'GET / HTTP/1.1\r\nConnection: close\r\nHost: a\r\n\r\n' | nc localhost 8080 This will cause the request to go into a waiting state unless and until the client closes the connection. Reason: When H11 completely processes the client's request, the event is of type Will raise an PR with the fix. |
Hi @theyashl There is no differences of boot logs between 0.30.3 and 0.30.4. Pay attention to websocket app in my case. Can you make you patch switching on by an environment variable or CLI param; and disable it as a default? |
Hi @bashkirtsevich , While, in present case, the server is unable to send response when You can explicitly install the dev fix and try if the fix solves your issue or not. |
Summary
Fixes: Issue- #2238
Checklist