--- layout: docs page_title: 'Configuration Entry Kind: Service Router' description: >- The service-router config entry kind controls Connect traffic routing and manipulation at networking layer 7 (e.g. HTTP). --- # Service Router -> **v1.8.4+:** On Kubernetes, the `ServiceRouter` custom resource is supported in Consul versions 1.8.4+.
**v1.6.0+:** On other platforms, this config entry is supported in Consul versions 1.6.0+. The `service-router` config entry kind (`ServiceRouter` on Kubernetes) controls Connect traffic routing and manipulation at networking layer 7 (e.g. HTTP). If a router is not explicitly configured or is configured with no routes then the system behaves as if a router were configured sending all traffic to a service of the same name. ## Interaction with other Config Entries - Service router config entries are a component of [L7 Traffic Management](/docs/connect/l7-traffic-management). - Service router config entries are restricted to only services that define their protocol as HTTP-based via a corresponding [`service-defaults`](/docs/connect/config-entries/service-defaults) config entry or globally via [`proxy-defaults`](/docs/connect/config-entries/proxy-defaults) . - Any route destination that omits the `ServiceSubset` field is eligible for splitting via a [`service-splitter`](/docs/connect/config-entries/service-splitter) should one be configured for that service, otherwise resolution proceeds according to any configured [`service-resolver`](/docs/connect/config-entries/service-resolver). ## Sample Config Entries ### Path prefix matching Route HTTP requests with a path starting with `/admin` to a different service: ```hcl Kind = "service-router" Name = "web" Routes = [ { Match { HTTP { PathPrefix = "/admin" } } Destination { Service = "admin" } }, # NOTE: a default catch-all will send unmatched traffic to "web" ] ``` Route HTTP requests with a path starting with `/admin` to a different service: ```yaml apiVersion: consul.hashicorp.com/v1alpha1 kind: ServiceRouter metadata: name: web spec: routes: - match: http: pathPrefix: /admin destination: service: admin # NOTE: a default catch-all will send unmatched traffic to "web" ``` ### Header/query parameter matching Route HTTP requests with a special url parameter or header to a canary subset: ```hcl Kind = "service-router" Name = "web" Routes = [ { Match { HTTP { Header = [ { Name = "x-debug" Exact = "1" }, ] } } Destination { Service = "web" ServiceSubset = "canary" } }, { Match { HTTP { QueryParam = [ { Name = "x-debug" Exact = "1" }, ] } } Destination { Service = "web" ServiceSubset = "canary" } }, # NOTE: a default catch-all will send unmatched traffic to "web" ] ``` Route HTTP requests with a special url parameter or header to a canary subset: ```yaml apiVersion: consul.hashicorp.com/v1alpha1 kind: ServiceRouter metadata: name: web spec: routes: - match: http: header: - name: x-debug exact: '1' destination: service: web serviceSubset: canary - match: http: queryParam: - name: x-debug exact: '1' destination: service: web serviceSubset: canary # NOTE: a default catch-all will send unmatched traffic to "web" ``` ### gRPC routing Re-route a gRPC method to another service. Since gRPC method calls [are HTTP/2](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md), we can use an HTTP path match rule to re-route traffic: ```hcl Kind = "service-router" Name = "billing" Routes = [ { Match { HTTP { PathExact = "/mycompany.BillingService/GenerateInvoice" } } Destination { Service = "invoice-generator" } }, # NOTE: a default catch-all will send unmatched traffic to "billing" ] ``` Re-route a gRPC method to another service. Since gRPC method calls [are HTTP/2](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md), we can use an HTTP path match rule to re-route traffic: ```yaml apiVersion: consul.hashicorp.com/v1alpha1 kind: ServiceRouter metadata: name: billing spec: routes: - match: http: pathExact: /mycompany.BillingService/GenerateInvoice destination: service: invoice-generator # NOTE: a default catch-all will send unmatched traffic to "billing" ``` ## Available Fields ', yaml: false, }, { name: 'Namespace', type: `string: "default"`, enterprise: true, description: 'Specifies the namespace the config entry will apply to.', yaml: false, }, { name: 'Meta', type: 'map: nil', description: 'Specifies arbitrary KV metadata pairs. Added in Consul 1.8.4.', yaml: false, }, { name: 'metadata', children: [ { name: 'name', description: 'Set to the name of the service being configured.', }, { name: 'namespace', description: 'If running Consul Open Source, the namespace is ignored (see [Kubernetes Namespaces in Consul OSS](/docs/k8s/crds#consul-oss)). If running Consul Enterprise see [Kubernetes Namespaces in Consul Enterprise](/docs/k8s/crds#consul-enterprise) for more details.', }, ], hcl: false, }, { name: 'Routes', type: 'array', description: `The list of routes to consider when processing L7 requests. The first route to match in the list is terminal and stops further evaluation. Traffic that fails to match any of the provided routes will be routed to the default service.`, children: [ { name: 'Match', type: 'ServiceRouteMatch: ', description: `A set of criteria that can match incoming L7 requests. If empty or omitted it acts as a catch-all.`, children: [ { name: 'HTTP', type: 'ServiceRouteHTTPMatch: ', description: `A set of [HTTP-specific match criteria](#serviceroutehttpmatch).`, }, ], }, { name: 'Destination', type: 'ServiceRouteDestination: ', description: `Controls [how to proxy](#serviceroutedestination) the matching request(s) to a service.`, }, ], }, ]} /> ### `ServiceRouteHTTPMatch`
At most only one of `PathExact`, `PathPrefix`, or `PathRegex` may be configured.', yaml: 'Exact path to match on the HTTP request path.

At most only one of `pathExact`, `pathPrefix`, or `pathRegex` may be configured.', }, }, { name: 'PathPrefix', type: 'string: ""', description: { hcl: 'Path prefix to match on the HTTP request path.

At most only one of `PathExact`, `PathPrefix`, or `PathRegex` may be configured.', yaml: 'Path prefix to match on the HTTP request path.

At most only one of `pathExact`, `pathPrefix`, or `pathRegex` may be configured.', }, }, { name: 'PathRegex', type: 'string: ""', description: { hcl: 'Regular expression to match on the HTTP request path.

The syntax is [described below](#regular-expression-syntax).

At most only one of `PathExact`, `PathPrefix`, or `PathRegex` may be configured.', yaml: 'Regular expression to match on the HTTP request path.

The syntax is [described below](#regular-expression-syntax).

At most only one of `pathExact`, `pathPrefix`, or `pathRegex` may be configured.', }, }, { name: 'Methods', type: 'array', description: 'A list of HTTP methods for which this match applies. If unspecified all HTTP methods are matched. If provided the names must be a valid [method](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods).', }, { name: 'Header', type: 'array)', description: 'A set of criteria that can match on HTTP request headers. If more than one is configured all must match for the overall match to apply.', children: [ { name: 'Name', type: 'string: ', description: 'Name of the header to match.', }, { name: 'Present', type: 'bool: false', description: { hcl: 'Match if the header with the given name is present with any value.

At most only one of `Exact`, `Prefix`, `Suffix`, `Regex`, or `Present` may be configured.', yaml: 'Match if the header with the given name is present with any value.

At most only one of `exact`, `prefix`, `suffix`, `regex`, or `present` may be configured.', }, }, { name: 'Exact', type: 'string: ""', description: { hcl: 'Match if the header with the given name is this value.

At most only one of `Exact`, `Prefix`, `Suffix`, `Regex`, or `Present` may be configured.', yaml: 'Match if the header with the given name is this value.

At most only one of `exact`, `prefix`, `suffix`, `regex`, or `present` may be configured.', }, }, { name: 'Prefix', type: 'string: ""', description: { hcl: 'Match if the header with the given name has this prefix.

At most only one of `Exact`, `Prefix`, `Suffix`, `Regex`, or `Present` may be configured.', yaml: 'Match if the header with the given name has this prefix.

At most only one of `exact`, `prefix`, `suffix`, `regex`, or `present` may be configured.', }, }, { name: 'Suffix', type: 'string: ""', description: { hcl: 'Match if the header with the given name has this suffix.

At most only one of `Exact`, `Prefix`, `Suffix`, `Regex`, or `Present` may be configured.', yaml: 'Match if the header with the given name has this suffix.

At most only one of `exact`, `prefix`, `suffix`, `regex`, or `present` may be configured.', }, }, { name: 'Regex', type: 'string: ""', description: { hcl: 'Match if the header with the given name matches this pattern.

The syntax is [described below](#regular-expression-syntax).

At most only one of `Exact`, `Prefix`, `Suffix`, `Regex`, or `Present` may be configured.', yaml: 'Match if the header with the given name matches this pattern.

The syntax is [described below](#regular-expression-syntax).

At most only one of `exact`, `prefix`, `suffix`, `regex`, or `present` may be configured.', }, }, { name: 'Invert', type: 'bool: false', description: 'Inverts the logic of the match', }, ], }, { name: 'QueryParam', type: 'array)', description: 'A set of criteria that can match on HTTP query parameters. If more than one is configured all must match for the overall match to apply.', children: [ { name: 'Name', type: 'string: ', description: 'The name of the query parameter to match on.', }, { name: 'Present', type: 'bool: false', description: { hcl: 'Match if the query parameter with the given name is present with any value.

At most only one of `Exact`, `Regex`, or `Present` may be configured.', yaml: 'Match if the query parameter with the given name is present with any value.

At most only one of `exact`, `regex`, or `present` may be configured.', }, }, { name: 'Exact', type: 'string: ""', description: { hcl: 'Match if the query parameter with the given name is this value.

At most only one of `Exact`, `Regex`, or `Present` may be configured.', yaml: 'Match if the query parameter with the given name is this value.

At most only one of `exact`, `regex`, or `present` may be configured.', }, }, { name: 'Regex', type: 'string: ""', description: { hcl: 'Match if the query parameter with the given name matches this pattern.

The syntax is [described below](#regular-expression-syntax).

At most only one of `Exact`, `Regex`, or `Present` may be configured.', yaml: 'Match if the query parameter with the given name matches this pattern.

The syntax is [described below](#regular-expression-syntax).

At most only one of `exact`, `regex`, or `present` may be configured.', }, }, ], }, ]} /> ### `ServiceRouteDestination`
This requires that either `Match.HTTP.PathPrefix` or `Match.HTTP.PathExact` be configured on this route.', yaml: 'Defines how to rewrite the HTTP request path before proxying it to its final destination.

This requires that either `match.http.pathPrefix` or `match.http.pathExact` be configured on this route.', }, }, { name: 'RequestTimeout', type: 'duration: 0', description: 'The total amount of time permitted for the entire downstream request (and retries) to be processed.', }, { name: 'NumRetries', type: 'int: 0', description: 'The number of times to retry the request when a retryable result occurs.', }, { name: 'RetryOnConnectFailure', type: 'bool: false', description: 'Allows for connection failure errors to trigger a retry.', }, { name: 'RetryOnStatusCodes', type: 'array', description: 'A list of HTTP response status codes that are eligible for retry.', }, ]} /> ## ACLs Configuration entries may be protected by [ACLs](/docs/security/acl). Reading a `service-router` config entry requires `service:read` on the resource. Creating, updating, or deleting a `service-router` config entry requires `service:write` on the resource and `service:read` on any other service referenced by name in these fields: - [`Routes[].Destination.Service`](#service) ## Regular Expression Syntax The actual syntax of the regular expression fields described here is entirely proxy-specific. When using [Envoy](/docs/connect/proxies/envoy) as a proxy (the only supported proxy in Kubernetes), the syntax for these fields is version specific: | Envoy Version | Syntax | | --------------- | ------------------------------------------------------------------- | | 1.11.2 or newer | [documentation](https://github.com/google/re2/wiki/Syntax) | | 1.11.1 or older | [documentation](https://en.cppreference.com/w/cpp/regex/ecmascript) |