Skip to content

Gateway route matchers

A common and annoying mismatch: the OpenAPI document describes the service’s own paths (/users/{id}), but you actually have to call it through a gateway that mounts it somewhere else (https://gw.example.com/api/v1/users/{id}).

Editing every URL by hand defeats the point of a live spec binding. A route matcher solves it by rewriting URLs at send time.

Create a route matcher and paste the gateway’s own configuration. Three kinds are supported:

KindWhat to paste
kongdeck / declarative YAML
nginxnginx.conf
envoyEnvoy YAML or JSON

The config is stored inline in the matcher’s YAML under .tinspec/route-matchers/, so it is committed with the project and reviewable.

Two scopes:

  • To an API provider — the usual case. In the provider’s settings, pick the matcher, the upstream it corresponds to, and the gateway URL. Every endpoint from that spec is then rewritten.
  • To a single request — the request editor’s Gateway tab, for a one-off.

A request’s own binding wins over the provider’s.

routeMatcher:
matcher: edge-kong
upstream: users-service
gatewayUrl: "{{gatewayUrl}}"

Leave upstream out and Tinspec matches automatically by comparing the spec’s server URL to the routes’ upstreams. Put gatewayUrl in an environment so the same project works against your local gateway and staging.

The provider settings show a live preview table: each spec path next to the gateway URL it will actually be sent to, with unmatched endpoints flagged.

Read that table. An endpoint the gateway does not route is a real finding — either the route is missing or the spec documents something that is not exposed.

When the config does not express a mapping — or expresses it in a way the parser cannot follow — add an explicit override:

overrides:
- upstream: users-service
from: /healthz # the backend path
to: /api/v1/healthz # the gateway-facing path

A gateway can also transcode gRPC to JSON — Envoy’s grpc_json_transcoder being the common case. Mark the matcher as transcoding; for Envoy configs this is auto-detected and the toggle just reflects it.

Then a unary gRPC method carrying a google.api.http annotation is sent as the mapped HTTP call rather than as native gRPC. The gRPC editor shows a chip naming the path it will use, so the decision is visible rather than surprising.

Streaming methods and methods without the annotation fall back to native gRPC.

  • Pre-run chains and pipelines do not apply route matchers. A request sent directly is rewritten; the same request run as a chain step is not.
  • The provider preview table shows the native gRPC retarget for a transcoding matcher — transcoded preview rows are not rendered yet.
routeMatchers:
- name: edge-kong
kind: kong
config: |
services:
- name: users-service
url: http://users:8000
routes:
- name: users
paths: [/api/v1]
strip_path: true
overrides:
- upstream: users-service
from: /healthz
to: /api/v1/healthz
transcodes: false