trapped / sx

No-frills all-in-one HTTP API gateway

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

SX: a minimal, declarative API gateway

WARNING: not production ready. Use at your own risk! Need something better? Check out nginx, Caddy or Envoy

SX is an all-in-one HTTP API gateway. It's intended to be the least-intrusive and simple as possible. It does not support TLS by design: add it on top.

This doesn't mean it's not feature packed - in fact, it provides:

  • round-robin load balancing with multiple addresses (if running in Kubernetes you should just use the Service address)
  • service mapping in YAML
  • route path grouping/matching (with simple glob patterns)
  • route group authorization (Basic Auth or JWT Bearer token)
  • caching and rate limiting (WIP) (requires Redis)
    • both support key extraction from request parameters
  • Prometheus metrics (and provides a simple Grafana dashboard you can import and customize)

It's very simple to deploy, and provides standard YAML manifests for:

  • docker-compose (includes Redis; also includes pre-configured Prometheus and Grafana)
  • Kubernetes (Redis not included)

Importantly, it supports auto-reload for the Kubernetes ConfigMap. Note this can take a few seconds up to a few minutes depending on the kubelet's sync interval.

It's also stateless - which means you can simply horizontally scale it, run in on preemptible/spot nodes, whatever (you should bring your own scaling for Redis, though).

Running

From the command line: sx -l :7654 -pprof :6060 -f config.yml

In docker-compose using the provided manifest: docker-compose -f sx/docker-compose.yml up

In Kubernetes: import the kubernetes/*.yml example manifests using kustomize or your preferred tool, then customize its configuration, resources...

You can also manually deploy the official Docker image ghcr.io/trapped/sx; have a look on GitHub packages for the available tags.

Configuration

Here's an example configuration file:

redis:
  readaddresses:
    - localhost:6379
  writeaddresses:
    - localhost:6379

services:
  - name: example
    addresses:
      - localhost:8080
    routes:
      - routes:
          - name: private
            method: POST
            path: /private
            ratelimit:
              perminute: 30
            auth:
              bearer:
                publickey: '{"use":"sign","kty":"oct","kid":"005456ff-1262-4bf0-a608-8534e1fe2763","alg":"HS256","k":"L0FCL4hivd7ShePdJnzEEoqlwoOfCrkcqdbXdADNk0s523xV7C5Sr6GiRIMpvNIelEsR6ta7MZnELY4JoHrm_w"}'
          - name: home
            method: GET
            path: /*
            cache:
              ttl: 5m

The above example uses a symmetric key (oct) for simplicity - you should use something asymmetric like RSA or EC.

Routes are matched in the order they are defined.

SX prefixes service paths with /{service name}, so in the above example it would expose:

  • /example/private -> localhost:8080/private
  • /example/* -> localhost:8080/*

Caching

You can enable caching for groups or single routes by specifying at least a Time-To-Live.

The request URL is always used as cache key; you can optionally add more keys (to partition your cache).

Responses are only cached if their status code indicates an OK result (1xx, 2xx, 3xx).

Prometheus metrics and profiling

SX exposes Prometheus metrics on the address specified with -pprof (0.0.0.0:6060 by default) at /metrics.

You can also attach using go tool pprof.

It's recommended not exposing this port to the external world.

Prometheus metrics follow this format:

  • system (Go) metrics: go_*
  • route metrics: sx_route_* with labels service, route, method, path, status
  • cache metrics: sx_cache_* with labels service, route, method, path

Timings are always provided as seconds.

You can also find an example Grafana dashboard in grafana/.

A health check endpoint is also available at /healthz.

valyala/fasthttp support

SX partially supports valyala/fasthttp which can be enabled with the -fast flag. Many things don't work, though, for example:

  • request/response streaming: fasthttp currently buffers everything
  • cache/rate limiting
  • metrics

Kubernetes ConfigMap autoreload

Kubernetes allows developers to update ConfigMaps in place; it builds a symlink chain in the Pod volume mount: /config/config.yml -> [...] -> /config/..2021_12_18_11_04_31.11673452/config.yml.

Note that this only happens when you mount a ConfigMap as a directory!

To detect this, SX watches FS events for the whole /config/ directory, and checks for changes in the /config/config.yml symlink real path or target file.

About

No-frills all-in-one HTTP API gateway

License:MIT License


Languages

Language:Go 95.2%Language:Shell 3.9%Language:Dockerfile 1.0%