Refactor cache, just use ETag

This commit is contained in:
Jan-Lukas Else 2023-04-11 16:43:14 +02:00
parent 0f5ddb2e80
commit a75fa07f57
5 changed files with 18 additions and 46 deletions

View File

@ -2,15 +2,12 @@ package main
import (
"context"
"crypto/sha256"
"fmt"
"log"
"net/http"
"net/url"
"sort"
"time"
"github.com/araddon/dateparse"
"github.com/dgraph-io/ristretto"
"go.goblog.app/app/pkgs/bufferpool"
"golang.org/x/sync/singleflight"
@ -20,7 +17,6 @@ const (
cacheLoggedInKey contextKey = "cacheLoggedIn"
cacheExpirationKey contextKey = "cacheExpiration"
lastModified = "Last-Modified"
cacheControl = "Cache-Control"
)
@ -88,13 +84,6 @@ func (a *goBlog) cacheMiddleware(next http.Handler) http.Handler {
w.WriteHeader(http.StatusNotModified)
return
}
if ifModifiedSinceHeader := r.Header.Get("If-Modified-Since"); ifModifiedSinceHeader != "" {
if t, err := dateparse.ParseAny(ifModifiedSinceHeader); err == nil && t.After(ci.creationTime) {
// send 304
w.WriteHeader(http.StatusNotModified)
return
}
}
// set status code
w.WriteHeader(ci.code)
// write cached body
@ -156,24 +145,15 @@ func (a *goBlog) setCacheHeaders(w http.ResponseWriter, cache *cacheItem) {
}
// Set cache headers
w.Header().Set("ETag", cache.eTag)
w.Header().Set(lastModified, cache.creationTime.UTC().Format(http.TimeFormat))
if w.Header().Get(cacheControl) == "" {
if cache.expiration != 0 {
w.Header().Set(cacheControl, fmt.Sprintf("public,max-age=%d,stale-while-revalidate=%d", cache.expiration, cache.expiration))
} else {
exp := a.cfg.Cache.Expiration
w.Header().Set(cacheControl, fmt.Sprintf("public,max-age=%d,s-max-age=%d,stale-while-revalidate=%d", exp, exp/3, exp))
}
}
w.Header().Set(cacheControl, "public,no-cache")
}
type cacheItem struct {
expiration int
creationTime time.Time
eTag string
code int
header http.Header
body []byte
expiration int
eTag string
code int
header http.Header
body []byte
}
// Calculate byte size of cache item using size of header, body and etag
@ -203,24 +183,12 @@ func (c *cache) getCache(key string, next http.Handler, r *http.Request) *cacheI
rec := newCacheRecorder()
next.ServeHTTP(rec, cr)
item := rec.finish()
// Set eTag
item.eTag = item.header.Get("ETag")
if item.eTag == "" {
item.eTag = fmt.Sprintf("%x", sha256.Sum256(item.body))
}
// Set creation time
item.creationTime = time.Now()
if lm := item.header.Get(lastModified); lm != "" {
if parsedTime, te := dateparse.ParseLocal(lm); te == nil {
item.creationTime = parsedTime
}
}
// Set expiration
item.expiration, _ = cr.Context().Value(cacheExpirationKey).(int)
// Remove problematic headers
item.header.Del("Accept-Ranges")
item.header.Del("ETag")
item.header.Del(lastModified)
item.header.Del("Last-Modified")
// Save cache
if cch := item.header.Get(cacheControl); !containsStrings(cch, "no-store", "private", "no-cache") {
cost := int64(item.cost())

View File

@ -1,6 +1,8 @@
package main
import (
"crypto/sha256"
"fmt"
"net/http"
)
@ -21,6 +23,10 @@ func newCacheRecorder() *cacheRecorder {
func (c *cacheRecorder) finish() *cacheItem {
c.done = true
c.item.eTag = c.item.header.Get("ETag")
if c.item.eTag == "" {
c.item.eTag = fmt.Sprintf("%x", sha256.Sum256(c.item.body))
}
return &c.item
}

View File

@ -6,7 +6,6 @@ import (
"net/http/httptest"
"strconv"
"testing"
"time"
"github.com/dgraph-io/ristretto"
"github.com/stretchr/testify/assert"
@ -14,9 +13,8 @@ import (
func Benchmark_cacheItem_cost(b *testing.B) {
ci := &cacheItem{
creationTime: time.Now(),
eTag: "abc",
code: 200,
eTag: "abc",
code: 200,
header: http.Header{
"Content-Type": []string{"text/html"},
},

2
go.mod
View File

@ -30,7 +30,7 @@ require (
github.com/gorilla/handlers v1.5.1
github.com/gorilla/sessions v1.2.1
github.com/gorilla/websocket v1.5.0
github.com/hacdias/indieauth/v3 v3.0.1
github.com/hacdias/indieauth/v3 v3.1.0
github.com/jlaffaye/ftp v0.1.0
// master
github.com/jlelse/feeds v1.2.1-0.20210704161900-189f94254ad4

4
go.sum
View File

@ -238,8 +238,8 @@ github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/z
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/hacdias/indieauth/v3 v3.0.1 h1:b/C2VlqOzijvVJuezFcGhEmMZyCvZgdHgLZIb9BOlxk=
github.com/hacdias/indieauth/v3 v3.0.1/go.mod h1:mVMKFOoVMYgGb06HgXiSevyIJu3/GoRo/EujEXSpAKs=
github.com/hacdias/indieauth/v3 v3.1.0 h1:aVj9hp9cNCYrlUnSybrG7vNSgJ1/4JIsSa0jsQ3zpHk=
github.com/hacdias/indieauth/v3 v3.1.0/go.mod h1:EmGEAbqGNhCnJR6Uk00t83x7ASQeo0EBNf/5XiFvS9w=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=