<p>I need the URI of requests that reach my <code>myapp</code> pods to be rewritten to remove the prefix <code>/foo</code> from the path. For example, a URI <code>/foo/bar</code> should be received as <code>/bar</code>. I am using a GCP load balancer that routes traffic directly to pods. I am not using Istio ingress, so Istio has no control over the load balancer's behavior.</p>
<p>I tried creating a <code>VirtualService</code> to handle the path rewrite:</p>
<pre><code>apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: myapp-route
spec:
  hosts:
  - myapp
  http:
  - match:
    - uri:
        prefix: &quot;/foo/&quot;
    rewrite:
      uri: &quot;/&quot;
    route:
    - destination:
        host: myapp
</code></pre>
<p>(This may not be <em>exactly</em> correct as I adapted/simplified what I tried for the question.)</p>
<p>This works when sending requests from a pod with an Istio sidecar to the <code>myapp</code> service, but not from the load balancer. I can see the URI is being rewritten as it goes out from any other pod, not when it's coming into a <code>myapp</code> pod.</p>
<p>How can I get URI rewriting as an incoming rule?</p>

<p>I found <a href="https://github.com/istio/istio/issues/22290#issuecomment-1317595537" rel="nofollow noreferrer">https://github.com/istio/istio/issues/22290#issuecomment-1317595537</a> which shows how to write a custom <code>EnvoyFilter</code> to do path rewriting and adapted it to my needs. I'm not at all sure if the directives to specify how and where the filter should be applied are correct, but it at least does the prefix rewrite as an inbound rule.</p>
<pre><code>apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: myapp-rewrite-filter
spec:
  workloadSelector:
    labels:
      app: myapp
  configPatches:
    # The first patch adds the lua filter to the listener/http connection manager
  - applyTo: HTTP_FILTER
    match:
      context: SIDECAR_INBOUND
      listener:
        filterChain:
          filter:
            name: &quot;envoy.filters.network.http_connection_manager&quot;
            subFilter:
              name: &quot;envoy.filters.http.router&quot;
    patch:
      operation: INSERT_BEFORE
      value: # lua filter specification
       name: envoy.filters.http.lua
       typed_config:
          &quot;@type&quot;: &quot;type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua&quot;
          inlineCode: |
            function remove_prefix(s, prefix)
              return (s:sub(0, #prefix) == prefix) and s:sub(#prefix+1) or s
            end
            function envoy_on_request(request_handle)
              local filter_name = &quot;SIMPLE_PATH_REWRITER&quot;
              request_handle:logDebug(filter_name .. &quot;: Starting&quot;)

              local prefix = &quot;/foo&quot;
              local path = request_handle:headers():get(&quot;:path&quot;)
              local unprefixed = remove_prefix(path, prefix)

              request_handle:headers():replace(&quot;:path&quot;, unprefixed)

              local msg = filter_name .. &quot;: Path &quot; .. path .. &quot; rewritten to &quot; .. unprefixed
              request_handle:logDebug(msg)
            end
</code></pre>
