Tornado源码分析 --- Etag实现
Etag(URL的Entity Tag):
对于具体Etag是什么,请求流程,实现原理,这里不进行介绍,可以参考下面链接:
http://www.oschina.net/question/234345_42536?sort=time
https://zh.wikipedia.org/wiki/HTTP_ETag
Tornado实现分析:
先从Tornado处理一个请求的调用顺序开始看(摘自文档:http://www.tornadoweb.cn/documentation):
- 程序为每一个请求创建一个 RequestHandler 对象
- 程序调用
initialize()函数,这个函数的参数是Application配置中的关键字 参数定义。(initialize方法是 Tornado 1.1 中新添加的,旧版本中你需要 重写__init__以达到同样的目的)initialize方法一般只是把传入的参数存 到成员变量中,而不会产生一些输出或者调用像send_error之类的方法。 - 程序调用
prepare()。无论使用了哪种 HTTP 方法,prepare都会被调用到,因此 这个方法通常会被定义在一个基类中,然后在子类中重用。prepare可以产生输出 信息。如果它调用了finish(或send_error` 等函数),那么整个处理流程 就此结束。 - 程序调用某个 HTTP 方法:例如
get()、post()、put()等。如果 URL 的正则表达式模式中有分组匹配,那么相关匹配会作为参数传入方法。
在一个请求结束的时候肯定会进行Etag的处理,所以找到调用的 finish() 函数:
finish() 函数 ---- 地址:tornado/web.py(删除了部分不在此主题的代码)
def finish(self, chunk=None):
# Automatically support ETags and add the Content-Length header if
# we have not flushed any content yet.
if not self._headers_written:
if (self._status_code == 200 and
self.request.method in ("GET", "HEAD") and
"Etag" not in self._headers):
self.set_etag_header()
if self.check_etag_header():
self._write_buffer = []
self.set_status(304)
if self._status_code in (204, 304):
assert not self._write_buffer, "Cannot send body with %s" % self._status_code
self._clear_headers_for_304()
elif "Content-Length" not in self._headers:
content_length = sum(len(part) for part in self._write_buffer)
self.set_header("Content-Length", content_length)
分析:
在调用 finish() 函数的时候,对HTTP请求进行判断,如果 状态码为200,请求的方法为 GET 或 HEAD,并且 Etag 不在HTTP头信息里面,则说明该请求是第一次发生。接下来,调用 set_etag_header() 函数,将 etag 写入到 header头信息中
set_etag_header() 函数 ---- 地址:tornado/web.py
def set_etag_header(self):
etag = self.compute_etag()
if etag is not None:
self.set_header("Etag", etag)
分析:
接着调用 compute_etag() 函数生成 etag,如果返回成功,则调用 set_header() 函数将 etag 写入header头信息的 “Etag” 字段。查看 compute_etag() 函数:
compute_etag() 函数 ---- 地址:tornado/web.py
def compute_etag(self):
hasher = hashlib.sha1()
for part in self._write_buffer:
hasher.update(part)
return '"%s"' % hasher.hexdigest()
分析:
这里通过 调用 hashlib库 生成相应的 etag,然后通过对于 self._write_buffer的循环,当服务端文件有改变的时候,调用hashlib中的 update() 函数更新生成的新的对象 hasher,从而返回最新的 etag
注:self._write_buffer在初始化的时候已经进行了定义 self._write_buffer = [ ], 如果某一个页面有改变,则会进行记录,从而来判断是否客户端请求的页面在服务端是否有改变
这里对于 etag 的生成函数 set_etag_header() 函数已经介绍完了,接着进行 check_etag_header() 校验函数的分析:
check_etag_header() 校验函数 ---- 地址:tornado/web.py
def check_etag_header(self):
etags = re.findall(
br'\*|(?:W/)?"[^"]*"',
utf8(self.request.headers.get("If-None-Match", ""))
)
if not computed_etag or not etags:
return False match = False
if etags[0] == b'*':
match = True
else:
# Use a weak comparison when comparing entity-tags.
def val(x):
return x[2:] if x.startswith(b'W/') else x for etag in etags:
if val(etag) == val(computed_etag):
match = True
break
return match
分析:
首先服务端获取 客户端发送过来的 header头信息 中的 “If-None-Match” 字段,拿到该 etag,并通过正则表达式匹配,查看是否跟服务端保存的etag相同。如果 没有获取到header头信息中的 etag字段或跟服务端etag不匹配,则返回 False,否认返回 True。
之后,如果该 check_etag_header() 函数 返回True 的话, 则说明,该请求中包含有该 etag 并且该etag和服务端保存的相同,接下来t通过 self._write_buffer = [ ] 对这个字段进行清空处理(表明该请求的页面暂时没有任何修改), 并且返回 状态码304 给客户端。
Tornado源码分析 --- Etag实现的更多相关文章
- Tornado源码分析 --- 静态文件处理模块
每个web框架都会有对静态文件的处理支持,下面对于Tornado的静态文件的处理模块的源码进行分析,以加强自己对静态文件处理的理解. 先从Tornado的主要模块 web.py 入手,可以看到在App ...
- tornado源码分析-iostream
tornado源码分析-iostream 1.iostream.py作用 用来异步读写文件,socket通信 2.使用示例 import tornado.ioloop import tornado.i ...
- Tornado源码分析系列之一: 化异步为'同步'的Future和gen.coroutine
转自:http://blog.nathon.wang/2015/06/24/tornado-source-insight-01-gen/ 用Tornado也有一段时间,Tornado的文档还是比较匮乏 ...
- Tornado源码分析 --- Cookie和XSRF机制
Cookie和Session的理解: 具体Cookie的介绍,可以参考:HTTP Cookie详解 可以先查看之前的一篇文章:Tornado的Cookie过期问题 XSRF跨域请求伪造(Cross-S ...
- Tornado源码分析 --- Redirect重定向
“重定向”简单介绍: “重定向”指的是HTTP重定向,是HTTP协议的一种机制.当client向server发送一个请求,要求获取一个资源时,在server接收到这个请求后发现请求的这个资源实际存放在 ...
- Tornado源码分析之http服务器篇
转载自 http://kenby.iteye.com/blog/1159621 一. Tornado是什么? Facebook发布了开源网络服务器框架Tornado,该平台基于Facebook刚刚收购 ...
- tornado源码分析系列一
先来看一个简单的示例: #!/usr/bin/env python #coding:utf8 import socket def run(): sock = socket.socket(socket. ...
- tornado源码分析
初识tornado 首先从经典的helloword案例入手 import tornado.ioloop import tornado.web class MainHandler(tornado.web ...
- tornado源码分析-多进程
1.源码文件 process.py 2.fork子进程 def fork_processes(num_processes, max_restarts=100): ... def start_child ...
随机推荐
- Django - 常用配置
一.logging配置 Django项目常用的logging配置 settings.py LOGGING = { 'version': 1, 'disable_existing_loggers': F ...
- IDEA安装以及项目初始化
首先安装idea: 如果15.0版本安装不上就安装16.0: 点击安装文件以后,一直点下一步就可以了. 安装完成后设置: 如果没有的话,需要点击SDKs,点击+,然后选择电脑上安装的JDK. 接下来创 ...
- OC如何跳到系统设置里的各种设置界面
当 iOS系统版本 <= iOS7时 , 只能跳转到 系统设置页面 ,楼主试了下,非真机是没有任何效果的 当iOS系统版本 < iOS 10.0 时 NSURL *url= [NSURL ...
- MySQL不能启动 Can't start server : Bind on unix socke
MySQL服务器突然不能启动,查看最后的启动日志如下: 080825 09:38:04 mysqld started080825 9:38:04 [ERROR] Can't start server ...
- Java压缩多个文件并导出
controller层: /** * 打包压缩下载文件 */ @RequestMapping(value = "/downLoadZipFile") public void dow ...
- [py]python中__new__作用
元类metaclass 使劲搞,但是没搞清楚__new__的作用 了解Python元类 Python进阶:一步步理解Python中的元类metaclass Python中的__new__和__init ...
- Java模板模式
模板类 package com.ietree.designpattern.template; /** * 模板类 * * @author Root */ public abstract class S ...
- Winform开发之ComboBox和ComboBoxEdit控件绑定key/value数据
使用 ComboBox 控件绑定key/value值: 因为 ComboBox 是有 DataSource 属性的,所以它可以直接绑定数据源,如 DataTable.ListItem 等. 使用 Da ...
- 文件上传—SSM框架文件上传
1.准备上传下载的api组件 <dependency> <groupId>commons-io</groupId> <artifactId>common ...
- MOPSO 多目标粒子群优化算法
近年来,基于启发式的多目标优化技术得到了很大的发展,研究表明该技术比经典方法更实用和高效.有代表性的多目标优化算法主要有NSGA.NSGA-II.SPEA.SPEA2.PAES和PESA等.粒子群优化 ...