- 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
39 lines
1.4 KiB
Go
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))
|
|
}
|
|
}
|