From cc8996dc5f40874ff6f56d18eb281d62f9652312 Mon Sep 17 00:00:00 2001 From: Blallo Date: Wed, 8 Mar 2023 22:20:16 +0100 Subject: [PATCH] Bundle the frontend in the binary, add makefiles --- Makefile | 11 ++++++ cmd/broadcast/assets_handler.go | 61 +++++++++++++++++++++++++++++++++ cmd/broadcast/http_handler.go | 20 +++++------ cmd/broadcast/main.go | 9 +++++ ui/Makefile | 3 ++ ui/src/features/radio/Radio.tsx | 5 ++- ui/ui.go | 10 ++++++ 7 files changed, 108 insertions(+), 11 deletions(-) create mode 100644 Makefile create mode 100644 cmd/broadcast/assets_handler.go create mode 100644 ui/Makefile create mode 100644 ui/ui.go diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..3ff9018 --- /dev/null +++ b/Makefile @@ -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 $* diff --git a/cmd/broadcast/assets_handler.go b/cmd/broadcast/assets_handler.go new file mode 100644 index 0000000..858219e --- /dev/null +++ b/cmd/broadcast/assets_handler.go @@ -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 +} diff --git a/cmd/broadcast/http_handler.go b/cmd/broadcast/http_handler.go index d2eaff4..b02a471 100644 --- a/cmd/broadcast/http_handler.go +++ b/cmd/broadcast/http_handler.go @@ -26,7 +26,7 @@ func (h *radioHandler) Start(w http.ResponseWriter, r *http.Request) { "context": "http", "err": err.Error(), }) - h.failure(w, http.StatusInternalServerError, map[string]any{ + failure(w, http.StatusInternalServerError, map[string]any{ "status": "failed", "err": err.Error(), }) @@ -38,14 +38,14 @@ func (h *radioHandler) Start(w http.ResponseWriter, r *http.Request) { "context": "http", "err": resp.(error).Error(), }) - h.failure(w, http.StatusInternalServerError, map[string]any{ + failure(w, http.StatusInternalServerError, map[string]any{ "status": "failed", "err": resp.(error).Error(), }) return } - h.success(w, map[string]any{ + success(w, map[string]any{ "status": "success", }) } @@ -63,7 +63,7 @@ func (h *radioHandler) Stop(w http.ResponseWriter, r *http.Request) { "context": "http", "err": err.Error(), }) - h.failure(w, http.StatusInternalServerError, map[string]any{ + failure(w, http.StatusInternalServerError, map[string]any{ "status": "failed", "err": err.Error(), }) @@ -75,14 +75,14 @@ func (h *radioHandler) Stop(w http.ResponseWriter, r *http.Request) { "context": "http", "err": resp.(error).Error(), }) - h.failure(w, http.StatusInternalServerError, map[string]any{ + failure(w, http.StatusInternalServerError, map[string]any{ "status": "failed", "err": resp.(error).Error(), }) return } - h.success(w, map[string]any{ + success(w, map[string]any{ "status": "success", }) } @@ -100,25 +100,25 @@ func (h *radioHandler) Status(w http.ResponseWriter, r *http.Request) { "context": "http", "err": err.Error(), }) - h.failure(w, http.StatusInternalServerError, map[string]any{ + failure(w, http.StatusInternalServerError, map[string]any{ "status": "failed", "err": err.Error(), }) return } - h.success(w, map[string]any{ + success(w, map[string]any{ "status": "success", "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.Header().Set("content-type", "application/json") 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.Header().Set("content-type", "application/json") json.NewEncoder(w).Encode(payload) diff --git a/cmd/broadcast/main.go b/cmd/broadcast/main.go index 3862af1..f170b54 100644 --- a/cmd/broadcast/main.go +++ b/cmd/broadcast/main.go @@ -184,7 +184,16 @@ func setupHandler(radio *broadcast.Radio, logger logz.Logger, addr string) error logger: logger, } + assetsHandler, err := newAssetsHandler(logger) + if err != nil { + return err + } + 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("/stop", handler.Stop) router.Get("/status", handler.Status) diff --git a/ui/Makefile b/ui/Makefile new file mode 100644 index 0000000..38efc59 --- /dev/null +++ b/ui/Makefile @@ -0,0 +1,3 @@ +.PHONY: build +build: + yarn build diff --git a/ui/src/features/radio/Radio.tsx b/ui/src/features/radio/Radio.tsx index fee354a..a68a78e 100644 --- a/ui/src/features/radio/Radio.tsx +++ b/ui/src/features/radio/Radio.tsx @@ -17,7 +17,10 @@ import { import styles from './Radio.module.scss'; 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); return wsUrl; }; diff --git a/ui/ui.go b/ui/ui.go new file mode 100644 index 0000000..826730c --- /dev/null +++ b/ui/ui.go @@ -0,0 +1,10 @@ +package ui + +import ( + "embed" +) + +var ( + //go:embed build + AssetsFS embed.FS +)