pkg/gateway/server/server.go
Source
- Package:
server - File:
pkg/gateway/server/server.go - GitHub: https://github.com/theroutercompany/api_router/blob/main/pkg/gateway/server/server.go
Overview
What: Wires the public HTTP server for the gateway: routes, middleware, health/readiness handlers, OpenAPI endpoint, metrics, auth protection for upstream proxies, WebSocket limits, and webhook ingestion endpoints.
Why:
The gateway needs a single place where HTTP concerns are composed consistently:
- request metadata and structured logging
- security headers and body limits
- rate limiting and CORS
- protocol metrics (HTTP/gRPC/WebSockets/SSE)
Keeping this wiring in one package makes runtime composition simple and keeps behavior consistent across entrypoints.
How:
New() constructs the router, initializes proxies/webhooks, mounts routes, then wraps everything in middleware.
Start() listens and serves until context cancellation or error, and Shutdown() triggers graceful stop.
Notes: Auth is enforced per-product via buildProtectedHandler (JWT + scope checks). WebSocket limits are enforced before upgrade and tracked through hijack handling.
Contents
Imports
import block 1
import (
"context"
"encoding/json"
"errors"
"fmt"
"net"
"net/http"
"strings"
"sync"
"time"
"github.com/rs/cors"
"github.com/theroutercompany/api_router/internal/openapi"
"github.com/theroutercompany/api_router/internal/platform/health"
gatewayauth "github.com/theroutercompany/api_router/pkg/gateway/auth"
gatewayconfig "github.com/theroutercompany/api_router/pkg/gateway/config"
gatewaymetrics "github.com/theroutercompany/api_router/pkg/gateway/metrics"
gatewayproblem "github.com/theroutercompany/api_router/pkg/gateway/problem"
gatewayproxy "github.com/theroutercompany/api_router/pkg/gateway/proxy"
gatewaymiddleware "github.com/theroutercompany/api_router/pkg/gateway/server/middleware"
gatewaywebhook "github.com/theroutercompany/api_router/pkg/gateway/webhook"
pkglog "github.com/theroutercompany/api_router/pkg/log"
"golang.org/x/net/http2"
"golang.org/x/net/http2/h2c"
)
Constants
const block 1
const maxRequestBodyBytes int64 = 1 << 20
maxRequestBodyBytes
What: Maximum allowed HTTP request body size (1 MiB).
Why: Prevents large payloads from exhausting memory and protects upstreams from oversized requests.
How: Enforced by the gatewaymiddleware.BodyLimit middleware early in the chain.
Types
type block 1
type readinessReporter interface {
Readiness(ctx context.Context) health.Report
}
readinessReporter
What: Minimal interface the server needs for readiness reporting.
Why: Decouples Server from a concrete readiness checker implementation and improves testability.
How: Implemented by internal/platform/health.Checker.
type block 2
type Option func(*Server)
Option
What: Functional option type for configuring the Server at construction time.
Why: Keeps the New() signature stable while allowing optional dependencies to be injected.
How: Options mutate fields on the server during New().
type block 3
type Server struct {
cfg gatewayconfig.Config
router *http.ServeMux
httpServer *http.Server
handler http.Handler
healthChecker readinessReporter
bootTime time.Time
metricsHandler http.Handler
authenticator *gatewayauth.Authenticator
tradeHandler http.Handler
taskHandler http.Handler
rateLimiter *rateLimiter
cors *cors.Cors
openapiProvider openapi.DocumentProvider
protocolMetrics *protocolMetrics
logger pkglog.Logger
wsLimiter *websocketLimiter
}
Server
What: The primary HTTP server wiring object for the gateway.
Why: Encapsulates configuration, router/middleware setup, proxy handlers, and lifecycle methods.
How: Stores the configured handlers (trade/task/webhooks), shared middleware dependencies (auth, rate limit, CORS, metrics), and exposes Start/Shutdown.
type block 4
type deadlineConn struct {
net.Conn
timeout time.Duration
}
deadlineConn
What: A net.Conn wrapper that applies read/write deadlines using a configured timeout.
Why: WebSocket idle timeouts must be enforced at the connection level after hijack.
How: Overrides Read and Write to set deadlines before delegating to the embedded connection.
type block 5
type websocketLimiter struct {
limit int
active int
mu sync.Mutex
}
websocketLimiter
What: Concurrency limiter for websocket upgrades.
Why: Protects the gateway from unbounded upgraded connections exhausting file descriptors and memory.
How: Tracks active upgrades under a mutex and returns Acquire/release callbacks.
type block 6
type websocketContext struct {
release func()
timeout time.Duration
}
websocketContext
What: Bookkeeping stored in request context for websocket upgrades.
Why: The limiter slot must be released and idle timeout must be applied even after hijack.
How: Carries a release callback and the configured idle timeout.
type block 7
type websocketContextKey struct{}
websocketContextKey
What: Context key type used to store websocket context.
Why: Uses a private, unique type to avoid collisions with other context values.
How: Used as the key in context.WithValue.
Functions and Methods
WithOpenAPIProvider
What: Server option that overrides the OpenAPI document provider.
Why: Allows swapping the OpenAPI source (e.g., prebuilt artifact vs dynamic merge service) without changing server code.
How: Sets Server.openapiProvider, which is used by the /openapi.json handler.
func WithOpenAPIProvider(provider openapi.DocumentProvider) Option {
return func(s *Server) {
s.openapiProvider = provider
}
}
Walkthrough
The list below documents the statements inside the function body, including nested blocks and inline closures.
- L46:
return func(s *Server) { s.openapiProvider = provider }- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values). - Nested steps:
- L46:
func(s *Server) { s.openapiProvider = provider }- What: Defines an inline function (closure).
- Why: Encapsulates callback logic and may capture variables from the surrounding scope.
- How: Declares a
funcliteral and uses it as a value (for example, as an HTTP handler or callback). - Nested steps:
- L47:
s.openapiProvider = provider- What: Assigns s.openapiProvider.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L47:
- L46:
WithLogger
What: Server option that overrides the logger used by the server.
Why: Allows embedding applications and CLIs to inject their own logger configuration.
How: Sets Server.logger when provided a non-nil logger.
func WithLogger(logger pkglog.Logger) Option {
return func(s *Server) {
if logger != nil {
s.logger = logger
}
}
}
Walkthrough
The list below documents the statements inside the function body, including nested blocks and inline closures.
- L53:
return func(s *Server) { if logger != nil { s.logger = logger } }- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values). - Nested steps:
- L53:
func(s *Server) { if logger != nil { s.logger = logger } }- What: Defines an inline function (closure).
- Why: Encapsulates callback logic and may capture variables from the surrounding scope.
- How: Declares a
funcliteral and uses it as a value (for example, as an HTTP handler or callback). - Nested steps:
- L54:
if logger != nil { s.logger = logger }- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L55:
s.logger = logger- What: Assigns s.logger.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L55:
- L54:
- L53:
New
What: Constructs a Server and wires routes + middleware based on gatewayconfig.Config.
Why: Provides a reusable server implementation for the runtime and for embedding.
How: Builds rate limiter/CORS/metrics/auth/OpenAPI provider, initializes proxies/webhooks, mounts routes, then wraps the mux in middleware (body limit, rate limit, CORS, logging, websocket limiting, security headers, request IDs, and h2c).
func New(cfg gatewayconfig.Config, checker readinessReporter, registry *gatewaymetrics.Registry, opts ...Option) *Server {
mux := http.NewServeMux()
s := &Server{
cfg: cfg,
router: mux,
healthChecker: checker,
bootTime: time.Now().UTC(),
metricsHandler: nil,
rateLimiter: newRateLimiter(cfg.RateLimit.Window.AsDuration(), cfg.RateLimit.Max),
cors: buildCORS(cfg.CORS.AllowedOrigins),
logger: pkglog.Shared(),
}
for _, opt := range opts {
if opt != nil {
opt(s)
}
}
if s.logger == nil {
s.logger = pkglog.Shared()
}
if registry != nil && cfg.Metrics.Enabled {
s.metricsHandler = registry.Handler()
}
if cfg.Metrics.Enabled {
s.protocolMetrics = newProtocolMetrics(registry)
} else {
s.protocolMetrics = newProtocolMetrics(nil)
}
s.wsLimiter = newWebsocketLimiter(cfg.WebSocket.MaxConcurrent)
if cfg.Auth.Secret != "" {
if authenticator, err := gatewayauth.New(cfg.Auth); err != nil {
s.logger.Errorw("failed to initialize authenticator", "error", err)
} else {
s.authenticator = authenticator
}
}
if s.openapiProvider == nil {
s.openapiProvider = openapi.NewService()
}
s.initProxies()
s.initWebhooks()
s.mountRoutes()
handler := http.Handler(mux)
handler = gatewaymiddleware.BodyLimit(maxRequestBodyBytes, traceIDFromContext, gatewayproblem.Write)(handler)
if s.rateLimiter != nil {
handler = gatewaymiddleware.RateLimit(
func(key string, now time.Time) bool { return s.rateLimiter.allow(key, now) },
clientKey,
time.Now,
traceIDFromContext,
gatewayproblem.Write,
)(handler)
}
if s.cors != nil {
handler = gatewaymiddleware.CORS(s.cors, traceIDFromContext, gatewayproblem.Write)(handler)
}
var tracker gatewaymiddleware.TrackFunc
var hijacker gatewaymiddleware.HijackedFunc
if s.protocolMetrics != nil || s.wsLimiter != nil {
tracker = s.trackRequest
hijacker = s.hijackedRequest
}
handler = gatewaymiddleware.Logging(s.logger, tracker, hijacker, requestIDFromContext, traceIDFromContext, clientAddress)(handler)
if s.wsLimiter != nil {
handler = websocketLimitMiddleware(s.wsLimiter, s.cfg.WebSocket.IdleTimeout.AsDuration(), traceIDFromContext, gatewayproblem.Write, s.logger)(handler)
}
handler = gatewaymiddleware.SecurityHeaders()(handler)
handler = gatewaymiddleware.RequestMetadata(ensureRequestIDs)(handler)
http2Server := &http2.Server{}
handler = h2c.NewHandler(handler, http2Server)
s.handler = handler
s.httpServer = &http.Server{
Addr: fmt.Sprintf(":%d", cfg.HTTP.Port),
Handler: handler,
}
if err := http2.ConfigureServer(s.httpServer, http2Server); err != nil {
s.logger.Errorw("failed to configure http2 server", "error", err)
}
return s
}
Walkthrough
Expand walkthrough (49 steps)
The list below documents the statements inside the function body, including nested blocks and inline closures.
- L82:
mux := http.NewServeMux()- What: Defines mux.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L84:
s := &Server{ cfg: cfg, router: mux, healthChecker: checker, bootTime: time.Now().UTC(), metricsHandler: nil, rateLimiter: newRateLimiter(c…- What: Defines s.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L95:
for _, opt := range opts { if opt != nil { opt(s) } }- What: Iterates over a collection.
- Why: Processes multiple elements with the same logic.
- How: Executes a
for ... rangeloop. - Nested steps:
- L96:
if opt != nil { opt(s) }- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L97:
opt(s)- What: Calls opt.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L97:
- L96:
- L101:
if s.logger == nil { s.logger = pkglog.Shared() }- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L102:
s.logger = pkglog.Shared()- What: Assigns s.logger.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L102:
- L105:
if registry != nil && cfg.Metrics.Enabled { s.metricsHandler = registry.Handler() }- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L106:
s.metricsHandler = registry.Handler()- What: Assigns s.metricsHandler.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L106:
- L108:
if cfg.Metrics.Enabled { s.protocolMetrics = newProtocolMetrics(registry) } else { s.protocolMetrics = newProtocolMetrics(nil) }- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L109:
s.protocolMetrics = newProtocolMetrics(registry)- What: Assigns s.protocolMetrics.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L111:
s.protocolMetrics = newProtocolMetrics(nil)- What: Assigns s.protocolMetrics.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L109:
- L114:
s.wsLimiter = newWebsocketLimiter(cfg.WebSocket.MaxConcurrent)- What: Assigns s.wsLimiter.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L116:
if cfg.Auth.Secret != "" { if authenticator, err := gatewayauth.New(cfg.Auth); err != nil { s.logger.Errorw("failed to initialize authentic…- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L117:
if authenticator, err := gatewayauth.New(cfg.Auth); err != nil { s.logger.Errorw("failed to initialize authenticator", "error", err) } else…- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L117:
authenticator, err := gatewayauth.New(cfg.Auth)- What: Defines authenticator, err.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L118:
s.logger.Errorw("failed to initialize authenticator", "error", err)- What: Calls s.logger.Errorw.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L120:
s.authenticator = authenticator- What: Assigns s.authenticator.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L117:
- L117:
- L124:
if s.openapiProvider == nil { s.openapiProvider = openapi.NewService() }- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L125:
s.openapiProvider = openapi.NewService()- What: Assigns s.openapiProvider.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L125:
- L128:
s.initProxies()- What: Calls s.initProxies.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L129:
s.initWebhooks()- What: Calls s.initWebhooks.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L131:
s.mountRoutes()- What: Calls s.mountRoutes.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L132:
handler := http.Handler(mux)- What: Defines handler.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L133:
handler = gatewaymiddleware.BodyLimit(maxRequestBodyBytes, traceIDFromContext, gatewayproblem.Write)(handler)- What: Assigns handler.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L134:
if s.rateLimiter != nil { handler = gatewaymiddleware.RateLimit( func(key string, now time.Time) bool { return s.rateLimiter.allow(key, now…- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L135:
handler = gatewaymiddleware.RateLimit( func(key string, now time.Time) bool { return s.rateLimiter.allow(key, now) }, clientKey, time.Now, …- What: Assigns handler.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- Nested steps:
- L136:
func(key string, now time.Time) bool { return s.rateLimiter.allow(key, now) }- What: Defines an inline function (closure).
- Why: Encapsulates callback logic and may capture variables from the surrounding scope.
- How: Declares a
funcliteral and uses it as a value (for example, as an HTTP handler or callback). - Nested steps:
- L136:
return s.rateLimiter.allow(key, now)- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L136:
- L136:
- L135:
- L143:
if s.cors != nil { handler = gatewaymiddleware.CORS(s.cors, traceIDFromContext, gatewayproblem.Write)(handler) }- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L144:
handler = gatewaymiddleware.CORS(s.cors, traceIDFromContext, gatewayproblem.Write)(handler)- What: Assigns handler.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L144:
- L146:
var tracker gatewaymiddleware.TrackFunc- What: Declares local names.
- Why: Introduces variables or types used later in the function.
- How: Executes a Go declaration statement inside the function body.
- L147:
var hijacker gatewaymiddleware.HijackedFunc- What: Declares local names.
- Why: Introduces variables or types used later in the function.
- How: Executes a Go declaration statement inside the function body.
- L148:
if s.protocolMetrics != nil || s.wsLimiter != nil { tracker = s.trackRequest hijacker = s.hijackedRequest }- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L149:
tracker = s.trackRequest- What: Assigns tracker.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L150:
hijacker = s.hijackedRequest- What: Assigns hijacker.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L149:
- L152:
handler = gatewaymiddleware.Logging(s.logger, tracker, hijacker, requestIDFromContext, traceIDFromContext, clientAddress)(handler)- What: Assigns handler.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L153:
if s.wsLimiter != nil { handler = websocketLimitMiddleware(s.wsLimiter, s.cfg.WebSocket.IdleTimeout.AsDuration(), traceIDFromContext, gatew…- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L154:
handler = websocketLimitMiddleware(s.wsLimiter, s.cfg.WebSocket.IdleTimeout.AsDuration(), traceIDFromContext, gatewayproblem.Write, s.logge…- What: Assigns handler.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L154:
- L156:
handler = gatewaymiddleware.SecurityHeaders()(handler)- What: Assigns handler.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L157:
handler = gatewaymiddleware.RequestMetadata(ensureRequestIDs)(handler)- What: Assigns handler.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L158:
http2Server := &http2.Server{}- What: Defines http2Server.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L159:
handler = h2c.NewHandler(handler, http2Server)- What: Assigns handler.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L161:
s.handler = handler- What: Assigns s.handler.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L162:
s.httpServer = &http.Server{ Addr: fmt.Sprintf(":%d", cfg.HTTP.Port), Handler: handler, }- What: Assigns s.httpServer.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L166:
if err := http2.ConfigureServer(s.httpServer, http2Server); err != nil { s.logger.Errorw("failed to configure http2 server", "error", err) }- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L166:
err := http2.ConfigureServer(s.httpServer, http2Server)- What: Defines err.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L167:
s.logger.Errorw("failed to configure http2 server", "error", err)- What: Calls s.logger.Errorw.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L166:
- L170:
return s- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
(*Server).Start
What: Starts listening and serving until context cancellation or server error.
Why: Separates serving from construction so runtime code can control lifecycle.
How: Runs ListenAndServe in a goroutine, then either shuts down on context cancellation (using configured shutdown timeout) or returns on server error.
func (s *Server) Start(ctx context.Context) error {
if s.httpServer == nil {
return errors.New("http server not initialised")
}
errCh := make(chan error, 1)
go func() {
s.logger.Infow("http server listening", "addr", s.httpServer.Addr)
if err := s.httpServer.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
errCh <- err
}
close(errCh)
}()
select {
case <-ctx.Done():
shutdownCtx, cancel := context.WithTimeout(context.Background(), s.cfg.HTTP.ShutdownTimeout.AsDuration())
defer cancel()
if err := s.httpServer.Shutdown(shutdownCtx); err != nil {
s.logger.Errorw("http server shutdown failed", "error", err)
return err
}
return ctx.Err()
case err := <-errCh:
if err != nil {
s.logger.Errorw("http server stopped with error", "error", err)
}
return err
}
}
Walkthrough
The list below documents the statements inside the function body, including nested blocks and inline closures.
- L175:
if s.httpServer == nil { return errors.New("http server not initialised") }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L176:
return errors.New("http server not initialised")- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L176:
- L179:
errCh := make(chan error, 1)- What: Defines errCh.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L180:
go func() { s.logger.Infow("http server listening", "addr", s.httpServer.Addr) if err := s.httpServer.ListenAndServe(); err != nil && !erro…- What: Starts a goroutine.
- Why: Runs work concurrently.
- How: Invokes the function call asynchronously using
go. - Nested steps:
- L180:
func() { s.logger.Infow("http server listening", "addr", s.httpServer.Addr) if err := s.httpServer.ListenAndServe(); err != nil && !errors.…- What: Defines an inline function (closure).
- Why: Encapsulates callback logic and may capture variables from the surrounding scope.
- How: Declares a
funcliteral and uses it as a value (for example, as an HTTP handler or callback). - Nested steps:
- L181:
s.logger.Infow("http server listening", "addr", s.httpServer.Addr)- What: Calls s.logger.Infow.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L182:
if err := s.httpServer.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) { errCh <- err }- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L182:
err := s.httpServer.ListenAndServe()- What: Defines err.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L183:
errCh <- err- What: Sends a value on a channel.
- Why: Communicates with another goroutine.
- How: Executes a channel send operation.
- L182:
- L185:
close(errCh)- What: Calls close.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L181:
- L180:
- L188:
select { case <-ctx.Done(): shutdownCtx, cancel := context.WithTimeout(context.Background(), s.cfg.HTTP.ShutdownTimeout.AsDuration()) defer…- What: Selects among concurrent operations.
- Why: Coordinates channel operations without blocking incorrectly.
- How: Executes a
selectstatement and runs one ready case. - Nested steps:
- L189:
case <-ctx.Done():- What: Selects a select-case branch.
- Why: Coordinates concurrent operations without blocking incorrectly.
- How: Runs this case body when its channel operation is ready (or runs default immediately).
- Nested steps:
- L190:
shutdownCtx, cancel := context.WithTimeout(context.Background(), s.cfg.HTTP.ShutdownTimeout.AsDuration())- What: Defines shutdownCtx, cancel.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L191:
defer cancel()- What: Defers a call for cleanup.
- Why: Ensures the deferred action runs even on early returns.
- How: Schedules the call to run when the surrounding function returns.
- L192:
if err := s.httpServer.Shutdown(shutdownCtx); err != nil { s.logger.Errorw("http server shutdown failed", "error", err) return err }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L192:
err := s.httpServer.Shutdown(shutdownCtx)- What: Defines err.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L193:
s.logger.Errorw("http server shutdown failed", "error", err)- What: Calls s.logger.Errorw.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L194:
return err- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L192:
- L196:
return ctx.Err()- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L190:
- L197:
case err := <-errCh:- What: Selects a select-case branch.
- Why: Coordinates concurrent operations without blocking incorrectly.
- How: Runs this case body when its channel operation is ready (or runs default immediately).
- Nested steps:
- L198:
if err != nil { s.logger.Errorw("http server stopped with error", "error", err) }- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L199:
s.logger.Errorw("http server stopped with error", "error", err)- What: Calls s.logger.Errorw.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L199:
- L201:
return err- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L198:
- L189:
(*Server).Shutdown
What: Gracefully stops the underlying HTTP server.
Why: Provides a clean shutdown path for the runtime and embedding.
How: Delegates to http.Server.Shutdown(ctx) when initialized.
func (s *Server) Shutdown(ctx context.Context) error {
if s.httpServer == nil {
return nil
}
return s.httpServer.Shutdown(ctx)
}
Walkthrough
The list below documents the statements inside the function body, including nested blocks and inline closures.
- L207:
if s.httpServer == nil { return nil }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L208:
return nil- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L208:
- L210:
return s.httpServer.Shutdown(ctx)- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
(*Server).mountRoutes
What: Mounts the fixed gateway routes on the internal http.ServeMux.
Why: Keeps route registration centralized and predictable.
How: Registers /health, readiness endpoints, /openapi.json, /metrics, and /v1/{trade,task} proxy prefixes when handlers are configured.
func (s *Server) mountRoutes() {
s.router.HandleFunc("/health", s.handleHealth)
s.router.HandleFunc("/readyz", s.handleReadiness)
s.router.HandleFunc("/readiness", s.handleReadiness)
if s.openapiProvider != nil {
s.router.HandleFunc("/openapi.json", s.handleOpenAPI)
}
if s.metricsHandler != nil {
s.router.Handle("/metrics", s.metricsHandler)
}
if s.tradeHandler != nil {
s.router.Handle("/v1/trade", s.tradeHandler)
s.router.Handle("/v1/trade/", s.tradeHandler)
}
if s.taskHandler != nil {
s.router.Handle("/v1/task", s.taskHandler)
s.router.Handle("/v1/task/", s.taskHandler)
}
}
Walkthrough
The list below documents the statements inside the function body, including nested blocks and inline closures.
- L214:
s.router.HandleFunc("/health", s.handleHealth)- What: Calls s.router.HandleFunc.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L215:
s.router.HandleFunc("/readyz", s.handleReadiness)- What: Calls s.router.HandleFunc.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L216:
s.router.HandleFunc("/readiness", s.handleReadiness)- What: Calls s.router.HandleFunc.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L217:
if s.openapiProvider != nil { s.router.HandleFunc("/openapi.json", s.handleOpenAPI) }- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L218:
s.router.HandleFunc("/openapi.json", s.handleOpenAPI)- What: Calls s.router.HandleFunc.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L218:
- L220:
if s.metricsHandler != nil { s.router.Handle("/metrics", s.metricsHandler) }- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L221:
s.router.Handle("/metrics", s.metricsHandler)- What: Calls s.router.Handle.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L221:
- L223:
if s.tradeHandler != nil { s.router.Handle("/v1/trade", s.tradeHandler) s.router.Handle("/v1/trade/", s.tradeHandler) }- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L224:
s.router.Handle("/v1/trade", s.tradeHandler)- What: Calls s.router.Handle.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L225:
s.router.Handle("/v1/trade/", s.tradeHandler)- What: Calls s.router.Handle.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L224:
- L227:
if s.taskHandler != nil { s.router.Handle("/v1/task", s.taskHandler) s.router.Handle("/v1/task/", s.taskHandler) }- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L228:
s.router.Handle("/v1/task", s.taskHandler)- What: Calls s.router.Handle.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L229:
s.router.Handle("/v1/task/", s.taskHandler)- What: Calls s.router.Handle.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L228:
(*Server).initProxies
What: Builds upstream reverse proxy handlers from config and wires them into trade/task routes.
Why: Proxy behavior is shared, but each product needs its own target base URL and auth scopes.
How: Iterates configured readiness upstreams, creates a gatewayproxy handler per upstream, then assigns protected handlers for trade and task.
func (s *Server) initProxies() {
for _, upstream := range s.cfg.Readiness.Upstreams {
handler, err := gatewayproxy.New(gatewayproxy.Options{
Target: upstream.BaseURL,
Product: upstream.Name,
TLS: gatewayproxy.TLSConfig{
Enabled: upstream.TLS.Enabled,
InsecureSkipVerify: upstream.TLS.InsecureSkipVerify,
CAFile: upstream.TLS.CAFile,
ClientCertFile: upstream.TLS.ClientCertFile,
ClientKeyFile: upstream.TLS.ClientKeyFile,
},
})
if err != nil {
s.logger.Errorw("failed to build proxy", "error", err, "upstream", upstream.Name)
continue
}
switch upstream.Name {
case "trade":
s.tradeHandler = s.buildProtectedHandler("trade", []string{"trade.read", "trade.write"}, handler)
case "task":
s.taskHandler = s.buildProtectedHandler("task", []string{"task.read", "task.write"}, handler)
}
}
}
Walkthrough
The list below documents the statements inside the function body, including nested blocks and inline closures.
- L234:
for _, upstream := range s.cfg.Readiness.Upstreams { handler, err := gatewayproxy.New(gatewayproxy.Options{ Target: upstream.BaseURL, Produ…- What: Iterates over a collection.
- Why: Processes multiple elements with the same logic.
- How: Executes a
for ... rangeloop. - Nested steps:
- L235:
handler, err := gatewayproxy.New(gatewayproxy.Options{ Target: upstream.BaseURL, Product: upstream.Name, TLS: gatewayproxy.TLSConfig{ Enabl…- What: Defines handler, err.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L246:
if err != nil { s.logger.Errorw("failed to build proxy", "error", err, "upstream", upstream.Name) continue }- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L247:
s.logger.Errorw("failed to build proxy", "error", err, "upstream", upstream.Name)- What: Calls s.logger.Errorw.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L248:
continue- What: Executes a statement.
- Why: Advances the function logic.
- How: Runs this statement as part of the function body.
- L247:
- L251:
switch upstream.Name { case "trade": s.tradeHandler = s.buildProtectedHandler("trade", []string{"trade.read", "trade.write"}, handler) case…- What: Selects a branch from multiple cases.
- Why: Keeps multi-case branching readable and explicit.
- How: Evaluates the switch expression and executes the first matching case.
- Nested steps:
- L252:
case "trade":- What: Selects a switch case.
- Why: Makes multi-branch control flow explicit and readable.
- How: Runs this case body when the switch value matches (or when default is selected).
- Nested steps:
- L253:
s.tradeHandler = s.buildProtectedHandler("trade", []string{"trade.read", "trade.write"}, handler)- What: Assigns s.tradeHandler.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L253:
- L254:
case "task":- What: Selects a switch case.
- Why: Makes multi-branch control flow explicit and readable.
- How: Runs this case body when the switch value matches (or when default is selected).
- Nested steps:
- L255:
s.taskHandler = s.buildProtectedHandler("task", []string{"task.read", "task.write"}, handler)- What: Assigns s.taskHandler.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L255:
- L252:
- L235:
(*Server).initWebhooks
What: Registers webhook ingestion endpoints when enabled in config.
Why: Allows external systems to deliver event callbacks to the gateway, which then forwards them securely to target upstreams.
How: For each configured endpoint, constructs gatewaywebhook.Options, builds a handler, mounts it at the configured path, and logs registration.
func (s *Server) initWebhooks() {
if !s.cfg.Webhooks.Enabled {
return
}
if len(s.cfg.Webhooks.Endpoints) == 0 {
return
}
for _, endpoint := range s.cfg.Webhooks.Endpoints {
opts := gatewaywebhook.Options{
Name: endpoint.Name,
Path: endpoint.Path,
TargetURL: endpoint.TargetURL,
Secret: endpoint.Secret,
SignatureHeader: endpoint.SignatureHeader,
MaxAttempts: endpoint.MaxAttempts,
InitialBackoff: endpoint.InitialBackoff.AsDuration(),
Timeout: endpoint.Timeout.AsDuration(),
Client: &http.Client{
Timeout: endpoint.Timeout.AsDuration(),
},
Logger: s.logger,
}
handler, err := gatewaywebhook.New(opts)
if err != nil {
s.logger.Errorw("failed to initialise webhook handler", "error", err, "webhook", endpoint.Name)
continue
}
s.router.Handle(endpoint.Path, handler)
s.logger.Infow("registered webhook endpoint", "webhook", endpoint.Name, "path", endpoint.Path)
}
}
Walkthrough
The list below documents the statements inside the function body, including nested blocks and inline closures.
- L261:
if !s.cfg.Webhooks.Enabled { return }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L262:
return- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L262:
- L264:
if len(s.cfg.Webhooks.Endpoints) == 0 { return }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L265:
return- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L265:
- L267:
for _, endpoint := range s.cfg.Webhooks.Endpoints { opts := gatewaywebhook.Options{ Name: endpoint.Name, Path: endpoint.Path, TargetURL: en…- What: Iterates over a collection.
- Why: Processes multiple elements with the same logic.
- How: Executes a
for ... rangeloop. - Nested steps:
- L268:
opts := gatewaywebhook.Options{ Name: endpoint.Name, Path: endpoint.Path, TargetURL: endpoint.TargetURL, Secret: endpoint.Secret, Signature…- What: Defines opts.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L282:
handler, err := gatewaywebhook.New(opts)- What: Defines handler, err.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L283:
if err != nil { s.logger.Errorw("failed to initialise webhook handler", "error", err, "webhook", endpoint.Name) continue }- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L284:
s.logger.Errorw("failed to initialise webhook handler", "error", err, "webhook", endpoint.Name)- What: Calls s.logger.Errorw.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L285:
continue- What: Executes a statement.
- Why: Advances the function logic.
- How: Runs this statement as part of the function body.
- L284:
- L287:
s.router.Handle(endpoint.Path, handler)- What: Calls s.router.Handle.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L288:
s.logger.Infow("registered webhook endpoint", "webhook", endpoint.Name, "path", endpoint.Path)- What: Calls s.logger.Infow.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L268:
(*Server).trackRequest
What: Integrates request completion tracking for protocol metrics and websocket limiter release.
Why: Normal HTTP requests complete with a status code, but websocket upgrades need limiter release when the request lifecycle ends.
How: Wraps protocolMetrics.track (if enabled) and releases websocket capacity (if the request carried websocket context) when the returned closure is invoked.
func (s *Server) trackRequest(r *http.Request) func(status int, elapsed time.Duration) {
var track func(int, time.Duration)
if s.protocolMetrics != nil {
track = s.protocolMetrics.track(r)
}
wc, ok := websocketContextFromRequest(r)
return func(status int, elapsed time.Duration) {
if track != nil {
track(status, elapsed)
}
if ok {
wc.release()
}
}
}
Walkthrough
The list below documents the statements inside the function body, including nested blocks and inline closures.
- L293:
var track func(int, time.Duration)- What: Declares local names.
- Why: Introduces variables or types used later in the function.
- How: Executes a Go declaration statement inside the function body.
- L294:
if s.protocolMetrics != nil { track = s.protocolMetrics.track(r) }- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L295:
track = s.protocolMetrics.track(r)- What: Assigns track.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L295:
- L297:
wc, ok := websocketContextFromRequest(r)- What: Defines wc, ok.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L298:
return func(status int, elapsed time.Duration) { if track != nil { track(status, elapsed) } if ok { wc.release() } }- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values). - Nested steps:
- L298:
func(status int, elapsed time.Duration) { if track != nil { track(status, elapsed) } if ok { wc.release() } }- What: Defines an inline function (closure).
- Why: Encapsulates callback logic and may capture variables from the surrounding scope.
- How: Declares a
funcliteral and uses it as a value (for example, as an HTTP handler or callback). - Nested steps:
- L299:
if track != nil { track(status, elapsed) }- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L300:
track(status, elapsed)- What: Calls track.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L300:
- L302:
if ok { wc.release() }- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L303:
wc.release()- What: Calls wc.release.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L303:
- L299:
- L298:
(*Server).hijackedRequest
What: Integrates hijack tracking for protocol metrics and websocket capacity release/idle timeout.
Why: WebSockets and other upgraded connections bypass normal response completion; metrics and limits must be tracked via Hijack().
How: Combines protocol-metrics closer (if enabled) with websocket limiter release, and provides an optional net.Conn wrapper that applies idle deadlines.
func (s *Server) hijackedRequest(r *http.Request) (func(), func(net.Conn) net.Conn) {
var metricsCloser func()
if s.protocolMetrics != nil {
metricsCloser = s.protocolMetrics.hijacked(r)
}
wc, ok := websocketContextFromRequest(r)
if !ok {
return metricsCloser, nil
}
release := wc.release
if release == nil {
release = func() {}
}
combined := func() {
release()
if metricsCloser != nil {
metricsCloser()
}
}
return combined, func(conn net.Conn) net.Conn {
if wc.timeout <= 0 {
return conn
}
return &deadlineConn{Conn: conn, timeout: wc.timeout}
}
}
Walkthrough
The list below documents the statements inside the function body, including nested blocks and inline closures.
- L309:
var metricsCloser func()- What: Declares local names.
- Why: Introduces variables or types used later in the function.
- How: Executes a Go declaration statement inside the function body.
- L310:
if s.protocolMetrics != nil { metricsCloser = s.protocolMetrics.hijacked(r) }- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L311:
metricsCloser = s.protocolMetrics.hijacked(r)- What: Assigns metricsCloser.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L311:
- L313:
wc, ok := websocketContextFromRequest(r)- What: Defines wc, ok.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L314:
if !ok { return metricsCloser, nil }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L315:
return metricsCloser, nil- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L315:
- L317:
release := wc.release- What: Defines release.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L318:
if release == nil { release = func() {} }- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L319:
release = func() {}- What: Assigns release.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- Nested steps:
- L319:
func() {}- What: Defines an inline function (closure).
- Why: Encapsulates callback logic and may capture variables from the surrounding scope.
- How: Declares a
funcliteral and uses it as a value (for example, as an HTTP handler or callback).
- L319:
- L319:
- L321:
combined := func() { release() if metricsCloser != nil { metricsCloser() } }- What: Defines combined.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- Nested steps:
- L321:
func() { release() if metricsCloser != nil { metricsCloser() } }- What: Defines an inline function (closure).
- Why: Encapsulates callback logic and may capture variables from the surrounding scope.
- How: Declares a
funcliteral and uses it as a value (for example, as an HTTP handler or callback). - Nested steps:
- L322:
release()- What: Calls release.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L323:
if metricsCloser != nil { metricsCloser() }- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L324:
metricsCloser()- What: Calls metricsCloser.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L324:
- L322:
- L321:
- L327:
return combined, func(conn net.Conn) net.Conn { if wc.timeout <= 0 { return conn } return &deadlineConn{Conn: conn, timeout: wc.timeout} }- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values). - Nested steps:
- L327:
func(conn net.Conn) net.Conn { if wc.timeout <= 0 { return conn } return &deadlineConn{Conn: conn, timeout: wc.timeout} }- What: Defines an inline function (closure).
- Why: Encapsulates callback logic and may capture variables from the surrounding scope.
- How: Declares a
funcliteral and uses it as a value (for example, as an HTTP handler or callback). - Nested steps:
- L328:
if wc.timeout <= 0 { return conn }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L329:
return conn- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L329:
- L331:
return &deadlineConn{Conn: conn, timeout: wc.timeout}- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L328:
- L327:
websocketLimitMiddleware
What: Middleware that enforces websocket concurrency limits and stores websocket bookkeeping in request context.
Why: Upgraded connections are long-lived; limiting upgrades prevents resource exhaustion.
How: For websocket requests, acquires the limiter and rejects with 503 on exhaustion; otherwise stores a release func + idle timeout in context for downstream tracking.
func websocketLimitMiddleware(limiter *websocketLimiter, timeout time.Duration, trace gatewaymiddleware.TraceIDFromContext, write gatewaymiddleware.ProblemWriter, logger pkglog.Logger) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
if limiter == nil || next == nil {
return next
}
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if !isWebSocketRequest(r) {
next.ServeHTTP(w, r)
return
}
release, ok := limiter.Acquire()
if !ok {
if write != nil {
tid := ""
if trace != nil {
tid = trace(r.Context())
}
write(w, http.StatusServiceUnavailable, "WebSocket Limit Reached", "Gateway is at websocket capacity", tid, r.URL.Path)
} else {
http.Error(w, http.StatusText(http.StatusServiceUnavailable), http.StatusServiceUnavailable)
}
if logger != nil {
logger.Warnw("websocket connection rejected", "limit", limiter.limit)
}
return
}
ctx := context.WithValue(r.Context(), websocketContextKey{}, websocketContext{
release: release,
timeout: timeout,
})
next.ServeHTTP(w, r.WithContext(ctx))
})
}
}
Walkthrough
The list below documents the statements inside the function body, including nested blocks and inline closures.
- L336:
return func(next http.Handler) http.Handler { if limiter == nil || next == nil { return next } return http.HandlerFunc(func(w http.Response…- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values). - Nested steps:
- L336:
func(next http.Handler) http.Handler { if limiter == nil || next == nil { return next } return http.HandlerFunc(func(w http.ResponseWriter,…- What: Defines an inline function (closure).
- Why: Encapsulates callback logic and may capture variables from the surrounding scope.
- How: Declares a
funcliteral and uses it as a value (for example, as an HTTP handler or callback). - Nested steps:
- L337:
if limiter == nil || next == nil { return next }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L338:
return next- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L338:
- L340:
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if !isWebSocketRequest(r) { next.ServeHTTP(w, r) return } release, o…- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values). - Nested steps:
- L340:
func(w http.ResponseWriter, r *http.Request) { if !isWebSocketRequest(r) { next.ServeHTTP(w, r) return } release, ok := limiter.Acquire() i…- What: Defines an inline function (closure).
- Why: Encapsulates callback logic and may capture variables from the surrounding scope.
- How: Declares a
funcliteral and uses it as a value (for example, as an HTTP handler or callback). - Nested steps:
- L341:
if !isWebSocketRequest(r) { next.ServeHTTP(w, r) return }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L342:
next.ServeHTTP(w, r)- What: Calls next.ServeHTTP.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L343:
return- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L342:
- L346:
release, ok := limiter.Acquire()- What: Defines release, ok.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L347:
if !ok { if write != nil { tid := "" if trace != nil { tid = trace(r.Context()) } write(w, http.StatusServiceUnavailable, "WebSocket Limit …- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L348:
if write != nil { tid := "" if trace != nil { tid = trace(r.Context()) } write(w, http.StatusServiceUnavailable, "WebSocket Limit Reached",…- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L349:
tid := ""- What: Defines tid.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L350:
if trace != nil { tid = trace(r.Context()) }- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- L353:
write(w, http.StatusServiceUnavailable, "WebSocket Limit Reached", "Gateway is at websocket capacity", tid, r.URL.Path)- What: Calls write.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L355:
http.Error(w, http.StatusText(http.StatusServiceUnavailable), http.StatusServiceUnavailable)- What: Calls http.Error.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L349:
- L357:
if logger != nil { logger.Warnw("websocket connection rejected", "limit", limiter.limit) }- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L358:
logger.Warnw("websocket connection rejected", "limit", limiter.limit)- What: Calls logger.Warnw.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L358:
- L360:
return- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L348:
- L363:
ctx := context.WithValue(r.Context(), websocketContextKey{}, websocketContext{ release: release, timeout: timeout, })- What: Defines ctx.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L367:
next.ServeHTTP(w, r.WithContext(ctx))- What: Calls next.ServeHTTP.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L341:
- L340:
- L337:
- L336:
(*deadlineConn).Read
What: Wraps net.Conn.Read with a per-operation read deadline.
Why: Enforces websocket idle timeout by timing out reads on inactive connections.
How: Sets SetReadDeadline(now + timeout) before delegating to the underlying connection.
func (c *deadlineConn) Read(b []byte) (int, error) {
if c.timeout > 0 {
_ = c.Conn.SetReadDeadline(time.Now().Add(c.timeout))
}
return c.Conn.Read(b)
}
Walkthrough
The list below documents the statements inside the function body, including nested blocks and inline closures.
- L378:
if c.timeout > 0 { _ = c.Conn.SetReadDeadline(time.Now().Add(c.timeout)) }- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L379:
_ = c.Conn.SetReadDeadline(time.Now().Add(c.timeout))- What: Assigns _.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L379:
- L381:
return c.Conn.Read(b)- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
(*deadlineConn).Write
What: Wraps net.Conn.Write with a per-operation write deadline.
Why: Prevents writes from blocking forever on idle or stalled websocket connections.
How: Sets SetWriteDeadline(now + timeout) before delegating to the underlying connection.
func (c *deadlineConn) Write(b []byte) (int, error) {
if c.timeout > 0 {
_ = c.Conn.SetWriteDeadline(time.Now().Add(c.timeout))
}
return c.Conn.Write(b)
}
Walkthrough
The list below documents the statements inside the function body, including nested blocks and inline closures.
- L385:
if c.timeout > 0 { _ = c.Conn.SetWriteDeadline(time.Now().Add(c.timeout)) }- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L386:
_ = c.Conn.SetWriteDeadline(time.Now().Add(c.timeout))- What: Assigns _.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L386:
- L388:
return c.Conn.Write(b)- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
newWebsocketLimiter
What: Constructs a websocketLimiter for the configured max concurrency.
Why: Encapsulates websocket capacity logic in a single component.
How: Returns a limiter with the provided limit; 0 or negative values are treated as unlimited by Acquire().
func newWebsocketLimiter(limit int) *websocketLimiter {
return &websocketLimiter{limit: limit}
}
Walkthrough
The list below documents the statements inside the function body, including nested blocks and inline closures.
- L398:
return &websocketLimiter{limit: limit}- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
(*websocketLimiter).Acquire
What: Attempts to acquire a websocket slot and returns a release function when successful.
Why: Provides bounded concurrency for upgrades and ensures capacity is returned exactly once.
How: If unlimited, returns an always-ok release; otherwise increments an internal counter under mutex and returns a sync.Once-guarded release that decrements.
func (l *websocketLimiter) Acquire() (func(), bool) {
if l == nil {
return func() {}, true
}
if l.limit <= 0 {
var once sync.Once
return func() { once.Do(func() {}) }, true
}
l.mu.Lock()
defer l.mu.Unlock()
if l.active >= l.limit {
return nil, false
}
l.active++
var once sync.Once
return func() {
once.Do(func() {
l.mu.Lock()
l.active--
l.mu.Unlock()
})
}, true
}
Walkthrough
The list below documents the statements inside the function body, including nested blocks and inline closures.
- L402:
if l == nil { return func() {}, true }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L403:
return func() {}, true- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values). - Nested steps:
- L403:
func() {}- What: Defines an inline function (closure).
- Why: Encapsulates callback logic and may capture variables from the surrounding scope.
- How: Declares a
funcliteral and uses it as a value (for example, as an HTTP handler or callback).
- L403:
- L403:
- L405:
if l.limit <= 0 { var once sync.Once return func() { once.Do(func() {}) }, true }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L406:
var once sync.Once- What: Declares local names.
- Why: Introduces variables or types used later in the function.
- How: Executes a Go declaration statement inside the function body.
- L407:
return func() { once.Do(func() {}) }, true- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values). - Nested steps:
- L407:
func() { once.Do(func() {}) }- What: Defines an inline function (closure).
- Why: Encapsulates callback logic and may capture variables from the surrounding scope.
- How: Declares a
funcliteral and uses it as a value (for example, as an HTTP handler or callback). - Nested steps:
- L407:
once.Do(func() {})- What: Calls once.Do.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- Nested steps:
- L407:
func() {}- What: Defines an inline function (closure).
- Why: Encapsulates callback logic and may capture variables from the surrounding scope.
- How: Declares a
funcliteral and uses it as a value (for example, as an HTTP handler or callback).
- L407:
- L407:
- L407:
- L406:
- L409:
l.mu.Lock()- What: Calls l.mu.Lock.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L410:
defer l.mu.Unlock()- What: Defers a call for cleanup.
- Why: Ensures the deferred action runs even on early returns.
- How: Schedules the call to run when the surrounding function returns.
- L411:
if l.active >= l.limit { return nil, false }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L412:
return nil, false- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L412:
- L414:
l.active++- What: Updates a counter.
- Why: Maintains an index or tally used by subsequent logic.
- How: Executes an increment/decrement statement.
- L415:
var once sync.Once- What: Declares local names.
- Why: Introduces variables or types used later in the function.
- How: Executes a Go declaration statement inside the function body.
- L416:
return func() { once.Do(func() { l.mu.Lock() l.active-- l.mu.Unlock() }) }, true- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values). - Nested steps:
- L416:
func() { once.Do(func() { l.mu.Lock() l.active-- l.mu.Unlock() }) }- What: Defines an inline function (closure).
- Why: Encapsulates callback logic and may capture variables from the surrounding scope.
- How: Declares a
funcliteral and uses it as a value (for example, as an HTTP handler or callback). - Nested steps:
- L417:
once.Do(func() { l.mu.Lock() l.active-- l.mu.Unlock() })- What: Calls once.Do.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- Nested steps:
- L417:
func() { l.mu.Lock() l.active-- l.mu.Unlock() }- What: Defines an inline function (closure).
- Why: Encapsulates callback logic and may capture variables from the surrounding scope.
- How: Declares a
funcliteral and uses it as a value (for example, as an HTTP handler or callback). - Nested steps:
- L418:
l.mu.Lock()- What: Calls l.mu.Lock.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L419:
l.active--- What: Updates a counter.
- Why: Maintains an index or tally used by subsequent logic.
- How: Executes an increment/decrement statement.
- L420:
l.mu.Unlock()- What: Calls l.mu.Unlock.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L418:
- L417:
- L417:
- L416:
isWebSocketRequest
What: Detects whether an HTTP request is attempting to upgrade to a WebSocket connection.
Why: WebSocket upgrades require special handling (capacity limiting, hijack tracking, idle timeouts).
How: Checks whether the request is attempting an upgrade to websocket via the Upgrade and Connection headers.
func isWebSocketRequest(r *http.Request) bool {
if r == nil {
return false
}
if strings.EqualFold(r.Header.Get("Upgrade"), "websocket") {
return true
}
connection := strings.ToLower(r.Header.Get("Connection"))
return strings.Contains(connection, "upgrade") && strings.EqualFold(r.Header.Get("Upgrade"), "websocket")
}
Walkthrough
The list below documents the statements inside the function body, including nested blocks and inline closures.
- L426:
if r == nil { return false }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L427:
return false- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L427:
- L429:
if strings.EqualFold(r.Header.Get("Upgrade"), "websocket") { return true }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L430:
return true- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L430:
- L432:
connection := strings.ToLower(r.Header.Get("Connection"))- What: Defines connection.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L433:
return strings.Contains(connection, "upgrade") && strings.EqualFold(r.Header.Get("Upgrade"), "websocket")- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
websocketContextFromRequest
What: Extracts websocket limiter context from a request.
Why: The websocket limiter must release capacity when the request completes or when the connection is hijacked/closed.
How: Reads a websocketContext value from the request context and ensures release is non-nil.
func websocketContextFromRequest(r *http.Request) (websocketContext, bool) {
if r == nil {
return websocketContext{}, false
}
v, ok := r.Context().Value(websocketContextKey{}).(websocketContext)
if !ok {
return websocketContext{}, false
}
if v.release == nil {
v.release = func() {}
}
return v, true
}
Walkthrough
The list below documents the statements inside the function body, including nested blocks and inline closures.
- L444:
if r == nil { return websocketContext{}, false }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L445:
return websocketContext{}, false- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L445:
- L447:
v, ok := r.Context().Value(websocketContextKey{}).(websocketContext)- What: Defines v, ok.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L448:
if !ok { return websocketContext{}, false }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L449:
return websocketContext{}, false- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L449:
- L451:
if v.release == nil { v.release = func() {} }- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L452:
v.release = func() {}- What: Assigns v.release.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- Nested steps:
- L452:
func() {}- What: Defines an inline function (closure).
- Why: Encapsulates callback logic and may capture variables from the surrounding scope.
- How: Declares a
funcliteral and uses it as a value (for example, as an HTTP handler or callback).
- L452:
- L452:
- L454:
return v, true- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
(*Server).buildProtectedHandler
What: Wraps an upstream proxy handler with authentication and scope enforcement.
Why: Trade/task upstreams require JWT authentication with product-specific scopes.
How: Ensures request/trace IDs, authenticates via gatewayauth.Authenticator, checks for required scopes, then forwards the request with routing metadata headers to the proxy.
func (s *Server) buildProtectedHandler(product string, requiredScopes []string, next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
req, requestID, traceID := ensureRequestIDs(r)
w.Header().Set("X-Request-Id", requestID)
w.Header().Set("X-Trace-Id", traceID)
if s.authenticator == nil {
gatewayproblem.Write(w, http.StatusServiceUnavailable, "Service Unavailable", "Gateway authentication is not configured", traceID, req.URL.Path)
return
}
principal, err := s.authenticator.Authenticate(req)
if err != nil {
s.writeAuthProblem(w, req, err, traceID)
return
}
if !principal.HasAnyScope(requiredScopes) {
gatewayproblem.Write(w, http.StatusForbidden, "Insufficient Scope", fmt.Sprintf("Requires one of scopes: %s", strings.Join(requiredScopes, ", ")), traceID, req.URL.Path)
return
}
req.Header.Set("X-Router-Product", product)
req.Header.Set("X-Request-Id", requestID)
req.Header.Set("X-Trace-Id", traceID)
next.ServeHTTP(w, req)
})
}
Walkthrough
The list below documents the statements inside the function body, including nested blocks and inline closures.
- L458:
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { req, requestID, traceID := ensureRequestIDs(r) w.Header().Set("X-Req…- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values). - Nested steps:
- L458:
func(w http.ResponseWriter, r *http.Request) { req, requestID, traceID := ensureRequestIDs(r) w.Header().Set("X-Request-Id", requestID) w.H…- What: Defines an inline function (closure).
- Why: Encapsulates callback logic and may capture variables from the surrounding scope.
- How: Declares a
funcliteral and uses it as a value (for example, as an HTTP handler or callback). - Nested steps:
- L459:
req, requestID, traceID := ensureRequestIDs(r)- What: Defines req, requestID, traceID.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L460:
w.Header().Set("X-Request-Id", requestID)- What: Calls w.Header().Set.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L461:
w.Header().Set("X-Trace-Id", traceID)- What: Calls w.Header().Set.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L463:
if s.authenticator == nil { gatewayproblem.Write(w, http.StatusServiceUnavailable, "Service Unavailable", "Gateway authentication is not co…- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L464:
gatewayproblem.Write(w, http.StatusServiceUnavailable, "Service Unavailable", "Gateway authentication is not configured", traceID, req.URL.…- What: Calls gatewayproblem.Write.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L465:
return- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L464:
- L468:
principal, err := s.authenticator.Authenticate(req)- What: Defines principal, err.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L469:
if err != nil { s.writeAuthProblem(w, req, err, traceID) return }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L470:
s.writeAuthProblem(w, req, err, traceID)- What: Calls s.writeAuthProblem.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L471:
return- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L470:
- L474:
if !principal.HasAnyScope(requiredScopes) { gatewayproblem.Write(w, http.StatusForbidden, "Insufficient Scope", fmt.Sprintf("Requires one o…- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L475:
gatewayproblem.Write(w, http.StatusForbidden, "Insufficient Scope", fmt.Sprintf("Requires one of scopes: %s", strings.Join(requiredScopes, …- What: Calls gatewayproblem.Write.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L476:
return- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L475:
- L479:
req.Header.Set("X-Router-Product", product)- What: Calls req.Header.Set.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L480:
req.Header.Set("X-Request-Id", requestID)- What: Calls req.Header.Set.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L481:
req.Header.Set("X-Trace-Id", traceID)- What: Calls req.Header.Set.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L483:
next.ServeHTTP(w, req)- What: Calls next.ServeHTTP.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L459:
- L458:
(*Server).writeAuthProblem
What: Converts authentication errors into consistent Problem+JSON responses.
Why: Callers need stable error formatting and correct WWW-Authenticate semantics.
How: Special-cases gatewayauth.Error to use its status/title/detail and conditionally sets WWW-Authenticate; otherwise returns a generic 401.
func (s *Server) writeAuthProblem(w http.ResponseWriter, r *http.Request, err error, traceID string) {
switch e := err.(type) {
case gatewayauth.Error:
if e.Status == http.StatusUnauthorized {
w.Header().Set("WWW-Authenticate", "Bearer")
}
gatewayproblem.Write(w, e.Status, e.Title, e.Detail, traceID, r.URL.Path)
default:
w.Header().Set("WWW-Authenticate", "Bearer")
gatewayproblem.Write(w, http.StatusUnauthorized, "Authentication Required", err.Error(), traceID, r.URL.Path)
}
}
Walkthrough
The list below documents the statements inside the function body, including nested blocks and inline closures.
- L488:
switch e := err.(type) { case gatewayauth.Error: if e.Status == http.StatusUnauthorized { w.Header().Set("WWW-Authenticate", "Bearer") } ga…- What: Selects a branch based on dynamic type.
- Why: Handles multiple concrete types cleanly.
- How: Executes a type switch statement.
- Nested steps:
- L488:
e := err.(type)- What: Defines e.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L489:
case gatewayauth.Error:- What: Selects a switch case.
- Why: Makes multi-branch control flow explicit and readable.
- How: Runs this case body when the switch value matches (or when default is selected).
- Nested steps:
- L490:
if e.Status == http.StatusUnauthorized { w.Header().Set("WWW-Authenticate", "Bearer") }- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L491:
w.Header().Set("WWW-Authenticate", "Bearer")- What: Calls w.Header().Set.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L491:
- L493:
gatewayproblem.Write(w, e.Status, e.Title, e.Detail, traceID, r.URL.Path)- What: Calls gatewayproblem.Write.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L490:
- L494:
default:- What: Selects a switch case.
- Why: Makes multi-branch control flow explicit and readable.
- How: Runs this case body when the switch value matches (or when default is selected).
- Nested steps:
- L495:
w.Header().Set("WWW-Authenticate", "Bearer")- What: Calls w.Header().Set.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L496:
gatewayproblem.Write(w, http.StatusUnauthorized, "Authentication Required", err.Error(), traceID, r.URL.Path)- What: Calls gatewayproblem.Write.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L495:
- L488:
clientKey
What: Derives the rate-limit key for a request.
Why: Rate limiting needs a stable key; client IP is the default heuristic.
How: Uses clientAddress; falls back to "global" if no address can be resolved.
func clientKey(r *http.Request) string {
addr := clientAddress(r)
if addr == "" {
return "global"
}
return addr
}
Walkthrough
The list below documents the statements inside the function body, including nested blocks and inline closures.
- L501:
addr := clientAddress(r)- What: Defines addr.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L502:
if addr == "" { return "global" }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L503:
return "global"- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L503:
- L505:
return addr- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
clientAddress
What: Resolves a best-effort client IP address string for logging and rate limiting.
Why: Gateway deployments are commonly behind load balancers; RemoteAddr may reflect a proxy.
How: Uses the first value in X-Forwarded-For when present, otherwise parses RemoteAddr host.
func clientAddress(r *http.Request) string {
if r == nil {
return ""
}
if forwarded := r.Header.Get("X-Forwarded-For"); forwarded != "" {
parts := strings.Split(forwarded, ",")
if len(parts) > 0 {
return strings.TrimSpace(parts[0])
}
}
host, _, err := net.SplitHostPort(r.RemoteAddr)
if err != nil {
return strings.TrimSpace(r.RemoteAddr)
}
return host
}
Walkthrough
The list below documents the statements inside the function body, including nested blocks and inline closures.
- L509:
if r == nil { return "" }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L510:
return ""- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L510:
- L513:
if forwarded := r.Header.Get("X-Forwarded-For"); forwarded != "" { parts := strings.Split(forwarded, ",") if len(parts) > 0 { return string…- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L513:
forwarded := r.Header.Get("X-Forwarded-For")- What: Defines forwarded.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L514:
parts := strings.Split(forwarded, ",")- What: Defines parts.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L515:
if len(parts) > 0 { return strings.TrimSpace(parts[0]) }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L516:
return strings.TrimSpace(parts[0])- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L516:
- L513:
- L520:
host, _, err := net.SplitHostPort(r.RemoteAddr)- What: Defines host, _, err.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L521:
if err != nil { return strings.TrimSpace(r.RemoteAddr) }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L522:
return strings.TrimSpace(r.RemoteAddr)- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L522:
- L524:
return host- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
buildCORS
What: Constructs a CORS policy object from configured allowed origins.
Why: Browser clients require explicit cross-origin policy; CORS needs to be environment-configurable.
How: Treats empty origins as allow-all, supports * to force allow-all, otherwise allows only exact origin matches and configures allowed methods/headers.
func buildCORS(origins []string) *cors.Cors {
allowAll := len(origins) == 0
allowed := make(map[string]struct{})
for _, origin := range origins {
o := strings.TrimSpace(origin)
if o == "" {
continue
}
if o == "*" {
allowAll = true
allowed = nil
break
}
allowed[o] = struct{}{}
}
return cors.New(cors.Options{
AllowedMethods: []string{http.MethodGet, http.MethodHead, http.MethodPost, http.MethodPut, http.MethodPatch, http.MethodDelete, http.MethodOptions},
AllowedHeaders: []string{"*"},
ExposedHeaders: []string{"X-Request-Id", "X-Trace-Id"},
OptionsSuccessStatus: http.StatusNoContent,
AllowOriginRequestFunc: func(_ *http.Request, origin string) bool {
if origin == "" {
return true
}
if allowAll {
return true
}
if allowed == nil {
return true
}
_, ok := allowed[origin]
return ok
},
})
}
Walkthrough
The list below documents the statements inside the function body, including nested blocks and inline closures.
- L528:
allowAll := len(origins) == 0- What: Defines allowAll.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L530:
allowed := make(map[string]struct{})- What: Defines allowed.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L531:
for _, origin := range origins { o := strings.TrimSpace(origin) if o == "" { continue } if o == "*" { allowAll = true allowed = nil break }…- What: Iterates over a collection.
- Why: Processes multiple elements with the same logic.
- How: Executes a
for ... rangeloop. - Nested steps:
- L532:
o := strings.TrimSpace(origin)- What: Defines o.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L533:
if o == "" { continue }- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L534:
continue- What: Executes a statement.
- Why: Advances the function logic.
- How: Runs this statement as part of the function body.
- L534:
- L536:
if o == "*" { allowAll = true allowed = nil break }- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L537:
allowAll = true- What: Assigns allowAll.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L538:
allowed = nil- What: Assigns allowed.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L539:
break- What: Executes a statement.
- Why: Advances the function logic.
- How: Runs this statement as part of the function body.
- L537:
- L541:
allowed[o] = struct{}{}- What: Assigns allowed[o].
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L532:
- L544:
return cors.New(cors.Options{ AllowedMethods: []string{http.MethodGet, http.MethodHead, http.MethodPost, http.MethodPut, http.MethodPatch, …- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values). - Nested steps:
- L549:
func(_ *http.Request, origin string) bool { if origin == "" { return true } if allowAll { return true } if allowed == nil { return true } _…- What: Defines an inline function (closure).
- Why: Encapsulates callback logic and may capture variables from the surrounding scope.
- How: Declares a
funcliteral and uses it as a value (for example, as an HTTP handler or callback). - Nested steps:
- L550:
if origin == "" { return true }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L551:
return true- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L551:
- L553:
if allowAll { return true }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L554:
return true- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L554:
- L556:
if allowed == nil { return true }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L557:
return true- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L557:
- L559:
_, ok := allowed[origin]- What: Defines _, ok.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L560:
return ok- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L550:
- L549:
(*Server).handleHealth
What: Implements GET /health and returns basic process health + metadata.
Why: Provides a lightweight liveness endpoint for load balancers and orchestration.
How: Returns JSON with status, uptime, timestamp, and optional version; always 200 unless encoding fails.
func (s *Server) handleHealth(w http.ResponseWriter, r *http.Request) {
_, requestID, _ := ensureRequestIDs(r)
w.Header().Set("Content-Type", "application/json")
w.Header().Set("X-Request-Id", requestID)
response := struct {
Status string `json:"status"`
Uptime float64 `json:"uptime"`
Timestamp string `json:"timestamp"`
Version string `json:"version,omitempty"`
}{
Status: "ok",
Uptime: time.Since(s.bootTime).Seconds(),
Timestamp: time.Now().UTC().Format(time.RFC3339),
Version: s.cfg.Version,
}
w.WriteHeader(http.StatusOK)
_ = json.NewEncoder(w).Encode(response)
}
Walkthrough
The list below documents the statements inside the function body, including nested blocks and inline closures.
- L566:
_, requestID, _ := ensureRequestIDs(r)- What: Defines _, requestID, _.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L567:
w.Header().Set("Content-Type", "application/json")- What: Calls w.Header().Set.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L568:
w.Header().Set("X-Request-Id", requestID)- What: Calls w.Header().Set.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L570:
response := struct { Status string `json:"status"` Uptime float64 `json:"uptime"` Timestamp string `json:"timestamp"` Version string `json:…- What: Defines response.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L582:
w.WriteHeader(http.StatusOK)- What: Calls w.WriteHeader.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L583:
_ = json.NewEncoder(w).Encode(response)- What: Assigns _.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
(*Server).handleReadiness
What: Implements GET /readyz and GET /readiness by probing upstreams.
Why: Readiness should reflect upstream reachability so rollouts don't send traffic to an unusable gateway.
How: Calls healthChecker.Readiness, returns 200 when ready and 503 otherwise, and includes upstream results plus request/trace IDs in JSON.
func (s *Server) handleReadiness(w http.ResponseWriter, r *http.Request) {
var requestID, traceID string
r, requestID, traceID = ensureRequestIDs(r)
w.Header().Set("Content-Type", "application/json")
w.Header().Set("X-Request-Id", requestID)
report := health.Report{Status: "ready", CheckedAt: time.Now().UTC()}
if s.healthChecker != nil {
report = s.healthChecker.Readiness(r.Context())
}
statusCode := http.StatusOK
if report.Status != "ready" {
statusCode = http.StatusServiceUnavailable
}
response := struct {
Status string `json:"status"`
CheckedAt time.Time `json:"checkedAt"`
Upstreams []health.UpstreamReport `json:"upstreams"`
RequestID string `json:"requestId,omitempty"`
TraceID string `json:"traceId,omitempty"`
}{
Status: report.Status,
CheckedAt: report.CheckedAt,
Upstreams: report.Upstreams,
RequestID: requestID,
TraceID: traceID,
}
w.WriteHeader(statusCode)
_ = json.NewEncoder(w).Encode(response)
}
Walkthrough
The list below documents the statements inside the function body, including nested blocks and inline closures.
- L587:
var requestID, traceID string- What: Declares local names.
- Why: Introduces variables or types used later in the function.
- How: Executes a Go declaration statement inside the function body.
- L588:
r, requestID, traceID = ensureRequestIDs(r)- What: Assigns r, requestID, traceID.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L589:
w.Header().Set("Content-Type", "application/json")- What: Calls w.Header().Set.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L590:
w.Header().Set("X-Request-Id", requestID)- What: Calls w.Header().Set.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L592:
report := health.Report{Status: "ready", CheckedAt: time.Now().UTC()}- What: Defines report.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L593:
if s.healthChecker != nil { report = s.healthChecker.Readiness(r.Context()) }- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L594:
report = s.healthChecker.Readiness(r.Context())- What: Assigns report.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L594:
- L597:
statusCode := http.StatusOK- What: Defines statusCode.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L598:
if report.Status != "ready" { statusCode = http.StatusServiceUnavailable }- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L599:
statusCode = http.StatusServiceUnavailable- What: Assigns statusCode.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L599:
- L602:
response := struct { Status string `json:"status"` CheckedAt time.Time `json:"checkedAt"` Upstreams []health.UpstreamReport `json:"upstream…- What: Defines response.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L616:
w.WriteHeader(statusCode)- What: Calls w.WriteHeader.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L617:
_ = json.NewEncoder(w).Encode(response)- What: Assigns _.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
(*Server).handleOpenAPI
What: Implements GET /openapi.json using the configured OpenAPI provider.
Why: Exposes the merged API contract for clients and tooling.
How: Calls openapiProvider.Document(ctx), returns Problem+JSON on error, otherwise writes the raw JSON bytes.
func (s *Server) handleOpenAPI(w http.ResponseWriter, r *http.Request) {
if s.openapiProvider == nil {
gatewayproblem.Write(w, http.StatusServiceUnavailable, "OpenAPI Unavailable", "OpenAPI provider not configured", traceIDFromContext(r.Context()), r.URL.Path)
return
}
data, err := s.openapiProvider.Document(r.Context())
if err != nil {
traceID := traceIDFromContext(r.Context())
gatewayproblem.Write(w, http.StatusServiceUnavailable, "OpenAPI Unavailable", err.Error(), traceID, r.URL.Path)
return
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
if _, err := w.Write(data); err != nil {
s.logger.Warnw("failed to write openapi response", "error", err)
}
}
Walkthrough
The list below documents the statements inside the function body, including nested blocks and inline closures.
- L621:
if s.openapiProvider == nil { gatewayproblem.Write(w, http.StatusServiceUnavailable, "OpenAPI Unavailable", "OpenAPI provider not configure…- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L622:
gatewayproblem.Write(w, http.StatusServiceUnavailable, "OpenAPI Unavailable", "OpenAPI provider not configured", traceIDFromContext(r.Conte…- What: Calls gatewayproblem.Write.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L623:
return- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L622:
- L626:
data, err := s.openapiProvider.Document(r.Context())- What: Defines data, err.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L627:
if err != nil { traceID := traceIDFromContext(r.Context()) gatewayproblem.Write(w, http.StatusServiceUnavailable, "OpenAPI Unavailable", er…- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L628:
traceID := traceIDFromContext(r.Context())- What: Defines traceID.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L629:
gatewayproblem.Write(w, http.StatusServiceUnavailable, "OpenAPI Unavailable", err.Error(), traceID, r.URL.Path)- What: Calls gatewayproblem.Write.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L630:
return- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L628:
- L633:
w.Header().Set("Content-Type", "application/json")- What: Calls w.Header().Set.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L634:
w.WriteHeader(http.StatusOK)- What: Calls w.WriteHeader.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L635:
if _, err := w.Write(data); err != nil { s.logger.Warnw("failed to write openapi response", "error", err) }- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L635:
_, err := w.Write(data)- What: Defines _, err.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L636:
s.logger.Warnw("failed to write openapi response", "error", err)- What: Calls s.logger.Warnw.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L635: