Envoy’s route configuration doesn’t just match requests; it actively transforms them, and headers are its primary canvas.
Let’s see how Envoy can manipulate request headers using a simple HTTP filter. Imagine we have an upstream service that expects a specific X-User-Id header, but our incoming requests don’t always provide it. We can use Envoy to add it.
static_resources:
listeners:
- name: listener_0
address:
socket_address:
address: 0.0.0.0
port_value: 8080
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: ingress_http
route_config:
name: local_route
virtual_hosts:
- name: local_service
domains: ["*"]
routes:
- match:
prefix: "/"
route:
cluster: some_service
# Add a header
request_headers_to_add:
- header:
key: "X-User-Id"
value: "default-user-123"
# Remove a header
request_headers_to_remove:
- "X-Forwarded-Client-Cert"
# Rewrite a header
request_headers_to_manipulate:
- header:
key: "Host"
# This uses string interpolation with the original value
# If the original Host was "example.com", it becomes "rewritten-example.com"
value_substitution: "rewritten-%s"
# This is the key for manipulation, not a direct value
# The actual manipulation happens based on the 'value_substitution' field
operation:
op: "POST_REPLACE" # POST_REPLACE is used for substitution
http_filters:
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
clusters:
- name: some_service
connect_timeout: 0.25s
type: LOGICAL_DNS
# This is a placeholder; replace with your actual upstream service
lb_policy: ROUND_ROBIN
# Example DNS for a local service
dns_lookup_family: V4_ONLY
load_assignment:
cluster_name: some_service
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: 127.0.0.1
port_value: 9000
When a request hits Envoy on port 8080, it first enters the http_connection_manager. The route_config then applies transformations. In this example:
- Adding Headers: The
request_headers_to_addsection injects a new header namedX-User-Idwith the valuedefault-user-123into every request that matches this route. This is useful for adding required metadata that might be missing from the client. - Removing Headers:
request_headers_to_removeeliminates theX-Forwarded-Client-Certheader. This is often done for security or to prevent upstream services from seeing potentially sensitive client certificate information that Envoy has already processed. - Rewriting Headers: The
request_headers_to_manipulatesection allows for more complex modifications. Here, we’re targeting theHostheader. Thevalue_substitution: "rewritten-%s"tells Envoy to take the original value of theHostheader and prependrewritten-to it. The%sis a placeholder for the original value. Theoperation: { op: "POST_REPLACE" }specifies that this substitution should occur after the header is potentially added or if it already exists. This is powerful for dynamically altering destination information or injecting context.
The core problem this solves is achieving granular control over request metadata as it flows through your network. Envoy acts as an intelligent proxy, able to enrich, sanitize, or modify headers based on complex routing rules, without requiring changes to your application code. This separation of concerns simplifies microservice communication and allows for centralized policy enforcement.
The value_substitution field supports string interpolation using %s for the original header value, and also allows for referencing other headers using the syntax %{HEADER_NAME}. For instance, you could rewrite a User-Agent header to include the original User-Agent and a specific internal identifier: value_substitution: "%{User-Agent} (internal-proxy)". This allows for dynamic construction of header values based on existing request context.
The next step in header manipulation is often implementing more advanced transformations using Lua or WebAssembly filters for logic that goes beyond simple additions, removals, or substitutions.