From 0e270081febd8bfb079e95c00084a18b694b3ae1 Mon Sep 17 00:00:00 2001 From: Alexey Khit Date: Sun, 28 May 2023 06:37:59 +0300 Subject: [PATCH] Add content-type to API responses --- internal/api/api.go | 37 +++++++++++++++++++++++++++++-------- internal/api/config.go | 4 +--- internal/debug/stack.go | 5 ++--- internal/hass/api.go | 4 ++-- internal/homekit/api.go | 8 ++++---- internal/streams/init.go | 9 +++------ internal/webtorrent/init.go | 2 +- 7 files changed, 42 insertions(+), 27 deletions(-) diff --git a/internal/api/api.go b/internal/api/api.go index 051d2978..ff8df898 100644 --- a/internal/api/api.go +++ b/internal/api/api.go @@ -88,6 +88,30 @@ func HandleFunc(pattern string, handler http.HandlerFunc) { http.HandleFunc(pattern, handler) } +// ResponseJSON important always add Content-Type +// so go won't need to call http.DetectContentType +func ResponseJSON(w http.ResponseWriter, v any) { + w.Header().Set("Content-Type", "application/json") + _ = json.NewEncoder(w).Encode(v) +} + +func ResponsePrettyJSON(w http.ResponseWriter, v any) { + w.Header().Set("Content-Type", "application/json") + enc := json.NewEncoder(w) + enc.SetIndent("", " ") + _ = enc.Encode(v) +} + +func ResponseRawJSON(w http.ResponseWriter, s string) { + w.Header().Set("Content-Type", "application/json") + _, _ = w.Write([]byte(s)) +} + +func ResponseText(w http.ResponseWriter, b []byte) { + w.Header().Set("Content-Type", "text/plain") + _, _ = w.Write(b) +} + const StreamNotFound = "stream not found" var basePath string @@ -131,9 +155,7 @@ func apiHandler(w http.ResponseWriter, r *http.Request) { app.Info["host"] = r.Host mu.Unlock() - if err := json.NewEncoder(w).Encode(app.Info); err != nil { - log.Warn().Err(err).Caller().Send() - } + ResponseJSON(w, app.Info) } func exitHandler(w http.ResponseWriter, r *http.Request) { @@ -158,11 +180,10 @@ func ResponseStreams(w http.ResponseWriter, streams []Stream) { return } - var response struct { + var response = struct { Streams []Stream `json:"streams"` + }{ + Streams: streams, } - response.Streams = streams - if err := json.NewEncoder(w).Encode(response); err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - } + ResponseJSON(w, response) } diff --git a/internal/api/config.go b/internal/api/config.go index d817b689..6221d62b 100644 --- a/internal/api/config.go +++ b/internal/api/config.go @@ -21,9 +21,7 @@ func configHandler(w http.ResponseWriter, r *http.Request) { http.Error(w, "", http.StatusNotFound) return } - if _, err = w.Write(data); err != nil { - log.Warn().Err(err).Caller().Send() - } + ResponseText(w, data) case "POST", "PATCH": data, err := io.ReadAll(r.Body) diff --git a/internal/debug/stack.go b/internal/debug/stack.go index 5d23cb5b..b88d9540 100644 --- a/internal/debug/stack.go +++ b/internal/debug/stack.go @@ -3,6 +3,7 @@ package debug import ( "bytes" "fmt" + "github.com/AlexxIT/go2rtc/internal/api" "net/http" "runtime" ) @@ -51,7 +52,5 @@ func stackHandler(w http.ResponseWriter, r *http.Request) { "Total: %d, Skipped: %d", runtime.NumGoroutine(), skipped), ) - if _, err := w.Write(buf[:i]); err != nil { - panic(err) - } + api.ResponseText(w, buf[:i]) } diff --git a/internal/hass/api.go b/internal/hass/api.go index 8824d47c..d12d2fae 100644 --- a/internal/hass/api.go +++ b/internal/hass/api.go @@ -3,6 +3,7 @@ package hass import ( "encoding/base64" "encoding/json" + "github.com/AlexxIT/go2rtc/internal/api" "github.com/AlexxIT/go2rtc/internal/streams" "github.com/AlexxIT/go2rtc/internal/webrtc" "net" @@ -11,8 +12,7 @@ import ( ) func apiOK(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/json") - _, _ = w.Write([]byte(`{"status":1,"payload":{}}`)) + api.ResponseRawJSON(w, `{"status":1,"payload":{}}`) } func apiStream(w http.ResponseWriter, r *http.Request) { diff --git a/internal/homekit/api.go b/internal/homekit/api.go index 39fdaa43..7a83ee2f 100644 --- a/internal/homekit/api.go +++ b/internal/homekit/api.go @@ -1,8 +1,8 @@ package homekit import ( - "encoding/json" "fmt" + "github.com/AlexxIT/go2rtc/internal/api" "github.com/AlexxIT/go2rtc/internal/app/store" "github.com/AlexxIT/go2rtc/internal/streams" "github.com/AlexxIT/go2rtc/pkg/hap" @@ -54,7 +54,7 @@ func apiHandler(w http.ResponseWriter, r *http.Request) { items = append(items, device) } - _ = json.NewEncoder(w).Encode(items) + api.ResponseJSON(w, items) case "POST": // TODO: post params... @@ -64,14 +64,14 @@ func apiHandler(w http.ResponseWriter, r *http.Request) { name := r.URL.Query().Get("name") if err := hkPair(id, pin, name); err != nil { log.Error().Err(err).Caller().Send() - _, err = w.Write([]byte(err.Error())) + http.Error(w, err.Error(), http.StatusInternalServerError) } case "DELETE": src := r.URL.Query().Get("src") if err := hkDelete(src); err != nil { log.Error().Err(err).Caller().Send() - _, err = w.Write([]byte(err.Error())) + http.Error(w, err.Error(), http.StatusInternalServerError) } } } diff --git a/internal/streams/init.go b/internal/streams/init.go index 697ce9d2..1de5ce8a 100644 --- a/internal/streams/init.go +++ b/internal/streams/init.go @@ -1,7 +1,6 @@ package streams import ( - "encoding/json" "github.com/AlexxIT/go2rtc/internal/api" "github.com/AlexxIT/go2rtc/internal/app" "github.com/AlexxIT/go2rtc/internal/app/store" @@ -81,16 +80,14 @@ func streamsHandler(w http.ResponseWriter, r *http.Request) { // without source - return all streams list if src == "" && r.Method != "POST" { - _ = json.NewEncoder(w).Encode(streams) + api.ResponseJSON(w, streams) return } // Not sure about all this API. Should be rewrited... switch r.Method { case "GET": - e := json.NewEncoder(w) - e.SetIndent("", " ") - _ = e.Encode(streams[src]) + api.ResponsePrettyJSON(w, streams[src]) case "PUT": name := query.Get("name") @@ -121,7 +118,7 @@ func streamsHandler(w http.ResponseWriter, r *http.Request) { if err := stream.Play(src); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) } else { - _ = json.NewEncoder(w).Encode(stream) + api.ResponseJSON(w, stream) } } else { http.Error(w, "", http.StatusNotFound) diff --git a/internal/webtorrent/init.go b/internal/webtorrent/init.go index ede46e0e..b07ccdaf 100644 --- a/internal/webtorrent/init.go +++ b/internal/webtorrent/init.go @@ -141,7 +141,7 @@ func apiHandle(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusCreated) data := fmt.Sprintf(`{"share":%q,"pwd":%q}`, share, pwd) - _, _ = w.Write([]byte(data)) + api.ResponseRawJSON(w, data) case "DELETE": if ok {