Skip to content
Weik.ioDocs
2026.2
Try Weik.io

Upstreams and routes

Weik.io 2026.2

An API version's routes and clusters are YARP's own configuration, and Weik.io adds the credential the gateway sends upstream and the connection settings around it.

On this page

An API version of type: proxy says where the gateway sends each call. Its routes and clusters blocks are the configuration of YARP, the .NET reverse proxy that runs inside the gateway, as YARP’s documentation writes it. Weik.io doesn’t define a subset of its own, so every YARP feature that is set in configuration works: transforms, header routing, session affinity, health checks, load balancing and timeouts.

Routes and clusters#

finance/apis/invoices.yaml
apiVersion: weik.io/v1
kind: api-version
metadata: { name: v1, project: finance, api: invoices }
spec:
  type: proxy
  routes:                                   # YARP RouteConfig
    - RouteId: pending
      Match: { Path: "/{**rest}" }
      ClusterId: erp
  clusters:                                 # YARP ClusterConfig
    - ClusterId: erp
      LoadBalancingPolicy: RoundRobin
      Destinations:
        erp: { Address: "{{erp-url}}/api/invoices" }

A route matches the part of the path after the API’s prefix and version, so with the prefix /invoices a call to https://api.example.com/invoices/v1/pending matches /{**rest} with rest as pending. A cluster lists the destinations a route sends to, and a cluster of several destinations balances the calls between them.

The destination’s address is a placeholder, so devtest and production send the calls to their own systems. The backend fills in the placeholders and checks the result with YARP’s own validator when you apply, so a broken route or cluster is refused before any gateway sees it. An integration’s own HTTP route is an upstream like any other: write its address in the cluster, such as http://integrations:8080 for an integration at the same site.

A credential for the upstream#

Most upstreams want a credential of their own, which the gateway adds to every call it forwards. authentication is a typed block on the version, so nobody encodes a Basic header by hand or writes a token cache:

Type What the gateway does
header Adds the headers you name, such as an API key the upstream expects
basic Builds the Basic authorization header from a username and a password
oidc Fetches an OAuth client-credentials token from the token endpoint, caches it and sends it
spec:
  authentication:
    type: oidc
    parameters:
      tokenEndpoint: "https://erp.example.com/token"
      clientId: weikio
      clientSecret: "{{erp-client-secret}}"     # a project secret
      scope: invoices.read

The secret stays a placeholder, resolved in each environment when the route table is built. The caller’s own credential never reaches the upstream: the gateway removes the key or token that admitted the caller before it forwards the call.

Connection settings#

connection tunes how the gateway connects to the upstream, for the things YARP’s own configuration has no setting for:

spec:
  connection:
    automaticDecompression: gzip
    connectTimeout: 30s
Setting What it does
allowAutoRedirect Follows the upstream’s redirects
automaticDecompression Decompresses gzip responses
useCookies Keeps a cookie container for the upstream
useProxy Sends the calls through the host’s proxy
connectTimeout How long a connection may take, 15 seconds when it’s not set
clientCertificate A client certificate from a secret, presented on every TLS connection to the upstream and its token endpoint

A client certificate is a secret stored with --as-file, a PEM file with the certificate, its issuers and its key, or a PKCS#12 file, with clientCertificatePassword for an encrypted key. A deploy refuses one that has expired, and a problem warns 30 days before it does.

Where an API may send#

The gateway’s --upstream-networks limits where the APIs it serves may send calls. A platform administrator sets it on gateways that face the internet, so an API version can’t reach into a network it shouldn’t.

YARP doesn’t retry a call, because it streams the request body and can’t send it twice. An upstream that needs retries gets them from an integration in front of it.