Skip to content
This repository was archived by the owner on Apr 24, 2025. It is now read-only.
This repository was archived by the owner on Apr 24, 2025. It is now read-only.

GetHttpResponseBody with large file #359

@RoeiGanor

Description

@RoeiGanor

Describe the bug / error

Issue with the wasm plugin while envoy serving relatively large file (approximately larger than 1mb).
When there is a large file, the request is being drop and the client fail to download the file.
The code is very similar to an example in this repository:

func (ctx *setBodyContext) OnHttpResponseBody(bodySize int, endOfStream bool) types.Action {

Our code:

func (ctx *httpContext) OnHttpResponseBody(bodySize int, endOfStream bool) types.Action {
	proxywasm.LogErrorf("Enter OnHttpResponseBody %d %t %d %d", bodySize, endOfStream, ctx.totalResponseBodySize, ctx.maxResponseBodySize)
	
	if !endOfStream {
		return types.ActionPause
	}

	if ctx.totalResponseBodySize > ctx.maxResponseBodySize {
		ctx.responseBodyTooLarge = true
	} else {
		reqBody, err := proxywasm.GetHttpResponseBody(0, ctx.totalResponseBodySize)
		if err != nil {
			proxywasm.LogErrorf("Failed to get response body: %v", err)
			return types.ActionContinue
		}

		// Saving the body for later
		ctx.responseBody = reqBody
	}

	return types.ActionContinue
}

The issue occurs when the envoy is serving a large file, but the endofstream is never true.
This is a small file (4064 bytes) example:

wasm log: Enter OnHttpResponseBody 4064 false 0 2147483647
wasm log: Enter OnHttpResponseBody 4064 true 4064 2147483647

This is a large file (2698669 bytes) example, the file is being dropped before the endofstream result in true

wasm log: Enter OnHttpResponseBody 114532 false 0 2147483647
wasm log: Enter OnHttpResponseBody 114532 false 114532 2147483647
wasm log: Enter OnHttpResponseBody 1047900 false 229064 2147483647

When the changing the types.ActionPause in !endOfStream to types.ActionContinue, the file is not being dropped:

func (ctx *httpContext) OnHttpResponseBody(bodySize int, endOfStream bool) types.Action {
	proxywasm.LogErrorf("Enter OnHttpResponseBody %d %t %d %d", bodySize, endOfStream, ctx.totalResponseBodySize, ctx.maxResponseBodySize)

	if !endOfStream {
		return types.ActionContinue
	}

	if ctx.totalResponseBodySize > ctx.maxResponseBodySize {
		ctx.responseBodyTooLarge = true
	} else {
		reqBody, err := proxywasm.GetHttpResponseBody(0, ctx.totalResponseBodySize)
		if err != nil {
			proxywasm.LogErrorf("Failed to get response body: %v", err)
			return types.ActionContinue
		}

		// Saving the body for later
		ctx.responseBody = reqBody
	}

	return types.ActionContinue
}

But another issue arise from this case, the GetHttpResponseBody being failed after 2 executions, which means you cant really retrieve the whole response body.
This is a large file (2698669 bytes) example:

wasm log: Enter OnHttpResponseBody 65536 false 0 2147483647
wasm log: Enter OnHttpResponseBody 1048576 false 0 2147483647
wasm log: Enter OnHttpResponseBody 1048576 false 0 2147483647
wasm log: Enter OnHttpResponseBody 535981 false 0 2147483647
wasm log: Enter OnHttpResponseBody 0 true 0 2147483647

What is your Envoy/Istio version?

envoy version 1.24.0

What is the SDK version?

v0.19.0

What is your TinyGo version?

tinygo version 0.25.0 darwin/amd64 (using go version go1.18.3 and LLVM version 14.0.0)

URL or snippet of your code including Envoy configuration

static_resources:

  listeners:
  - address:
      socket_address:
        address: 127.0.0.1
        port_value: 8086
    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
          use_remote_address: true
          codec_type: AUTO
          stat_prefix: ingress_https
          access_log:
            - name: envoy.access_loggers.file
              typed_config:
                "@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog
                path: "./access.log"
          http_filters:
            - name: envoy.filters.http.wasm
              typed_config:
                "@type": type.googleapis.com/udpa.type.v1.TypedStruct
                type_url: type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm
                value:
                  config:
                    fail_open: true
                    configuration:
                      "@type": type.googleapis.com/google.protobuf.StringValue
                      value: <plugin-configuration>
                    vm_config:
                      runtime: "envoy.wasm.runtime.v8"
                      code:
                        local:
                          filename: "./wib-proxy-wasm-tap.wasm"
            - name: envoy.filters.http.router
              typed_config:
                "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
          route_config:
            name: local_route
            virtual_hosts:
            - name: passthrough
              domains: ["*"]
              routes:
              - match:
                  prefix: "/"
                route:
                  cluster: service-http

  clusters:
  - name: service-http
    type: STRICT_DNS
    dns_lookup_family: V4_ONLY
    lb_policy: ROUND_ROBIN
    load_assignment:
      cluster_name: service-http
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: 127.0.0.1
                port_value: 8080
  - name: wib
    connect_timeout: 5000s
    type: STRICT_DNS
    dns_lookup_family: V4_ONLY
    lb_policy: round_robin
    load_assignment:
      cluster_name: wib
      endpoints:
        - lb_endpoints:
            - endpoint:   
                address:
                  socket_address:
                    address: 127.0.0.1
                    port_value: 9094

Additional context (Optional)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions