88 lines
2.2 KiB
Go
88 lines
2.2 KiB
Go
package site
|
|
|
|
import (
|
|
"RenewCMS/api/pkg/apperr"
|
|
validator "RenewCMS/api/pkg/validator"
|
|
"RenewCMS/internal/infrastructure/useCases"
|
|
"encoding/json"
|
|
"log"
|
|
"net/http"
|
|
"net/url"
|
|
"strconv"
|
|
"time"
|
|
|
|
"github.com/go-chi/chi/v5"
|
|
)
|
|
|
|
const (
|
|
defaultSitemapPage = 1
|
|
defaultSitemapSize = 100
|
|
totalCountHeader = "X-Total-Count"
|
|
)
|
|
|
|
type SitemapHandler struct {
|
|
ListUseCase *useCases.ListSitemapUseCase
|
|
}
|
|
|
|
func NewSitemapHandler(list *useCases.ListSitemapUseCase) *SitemapHandler {
|
|
return &SitemapHandler{ListUseCase: list}
|
|
}
|
|
|
|
type sitemapQuery struct {
|
|
Page int `validate:"gte=1"`
|
|
Size int `validate:"oneof=25 50 100 500"`
|
|
}
|
|
|
|
type sitemapItem struct {
|
|
URL string `json:"url"`
|
|
ModifiedAt string `json:"modified_at"`
|
|
Noindex bool `json:"noindex"`
|
|
}
|
|
|
|
func sitemapIntParam(values url.Values, name string, fallback int) (int, error) {
|
|
if !values.Has(name) {
|
|
return fallback, nil
|
|
}
|
|
return strconv.Atoi(values.Get(name))
|
|
}
|
|
|
|
func readSitemapQuery(values url.Values) (sitemapQuery, error) {
|
|
page, err := sitemapIntParam(values, "page", defaultSitemapPage)
|
|
if err != nil {
|
|
return sitemapQuery{}, err
|
|
}
|
|
size, err := sitemapIntParam(values, "size", defaultSitemapSize)
|
|
if err != nil {
|
|
return sitemapQuery{}, err
|
|
}
|
|
return sitemapQuery{Page: page, Size: size}, nil
|
|
}
|
|
|
|
func (h *SitemapHandler) Sitemap(w http.ResponseWriter, r *http.Request) {
|
|
query, err := readSitemapQuery(r.URL.Query())
|
|
if err != nil || validator.Validate.Struct(query) != nil {
|
|
http.Error(w, apperr.BodyErrorMessage, http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
page, err := h.ListUseCase.List(chi.URLParam(r, "key"), query.Page, query.Size)
|
|
if err != nil {
|
|
writeSiteError(w, err)
|
|
return
|
|
}
|
|
|
|
items := make([]sitemapItem, 0, len(page.Entries))
|
|
for _, entry := range page.Entries {
|
|
items = append(items, sitemapItem{URL: entry.URL, ModifiedAt: entry.ModifiedAt.UTC().Format(time.RFC3339), Noindex: entry.Noindex})
|
|
}
|
|
body, err := json.Marshal(items)
|
|
if err != nil {
|
|
http.Error(w, "Failed to encode response", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
w.Header().Set(totalCountHeader, strconv.Itoa(page.Total))
|
|
if _, err := w.Write(body); err != nil {
|
|
log.Printf("Failed to write response: %v", err)
|
|
}
|
|
}
|