// Package api holds the SEO plugin's JSON endpoints under /_seo/api/v1. package api import ( "errors" "net/http" "git.golem15.com/golem15/sm-seo-plugin/classes" "git.golem15.com/golem15/summercms/modules/diary" "git.golem15.com/golem15/summercms/modules/wire" ) var log = diary.For("seo") // Resolve serves GET /_seo/api/v1/resolve?url=: the // effective SEO of a public URL for the frontend's . It answers 200 // with the resolve answer (action ok or not_found, the status the page // should answer with) and 422 when url is missing or not a path or an // http(s) URL. Absolute URLs come from the configured site URL, never from // the request's Host. func Resolve(service func() *classes.Service) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { svc := service() if svc == nil { wire.WriteJSON(w, http.StatusServiceUnavailable, map[string]string{"error": "SEO is not available"}) return } res, err := svc.Resolver().Resolve(r.Context(), r.URL.Query().Get("url")) if errors.Is(err, classes.ErrBadURL) { wire.WriteJSON(w, http.StatusUnprocessableEntity, map[string]string{"error": err.Error()}) return } if err != nil { log.Error("golem15.seo: resolve", "error", err) wire.WriteJSON(w, http.StatusInternalServerError, map[string]string{"error": "Internal Server Error"}) return } w.Header().Set("X-Robots-Tag", "noindex") wire.WriteJSON(w, http.StatusOK, res) } }