mirror of
https://github.com/kataras/iris.git
synced 2025-12-18 18:37:05 +00:00
make cache package to work across multi handlers, remove the old 'WrapHandler' and keep the cache.Handler as documented only
Former-commit-id: b030cd92d26a9f646b060e379b3702b9a677749b
This commit is contained in:
88
cache/client/handler.go
vendored
88
cache/client/handler.go
vendored
@@ -1,6 +1,7 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/kataras/iris/cache/cfg"
|
||||
@@ -10,34 +11,27 @@ import (
|
||||
)
|
||||
|
||||
// Handler the local cache service handler contains
|
||||
// the original bodyHandler, the memory cache entry and
|
||||
// the original response, the memory cache entry and
|
||||
// the validator for each of the incoming requests and post responses
|
||||
type Handler struct {
|
||||
|
||||
// bodyHandler the original route's handler.
|
||||
// If nil then it tries to take the next handler from the chain.
|
||||
bodyHandler context.Handler
|
||||
|
||||
// Rule optional validators for pre cache and post cache actions
|
||||
//
|
||||
// See more at ruleset.go
|
||||
rule rule.Rule
|
||||
|
||||
// entry is the memory cache entry
|
||||
entry *entry.Entry
|
||||
// when expires.
|
||||
expiration time.Duration
|
||||
// entries the memory cache stored responses.
|
||||
entries map[string]*entry.Entry
|
||||
mu sync.RWMutex
|
||||
}
|
||||
|
||||
// NewHandler returns a new cached handler for the "bodyHandler"
|
||||
// which expires every "expiration".
|
||||
func NewHandler(bodyHandler context.Handler,
|
||||
expiration time.Duration) *Handler {
|
||||
|
||||
e := entry.NewEntry(expiration)
|
||||
|
||||
func NewHandler(expiration time.Duration) *Handler {
|
||||
return &Handler{
|
||||
bodyHandler: bodyHandler,
|
||||
rule: DefaultRuleSet,
|
||||
entry: e,
|
||||
rule: DefaultRuleSet,
|
||||
expiration: expiration,
|
||||
entries: make(map[string]*entry.Entry, 0),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,35 +60,53 @@ func (h *Handler) AddRule(r rule.Rule) *Handler {
|
||||
return h
|
||||
}
|
||||
|
||||
var emptyHandler = func(ctx context.Context) {
|
||||
ctx.StatusCode(500)
|
||||
ctx.WriteString("cache: empty body handler")
|
||||
ctx.StopExecution()
|
||||
}
|
||||
|
||||
func (h *Handler) ServeHTTP(ctx context.Context) {
|
||||
// check for pre-cache validators, if at least one of them return false
|
||||
// for this specific request, then skip the whole cache
|
||||
bodyHandler := h.bodyHandler
|
||||
|
||||
bodyHandler := ctx.NextHandler()
|
||||
if bodyHandler == nil {
|
||||
if nextHandler := ctx.NextHandler(); nextHandler != nil {
|
||||
// skip prepares the context to move to the next handler if the "nextHandler" has a ctx.Next() inside it,
|
||||
// even if it's not executed because it's cached.
|
||||
ctx.Skip()
|
||||
bodyHandler = nextHandler
|
||||
} else {
|
||||
ctx.StatusCode(500)
|
||||
ctx.WriteString("cache: empty body handler")
|
||||
ctx.StopExecution()
|
||||
return
|
||||
}
|
||||
emptyHandler(ctx)
|
||||
return
|
||||
}
|
||||
// skip prepares the context to move to the next handler if the "nextHandler" has a ctx.Next() inside it,
|
||||
// even if it's not executed because it's cached.
|
||||
ctx.Skip()
|
||||
|
||||
if !h.rule.Claim(ctx) {
|
||||
bodyHandler(ctx)
|
||||
return
|
||||
}
|
||||
|
||||
// check if we have a stored response( it is not expired)
|
||||
res, exists := h.entry.Response()
|
||||
if !exists {
|
||||
var (
|
||||
response *entry.Response
|
||||
valid = false
|
||||
key = ctx.Path()
|
||||
)
|
||||
|
||||
// if it's not exists, then execute the original handler
|
||||
h.mu.RLock()
|
||||
e, found := h.entries[key]
|
||||
h.mu.RUnlock()
|
||||
|
||||
if found {
|
||||
// the entry is here, .Response will give us
|
||||
// if it's expired or no
|
||||
response, valid = e.Response()
|
||||
} else {
|
||||
// create the entry now.
|
||||
e = entry.NewEntry(h.expiration)
|
||||
h.mu.Lock()
|
||||
h.entries[key] = e
|
||||
h.mu.Unlock()
|
||||
}
|
||||
|
||||
if !valid {
|
||||
// if it's expired, then execute the original handler
|
||||
// with our custom response recorder response writer
|
||||
// because the net/http doesn't give us
|
||||
// a built'n way to get the status code & body
|
||||
@@ -119,12 +131,12 @@ func (h *Handler) ServeHTTP(ctx context.Context) {
|
||||
// check for an expiration time if the
|
||||
// given expiration was not valid then check for GetMaxAge &
|
||||
// update the response & release the recorder
|
||||
h.entry.Reset(recorder.StatusCode(), recorder.Header().Get(cfg.ContentTypeHeader), body, GetMaxAge(ctx.Request()))
|
||||
e.Reset(recorder.StatusCode(), recorder.Header().Get(cfg.ContentTypeHeader), body, GetMaxAge(ctx.Request()))
|
||||
return
|
||||
}
|
||||
|
||||
// if it's valid then just write the cached results
|
||||
ctx.ContentType(res.ContentType())
|
||||
ctx.StatusCode(res.StatusCode())
|
||||
ctx.Write(res.Body())
|
||||
ctx.ContentType(response.ContentType())
|
||||
ctx.StatusCode(response.StatusCode())
|
||||
ctx.Write(response.Body())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user