80 lines
1.9 KiB
Go
80 lines
1.9 KiB
Go
|
// Package frontend contains compiled frontend assets and a registration
|
||
|
// for the HTTP listeners
|
||
|
package frontend
|
||
|
|
||
|
import (
|
||
|
"embed"
|
||
|
"errors"
|
||
|
"fmt"
|
||
|
"io"
|
||
|
"io/fs"
|
||
|
"mime"
|
||
|
"net/http"
|
||
|
"path"
|
||
|
|
||
|
"github.com/gorilla/mux"
|
||
|
"github.com/sirupsen/logrus"
|
||
|
)
|
||
|
|
||
|
type (
|
||
|
frontendServer struct {
|
||
|
router *mux.Router
|
||
|
log *logrus.Logger
|
||
|
}
|
||
|
)
|
||
|
|
||
|
//go:embed assets/*
|
||
|
var assets embed.FS
|
||
|
|
||
|
// RegisterHandler takes a Router and registers the frontend onto that
|
||
|
// router
|
||
|
func RegisterHandler(router *mux.Router, logger *logrus.Logger) {
|
||
|
srv := frontendServer{router, logger}
|
||
|
|
||
|
router.
|
||
|
PathPrefix("/assets").
|
||
|
Handler(http.StripPrefix("/assets", http.HandlerFunc(srv.handleAsset))).
|
||
|
Methods(http.MethodGet)
|
||
|
router.NotFoundHandler = http.HandlerFunc(srv.handleIndex)
|
||
|
}
|
||
|
|
||
|
func (f frontendServer) handleAsset(w http.ResponseWriter, r *http.Request) {
|
||
|
asset, err := assets.Open(path.Join("assets", r.URL.Path))
|
||
|
if err != nil {
|
||
|
if errors.Is(err, fs.ErrNotExist) {
|
||
|
http.Error(w, "that's not the file you're looking for", http.StatusNotFound)
|
||
|
return
|
||
|
}
|
||
|
http.Error(w, fmt.Sprintf("opening asset: %s", err), http.StatusInternalServerError)
|
||
|
return
|
||
|
}
|
||
|
defer func() {
|
||
|
if err := asset.Close(); err != nil {
|
||
|
f.log.WithError(err).Error("closing assets file (leaked fd)")
|
||
|
}
|
||
|
}()
|
||
|
|
||
|
w.Header().Set("Content-Type", mime.TypeByExtension(path.Ext(r.URL.Path)))
|
||
|
|
||
|
if _, err = io.Copy(w, asset); err != nil {
|
||
|
f.log.WithError(err).Debug("copying index to browser")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (f frontendServer) handleIndex(w http.ResponseWriter, _ *http.Request) {
|
||
|
index, err := assets.Open("assets/index.html")
|
||
|
if err != nil {
|
||
|
http.Error(w, fmt.Sprintf("opening index: %s", err), http.StatusInternalServerError)
|
||
|
return
|
||
|
}
|
||
|
defer func() {
|
||
|
if err := index.Close(); err != nil {
|
||
|
f.log.WithError(err).Error("closing assets file (leaked fd)")
|
||
|
}
|
||
|
}()
|
||
|
|
||
|
if _, err = io.Copy(w, index); err != nil {
|
||
|
f.log.WithError(err).Debug("copying index to browser")
|
||
|
}
|
||
|
}
|