MCPcopy Create free account
hub / github.com/PerpetualSoftware/pad / setupRouter

Method setupRouter

internal/server/server.go:961–1656  ·  view source on GitHub ↗
()

Source from the content-addressed store, hash-verified

959}
960
961func (s *Server) setupRouter() {
962 r := chi.NewRouter()
963
964 // Infrastructure middleware (applies to all routes including /metrics)
965 // CapturePeerAddr MUST run before TrustedProxyRealIP so downstream code
966 // that needs to verify the real TCP peer (e.g. the bootstrap loopback
967 // check) can read the untampered value from request context even on
968 // deployments with a trusted reverse proxy in front.
969 r.Use(CapturePeerAddr)
970 // RealIP is gated on PAD_TRUSTED_PROXIES. When unset (the default), proxy
971 // headers are ignored and the real TCP peer address is used everywhere.
972 // This prevents X-Forwarded-For spoofing from bypassing rate limits, the
973 // bootstrap loopback check, or audit logs on direct-exposed deployments.
974 r.Use(TrustedProxyRealIP(s.trustedProxyCIDRs))
975 r.Use(chimiddleware.RequestID)
976 r.Use(StructuredLogger)
977 if s.metrics != nil {
978 r.Use(MetricsMiddleware(s.metrics))
979 }
980 r.Use(chimiddleware.Recoverer)
981
982 // Security headers (applies to all routes)
983 r.Use(SecurityHeaders)
984 if s.secureCookies {
985 r.Use(StrictTransportSecurity)
986 }
987
988 // MCP Streamable HTTP transport + OAuth discovery endpoints
989 // (PLAN-943 TASK-950). Mounted outside the standard /api/v1
990 // auth-required group because:
991 //
992 // - /mcp uses Bearer auth via its own MCPBearerAuth middleware,
993 // producing the spec-shape 401 + WWW-Authenticate that MCP
994 // clients expect (the API-stack 401 envelope is JSON-only and
995 // would fail Claude Desktop's discovery handshake).
996 // - /.well-known/oauth-protected-resource and
997 // /.well-known/oauth-authorization-server are public discovery
998 // documents (RFC 9728 / RFC 8414); routing them through
999 // TokenAuth+SessionAuth+RequireAuth would 401 unauth probes.
1000 //
1001 // No-op when SetMCPTransport hasn't been called or cloud mode is
1002 // off — see registerMCPRoutes for the gating.
1003 s.registerMCPRoutes(r)
1004
1005 // OAuth 2.1 authorization-server flow endpoints (PLAN-943
1006 // TASK-1025 sub-PR C). /oauth/{register,authorize,token,
1007 // authorize/decide} mounted alongside /mcp + /.well-known/*,
1008 // outside /api/v1's auth-required group. CSRF middleware runs
1009 // only on /api/* paths so /oauth/* is naturally exempt; the
1010 // consent-decision endpoint adds its own form-token check
1011 // using the existing __Host-pad_csrf cookie.
1012 //
1013 // SessionAuth runs in this group so /oauth/authorize can detect
1014 // whether the user is logged in via the __Host-pad_session
1015 // cookie. SessionAuth falls through gracefully when no cookie
1016 // is present (handlers see currentUser(r)==nil and redirect to
1017 // /login). RequireAuth is intentionally NOT used — /oauth/authorize
1018 // must be reachable anonymously to trigger the login redirect.

Callers 1

ensureRouterMethod · 0.95

Calls 11

registerMCPRoutesMethod · 0.95
registerOAuthRoutesMethod · 0.95
TrustedProxyRealIPFunction · 0.85
MetricsMiddlewareFunction · 0.85
parseCORSOriginsFunction · 0.85
corsAllowCredentialsFunction · 0.85
HandleMethod · 0.80
HandlerMethod · 0.80
GetMethod · 0.65
DeleteMethod · 0.65
PutMethod · 0.65

Tested by

no test coverage detected