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

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

解析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. 模拟linux下的ls -l命令

    #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h&g ...

  2. 用Markdown来写作

    Markdown 是一种简单的.轻量级的标记语法.github上面很多的README就是用markdonw语法写的. Markdown 的语法十分简单,常用的标记符号也不超过十个,且一旦熟悉这种语法规 ...

  3. 谷歌、火狐浏览器下实现JS跨域iframe高度自适应的完美解决方法,跨域调用JS不再是难题!

    谷歌.火狐浏览器下实现JS跨域iframe高度自适应的解决方法 导读:今天开发的时候遇到个iframe自适应高度的问题,相信大家对这个不陌生,但是一般我们都是在同一个项目使用iframe嵌套页面,这个 ...

  4. Studio-Class Diagram

    UML Design Via Visual Studio-Class Diagram 用过几个建模设计工具,小的有staruml,大的有rational rose,EA.最后发现还是Visual St ...

  5. java_代码注释风格

    <?xml version="1.0" encoding="UTF-8" standalone="no"?><templa ...

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

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

  7. asp.net 一般处理程序session 为 null

    必须继承  IRequiresSessionState  接口才行!

  8. WebBrowser一点心得,如果在Javascript和Winform代码之间实现双向通信

    原文:WebBrowser一点心得,如果在Javascript和Winform代码之间实现双向通信 最近工作需要,学习了一下winform内嵌webbrowser控件,然后与htm页面中的javasc ...

  9. 下载的youtube视频

    youtube 视频下载方法[详解]   1.打开网址: http://kej.tw/flvretriever/. 2.输入要下载的youtube视频的网址. 3.点击右侧RETRIEVE NOW ! ...

  10. 常见浏览器扩展开发笔记(chrome firefox 360 baidu qq sougou liebao uc opera)

    浏览器扩展开发貌似时下很冷门啊,但是不少企业还是有类似的应用,360的抢票插件啊,笔者最近在做的网页翻译扩展之类的.笔者在开发的过程中,遇到了不少坑,说是坑,说白了就是各个厂商支持的API不统一导致的 ...