twisted学习笔记 No.2 WebServer
原创博文,转载请注明出处。
当服务器接收到一个客户端请求后,会创建一个请求对象并传递到资源系统,资源系统会根据请求路径分发到相应的资源对象,资源被要求渲染自身并返回结果到客户端。
解析HTTP Requests:
twisted.web.http.Request描述了一个HTTP request,我们可以从其中发现处理request的方法。
1 from twisted.internet import reactor
2 from twisted.web import http
3
4 class MyRequestHandler(http.Request):
5 resources={
6 '/':'<h1>Home</h1>Home page',
7 '/about':'<h1>About</h1>All about me',
8 }
9 def process(self):
10 self.setHeader('Content-Type','text/html')
11 if self.resources.has_key(self.path):
12 self.write(self.resources[self.path])
13 else:
14 self.setResponseCode(http.NOT_FOUND)
15 self.write("<h1>Not Found</h1>Sorry, no such source")
16 self.finish()
17
18 class MyHTTP(http.HTTPChannel): #继承高级API http.HTTPChannel
19 requestFactory=MyRequestHandler
20
21 class MyHTTPFactory(http.HTTPFactory):
22 def buildProtocol(self,addr):
23 return MyHTTP()
24
25 reactor.listenTCP(8000,MyHTTPFactory())
26 reactor.run()
执行程序后,在浏览器输入http://localhost:8000/和http://localhost:8000/about 看看发生了什么吧
处理 GET request:
from twisted.web.server import Site
from twisted.web.static import File
利用Site,我们不在担心HTTP协议的细节问题,这是http.HTTPFactory的子类,可以管理HTTP会话并且把resources 分发给我们。
from twisted.internet import reactor
from twisted.web.server import Site
from twisted.web.static import File root = File('/var/www/mysite')
root.putChild("doc",File("/usr/share/doc"))
root.putChild("logs",File("/var/log/mysitelogs"))
factory=Site(root)
reactor.listenTCP(8000,factory)
reactor.run()
现在访问 http://localhost:8000/将会得到来自本地文件系统/var/www/mysite的内容回应,访问 localhost:8000/doc将会得到/usr/share/doc的内容回应,
访问localhost:8000/logs将会得到来自/var/log/mysitelogs的内容回应。本人测试在windows环境下尚且无法支持,留着以后再来研究。
提供动态内容:
与提供静态内容不同的是,你需要定义一个继承自Resource的子类去决定一个Site所能提供的内容。
from twisted.internet import reactor
from twisted.web.resource import Resource
from twisted.web.server import Site import time class ClockPage(Resource):
isLeaf=True
def render_GET(self,request):
return "The local time is %s"%(time.ctime(),) resource=ClockPage()
factory=Site(resource)
reactor.listenTCP(8000,factory)
reactor.run()
关于Resource的API文档:点击进入
我们需要定义render_GET render_POST render_HEAD等等“render_METHOD”(其中METHOD是HTTP做出请求的方法)
render_METHOD methods are expected to return a string which will be the rendered page, unless the return value is twisted.web.server.NOT_DONE_YET, in which case it is this class's responsibility to write the results to request.write(data), then call request.finish().
isleaf变量用来描述一个source是否拥有子类,如果设置为False,访问所有的URL将会产生404NO such resource
from twisted.internet import reactor
from twisted.web.resource import Resource,NoResource
from twisted.web.server import Site from calendar import calendar class YearPage(Resource):
def __init__(self,year):
Resource.__init__(self)
self.year=year def render_GET(self,request):
return "<html><body><pre>%s</pre></body></html>"%(calendar(self.year),) class CalendarHome(Resource):
def getChild(self,name,request):
if name=='':
return self
if name.isdigit():
return YearPage(int(name))
else:
return NoResource() def render_GET(self,request):
return "<html><body>Welcome to the calendar server!</body></html>" root=CalendarHome()
factory=Site(root)
reactor.listenTCP(8000,factory)
reactor.run()
本例示范了一个日历服务器,如输入http://localhost:8000/2012就可以显示2012全年的日历,
Redirects重定向:
from twisted.web.util import redirectTo
我们修改上例中CalendarHome
from twisted.web.util import redirectTo
from datetime import datetime def render_GET(self,request):
return redirectTo(datetime.now().year,request)
当我们访问http://localhost:8000/时,datetime.now().year就会作为参数链接在URL的后面即http://localhost:8000/2013
处理POST Requests:
from twisted.internet import reactor
from twisted.web.resource import Resource
from twisted.web.server import Site
import cgi class FormPage(Resource):
isLeaf=True
def render_GET(self,request):
return """
<html>
<body>
<form method="POST">
<input name="form-field" type="text"/>
<input type="submit"/>
</form>
</body>
</html>
""" def render_POST(self,request):
return """
<html>
<body>You submitted: %s</body>
</html>
"""%(cgi.escape(request.args["form-field"][0],)) #cgi.escape(s,[quote,])把在s中的“&”、“<”和“>”转化成HTML安全序列 使用request.args字典存取提交的HTML表单数据 factory=Site(FormPage())
reactor.listenTCP(8000,factory)
reactor.run()
异步处理:
如果发生了请求阻塞,这时候我们就应该使用异步处理方法。
先看一个例子:
from twisted.internet import reactor
from twisted.web.resource import Resource
from twisted.web.server import Site import time class BusyPage(Resource):
isLeaf=True
def render_GET(self,request):
time.sleep(5)
return "Finally done, at %s"%(time.asctime(),) factory=Site(BusyPage())
reactor.listenTCP(8000,factory)
reactor.run()
对于每一次请求我们等待5秒钟,加入我们在浏览器中打开多个标签并输入http://localhost:8000/,我们会发现服务器的回应是连续的,也就是说这几个回应所显示的时间依次相差5秒钟,第一个打开的页面和最后一个打开的页面相差N*5秒,这对于我们将是灾难性的。所以我们有必要进行异步处理。
我们看一下改进的程序:我们使用了deferred,在本例程中你可能会发现requests也是连续的,这是由于你所用的浏览器对于同一resource的请求连续。
# -*- coding: cp936 -*-
from twisted.internet import reactor
from twisted.internet.task import deferLater
from twisted.web.resource import Resource
from twisted.web.server import Site, NOT_DONE_YET import time class BusyPage(Resource):
isLeaf=True def _delayedRender(self,request):
request.write("Fianlly done, at %s"%(time.asctime(),))#渲染网页
request.finish() def render_GET(self,request):
d=deferLater(reactor,5,lambda:request)#返回一个由request引起的deferred
d.addCallback(self._delayedRender)
return NOT_DONE_YET#它告知Resource有些事情是异步的而且尚未完成,直到你调用了request.finish() factory =Site(BusyPage())
reactor.listenTCP(8000,factory)
reactor.run()
twisted学习笔记 No.2 WebServer的更多相关文章
- twisted学习笔记No.3 Web Clients
原创博文,转载请注明出处. 这一章我们学习利用twisted建立web 客户端. twisted.web.client.getPage用来异步下载一个页面,并且返回一个deferred from tw ...
- twisted学习笔记 No.1
原创博文,转载请注明出处 . 1.安装twisted ,然后安装PyOpenSSL(一个Python开源OpenSSL库),这个软件包用于给Twisted提供加密传输支持(SSL).最后,安装PyCr ...
- twisted学习笔记4 部署Twisted 应用程序
原创博文,转载请注明出处. Twisted是一个可扩展,跨平台的网络服务器和客户端引擎. Twisted Application 框架有五个主要基础部分组成:服务,应用程序,TAC文件插件和twist ...
- twisted 学习笔记二:创建一个简单TCP客户端
#coding=utf-8 from twisted.internet import reactor,protocol class QuickClient(protocol.Protocol): de ...
- twisted 学习笔记一:事件循环
from twisted.internet import reactor import time def printTime(): print "Current time is", ...
- 【Ext.Net学习笔记】01:在ASP.NET WebForm中使用Ext.Net
Ext.NET是基于跨浏览器的ExtJS库和.NET Framework的一套支持ASP.NET AJAX的开源Web控件,包含有丰富的Ajax运用,其前身是Coolite. 下载地址:http:// ...
- Ext.Net学习笔记01:在ASP.NET WebForm中使用Ext.Net
Ext.Net是一个对ExtJS进行封装了的.net控件库,可以在ASP.NET WebForm和MVC中使用.从今天开始记录我的学习笔记,这是第一篇,今天学习了如何在WebForm中使用Ext.Ne ...
- Visual Studio 2015 Owin+MVC+WebAPI+ODataV4+EntityFrawork+Identity+Oauth2.0+AngularJS 1.x 学习笔记
2016年,.net 会有很多大更新 ASP.NET 5 在此之前我都是用着古老的.net做开发的 (WebForm + IIS) 为了接下来应对 .net 的新功能,我特地去学习了一下基本的 MVC ...
- shell学习笔记
shell学习笔记 .查看/etc/shells,看看有几个可用的Shell . 曾经用过的命令存在.bash_history中,但是~/.bash_history记录的是前一次登录前记录的所有指令, ...
随机推荐
- sql小总结2
SQL NULL 值 如果表中的某个列是可选的,那么我们可以在不向该列添加值的情况下插入新记录或更新已有的记录.这意味着该字段将以 NULL 值保存. NULL 值的处理方式与其他值不同. NULL ...
- Kinect SDK C++ - 2. Kinect Depth Data
Today we will learn how to get depth data from a kinect and what the format of the data is kinect co ...
- c++双缓冲技术,以避免闪烁绘图
当数据量非常大时,画图可能须要几秒钟甚至更长的时间,并且有时还会出现闪烁现象,为了解决这些问题.可採用双缓冲技术来画图. 双缓冲即在内存中创建一个与屏幕画图区域一致的对象,先将图形绘制到内存中的这个对 ...
- ArcGIS网络分析之Silverlight客户端最近设施点分析(四)
原文:ArcGIS网络分析之Silverlight客户端最近设施点分析(四) 在上一篇中说了如何实现最近路径分析,本篇将讨论如何实现最近设施点分析. 最近设施点分析实际上和路径分析有些相识,实现的过程 ...
- hdu2203 KMP水的问题
两种方法 首先是纯KMP #include<stdio.h> #include<string.h> #include<iostream> using nam ...
- 拥抱大家庭,nodejs走thrift
拥抱大家庭,nodejs走thrift.最贱的例子,nodejs与nodejs之间走thrift对传. 1,官网下载 http://mirrors.cnnic.cn/apache/thrift/0.9 ...
- 关于linux 原始套接字编程
关于linux 网络编程最权威的书是<<unix网络编程>>,但是看这本书时有些内容你可能理解的不是很深刻,或者说只知其然而不知其所以然,那么如果你想搞懂的话那么我建议你可以看 ...
- SQL Server日志文件庞大收缩方法(实测好用)
原文:SQL Server日志文件庞大收缩方法(实测好用) 这两个命令连续执行,间隔时间越少越明显(可多次运行),直到达到效果 --截断 BACKUP LOG CloudMonitor TO DISK ...
- 设计模式组合模式(Composite)精华
23种子GOF设计模式一般分为三类:创建模式.结构模型.行为模式. 创建模式抽象的实例,他们帮助如何创建一个系统独立.这是一个这些对象和陈述的组合. 创建使用继承类的类架构更改实例.的对象类型模型的建 ...
- 枚举 UIButton补充
一.URL 1.什么是URL? URL是某个资源的唯一路径,通过这个路径就能访问对应的资源 2.URL的组成 协议头://全路径 * 协议头就代表资源的类型,比如http代表网络服务器资源,ftp代表 ...