envoyproxy/envoy

gRPC HTTP/1.1 bridge does not perform protobuf upgrading on empty payloads

Open

#21,312 创建于 2022年5月16日

在 GitHub 查看
 (4 评论) (2 反应) (0 负责人)C++ (5,373 fork)batch import
bughelp wanted

仓库指标

Star
 (27,997 star)
PR 合并指标
 (平均合并 8天) (30 天内合并 378 个 PR)

描述

Title: gRPC HTTP/1.1 bridge does not perform protobuf upgrading on empty payloads

Description:

When sending an empty body over HTTP to an envoy instance configured with to perform protobuf upgrading the filter seems to be bypassed. The result is requests with content-type application/x-protobuf would not forwarded to desired gRPC cluster.

With the configuration I'm using this results in a 504 Gateway Timeout after the configured timeout expires, but the exact effects would depend on how exactly the routes and clusters are set-up.

ps: it seems like this only happens with empty payloads, if they have at least one byte it seems to work fine.

Repro steps:

I could reproduce it by running examples/grpc-bridge/server/service.go and an envoy instance with the configuration attached. I've encoded a few demo payloads to demonstrate the problem when calling POST /kv.KV/Set, but the problem should be reproducible with any endpoint.

generating payloads:

cd examples/grpc-bridge
# generate a payload with non-empty values
echo 'key: "foo", value: "bar"' | protoc --encode 'kv.SetRequest' -I./protos ./protos/kv.proto > set.protobuf.bin
# generate a payload with fields set to de default values (equivalent to empty payload in protobuf 3)
echo 'key: "", value: ""' | protoc --encode 'kv.SetRequest' -I./protos ./protos/kv.proto > set_default.protobuf.bin

sending with curl:

$ curl -v -X POST -H 'Content-Type: application/x-protobuf' --data-binary '@set.protobuf.bin' http://localhost:8090/kv.KV/Set        
Note: Unnecessary use of -X or --request, POST is already inferred.
*   Trying 127.0.0.1:8090...
* Connected to localhost (127.0.0.1) port 8090 (#0)
> POST /kv.KV/Set HTTP/1.1
> Host: localhost:8090
> User-Agent: curl/7.83.1
> Accept: */*
> Content-Type: application/x-protobuf
> Content-Length: 10
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< content-type: application/grpc
< x-envoy-upstream-service-time: 0
< grpc-status: 0
< grpc-message: 
< content-length: 2
< date: Mon, 16 May 2022 15:24:58 GMT
< server: envoy
< 
* Connection #0 to host localhost left intact

$ curl -v -X POST -H 'Content-Type: application/x-protobuf' --data-binary '@set_default.protobuf.bin' http://localhost:8090/kv.KV/Set
Note: Unnecessary use of -X or --request, POST is already inferred.
*   Trying 127.0.0.1:8090...
* Connected to localhost (127.0.0.1) port 8090 (#0)
> POST /kv.KV/Set HTTP/1.1
> Host: localhost:8090
> User-Agent: curl/7.83.1
> Accept: */*
> Content-Type: application/x-protobuf
> Content-Length: 0
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 504 Gateway Timeout
< content-length: 24
< content-type: text/plain
< date: Mon, 16 May 2022 15:14:42 GMT
< server: envoy
< 
* Connection #0 to host localhost left intact
upstream request timeout

Config:

staticResources:
  listeners:
  - address:
      socketAddress:
        address: 0.0.0.0
        portValue: 8090
    filterChains:
    - filters:
      - name: envoy.filters.network.http_conection_manager
        typedConfig:
          "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
          statPrefix: ingress_http
          routeConfig:
            name: local_route
            virtualHosts:
            - name: backend
              domains:
              - "*"
              routes:
              - match:
                  prefix: "/"
                route:
                  cluster: grpc
                  timeout: 60s
          httpFilters:
          - name: envoy.filters.http.grpc_http1_bridge
            typedConfig:
              "@type": type.googleapis.com/envoy.extensions.filters.http.grpc_http1_bridge.v3.Config
              upgradeProtobufToGrpc: true
          - name: envoy.filters.http.router
  clusters:
  - name: grpc
    type: LOGICAL_DNS
    connectTimeout: 1s
    loadAssignment:
      clusterName: grpc
      endpoints:
      - lbEndpoints:
        - endpoint:
            address:
              socketAddress:
                address: 0.0.0.0
                portValue: 8081
    healthChecks:
    - timeout: 1s
      interval: 1s
      unhealthyThreshold: 5
      healthyThreshold: 2
      grpcHealthCheck: {}
      noTrafficInterval: 1s
    typedExtensionProtocolOptions:
      envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
        "@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
        explicitHttpConfig:
          http2ProtocolOptions: {}
admin:
  address:
    socketAddress:
      address: 0.0.0.0
      portValue: 9901

贡献者指南