envoyproxy / envoy

Cloud-native high-performance edge/middle/service proxy
https://www.envoyproxy.io
Apache License 2.0
24.89k stars 4.79k forks source link

`Content-Length: 0` header breaking the gRPC HTTP/1.1 reverse bridge #29989

Open natetarrh opened 1 year ago

natetarrh commented 1 year ago

Title: Content-Length: 0 header breaking the gRPC HTTP/1.1 reverse bridge

Description:

Puma 6 and above introduced changes to HTTP/1.1 response headers. Specifically, a 0-byte response to an application/grpc request (i.e., a Protobuf object with no non-defaults set) from a Puma 5.X server has a Transfer-Encoding: chunked header set but no content length header, and a 0-byte response from a Puma 6.X server has a Content-Length: 0 header set but no transfer encoding header. The gRPC HTTP/1.1 reverse bridge fails to parse the Puma 6.X server response because it sees that the response cannot have a body and then optimizes away the encodeData response of the gRPC HTTP/1.1 reverse bridge.

Repro steps:

See this repo for a minimally-reproducing test case with a gRPC request against a both a working and broken upstream HTTP server example.

Admin and Stats Output:

N/A

Config:

admin:
  address:
    socket_address: { address: 0.0.0.0, port_value: 9901 }

static_resources:
  listeners:
  - name: main
    address:
      socket_address:
        address: 0.0.0.0
        port_value: 8000
    filter_chains:
    - filters:
      - name: envoy.filters.network.http_connection_manager
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
          stat_prefix: ingress_http
          codec_type: AUTO
          route_config:
            name: local_route
            virtual_hosts:
            - name: local_service
              domains:
              - "*"
              routes:
              - match:
                  prefix: "/"
                route:
                  cluster: web_service
          http_filters:
          - name: envoy.filters.http.grpc_http1_reverse_bridge
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.http.grpc_http1_reverse_bridge.v3.FilterConfig
              content_type: application/x-protobuf
              withhold_grpc_frames: true
              response_size_header: X-Content-Length
          - name: envoy.filters.http.router
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router

  clusters:
  - name: web_service
    type: STATIC
    lb_policy: ROUND_ROBIN
    load_assignment:
      cluster_name: web_service
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: 127.0.0.1
                port_value: 3000

Logs:

N/A

Call Stack:

N/A

hq6 commented 9 months ago

I think https://github.com/envoyproxy/envoy/pull/31065 fixes this issue, so it should be closed?