feat: embed static files into binary

This commit is contained in:
rramiachraf 2024-05-03 14:47:57 +01:00
parent 2c0f43b8f7
commit 6d6856700b
13 changed files with 74 additions and 39 deletions

View File

@ -20,7 +20,6 @@ LABEL org.opencontainers.image.licenses="MIT"
LABEL org.opencontainers.image.description="Private alternative front-end for Genius."
COPY --from=build /code/dumb .
COPY --from=build /code/static static
COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
EXPOSE 5555/tcp

View File

@ -22,7 +22,7 @@ func TestAlbum(t *testing.T) {
rr := httptest.NewRecorder()
l := utils.NewLogger(os.Stdout)
m := New(l)
m := New(l, &assets{})
m.ServeHTTP(rr, r)

View File

@ -20,7 +20,7 @@ func TestAnnotations(t *testing.T) {
rr := httptest.NewRecorder()
l := utils.NewLogger(os.Stdout)
m := New(l)
m := New(l, &assets{})
m.ServeHTTP(rr, r)

View File

@ -2,12 +2,7 @@ package handlers
import (
"context"
"io"
"mime"
"net/http"
"os"
"path"
"strings"
"github.com/a-h/templ"
gorillaHandlers "github.com/gorilla/handlers"
@ -16,7 +11,7 @@ import (
"github.com/rramiachraf/dumb/views"
)
func New(logger *utils.Logger) *mux.Router {
func New(logger *utils.Logger, staticFiles static) *mux.Router {
r := mux.NewRouter()
r.Use(utils.MustHeaders)
@ -31,25 +26,7 @@ func New(logger *utils.Logger) *mux.Router {
r.HandleFunc("/search", search(logger)).Methods("GET")
r.HandleFunc("/{annotation-id}/{artist-song}/{verse}/annotations", annotations(logger)).Methods("GET")
r.HandleFunc("/instances.json", instances(logger)).Methods("GET")
r.PathPrefix("/static/").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
url := strings.Replace(r.URL.Path, "/static", "static", 1)
f, err := os.Open(url)
if err != nil {
w.WriteHeader(http.StatusNotFound)
views.ErrorPage(http.StatusNotFound, "page not found")
return
}
defer f.Close()
mimeType := mime.TypeByExtension(path.Ext(r.URL.Path))
w.Header().Set("content-type", mimeType)
if _, err := io.Copy(w, f); err != nil {
logger.Error(err.Error())
}
})
r.PathPrefix("/static/").HandlerFunc(staticAssets(logger, staticFiles))
r.PathPrefix("/{annotation-id}/{artist-song}-lyrics").HandlerFunc(lyrics(logger)).Methods("GET")
r.PathPrefix("/{annotation-id}/{artist-song}").HandlerFunc(lyrics(logger)).Methods("GET")
r.PathPrefix("/{annotation-id}").HandlerFunc(lyrics(logger)).Methods("GET")

13
handlers/handler_test.go Normal file
View File

@ -0,0 +1,13 @@
package handlers
import (
"io/fs"
"os"
"path"
)
type assets struct{}
func (assets) Open(p string) (fs.File, error) {
return os.Open(path.Join("./", p))
}

View File

@ -19,7 +19,7 @@ func TestInstancesList(t *testing.T) {
rr := httptest.NewRecorder()
l := utils.NewLogger(os.Stdout)
m := New(l)
m := New(l, &assets{})
m.ServeHTTP(rr, r)
c := rr.Result().Header.Get("content-type")

View File

@ -33,7 +33,7 @@ func testLyrics(t *testing.T, url string) {
rr := httptest.NewRecorder()
l := utils.NewLogger(os.Stdout)
m := New(l)
m := New(l, &assets{})
m.ServeHTTP(rr, r)

View File

@ -53,7 +53,7 @@ func imageProxy(l *utils.Logger) http.HandlerFunc {
return
}
w.Header().Add("Content-type", mime.TypeByExtension("."+ext))
w.Header().Set("Content-type", mime.TypeByExtension("."+ext))
w.Header().Add("Cache-Control", "max-age=1296000")
if _, err = io.Copy(w, res.Body); err != nil {
l.Error("unable to write image, %s", err.Error())

View File

@ -20,7 +20,7 @@ func TestImageProxy(t *testing.T) {
rr := httptest.NewRecorder()
l := utils.NewLogger(os.Stdout)
m := New(l)
m := New(l, &assets{})
m.ServeHTTP(rr, r)

View File

@ -21,7 +21,7 @@ func TestSearch(t *testing.T) {
rr := httptest.NewRecorder()
l := utils.NewLogger(os.Stdout)
m := New(l)
m := New(l, &assets{})
m.ServeHTTP(rr, r)

38
handlers/static.go Normal file
View File

@ -0,0 +1,38 @@
package handlers
import (
"io"
"io/fs"
"mime"
"net/http"
"path"
"strings"
"github.com/rramiachraf/dumb/utils"
"github.com/rramiachraf/dumb/views"
)
type static interface {
Open(string) (fs.File, error)
}
func staticAssets(logger *utils.Logger, embededFiles static) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
url := strings.Replace(r.URL.Path, "/static", "static", 1)
f, err := embededFiles.Open(url)
if err != nil {
w.WriteHeader(http.StatusNotFound)
views.ErrorPage(http.StatusNotFound, "page not found")
return
}
defer f.Close()
mimeType := mime.TypeByExtension(path.Ext(r.URL.Path))
w.Header().Set("content-type", mimeType)
if _, err := io.Copy(w, f); err != nil {
logger.Error(err.Error())
}
}
}

14
main.go
View File

@ -1,6 +1,7 @@
package main
import (
"embed"
"fmt"
"net"
"net/http"
@ -13,11 +14,14 @@ import (
"github.com/rramiachraf/dumb/utils"
)
//go:embed static
var staticFiles embed.FS
func main() {
logger := utils.NewLogger(os.Stdout)
server := &http.Server{
Handler: handlers.New(logger),
Handler: handlers.New(logger, staticFiles),
WriteTimeout: 25 * time.Second,
ReadTimeout: 25 * time.Second,
}
@ -25,8 +29,7 @@ func main() {
PROXY_ENV := os.Getenv("PROXY")
if PROXY_ENV != "" {
if _, err := url.ParseRequestURI(PROXY_ENV); err != nil {
logger.Error("invalid proxy")
os.Exit(1)
logger.Fatal("invalid proxy")
}
logger.Info("using a custom proxy for requests")
@ -41,13 +44,12 @@ func main() {
l, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
if err != nil {
logger.Error(err.Error())
logger.Fatal(err.Error())
}
logger.Info("server is listening on port %d", port)
if err := server.Serve(l); err != nil {
logger.Error(err.Error())
os.Exit(1)
logger.Fatal(err.Error())
}
}

View File

@ -4,6 +4,7 @@ import (
"fmt"
"io"
"log/slog"
"os"
)
type Logger struct {
@ -24,3 +25,8 @@ func (l *Logger) Error(f string, args ...any) {
func (l *Logger) Info(f string, args ...any) {
l.slog.Info(fmt.Sprintf(f, args...))
}
func (l *Logger) Fatal(f string, args ...any) {
l.Error(f, args...)
os.Exit(1)
}