// Package api holds the sitemap plugin's HTTP handlers outside the admin: // the IndexNow key file, the HTML sitemap API and the management API. package api import ( "net/http" "git.golem15.com/golem15/sm-sitemap-plugin/classes" "git.golem15.com/golem15/summercms/modules/backpack" "gorm.io/gorm" ) // KeyFilePattern is the {file} constraint of the key file route: an // IndexNow key file name, .txt. const KeyFilePattern = `[A-Za-z0-9-]{8,128}\.txt` // KeyFile serves GET /_sitemap/indexnow/{file}: the IndexNow key as // text/plain when IndexNow is on and file is .txt; any other name, a // replaced key or IndexNow off answers 404 (D-31). The SEO layer serves it // at the site root. func KeyFile(app func() *backpack.App) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { a := app() if a == nil { http.NotFound(w, r) return } db, ok := a.Lookup[*gorm.DB]() if !ok || db == nil { http.Error(w, "Internal Server Error", http.StatusInternalServerError) return } settings, err := classes.LoadSettings(db.WithContext(r.Context())) if err != nil { http.Error(w, "Internal Server Error", http.StatusInternalServerError) return } key := classes.ActiveKey(settings) if key == "" || r.PathValue("file") != classes.KeyFileName(key) { http.NotFound(w, r) return } w.Header().Set("Content-Type", "text/plain; charset=utf-8") w.Header().Set("Cache-Control", "no-cache, private") w.Header().Set("X-Robots-Tag", "noindex") w.WriteHeader(http.StatusOK) _, _ = w.Write([]byte(key)) } }