🔀 REST-to-gRPC Transcoding Engine (pkg/transcoder)
Toron Edge Gateway features a native, zero-dependency REST-to-gRPC Transcoding Engine (pkg/transcoder). It translates incoming RESTful JSON HTTP requests (e.g. GET /v1/users/123) into binary Protobuf-encoded HTTP/2 gRPC requests (e.g. POST /user.UserService/GetUser) and converts returning binary gRPC payloads and grpc-status headers back into REST JSON responses.
🌟 Key Features
- Zero External Dependencies: Implements JSON payload parsing, path parameter extraction, gRPC 5-byte wire framing, and status code mapping using Go stdlib without protobuf compiler dependencies.
- Direct Parameterized Subpath Routing (
SEC-30, CWE-284 / CWE-400):- Elimination of Empty Upstream Proxies: Completely removed dummy upstream reverse proxy registration that previously caused parameterized REST requests to abort with
502 Bad Gateway: No upstream target available. - Native In-Process Prefix Binding: Parameterized endpoints (e.g.
GET /v1/users/:id,GET /v1/users/:id/orders/:orderId) bind directly toRouter.HandlePrefixWithMatcherwith path pattern validation (MatchPathPattern), executing cleanly throughrouter.ServeHTTP. - Multi-Level Route Segregation & Method Gating: Multiple routes sharing common path prefixes are cleanly segregated without route shadowing; invalid methods return
405 Method Not Allowed, and segment count mismatches return404 Not Found.
- Elimination of Empty Upstream Proxies: Completely removed dummy upstream reverse proxy registration that previously caused parameterized REST requests to abort with
- Hop-by-Hop Header Sanitization & Strict RFC 7540 Compliance (
SEC-29, CWE-444 / CWE-436):- Static Hop-by-Hop Header Stripping: Strips standard RFC 7230 / RFC 7540 connection-specific headers (
Connection,Keep-Alive,Upgrade,Proxy-Connection,Transfer-Encoding,Proxy-Authenticate,Proxy-Authorization,Trailer,Trailers,Host) before dispatching HTTP/2 gRPC requests. - Dynamic Connection Token Parsing: Dynamically parses comma-delimited tokens from the client
Connectionheader and strips matching nominated headers per RFC 7230 §6.1 / RFC 9110 §7.6.1. - Strict
TE: trailersInvariant: Discards clientTEvalues (e.g.gzip,deflate) and strictly enforces single-valuedTE: trailersper RFC 7540 §8.1.2.2 / RFC 9113 §8.2.2, preventing upstream gRPC backends from terminating streams withRST_STREAM (PROTOCOL_ERROR 0x1). - Metadata Preservation: Preserves application authentication, tracing, and custom metadata headers (
Authorization,X-Request-Id,Traceparent,User-Agent) intact with full byte fidelity.
- Static Hop-by-Hop Header Stripping: Strips standard RFC 7230 / RFC 7540 connection-specific headers (
- Bounded Ingestion & 413 Rejection (
SEC-28, CWE-400 / CWE-770): Protects against memory exhaustion and OOM kills via configurablemax_body_bytes(default: 4 MB /4194304bytes):- Declared
Content-LengthFast-Fail: Requests declaring payload size $> \text{max_body_bytes}$ are rejected immediately withHTTP 413 Payload Too Largewithout socket reading or memory allocation. - Bounded Stream Over-Read: Chunked or undeclared streams are capped via
io.LimitReaderand rejected withHTTP 413if bytes exceed the ceiling, preventingjson.Unmarshalheap explosion. - Upstream Isolation: Upstream gRPC backends receive 0 requests on rejected payloads.
- Declared
- URL Path & Query Parameter Extraction: Automatically maps path parameters (
/v1/users/:id) and query parameters into gRPC request fields. - gRPC Status Mapping: Translates gRPC trailer statuses (
grpc-status: 0->200 OK,grpc-status: 5->404 Not Found,grpc-status: 16->401 Unauthorized).
⚙️ Configuration Reference (config.yaml)
transcoder:
enabled: true
max_body_bytes: 4194304 # Maximum incoming request body limit in bytes (default: 4MB; SEC-28)
routes:
- http_method: "GET"
http_path: "/v1/users/:id"
grpc_method: "/user.UserService/GetUser"
upstream_url: "http://localhost:9005"
field_mappings:
id: "userId"
🚀 Usage Example
Curl Command
curl -i http://localhost:8080/v1/users/123
JSON Response
{
"userId": "123",
"name": "John Doe",
"status": "active"
}