Something something etag middleware
This commit is contained in:
parent
91cc68efe7
commit
f2e52a18e5
1 changed files with 66 additions and 0 deletions
66
internal/middleware/etag_cache.go
Normal file
66
internal/middleware/etag_cache.go
Normal file
|
|
@ -0,0 +1,66 @@
|
||||||
|
package middleware
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"hash/crc64"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ETag struct {
|
||||||
|
Name string
|
||||||
|
Value string
|
||||||
|
Expiration time.Duration
|
||||||
|
HashTime time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
var etags = make([]*ETag, 0)
|
||||||
|
|
||||||
|
func (etag *ETag) Header() string {
|
||||||
|
return fmt.Sprintf("\"pb-%s-%s\"", etag.Name, etag.Value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (etag *ETag) CacheControlHeader() string {
|
||||||
|
return fmt.Sprintf("max-age=%d", int(etag.Expiration.Seconds()))
|
||||||
|
}
|
||||||
|
|
||||||
|
func StaticEtagMiddleware(etag ETag, next http.Handler) http.Handler {
|
||||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
cc := etag.CacheControlHeader()
|
||||||
|
w.Header().Set("ETag", etag.Header())
|
||||||
|
w.Header().Set("Cache-Control", cc)
|
||||||
|
|
||||||
|
log.Printf("Returned etag with Cache-Control '%s'", cc)
|
||||||
|
|
||||||
|
if match := r.Header.Get("If-None-Match"); match != "" {
|
||||||
|
if strings.Contains(match, etag.Value) {
|
||||||
|
log.Print("ETag cache hit")
|
||||||
|
w.WriteHeader(http.StatusNotModified)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
next.ServeHTTP(w, r)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// GenerateETagFromBuffer calculates etag value from one or more buffers (e.g. embedded files)
|
||||||
|
func GenerateETagFromBuffer(name string, expiration time.Duration, buffers ...[]byte) (*ETag, error) {
|
||||||
|
start := time.Now()
|
||||||
|
hash := crc64.New(crc64.MakeTable(crc64.ECMA))
|
||||||
|
for _, buffer := range buffers {
|
||||||
|
_, err := hash.Write(buffer)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("unable to generate etag from buffer: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
etag := &ETag{
|
||||||
|
Name: name,
|
||||||
|
Expiration: expiration,
|
||||||
|
Value: fmt.Sprintf("%x", hash.Sum64()),
|
||||||
|
HashTime: time.Since(start),
|
||||||
|
}
|
||||||
|
etags = append(etags, etag)
|
||||||
|
return etag, nil
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue