我有一个服务于大量的静态内容的服务器。 该CherryPy的工具tools.gzip启用压缩每当支持gzip的内容的文件。
问:是的CherryPy gzip压缩的静态文件每次收到请求时,还是一次gzip压缩的内容和服务是gzip压缩的副本,所有的请求?
如果CherryPy的每收到请求时目前使用gzip压缩文件,就会使tools.caching防止这种情况,或是否有更好的办法?
我有一个服务于大量的静态内容的服务器。 该CherryPy的工具tools.gzip启用压缩每当支持gzip的内容的文件。
问:是的CherryPy gzip压缩的静态文件每次收到请求时,还是一次gzip压缩的内容和服务是gzip压缩的副本,所有的请求?
如果CherryPy的每收到请求时目前使用gzip压缩文件,就会使tools.caching防止这种情况,或是否有更好的办法?
首先,我想指出的是,尽管看似轻松的HTTP造成其巨大广泛的传播和每种语言的好客户端库的存在,HTTP,其实是一个复杂的协议,该协议涉及多个交互层。 缓存也不例外, RFC 2616第13节 。 以下是说过Last-Modified
/ If-Modified-Since
,因为ETag
用gzip荷兰国际集团是另一回事 。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import cherrypy
path = os.path.abspath(os.path.dirname(__file__))
config = {
'global' : {
'server.socket_host' : '127.0.0.1',
'server.socket_port' : 8080,
'server.thread_pool' : 8
},
'/static' : {
'tools.gzip.on' : True,
'tools.staticdir.on' : True,
'tools.staticdir.dir' : os.path.join(path, 'static')
}
}
if __name__ == '__main__':
cherrypy.quickstart(config = config)
然后把一些纯文本或HTML文件static
目录。
Firefox和铬不要在第一次请求发送缓存相关的头,即GET /static/some.html:
Accept-Encoding: gzip, deflate
Host: 127.0.0.1:8080
响应:
Accept-Ranges: bytes
Content-Encoding: gzip
Content-Length: 50950
Content-Type: text/html
Date: Mon, 15 Dec 2014 12:32:40 GMT
Last-Modified: Wed, 22 Jan 2014 09:22:27 GMT
Server: CherryPy/3.6.0
Vary: Accept-Encoding
在随后的请求,任何网络避免与以下缓存信息(萤火虫):
Data Size: 50950
Device: disk
Expires: Sat Jan 17 2015 05:39:41 GMT
Fetch Count: 6
Last Fetched: Mon Dec 15 2014 13:19:45 GMT
Last Modified: Mon Dec 15 2014 13:19:44 GMT
因为默认的CherryPy不提供有效期( Expires
或Cache-Control
),火狐(可能太铬)根据使用启发式RFC 2616第13.2.4节 :
如果没有到期,缓存控制:最大生存周期,或缓存控制:S-最大生存周期(见14.9.3)出现在响应,并且响应不包括高速缓存上的其他限制,高速缓存可以计算新鲜终身使用启发式...
此外,如果响应确实有上次修改时间,启发式过期值应不大于自该时刻的间隔的一些部分更。 这部分的典型设置可能是10%。
下面的代码,以证明启发式性质的Expires
值:
import email.utils
import datetime
s = 'Wed, 22 Jan 2014 09:22:27 GMT'
lm = datetime.datetime(*email.utils.parsedate(s)[0:6])
print datetime.datetime.utcnow() + (datetime.datetime.utcnow() - lm) / 10
当你刷新页面浏览器附加Cache-Control
请求:
Accept-Encoding: gzip,deflate
Cache-Control: max-age=0
Host: 127.0.0.1:8080
If-Modified-Since: Wed, 22 Jan 2014 09:22:27 GMT
CherryPy的回复304,如果该文件没有被更改不会被修改 。 下面是它如何工作的:
cherrypy.lib.static.serve_file
def serve_file(path, content_type=None, disposition=None, name=None, debug=False):
# ...
try:
st = os.stat(path)
except OSError:
if debug:
cherrypy.log('os.stat(%r) failed' % path, 'TOOLS.STATIC')
raise cherrypy.NotFound()
# ...
# Set the Last-Modified response header, so that
# modified-since validation code can work.
response.headers['Last-Modified'] = httputil.HTTPDate(st.st_mtime)
cptools.validate_since()
# ...
cherrypy.lib.cptools.validate_since
def validate_since():
"""Validate the current Last-Modified against If-Modified-Since headers.
If no code has set the Last-Modified response header, then no validation
will be performed.
"""
response = cherrypy.serving.response
lastmod = response.headers.get('Last-Modified')
if lastmod:
# ...
since = request.headers.get('If-Modified-Since')
if since and since == lastmod:
if (status >= 200 and status <= 299) or status == 304:
if request.method in ("GET", "HEAD"):
raise cherrypy.HTTPRedirect([], 304)
else:
raise cherrypy.HTTPError(412)
使用tools.staticdir
CherryPy的不发送文件内容,无论他们的gzip,对于提供有效的请求If-Modified-Since
头,但只有304没有修改要求的文件系统进行修改的时间响应。 而无需刷新它甚至不会收到请求,因为浏览器使用了过期时间的试探,当服务器不提供一个页面。 当然,使配置更加确定,它提供的缓存时间的生存不会受到伤害,如:
'/static' : {
'tools.gzip.on' : True,
'tools.staticdir.on' : True,
'tools.staticdir.dir' : os.path.join(path, 'static'),
'tools.expires.on' : True,
'tools.expires.secs' : 3600 # expire in an hour
}