-
Notifications
You must be signed in to change notification settings - Fork 304
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
Feature Request: Enable half-closed with CloseWrite #507
Comments
Hi, @fortuna. Interesting use-case. From what you describe it sounds like it's somewhat in conflict with RFC 6455: 5.5.1:
Essentially this states that the close handshake should happen, i.e. we can't send off a close-frame without receiving one back. Although the receiving side could delay the close for the current message.
But with regards to closing the underlying TCP connection, the spec is pretty clear:
In the clients case, we could probably change the behavior a bit, but I'm not sure if that would be helpful for your use-case? Given the above, does it sound like what you want to achieve is possible? If yes I'm probably not fully grokking what you're looking to do and would appreciate some more details. |
Unfortunately the RFC text is a bit limiting, but not completely. For the "MUST send a Close frame in response", we will always send a Close, but later. The "as soon as practical" is a SHOULD, so we would not be in violation of that. They say that the client MAY delay the Close until its current message is sent. But it doesn't say it MUST be sent right after the message, or that sending it after future messages is forbidden. That's where the RFC text is lacking. Sending it later is not in violation of the text, but the text doesn't make it clear it's safe, unfortunately. As for closing the TCP connection, that's fine, because the client will send a TCP FIN when it sends the Websocket Close, and receive a FIN when it receives the Websocket Close, ensuring TCP is fully closed when Websocket is. In my case, I control both the client and the server, so I could ensure that is working. However, that will certainly tie my implementation, and I'm not sure what other reverse proxies will do along the way. I intend to put my reverse proxy behind CDNs like Cloudflare, who may have a different interpretation of the RFC. I'm still debating what's the best way to proceed:
|
@mafredri does this implementation support unlimited messages? |
So I tried the approach of using a single message for the entire stream, which gives me a FIN signal. It almost worked, but it breaks due to the fact that the Writer.Write buffers the content, only flushing at the end of the message. I need a mechanism to force the flush on every write, essentially removing the buffered writes. |
FYI, I was able to accomplish half-close with the Gorilla library. They allow us to provide a Close handler: https://pkg.go.dev/github.com/gorilla/websocket#Conn.SetCloseHandler. Though, to me it would still be preferable if I could send the entire stream as one message. I can accomplish that with gobwas via https://pkg.go.dev/github.com/gobwas/[email protected]/wsutil#Writer.FlushFragment or https://pkg.go.dev/github.com/gobwas/[email protected]/wsutil#Writer.WriteThrough. Feature request:
|
I'm writing a TCP reverse proxy over Websocket and I'm trying to use this library.
However, it provides no way to close the write side only. That's needed to indicate end of stream (EOF), which gets mapped to a FIN on the TCP connection to the origin.
Looking at the code, I see that Close() runs the full handhsake. Perhaps CloseWrite could just send the close message with the normal status, but not wait for the response. And the code should not close the connection when receiving the close message. It should only do that on the explicit Close() or CloseWrite() call by the application code.
The text was updated successfully, but these errors were encountered: