Files
sm-seo-plugin/controllers/api/verification.go
Jakub Zych ec74062624 feat: verification files API
- GET /_seo/api/v1/verification/{name} serves a verification file stored
  in the SEO settings with its content type, nosniff and a sandboxing CSP
  (D-05, D-103); the name pattern is enforced in the route and the
  lookup, and no route is registered at the site root
2026-10-27 11:52:55 +01:00

39 lines
1.4 KiB
Go

package api
import (
"net/http"
"git.golem15.com/golem15/sm-seo-plugin/classes"
"git.golem15.com/golem15/summercms/modules/wire"
)
// Verification serves GET /_seo/api/v1/verification/{name} (D-05, D-103):
// the body of a search-engine verification file stored in the SEO
// settings, with the content type of its extension, for the frontend to
// serve at the site root. The body is never run: it carries nosniff and a
// sandboxing Content-Security-Policy. An unknown or malformed name is 404.
func Verification(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
}
file, found, err := svc.VerificationFileByName(r.Context(), r.PathValue("name"))
if err != nil {
log.Error("golem15.seo: verification file", "error", err)
wire.WriteJSON(w, http.StatusInternalServerError, map[string]string{"error": "Internal Server Error"})
return
}
if !found {
wire.WriteJSON(w, http.StatusNotFound, map[string]string{"error": "Not Found"})
return
}
w.Header().Set("Content-Type", file.ContentType)
w.Header().Set("X-Content-Type-Options", "nosniff")
w.Header().Set("Content-Security-Policy", "default-src 'none'; sandbox")
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte(file.Body))
}
}