Add page for individual service details
This commit is contained in:
@ -3,6 +3,7 @@ package controller
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
@ -53,12 +54,9 @@ func Handle() {
|
||||
// CreateRouter creates the router for the http server
|
||||
func CreateRouter(cfg *config.Config) *mux.Router {
|
||||
router := mux.NewRouter()
|
||||
statusesHandler := serviceStatusesHandler
|
||||
if cfg.Security != nil && cfg.Security.IsValid() {
|
||||
statusesHandler = security.Handler(serviceStatusesHandler, cfg.Security)
|
||||
}
|
||||
router.HandleFunc("/favicon.ico", favIconHandler).Methods("GET") // favicon needs to be always served from the root
|
||||
router.HandleFunc(cfg.Web.PrependWithContextRoot("/api/v1/statuses"), statusesHandler).Methods("GET")
|
||||
router.HandleFunc(cfg.Web.PrependWithContextRoot("/api/v1/statuses"), secureIfNecessary(cfg, serviceStatusesHandler)).Methods("GET")
|
||||
router.HandleFunc(cfg.Web.PrependWithContextRoot("/api/v1/statuses/{key}"), secureIfNecessary(cfg, GzipHandlerFunc(serviceStatusHandler))).Methods("GET")
|
||||
router.HandleFunc(cfg.Web.PrependWithContextRoot("/api/v1/badges/uptime/{duration}/{identifier}"), badgeHandler).Methods("GET")
|
||||
router.HandleFunc(cfg.Web.PrependWithContextRoot("/health"), healthHandler).Methods("GET")
|
||||
router.PathPrefix(cfg.Web.ContextRoot).Handler(GzipHandler(http.StripPrefix(cfg.Web.ContextRoot, http.FileServer(http.Dir("./static")))))
|
||||
@ -68,6 +66,16 @@ func CreateRouter(cfg *config.Config) *mux.Router {
|
||||
return router
|
||||
}
|
||||
|
||||
func secureIfNecessary(cfg *config.Config, handler http.HandlerFunc) http.HandlerFunc {
|
||||
if cfg.Security != nil && cfg.Security.IsValid() {
|
||||
return security.Handler(serviceStatusesHandler, cfg.Security)
|
||||
}
|
||||
return handler
|
||||
}
|
||||
|
||||
// serviceStatusesHandler handles requests to retrieve all service statuses
|
||||
// Due to the size of the response, this function leverages a cache.
|
||||
// Must not be wrapped by GzipHandler
|
||||
func serviceStatusesHandler(writer http.ResponseWriter, r *http.Request) {
|
||||
gzipped := strings.Contains(r.Header.Get("Accept-Encoding"), "gzip")
|
||||
var exists bool
|
||||
@ -85,7 +93,7 @@ func serviceStatusesHandler(writer http.ResponseWriter, r *http.Request) {
|
||||
gzipWriter := gzip.NewWriter(buffer)
|
||||
data, err = watchdog.GetServiceStatusesAsJSON()
|
||||
if err != nil {
|
||||
log.Printf("[main][serviceStatusesHandler] Unable to marshal object to JSON: %s", err.Error())
|
||||
log.Printf("[controller][serviceStatusesHandler] Unable to marshal object to JSON: %s", err.Error())
|
||||
writer.WriteHeader(http.StatusInternalServerError)
|
||||
_, _ = writer.Write([]byte("Unable to marshal object to JSON"))
|
||||
return
|
||||
@ -106,6 +114,28 @@ func serviceStatusesHandler(writer http.ResponseWriter, r *http.Request) {
|
||||
_, _ = writer.Write(data)
|
||||
}
|
||||
|
||||
// serviceStatusHandler retrieves a single ServiceStatus by group name and service name
|
||||
func serviceStatusHandler(writer http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
serviceStatus := watchdog.GetServiceStatusByKey(vars["key"])
|
||||
if serviceStatus == nil {
|
||||
log.Printf("[controller][serviceStatusHandler] Service with key=%s not found", vars["key"])
|
||||
writer.WriteHeader(http.StatusNotFound)
|
||||
_, _ = writer.Write([]byte("not found"))
|
||||
return
|
||||
}
|
||||
data, err := json.Marshal(serviceStatus)
|
||||
if err != nil {
|
||||
log.Printf("[controller][serviceStatusHandler] Unable to marshal object to JSON: %s", err.Error())
|
||||
writer.WriteHeader(http.StatusInternalServerError)
|
||||
_, _ = writer.Write([]byte("Unable to marshal object to JSON"))
|
||||
return
|
||||
}
|
||||
writer.Header().Add("Content-Type", "application/json")
|
||||
writer.WriteHeader(http.StatusOK)
|
||||
_, _ = writer.Write(data)
|
||||
}
|
||||
|
||||
func healthHandler(writer http.ResponseWriter, _ *http.Request) {
|
||||
writer.Header().Add("Content-Type", "application/json")
|
||||
writer.WriteHeader(http.StatusOK)
|
||||
|
@ -32,10 +32,18 @@ func (w *gzipResponseWriter) Write(b []byte) (int, error) {
|
||||
return w.Writer.Write(b)
|
||||
}
|
||||
|
||||
// GzipHandler compresses the response of a given handler if the request's headers specify that the client
|
||||
// GzipHandler compresses the response of a given http.Handler if the request's headers specify that the client
|
||||
// supports gzip encoding
|
||||
func GzipHandler(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(writer http.ResponseWriter, r *http.Request) {
|
||||
return GzipHandlerFunc(func(writer http.ResponseWriter, r *http.Request) {
|
||||
next.ServeHTTP(writer, r)
|
||||
})
|
||||
}
|
||||
|
||||
// GzipHandlerFunc compresses the response of a given http.HandlerFunc if the request's headers specify that the client
|
||||
// supports gzip encoding
|
||||
func GzipHandlerFunc(next http.HandlerFunc) http.HandlerFunc {
|
||||
return func(writer http.ResponseWriter, r *http.Request) {
|
||||
// If the request doesn't specify that it supports gzip, then don't compress it
|
||||
if !strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") {
|
||||
next.ServeHTTP(writer, r)
|
||||
@ -47,5 +55,5 @@ func GzipHandler(next http.Handler) http.Handler {
|
||||
gz.Reset(writer)
|
||||
defer gz.Close()
|
||||
next.ServeHTTP(&gzipResponseWriter{ResponseWriter: writer, Writer: gz}, r)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user