Skip to content

Strange internal_redirect / buffer interactions #44128

@turettn

Description

@turettn

Title: Strange internal_redirect / buffer interactions

Description:
I have an envoy config with:

  • envoy.filters.http.buffer with max_request_bytes: 4194304
  • A route with internal_redirect_action and internal_redirect_policy enabled
  • A route to handle the internal redirect via dynamic_forward_proxy, and buffering disabled

When a request with body size <= 2MiB is internall redirected, everything works just fine.

Request bodies > 2MiB and <= 4MiB get the redirect passed back to the customer. The following appears in the logs with a 3MB request body:

envoy-1    | [2026-03-26 15:23:45.009][28][debug][router] [source/common/router/router.cc:1025] The request payload has at least 6000000 bytes data which exceeds buffer limit 4194304. Marking request as buffer overflowed to cancel internal redirects.

Request bodies over 4MiB result in a HTTP413 as expected.

It appears the buffer is getting filled twice, even though buffering is disabled on the internal redirect route.

My current workaround is to set per_request_buffer_limit_bytes on the vhost to 8MiB. It feels like this shouldn't be required, since buffering isn't enabled (or required by the backend) on the sub-request.

Repro steps:

Include sample requests, environment, etc. All data and inputs
required to reproduce the bug.

Use the config below, and some toy backends:

  • server1 - redirect everything to server2
  • server2 - just return the size of the request body

Send a request with body size 3MB

Config:

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

static_resources:
  listeners:
  - name: listener_0
    address:
      socket_address: { address: 0.0.0.0, port_value: 10000 }
    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
            internal_only_headers:
            - "X-Internal-Redirect"
            virtual_hosts:
            - name: local_service
              domains: ["*"]
              # Uncommenting this line fixes the problem
              # per_request_buffer_limit_bytes: 8388608
              routes:
              - match:
                  prefix: "/"
                  headers:
                  - name: X-Internal-Redirect
                    present_match: false
                route:
                  cluster: server1
                  internal_redirect_action:  'HANDLE_INTERNAL_REDIRECT'
                  internal_redirect_policy:
                    max_internal_redirects: 1
                    redirect_response_codes: [301]
                    response_headers_to_copy:
                    - 'X-Internal-Redirect'
              - match:
                  prefix: /
                  headers:
                  - name: X-Internal-Redirect
                    present_match: True
                route:
                  cluster: dynamic_forward_proxy_cluster
                typed_per_filter_config:
                  envoy.filters.http.buffer:
                    "@type": type.googleapis.com/envoy.extensions.filters.http.buffer.v3.BufferPerRoute
                    disabled: true


          http_filters:
          - name: envoy.filters.http.dynamic_forward_proxy
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.http.dynamic_forward_proxy.v3.FilterConfig
          - name: envoy.filters.http.buffer
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.http.buffer.v3.Buffer
              max_request_bytes: 4194304
          - name: envoy.filters.http.router
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router

  clusters:
  - name: dynamic_forward_proxy_cluster
    lb_policy: CLUSTER_PROVIDED
    cluster_type:
      name: envoy.clusters.dynamic_forward_proxy
      typed_config:
        "@type": type.googleapis.com/envoy.extensions.clusters.dynamic_forward_proxy.v3.ClusterConfig

  - name: server1
    connect_timeout: 0.25s
    type: STRICT_DNS
    lb_policy: ROUND_ROBIN
    load_assignment:
      cluster_name: server1
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: server1
                port_value: 12345

Logs:

[2026-03-26 15:31:32.776][26][debug][conn_handler] [source/common/listener_manager/active_tcp_listener.cc:160] [Tags: "ConnectionId":"13"] new connection from 192.168.65.1:30028
[2026-03-26 15:31:32.776][26][debug][http] [source/common/http/conn_manager_impl.cc:394] [Tags: "ConnectionId":"13"] new stream
[2026-03-26 15:31:32.777][26][debug][http] [source/common/http/conn_manager_impl.cc:1291] [Tags: "ConnectionId":"13","StreamId":"282741079585230665"] request headers complete (end_stream=false):
':authority', 'localhost:10000'
':path', '/redirect_with_header'
':method', 'POST'
'user-agent', 'python-requests/2.32.5'
'accept-encoding', 'gzip, deflate, zstd'
'accept', '*/*'
'connection', 'keep-alive'
'content-length', '3000000'

[2026-03-26 15:31:32.777][26][debug][connection] [./source/common/network/connection_impl.h:101] [Tags: "ConnectionId":"13"] current connecting state: false
[2026-03-26 15:31:32.777][26][debug][http] [source/common/http/filter_manager.cc:1648] [Tags: "ConnectionId":"13","StreamId":"282741079585230665"] setting buffer limit to 4194304
[2026-03-26 15:31:32.808][26][debug][http] [source/common/http/conn_manager_impl.cc:1274] [Tags: "ConnectionId":"13","StreamId":"282741079585230665"] request end stream timestamp recorded
[2026-03-26 15:31:32.808][26][debug][router] [source/common/router/router.cc:537] [Tags: "ConnectionId":"13","StreamId":"282741079585230665"] cluster 'server1' match for URL '/redirect_with_header'
[2026-03-26 15:31:32.808][26][debug][router] [source/common/router/router.cc:809] [Tags: "ConnectionId":"13","StreamId":"282741079585230665"] router decoding headers:
':authority', 'localhost:10000'
':path', '/redirect_with_header'
':method', 'POST'
':scheme', 'http'
'user-agent', 'python-requests/2.32.5'
'accept-encoding', 'gzip, deflate, zstd'
'accept', '*/*'
'content-length', '3000000'
'x-forwarded-proto', 'http'
'x-request-id', '56247295-476a-436c-a492-07fa1101a0a3'
'x-envoy-expected-rq-timeout-ms', '15000'

[2026-03-26 15:31:32.808][26][debug][pool] [source/common/conn_pool/conn_pool_base.cc:330] [Tags: "ConnectionId":"6"] using existing fully connected connection
[2026-03-26 15:31:32.808][26][debug][pool] [source/common/conn_pool/conn_pool_base.cc:247] [Tags: "ConnectionId":"6"] creating stream
[2026-03-26 15:31:32.808][26][debug][router] [source/common/router/upstream_request.cc:599] [Tags: "ConnectionId":"13","StreamId":"282741079585230665"] pool ready
[2026-03-26 15:31:32.808][26][debug][router] [source/common/router/router.cc:1025] The request payload has at least 6000000 bytes data which exceeds buffer limit 4194304. Marking request as buffer overflowed to cancel internal redirects.
[2026-03-26 15:31:32.809][26][debug][http] [source/common/http/conn_manager_impl.cc:2004] [Tags: "ConnectionId":"13","StreamId":"282741079585230665"] Read-disabling downstream stream due to filter callbacks.
[2026-03-26 15:31:32.809][26][debug][http] [source/common/http/conn_manager_impl.cc:1994] [Tags: "ConnectionId":"13","StreamId":"282741079585230665"] Read-enabling downstream stream due to filter callbacks.
[2026-03-26 15:31:32.809][26][debug][connection] [source/common/network/connection_impl.cc:638] [Tags: "ConnectionId":"6"] onAboveWriteBufferHighWatermark
[2026-03-26 15:31:32.809][26][debug][http] [source/common/http/conn_manager_impl.cc:2004] [Tags: "ConnectionId":"13","StreamId":"282741079585230665"] Read-disabling downstream stream due to filter callbacks.
[2026-03-26 15:31:32.809][26][debug][client] [source/common/http/codec_client.cc:150] [Tags: "ConnectionId":"6"] encode complete
[2026-03-26 15:31:32.810][26][debug][connection] [source/common/network/connection_impl.cc:627] [Tags: "ConnectionId":"6"] onBelowWriteBufferLowWatermark
[2026-03-26 15:31:32.810][26][debug][http] [source/common/http/conn_manager_impl.cc:1994] [Tags: "ConnectionId":"13","StreamId":"282741079585230665"] Read-enabling downstream stream due to filter callbacks.
[2026-03-26 15:31:32.811][26][debug][client] [source/common/http/codec_client.cc:137] [Tags: "ConnectionId":"6"] response complete
[2026-03-26 15:31:32.811][26][debug][router] [source/common/router/router.cc:1687] [Tags: "ConnectionId":"13","StreamId":"282741079585230665"] upstream headers complete: end_stream=true
[2026-03-26 15:31:32.811][26][debug][router] [source/common/router/router.cc:1974] [Tags: "ConnectionId":"13","StreamId":"282741079585230665"] attempting internal redirect
[2026-03-26 15:31:32.811][26][debug][router] [source/common/router/router.cc:1133] Executing cleanup(): resetting retry_state_ and disabling timers
[2026-03-26 15:31:32.811][26][debug][http] [source/common/http/conn_manager_impl.cc:1948] [Tags: "ConnectionId":"13","StreamId":"282741079585230665"] encoding headers via codec (end_stream=true):
':status', '301'
'date', 'Thu, 26 Mar 2026 15:31:32 GMT'
'server', 'envoy'
'content-length', '0'
'location', 'http://server2:12346/redirect_with_header'
'x-internal-redirect', 'true'
'x-envoy-upstream-service-time', '1'

[2026-03-26 15:31:32.811][26][debug][http] [source/common/http/conn_manager_impl.cc:2063] [Tags: "ConnectionId":"13","StreamId":"282741079585230665"] Codec completed encoding stream.
[2026-03-26 15:31:32.811][26][debug][router] [source/common/router/router.cc:1133] Executing cleanup(): resetting retry_state_ and disabling timers
[2026-03-26 15:31:32.811][26][debug][pool] [source/common/http/http1/conn_pool.cc:61] [Tags: "ConnectionId":"6"] response complete
[2026-03-26 15:31:32.811][26][debug][pool] [source/common/conn_pool/conn_pool_base.cc:282] [Tags: "ConnectionId":"6"] destroying stream: 0 active remaining, readyForStream false, currentUnusedCapacity 1
[2026-03-26 15:31:32.812][26][debug][connection] [source/common/network/connection_impl.cc:777] [Tags: "ConnectionId":"13"] remote close
[2026-03-26 15:31:32.812][26][debug][connection] [source/common/network/connection_impl.cc:317] [Tags: "ConnectionId":"13"] closing socket: 0

Call Stack:
N/A

Metadata

Metadata

Assignees

Labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions