web.go
web.go
"io"
"io/fs"
"log/slog"
+ "mime"
"net/http"
"os"
"path/filepath"
logger := web.Logger
file := r.PathValue("file")
+ logger.Info("serving file", "file", file, "fs", staticfs)
reader, err := staticfs.Open(file)
if err != nil {
logger.Error(err.Error())
http.Error(w, "file not found", 404)
return
}
- contentType := http.DetectContentType(contents)
+ contentType := mime.TypeByExtension(filepath.Ext(file))
+ if contentType == "" {
+ contentType = http.DetectContentType(contents)
+ }
w.Header().Add("Content-Type", contentType)
_, err = w.Write(contents)
}
}
-type StaticFs struct {
- Dir string
-}
+func getFileSystem(logger *slog.Logger, ffs embed.FS, datadir string, dirName string) (fs.FS, error) {
+ dir := filepath.Join(datadir, dirName)
+ _, err := os.Stat(dir)
+ if err == nil {
+ logger.Info("found folder in data_dir", "dir", dir)
+ return os.DirFS(dir), nil
+ }
-func (fs *StaticFs) Open(name string) (os.File, error) {
- fp, err := os.Open(filepath.Join(fs.Dir, name))
- return *fp, err
+ logger.Info("using embeded folder", "dir", dir)
+ fsys, err := fs.Sub(ffs, dirName)
+ if err != nil {
+ return nil, err
+ }
+
+ return fsys, nil
}
func StartWebServer(cfg *GitCfg) {
dbpath := filepath.Join(cfg.DataDir, "pr.db")
dbh, err := Open(dbpath, cfg.Logger)
if err != nil {
- panic(fmt.Sprintf("cannot find database file, check folder and perms: %s", dbpath))
+ panic(fmt.Sprintf("cannot find database file, check folder and perms: %s: %s", dbpath, err))
}
be := &Backend{
http.HandleFunc("GET /", ctxMdw(ctx, repoListHandler))
http.HandleFunc("GET /syntax.css", ctxMdw(ctx, chromaStyleHandler))
http.HandleFunc("GET /rss", ctxMdw(ctx, rssHandler))
- dir := filepath.Join(cfg.DataDir, "static")
- var filesys fs.FS = staticFS
- _, err = os.Stat(dir)
- if err == nil {
- cfg.Logger.Info("detected static folder, using instead of the default one")
- filesys = os.DirFS(dir)
+ filesys, err := getFileSystem(cfg.Logger, staticFS, cfg.DataDir, "static")
+ if err != nil {
+ panic(err)
}
- http.HandleFunc("GET /static/{file}", serveFile(filesys))
+ http.HandleFunc("GET /static/{file}", ctxMdw(ctx, serveFile(filesys)))
cfg.Logger.Info("starting web server", "addr", addr)
err = http.ListenAndServe(addr, nil)
web.go
web.go
"embed"
"fmt"
"html/template"
+ "io"
+ "io/fs"
"log/slog"
+ "mime"
"net/http"
+ "os"
"path/filepath"
"slices"
"strconv"
//go:embed tmpl/*
var tmplFS embed.FS
+//go:embed static/*
+var staticFS embed.FS
+
type WebCtx struct {
Pr *PrCmd
Backend *Backend
}
}
+func serveFile(staticfs fs.FS) func(w http.ResponseWriter, r *http.Request) {
+ return func(w http.ResponseWriter, r *http.Request) {
+ web, err := getWebCtx(r)
+ if err != nil {
+ w.WriteHeader(http.StatusUnprocessableEntity)
+ return
+ }
+ logger := web.Logger
+
+ file := r.PathValue("file")
+ logger.Info("serving file", "file", file, "fs", staticfs)
+ reader, err := staticfs.Open(file)
+ if err != nil {
+ logger.Error(err.Error())
+ http.Error(w, "file not found", 404)
+ return
+ }
+ contents, err := io.ReadAll(reader)
+ if err != nil {
+ logger.Error(err.Error())
+ http.Error(w, "file not found", 404)
+ return
+ }
+ contentType := mime.TypeByExtension(filepath.Ext(file))
+ if contentType == "" {
+ contentType = http.DetectContentType(contents)
+ }
+ w.Header().Add("Content-Type", contentType)
+
+ _, err = w.Write(contents)
+ if err != nil {
+ logger.Error(err.Error())
+ http.Error(w, "server error", 500)
+ return
+ }
+ }
+}
+
+func getFileSystem(logger *slog.Logger, ffs embed.FS, datadir string, dirName string) (fs.FS, error) {
+ dir := filepath.Join(datadir, dirName)
+ _, err := os.Stat(dir)
+ if err == nil {
+ logger.Info("found folder in data_dir", "dir", dir)
+ return os.DirFS(dir), nil
+ }
+
+ logger.Info("using embeded folder", "dir", dir)
+ fsys, err := fs.Sub(ffs, dirName)
+ if err != nil {
+ return nil, err
+ }
+
+ return fsys, nil
+}
+
func StartWebServer(cfg *GitCfg) {
addr := fmt.Sprintf("%s:%s", cfg.Host, cfg.WebPort)
dbpath := filepath.Join(cfg.DataDir, "pr.db")
dbh, err := Open(dbpath, cfg.Logger)
if err != nil {
- panic(fmt.Sprintf("cannot find database file, check folder and perms: %s", dbpath))
+ panic(fmt.Sprintf("cannot find database file, check folder and perms: %s: %s", dbpath, err))
}
be := &Backend{
http.HandleFunc("GET /", ctxMdw(ctx, repoListHandler))
http.HandleFunc("GET /syntax.css", ctxMdw(ctx, chromaStyleHandler))
http.HandleFunc("GET /rss", ctxMdw(ctx, rssHandler))
+ filesys, err := getFileSystem(cfg.Logger, staticFS, cfg.DataDir, "static")
+ if err != nil {
+ panic(err)
+ }
+ http.HandleFunc("GET /static/{file}", ctxMdw(ctx, serveFile(filesys)))
cfg.Logger.Info("starting web server", "addr", addr)
err = http.ListenAndServe(addr, nil)