Served the frontend's build output from server.frontend.dir
internal/frontend serves a Vite build from an fs.FS: hashed files under /assets/ are cached for a year, HTML and other files get no-cache, ETags are computed (and cached for a build that can't change), precompressed variants are served when the client accepts them, and a path without an extension falls back to index.html for client-side routes. Only GET and HEAD are allowed. server.WithFrontend serves it for every path outside /api and /ws, behind compression and the frontend group's hooks. job-search serve passes the directory in server.frontend.dir, checked for an index.html at start; empty means no frontend. Its option building moved into serverOptions, with the access log.
This commit is contained in:
1 parent
155b84caea
commit
9905ffb4cb
7 files changed
+430
-36
No files matched your search
@@ -6,6 +6,7 @@ import (
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"log"
|
||||
"log/slog"
|
||||
"net"
|
||||
@@ -38,6 +39,8 @@ const (
|
||||
GroupAPI
|
||||
// GroupWebSocket is /ws upgrade requests.
|
||||
GroupWebSocket
|
||||
// GroupFrontend is the static frontend (see WithFrontend).
|
||||
GroupFrontend
|
||||
)
|
||||
|
||||
// Middleware is the standard net/http middleware shape.
|
||||
@@ -83,6 +86,15 @@ func WithEvents(bus *events.Bus) Option {
|
||||
}
|
||||
}
|
||||
|
||||
// WithFrontend makes the server serve the frontend's build output, files,
|
||||
// for every path outside /api and /ws. Without it there is no frontend: such
|
||||
// paths get 404.
|
||||
func WithFrontend(files fs.FS) Option {
|
||||
return func(s *Server) {
|
||||
s.frontend = files
|
||||
}
|
||||
}
|
||||
|
||||
// WithMiddleware appends middleware to a group. This is the generic hook
|
||||
// (auth, metrics, tracing, custom header rules, ...).
|
||||
func WithMiddleware(group Group, middlewares ...Middleware) Option {
|
||||
@@ -120,8 +132,10 @@ type Server struct {
|
||||
log *slog.Logger
|
||||
// accessLog is where the access log is written, or nil for none.
|
||||
accessLog *log.Logger
|
||||
hooks map[Group][]Middleware
|
||||
limiters map[Group]limiterHook
|
||||
// frontend is the frontend's build output, or nil for none.
|
||||
frontend fs.FS
|
||||
hooks map[Group][]Middleware
|
||||
limiters map[Group]limiterHook
|
||||
|
||||
// trusted are the proxies whose forwarding headers are believed.
|
||||
trusted []netip.Prefix
|
||||
@@ -145,7 +159,7 @@ type Server struct {
|
||||
}
|
||||
|
||||
// New builds the server and its router. It logs to slog.Default() unless
|
||||
// given WithLogger.
|
||||
// given WithLogger, and serves no frontend unless given WithFrontend.
|
||||
func New(conf *config.JSCServer, opts ...Option) (*Server, error) {
|
||||
server := &Server{
|
||||
conf: conf,
|
||||
|
||||
Reference in new issue
Block a user