-
Notifications
You must be signed in to change notification settings - Fork 337
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
Properly support *conditional* WebSocket upgrades #473
Comments
@mslupny Hi Matt, thanks for bringing attention to this! Apologies for the slow response. I'm not familiar with the details on this, and unfortunately won't have much time to investigate myself. But one thing I want to check: the linked spec is described as non-normative. I would generally interpret that as meaning that the section describes recommended or pedagogical behaviour rather than a requirement. Are you familiar with the possible implications of http-kit not confirming here? If we're talking about a possible non-trivial architectural change to make/investigate, I think it'd be helpful to be very clear on what the benefits would be (or costs of not doing so). How did you come across this issue? Have you actually encountered some problem in production? Thanks! |
Unfortunately, we hit this problem in production and noticed it because of errors in nginx logs. Basically you can replace the HTTP client from the test case above with nginx and everything still holds:
The workaround is to include the header "Connection: close" in the response in step 3, which prevents reusing the TCP connection by nginx. I understand this is an edge case and not something that justifies rearchitecting the library just to get it fixed, especially since a workaround exists. It might be a good idea to just document the workaround somewhere, and hope the scenario is handled in case http-kit gets a rewrite in the future 😉. |
I'm sorry, I'm not sure I'm following. Where does nginx enter into the picture? Are you suggesting that nginx has the same behaviour as http-kit, and that you actually encountered this problem with nginx? |
Not at all. You asked whether this is a hypothetical problem or something encountered in production. We encountered it in production in a setup with nginx used as reverse proxy and a Clojure application with http-kit used as HTTP server. In this architecture, nginx makes HTTP requests to http-kit, and this is how we found the problem. To be clear: the problem is not specific to nginx. You can reproduce it with any HTTP client that can reuse TCP connections. Feel free to ping me on Clojurians Slack in case there's still something unclear, might be faster that way. |
Okay, that was helpful - thank you. So to confirm in some more detail:
Is that correct so far? |
Spot on! 🙌 |
@mslupny Thanks Matt! Apologies for the long delay replying. I've updated the issue title based on my understanding of the above issue summary. From my superficial understanding, it seems like the core issue may be around point Input and/or PRs very welcome 👍 |
http-kit is non conforming to https://datatracker.ietf.org/doc/html/rfc6455#section-1.3:
The root cause of the problem in http-kit is that the selector attachment (WsAtta) is
assigned based on HTTP request headers [1], when it should be done only after
making sure the response has status code 101.
It seems to me that fixing the problem in http-kit would require a major architectural change
because as of now WebSocket handshake is sent directly to the socket,
bypassing the callback chain [2], so there's no way of knowing that server
handler returned 101.
Please let me know if I'm missing something and there's a way of fixing it without a major rewrite - I'm willing to work on a patch :).
A simple test that reproduces the problem:
The second
http/get
fails with the exception:tcpdump output from the test:
As you can see, the server closes the connection right after receiving the second request (because
HttpServer.decodeWs
is called instead ofHttpServer.decodeHttp
).[1] https://github.com/http-kit/http-kit/blob/master/src/java/org/httpkit/server/HttpServer.java#L183
[2] https://github.com/http-kit/http-kit/blob/master/src/java/org/httpkit/server/AsyncChannel.java#L164
The text was updated successfully, but these errors were encountered: