-
Notifications
You must be signed in to change notification settings - Fork 333
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
Surface websocket protocol errors to user applications #804
Surface websocket protocol errors to user applications #804
Conversation
CLA Assistant Lite bot All contributors have signed the CLA ✍️ ✅ |
8c33a48
to
6ff569a
Compare
I have read the CLA Document and I hereby sign the CLA |
26e1402
to
013463a
Compare
013463a
to
df9776c
Compare
dc82b35
to
c929b98
Compare
c929b98
to
a9cf330
Compare
src/workerd/api/web-socket.c++
Outdated
auto upstream = other->pumpTo(*self); | ||
auto downstream = self->pumpTo(*other); | ||
auto upstream = other->pumpTo(*self).catch_([](kj::Exception&& e) { | ||
KJ_UNWRAP_OR(WebSocketProtocolError::fromException(e), { |
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.
Might be misreading this, but I suspect:
if (WebSocketProtocolError::fromException(e) == nullptr) {
throw e;
}
may have clearer intent. KJ_UNWRAP_OR
returns the inner value on success, but we don't seem to be doing anything with that value here so I'm wondering if something was supposed to be done with it?
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.
I'm actually not sure if it matters all that since this is pretty much passing through the error, but you might also want to use kj::throwFatalException(e)
instead. I believe that it basically extends our async stack a bit?
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.
btw, can this be written to use coroutine syntax rather than using catch_
?
And yes, this should use kj::throwFatalException(e)
instead.
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.
Ah, that's how you say "this Maybe is empty". I'd found KJ_IF_MAYBE(_, m){} else { ... }
, but that's ugly.
(In my ideal world, kj::Maybe
would provide operator bool()
for "has stuff in it", or maybe a .empty()
method, but this is not that world.)
I fixed everything but the coroutine syntax. I can convert each individual pumpTo
call, but currently the two promises get joined down below and I'm not sure what to do with that. Suggestions welcome.
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.
@jasnell I've coroutine-ified things as much as I can. There's still a call to kj::joinPromises
that I don't see how to get rid of, but there's no more catch_
. Does this look good to you?
4445478
to
155b33b
Compare
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.
Thanks Sam!
155b33b
to
d35d1f1
Compare
920f4ee
to
eb52246
Compare
🙃 it just occurred to me that the hibernatable websocket readloop is outside the regular Workerd web-socket code. Could you also update |
eb52246
to
32c00d4
Compare
Currently, if a websocket client sends bad data[1] to an application, the application just receives a generic error message with no indication of what went wrong. Also, the client just gets an aborted[2] websocket connection without any clue as to what they did wrong. This commit changes two things: first, the application now gets an error event describing what was wrong with the received data. This gives the application's owner some clue what's going wrong. Second, we now send a Close frame to the client with an appropriate error code, as we SHOULD do[3]. In an ideal world, this will let the client's owner figure out what they're doing wrong and fix it. [1] Invalid according to RFC 6455, for example sending a continuation frame without a preceding start frame or sending a frame with reserved bits (RSV1, RSV2, and RSV3; see https://datatracker.ietf.org/doc/html/rfc6455#section-5.2) set. [2] The underlying TCP connection is closed without first sending a websocket "Close" frame. [3] https://datatracker.ietf.org/doc/html/rfc6455#section-7.1.7
32c00d4
to
29c39b0
Compare
I'm dusting this change off after months of ignoring it. It still needs to include hibernating websockets, so I've marked as draft for the time being. |
Obsoleted by capnproto/capnproto#1896, which handles the error much closer to its cause |
Currently, if a websocket client sends bad data[1] to an application, the application just receives a generic error message with no indication of what went wrong. Also, the client just gets an aborted[2] websocket connection without any clue as to what they did wrong.
This commit changes two things: first, the application now gets an error event describing what was wrong with the received data. This gives the application's owner some clue what's going wrong.
Second, we now send a Close frame to the client with an appropriate error code, as we SHOULD do[3]. In an ideal world, this will let the client's owner figure out what they're doing wrong and fix it.
[1] Invalid according to RFC 6455, for example sending a continuation frame without a preceding start frame or sending a frame with reserved bits (RSV1, RSV2, and RSV3; see
https://datatracker.ietf.org/doc/html/rfc6455#section-5.2) set.
[2] The underlying TCP connection is closed without first sending a websocket "Close" frame.
[3] https://datatracker.ietf.org/doc/html/rfc6455#section-7.1.7