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

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

解析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. 背包问题 (DP)

    利用记忆化数组.记dp[i][j]为根据rec的定义,从第i个物品开始挑选总重小于j时,总价值的最大值. 递推式: dp[i][j]=0     (j<w[i]) dp[i][j] dp[i][ ...

  2. React.js终探(七)(完)

    我们在前面介绍了组件的各种特性,这一节我们来说说多组件的情况. 在实际开发中,我们的组件难免会遇到有公共部分的情况,如果是个别情况还好,但如果数量比较多的话,那这时候,就需要公用了. 怎么公用呢? R ...

  3. 【翻译】C#和.NET核心快速参考

    原文:[翻译]C#和.NET核心快速参考 PS:在网上看到的一篇C#总结,英文的,总结的还可以,都是基础知识,翻译给大家学习.文章结尾有英文原版.发布地址:http://www.cnblogs.com ...

  4. Java 测试并行编程(三)

    有很多其他的交替运行 因为在并行代码中的错误一般是低概率事件.因此,试运行并发差错时需要反复多次,但是,有很多方法可以提高发现这些错误的概率 ,在前面提到的,在多处理器系统.假设 线程的数量,那么 与 ...

  5. Bag标签之中的一个行代码实行中文分词实例1

    例1: 分词(返回以逗号隔开的词组,gap=",") <bagid=pPage act=2words name=words gap=",">我喜欢黄 ...

  6. update与fixedupdate差别

    猴子原创,欢迎转载.转载请注明: 转载自Cocos2D开发网--Cocos2Dev.com,谢谢! 原文地址: http://www.cocos2dev.com/?p=307 今天有人问我问什么我在处 ...

  7. poj 1068 Parencodings 模拟

    进入每个' )  '多少前' (  ', 我们力求在每' ) '多少前' )  ', 我的方法是最原始的图还原出来,去寻找')'. 用. . #include<stdio.h> #incl ...

  8. 关于webbrowser控件自动登陆的问题

    原文:关于webbrowser控件自动登陆的问题 楼主dtb(陈少)2004-03-04 22:16:55 在 VB / 网络编程 提问 请问怎么用webbrowser自动登陆www.jp168.co ...

  9. poj 3273 Monthly Expense (二分)

    //最大值最小 //天数的a[i]值是固定的 不能改变顺序 # include <algorithm> # include <string.h> # include <s ...

  10. Installshield关于.NET安装时需要重启动的处理办法,以及延伸出的重启后继续安装的安装包的一点想法

    原文:Installshield关于.NET安装时需要重启动的处理办法,以及延伸出的重启后继续安装的安装包的一点想法 很多朋友做安装包的时候,所打包的软件需要.NET Framework之类的环境,他 ...