You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The proxy is a monolith: it owns the listener, takes every request, and applies its whole middleware stack to whatever it serves. A service that embeds it to add REST, rate limiting or forward-auth next to its own gRPC API has to give up its listener, point the proxy back at itself over loopback, and accept every capability the config turns on for every request.
Goal
An embeddable edge made of explicit capabilities. With none enabled it is transparent: every request reaches the embedder's service unchanged. Each capability is switched on by one call and says which traffic it applies to.
Two slots. The upstream is any gRPC tower service (a remote tonic::transport::Channel, or the embedder's own services in process); transcoded calls and native gRPC requests go there. The fallback receives everything the edge does not serve (404 by default). The standalone binary is the same edge with a remote channel as its upstream.
Endpoints claim requests: transcoding (optionally narrowed to chosen services / methods), health probes, metrics, OpenAPI, OIDC, forward-auth /verify, extra routes.
Guards wrap requests and may reject them: rate limit, concurrency limit, JWT, ext_authz, auth decider, CORS, maintenance. Each has a scope: transcoded, endpoints, native gRPC, fallback, all, narrowed by path glob and method. A request is classified once; a scope check is one comparison.
Rejections speak the protocol of the request: a JSON google.rpc.Status body with the mapped HTTP status for REST, a trailers-only response (RESOURCE_EXHAUSTED, UNAUTHENTICATED, UNAVAILABLE) for gRPC.
Build-time checks: overlapping routes, a built-in endpoint on a transcoded path, and a guard whose scope selects nothing are errors when the edge is built.
Connection limits belong to the listener: serve takes max_connections; request-level concurrency is a guard.
Slices
feat(embed)!: in-process upstream, pass-through and your own TLS on one listener #117: in-process upstream and pass-through (upstream as any gRPC tower service, native gRPC and unmatched requests on the same listener, the connection's address and TLS certificates reaching the upstream behind an embedder's own server, uniform deadline enforcement).
Problem
The proxy is a monolith: it owns the listener, takes every request, and applies its whole middleware stack to whatever it serves. A service that embeds it to add REST, rate limiting or forward-auth next to its own gRPC API has to give up its listener, point the proxy back at itself over loopback, and accept every capability the config turns on for every request.
Goal
An embeddable edge made of explicit capabilities. With none enabled it is transparent: every request reaches the embedder's service unchanged. Each capability is switched on by one call and says which traffic it applies to.
tonic::transport::Channel, or the embedder's own services in process); transcoded calls and native gRPC requests go there. The fallback receives everything the edge does not serve (404 by default). The standalone binary is the same edge with a remote channel as its upstream./verify, extra routes.google.rpc.Statusbody with the mapped HTTP status for REST, a trailers-only response (RESOURCE_EXHAUSTED,UNAUTHENTICATED,UNAVAILABLE) for gRPC.servetakesmax_connections; request-level concurrency is a guard.Slices
serveand the standalone binary, configured from the YAML.serve.Breaking: the edge replaces
ProxyState/TranscodeState::grpc_channeland the router-centric API (6.0.0).