datawareforge/modules/httpcache/httpcache.go
Marcos A. Lucas 591049def5
feat: Customização white-label para DATAWARE Forge e ajustes diversos
[PT-BR]
Este commit implementa a rebranding completa do Forgejo para DATAWARE Forge, integrando as seguintes alterações:
- Atualização de mensagens, textos, variáveis e endpoints em comandos e arquivos de configuração (ex.: dump, serv, app.ini, scripts Docker, serviço systemd) para refletir a nova identidade DATAWARE Forge.
- Modificação dos nomes de temas e das referências a “Forgejo” e “Gitea” para “DATAWARE Forge” em diversos módulos, headers de API, webhooks, e testes (incluindo X-DatawareForge-OTP e X-DatawareForge-Object-Type).
- Ajustes nos modelos de usuário e configurações do sistema para reservar novos nomes (ex.: dataware-actions, DATAWARE Actions) e atualizar emails institucionais.
- Atualização do package-lock.json para refletir o novo nome do projeto.
- Inclusão e adaptação dos temas especiais de acessibilidade (para deuteranopia/protanopia e tritanopia) em light e dark modes.
- Correções diversas em mensagens de log e validações para garantir a consistência com a nova marca.

Esta atualização consolida a customização white-label para uso interno e futura distribuição a clientes, mantendo os créditos e a integridade do código original.

[EN]
This commit implements the complete rebranding from Forgejo to DATAWARE Forge, integrating the following changes:
- Updated messages, text, variables, and endpoints in commands and configuration files (e.g., dump, serv, app.ini, Docker scripts, systemd service) to reflect the new DATAWARE Forge identity.
- Modified theme names and replaced references to “Forgejo” and “Gitea” with “DATAWARE Forge” throughout various modules, API headers, webhooks, and tests (including X-DatawareForge-OTP and X-DatawareForge-Object-Type).
- Adjusted user models and system settings to reserve new names (e.g., dataware-actions, DATAWARE Actions) and update institutional email addresses.
- Updated package-lock.json to reflect the new project name.
- Added and adapted special accessibility themes (for deuteranopia/protanopia and tritanopia) in both light and dark modes.
- Various fixes in log messages and validations to ensure consistency with the new branding.

This update consolidates the white-label customization for internal use and future client distribution while preserving the original credits and code integrity.

Marcos A. Lucas <mlucas@dataware.com.br>
2025-03-09 05:02:32 -03:00

102 lines
3.4 KiB
Go

// Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package httpcache
import (
"io"
"net/http"
"strconv"
"strings"
"time"
"code.gitea.io/gitea/modules/setting"
)
// SetCacheControlInHeader sets suitable cache-control headers in the response
func SetCacheControlInHeader(h http.Header, maxAge time.Duration, additionalDirectives ...string) {
directives := make([]string, 0, 2+len(additionalDirectives))
// "max-age=0 + must-revalidate" (aka "no-cache") is preferred instead of "no-store"
// because browsers may restore some input fields after navigate-back / reload a page.
if setting.IsProd {
if maxAge == 0 {
directives = append(directives, "max-age=0", "private", "must-revalidate")
} else {
directives = append(directives, "private", "max-age="+strconv.Itoa(int(maxAge.Seconds())))
}
} else {
directives = append(directives, "max-age=0", "private", "must-revalidate")
// to remind users they are using non-prod setting.
h.Set("X-Gitea-Debug", "RUN_MODE="+setting.RunMode)
h.Set("X-Forgejo-Debug", "RUN_MODE="+setting.RunMode)
h.Set("X-DatawareForge-Debug", "RUN_MODE="+setting.RunMode)
}
h.Set("Cache-Control", strings.Join(append(directives, additionalDirectives...), ", "))
}
func ServeContentWithCacheControl(w http.ResponseWriter, req *http.Request, name string, modTime time.Time, content io.ReadSeeker) {
SetCacheControlInHeader(w.Header(), setting.StaticCacheTime)
http.ServeContent(w, req, name, modTime, content)
}
// HandleGenericETagCache handles ETag-based caching for a HTTP request.
// It returns true if the request was handled.
func HandleGenericETagCache(req *http.Request, w http.ResponseWriter, etag string) (handled bool) {
if len(etag) > 0 {
w.Header().Set("Etag", etag)
if checkIfNoneMatchIsValid(req, etag) {
w.WriteHeader(http.StatusNotModified)
return true
}
}
SetCacheControlInHeader(w.Header(), setting.StaticCacheTime)
return false
}
// checkIfNoneMatchIsValid tests if the header If-None-Match matches the ETag
func checkIfNoneMatchIsValid(req *http.Request, etag string) bool {
ifNoneMatch := req.Header.Get("If-None-Match")
if len(ifNoneMatch) > 0 {
for _, item := range strings.Split(ifNoneMatch, ",") {
item = strings.TrimPrefix(strings.TrimSpace(item), "W/") // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag#directives
if item == etag {
return true
}
}
}
return false
}
// HandleGenericETagTimeCache handles ETag-based caching with Last-Modified caching for a HTTP request.
// It returns true if the request was handled.
func HandleGenericETagTimeCache(req *http.Request, w http.ResponseWriter, etag string, lastModified *time.Time) (handled bool) {
if len(etag) > 0 {
w.Header().Set("Etag", etag)
}
if lastModified != nil && !lastModified.IsZero() {
// http.TimeFormat required a UTC time, refer to https://pkg.go.dev/net/http#TimeFormat
w.Header().Set("Last-Modified", lastModified.UTC().Format(http.TimeFormat))
}
if len(etag) > 0 {
if checkIfNoneMatchIsValid(req, etag) {
w.WriteHeader(http.StatusNotModified)
return true
}
}
if lastModified != nil && !lastModified.IsZero() {
ifModifiedSince := req.Header.Get("If-Modified-Since")
if ifModifiedSince != "" {
t, err := time.Parse(http.TimeFormat, ifModifiedSince)
if err == nil && lastModified.Unix() <= t.Unix() {
w.WriteHeader(http.StatusNotModified)
return true
}
}
}
SetCacheControlInHeader(w.Header(), setting.StaticCacheTime)
return false
}