stillbox/pkg/server/routes.go

119 lines
2.7 KiB
Go
Raw Normal View History

2024-07-14 13:47:48 -04:00
package server
import (
2024-11-22 12:32:22 -05:00
"errors"
2024-08-08 22:01:03 -04:00
"io/fs"
2024-07-14 13:47:48 -04:00
"net/http"
2024-11-22 12:32:22 -05:00
"path"
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"
2024-07-14 13:47:48 -04:00
"github.com/go-chi/chi/v5"
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-11-22 12:32:22 -05:00
clientRoot, err := fs.Sub(client.Client, client.Prefix)
2024-08-08 22:01:03 -04:00
if err != nil {
panic(err)
}
2024-07-14 13:47:48 -04:00
r := s.r
2025-01-06 08:22:51 -05:00
r.Use(s.WithCtxStores())
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)
s.alerter.PrivateRoutes(r)
2024-11-10 14:44:52 -05:00
r.Mount("/api", s.rest.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.sources.PublicRoutes(r)
2024-07-14 13:47:48 -04:00
})
2025-01-06 08:22:51 -05:00
r.Group(func(r chi.Router) {
// auth/share routes get rate-limited heavily, but not using middleware
s.rateLimit(r)
2025-01-06 08:22:51 -05:00
r.Use(render.SetContentType(render.ContentTypeJSON))
s.auth.PublicRoutes(r)
2025-01-20 20:28:25 -05:00
r.Mount("/share", s.rest.ShareRouter())
2025-01-06 08:22:51 -05:00
})
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
})
}
2025-01-06 08:22:51 -05:00
// WithCtxStores is a middleware that installs all stores in the request context.
func (s *Server) WithCtxStores() func(next http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
fn := func(w http.ResponseWriter, r *http.Request) {
r = r.WithContext(s.fillCtx(r.Context()))
2025-01-06 08:22:51 -05:00
next.ServeHTTP(w, r)
}
return http.HandlerFunc(fn)
}
}
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))
}
}
2025-01-06 08:22:51 -05:00
2024-10-18 15:21:42 -04:00
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) {
2024-11-22 12:32:22 -05:00
hfs := http.FS(clientRoot)
var pe *fs.PathError
pc := path.Clean(r.URL.Path)
f, err := hfs.Open(pc)
if err != nil {
if errors.As(err, &pe) {
2024-11-22 14:10:27 -05:00
http.ServeFileFS(w, r, clientRoot, "/index.html")
2024-11-22 12:32:22 -05:00
return
}
} else {
f.Close()
}
2024-08-08 22:01:03 -04:00
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)
}