Files
chat/internal/server/routes.go
clawbot 7047167dc8
Some checks failed
check / check (push) Failing after 1m39s
Add tests for register and login endpoints
2026-02-27 05:00:51 -08:00

161 lines
2.9 KiB
Go

package server
import (
"io/fs"
"net/http"
"time"
"git.eeqj.de/sneak/chat/web"
sentryhttp "github.com/getsentry/sentry-go/http"
"github.com/go-chi/chi"
"github.com/go-chi/chi/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(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.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)
})
}