well-known/server/server.go

93 lines
2.4 KiB
Go

package main
import (
"context"
"encoding/json"
"fmt"
"net/http"
"strings"
)
type WellKnownGetter interface {
GetData(ctx context.Context) (wkRegistry, error)
}
// GetHealthServer returns a simple health check handler.
func GetHealthServer() http.Handler {
mux := http.NewServeMux()
mux.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) {
endpoint := "/healthz"
requestCounter.WithLabelValues(endpoint).Inc()
w.WriteHeader(http.StatusOK)
w.Write([]byte("OK"))
})
return mux
}
// GetServer returns an HTTP handler that serves the well-known endpoints.
func GetServer(wks WellKnownGetter) http.Handler {
mux := http.NewServeMux()
mux.HandleFunc("/.well-known/", func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
reg, err := wks.GetData(ctx)
if err != nil {
http.Error(w, "Failed to fetch well-known records", http.StatusInternalServerError)
return
}
// Extract the ID from the URL path (strip the prefix)
id := strings.TrimPrefix(r.URL.Path, "/.well-known/")
if id == "" {
errorCounter.WithLabelValues(id).Inc()
http.Error(w, "Not found", http.StatusNotFound)
return
}
// First, try the exact match
val, ok := reg[id]
// If a match is found, check for the format annotation
if ok {
data := val.(map[string]interface{})["data"]
format := val.(map[string]interface{})["format"]
// If the format is locked to JSON, always return application/json
if format == "json" {
w.Header().Set("Content-Type", "application/json")
b, err := json.Marshal(data)
if err != nil {
http.Error(w, "Failed to encode JSON", http.StatusInternalServerError)
errorCounter.WithLabelValues(id).Inc()
return
}
w.Write(b)
requestCounter.WithLabelValues(id).Inc()
return
} else if format == "text" {
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
switch v := data.(type) {
case []string:
fmt.Fprint(w, strings.Join(v, "\n"))
requestCounter.WithLabelValues(id).Inc()
case string:
fmt.Fprint(w, v)
requestCounter.WithLabelValues(id).Inc()
default:
http.Error(w, "Unsupported data type for text/plain format", http.StatusInternalServerError)
errorCounter.WithLabelValues(id).Inc()
}
return
}
}
// If no match is found, return 404
errorCounter.WithLabelValues(id).Inc()
http.Error(w, "Not found", http.StatusNotFound)
})
return mux
}