x/gateway Primer
x/gateway Primer
Section titled “x/gateway Primer”Beta — API is stable within a minor version. Check Release Posture and Extension Maturity before adopting in production.
Open this page after x/* Family when the change is clearly about edge transport behavior rather than the smallest canonical service shape: proxying upstream requests, rewriting paths, balancing across backends, or wiring gateway-level health.
x/gateway is the canonical and only app-facing entrypoint for gateway and edge transport work in Plumego. Its subordinate packages are reached through x/gateway first, not opened directly:
x/gateway/cache— gateway-edge HTTP response cachingx/gateway/discovery— service instance resolutionx/gateway/ipc— inter-process transportx/gateway/protocol— protocol adapter registry (gRPC, GraphQL transcoding)x/gateway/protocolmw— protocol-aware middleware for the proxy pipelinex/gateway/transform— request/response header, query-param, and body transformation chains
Stability and adoption
Section titled “Stability and adoption”Gateway and edge transport behavior should be isolated behind application-local
configuration when compatibility matters. Check x/gateway/module.yaml,
Release Posture, and
Extension Maturity before adopting proxy,
rewrite, balancer, discovery, or IPC APIs in production.
Start here when
Section titled “Start here when”- you are building or modifying reverse proxy behavior (
proxy.go) - you are configuring gateway routing rules or path rewrites (
rewrite.go) - you are adding or tuning a load-balancing strategy (
balancer.go) - you are wiring a cache layer at the gateway edge (
cache/) - you are implementing gateway-level health checks (
health.go) - you are adding discovery-based backend resolution or IPC transport helpers
- you are adapting gRPC or GraphQL upstream protocols via the proxy pipeline (
protocol/,protocolmw/) - you are composing header, query-param, or body transforms at the gateway edge (
transform/)
Do not start here when
Section titled “Do not start here when”- the change is about reusable CRUD resource APIs — that belongs in
x/rest - the work introduces tenant-specific edge policy — coordinate with
x/tenant - the change is core bootstrap or stable root entrypoints
- the work is business-specific gateway policy baked into the extension primitives
First files to read in the current repository
Section titled “First files to read in the current repository”x/gateway/module.yamlx/gateway/entrypoints.gox/gateway/backend.gox/gateway/balancer.gox/gateway/rewrite.go(if path rewriting is involved)x/gateway/cache/(if caching is involved)
Concrete ownership examples
Section titled “Concrete ownership examples”Keep it in x/gateway when the work is about | Move out when the work becomes |
|---|---|
proxy: reverse-proxy handler construction, upstream selection, request forwarding | reusable resource-interface CRUD transport — that belongs in x/rest |
rewrite: path rewriting, header injection, and modifier composition | business-specific gateway policy that belongs in application code |
balancer: backend pool management and load-balancing strategy selection | tenant-specific routing policy or per-tenant backend assignment |
cache: gateway-edge response caching adapters | application-level data caching not at the edge — use x/data/cache instead |
health: gateway-level backend health tracking and circuit state | fine-grained component health types in the stable health module |
protocol: protocol adapter registry, gRPC and GraphQL transcoding at the proxy edge | business-level protocol logic — keep that in application code |
protocolmw: protocol-aware middleware composing adapters into the proxy pipeline | generic HTTP middleware not tied to protocol adaptation — use middleware/ |
transform: header injection/removal, query-param edits, JSON body rewriting, method/status overrides | application-level response shaping outside the gateway edge |
discovery / ipc via x/gateway entrypoints | opening x/gateway/discovery or x/gateway/ipc directly for work that belongs at the gateway surface |
Import
Section titled “Import”import "github.com/spcent/plumego/x/gateway"Reverse proxy with static backends
Section titled “Reverse proxy with static backends”proxy := gateway.NewGateway(gateway.GatewayConfig{ Targets: []string{ "http://backend-1:8080", "http://backend-2:8080", }, LoadBalancer: gateway.NewRoundRobinBalancer(),})
// As a standalone handlerr.Handle("/api/*", proxy)
// Or as middlewarer.Handle("/api/*", proxy.Middleware()(nextHandler))Register a proxied route in one call
Section titled “Register a proxied route in one call”proxy, err := gateway.RegisterProxy(router, "/api/*", gateway.GatewayConfig{ Targets: []string{"http://upstream:9000"}, LoadBalancer: gateway.NewRoundRobinBalancer(),})Load balancing strategies
Section titled “Load balancing strategies”| Constructor | Strategy |
|---|---|
NewRoundRobinBalancer() | Rotate through backends in order |
NewRandomBalancer() | Pick a backend at random |
NewWeightedRoundRobinBalancer() | Round-robin weighted by backend weight |
NewIPHashBalancer() | Route same client IP to same backend |
NewLeastConnectionsBalancer() | Send to backend with fewest active connections |
proxy := gateway.NewGateway(gateway.GatewayConfig{ Targets: []string{"http://a:8080", "http://b:8080"}, LoadBalancer: gateway.NewLeastConnectionsBalancer(),})Path rewriting
Section titled “Path rewriting”proxy := gateway.NewGateway(gateway.GatewayConfig{ Targets: []string{"http://upstream:9000"}, PathRewrite: gateway.StripPrefix("/api/v1"),})Available rewrite helpers:
| Function | Effect |
|---|---|
StripPrefix(prefix) | Remove prefix from path before forwarding |
AddPrefix(prefix) | Prepend prefix to forwarded path |
ReplacePrefix(old, new) | Swap one prefix for another |
RewriteMap(rules) | Apply first matching exact-path rule |
Chain(rewriters...) | Compose multiple rewriters left-to-right |
Backend pool and health checking
Section titled “Backend pool and health checking”pool, err := gateway.NewBackendPool([]string{ "http://backend-1:8080", "http://backend-2:8080",})if err != nil { log.Fatal(err)}
checker := gateway.NewHealthChecker(pool, &gateway.HealthCheckConfig{ Interval: 10 * time.Second, Timeout: 2 * time.Second, Path: "/healthz",})checker.Start()defer checker.Stop()Why this primer exists
Section titled “Why this primer exists”Gateway and edge transport is where the confusion between “routing” (which belongs in router) and “proxying” (which belongs here) causes the most boundary drift. x/gateway is the gatekeeper for all six subordinate packages: always start here before opening cache, discovery, ipc, protocol, protocolmw, or transform directly. That indirection keeps the app-facing surface stable even as subordinate internals evolve.