mirror of
https://github.com/kataras/iris.git
synced 2025-01-23 02:31:04 +01:00
This commit is contained in:
parent
333be428c4
commit
cf0338d342
|
@ -364,6 +364,8 @@ Response:
|
|||
|
||||
Other Improvements:
|
||||
|
||||
- Fix [#1621](https://github.com/kataras/iris/issues/1621) and add a new `cache.WithKey` to customize the cached entry key.
|
||||
|
||||
- Add a `Response() *http.Response` to the Response Recorder.
|
||||
- Fix Response Recorder `Flush` when transfer-encoding is `chunked`.
|
||||
- Fix Response Recorder `Clone` concurrent access afterwards.
|
||||
|
|
86
_examples/response-writer/cache/simple/main.go
vendored
86
_examples/response-writer/cache/simple/main.go
vendored
|
@ -4,16 +4,14 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/kataras/iris/v12"
|
||||
|
||||
"github.com/kataras/iris/v12/cache"
|
||||
"github.com/kataras/iris/v12/middleware/basicauth"
|
||||
)
|
||||
|
||||
var markdownContents = []byte(`## Hello Markdown
|
||||
|
||||
This is a sample of Markdown contents
|
||||
|
||||
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
|
@ -23,36 +21,7 @@ All features of Sundown are supported, including:
|
|||
the --tidy option. Without --tidy, the differences are
|
||||
mostly in whitespace and entity escaping, where blackfriday is
|
||||
more consistent and cleaner.
|
||||
|
||||
* **Common extensions**, including table support, fenced code
|
||||
blocks, autolinks, strikethroughs, non-strict emphasis, etc.
|
||||
|
||||
* **Safety**. Blackfriday is paranoid when parsing, making it safe
|
||||
to feed untrusted user input without fear of bad things
|
||||
happening. The test suite stress tests this and there are no
|
||||
known inputs that make it crash. If you find one, please let me
|
||||
know and send me the input that does it.
|
||||
|
||||
NOTE: "safety" in this context means *runtime safety only*. In order to
|
||||
protect yourself against JavaScript injection in untrusted content, see
|
||||
[this example](https://github.com/russross/blackfriday#sanitize-untrusted-content).
|
||||
|
||||
* **Fast processing**. It is fast enough to render on-demand in
|
||||
most web applications without having to cache the output.
|
||||
|
||||
* **Routine safety**. You can run multiple parsers in different
|
||||
goroutines without ill effect. There is no dependence on global
|
||||
shared state.
|
||||
|
||||
* **Minimal dependencies**. Blackfriday only depends on standard
|
||||
library packages in Go. The source code is pretty
|
||||
self-contained, so it is easy to add to any project, including
|
||||
Google App Engine projects.
|
||||
|
||||
* **Standards compliant**. Output successfully validates using the
|
||||
W3C validation tool for HTML 4.01 and XHTML 1.0 Transitional.
|
||||
|
||||
[this is a link](https://github.com/kataras/iris) `)
|
||||
`)
|
||||
|
||||
// Cache should not be used on handlers that contain dynamic data.
|
||||
// Cache is a good and a must-feature on static content, i.e "about page" or for a whole blog site.
|
||||
|
@ -63,6 +32,30 @@ func main() {
|
|||
// saves its content on the first request and serves it instead of re-calculating the content.
|
||||
// After 10 seconds it will be cleared and reset.
|
||||
|
||||
pages := app.Party("/pages")
|
||||
pages.Use(cache.Handler(10 * time.Second)) // Per Party.
|
||||
pages.Get("/", pagesIndex)
|
||||
pages.Post("/", pagesIndexPost)
|
||||
|
||||
// Note: on authenticated requests
|
||||
// the cache middleare does not run at all (see iris/cache/ruleset).
|
||||
auth := basicauth.Default(map[string]string{
|
||||
"admin": "admin",
|
||||
})
|
||||
app.Get("/protected", auth, cache.Handler(5*time.Second), protected)
|
||||
|
||||
// Set custom cache key/identifier,
|
||||
// for the sake of the example
|
||||
// we will SHARE the keys on both GET and POST routes
|
||||
// so the first one is executed that's the body
|
||||
// for both of the routes. Please don't do that
|
||||
// on production, this is just an example.
|
||||
custom := app.Party("/custom")
|
||||
custom.Use(cache.WithKey("shared"))
|
||||
custom.Use(cache.Handler(10 * time.Second))
|
||||
custom.Get("/", customIndex)
|
||||
custom.Post("/", customIndexPost)
|
||||
|
||||
app.Listen(":8080")
|
||||
}
|
||||
|
||||
|
@ -74,7 +67,32 @@ func writeMarkdown(ctx iris.Context) {
|
|||
ctx.Markdown(markdownContents)
|
||||
}
|
||||
|
||||
func pagesIndex(ctx iris.Context) {
|
||||
println("Handler executed. Content refreshed.")
|
||||
ctx.WriteString("GET: hello")
|
||||
}
|
||||
|
||||
func pagesIndexPost(ctx iris.Context) {
|
||||
println("Handler executed. Content refreshed.")
|
||||
ctx.WriteString("POST: hello")
|
||||
}
|
||||
|
||||
func protected(ctx iris.Context) {
|
||||
username, _, _ := ctx.Request().BasicAuth()
|
||||
ctx.Writef("Hello, %s!", username)
|
||||
}
|
||||
|
||||
func customIndex(ctx iris.Context) {
|
||||
ctx.WriteString("Contents from GET custom index")
|
||||
}
|
||||
|
||||
func customIndexPost(ctx iris.Context) {
|
||||
ctx.WriteString("Contents from POST custom index")
|
||||
}
|
||||
|
||||
/* Note that `HandleDir` does use the browser's disk caching by-default
|
||||
therefore, register the cache handler AFTER any HandleDir calls,
|
||||
for a faster solution that server doesn't need to keep track of the response
|
||||
navigate to https://github.com/kataras/iris/blob/master/_examples/cache/client-side/main.go */
|
||||
navigate to https://github.com/kataras/iris/blob/master/_examples/cache/client-side/main.go.
|
||||
|
||||
The `HandleDir` has its own cache mechanism, read the 'file-server' examples. */
|
||||
|
|
12
cache/cache.go
vendored
12
cache/cache.go
vendored
|
@ -34,6 +34,18 @@ import (
|
|||
"github.com/kataras/iris/v12/context"
|
||||
)
|
||||
|
||||
// WithKey sets a custom entry key for cached pages.
|
||||
// Should be prepended to the cache handler.
|
||||
//
|
||||
// Usage:
|
||||
// app.Get("/", cache.WithKey("custom-key"), cache.Handler(time.Minute), mainHandler)
|
||||
func WithKey(key string) context.Handler {
|
||||
return func(ctx *context.Context) {
|
||||
client.SetKey(ctx, key)
|
||||
ctx.Next()
|
||||
}
|
||||
}
|
||||
|
||||
// Cache accepts the cache expiration duration.
|
||||
// If the "expiration" input argument is invalid, <=2 seconds,
|
||||
// then expiration is taken by the "cache-control's maxage" header.
|
||||
|
|
50
cache/client/handler.go
vendored
50
cache/client/handler.go
vendored
|
@ -1,6 +1,7 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
|
@ -73,6 +74,48 @@ func parseLifeChanger(ctx *context.Context) entry.LifeChanger {
|
|||
}
|
||||
}
|
||||
|
||||
const entryKeyContextKey = "iris.cache.server.entry.key"
|
||||
|
||||
// SetKey sets a custom entry key for cached pages.
|
||||
// See root package-level `WithKey` instead.
|
||||
func SetKey(ctx *context.Context, key string) {
|
||||
ctx.Values().Set(entryKeyContextKey, key)
|
||||
}
|
||||
|
||||
// GetKey returns the entry key for the current page.
|
||||
func GetKey(ctx *context.Context) string {
|
||||
return ctx.Values().GetString(entryKeyContextKey)
|
||||
}
|
||||
|
||||
func getOrSetKey(ctx *context.Context) string {
|
||||
if key := GetKey(ctx); key != "" {
|
||||
return key
|
||||
}
|
||||
|
||||
// Note: by-default the rules(ruleset pkg)
|
||||
// explictly ignores the cache handler
|
||||
// execution on authenticated requests
|
||||
// and immediately runs the next handler:
|
||||
// if !h.rule.Claim(ctx) ...see `Handler` method.
|
||||
// So the below two lines are useless,
|
||||
// however we add it for cases
|
||||
// that the end-developer messedup with the rules
|
||||
// and by accident allow authenticated cached results.
|
||||
username, password, _ := ctx.Request().BasicAuth()
|
||||
authPart := username + strings.Repeat("*", len(password))
|
||||
|
||||
key := ctx.Method() + authPart
|
||||
|
||||
u := ctx.Request().URL
|
||||
if !u.IsAbs() {
|
||||
key += ctx.Scheme() + ctx.Host()
|
||||
}
|
||||
key += u.String()
|
||||
|
||||
SetKey(ctx, key)
|
||||
return key
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -90,16 +133,11 @@ func (h *Handler) ServeHTTP(ctx *context.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
scheme := "http"
|
||||
if ctx.Request().TLS != nil {
|
||||
scheme = "https"
|
||||
}
|
||||
|
||||
var (
|
||||
response *entry.Response
|
||||
valid = false
|
||||
// unique per subdomains and paths with different url query.
|
||||
key = scheme + ctx.Host() + ctx.Request().URL.RequestURI()
|
||||
key = getOrSetKey(ctx)
|
||||
)
|
||||
|
||||
h.mu.RLock()
|
||||
|
|
Loading…
Reference in New Issue
Block a user