From 6f22da7622f4f4160e447e78c6960657c8bf4885 Mon Sep 17 00:00:00 2001 From: Gerasimos Maropoulos Date: Fri, 28 Oct 2016 21:55:00 +0300 Subject: [PATCH] Nothing special here, remote cache is not ready yet Remote Cache is not inside docs or history because it's not ready for production yet, however it seems to works fine, but until I test it on more than 2kk requests I will not add this on history or docs. The upcoming 24 hours I will upload a relative package which will combine all cache features to one --- cache.go | 60 ++++++++++++++++++++++++-------------------------------- http.go | 4 ++-- iris.go | 4 ++-- 3 files changed, 30 insertions(+), 38 deletions(-) diff --git a/cache.go b/cache.go index 6f674c32..c78a5477 100644 --- a/cache.go +++ b/cache.go @@ -71,7 +71,6 @@ func (cs *cacheService) start() { now := time.Now() for k, v := range cs.cache { if now.After(v.expires) { - println("remove cache") delete(cs.cache, k) } } @@ -84,7 +83,7 @@ func (cs *cacheService) start() { func (cs *cacheService) get(key string) *cacheEntry { cs.mu.RLock() - if v, ok := cs.cache[key]; ok { + if v, ok := cs.cache[key]; ok && time.Now().Before(v.expires) { // we check for expiration, the gc clears the cache but gc maybe late cs.mu.RUnlock() return v } @@ -199,13 +198,8 @@ func getResponseStatusCode(ctx *Context) int { func (cs *cacheService) Cache(bodyHandler HandlerFunc, expiration time.Duration) HandlerFunc { expiration = validateCacheDuration(expiration) - if cs.gcDuration == -1 { - // if gc duration is not setted yet or this is the only one Cache which happens to have bigger expiration than the minimumAllowedCacheDuration - // then set that as the gcDuration - cs.gcDuration = expiration // the first time the lowerExpiration should be > minimumAllowedCacheDuration so: - } else if expiration < cs.gcDuration { // find the lower - // if this expiration is lower than the already setted, set the gcDuration to this - cs.gcDuration = expiration + if cs.gcDuration == -1 || expiration < cs.gcDuration { + cs.gcDuration = expiration // the first time the gcDuration should be > minimumAllowedCacheDuration so: } h := func(ctx *Context) { @@ -245,6 +239,9 @@ const ( queryCacheDuration = "cache_duration" queryCacheStatusCode = "cache_status_code" queryCacheContentType = "cache_content_type" + requestCacheTimeout = 5 * time.Second + statusCacheSucceed = StatusOK + statusCacheFailed = StatusBadRequest ) // RemoteCache accepts the remote server address and path of the external cache service, the body handler and optional an expiration @@ -262,25 +259,25 @@ func RemoteCache(cacheServerAddr string, bodyHandler HandlerFunc, expiration tim req := fasthttp.AcquireRequest() req.SetRequestURI(cacheServerAddr) req.Header.SetMethodBytes(MethodGetBytes) - req.URI().QueryArgs().Add("cache_key", GetRemoteCacheKey(ctx)) + req.URI().QueryArgs().Add(queryCacheKey, GetRemoteCacheKey(ctx)) res := fasthttp.AcquireResponse() - err := client.DoTimeout(req, res, time.Duration(5)*time.Second) - if err != nil || res.StatusCode() == StatusBadRequest { + err := client.DoTimeout(req, res, requestCacheTimeout) + if err != nil || res.StatusCode() == statusCacheFailed { // if not found on cache, then execute the handler and save the cache to the remote server bodyHandler.Serve(ctx) // save to the remote cache req.Header.SetMethodBytes(MethodPostBytes) - - req.URI().QueryArgs().Add("cache_duration", cacheDurationStr) + args := req.URI().QueryArgs() + args.Add(queryCacheDuration, cacheDurationStr) statusCode := strconv.Itoa(ctx.Response.StatusCode()) - req.URI().QueryArgs().Add("cache_status_code", statusCode) + args.Add(queryCacheStatusCode, statusCode) cType := string(ctx.Response.Header.Peek(contentType)) - req.URI().QueryArgs().Add("cache_content_type", cType) + args.Add(queryCacheContentType, cType) req.SetBody(ctx.Response.Body()) go func() { - client.DoTimeout(req, res, time.Duration(5)*time.Second) + client.DoTimeout(req, res, requestCacheTimeout) fasthttp.ReleaseRequest(req) fasthttp.ReleaseResponse(res) }() @@ -332,11 +329,11 @@ func ServeRemoteCache(gcDuration time.Duration) HandlerFunc { // use the app.ServeRemoteCache instead of iris.ServeRemoteCache func (cs *cacheService) ServeRemoteCache(gcDuration time.Duration) HandlerFunc { cs.gcDuration = validateCacheDuration(gcDuration) - + // the service started at pre-listen state(on .Build) if gcDuration > 0 h := func(ctx *Context) { - key := ctx.URLParam("cache_key") + key := ctx.URLParam(queryCacheKey) if key == "" { - ctx.SetStatusCode(StatusBadRequest) + ctx.SetStatusCode(statusCacheFailed) return } @@ -347,11 +344,11 @@ func (cs *cacheService) ServeRemoteCache(gcDuration time.Duration) HandlerFunc { } } else if ctx.IsPost() { // get the cache expiration via url param - expirationSeconds, err := ctx.URLParamInt64("cache_duration") + expirationSeconds, err := ctx.URLParamInt64(queryCacheDuration) // get the body from the requested body body := ctx.Request.Body() if len(body) == 0 { - ctx.SetStatusCode(StatusBadRequest) + ctx.SetStatusCode(statusCacheFailed) return } @@ -365,27 +362,22 @@ func (cs *cacheService) ServeRemoteCache(gcDuration time.Duration) HandlerFunc { expirationSeconds = int64(minimumAllowedCacheDuration.Seconds()) } - cacheDuration := time.Duration(expirationSeconds) * time.Second - statusCode, err := ctx.URLParamInt("cache_status_code") - if err != nil { - statusCode = StatusOK - } - cType := ctx.URLParam("cache_content_type") - if cType == "" { - cType = contentHTML - } + cacheDuration := validateCacheDuration(time.Duration(expirationSeconds) * time.Second) + statusCode, _ := ctx.URLParamInt(queryCacheDuration) + statusCode = validateStatusCode(statusCode) + cType := validateContentType(ctx.URLParam(queryCacheContentType)) cs.set(key, statusCode, cType, body, cacheDuration) - ctx.SetStatusCode(StatusOK) + ctx.SetStatusCode(statusCacheSucceed) return } else if ctx.IsDelete() { cs.remove(key) - ctx.SetStatusCode(StatusOK) + ctx.SetStatusCode(statusCacheSucceed) return } - ctx.SetStatusCode(StatusBadRequest) + ctx.SetStatusCode(statusCacheFailed) } return h diff --git a/http.go b/http.go index 0d0c5943..bc9a1934 100644 --- a/http.go +++ b/http.go @@ -1207,7 +1207,7 @@ func CERT(addr string, cert tls.Certificate) (net.Listener, error) { // LETSENCRYPT returns a new Automatic TLS Listener using letsencrypt.org service // receives two parameters, the first is the domain of the server // and the second is optionally, the cache file, if you skip it then the cache directory is "./letsencrypt.cache" -// if you want to disable cache file then simple give it a value of emtpy string "" +// if you want to disable cache file then simple give it a value of empty string "" // // supports localhost domains for testing, // but I recommend you to use the LETSENCRYPTPROD if you gonna to use it on production @@ -1243,7 +1243,7 @@ func LETSENCRYPT(addr string, cacheFileOptional ...string) (net.Listener, error) // LETSENCRYPTPROD returns a new Automatic TLS Listener using letsencrypt.org service // receives two parameters, the first is the domain of the server // and the second is optionally, the cache directory, if you skip it then the cache directory is "./certcache" -// if you want to disable cache directory then simple give it a value of emtpy string "" +// if you want to disable cache directory then simple give it a value of empty string "" // // does NOT supports localhost domains for testing, use LETSENCRYPT instead. // diff --git a/iris.go b/iris.go index 0d3e3418..d5742046 100644 --- a/iris.go +++ b/iris.go @@ -553,7 +553,7 @@ func (s *Framework) ListenTLS(addr string, certFile, keyFile string) { // it's also starts a second 'http' server to redirect all 'http://$ADDR_HOSTNAME:80' to the' https://$ADDR' // it creates a cache file to store the certifications, for performance reasons, this file by-default is "./letsencrypt.cache" // if you skip the second parameter then the cache file is "./letsencrypt.cache" -// if you want to disable cache then simple pass as second argument an empty emtpy string "" +// if you want to disable cache then simple pass as second argument an empty empty string "" // // example: https://github.com/iris-contrib/examples/blob/master/letsencyrpt/main.go // @@ -568,7 +568,7 @@ func ListenLETSENCRYPT(addr string, cacheFileOptional ...string) { // it's also starts a second 'http' server to redirect all 'http://$ADDR_HOSTNAME:80' to the' https://$ADDR' // it creates a cache file to store the certifications, for performance reasons, this file by-default is "./letsencrypt.cache" // if you skip the second parameter then the cache file is "./letsencrypt.cache" -// if you want to disable cache then simple pass as second argument an empty emtpy string "" +// if you want to disable cache then simple pass as second argument an empty empty string "" // // example: https://github.com/iris-contrib/examples/blob/master/letsencyrpt/main.go //