1、Cache-Control
作用于浏览器端,可以用来设置缓存的max-age值(单位为秒)指定数据存活的时间。
import web
import datetime
urls = (
'/', 'Index',
)
app = web.application(urls, globals())
class Index:
def GET(self):
web.header('Cache-Control','max-age=30')
return datetime.datetime.now()
if __name__ == '__main__':
app.run()
2、Expires
过期时间,作用于浏览器。当浏览器的时间与服务器时间不同步时,有可能失效。
import web
import datetime
urls = (
'/', 'Index',
)
app = web.application(urls, globals())
class Index:
def GET(self):
#web.header('Cache-Control','max-age=30')
date_obj = datetime.datetime.utcnow() + datetime.timedelta(seconds=30)
date_str = date_obj.strftime("%a, %d %b %Y %H:%M:%S GMT")
web.header('Expires', date_str)
return datetime.datetime.now()
if __name__ == '__main__':
app.run()
3、Last-modified
某些情景下,人们不希望信息缓存在浏览器上固定的时间,反而期望这种方式——当信息更新时,去服务器上取信息,否则,本地返回。Last-Modified头信息帮我们做到了这一点。服务器使用304 Not Modified对未更新的数据进行状态标记。
import web
import datetime
import time
urls = (
'/', 'Index'
)
class Index:
def modified(self, cache_time, now):
last_time_str = web.ctx.env.get('HTTP_IF_MODIFIED_SINCE', '')
st = time.strptime(last_time_str, "%a, %d %b %Y %H:%M:%S %Z") if last_time_str else None
last_time = datetime.datetime(*st[0:6]) if st else None
if last_time and last_time + datetime.timedelta(seconds = cache_time) > now:
web.notmodified()
return False
else:
web.header('Last-Modified', now.strftime("%a, %d %b %Y %H:%M:%S GMT"))
return True
def GET(self):
cache_time = 30
now = datetime.datetime.now()
if self.modified(cache_time, now):
return now
app = web.application(urls, globals())
if __name__ == '__main__':
app.run()
4、Etag
Etag实现了与Last-modified相同的功能,只是用hash code替代了时间。需要注意的是,Etag 需要将字符串引号发送给服务器,形如ETag: "abcdefg"。
5、Compression
压缩响应数据可以有效降低服务器带宽压力。在请求中,我们使用Accept-encoding指定压缩方式——通常为gzip,deflate。
import datetime
import time
import web
import gzip
import cStringIO
urls = (
'/', 'Index'
)
app = web.application(urls, globals())
render = web.template.render('templates/')
class Index:
def c_gzip(self, data):
z_buf = cStringIO.StringIO()
with gzip.GzipFile(mode='wb', fileobj=z_buf, compresslevel=9) as z_file:
z_file.write(data)
gzip_data = z_buf.getvalue()
if len(gzip_data) < len(data):
web.header('Content-Encoding', 'gzip')
web.header('Content-Length', str(len(gzip_data)))
web.header('Vary', 'Accept-Encoding', unique=True)
data = gzip_data
return data
def GET(self):
data = str(render.index())
accept_ecoding = web.ctx.env.get('HTTP_ACCEPT_ENCODING', '')
if 'gzip' in accept_ecoding:
data = self.c_gzip(data)
return data
if __name__ == '__main__':
app.run()
6、Redirects
网站的重新架构或者网站服务器的改变都有可能改变某一资源的访问方式,这也就催生了重定向方案。
301 Moved Permanently:访问地址永久的被新地址替代了,客户端再次访问使用新地址,修改操作除外(POST/PUT/DELETE)。
302 Found:访问地址被新地址临时替代,客户端再次访问不使用新地址。
303 See Other:访问地址被新地址临时替代,客户端再次访问不使用新地址,但POST/PUT/DELETE请求被重定向。
307 Temporary Redirect:临时重定向,客户端再次访问使用旧的URL.
浏览器对302的实现比较混乱,我们应该尽量使用303或307替代使用。