From 55d28230ccfa0a1adec8fc9b0290843eebcd9074 Mon Sep 17 00:00:00 2001 From: Locria Cyber <74560659+iacore@users.noreply.github.com> Date: Fri, 20 Oct 2023 08:25:18 +0000 Subject: [PATCH] Add support for plain text and curl --- go.mod | 2 ++ go.sum | 4 ++++ main.go | 47 +++++++++++++++++++++++++++++++++++++++-------- readme.md | 1 + 4 files changed, 46 insertions(+), 8 deletions(-) diff --git a/go.mod b/go.mod index 6dd2fdf..4ea7200 100644 --- a/go.mod +++ b/go.mod @@ -11,6 +11,7 @@ require ( ) require ( + github.com/elnormous/contenttype v1.0.4 github.com/google/uuid v1.3.1 // indirect github.com/mattn/go-colorable v0.1.12 // indirect github.com/mattn/go-isatty v0.0.14 // indirect @@ -19,6 +20,7 @@ require ( github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.0 // indirect github.com/tidwall/sjson v1.2.5 // indirect + github.com/timewasted/go-accept-headers v0.0.0-20130320203746-c78f304b1b09 go.mau.fi/util v0.1.0 // indirect golang.org/x/crypto v0.13.0 // indirect golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect diff --git a/go.sum b/go.sum index 8badff2..3947672 100644 --- a/go.sum +++ b/go.sum @@ -4,6 +4,8 @@ github.com/coreos/go-systemd/v22 v22.5.0/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/elnormous/contenttype v1.0.4 h1:FjmVNkvQOGqSX70yvocph7keC8DtmJaLzTTq6ZOQCI8= +github.com/elnormous/contenttype v1.0.4/go.mod h1:5KTOW8m1kdX1dLMiUJeN9szzR2xkngiv2K+RVZwWBbI= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -40,6 +42,8 @@ github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= +github.com/timewasted/go-accept-headers v0.0.0-20130320203746-c78f304b1b09 h1:QVxbx5l/0pzciWYOynixQMtUhPYC3YKD6EcUlOsgGqw= +github.com/timewasted/go-accept-headers v0.0.0-20130320203746-c78f304b1b09/go.mod h1:Uy/Rnv5WKuOO+PuDhuYLEpUiiKIZtss3z519uk67aF0= go.mau.fi/util v0.1.0 h1:BwIFWIOEeO7lsiI2eWKFkWTfc5yQmoe+0FYyOFVyaoE= go.mau.fi/util v0.1.0/go.mod h1:AxuJUMCxpzgJ5eV9JbPWKRH8aAJJidxetNdUj7qcb84= golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck= diff --git a/main.go b/main.go index 0899c36..6f8c4c9 100644 --- a/main.go +++ b/main.go @@ -17,6 +17,7 @@ import ( "git.exozy.me/exozyme/status/core" "git.exozy.me/exozyme/status/scanner" "github.com/cbroglie/mustache" + "github.com/timewasted/go-accept-headers" ) //go:embed all:public @@ -46,7 +47,7 @@ func parseAndRenderTemplate(templateName string, data interface{}) (string, erro return res, nil } -func rootPage(w http.ResponseWriter, r *http.Request) { +func index(w http.ResponseWriter, r *http.Request) { if r.Method != "GET" { return } @@ -77,6 +78,31 @@ func rootPage(w http.ResponseWriter, r *http.Request) { // don't uncomment this in production. verbose // log.Printf("%v", data) + ua := r.UserAgent() + + prefer_text := strings.HasPrefix(ua, "curl/") + + header_accept := accept.Parse(r.Header.Get("Accept")) + accept_text := header_accept.Accepts("text/plain") + accept_html := header_accept.Accepts("text/html") + + if (!accept_html || prefer_text) && accept_text { + indexForVT100(w, r, data) + } else if accept_html { + indexForBrowser(w, r, data) + } else { // when no valid content type is requested + // not to-spec. still sends plain text anyway + indexForVT100(w, r, data) + } +} + +func indexForVT100(w http.ResponseWriter, r *http.Request, data scanner.ServiceStatusBatch) { + w.Header().Add("Content-Type", "text/plain; charset=utf-8") + parsedTemplate := formatPlainText(data) + w.Write([]byte(parsedTemplate)) +} + +func indexForBrowser(w http.ResponseWriter, r *http.Request, data scanner.ServiceStatusBatch) { parsedTemplate, err := parseAndRenderTemplate("templates/index.html", data) if err != nil { http.Error(w, err.Error(), 500) @@ -113,7 +139,7 @@ func main() { log.Panic(err) } - http.HandleFunc("/", rootPage) + http.HandleFunc("/", index) // serve public folder from embedfs htmlContent, err := fs.Sub(fs.FS(staticAssets), "public") @@ -230,11 +256,8 @@ func routineCheck(timeout time.Duration, onlyShowDown bool) error { return nil } -func notify(updates []scanner.ServiceStatus) error { - if len(updates) == 0 { - return nil - } - messageBody := "" +func formatPlainText(updates []scanner.ServiceStatus) string { + result := "" for _, v := range updates { var upOrDown string if v.Ok { @@ -243,8 +266,16 @@ func notify(updates []scanner.ServiceStatus) error { upOrDown = "DOWN" } serviceType := fmt.Sprintf("[%s]", v.Type) - messageBody += fmt.Sprintf("%-4s | %-24s %-7s %s\n", upOrDown, v.Name, serviceType, v.Status) + result += fmt.Sprintf("%-4s | %-24s %-7s %s\n", upOrDown, v.Name, serviceType, v.Status) } + return result +} + +func notify(updates []scanner.ServiceStatus) error { + if len(updates) == 0 { + return nil + } + messageBody := formatPlainText(updates) _, err := client.SendNoticeHTML( "```\n"+messageBody+"```", "
"+strings.TrimRight(messageBody, "\n")+"
") diff --git a/readme.md b/readme.md index 678107a..c51594a 100644 --- a/readme.md +++ b/readme.md @@ -34,6 +34,7 @@ Services - [x] persist data on disk - [x] clean up old checkpoints - [x] Matrix notification +- [x] serves plain text to curl ## Environment Variables