From 60cb7a55c6dfd7b5594efe8c04e600bc5e3191f6 Mon Sep 17 00:00:00 2001 From: Blallo Date: Tue, 14 Feb 2023 00:17:40 +0100 Subject: [PATCH] Add http endpoint --- cmd/broadcast/http_handler.go | 125 ++++++++++++++++++++++++++++++++++ cmd/broadcast/main.go | 47 ++++++++++--- go.mod | 8 ++- go.sum | 2 + 4 files changed, 170 insertions(+), 12 deletions(-) create mode 100644 cmd/broadcast/http_handler.go diff --git a/cmd/broadcast/http_handler.go b/cmd/broadcast/http_handler.go new file mode 100644 index 0000000..d2eaff4 --- /dev/null +++ b/cmd/broadcast/http_handler.go @@ -0,0 +1,125 @@ +package main + +import ( + "encoding/json" + "net/http" + + "git.abbiamoundominio.org/blallo/broadcast" + "git.sr.ht/~blallo/logz/interface" +) + +type radioHandler struct { + radio *broadcast.Radio + logger logz.Logger +} + +func (h *radioHandler) Start(w http.ResponseWriter, r *http.Request) { + h.logger.Debug(map[string]any{ + "msg": "Received Start request", + "context": "http", + }) + + resp, err := withTimeout(r.Context(), h.radio.Start()) + if err != nil { + h.logger.Warn(map[string]any{ + "msg": "Failed to start", + "context": "http", + "err": err.Error(), + }) + h.failure(w, http.StatusInternalServerError, map[string]any{ + "status": "failed", + "err": err.Error(), + }) + return + } + if resp != nil { + h.logger.Warn(map[string]any{ + "msg": "Could not start", + "context": "http", + "err": resp.(error).Error(), + }) + h.failure(w, http.StatusInternalServerError, map[string]any{ + "status": "failed", + "err": resp.(error).Error(), + }) + return + } + + h.success(w, map[string]any{ + "status": "success", + }) +} + +func (h *radioHandler) Stop(w http.ResponseWriter, r *http.Request) { + h.logger.Debug(map[string]any{ + "msg": "Received Stop request", + "context": "http", + }) + + resp, err := withTimeout(r.Context(), h.radio.Stop()) + if err != nil { + h.logger.Warn(map[string]any{ + "msg": "Failed to stop", + "context": "http", + "err": err.Error(), + }) + h.failure(w, http.StatusInternalServerError, map[string]any{ + "status": "failed", + "err": err.Error(), + }) + return + } + if resp != nil { + h.logger.Warn(map[string]any{ + "msg": "Could not stop", + "context": "http", + "err": resp.(error).Error(), + }) + h.failure(w, http.StatusInternalServerError, map[string]any{ + "status": "failed", + "err": resp.(error).Error(), + }) + return + } + + h.success(w, map[string]any{ + "status": "success", + }) +} + +func (h *radioHandler) Status(w http.ResponseWriter, r *http.Request) { + h.logger.Debug(map[string]any{ + "msg": "Received Status request", + "context": "http", + }) + + resp, err := withTimeout(r.Context(), h.radio.Status()) + if err != nil { + h.logger.Warn(map[string]any{ + "msg": "Failed to get status", + "context": "http", + "err": err.Error(), + }) + h.failure(w, http.StatusInternalServerError, map[string]any{ + "status": "failed", + "err": err.Error(), + }) + return + } + + h.success(w, map[string]any{ + "status": "success", + "lines": resp.([]string), + }) +} + +func (h *radioHandler) 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) { + 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 09f6bc4..a7df85d 100644 --- a/cmd/broadcast/main.go +++ b/cmd/broadcast/main.go @@ -3,11 +3,14 @@ package main import ( "context" "flag" + "net/http" "os" "os/signal" "syscall" "time" + "github.com/go-chi/chi/v5" + "git.abbiamoundominio.org/blallo/broadcast" "git.sr.ht/~blallo/logz/interface" "git.sr.ht/~blallo/logz/zlog" @@ -15,6 +18,7 @@ import ( var ( debug = flag.Bool("debug", false, "Enable debug logging") + addr = flag.String("addr", ":8080", "Addres to bind to, in the 'ipaddress:port' format") ) func main() { @@ -65,12 +69,14 @@ func main() { resp := <-radio.Start() if resp != nil { logger.Warn(map[string]any{ - "msg": "Failed to start", - "err": resp.(error).Error(), + "msg": "Failed to start", + "context": "os", + "err": resp.(error).Error(), }) } else { logger.Info(map[string]any{ - "msg": "Started", + "msg": "Started", + "context": "os", }) } } @@ -86,12 +92,14 @@ func main() { resp := <-radio.Stop() if resp != nil { logger.Warn(map[string]any{ - "msg": "Failed to stop", - "err": resp.(error).Error(), + "msg": "Failed to stop", + "context": "os", + "err": resp.(error).Error(), }) } else { logger.Info(map[string]any{ - "msg": "Stopped", + "msg": "Stopped", + "context": "os", }) } } @@ -108,6 +116,7 @@ func main() { for i, line := range resp.([]string) { logger.Info(map[string]any{ "msg": line, + "context": "os", "lineNum": i, }) } @@ -119,19 +128,23 @@ func main() { resp, err := withTimeout(ctx, radio.Start()) if err != nil { logger.Err(map[string]any{ - "msg": "Cannot start", - "err": err.Error(), + "msg": "Cannot start", + "context": "os", + "err": err.Error(), }) } else { if resp != nil { logger.Info(map[string]any{ - "msg": "Started", - "resp": resp.(error).Error(), + "msg": "Started", + "context": "os", + "resp": resp.(error).Error(), }) } } }() + go setupHandler(radio, logger, *addr) + if err := radio.Run(ctx); err != nil { logger.Err(map[string]any{ "msg": "Execution failed", @@ -152,3 +165,17 @@ func withTimeout[T any](ctx context.Context, respCh <-chan T) (zero T, err error return resp, nil } } + +func setupHandler(radio *broadcast.Radio, logger logz.Logger, addr string) error { + handler := &radioHandler{ + radio: radio, + logger: logger, + } + + router := chi.NewRouter() + router.Post("/start", handler.Start) + router.Post("/stop", handler.Stop) + router.Get("/status", handler.Status) + + return http.ListenAndServe(addr, router) +} diff --git a/go.mod b/go.mod index 1be4b66..f84a91c 100644 --- a/go.mod +++ b/go.mod @@ -2,13 +2,17 @@ module git.abbiamoundominio.org/blallo/broadcast go 1.20 +require ( + git.sr.ht/~blallo/logz/interface v0.0.0-20220324191132-95d94ae8e337 + github.com/cenkalti/backoff/v4 v4.2.0 +) + require ( git.sr.ht/~blallo/logz v0.0.0-20220324191132-95d94ae8e337 // indirect - git.sr.ht/~blallo/logz/interface v0.0.0-20220324191132-95d94ae8e337 // indirect git.sr.ht/~blallo/logz/testlogger v0.0.0-20230212191205-53d5ce2c0d54 // indirect git.sr.ht/~blallo/logz/zlog v0.0.0-20220324191132-95d94ae8e337 // indirect - github.com/cenkalti/backoff/v4 v4.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/go-chi/chi/v5 v5.0.8 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/rs/zerolog v1.26.1 // indirect github.com/stretchr/objx v0.5.0 // indirect diff --git a/go.sum b/go.sum index d88f008..1f4cde7 100644 --- a/go.sum +++ b/go.sum @@ -12,6 +12,8 @@ github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-chi/chi/v5 v5.0.8 h1:lD+NLqFcAi1ovnVZpsnObHGW4xb4J8lNmoYVfECH1Y0= +github.com/go-chi/chi/v5 v5.0.8/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=