envoyproxy / envoy

Cloud-native high-performance edge/middle/service proxy
https://www.envoyproxy.io
Apache License 2.0
24.94k stars 4.8k forks source link

Lua vs Wasm filter on failures during filter chain #36791

Open dragoscalinescu opened 5 days ago

dragoscalinescu commented 5 days ago

I have an envoy configuration which contains 3 filters:

Something like this

          - name: envoy.filters.http.ext_authz
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz
              http_service:
                path_prefix: "/429"
                server_uri:
                  uri: "http://httpstat.us/429"
                  cluster: "ext_authz-http-service"
                  timeout: "3s"
          - name: envoy.filters.http.lua
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua
              default_source_code:
                inline_string:
                  function envoy_on_request(request_handle)
                    request_handle:logInfo("Hello from lua filter")
                  end
                  function envoy_on_response(response_handle)
                    response_handle:logInfo("Bye from lua filter")
                  end
          - name: envoy.filters.http.wasm
            typed_config:
              "@type": "type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm"
              config:
                name: config-name
                root_id: id
                vm_config:
                  vm_id: vm.id
                  runtime: envoy.wasm.runtime.v8
                  code:
                    local:
                      filename: /path/to/my.wasm
                  allow_precompiled: true

When trying this, I only get the Lua envoy_on_response callback triggered, but not the on_http_response_headers nor the on_http_response_body wasm callbacks.

Some trace logs:

[2024-10-23 19:42:14.759][53500569][trace][misc] [source/common/event/scaled_range_timer_manager_impl.cc:60] enableTimer called on 0x600000971580 for 300000ms, min is 300000ms
[2024-10-23 19:42:14.759][53500569][trace][http] [source/common/http/filter_manager.cc:1197] [Tags: "ConnectionId":"5","StreamId":"12470536000766714697"] encode headers called: filter=envoy.filters.http.wasm status=0
[2024-10-23 19:42:14.759][53500569][trace][lua] [./source/extensions/filters/common/lua/lua.h:149] creating N5Envoy10Extensions11HttpFilters3Lua19StreamHandleWrapperE at 0x11a356b80
[2024-10-23 19:42:14.760][53500569][info][lua] [source/extensions/filters/http/lua/lua_filter.cc:920] script log: Bye from lua filter
[2024-10-23 19:42:14.760][53500569][debug][lua] [source/extensions/filters/common/lua/lua.cc:39] coroutine finished
[2024-10-23 19:42:14.760][53500569][trace][lua] [./source/extensions/filters/common/lua/lua.h:210] marking dead N5Envoy10Extensions11HttpFilters3Lua19StreamHandleWrapperE at 0x11a356b80
[2024-10-23 19:42:14.760][53500569][trace][http] [source/common/http/filter_manager.cc:1197] [Tags: "ConnectionId":"5","StreamId":"12470536000766714697"] encode headers called: filter=envoy.filters.http.lua status=0
[2024-10-23 19:42:14.760][53500569][trace][ext_authz] [source/extensions/filters/http/ext_authz/ext_authz.cc:186] [Tags: "ConnectionId":"5","StreamId":"12470536000766714697"] ext_authz filter has 0 response header(s) to add and 0 response header(s) to set to the encoded response:
[2024-10-23 19:42:14.760][53500569][trace][http] [source/common/http/filter_manager.cc:1197] [Tags: "ConnectionId":"5","StreamId":"12470536000766714697"] encode headers called: filter=envoy.filters.http.ext_authz status=0
[2024-10-23 19:42:14.760][53500569][debug][http] [source/common/http/conn_manager_impl.cc:1863] [Tags: "ConnectionId":"5","StreamId":"12470536000766714697"] encoding headers via codec (end_stream=false):

Is this expected? Envoy 1.28 for context

UPDATE: External processor filters seem to behave the same way as the lua one, I am getting a ProcessingRequest for RESPONSE_BODY case. Is there a different behaviour for wasm?

wbpcode commented 4 days ago

Yeah. Seems it's designed as that (although I don't know why). The wasm will be skipped if the request headers is not processed. In your case, the auth will send a local reply and the the request headers won't be processed by the wasm, so, the wasm will be skipped.

johnlanni commented 3 days ago

I think this might be due to implementation, because proxy-wasm defines a stream context that allows the wasm module to restore the context of a specific request during Envoy's asynchronous processing of multiple requests. Since this stream context is only created during the request header phase, if the wasm filter finds that the context has not been created during the response header phase, it will automatically skip.

However, this design isn't necessarily flawed; in fact, I think it might even have some advantages. While it does sacrifice some flexibility, the logic of the wasm plugin can be simpler, as it doesn’t need to account for situations where the decode phase hasn't been passed, leading to missing states.