diff --git a/cmd/disk-cache-utils.go b/cmd/disk-cache-utils.go index 5713b40aa..5f03c52a4 100644 --- a/cmd/disk-cache-utils.go +++ b/cmd/disk-cache-utils.go @@ -29,11 +29,14 @@ import ( ) type cacheControl struct { - expiry time.Time - maxAge int - sMaxAge int - minFresh int - maxStale int + expiry time.Time + maxAge int + sMaxAge int + minFresh int + maxStale int + noStore bool + onlyIfCached bool + noCache bool } func (c cacheControl) isEmpty() bool { @@ -45,6 +48,19 @@ func (c cacheControl) isStale(modTime time.Time) bool { if c.isEmpty() { return false } + // response will never be stale if only-if-cached is set + if c.onlyIfCached { + return false + } + // Cache-Control value no-store indicates never cache + if c.noStore { + return true + } + // Cache-Control value no-cache indicates cache entry needs to be revalidated before + // serving from cache + if c.noCache { + return true + } now := time.Now() if c.sMaxAge > 0 && c.sMaxAge < int(now.Sub(modTime).Seconds()) { @@ -88,6 +104,19 @@ func cacheControlOpts(o ObjectInfo) (c cacheControl) { vals := strings.Split(headerVal, ",") for _, val := range vals { val = strings.TrimSpace(val) + + if val == "no-store" { + c.noStore = true + continue + } + if val == "only-if-cached" { + c.onlyIfCached = true + continue + } + if val == "no-cache" { + c.noCache = true + continue + } p := strings.Split(val, "=") if len(p) != 2 { diff --git a/cmd/disk-cache.go b/cmd/disk-cache.go index 59bc38ac9..7fab8e4e0 100644 --- a/cmd/disk-cache.go +++ b/cmd/disk-cache.go @@ -185,12 +185,17 @@ func (c *cacheObjects) GetObjectNInfo(ctx context.Context, bucket, object string cacheReader, cacheErr := c.get(ctx, dcache, bucket, object, rs, h, opts) if cacheErr == nil { cc = cacheControlOpts(cacheReader.ObjInfo) - if !cc.isStale(cacheReader.ObjInfo.ModTime) { + if (!cc.isEmpty() && !cc.isStale(cacheReader.ObjInfo.ModTime)) || + cc.onlyIfCached { // This is a cache hit, mark it so c.cacheStats.incHit() c.cacheStats.incBytesServed(cacheReader.ObjInfo.Size) return cacheReader, nil } + if cc.noStore { + c.cacheStats.incMiss() + return c.GetObjectNInfo(ctx, bucket, object, rs, h, lockType, opts) + } } // Reaching here implies cache miss