原创博文,转载请注明出处

当服务器接收到一个客户端请求后,会创建一个请求对象并传递到资源系统,资源系统会根据请求路径分发到相应的资源对象,资源被要求渲染自身并返回结果到客户端。

解析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的更多相关文章

  1. twisted学习笔记No.3 Web Clients

    原创博文,转载请注明出处. 这一章我们学习利用twisted建立web 客户端. twisted.web.client.getPage用来异步下载一个页面,并且返回一个deferred from tw ...

  2. twisted学习笔记 No.1

    原创博文,转载请注明出处 . 1.安装twisted ,然后安装PyOpenSSL(一个Python开源OpenSSL库),这个软件包用于给Twisted提供加密传输支持(SSL).最后,安装PyCr ...

  3. twisted学习笔记4 部署Twisted 应用程序

    原创博文,转载请注明出处. Twisted是一个可扩展,跨平台的网络服务器和客户端引擎. Twisted Application 框架有五个主要基础部分组成:服务,应用程序,TAC文件插件和twist ...

  4. twisted 学习笔记二:创建一个简单TCP客户端

    #coding=utf-8 from twisted.internet import reactor,protocol class QuickClient(protocol.Protocol): de ...

  5. twisted 学习笔记一:事件循环

    from twisted.internet import reactor import time def printTime(): print "Current time is", ...

  6. 【Ext.Net学习笔记】01:在ASP.NET WebForm中使用Ext.Net

    Ext.NET是基于跨浏览器的ExtJS库和.NET Framework的一套支持ASP.NET AJAX的开源Web控件,包含有丰富的Ajax运用,其前身是Coolite. 下载地址:http:// ...

  7. Ext.Net学习笔记01:在ASP.NET WebForm中使用Ext.Net

    Ext.Net是一个对ExtJS进行封装了的.net控件库,可以在ASP.NET WebForm和MVC中使用.从今天开始记录我的学习笔记,这是第一篇,今天学习了如何在WebForm中使用Ext.Ne ...

  8. Visual Studio 2015 Owin+MVC+WebAPI+ODataV4+EntityFrawork+Identity+Oauth2.0+AngularJS 1.x 学习笔记

    2016年,.net 会有很多大更新 ASP.NET 5 在此之前我都是用着古老的.net做开发的 (WebForm + IIS) 为了接下来应对 .net 的新功能,我特地去学习了一下基本的 MVC ...

  9. shell学习笔记

    shell学习笔记 .查看/etc/shells,看看有几个可用的Shell . 曾经用过的命令存在.bash_history中,但是~/.bash_history记录的是前一次登录前记录的所有指令, ...

随机推荐

  1. .Net常用方法汇总

    //创建某个目录的文件夹 调用如下: var folder = initFolder(Export_Folder.Text, "ExportMembers"); private s ...

  2. (二)spring MVC配置

    使用Maven添加依赖的jar包 <!-- 自动扫描的包名 -->                                                 <mvc:reso ...

  3. 【LeetCode】 sort list 单清单归并

    称号:Sort a linked list in O(n log n) time using constant space complexity. 思路:要求时间复杂度O(nlogn) 知识点:归并排 ...

  4. Java中关于继承、类、多态、接口的知识点

    继承 含义:在面向对象编程中,可以通过扩展一个已有的类,并继承该类的属性和行为,来创建一个新的类 优点:1)代码的重用性:2)子类扩展父类的属性和方法:3)父类的属性和方法可用于子类:4)设计应用程序 ...

  5. 工作笔记3.手把手教你搭建SSH(struts2+hibernate+spring)环境

    上文中我们介绍<工作笔记2.软件开发经常使用工具> 从今天開始本文将教大家怎样进行开发?本文以搭建SSH(struts2+hibernate+spring)框架为例,共分为3步: 1)3个 ...

  6. sql语句查询列的说明

    SELECT C.name,value FROM sys.columns C INNER JOIN sys.tables T ON C.object_id = T.object_idINNER JOI ...

  7. Cassandra C++/NodeJs开发环境

    工作的需要,开始更多地倾向于去中心化的结构,目前看来Cassandra算是去中心化DB中性能/管理最热门的选择,崇尚其P2P的理念. 自身原因对JAVA不擅长(周围写C的好少),还是更热衷于C++/J ...

  8. nolock引发

      Sql Server之旅——终点站 nolock引发的三级事件的一些思考   曾今有件事情让我记忆犹新,那年刚来携程不久,马上就被安排写一个接口,供企鹅公司调用他们员工的差旅信息,然后我就三下五除 ...

  9. Oracle SQL in 超过1000 的解决方案

    处理 Oracle SQL in 超过1000 的解决方案 处理oracle sql 语句in子句中(where id in (1, 2, ..., 1000, 1001)),如果子句中超过1000项 ...

  10. CSS3 选择器读解

    文章资料来自于W3Cfuns CSS3.0 四个基本的结构性伪类选择器:root 此选择器将绑定到页面的根元素中,所谓根元素,是指文档树中最顶层的元素,也就是<html>部 分. < ...