Bundle the frontend in the binary, add makefiles

This commit is contained in:
sfigato 2023-03-08 22:20:16 +01:00
parent f3154c4a6d
commit cc8996dc5f
Signed by: blallo
GPG Key ID: C530464EEDCF489A
7 changed files with 108 additions and 11 deletions

11
Makefile Normal file
View File

@ -0,0 +1,11 @@
VERSION ?= dev
GO ?= go
build: ./bin ui-build
$(GO) build -o ./bin ./cmd/broadcast
./bin:
mkdir -p bin
ui-%:
cd ui && make $*

View File

@ -0,0 +1,61 @@
package main
import (
"io/fs"
"net/http"
"strings"
"git.abbiamoundominio.org/blallo/broadcast/ui"
"git.sr.ht/~blallo/logz/interface"
)
type assetsHandler struct {
logger logz.Logger
fsHandler http.Handler
}
func (h *assetsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
h.logger.Info(map[string]any{
"msg": "Method not allowed",
"context": "assets",
})
failure(w, http.StatusMethodNotAllowed, map[string]any{
"status": "failed",
"err": "method not allowed",
})
}
h.logger.Debug(map[string]any{
"msg": "request path",
"url": r.URL,
})
switch {
case strings.HasSuffix(r.URL.Path, "html"), r.URL.Path == "/":
w.Header().Set("content-type", "text/html")
case strings.HasSuffix(r.URL.Path, "js"):
w.Header().Set("content-type", "text/javascript")
case strings.HasSuffix(r.URL.Path, "css"):
w.Header().Set("content-type", "text/css")
case strings.HasSuffix(r.URL.Path, "json"):
w.Header().Set("content-type", "application/json")
case strings.HasSuffix(r.URL.Path, "png"), strings.HasSuffix(r.URL.Path, "ico"):
w.Header().Set("content-type", "image/png")
}
h.fsHandler.ServeHTTP(w, r)
}
func newAssetsHandler(logger logz.Logger) (*assetsHandler, error) {
relAssetsFS, err := fs.Sub(ui.AssetsFS, "build")
if err != nil {
return nil, err
}
assets := http.FileServer(http.FS(relAssetsFS))
return &assetsHandler{
logger: logger,
fsHandler: assets,
}, nil
}

View File

@ -26,7 +26,7 @@ func (h *radioHandler) Start(w http.ResponseWriter, r *http.Request) {
"context": "http", "context": "http",
"err": err.Error(), "err": err.Error(),
}) })
h.failure(w, http.StatusInternalServerError, map[string]any{ failure(w, http.StatusInternalServerError, map[string]any{
"status": "failed", "status": "failed",
"err": err.Error(), "err": err.Error(),
}) })
@ -38,14 +38,14 @@ func (h *radioHandler) Start(w http.ResponseWriter, r *http.Request) {
"context": "http", "context": "http",
"err": resp.(error).Error(), "err": resp.(error).Error(),
}) })
h.failure(w, http.StatusInternalServerError, map[string]any{ failure(w, http.StatusInternalServerError, map[string]any{
"status": "failed", "status": "failed",
"err": resp.(error).Error(), "err": resp.(error).Error(),
}) })
return return
} }
h.success(w, map[string]any{ success(w, map[string]any{
"status": "success", "status": "success",
}) })
} }
@ -63,7 +63,7 @@ func (h *radioHandler) Stop(w http.ResponseWriter, r *http.Request) {
"context": "http", "context": "http",
"err": err.Error(), "err": err.Error(),
}) })
h.failure(w, http.StatusInternalServerError, map[string]any{ failure(w, http.StatusInternalServerError, map[string]any{
"status": "failed", "status": "failed",
"err": err.Error(), "err": err.Error(),
}) })
@ -75,14 +75,14 @@ func (h *radioHandler) Stop(w http.ResponseWriter, r *http.Request) {
"context": "http", "context": "http",
"err": resp.(error).Error(), "err": resp.(error).Error(),
}) })
h.failure(w, http.StatusInternalServerError, map[string]any{ failure(w, http.StatusInternalServerError, map[string]any{
"status": "failed", "status": "failed",
"err": resp.(error).Error(), "err": resp.(error).Error(),
}) })
return return
} }
h.success(w, map[string]any{ success(w, map[string]any{
"status": "success", "status": "success",
}) })
} }
@ -100,25 +100,25 @@ func (h *radioHandler) Status(w http.ResponseWriter, r *http.Request) {
"context": "http", "context": "http",
"err": err.Error(), "err": err.Error(),
}) })
h.failure(w, http.StatusInternalServerError, map[string]any{ failure(w, http.StatusInternalServerError, map[string]any{
"status": "failed", "status": "failed",
"err": err.Error(), "err": err.Error(),
}) })
return return
} }
h.success(w, map[string]any{ success(w, map[string]any{
"status": "success", "status": "success",
"lines": resp.([]string), "lines": resp.([]string),
}) })
} }
func (h *radioHandler) success(w http.ResponseWriter, payload map[string]any) { func success(w http.ResponseWriter, payload map[string]any) {
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
w.Header().Set("content-type", "application/json") w.Header().Set("content-type", "application/json")
json.NewEncoder(w).Encode(payload) json.NewEncoder(w).Encode(payload)
} }
func (h *radioHandler) failure(w http.ResponseWriter, status int, payload map[string]any) { func failure(w http.ResponseWriter, status int, payload map[string]any) {
w.WriteHeader(status) w.WriteHeader(status)
w.Header().Set("content-type", "application/json") w.Header().Set("content-type", "application/json")
json.NewEncoder(w).Encode(payload) json.NewEncoder(w).Encode(payload)

View File

@ -184,7 +184,16 @@ func setupHandler(radio *broadcast.Radio, logger logz.Logger, addr string) error
logger: logger, logger: logger,
} }
assetsHandler, err := newAssetsHandler(logger)
if err != nil {
return err
}
router := chi.NewRouter() router := chi.NewRouter()
router.Handle("/", assetsHandler)
router.Handle("/{elem}", assetsHandler)
router.Handle("/static/js/{elem}", assetsHandler)
router.Handle("/static/css/{elem}", assetsHandler)
router.Post("/start", handler.Start) router.Post("/start", handler.Start)
router.Post("/stop", handler.Stop) router.Post("/stop", handler.Stop)
router.Get("/status", handler.Status) router.Get("/status", handler.Status)

3
ui/Makefile Normal file
View File

@ -0,0 +1,3 @@
.PHONY: build
build:
yarn build

View File

@ -17,7 +17,10 @@ import {
import styles from './Radio.module.scss'; import styles from './Radio.module.scss';
const getWSUrl = async () => { const getWSUrl = async () => {
const wsUrl = process.env.WS_ADDR ? process.env.WS_ADDR : "ws://localhost/liveness"; const proto = (window.location.protocol === "http:") ? "ws" : "wss"
const wsUrl = process.env.WS_ADDR ?
process.env.WS_ADDR :
proto + "://" + window.location.host + window.location.pathname + "liveness";
console.log("WS ADDR: %s", wsUrl); console.log("WS ADDR: %s", wsUrl);
return wsUrl; return wsUrl;
}; };

10
ui/ui.go Normal file
View File

@ -0,0 +1,10 @@
package ui
import (
"embed"
)
var (
//go:embed build
AssetsFS embed.FS
)