Copy http headers + (override x-b3 in ingress GW)


I wonder what’s the best way to copy headers from an HTTP request.

I tried some VirtualService configuration, but I was sure that it was not going to work based on Headers reference [1]. The test was:

kind: VirtualService
group: front
name: myapp-front

  • myapp-gw
  • myapp.x.y.z
  • headers:
    new-header: request.headers[“old-header”]
    • destination:
      host: myapp

In this test, I just tried to copy a header coming in the request (old-header) to new-header. But what I got was the ‘new-header’ with value ‘request.headers[“old-header”]’, so no resolution was performed (as expected).

Has anybody done something similiar before? It seems a very simple use case.

What could be a different approach? EnvoyFilters?




Hi David,

Unfortunately, VirtualService’s don’t support being able to copy one header value to another. Envoy does support a few dynamic values listed here:

Any other dynamic values than those listed in the envoy docs and you would have to use filters


Thanks Greg.

As I said, I finally had to use an EnvoyFilter. But now I have a different problem. Let me explain it.

I am trying to copy a header in the Ingress GW, so every request going through the Ingress GW, would have a copy of a given header to a new one. This is working if I use a normal header as the one mentioned above: copy from old-header to new-header.
What it is not working in my case is if i want to copy a certain header containing the “traceId” to the x-b3-traceid header. It seems it is reserved somehow, but I would like to override it so Envoy does not have to create a new one…

This is mainly to transform certain custom tracing stuff outside the service mesh to the x-b3 format within the mesh.

Any idea of how to achieve this? I also notice that the old-header/new-header copy is taken place when invoking the upstream service from the Ingress GW, but I would expect it to happen in first place in the Ingress GW, so I would see the new header already in the HTTP request headers log in the GW.

Find the EnvoyFilter definition here

I also tried to use x-client-trace-id and x-envoy-force-trace but nor really know the way they work and if they are also supported in this case.


Using x-client-trace-id should work, and would be the preferred way of marrying external trace ids with the envoy mechanisms for generating trace ids, as far as I am aware. This header should be generated by the client (before Ingress GW) and be globally-unique. Envoy should then merge this into the x-request-id that is used within the mesh with tracing (including generation of headers, etc.).

Disclaimer: I’ve not tried this, but know of people that have.

Thanks Douglas.

In our case, we cannot change anything on the client side, so that’s why I am trying to copy headers in the Ingress GW… but it seems that the filter is executed too late.