From 8e656fdfd03e795a9d555738dc87652092c06fdd Mon Sep 17 00:00:00 2001 From: Stefan Prodan Date: Mon, 13 Aug 2018 14:54:46 +0300 Subject: [PATCH] Add UI/API response and forward OpenTracing headers to backend --- pkg/server/api.go | 46 +++++++++++++++++++++++++++++++ pkg/server/handlers.go | 61 ++++++++++++++++++++++++++++++++++-------- pkg/server/server.go | 3 +++ 3 files changed, 99 insertions(+), 11 deletions(-) create mode 100644 pkg/server/api.go diff --git a/pkg/server/api.go b/pkg/server/api.go new file mode 100644 index 0000000..dca178f --- /dev/null +++ b/pkg/server/api.go @@ -0,0 +1,46 @@ +package server + +import ( + "encoding/json" + "fmt" + "net/http" + "os" + + "github.com/stefanprodan/k8s-podinfo/pkg/version" +) + +func (s *Server) apiInfo(w http.ResponseWriter, r *http.Request) { + if r.URL.Path != "/api/info" { + w.WriteHeader(http.StatusNotFound) + return + } + + host, _ := os.Hostname() + data := struct { + Title string `json:"title"` + Message string `json:"message"` + Version string `json:"version"` + Revision string `json:"revision"` + Hostname string `json:"hostname"` + Color string `json:"color"` + }{ + Title: fmt.Sprintf("podinfo v%v", version.VERSION), + Message: fmt.Sprintf("Hello from podinfo v%v Git commit %v", version.VERSION, version.GITCOMMIT), + Version: version.VERSION, + Revision: version.GITCOMMIT, + Hostname: host, + Color: "green", + } + + d, err := json.Marshal(data) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(err.Error())) + return + } + + w.Header().Set("Content-Type", "application/json; charset=utf-8") + w.Header().Set("X-Content-Type-Options", "nosniff") + w.WriteHeader(http.StatusOK) + w.Write(d) +} diff --git a/pkg/server/handlers.go b/pkg/server/handlers.go index 4f4e094..c71363c 100644 --- a/pkg/server/handlers.go +++ b/pkg/server/handlers.go @@ -5,10 +5,12 @@ import ( "crypto/sha256" "encoding/hex" "encoding/json" + "html/template" "io/ioutil" "net/http" "os" "path" + "strings" "sync/atomic" "time" @@ -23,23 +25,43 @@ func (s *Server) index(w http.ResponseWriter, r *http.Request) { return } - resp, err := makeResponse() - if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(err.Error())) - } + log.Debug().Msgf("Request %s received from %s on %s", r.Header.Get("x-request-id"), r.RemoteAddr, r.RequestURI) - d, err := yaml.Marshal(resp) + resp, err := makeResponse() if err != nil { w.WriteHeader(http.StatusInternalServerError) w.Write([]byte(err.Error())) return } - w.Header().Set("Content-Type", "text/plain; charset=utf-8") - w.Header().Set("X-Content-Type-Options", "nosniff") - w.WriteHeader(http.StatusOK) - w.Write(d) + if strings.Contains(r.UserAgent(), "Mozilla") { + uiPath := os.Getenv("uiPath") + if len(uiPath) < 1 { + uiPath = "ui" + } + tmpl, err := template.New("vue.html").ParseFiles(path.Join(uiPath, "vue.html")) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(path.Join(uiPath, "vue.html") + err.Error())) + return + } + if err := tmpl.Execute(w, nil); err != nil { + http.Error(w, path.Join(uiPath, "vue.html")+err.Error(), http.StatusInternalServerError) + } + + } else { + d, err := yaml.Marshal(resp) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(err.Error())) + return + } + w.Header().Set("Content-Type", "text/plain; charset=utf-8") + w.Header().Set("X-Content-Type-Options", "nosniff") + w.WriteHeader(http.StatusOK) + w.Write(d) + } + } func (s *Server) echo(w http.ResponseWriter, r *http.Request) { @@ -88,7 +110,24 @@ func (s *Server) backend(w http.ResponseWriter, r *http.Request) { backendURL := os.Getenv("backend_url") if len(backendURL) > 0 { - resp, err := http.Post(backendURL, r.Header.Get("Content-type"), bytes.NewReader(body)) + + backendReq, err := http.NewRequest("POST", backendURL, bytes.NewReader(body)) + if err != nil { + log.Error().Msgf("Backend call failed: %v", err) + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(err.Error())) + return + } + + // forward tracing headers + if len(r.Header.Get("x-b3-traceid")) > 0 { + backendReq.Header.Set("x-request-id", r.Header.Get("x-request-id")) + backendReq.Header.Set("x-b3-spanid", r.Header.Get("x-b3-spanid")) + backendReq.Header.Set("x-b3-sampled", r.Header.Get("x-b3-sampled")) + backendReq.Header.Set("x-b3-traceid", r.Header.Get("x-b3-traceid")) + } + + resp, err := http.DefaultClient.Do(backendReq) if err != nil { log.Error().Msgf("Backend call failed: %v", err) w.WriteHeader(http.StatusInternalServerError) diff --git a/pkg/server/server.go b/pkg/server/server.go index 4b23250..a8230ba 100644 --- a/pkg/server/server.go +++ b/pkg/server/server.go @@ -57,6 +57,9 @@ func NewServer(options ...func(*Server)) *Server { s.mux.HandleFunc("/debug/pprof/symbol", pprof.Symbol) s.mux.HandleFunc("/debug/pprof/trace", pprof.Trace) + // API + s.mux.HandleFunc("/api/info", s.apiInfo) + return s }