Skip to content

cloud-mill/RESTGate

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

13 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

RESTGate

The Cloud-Native L-7 Gateway to Seamless API Integration πŸš€

RESTGate is a small, configuration-driven Layer-7 API gateway / reverse proxy written in Go. You describe your backend microservices and their REST routes in a single YAML file, and RESTGate routes incoming HTTP traffic to the right service - ideal for fronting RESTful APIs inside a Kubernetes cluster.


Features

  • Config-driven routing - declare services and routes in one YAML file; no code changes to add a route.
  • WebSocket & streaming - proxies HTTP protocol upgrades (WebSocket), Server-Sent Events, and chunked/streaming responses out of the box.
  • Built on the standard library - uses Go's battle-tested net/http/httputil reverse proxy with a tuned, connection-pooling transport. One proxy is built per service at startup, not per request.
  • Production-ready operations
    • Graceful shutdown on SIGINT/SIGTERM (drains in-flight requests).
    • Sensible HTTP server timeouts (Slowloris protection via read_header_timeout).
    • Separate admin server for /healthz, /readyz, /metrics and /version, so operational endpoints never collide with proxied routes.
  • Observability - structured logging (text or JSON) and Prometheus metrics out of the box.
  • Safe by default - strict config validation at startup, panic-recovery middleware, distroless non-root container image.
  • Cloud-native - drops into Kubernetes with the manifests in deploy/k8s/.

How it works

client -> :7000  proxy -> middleware -> router -> reverse proxy -> backend service
          :9000  admin: /healthz  /readyz  /metrics  /version

A request is matched to a route by method and path, passes through the recover/log/metrics middleware, and is proxied to that service's service_url. Health, readiness and metrics are served separately on the admin port.

Configuration

RESTGate is configured by a single YAML file. Resolve order for its location:

  1. -config <path> command-line flag
  2. RESTGATE_CONFIG_PATH environment variable
  3. RESTATE_CONFIG_PATH environment variable (deprecated legacy spelling, still honored with a warning)

See config/restgate.example.yaml for a complete example.

Reference

Key Type Default Description
port int 7000 Port the proxy (data-plane) listens on.
admin_port int 9000 Port for health/readiness/metrics/version. Must differ from port.
log_level string info trace, debug, info, warn, or error.
log_format string text text or json.
read_header_timeout duration 10s Max time to read request headers (Slowloris protection).
read_timeout duration (off) Max time to read the whole request. Off by default to allow large uploads.
write_timeout duration (off) Max time to write the response. Off by default to allow streaming.
idle_timeout duration 120s Keep-alive idle timeout.
shutdown_timeout duration 15s Grace period for draining on shutdown.
response_header_timeout duration (off) Max wait for a backend's response headers.
observed_services[] list - Backend services and their routes (below).

Each entry in observed_services:

Key Description
name A label for the service (documentation only).
service_url Backend base URL, e.g. http://account-service:8000 (K8s DNS). Must be http/https with a host.
routes[] Routes proxied to this service.

Each route:

Key Description
name Unique route name (used as the metrics label). Required.
methods Comma-separated HTTP methods, e.g. "GET,OPTIONS".
pattern URL path pattern, e.g. /account/{id}. Must start with /.
description Optional human-readable description.

Invalid configuration (bad port, duplicate route name, unparseable service_url, unknown YAML key, …) is rejected at startup with a clear error.

WebSocket & streaming

RESTGate transparently proxies HTTP protocol upgrades (WebSocket), Server-Sent Events, and chunked/streaming responses - the connection is hijacked on a 101 Switching Protocols and bytes are copied bidirectionally.

To expose a WebSocket endpoint, declare its route with the GET method (a WebSocket handshake is an HTTP GET with an Upgrade header):

  - name: realtime-service
    service_url: "http://realtime-service:8080"
    routes:
      - name: realtime_socket
        methods: "GET"
        pattern: "/realtime/ws"

Caveat: Do not set read_timeout or write_timeout if you proxy WebSockets or other long-lived streams - those timeouts would close the connection mid-stream. They are disabled by default for this reason. idle_timeout and read_header_timeout do not affect an established upgrade. WebSocket backends should be reachable over HTTP/1.1 (internal http:// services are).

Admin & observability endpoints

Served on admin_port (default 9000):

Endpoint Purpose
GET /healthz Liveness - always 200 while the process runs.
GET /readyz Readiness - 200 once listeners are bound, 503 otherwise.
GET /metrics Prometheus metrics (restgate_requests_total, restgate_request_duration_seconds, …).
GET /version Build version, commit and time as JSON.

Running locally

# Build a static binary into ./bin (version info baked in via ldflags)
make build

# Run against the example config
./bin/restgate -config config/restgate.example.yaml
# ...or
RESTGATE_CONFIG_PATH=config/restgate.example.yaml ./bin/restgate

Useful make targets: build, run, test, test-race, cover, vet, fmt, lint, docker. Run make help for the full list.

Docker

# Build the image (multi-stage, distroless, non-root)
make docker
# ...or directly:
docker build -t restgate:latest .

# Run, mounting your config to the default in-container path
docker run --rm \
  -v "$(pwd)/config/restgate.example.yaml:/etc/restgate/restgate.yaml:ro" \
  -p 7000:7000 -p 9000:9000 \
  restgate:latest

The image defaults RESTGATE_CONFIG_PATH to /etc/restgate/restgate.yaml.

Kubernetes

Ready-to-edit manifests live in deploy/k8s/:

kubectl apply -f deploy/k8s/configmap.yaml    # the RESTGate config
kubectl apply -f deploy/k8s/deployment.yaml   # Deployment w/ liveness & readiness probes
kubectl apply -f deploy/k8s/service.yaml      # ClusterIP service (http + admin ports)
kubectl apply -f deploy/k8s/ingress.yaml      # Ingress (set your ingressClassName)

The Deployment runs as a non-root user with a read-only root filesystem, wires the liveness/readiness probes to the admin port, and exposes Prometheus scrape annotations. Edit the image: field to point at your registry.

Development

Requires Go 1.25+ and golangci-lint v2 (for the make lint target).

go test -race -cover ./...   # tests with the race detector
go vet ./...                 # vet
make lint                    # golangci-lint
make build                   # static binary into ./bin

Run make help for all available targets.

Contributing

RESTGate's small, conventional codebase makes it easy to modify and extend - add logging, auth, rate limiting, or routing features as middleware. Fork it, open a PR, and our team will review.

πŸ₯‡ Every contributor is honorably mentioned in CONTRIBUTING.md and immortalized in the git history.

Raise Issues

Questions or problems? Please open a GitHub issue - we'll address it as soon as we can.

About

The production ready Cloud-Native L-7 Gateway to Seamless API Integration πŸš€

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors