aboutsummaryrefslogtreecommitdiffstats
path: root/modules/httpcache/httpcache.go
diff options
context:
space:
mode:
Diffstat (limited to 'modules/httpcache/httpcache.go')
-rw-r--r--modules/httpcache/httpcache.go53
1 files changed, 38 insertions, 15 deletions
diff --git a/modules/httpcache/httpcache.go b/modules/httpcache/httpcache.go
index 2c9af94405..dd3efab7a5 100644
--- a/modules/httpcache/httpcache.go
+++ b/modules/httpcache/httpcache.go
@@ -4,40 +4,60 @@
package httpcache
import (
- "io"
+ "fmt"
"net/http"
"strconv"
"strings"
"time"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/util"
)
+type CacheControlOptions struct {
+ IsPublic bool
+ MaxAge time.Duration
+ NoTransform bool
+}
+
// 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))
+func SetCacheControlInHeader(h http.Header, opts *CacheControlOptions) {
+ directives := make([]string, 0, 4)
// "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.
+ publicPrivate := util.Iif(opts.IsPublic, "public", "private")
if setting.IsProd {
- if maxAge == 0 {
+ if opts.MaxAge == 0 {
directives = append(directives, "max-age=0", "private", "must-revalidate")
} else {
- directives = append(directives, "private", "max-age="+strconv.Itoa(int(maxAge.Seconds())))
+ directives = append(directives, publicPrivate, "max-age="+strconv.Itoa(int(opts.MaxAge.Seconds())))
}
} else {
- directives = append(directives, "max-age=0", "private", "must-revalidate")
+ // use dev-related controls, and remind users they are using non-prod setting.
+ directives = append(directives, "max-age=0", publicPrivate, "must-revalidate")
+ h.Set("X-Gitea-Debug", fmt.Sprintf("RUN_MODE=%v, MaxAge=%s", setting.RunMode, opts.MaxAge))
+ }
- // to remind users they are using non-prod setting.
- h.Set("X-Gitea-Debug", "RUN_MODE="+setting.RunMode)
+ if opts.NoTransform {
+ directives = append(directives, "no-transform")
}
+ h.Set("Cache-Control", strings.Join(directives, ", "))
+}
- h.Set("Cache-Control", strings.Join(append(directives, additionalDirectives...), ", "))
+func CacheControlForPublicStatic() *CacheControlOptions {
+ return &CacheControlOptions{
+ IsPublic: true,
+ MaxAge: setting.StaticCacheTime,
+ NoTransform: true,
+ }
}
-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)
+func CacheControlForPrivateStatic() *CacheControlOptions {
+ return &CacheControlOptions{
+ MaxAge: setting.StaticCacheTime,
+ NoTransform: true,
+ }
}
// HandleGenericETagCache handles ETag-based caching for a HTTP request.
@@ -50,7 +70,8 @@ func HandleGenericETagCache(req *http.Request, w http.ResponseWriter, etag strin
return true
}
}
- SetCacheControlInHeader(w.Header(), setting.StaticCacheTime)
+ // not sure whether it is a public content, so just use "private" (old behavior)
+ SetCacheControlInHeader(w.Header(), CacheControlForPrivateStatic())
return false
}
@@ -58,7 +79,7 @@ func HandleGenericETagCache(req *http.Request, w http.ResponseWriter, etag strin
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, ",") {
+ for item := range strings.SplitSeq(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
@@ -95,6 +116,8 @@ func HandleGenericETagTimeCache(req *http.Request, w http.ResponseWriter, etag s
}
}
}
- SetCacheControlInHeader(w.Header(), setting.StaticCacheTime)
+
+ // not sure whether it is a public content, so just use "private" (old behavior)
+ SetCacheControlInHeader(w.Header(), CacheControlForPrivateStatic())
return false
}