Files
Warp/server/internal/httputil/router.go
T
tajniak81andClaude Opus 5 b4fb60a8ab
CI / Test (ubuntu-latest) (push) Canceled after 0s
CI / Test (windows-latest) (push) Canceled after 0s
CI / Storage tests on PostgreSQL (push) Canceled after 0s
CI / golangci-lint (push) Canceled after 0s
CI / Smoke test the binary (push) Canceled after 0s
Phase 0: bootstrap the Warp homeserver
Scaffolds the server module and everything Phase 0 of PLAN.md calls for:
a binary that boots, serves its discovery endpoints and nothing else yet.

- config: one YAML file plus per-field WARP_* environment overrides,
  unknown fields rejected, validation that reports every problem at once
- logging and metrics: slog, a Prometheus registry, per-route HTTP
  instrumentation labelled by pattern rather than path
- httputil: the Matrix error envelope, error-returning handlers, CORS,
  request logging, panic recovery, and a router over http.ServeMux
- endpoints: /_matrix/client/versions, /.well-known/matrix/client,
  /.well-known/matrix/server (gated), /healthz, /metrics, and
  M_UNRECOGNIZED for everything else
- storage: driver registry, shared database/sql base, checksummed
  migration runner, sqlite and postgres drivers, pocketbase stub
- settings: server_settings table behind a cached service, so the
  federation and registration switches change without a restart
- federation: the gate that makes federation a runtime mode
- cmd/warp: serve, migrate, generate-keys, version
- Makefile, golangci-lint v2, GitHub Actions CI (Linux and Windows tests,
  race on Linux, storage tests against PostgreSQL, lint, boot smoke test),
  Dockerfile, example config and docs

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-15 17:01:13 +02:00

51 lines
1.6 KiB
Go

package httputil
import (
"net/http"
)
// Instrumenter wraps a handler with per-route instrumentation. The route is
// the ServeMux pattern the handler is registered under; it is passed
// explicitly because the pattern ServeMux records on a request is not
// visible to middleware wrapping the mux from the outside.
type Instrumenter func(route string, h http.Handler) http.Handler
// Router is a thin layer over http.ServeMux that applies an Instrumenter to
// every route and knows how to answer unrouted requests the Matrix way.
//
// Patterns use Go 1.22 syntax, method included:
//
// r.HandleFunc("GET /_matrix/client/versions", versions)
type Router struct {
mux *http.ServeMux
instrument Instrumenter
}
// NewRouter returns a router. A nil Instrumenter means no instrumentation.
func NewRouter(instrument Instrumenter) *Router {
if instrument == nil {
instrument = func(_ string, h http.Handler) http.Handler { return h }
}
mux := http.NewServeMux()
r := &Router{mux: mux, instrument: instrument}
// Anything that matches no other pattern is M_UNRECOGNIZED, per the
// Client-Server API's "Unsupported endpoints" rule.
r.Handle("/", NotFoundHandler())
return r
}
// Handle registers a handler for a pattern.
func (r *Router) Handle(pattern string, h http.Handler) {
r.mux.Handle(pattern, r.instrument(pattern, h))
}
// HandleFunc registers an error-returning handler for a pattern.
func (r *Router) HandleFunc(pattern string, h Handler) {
r.Handle(pattern, Wrap(h))
}
// ServeHTTP implements http.Handler.
func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
r.mux.ServeHTTP(w, req)
}