Skip to content

Repository files navigation

http-rewrite

A lightweight HTTP reverse proxy sidecar that rewrites paths and query parameters based on a YAML configuration. Designed to run as a Kubernetes sidecar container alongside your main application.

Overview

http-rewrite listens for incoming HTTP requests and proxies them to a backend service, rewriting URL paths and/or query parameters on the fly. Route patterns support named captures and wildcards, and captured values can be interpolated into the target path or query using ${variable} syntax.

Use cases include:

  • Extracting path segments (e.g. language codes) and mapping them to query parameters
  • Normalizing URL structures between an API gateway and a backend service
  • Returning static HTTP responses for unmatched routes (e.g. 402 Payment Required)

Quick Start

Prerequisites

  • Go 1.23+
  • Docker (for container builds)

Run locally

go run . -c examples/echo.yaml

Run with Docker

# Build the image
docker build . -t rewrite

# Run with a config file
docker run -it --rm \
  --mount type=bind,source=$(pwd)/examples/echo.yaml,target=/config.yaml \
  -p 0.0.0.0:8081:8081 \
  rewrite

Or use the published image directly:

docker run -it --rm \
  --mount type=bind,source=$(pwd)/examples/echo.yaml,target=/config.yaml \
  -p 0.0.0.0:8081:8081 \
  lindex/http-rewrite:v0.3.1

Configuration

The proxy is configured via a YAML file (default: config.yaml, override with -c <path>).

Top-level structure

listen: 8081       # Port to listen on

apis:              # List of routing rules (evaluated in order)
  - input: ...
    proxy: ...     # OR http: ...

input — Incoming request matching

Field Type Description
path string chi-compatible route pattern (supports {param} and {*} wildcards)
method string Single HTTP method, or ALL / * for any
methods list of strings Multiple HTTP methods (mutually exclusive with method)

proxy — Forward to a backend

Field Type Description
scheme string http (default) or https
host string Target hostname (default: localhost)
port int Target port (required)
path string Rewritten path, supports ${param} and ${*} interpolation
query object Query parameter overrides (see below)

query.set — map of query parameter names to values (supports ${param} interpolation):

query:
  set:
    lang: "${lang}"

http — Return a static HTTP response

Field Type Description
status int HTTP status code
body string Optional response body

Path interpolation

Captured route parameters are available as ${param}. The wildcard tail segment is available as ${*}.

Environment variables are also substituted using the same ${VAR} syntax (via ninlil/envsubst).

Example Configurations

Language-prefix routing (examples/echo.yaml)

Routes GET /sv/some/path?arg1=1GET localhost:10000/some/path?arg1=1&lang=sv

Unmatched routes return 402 Unknown.

listen: 8081
apis:
  - input:
      methods:
        - GET
        - PUT
      path: /{lang:[a-z]{2}}/*
    proxy:
      scheme: http
      host: localhost
      port: 10000
      path: /${*}
      query:
        set:
          lang: "${lang}"

  - input:
      method: ALL
      path: /*
    http:
      status: 402
      body: "Unknown"

Language-prefix routing with passthrough fallback (examples/lang-2.yaml)

Same as above but proxies unmatched routes through instead of returning an error.

listen: 8081
apis:
  - input:
      methods:
        - GET
        - PUT
      path: /{lang:[a-z]{2}}/*
    proxy:
      scheme: http
      host: localhost
      port: 10000
      path: /${*}
      query:
        set:
          lang: "${lang}"

  - input:
      method: ALL
      path: /*
    proxy:
      scheme: http
      host: localhost
      port: 10000
      path: /${*}

Kubernetes Sidecar Deployment

http-rewrite is designed to run as a sidecar container. The main application container does not expose its port directly — all traffic is routed through the rewrite sidecar.

ConfigMap

Store the configuration in a ConfigMap:

apiVersion: v1
kind: ConfigMap
metadata:
  name: myapp-rewrite-config
data:
  config.yaml: |-
    listen: 8081
    apis:
      - input:
          methods: [GET, PUT]
          path: /{lang:[a-z]{2}}/*
        proxy:
          host: localhost
          port: 10000
          path: /${*}
          query:
            set:
              lang: "${lang}"
      - input:
          method: ALL
          path: /*
        proxy:
          host: localhost
          port: 10000
          path: /${*}

Deployment

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
spec:
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
        - name: main
          image: lindex/http-https-echo:v0.1.0
          # Port NOT exposed — rewrite sidecar handles inbound traffic

        - name: rewrite-sidecar
          image: lindex/http-rewrite:v0.3.1
          ports:
            - containerPort: 8081
          volumeMounts:
            - name: rewrite-config
              mountPath: /config.yaml
              subPath: config.yaml

      volumes:
        - name: rewrite-config
          configMap:
            name: myapp-rewrite-config

Service

apiVersion: v1
kind: Service
metadata:
  name: myapp
spec:
  selector:
    app: myapp
  ports:
    - name: http
      port: 80
      targetPort: 8081

Docker Image

Images are published to Docker Hub as lindex/http-rewrite.

Tag pattern Description
v1.2.3 Exact version
v1.2 Latest patch for a minor version

The image is built on gcr.io/distroless/static-debian12 and runs as a non-root user.

Development

# Run tests
go test ./...

# Build binary
go build -o http-rewrite .

# Build Docker image
docker build . -t rewrite

License

MIT

About

Sidecar for rewriting HTTP requests for internal services

Resources

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages