使用浏览器资源url强制浏览器更新其缓存的操作

falkolab.cacheburster的Python项目详细描述


这个包提供了新的灵活的ZCML指令来插入一个由 内容版本信息(hash、crc32或versionfile)到资源的url中, 因此,每当内容改变时,url就会改变,从而迫使浏览器 更新其缓存。

Zope 3/Bluebream的缓存burster

此包包含iversionedresourcelayer层。此层支持 一组正确的组件注册,可用于 定制皮肤。

测试

为了测试缓存burster,我们使用测试中定义的测试皮肤 使用iversionedResourceLayer层作为唯一基础层的包。 这意味着,我们的测试皮肤只提供 包及其在测试中定义的测试视图。

首先以管理员身份登录:

>>> from zope.testbrowser.testing import Browser
>>> browser = Browser()
>>> browser.addHeader('Authorization', 'Basic mgr:mgrpw')

我们的页面模板文件如下:

>>> print getTemplateContent('page.pt')
<html><head>
<script type="text/javascript" src="script.js"
tal:attributes="src context/++resource++script.js"></script>
<BLANKLINE>
<script type="text/javascript" src="one-module.css"
tal:attributes="src context/++resource++one-module.css"></script>
</head>
<body></body>
</html>

我们有page.html视图,它注册在 ftesting.zcml用于测试的皮肤文件:

>>> browser.open('http://localhost/page.html')
>>> browser.url
'http://localhost/page.html'

渲染视图:

>>> print browser.contents
<html><head>
<script type="text/javascript"
        src="http://localhost/@@/script.js"></script>
<BLANKLINE>
<script type="text/javascript"
        src="http://localhost/@@/one-module.css"></script>
</head>
<body></body>
</html>

一切都没变,好吧。

缓存burster规则

现在我们注册cache burster规则:

>>> from zope.configuration import xmlconfig
>>> import falkolab.cacheburster
>>> context = xmlconfig.file('meta.zcml', falkolab.cacheburster)
>>> def zcml(s, context):
...     return xmlconfig.string(s, context)
>>> context = zcml(r"""
...    <configure
...        xmlns="http://namespaces.zope.org/browser"
...        >
...
...      <cacheburster
...          from="(script).js"
...          to="\1.{version}.js"
...          fileset="tests/testfiles/*.js"
...          />
...
...    </configure>
... """, context)

好的。再次呈现页面:

>>> browser.open('http://localhost/page.html')
>>> print browser.contents
<html><head>
<script type="text/javascript"
        src="http://localhost/@@/script.8dc15d98.js"></script>
<BLANKLINE>
<script type="text/javascript"
        src="http://localhost/@@/one-module.css"></script>
</head>
<body></body>
</html>

cacheburster指令fromto字段使用python re语法。 类似于re.sub(from,to,resourcename) 我们可以指定from=“(.*.js”。这意味着这条规则被所有人接受了 以.js结尾的资源。

测试资源url是否可访问:

>>> browser.open('http://localhost/@@/script.8dc15d98.js')
>>> print browser.contents
alert('script.js');

添加下一条规则:

>>> context = zcml(r"""
...    <configure
...        xmlns="http://namespaces.zope.org/browser"
...        >
...
...      <cacheburster
...          from="(.*)-module.css"
...          to="\1-module.css?{version}"
...          manager="md5"
...          />
...
...    </configure>
... """, context)

再次呈现页面:

>>> browser.open('http://localhost/page.html')
>>> print browser.contents
<html><head>
<script type="text/javascript"
        src="http://localhost/@@/script.8dc15d98.js"></script>
<BLANKLINE>
<script type="text/javascript"
        src="http://localhost/@@/one-module.css?c25661cc824732136e9ec697d97afaed"></script>
</head>
<body></body>
</html>

测试资源url是否可访问:

>>> browser.open('http://localhost/@@/one-module.css?579d7fcdc5acc3fe9f063020b2f573cf')
>>> print browser.contents
body {background:#ffffff;}

没有文件资源

注册资源和规则:

>>> import zope.browserresource
>>> context = xmlconfig.file('meta.zcml', zope.browserresource, context)
>>> context = zcml(r"""
...    <configure
...        xmlns="http://namespaces.zope.org/browser"
...        >
...    <resource
...       name="nofile"
...       factory="falkolab.cacheburster.testing.NoFileResourceFactory"
...       layer="falkolab.cacheburster.interfaces.IVersionedResourceLayer"
...       />
...
...      <cacheburster
...          from="nofile"
...          to="{version}.nofile"
...          />
...
...    </configure>
... """, context)
>>> browser.open('http://localhost/page2.html')
>>> print browser.contents
<html><head>
<script type="text/javascript"
        src="http://localhost/@@/fdd9b757.nofile"></script>
</head>
<body></body>
</html>

测试资源url是否可访问:

>>> browser.open('http://localhost/@@/fdd9b757.nofile')
>>> print browser.contents
no file resource body

资源目录

>>> context = zcml(r"""
...    <configure
...        xmlns="http://namespaces.zope.org/browser"
...        >
...    <resourceDirectory
...       name="resources"
...       directory="tests/testfiles"
...       layer="falkolab.cacheburster.interfaces.IVersionedResourceLayer"
...       />
...    </configure>
... """, context)

现在我们在resourcedirectory:

中测试资源url
>>> resourceDir = zope.component.getAdapter(request, name='resources')
>>> resourceDir['script.js']()
'http://127.0.0.1/@@/resources/script.js'
>>> resourceDir['one-module.css']()
'http://127.0.0.1/@@/resources/one-module.css?c25661cc824732136e9ec697d97afaed'

我们可以看到(script.js(.*)-module.css之间的规则匹配差异。 测试资源url是否可访问:

>>> browser.open('http://localhost/@@/resources/one-module.css?c25661cc824732136e9ec697d97afaed')
>>> print browser.contents
body {background:#ffffff;}

文件版本管理器

创建文件管理器并将其注册为版本文件

>>> import os, tempfile
>>> temp_dir = tempfile.mkdtemp()
>>> pathToVersionFile = os.path.join(temp_dir, 'version.txt')
>>> open(pathToVersionFile, 'w').write("1")
>>> from zope.browserresource.interfaces import IResource
>>> manager = falkolab.cacheburster.version.FileVersionManager(pathToVersionFile)
>>> zope.component.provideAdapter(manager,
...     (zope.browserresource.interfaces.IResource,
...     falkolab.cacheburster.interfaces.IVersionedResourceLayer),
... falkolab.cacheburster.interfaces.IVersionManager, name='versionfile')

添加规则:

>>> context = zcml(r"""
...    <configure
...        xmlns="http://namespaces.zope.org/browser"
...        >
...
...      <cacheburster
...          from="(.*).pack"
...          to="\1.{version}"
...          fileset="tests/testfiles/*.pack"
...          manager="versionfile"
...          />
...
...    </configure>
... """, context)

查看页面:

>>> print getTemplateContent('page3.pt')
<html><head>
<script type="text/javascript" src="any_script.pack"
tal:attributes="src context/++resource++any_script.pack"></script>
</head>
<body></body>
</html>

渲染页:

>>> browser.open('http://localhost/page3.html')
>>> print browser.contents
<html><head>
<script type="text/javascript"
        src="http://localhost/@@/any_script.1"></script>
</head>
<body></body>
</html>

清理

>>> import shutil
>>> shutil.rmtree(temp_dir)

更改

0.1.5(2010-12-17)

  • 添加了路径规范化,以便a//b、a/b/、a//b和a/foo//b都成为a/b。

0.1.4(2010-12-07)

  • 修复资源目录中的直接调用资源

0.1.3(2010-11-23)

  • 资源目录支持

0.1.2(2010-11-21)

  • 对manifest.in的更改

0.1.1(2010-11-19)

  • 包裹坏了。添加readme.txt的更改

0.1.0(2010-11-16)

  • 初次发布。

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
java Getting“类型不匹配:在实例化映射列表时,无法将ArrayList<HashMap<String,String>>转换为List<Map<String,String>>”   java如何将ArrayList传输到安卓中的其他活动?   使用bouncy castle作为加密提供程序和GCM、cipherOutputStream时使用java。close()似乎没有抛出invalidCipherTextException   将自定义库导出到可导入jar文件java   java如何在队列中使用异常   JAVA木卫一。FileNotFoundException。正在尝试传入参数[0]   java使用自定义构造函数将JsonNode转换为POJO   由于无限循环,java Netbeans自动生成的GUI未显示。。。但我需要那个环   运行时从另一个Java cosole应用程序运行Java控制台应用程序   java在安卓中播放彩信wmv视频   web服务在Java中创建和发送SOAP消息   ReactJS&Java:对飞行前请求的响应未通过访问控制检查   java如何在安卓中使用PRDownloader恢复下载文件?   java为什么openFd(文件名)不能使用字符串?