熬着熬着,让时间熬成想要的那个自己,一个美丽的人。
分类: Python/Ruby
2014-01-09 18:08:48
这章节将会谈论下Twisted Web中的HTTP client,从一次性应用程序的快速web资源检索到Agent API开发的弹性web client。
基本HTTP资源检索
Twisted有几个高层工具类进行快速一次性资源检索。
输出一个web资源
Twisted.web.client.getPage异步地检索一个给定URL的资源。它返回一个Deferred,触发callback回调一个字符串资源。Example 5-1 强调了getPage的应用,检索并打印出用户提供的URL的资源。
除了名字,getPage能生成任何HTTP请求类型。用getPage产生一个HTTP的POST请求,提供方法和前数据关键词参数:比如,getPage(sys.argv[1], method=’POST’, postdata=’My test data’)。
getPage也提供了运用cookies信息记录, 后重定向,改变请求的用户代理。
下载一个Web 资源
Twisted.web.client.downloadPage 异步的下载给定的URL的资源到一个特定的文件。Example 5-2 强调了getPage的应用。
我们可以如下测试:
python download_resource.py
会把Google的主页保存到文件google.html里面
Agent
getPage和downloadPage对获得较小的工作量来说还蛮适合,但是对主要的Twisted HTTP 的client API来说,还是得需要Agent,因为需要弹性可扩展的来支持一个广分布的RFC-compliant 行为。
请求Agent资源
Example 5-3 运用Agent API实现了跟Example5-1 中的print_resource.py 一样的功能。
Agent版本需要更多一点的工作量,但是它具有多用途的。我们来分解一下触发步骤:
1. 初始化一个twiste.web.client.Agent实例。因为agent处理连接环节,必须跟reactor一起初始化。
2. 运用agent的请求方法生成一个HTTP请求,至少需要HTTP方法和URL两个参数。如果成功agent.request会返回一个Deferred来触发一个封装了对请求予以回应的Response对象。
3. 注册一个有agent.request返回的Deferred的回调来处理Response主体,等response.deliverBody可用时。因为回应是通过成块在网络传输,我们需要Protocol来处理接收到的数据并在主体已经完全传输完后通知我们。
为打成目标,我们创建了一个Protocol的子类并命名为ResourcePrinter,跟我们第二章构建基本的TCP server和client一样。不同之处在于我们想要在ResourcePrinter之外还能继续处理事件。通往外部的连接会是一个Deferred并在初始化时被传给ResourcePrinter实例,在连接中断时触发。这个Deferred有printResource创建并返回,因此更多的回调能够被记录进行额外的处理。伴随着回应主体块到达,reactor唤醒dataReceived,我们输出数据到屏幕。Reactor触发了connectionLost,我们就触发Deferred。
4. 一旦连接终止,reactor就停止。为达到这个目的,我们注册了一个Deferred的停止函数来回调,由connectionLost来触发,由printResource来返回。重回addBoth注册的同一个函数给callback和errback链,因此reactor不管下载是否成功都会停止。
5. 最后,运行reactor来关闭HTTP请求。
运行这个例子,python agent_print_resource.py 处理结果跟Example5-1一样。
检索响应元数据
Agent支持所有HTTP方法和任意的HTTP首部。Example 5-4 强调了HTTP 首部请求的功能。
Deferred中的Response对象由agent.request返回,包含大量有用HTTP响应元数据,包括HTTP状态码,HTTP版本以及首部。
Example5-4也强调了抽象信息。
用一个URL测试这个脚本:python print_metadata.py
结果:
HTTP version: ('HTTP', 1, 1)
Status code: 302
Status phrase: Found
Response headers:
Alternate-Protocol ['80:quic']
Content-Length ['376']
X-Xss-Protection ['1; mode=block']
Set-Cookie ['PREF=ID=879d0e073388fc22:FF=0:NW=1:TM=1389252277:LM=1389252277:S=K3ZbvVInZeLAdlWV; expires=Sat, 09-Jan-2016 07:24:37 GMT; path=/; domain=.google.com']
Server ['gws']
Location ['']
Cache-Control ['private']
Date ['Thu, 09 Jan 2014 07:24:37 GMT']
X-Frame-Options ['SAMEORIGIN']
Content-Type ['text/html; charset=UTF-8']
用Agent提交数据
用Agent提交HTTP数据,我们需要构建一个生产商来创建IBodyProducer接口,在Agent需要的时候产生POST 数据。
注:即使进程以不同的速率产生并消耗,生产者/消费者设计模式设施就有可能大量以一种方式流向内存和cpu效率。 你可以参阅跟多关于Twisted的生产/消耗API。
IBodyProducer接口是由Twisted的zope.interface.implements实施,必须实现下面的几个方法,必须一个长度属性来跟踪生产商最终会产生的数据长度:
l startProducing
l stopProducing
l pauseProducing
l resumeProducing
比如,我们可以构建一个简单的StringProducer,当startProducing被触发的时候输出POST数据给等待的消耗者。StringProducer作为bodyProducer的参数被传给agent.request。
测试这个例子我们需要用一个URL接收POST请求。不是一个好的测试例子,因为运行: python post_data.py 'Hello,worl!'
结果如下:
The request method POST
is inappropriate for the URL /
. That’s all we know.
通过这个例子可知,能够简单的给一个基本的web server来提交数据是很有用的。当然,我们前面的章节可以修改Twisted web server。
Python test_server.py 会启动web sever,监听8000端口。运行着server,我们可以从客户端测试了:python post_data.py 'Hello,world!'
结果:!dlrow,olleH
其他练习和下一步计划:
这个章节主要介绍了Twisted HTTP的客户端。高层的API getPagehe downloadPage能迅速简易检索资源。Agent是一个弹性可扩展的web client。
Twisted Web Client HOWTO详细介绍了Agent API,包括处理代理和cookies信息记录程序。
Twisted Web examples目录有大量HTTP client的例子。