Routing decides what happens to each HTTP request: the connection manager picks a virtual host by the request's authority, then walks that host's routes in order and takes the first match. Use it to send traffic to clusters, split by weight, redirect, rewrite, or answer without an upstream.
This page maps what a route can do; the route reference has the full field tables.
A route configuration
route_config:
name: local_routes
virtual_hosts:
- name: api
domains: ["api.example.com"]
routes:
- match: { prefix: "/" }
route: { cluster: api }
domains accepts exact hosts, suffix wildcards (*.example.com), prefix wildcards (example.*), and the catch-all *. The most specific domain wins across virtual hosts: exact beats suffix, suffix beats prefix, and longer matches beat shorter ones.
Matching requests
A match combines a path rule with optional header and query-parameter rules; all must hold:
- match:
path_separated_prefix: "/api/v1" # or prefix, path (exact), safe_regex
headers:
- name: ":method"
string_match: { exact: "GET" }
query_parameters:
- name: version
string_match: { exact: "v1" }
route: { cluster: api }
Path rules are prefix, path (exact), safe_regex, or path_separated_prefix (matches /api/v1 and /api/v1/... but not /api/v1beta); set case_sensitive: false to ignore case. Header matchers support exact, prefix, suffix, contains, regex and present patterns, plus invert_match; the pseudo-headers :method, :path and :scheme are matchable. Query parameters match by string pattern or presence.
Actions
Each route takes exactly one action. Route to a cluster (as above), split across weighted clusters:
route:
weighted_clusters:
clusters:
- name: api-v1
weight: 90
- name: api-v2
weight: 10
pick the cluster from a request header (route: { cluster_header: x-cluster }), redirect:
redirect:
response_code: MOVED_PERMANENTLY
host_redirect: example.com
path_redirect: "/new"
or answer directly:
direct_response:
status: 404
body: { inline_string: "not found" }Rewrites
A route action can rewrite the path before forwarding — prefix_rewrite replaces the matched prefix, regex_rewrite applies a pattern; the two are mutually exclusive:
route:
cluster: api
prefix_rewrite: "/internal"Header mutation
Request and response headers can be added or removed at the route configuration, virtual host, and route levels:
request_headers_to_add:
- header: { key: x-env, value: prod }
append_action: OVERWRITE_IF_EXISTS_OR_ADD
request_headers_to_remove: [x-debug]
By default outer levels apply last and win; set most_specific_header_mutations_wins: true on the route configuration to reverse that.
Timeouts, retries, and upgrades
A route's upstream timeout defaults to 15s; timeout: 0s disables it. A retry_policy on the route or virtual host retries safe failures — see health checks and resilience. WebSocket upgrades are enabled per connection manager or per route:
route:
cluster: api
upgrade_configs:
- upgrade_type: websocket
HTTP CONNECT upgrades are not supported.
Routes can also come from a control plane instead of the file: point the connection manager at rds with an ADS config source and the same route configuration arrives over xDS — see xDS control planes.
Verify
Send a request with the virtual host's domain:
curl -s -H "Host: api.example.com" http://127.0.0.1:8080/api/v1/status -o /dev/null -w "%{http_code}\n"200Limits
- First match wins — order routes from most to least specific, catch-all last.
- CONNECT upgrades, request mirroring, and hedging are not supported.
- Weighted-cluster entries carry only
nameandweight; per-entry header mutation is not supported. - Header
range_matchand route-level CORS policy are not supported (CORS is an HTTP filter). - Per-route filter overrides (
typed_per_filter_config) must name a configured filter; replacement config is accepted for the local rate limit and RBAC filters only.
Every match, action, and policy field is listed in the route reference.