package server import ( "time" "github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5/middleware" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/collectors" "github.com/prometheus/client_golang/prometheus/promhttp" ) const ( requestTimeout = 60 * time.Second // maxRequestBodyBytes caps every request body. A route group // can mount s.mw.MaxBodyBytes with a smaller value to lower // its bound, but cannot raise it: this cap runs first. maxRequestBodyBytes int64 = 1 << 20 // 1 MiB ) // SetupRoutes configures the chi router with middleware and // all application routes. func (s *Server) SetupRoutes() { s.router = chi.NewRouter() s.router.Use(s.mw.Recoverer()) s.router.Use(middleware.RequestID) s.router.Use(s.mw.Logging()) s.router.Use(s.mw.SecurityHeaders()) s.router.Use(s.mw.CORS(s.params.Config.CORSAllowedOrigins)) s.router.Use(s.mw.MaxBodyBytes(maxRequestBodyBytes)) s.router.Use(middleware.Timeout(requestTimeout)) // The metrics go in a registry of this server's own, not in // Prometheus' default one, which takes them only once per process. registry := prometheus.NewRegistry() registry.MustRegister( collectors.NewGoCollector(), collectors.NewProcessCollector(collectors.ProcessCollectorOpts{}), ) // Requests are measured only once chi has matched them to one of // these routes, by path and method. The metrics are labelled with // both, which any client can make up, so measuring every request // would let clients add labels without bound. A Route here would // be matched by its path prefix alone, so each path is given in // full. s.router.Group(func(r chi.Router) { // config.New refuses one of the two credentials without the // other. if s.params.Config.MetricsUsername != "" { r.Use(s.mw.Metrics(registry)) } r.Get("/.well-known/healthcheck", s.h.HandleHealthCheck()) r.With(s.mw.RateLimit(s.params.Config.ReportsPerMinute)). Post("/api/v1/reports", s.h.HandleReport()) }) if s.params.Config.MetricsUsername != "" { s.router.With(s.mw.MetricsAuth()). Get("/metrics", promhttp.HandlerFor( registry, promhttp.HandlerOpts{}, ).ServeHTTP) } }