Files
new-api/controller/revalidated_response.go

55 lines
1.6 KiB
Go

package controller
import (
"net/http"
"github.com/QuantumNous/new-api/common"
"github.com/gin-gonic/gin"
)
// etagVersionPublicContent namespaces the public-content ETag; bump it when
// the JSON envelope served by serveRevalidatedJSON changes shape.
const etagVersionPublicContent = "public-content:v1"
type publicContentResponse struct {
Success bool `json:"success"`
Message string `json:"message"`
Data string `json:"data"`
}
// serveRevalidatedJSON writes public content as JSON with a weak
// content-derived ETag and answers conditional requests with 304 Not
// Modified. The ETag is a weak validator derived from the content, so it is
// stable across replicas and JSON encodings, and a new one is issued when
// the content changes. Cache-Control: no-cache forces revalidation before
// reuse, so an admin edit takes effect on the next request; Vary:
// Accept-Encoding keeps the gzip and identity encodings apart in shared
// caches.
func serveRevalidatedJSON(c *gin.Context, content string) {
body, err := common.Marshal(publicContentResponse{
Success: true,
Message: "",
Data: content,
})
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{
"success": false,
"message": err.Error(),
})
return
}
etag := common.ETagFor(etagVersionPublicContent, content)
c.Header("ETag", etag)
c.Header("Cache-Control", "no-cache")
c.Header("Vary", "Accept-Encoding")
if common.ETagMatches(c.GetHeader("If-None-Match"), etag) {
c.Status(http.StatusNotModified)
return
}
c.Data(http.StatusOK, "application/json; charset=utf-8", body)
}