All checks were successful
check / check (push) Successful in 1m2s
Migrate all import paths from github.com/go-chi/chi to github.com/go-chi/chi/v5 and github.com/go-chi/chi/middleware to github.com/go-chi/chi/v5/middleware. This resolves GO-2026-4316 (open redirect vulnerability in RedirectSlashes middleware) by moving to the maintained v5 module path. Files changed: - go.mod: chi v1.5.5 → chi/v5 v5.2.1 - internal/server/server.go: updated import - internal/server/routes.go: updated imports - internal/middleware/middleware.go: updated import - internal/handlers/api.go: updated import - README.md: updated Required Libraries table
170 lines
3.1 KiB
Go
170 lines
3.1 KiB
Go
package server
|
|
|
|
import (
|
|
"io/fs"
|
|
"net/http"
|
|
"time"
|
|
|
|
"git.eeqj.de/sneak/neoirc/web"
|
|
|
|
sentryhttp "github.com/getsentry/sentry-go/http"
|
|
"github.com/go-chi/chi/v5"
|
|
"github.com/go-chi/chi/v5/middleware"
|
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
|
"github.com/spf13/viper"
|
|
)
|
|
|
|
const routeTimeout = 60 * time.Second
|
|
|
|
// SetupRoutes configures the HTTP routes and middleware.
|
|
func (srv *Server) SetupRoutes() {
|
|
srv.router = chi.NewRouter()
|
|
|
|
srv.router.Use(middleware.Recoverer)
|
|
srv.router.Use(middleware.RequestID)
|
|
srv.router.Use(srv.mw.Logging())
|
|
|
|
if viper.GetString("METRICS_USERNAME") != "" {
|
|
srv.router.Use(srv.mw.Metrics())
|
|
}
|
|
|
|
srv.router.Use(srv.mw.CORS())
|
|
srv.router.Use(srv.mw.CSP())
|
|
srv.router.Use(middleware.Timeout(routeTimeout))
|
|
|
|
if srv.sentryEnabled {
|
|
sentryHandler := sentryhttp.New(
|
|
sentryhttp.Options{ //nolint:exhaustruct // optional fields
|
|
Repanic: true,
|
|
},
|
|
)
|
|
|
|
srv.router.Use(sentryHandler.Handle)
|
|
}
|
|
|
|
// Health check.
|
|
srv.router.Get(
|
|
"/.well-known/healthcheck.json",
|
|
srv.handlers.HandleHealthCheck(),
|
|
)
|
|
|
|
// Protected metrics endpoint.
|
|
if viper.GetString("METRICS_USERNAME") != "" {
|
|
srv.router.Group(func(router chi.Router) {
|
|
router.Use(srv.mw.MetricsAuth())
|
|
router.Get("/metrics",
|
|
http.HandlerFunc(
|
|
promhttp.Handler().ServeHTTP,
|
|
))
|
|
})
|
|
}
|
|
|
|
// API v1.
|
|
srv.router.Route("/api/v1", srv.setupAPIv1)
|
|
|
|
// Serve embedded SPA.
|
|
srv.setupSPA()
|
|
}
|
|
|
|
func (srv *Server) setupAPIv1(router chi.Router) {
|
|
router.Get(
|
|
"/server",
|
|
srv.handlers.HandleServerInfo(),
|
|
)
|
|
router.Post(
|
|
"/session",
|
|
srv.handlers.HandleCreateSession(),
|
|
)
|
|
router.Post(
|
|
"/register",
|
|
srv.handlers.HandleRegister(),
|
|
)
|
|
router.Post(
|
|
"/login",
|
|
srv.handlers.HandleLogin(),
|
|
)
|
|
router.Get(
|
|
"/state",
|
|
srv.handlers.HandleState(),
|
|
)
|
|
router.Post(
|
|
"/logout",
|
|
srv.handlers.HandleLogout(),
|
|
)
|
|
router.Get(
|
|
"/users/me",
|
|
srv.handlers.HandleUsersMe(),
|
|
)
|
|
router.Get(
|
|
"/messages",
|
|
srv.handlers.HandleGetMessages(),
|
|
)
|
|
router.Post(
|
|
"/messages",
|
|
srv.handlers.HandleSendCommand(),
|
|
)
|
|
router.Get(
|
|
"/history",
|
|
srv.handlers.HandleGetHistory(),
|
|
)
|
|
router.Get(
|
|
"/channels",
|
|
srv.handlers.HandleListAllChannels(),
|
|
)
|
|
router.Get(
|
|
"/channels/{channel}/members",
|
|
srv.handlers.HandleChannelMembers(),
|
|
)
|
|
}
|
|
|
|
func (srv *Server) setupSPA() {
|
|
distFS, err := fs.Sub(web.Dist, "dist")
|
|
if err != nil {
|
|
srv.log.Error(
|
|
"failed to get web dist filesystem",
|
|
"error", err,
|
|
)
|
|
|
|
return
|
|
}
|
|
|
|
fileServer := http.FileServer(http.FS(distFS))
|
|
|
|
srv.router.Get("/*", func(
|
|
writer http.ResponseWriter,
|
|
request *http.Request,
|
|
) {
|
|
readFS, ok := distFS.(fs.ReadFileFS)
|
|
if !ok {
|
|
fileServer.ServeHTTP(writer, request)
|
|
|
|
return
|
|
}
|
|
|
|
fileData, readErr := readFS.ReadFile(
|
|
request.URL.Path[1:],
|
|
)
|
|
if readErr != nil || len(fileData) == 0 {
|
|
indexHTML, indexErr := readFS.ReadFile(
|
|
"index.html",
|
|
)
|
|
if indexErr != nil {
|
|
http.NotFound(writer, request)
|
|
|
|
return
|
|
}
|
|
|
|
writer.Header().Set(
|
|
"Content-Type",
|
|
"text/html; charset=utf-8",
|
|
)
|
|
writer.WriteHeader(http.StatusOK)
|
|
_, _ = writer.Write(indexHTML)
|
|
|
|
return
|
|
}
|
|
|
|
fileServer.ServeHTTP(writer, request)
|
|
})
|
|
}
|