Search code examples
istioenvoyproxyistio-sidecar

envoy filter to intercept upstream response


I have written the ext_authz filter for envoy and have basic understanding of how envoy filters done. But now I want to filter the response coming back from the upstream. Specifically, I want to handle two things:

  1. Intercept data/jsonBody coming from upstream and Filter/Modify the responseJsonBody based on some business rule before envoy sends back to downstream.

  2. If upstream is down(when http response code 408-Timeout), I want to save the post-request to async-msg-que and send back a 202-Accepted back to downstream. This way, when the upstream comes back it will process pending post-request from it's async-msg-que.

Is there a existing filter I can use for these purpose or what is the right way to do this using envoy-proxy sidecar.

Thanks.


Solution

  • You need to write the filter yourself using lua:

    apiVersion: networking.istio.io/v1alpha3
    kind: EnvoyFilter
    metadata:
      name: custom-filter
      namespace: some-namespace
    spec:
      workloadSelector:
        labels:
          istio: ingressgateway
      configPatches:
      - applyTo: HTTP_FILTER
        match:
          context: GATEWAY
          listener:
            filterChain:
              filter:
                name: "envoy.filters.network.http_connection_manager"
                subFilter:
                  name: "envoy.extAuthz" # name of your ext_authz filter
        patch:
          operation: INSERT_AFTER
          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") == "408" then
                    -- send message depending on your queue, eg via httpCall()
                    -- Overwrite status and body
                    response_handle:headers():replace(":status", "202")
                  else 
                    -- get response body as jsonString
                    local body = response_handle:body()
                    local jsonString = tostring(body:getBytes(0, body:length()))
                    -- do something, eg replace secret by regex 
                    jsonString = jsonString:gsub("(foo|bar)", "")
                    response_handle:body():set(jsonString)
                  end
                end
    

    Note that you need to handle timeouts of the queue somehow.

    Envoy With Lua

    httpCall

    Lua Docs