2024-07-14 13:47:48 -04:00
|
|
|
package server
|
|
|
|
|
|
|
|
import (
|
2024-08-08 22:01:03 -04:00
|
|
|
"io/fs"
|
2024-07-14 13:47:48 -04:00
|
|
|
"net/http"
|
2024-08-08 22:01:03 -04:00
|
|
|
"strings"
|
2024-07-14 13:47:48 -04:00
|
|
|
|
2024-08-08 22:01:03 -04:00
|
|
|
"dynatron.me/x/stillbox/client"
|
2024-10-22 10:21:11 -04:00
|
|
|
"dynatron.me/x/stillbox/internal/version"
|
2024-11-03 07:19:03 -05:00
|
|
|
"dynatron.me/x/stillbox/pkg/config"
|
|
|
|
"dynatron.me/x/stillbox/pkg/database"
|
2024-11-09 13:14:31 -05:00
|
|
|
"dynatron.me/x/stillbox/pkg/talkgroups"
|
2024-07-14 13:47:48 -04:00
|
|
|
"github.com/go-chi/chi/v5"
|
2024-07-14 21:26:53 -04:00
|
|
|
"github.com/go-chi/chi/v5/middleware"
|
2024-07-14 17:39:03 -04:00
|
|
|
"github.com/go-chi/httprate"
|
|
|
|
"github.com/go-chi/render"
|
2024-07-14 13:47:48 -04:00
|
|
|
)
|
|
|
|
|
2024-10-22 10:21:11 -04:00
|
|
|
const (
|
|
|
|
serverHeader = "Server"
|
|
|
|
)
|
|
|
|
|
2024-07-14 13:47:48 -04:00
|
|
|
func (s *Server) setupRoutes() {
|
2024-08-10 10:42:22 -04:00
|
|
|
clientRoot, err := fs.Sub(client.Calls, "calls")
|
2024-08-08 22:01:03 -04:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
2024-07-14 13:47:48 -04:00
|
|
|
r := s.r
|
2024-11-10 10:28:04 -05:00
|
|
|
r.Use(middleware.WithValue(database.DBCtxKey, s.db))
|
|
|
|
r.Use(middleware.WithValue(talkgroups.StoreCtxKey, s.tgs))
|
2024-07-14 13:47:48 -04:00
|
|
|
|
2024-10-30 09:49:45 -04:00
|
|
|
s.installPprof()
|
|
|
|
|
2024-07-14 13:47:48 -04:00
|
|
|
r.Group(func(r chi.Router) {
|
2024-07-29 00:29:16 -04:00
|
|
|
// authenticated routes
|
2024-08-04 01:53:19 -04:00
|
|
|
r.Use(s.auth.VerifyMiddleware(), s.auth.AuthMiddleware())
|
2024-08-04 07:39:52 -04:00
|
|
|
s.nex.PrivateRoutes(r)
|
2024-08-10 18:21:13 -04:00
|
|
|
s.auth.PrivateRoutes(r)
|
2024-10-23 08:55:19 -04:00
|
|
|
s.alerter.PrivateRoutes(r)
|
2024-11-04 11:15:24 -05:00
|
|
|
r.Mount("/api", s.api.Subrouter())
|
2024-07-14 13:47:48 -04:00
|
|
|
})
|
|
|
|
|
2024-07-14 17:39:03 -04:00
|
|
|
r.Group(func(r chi.Router) {
|
2024-10-18 15:21:42 -04:00
|
|
|
s.rateLimit(r)
|
2024-07-14 17:39:03 -04:00
|
|
|
r.Use(render.SetContentType(render.ContentTypeJSON))
|
2024-07-14 13:47:48 -04:00
|
|
|
// public routes
|
2024-08-03 00:16:23 -04:00
|
|
|
s.auth.PublicRoutes(r)
|
|
|
|
s.sources.PublicRoutes(r)
|
2024-07-14 13:47:48 -04:00
|
|
|
})
|
|
|
|
|
|
|
|
r.Group(func(r chi.Router) {
|
2024-10-18 15:21:42 -04:00
|
|
|
s.rateLimit(r)
|
|
|
|
r.Use(s.auth.VerifyMiddleware())
|
2024-07-14 13:47:48 -04:00
|
|
|
|
|
|
|
// optional auth routes
|
|
|
|
|
2024-08-08 22:01:03 -04:00
|
|
|
s.clientRoute(r, clientRoot)
|
2024-07-14 13:47:48 -04:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2024-10-18 15:21:42 -04:00
|
|
|
func (s *Server) rateLimit(r chi.Router) {
|
|
|
|
if s.conf.RateLimit.Verify() {
|
|
|
|
r.Use(rateLimiter(&s.conf.RateLimit))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
func rateLimiter(cfg *config.RateLimit) func(http.Handler) http.Handler {
|
|
|
|
return httprate.LimitByRealIP(cfg.Requests, cfg.Over)
|
2024-07-14 17:39:03 -04:00
|
|
|
}
|
|
|
|
|
2024-08-08 22:01:03 -04:00
|
|
|
func (s *Server) clientRoute(r chi.Router, clientRoot fs.FS) {
|
|
|
|
r.Get("/*", func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
rctx := chi.RouteContext(r.Context())
|
|
|
|
pathPrefix := strings.TrimSuffix(rctx.RoutePattern(), "/*")
|
|
|
|
fs := http.StripPrefix(pathPrefix, http.FileServer(http.FS(clientRoot)))
|
|
|
|
fs.ServeHTTP(w, r)
|
|
|
|
})
|
2024-07-14 13:47:48 -04:00
|
|
|
}
|
2024-10-22 10:21:11 -04:00
|
|
|
|
|
|
|
func ServerHeaderAdd(next http.Handler) http.Handler {
|
2024-11-03 07:19:03 -05:00
|
|
|
serverString := version.HttpString(version.Name)
|
2024-10-22 10:21:11 -04:00
|
|
|
hfn := func(w http.ResponseWriter, r *http.Request) {
|
2024-10-31 16:50:08 -04:00
|
|
|
w.Header().Set(serverHeader, serverString)
|
2024-10-22 10:21:11 -04:00
|
|
|
next.ServeHTTP(w, r)
|
|
|
|
}
|
|
|
|
return http.HandlerFunc(hfn)
|
|
|
|
}
|