0

By following envoy filter to intercept upstream response I was able to create envoy filter and it's partially working as well. I can see my https request is being interpreted by the envoy filter and can see the updated response getting printed in the logs.

However, in the Postman I am not getting response back and it is waiting indefinitely. The access logs shows the 400 response being logged. Wondering why the postman is not receiving the response body.

apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: test-http-filter
  namespace: test
spec:
  workloadSelector:
    labels:
      app: istio
  configPatches:
  - applyTo: HTTP_FILTER
    match:
      context: GATEWAY
      listener:
        filterChain:
          filter:
            name: envoy.filters.network.http_connection_manager
            subfilter: 
              name: envoy.filters.http.router
    patch:
      operation: INSERT_AFTER  # INSER_BEFORE also tried
      value: 
       name: envoy.custom-resp
       typed_config:
          "@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua"
          inlineCode: |
            function envoy_on_response(response_handle) 
                  if response_handle:headers():get(":status") == "404" or response_handle:headers():get(":status") == "400" then
                    local body = response_handle:body()
                    local jsonString = tostring(body:getBytes(0, body:length()))
                    response_handle:logErr("Status: "..response_handle:headers():get(":status"))
                    response_handle:logErr("JSONString: "..jsonString)
                    jsonString = jsonString:gsub("mystring", "myUpdatedstring")
                    response_handle:body():setBytes(jsonString)
                  end
                end

Anyone experienced similar issue with response_bandle:body():setBytes() . The original post had response_handle():set() which is throwing error in my case.

NewBee
  • 228
  • 4
  • 14
  • Please check if the response has body. Also check by passing the optional parameter always_wrap_body. More details are in envoy documentation https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/lua_filter#body – Nataraj Medayhal Jul 19 '22 at 09:17
  • yes. it has response body which I am storing in jsonString. I tried the always_wrap_body with both true and false. no change in behaviour – NewBee Jul 19 '22 at 11:11
  • I am the author of the link answer. I was able to get it working with the exact config (except deployed in the istio-system namespace with the default workloadSelector of the ingress gateway) and the INSERT_BEFORE. What are you trying to achieve? Have the rewrite on every request or just a special one? The namespace and the selector wouldn't work with the default config. Also the INSERT_AFTER shouldn't work, since `http.router` must be the last in the chain. – Chris Jul 20 '22 at 18:46
  • I would recommand to start with something simple, like `response_handle:headers():add("X-User-Header", "worked")` on every request. If that works, add the rest to find out if some of your code will break the filter. – Chris Jul 20 '22 at 18:47
  • thanks chris. you are right. insert_after isn't working. somehow while trying multiple values, i haven't noticed it. I tested the headers() by setting a dummy value. I can see the new header. Only the response body is not getting loaded. – NewBee Jul 21 '22 at 15:16

1 Answers1

2

Please change patch operation from "operation: INSERT_AFTER" to "operation: INSERT_BEFORE" as the filter is getting applied after sending the response. Update the envoy filter as below

patch:
  operation: INSERT_BEFORE

Corrected the Envoy Filter

apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: test-http-filter
  namespace: istio-system
spec:
  workloadSelector:
    labels:
      istio: ingressgateway
  configPatches:
  - applyTo: HTTP_FILTER
    match:
      context: GATEWAY
      listener:
        filterChain:
          filter:
            name: envoy.filters.network.http_connection_manager
    patch:
      operation: INSERT_BEFORE
      value: 
       name: envoy.lua
       typed_config:
          "@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua"
          inlineCode: |
            function envoy_on_response(response_handle) 
                  if response_handle:headers():get(":status") == "404" or response_handle:headers():get(":status") == "400" then
                    local body = response_handle:body()
                    local jsonString = tostring(body:getBytes(0, body:length()))
                    response_handle:logErr("Status: "..response_handle:headers():get(":status"))
                    response_handle:logErr("JSONString: "..jsonString)
                    jsonString = jsonString:gsub("mystring", "myUpdatedstring")
                    response_handle:body():setBytes(jsonString)
                  end
                end
Chris
  • 5,109
  • 3
  • 19
  • 40
Nataraj Medayhal
  • 980
  • 1
  • 2
  • 12