package controller import ( "fmt" "net/http" "strings" "time" "github.com/TwinProduction/gatus/core" "github.com/TwinProduction/gatus/storage" "github.com/gorilla/mux" ) // badgeHandler handles the automatic generation of badge based on the group name and service name passed. // // Valid values for {duration}: 7d, 24h, 1h // Pattern for {identifier}: .svg func badgeHandler(writer http.ResponseWriter, request *http.Request) { variables := mux.Vars(request) duration := variables["duration"] if duration != "7d" && duration != "24h" && duration != "1h" { writer.WriteHeader(http.StatusBadRequest) _, _ = writer.Write([]byte("Durations supported: 7d, 24h, 1h")) return } identifier := variables["identifier"] key := strings.TrimSuffix(identifier, ".svg") serviceStatus := storage.Get().GetServiceStatusByKey(key) if serviceStatus == nil { writer.WriteHeader(http.StatusNotFound) _, _ = writer.Write([]byte("Requested service not found")) return } if serviceStatus.Uptime == nil { writer.WriteHeader(http.StatusInternalServerError) _, _ = writer.Write([]byte("Failed to compute uptime")) return } formattedDate := time.Now().Format(http.TimeFormat) writer.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate") writer.Header().Set("Date", formattedDate) writer.Header().Set("Expires", formattedDate) writer.Header().Set("Content-Type", "image/svg+xml") _, _ = writer.Write(generateSVG(duration, serviceStatus.Uptime)) } func generateSVG(duration string, uptime *core.Uptime) []byte { var labelWidth, valueWidth, valueWidthAdjustment int var color string var value float64 switch duration { case "7d": labelWidth = 65 value = uptime.LastSevenDays case "24h": labelWidth = 70 value = uptime.LastTwentyFourHours case "1h": labelWidth = 65 value = uptime.LastHour default: } if value >= 0.8 { color = "#40cc11" } else { color = "#c7130a" } sanitizedValue := strings.TrimRight(strings.TrimRight(fmt.Sprintf("%.2f", value*100), "0"), ".") + "%" if strings.Contains(sanitizedValue, ".") { valueWidthAdjustment = -10 } valueWidth = (len(sanitizedValue) * 11) + valueWidthAdjustment width := labelWidth + valueWidth labelX := labelWidth / 2 valueX := labelWidth + (valueWidth / 2) svg := []byte(fmt.Sprintf(` uptime %s uptime %s %s %s `, width, width, labelWidth, color, labelWidth, valueWidth, labelWidth, width, labelX, duration, labelX, duration, valueX, sanitizedValue, valueX, sanitizedValue)) return svg }