Closed niloc132 closed 2 years ago
Hi, thanks for your issue! This is great, thanks for all the explanation and research. Please note that this repo is in maintenance mode, and we recommend users migrate to the official grpc-web client: https://github.com/grpc/grpc-web. That said, I'm happy to review PRs that fix bugs in the existing code.
Thanks for the heads up - we've found the upstream grpc/grpc-web to be lacking with no binary streaming support, and in the absence of tls browsers cannot use h2, so there is a very low limit on the number of concurrent streams (not unlike with websockets). We are trying to reduce our dependence (but not our support for) the improbably-eng/grpc-web grpcwebproxy, but if we should migrate away entirely, perhaps we will need to manage our own implementation entirely.
Versions of relevant software used At least 0.12 through latest
What happened Websockets support a mechanism known as "subprotocols" where a connecting client can offer zero to many options, and the server can pick from that list the best suited. The server then should communicate that negotiated protocol back to the client so both sides know which protocol is in use for the duration of the connection as the websocket finishes opening, and both client and server then can proceed sending messages using that protocol.
The websocket spec calls for the
Sec-Websocket-Protocol
header(s) to be defined by the client (multiple headers can be set, each header entry should be comma separated). The server then must select one of these values, or respond that it does not accept these options. See https://datatracker.ietf.org/doc/html/rfc6455#section-4.1, See https://datatracker.ietf.org/doc/html/rfc6455#section-4.2 for more details.The use case here is to implement an alternative but compatible websocket client/server (see #1081, #198) that is able to share a single websocket for all active streams. The proposed client implementation would support both
grpc-websockets
andgrpc-websockets-multiplex
. Server negotiation should inform the client which implementation will be used.Presently, grpcwebproxy's websocket implementation when offered multiple protocols will simply fail the connection, rather than pick the acceptable option
grpc-websockets
.What you expected to happen If the client websocket contains
grpc-websockets
as an option, it is expected that the server will respond by opening the websocket selecting that as the negotiated subprotocol. Note that thenhooyr.io/websocket
library correctly handles this, but only theIsGrpcWebSocketRequest
check incorrectly fails.How to reproduce it (as minimally and precisely as possible): The simplest way is to modify client/grpc-web/src/transports/websocket/websocket.ts to also offer any other protocol along with
grpc-websockets
, under the assumption that any server which can use that protocol will respond back with that same string. For example:Anything else we need to know I'll offer a pull request to fix this. The project github.com/deephaven/deephaven-core has an in-process grpc-web and grpc-websockets proxy, and is seeking to add a grpc-websockets-multiplex proxy for faster non-tls stream initiation (and to avoid exhausting the browser's allowed websocket count). If there is interest, we can provide a ts client here, and see about an update to the Go proxy provided by improbable-eng/grpc-web.