package main import ( "embed" "flag" "io/fs" "log/slog" "net/http" // sure, we could use fiber... but for now lets' stick with net/http to keep dependencies to a minimum "os" ) //go:embed static/* var staticFS embed.FS func loggingMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { slog.Info("request", "method", r.Method, "path", r.URL.Path) next.ServeHTTP(w, r) }) } func cacheMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Cache-Control", "public, max-age=3600") next.ServeHTTP(w, r) }) } func main() { addr := flag.String("addr", ":8080", "listen address") flag.Parse() logger := slog.New(slog.NewTextHandler(os.Stdout, nil)) slog.SetDefault(logger) /* strip "static/" prefix so files are served from root */ subFS, err := fs.Sub(staticFS, "static") if err != nil { slog.Error("failed to create sub filesystem", "error", err) os.Exit(1) } fileServer := http.FileServer(http.FS(subFS)) http.Handle("/", loggingMiddleware(cacheMiddleware(fileServer))) slog.Info("starting server", "addr", *addr) if err := http.ListenAndServe(*addr, nil); err != nil { slog.Error("server failed", "error", err) os.Exit(1) } }