缓存资源插件不工作? [英] Cached-resources plugin is not working?

查看:83
本文介绍了缓存资源插件不工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在我的Grails项目中使用了缓存资源插件,但是每次使用F5刷新页面时,它都会使用http响应代码200而不是304来重新加载资源。我错过了什么?


<通过覆盖 cached-resources-1.0 cache-headers-1.1.5 中的一些方法解决了这个问题。 >插件。


查看他的插件。

cache-headers 插件的 CacheHeadersService 处付费, void cache(response,Map args)方法,而不是动态添加 void cache(req,response,Map args)方法(请参见下面的类)如果资源被浏览器缓存,请发送304.

缓存资源插件中的 HashAndCacheResourceMapper 插件,方法 def map (resource,config),我重写使用 CacheHeadersService 中的ne方法。



在BootStrap运行方法 void cacheResources(GrailsApplication应用程序),将更改应用于您的项目。

 类CustomCachedResourcesProcessor {

public static void cacheResources(GrailsApplication application){
addMethodsToMapResources(application)
application.mainContext.grailsResource Processor.reloadAll()
}

private static void addMethodsToMapResources(GrailsApplication application){
addCacheMethod()
application.getClassForName(org.grails.plugin.cachedresources .HashAndCacheResourceMapper)。metaClass.map {resource,config->
if(log.debugEnabled){
log.debug将资源散列到唯一名称...
}

resource.processedFile = renameToHashOfContents(resource.processedFile ,resource.processedFileExtension)
resource.updateActualUrlFromProcessedFile()

//完成所有可怕的缓存头文件
resource.requestProcessors<< {req,resp - >
if(log.debugEnabled){
log.debug在$ {req.requestURI}上设置缓存标题
}
cacheHeadersService.cache(req,resp,[neverExpires: )



$ private static void addCacheMethod(){
CacheHeadersService.metaClass.cache {request,response,true,shared:true] ,Map args->
if(!enabled){
return
}
def store = args.store
def share = args.shared
def validFor = args.validFor
def validUntil = args.validUntil
def neverExpires = args.neverExpires
def requiresAuth = args.auth

def now = new Date()

def expiresOn
def maxage
if(validFor!= null){
expiresOn = new Date(now.time + validFor * 1000L)
maxage = Math.max( 0,validFor)
} else if(validUntil!= null){
expiresOn = validUntil
maxage = Math.round(Math.max(0,validUntil.time-now.time)/ 1000L)
} else if(neverExpires){
// HTTP 1.1规范说明不应该在将来设置超过1年
// @todo调查servletresponse.setDateHeader()的impls是使用高效的threadlocals,
//和if所以改为使用这些
expiresOn = now + 365
maxage = Math.round(Math.max(0,expiresOn.time-now.time)/ 1000L)
}

def cacheControl = []

//现在设置标题
if((store!= null)&& !store){
cacheControl<< 'no-store'
}

//如果没有显式的共享,总是将其设置为private - 通过默认最安全的方式帮助grails开发人员
if(share){
cacheControl< ;< 'public'
//注意,对于验证网站,我们仍然需要添加no-cache来强制验证
//如果应用程序处理etag / lastmod $ b $,应用程序可以返回未修改 b if(requiresAuth){
cacheControl<< 'no-cache'
}
} else {
cacheControl<< 'private'
}

if(maxage!= null){
if(share){
cacheControl< s-maxage = $ maxage
}
//总是设置max-age,即使共享。浏览器可能无法启动s-maxage
cacheControl<< max-age = $ maxage
}

if(cacheControl){
response.setHeader('Cache-Control',cacheControl.join(','))


if(expiresOn!= null){
response.setDateHeader('Expires',expiresOn.time)
}

def
def modifiedDate = -1
try {
modifiedDate = request.getDateHeader('If-Modified-Since')
} catch(IllegalArgumentException iae){
log.error(Could not parse If-Modified-Since header,iae)
}

def lastModChanged = false

if(possibleTags ||(modifiedDate!= -1)){
if(modifiedDate!= -1){
def compareDate = new Date(modifiedDate)
if (compareDate> now){
lastModChanged = true
}
}
$ b $ if(!lastModChanged){
response.sendError(304)//未修改
返回false
}
}

//总是设置最后一次修改以供礼貌和旧客户使用,
//仅当应用程序尚未设置时(负载均衡需要相同的lastmods)
if(!response.containsHeader('Last-Modified ')){
lastModified(response,now)
}
}
}
}

让我知道您对此有何看法。


I'm using cached-resources plugin in my Grails project, but every time I refresh page with F5 it reloads resources with http response code 200 instead of 304. Have I missed something?

解决方案

Solved this problem by overriding some methods in cached-resources-1.0 and cache-headers-1.1.5 plugins.

Take a look at his plugins.
Pay attantion at CacheHeadersService in cache-headers plugin, void cache(response, Map args) method, instead of it I add dynamicly void cache(req,response, Map args) method (see the class below) wich looks at request headers and send 304 if resource is cached by browser.
And also HashAndCacheResourceMapper in cached-resources plugin, method def map(resource, config) wich I override to use my ne method from CacheHeadersService.

In BootStrap run method void cacheResources(GrailsApplication application) to apply changes to your project.

class CustomCachedResourcesProcessor {

public static void cacheResources(GrailsApplication application){
    addMethodsToMapResources(application)
    application.mainContext.grailsResourceProcessor.reloadAll()
}

private static void addMethodsToMapResources(GrailsApplication application){
    addCacheMethod()
    application.getClassForName("org.grails.plugin.cachedresources.HashAndCacheResourceMapper").metaClass.map{resource, config->
        if (log.debugEnabled) {
            log.debug "Hashing resources to unique names..."
        }

        resource.processedFile = renameToHashOfContents(resource.processedFile, resource.processedFileExtension)
        resource.updateActualUrlFromProcessedFile()

        // Do all the horrible cache header stuff
        resource.requestProcessors << { req, resp ->
            if (log.debugEnabled) {
                log.debug "Setting caching headers on ${req.requestURI}"
            }
            cacheHeadersService.cache(req,resp, [neverExpires: true, shared: true])
        }
    }
}

private static void addCacheMethod(){
    CacheHeadersService.metaClass.cache{request,response, Map args->
        if (!enabled) {
            return
        }
        def store = args.store
        def share = args.shared
        def validFor = args.validFor
        def validUntil = args.validUntil
        def neverExpires = args.neverExpires
        def requiresAuth = args.auth

        def now = new Date()

        def expiresOn
        def maxage
        if (validFor != null) {
            expiresOn = new Date(now.time + validFor*1000L)
            maxage = Math.max(0, validFor)
        } else if (validUntil != null) {
            expiresOn = validUntil
            maxage = Math.round( Math.max(0, validUntil.time-now.time) / 1000L)
        } else if (neverExpires) {
            // HTTP 1.1 spec says SHOULD NOT set more than 1 yr in future
            // @todo Investigate if impls of servletresponse.setDateHeader() are using efficient threadlocals,
            // and if so change to use those
            expiresOn = now + 365
            maxage = Math.round( Math.max(0, expiresOn.time-now.time) / 1000L)
        }

        def cacheControl = []

        // Now set the headers
        if ((store != null) && !store) {
            cacheControl << 'no-store'
        }

        // Always set private if no explicit share - help grails devs by defaulting to safest
        if (share) {
            cacheControl << 'public'
            // Note, for authentication sites we still need to add no-cache to force verification
            // to which the app can return "not modified" if it handles etag/lastmod
            if (requiresAuth) {
                cacheControl <<  'no-cache'
            }
        } else {
            cacheControl << 'private'
        }

        if (maxage != null) {
            if (share) {
                cacheControl << "s-maxage=$maxage"
            }
            // Always set max-age anyway, even if shared. Browsers may not pick up on s-maxage
            cacheControl << "max-age=$maxage"
        }

        if (cacheControl) {
            response.setHeader('Cache-Control', cacheControl.join(', '))
        }

        if (expiresOn != null) {
            response.setDateHeader('Expires', expiresOn.time)
        }

        def possibleTags = request.getHeader('If-None-Match')
        def modifiedDate = -1
        try {
            modifiedDate = request.getDateHeader('If-Modified-Since')
        } catch (IllegalArgumentException iae) {
            log.error ("Couldn't parse If-Modified-Since header", iae)
        }

        def lastModChanged = false

        if (possibleTags || (modifiedDate != -1)) {
            if (modifiedDate != -1) {
                def compareDate = new Date(modifiedDate)
                if (compareDate > now) {
                    lastModChanged = true
                }
            }

            if (!lastModChanged) {
                response.sendError(304) // Not modified
                return false
            }
        }

        // Always set last modified for courtesy and older clients,
        // only if not already set by application (load balancers need identical lastmods)
        if (!response.containsHeader('Last-Modified')) {
            lastModified(response, now)
        }
    }
  }
}

Let me know what do you think about it.

这篇关于缓存资源插件不工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆