You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The GrpcWeb module does not properly convert from application/grpc-web-text to application/grpc, which results in the error: protocol error: received message with invalid compression flag: 65 (valid flags are 0 and 1), while sending request.
After attempting to set up the GrpcWebModule following the reference example, I was unable to forward requests from gRPC-Web to native gRPC. After some investigation, I discovered that the module doesn't upgrade the connection from HTTP/1 to HTTP/2 properly. Specifically, it doesn't change the content type as expected: application/grpc-web-text was converted to application/grpc-text. The issue arises from this line.
I assume that the error with the compression flag is related to the content-type parsing, as mentioned in this comment.
I created a repository with all the artifacts necessary to reproduce the error.
First, I have a simple Hello gRPC server written in Rust with tokio 0.10.2. It runs on port 50051.
Then, I have the Pingora proxy. It also runs a simple CORS service to handle preflight requests:
implServeHttpforGrpcWebPreflightHttpApp{asyncfnresponse(&self,_http_session:&mutServerSession) -> Response<Vec<u8>>{let buffer = "Grpc Web OK".as_bytes().to_vec();Response::builder().status(200).header(
http::header::ACCESS_CONTROL_ALLOW_HEADERS,"content-type,x-grpc-web,x-user-agent",).header(http::header::ACCESS_CONTROL_ALLOW_METHODS,"POST").header(http::header::CONTENT_LENGTH, buffer.len()).header(http::header::ACCESS_CONTROL_ALLOW_ORIGIN,"null").header(http::header::ACCESS_CONTROL_EXPOSE_HEADERS,"*").header(http::header::ACCESS_CONTROL_MAX_AGE,1728000).body(buffer).unwrap()}}
The proxy configuration is as follows. The GrpcWeb module is added in init_downstream_modules and initialized for every request in early_request_filter, as shown in the reference example. For the upstream_peer, it returns the GrpcWebPreflight peer whenever the method is OPTIONS, or the Hello server peer otherwise. The ALPN version is set to H2 for the Hello server peer.
For gRPC-Web, there is a simple JavaScript client that sends a Hello request. You can open index.html in the browser and provide the proxy URL.
Expected results
Native gRPC requests should be ignored by the module and forwarded normally.
gRPC-Web requests with content type application/grpc-web-text should be parsed as application/grpc before being sent to the upstream peer, and the response should be parsed back to application/grpc-web+{proto | json | ... }.
Observed results
Native gRPC requests are being ignored by the module and forwarded normally, as expected.
gRPC-Web requests with content type application/grpc-web-text are being incorrectly parsed as application/grpc-text, which results in the error protocol error: received message with invalid compression flag: 65 (valid flags are 0 and 1), while sending request.
Additional context
grpc-web should be treated differently from grpc-web-text. As outlined in the gRPC documentation, grpc-web-text is text-encoded and should be parsed before being converted to native gRPC.
This is similar to how Envoy handles it here with its gRPC-Web filter.
The text was updated successfully, but these errors were encountered:
Describe the bug
The GrpcWeb module does not properly convert from
application/grpc-web-text
toapplication/grpc
, which results in the error:protocol error: received message with invalid compression flag: 65 (valid flags are 0 and 1), while sending request
.After attempting to set up the
GrpcWebModule
following the reference example, I was unable to forward requests from gRPC-Web to native gRPC. After some investigation, I discovered that the module doesn't upgrade the connection from HTTP/1 to HTTP/2 properly. Specifically, it doesn't change the content type as expected:application/grpc-web-text
was converted toapplication/grpc-text
. The issue arises from this line.I assume that the error with the compression flag is related to the content-type parsing, as mentioned in this comment.
Pingora info
Pingora version:
0.4.0
Rust version:
cargo 1.83.0 (5ffbef321 2024-10-29)
Operating system version: macOS Sonoma 14.7.1
Steps to reproduce
I created a repository with all the artifacts necessary to reproduce the error.
First, I have a simple Hello gRPC server written in Rust with
tokio 0.10.2
. It runs on port 50051.Then, I have the Pingora proxy. It also runs a simple CORS service to handle preflight requests:
The proxy configuration is as follows. The GrpcWeb module is added in
init_downstream_modules
and initialized for every request inearly_request_filter
, as shown in the reference example. For the upstream_peer, it returns the GrpcWebPreflight peer whenever the method isOPTIONS
, or the Hello server peer otherwise. The ALPN version is set to H2 for the Hello server peer.The proxy runs at
0.0.0.0:6193
.gRPC requests can be sent with grpcurl:
For gRPC-Web, there is a simple JavaScript client that sends a Hello request. You can open index.html in the browser and provide the proxy URL.
Expected results
Native gRPC requests should be ignored by the module and forwarded normally.
gRPC-Web requests with content type
application/grpc-web-text
should be parsed asapplication/grpc
before being sent to the upstream peer, and the response should be parsed back toapplication/grpc-web+{proto | json | ... }
.Observed results
Native gRPC requests are being ignored by the module and forwarded normally, as expected.
gRPC-Web requests with content type
application/grpc-web-text
are being incorrectly parsed asapplication/grpc-text
, which results in the errorprotocol error: received message with invalid compression flag: 65 (valid flags are 0 and 1), while sending request
.Additional context
grpc-web
should be treated differently fromgrpc-web-text
. As outlined in the gRPC documentation,grpc-web-text
is text-encoded and should be parsed before being converted to native gRPC.This is similar to how Envoy handles it here with its gRPC-Web filter.
The text was updated successfully, but these errors were encountered: