implement frontend routing

This commit is contained in:
Lukas Schulte Pelkum 2023-06-08 19:17:34 +02:00
parent 941da057ae
commit a53bd39dbd
No known key found for this signature in database
GPG Key ID: AB3985CECFAFC962
19 changed files with 82 additions and 1 deletions

View File

@ -22,6 +22,6 @@ RUN go build \
FROM gcr.io/distroless/base:latest
WORKDIR /root
COPY --from=build /app/pasty .
COPY web ./web/
COPY internal/web/web ./web/
EXPOSE 8080
CMD ["./pasty"]

View File

@ -0,0 +1,77 @@
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(writer, err)
return
}
defer func() {
_ = file.Close()
}()
fileInfo, err := file.Stat()
if err != nil {
writeErr(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(writer, err)
return
}
writer.Header().Set("Content-Type", mime.TypeByExtension(fileInfo.Name()))
writer.Header().Set("Content-Length", strconv.Itoa(len(content)))
_, _ = writer.Write(content)
}
}
func serveIndexFile(writer http.ResponseWriter, _ *http.Request) {
indexFile, err := frontend.ReadFile("frontend/index.html")
if err != nil {
writeErr(writer, err)
return
}
writer.Header().Set("Content-Type", "text/html")
writer.Header().Set("Content-Length", strconv.Itoa(len(indexFile)))
_, _ = writer.Write(indexFile)
}

View File

@ -39,7 +39,11 @@ type Server struct {
func (server *Server) Start() error {
router := chi.NewRouter()
// Serve the web frontend
router.Get("/*", frontendHandler(router.NotFoundHandler()))
// Register the paste API endpoints
router.Get("/api/*", router.NotFoundHandler())
router.With(server.v2MiddlewareInjectPaste).Get("/api/v2/pastes/{paste_id}", server.v2EndpointGetPaste)
router.Post("/api/v2/pastes", server.v2EndpointCreatePaste)
router.With(server.v2MiddlewareInjectPaste, server.v2MiddlewareAuthorize).Patch("/api/v2/pastes/{paste_id}", server.v2EndpointModifyPaste)