package v1 import ( "encoding/json" "fmt" "net" "net/http" "strings" "github.com/gorilla/mux" "github.com/wild-cloud/wild-central/internal/domains" ) // DomainsListAll lists all registered domains. func (api *API) DomainsListAll(w http.ResponseWriter, r *http.Request) { doms, err := api.domains.List() if err != nil { respondError(w, http.StatusInternalServerError, fmt.Sprintf("Failed to list domains: %v", err)) return } if doms == nil { doms = []domains.Domain{} } respondJSON(w, http.StatusOK, map[string]any{ "domains": doms, }) } // DomainsGet retrieves a domain by its domain name. func (api *API) DomainsGet(w http.ResponseWriter, r *http.Request) { domain := mux.Vars(r)["domain"] dom, err := api.domains.Get(domain) if err != nil { respondError(w, http.StatusNotFound, fmt.Sprintf("Domain not found: %v", err)) return } respondJSON(w, http.StatusOK, dom) } // DomainsRegister creates or updates a domain registration. func (api *API) DomainsRegister(w http.ResponseWriter, r *http.Request) { var dom domains.Domain if err := json.NewDecoder(r.Body).Decode(&dom); err != nil { respondError(w, http.StatusBadRequest, fmt.Sprintf("Invalid request body: %v", err)) return } // Validate routes for i, r := range dom.Routes { for _, p := range r.Paths { if !strings.HasPrefix(p, "/") { respondError(w, http.StatusBadRequest, fmt.Sprintf("Route %d: path prefix must start with /: %q", i, p)) return } } for _, cidr := range r.IPAllow { if _, _, err := net.ParseCIDR(cidr); err != nil { respondError(w, http.StatusBadRequest, fmt.Sprintf("Route %d: invalid CIDR in ipAllow: %q", i, cidr)) return } } } if err := api.domains.Register(dom); err != nil { respondError(w, http.StatusBadRequest, fmt.Sprintf("Failed to register domain: %v", err)) return } // Return the stored version (has defaults applied) stored, _ := api.domains.Get(dom.DomainName) respondJSON(w, http.StatusCreated, map[string]any{ "message": fmt.Sprintf("Domain %q registered", dom.DomainName), "domain": stored, }) } // DomainsUpdate applies partial updates to a domain. func (api *API) DomainsUpdate(w http.ResponseWriter, r *http.Request) { domain := mux.Vars(r)["domain"] var updates map[string]any if err := json.NewDecoder(r.Body).Decode(&updates); err != nil { respondError(w, http.StatusBadRequest, fmt.Sprintf("Invalid request body: %v", err)) return } if err := api.domains.Update(domain, updates); err != nil { respondError(w, http.StatusNotFound, fmt.Sprintf("Failed to update domain: %v", err)) return } dom, _ := api.domains.Get(domain) respondJSON(w, http.StatusOK, map[string]any{ "message": fmt.Sprintf("Domain %q updated", domain), "domain": dom, }) } // DomainsDeregister removes a domain registration. func (api *API) DomainsDeregister(w http.ResponseWriter, r *http.Request) { domain := mux.Vars(r)["domain"] if err := api.domains.Deregister(domain); err != nil { respondError(w, http.StatusNotFound, fmt.Sprintf("Failed to deregister domain: %v", err)) return } respondMessage(w, http.StatusOK, fmt.Sprintf("Domain %q deregistered", domain)) } // DomainsDeregisterBySource removes all domains from a source with a given backend. func (api *API) DomainsDeregisterBySource(w http.ResponseWriter, r *http.Request) { source := r.URL.Query().Get("source") backend := r.URL.Query().Get("backend") if source == "" { respondError(w, http.StatusBadRequest, "source query parameter is required") return } if err := api.domains.DeregisterBySource(source, backend); err != nil { respondError(w, http.StatusInternalServerError, fmt.Sprintf("Failed to deregister: %v", err)) return } respondMessage(w, http.StatusOK, fmt.Sprintf("Domains from %q deregistered", source)) }