package host import ( "context" "encoding/json" "fmt" "net/http" "net/url" "git.wzray.com/homelab/hivemind/internal/config" "github.com/rs/zerolog/log" ) type TraefikListener interface { OnTraefikUpdate(traefikResponse) } type TraefikGateway struct { client *http.Client server *http.Server listener TraefikListener address url.URL domain string } func NewTraefikGateway(cfg config.HostConfig, listener TraefikListener) *TraefikGateway { mux := http.NewServeMux() gw := &TraefikGateway{ client: &http.Client{}, server: &http.Server{ Addr: cfg.ListenAddress, Handler: mux, }, listener: listener, address: url.URL{ Scheme: "http", Host: cfg.LocalAddress, }, domain: cfg.Domain, } mux.HandleFunc("/callback", gw.onCallback) return gw } func (g *TraefikGateway) Listen() error { return g.server.ListenAndServe() } func (g *TraefikGateway) Shutdown(ctx context.Context) error { return g.server.Shutdown(ctx) } func (g *TraefikGateway) GetRawData() (*traefikResponse, error) { var raw TraefikRawResponse url := g.address url.Path = "/api/rawdata" req := http.Request{ Method: http.MethodGet, URL: &url, } req.Host = g.domain r, err := g.client.Do(&req) if err != nil { return nil, fmt.Errorf("make request: %w", err) } defer r.Body.Close() if err := json.NewDecoder(r.Body).Decode(&raw); err != nil { return nil, fmt.Errorf("unmarshal body: %w", err) } out := parseTraefikResponse(raw) return &out, nil } func (g *TraefikGateway) onCallback(w http.ResponseWriter, req *http.Request) { var raw TraefikRawResponse if err := json.NewDecoder(req.Body).Decode(&raw); err != nil { w.WriteHeader(http.StatusInternalServerError) log.Err(err).Msg("unable to decode traefik callback data") return } resp := parseTraefikResponse(raw) if g.listener != nil { g.listener.OnTraefikUpdate(resp) } w.Write([]byte("OK")) }