pasty/internal/web/frontend_server.go

78 lines
1.6 KiB
Go

package web
import (
"embed"
"errors"
"io"
"io/fs"
"mime"
"net/http"
"path/filepath"
"strconv"
"strings"
)
//go:embed frontend/*
var frontend embed.FS
func frontendHandler(notFoundHandler http.HandlerFunc) http.HandlerFunc {
return func(writer http.ResponseWriter, request *http.Request) {
path := strings.TrimSpace(strings.TrimSuffix(request.URL.Path, "/"))
isFirstLevel := strings.Count(path, "/") <= 1
file, err := frontend.Open(filepath.Join("frontend", path))
if err != nil {
if errors.Is(err, fs.ErrNotExist) {
if isFirstLevel {
serveIndexFile(writer, request)
} else {
notFoundHandler(writer, request)
}
return
}
writeErr(request, writer, err)
return
}
defer func() {
_ = file.Close()
}()
fileInfo, err := file.Stat()
if err != nil {
writeErr(request, writer, err)
return
}
if fileInfo.IsDir() {
if isFirstLevel {
serveIndexFile(writer, request)
} else {
notFoundHandler(writer, request)
}
return
}
content, err := io.ReadAll(file)
if err != nil {
writeErr(request, writer, err)
return
}
writer.Header().Set("Content-Type", mime.TypeByExtension(filepath.Ext(fileInfo.Name())))
writer.Header().Set("Content-Length", strconv.Itoa(len(content)))
_, _ = writer.Write(content)
}
}
func serveIndexFile(writer http.ResponseWriter, request *http.Request) {
indexFile, err := frontend.ReadFile("frontend/index.html")
if err != nil {
writeErr(request, writer, err)
return
}
writer.Header().Set("Content-Type", "text/html")
writer.Header().Set("Content-Length", strconv.Itoa(len(indexFile)))
_, _ = writer.Write(indexFile)
}