proxy-wasm / proxy-wasm-rust-sdk

WebAssembly for Proxies (Rust SDK)

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

WASM filter doesn't progress from `on_http_[request|response]_header` to `on_http_[request|response]_body`

adalrsjr1 opened this issue · comments

I'm trying to create a filter that access the body content of an HTTP request/response, but it fails. The code can't progress from on_http_response_headers to on_http_response_body. I'm using a customized code baded onhttp_body example.

I noticed that I can't go from on_http_request_headers to on_http_request_body as well.

My toy application is an Nginx+Istio proxy on Kubernetes. Following are the filter configuration and the code.

Do I missing anything?

apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: my-wasm-filter
spec:
  workloadSelector:
    labels:
      app: wasm-filter
  configPatches:
  - applyTo: HTTP_FILTER
    match:
      context: ANY # I've tried SIDECAR_INBOUND with no sucess as well
      listener:
        filterChain:
          filter:
            name: envoy.filters.network.http_connection_manager
            subFilter:
              name: envoy.filters.http.router
    patch:
      operation: INSERT_BEFORE
      value:
        name: my-wasm-filter
        typed_config:
          '@type': type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm
          config:
            root_id: "my-wasm-filter-root-0.1"
            vm_config:
              code:
                local:
                  filename: /wasm-filter/myenvoyfilter.wasm
              runtime: envoy.wasm.runtime.v8
              vm_id: my-wasm-filter-0.1
---
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: my-wasm-filter-config
spec:
  configPatches:
  - applyTo: EXTENSION_CONFIG
    patch:
      operation: ADD
      value:
        name: my-wasm-filter
        typed_config:
          '@type': type.googleapis.com/udpa.type.v1.TypedStruct
          type_url: type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm
          value:
            config:
              root_id: "my-wasm-filter-root-0.1"
              vm_config:
                vm_id: "my-wasm-filter-0.1"
                code:
                  local:
                    filename: file:///wasm-filter/myenvoyfilter.wasm 
                runtime: envoy.wasm.runtime.v8
    fn on_http_response_headers(&mut self, _num_headers: usize, _end_of_stream: bool) -> Action {
        match self.get_shared_data(":path") {
            (None, _) => {
                warn!("cannot retrieve :path from shared data");
            },
            (Some(path), _) => {
                debug!("[{}] on response headers {}", self.context_id, str::from_utf8(&path).unwrap());
            }
        }
        debug!("still on response headers");
        
        // If there is a Content-Length header and we change the length of
        // the body later, then clients will break. So remove it.
        // We must do this here, because once we exit this function we
        // can no longer modify the response headers.
        self.set_http_response_header("content-length", None);
        Action::Continue
    }

    fn on_http_response_body(&mut self, _body_size: usize, _end_of_stream: bool) -> Action {
        debug!("on response body");
        if !_end_of_stream {
            // Wait -- we'll be called again when the complete body is buffered
            // at the host side.
            trace!("waiting end of stream");
            return Action::Pause;
        }
        match self.get_shared_data(":path") {
            (None, _) => {
                warn!("cannot retrieve :path from shared data");
            },
            (Some(path), _) => {
                debug!("[{}] on response body {}", self.context_id, str::from_utf8(&path).unwrap());
            }
        }

        // Replace the message body if it contains the text "secret".
        // Since we returned "Pause" previuously, this will return the whole body.
        // if let Some(body_bytes) = self.get_http_response_body(0, body_size) {
        //     let body_str = String::from_utf8(body_bytes).unwrap();
        //     if body_str.contains("secret") {
        //         let new_body = format!("Original message body ({} bytes) redacted.", body_size);
        //         self.set_http_response_body(0, body_size, &new_body.into_bytes());
        //     }
        // }
        Action::Continue
    }

Here is the part of the log referent to HTTP response.

2022-08-03T14:15:04.691239Z     debug   envoy wasm      wasm log my-wasm-filter-0.1: [6] on response headers b                                                                                                                                                                                                                           [5/1795]
2022-08-03T14:15:04.691267Z     trace   envoy wasm      [vm<-host] env.proxy_log return: 0                                                                                                                                                                                                                                                       
2022-08-03T14:15:04.691283Z     trace   envoy wasm      [vm->host] env.proxy_log(1, 1114328, 25)                                                                                                                                                                                                                                                 
2022-08-03T14:15:04.691367Z     debug   envoy wasm      wasm log my-wasm-filter-0.1: still on response headers                                                                                                                                                                                                                                   
2022-08-03T14:15:04.691374Z     trace   envoy wasm      [vm<-host] env.proxy_log return: 0                                                                                                                                                                                                                                                       
2022-08-03T14:15:04.691386Z     trace   envoy wasm      [vm->host] env.proxy_remove_header_map_value(2, 1051436, 14)                                                                                                                                                                                                                             
2022-08-03T14:15:04.691468Z     trace   envoy wasm      [vm<-host] env.proxy_remove_header_map_value return: 0
2022-08-03T14:15:04.691486Z     trace   envoy wasm      [host<-vm] proxy_on_response_headers return: 0
2022-08-03T14:15:04.693984Z     debug   envoy wasm      expr_evaluate value error: No value with name "downstream_peer" found in Activation
2022-08-03T14:15:04.694185Z     trace   envoy wasm      wasm log stats_inbound stats_inbound: [extensions/stats/plugin.cc:628]::report() Failed to evaluate expression: <downstream_peer.cluster_id>
2022-08-03T14:15:04.694397Z     debug   envoy wasm      wasm log stats_inbound stats_inbound: [extensions/stats/plugin.cc:640]::report() metricKey cache hit , stat=16
2022-08-03T14:15:04.694818Z     debug   envoy wasm      wasm log stats_inbound stats_inbound: [extensions/stats/plugin.cc:640]::report() metricKey cache hit , stat=18
2022-08-03T14:15:04.694902Z     debug   envoy wasm      wasm log stats_inbound stats_inbound: [extensions/stats/plugin.cc:640]::report() metricKey cache hit , stat=22
2022-08-03T14:15:04.694917Z     debug   envoy wasm      wasm log stats_inbound stats_inbound: [extensions/stats/plugin.cc:640]::report() metricKey cache hit , stat=26
2022-08-03T14:15:04.694999Z     trace   envoy wasm      [host->vm] proxy_on_log(6)
2022-08-03T14:15:04.695034Z     trace   envoy wasm      [host<-vm] proxy_on_log return: void
2022-08-03T14:15:04.695096Z     trace   envoy wasm      [host->vm] proxy_on_done(6)
2022-08-03T14:15:04.695125Z     trace   envoy wasm      [host<-vm] proxy_on_done return: 1
2022-08-03T14:15:04.695129Z     trace   envoy wasm      [host->vm] proxy_on_delete(6)
2022-08-03T14:15:04.695181Z     trace   envoy wasm      [host<-vm] proxy_on_delete return: void
[2022-08-03T14:15:04.678Z] "HEAD /b HTTP/1.1" 404 - via_upstream - "-" 0 0 13 2 "-" "curl/7.47.0" "de2f78e1-9f58-9c2f-a7c0-58c167d92999" "wasm-filter" "10.244.0.41:80" inbound|80|| 127.0.0.6:55503 10.244.0.41:80 10.244.0.15:43030 - default

It's a HEAD request, so there is no response body sent by the upstream, which is why on_http_response_body is not called.

oh man, it is embarassing my lack of attention on such silly thing 😅
I changed my curl -I to curl and it worked as expected.

Closing the issue.