client-side caching for avatars
This commit is contained in:
@@ -8,6 +8,7 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -87,7 +88,20 @@ func (p *AvatarProxy) Routes() (string, chi.Router) {
|
||||
|
||||
// GET /123456789.image
|
||||
router.Get("/{avatar}", func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
avatar := chi.URLParam(r, "avatar")
|
||||
|
||||
// client-side caching
|
||||
etag := `"` + avatar + `"`
|
||||
w.Header().Set("Etag", etag)
|
||||
w.Header().Set("Cache-Control", "max-age=2592000") // 30 days
|
||||
if match := r.Header.Get("If-None-Match"); match != "" {
|
||||
if strings.Contains(match, etag) {
|
||||
w.WriteHeader(http.StatusNotModified)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
location := p.location(strings.TrimSuffix(avatar, imgSfx))
|
||||
avFile := path.Join(location, avatar)
|
||||
fh, err := os.Open(avFile)
|
||||
@@ -103,6 +117,11 @@ func (p *AvatarProxy) Routes() (string, chi.Router) {
|
||||
}()
|
||||
|
||||
w.Header().Set("Content-Type", "image/*")
|
||||
if fi, err := fh.Stat(); err == nil {
|
||||
w.Header().Set("Content-Length", strconv.Itoa(int(fi.Size())))
|
||||
}
|
||||
|
||||
// write all headers
|
||||
if status, ok := r.Context().Value(render.StatusCtxKey).(int); ok {
|
||||
w.WriteHeader(status)
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ func TestRoutes(t *testing.T) {
|
||||
handler.ServeHTTP(rr, req)
|
||||
|
||||
assert.Equal(t, http.StatusOK, rr.Code)
|
||||
assert.Equal(t, http.Header{"Content-Type": []string{"image/*"}}, rr.HeaderMap)
|
||||
assert.EqualValues(t, http.Header{"Content-Type": []string{"image/*"}, "Content-Length": []string{"21"}}, rr.HeaderMap)
|
||||
bb := bytes.Buffer{}
|
||||
sz, err := io.Copy(&bb, rr.Body)
|
||||
assert.NoError(t, err)
|
||||
|
||||
Reference in New Issue
Block a user