Twisted网络编程必备(5)


转自:http://www.yybug.com/read-htm-tid-15324.html

4.4 管理资源等级

 

WEB应用中的路径通常使用分级目录管理。例如如下URL:

http://example.com/people

http://example.com/people/charles

http://example.com/people/charles/contact

这里可以很清楚的看出等级划分。页面/people/charles是/people的子页面,而页面/people/charles/contact是/people/charles的子页面。等级中的每个页面都有特定的意义:/people/charles是一个人,而/people/charles/contact是一项数据,charles的数据。

WEB服务器的缺省行为是将PATH等级映射到磁盘上的文件。客户端的每次请求都是对应特定的资源,服务器查找文件并定位磁盘路径,然后将文件内容或者可执行文件的执行结果作为响应。在WEB应用中可以人为的生成一个对应路径文件的内容。例如,你的数据并没有存储在磁盘上,而是在一个关系数据库或者另一个服务器上。或者你想要在请求时自动创建资源。类似这种情况,最好的办法是为等级浏览创建自己的逻辑。

编写自己的资源管理逻辑可以帮助你管理安全。而不是打开WEB服务器的整个目录,你可以有选择的控制哪些文件是可以访问的。

 

4.4.1 下面如何做?

 

twisted.web.resource和twisted.web.static还有twisted.web.server模块提供了比twisted.web.http.Resource更高层次的请求管理类,你可以使用这些来设置一个WEB服务器来处理多种逻辑等级的资源。例子4-4使用了这些类来建立十六进制颜色代码。请求资源/color/hex,hex是十六进制的颜色代码,你可以得到一个背景为#hex的页面。对应每一种可能出现的颜色可能,服务器动态创建资源。

复制代码
代码
     
     
from twisted.web import resource,static,server class ColorPage(resource.Resource): def __init__ (self,color): self.color = color def render(self,request): return """ <html> <head> <title>Color: %s</title> <link type='text/css' href='/styles.css' rel='Stylesheet' /> </head> <body style='background-color: #%s'> <h1>This is #%s.</h1> <p style='background-color: white'> <a href='/color/'>Back</a> </p> </body> </html> """ % (self.color, self.color, self.color) class ColorRoot(resource.Resource): def __init__ (self): resource.Resource. __init__ (self) self.requestedColors = [] self.putChild( '' ,ColorIndexPage(self.requestColors)) def render(self,request): # redirect /color -> /color/ request.redirect(request.path + ' / ' ) return ' please use /colors/ instead. ' def getChild(self,path,request): if path not in self.requestedColors: self.requestedColors.append(path) return ColorPage(path) class ColorIndexPage(resource.Resource): def __init__ (self,requestColorsList): resource.Resource. __init__ (self) self.requestedColors = requestedColorsList def render(self,request): request.write( """ <html> <head> <title>Colors</title> <link type='text/css' href='/styles.css' rel='Stylesheet' /> </head> <body> <h1>Colors</h1> To see a color, enter a url like <a href='/color/ff0000'>/color/ff0000</a>. <br /> Colors viewed so far: <ul> """ ) for color in self.requestedColors: request.write( " <li><a href= " / blog /% s " style='color: #%s'>%s</a></li> " % ( color, color, color)) request.write( """ </ul> </body> </html> """ ) return "" class HomePage(resource.Resource): def render(self,request): return """ <html> <head> <title>Colors</title> <link type='text/css' href='/styles.css' rel='Stylesheet' /> </head> <body> <h1>Colors Demo</h1> What's here: <ul> <li><a href='/color'>Color viewer</a></li> </ul> </body> </html> """ if __name__ == ' __main__ ' : from twisted.internet import reactor root = resource.Resource() root.putChild( '' ,HomePage()) root.putChild( ' color ' ,ColorRoot()) root.putChild( ' styles.css ' ,static.File( ' styles.css ' )) site = server.Site(root) reactor.listenTCP( 8000 ,site) reactor.run()
复制代码

 

例子4-4引用了静态文件。所以需要在resourcetree.py脚本目录下创建一个styles.css文件。内容如下:

复制代码
代码
     
     
body { font-family : Georgia, Times, serif ; font-size : 11pt ; } h1 { margin : 10px 0 ; padding : 5px ; background-color : black ; color : white ; } a { font-family : monospace ; } p { padding : 10px ; }
复制代码

 

运行resourcetree.py脚本,将会在8000端口启动一个WEB服务器。下面是服务器全部可用路径:

/        主页

/css    虚拟的CSS资源

/css/styles.css    静态文件styles.css

/colors/ 颜色查看页面

/colors/hexcolor 按照背景色为#hexcolor的页面

尝试通过http://localhost:8000/colors/00abef来访问,将会得到背景色为#00abef的页面,大约是亮蓝色。

可以随便试试其他颜色。同样可以进入http://localhost:8000/,选择可选答案。

4.4.2 它们如何工作?

 

例子4.4从twisted.web包中引入了几个类:resource.Resource、static.File、server.Site。每个resource.Resource对象做两件事。首先,定义请求的资源如何处理。第二,定义请求子资源的Resource对象。

例如查看类ColorRoot。在这个类的实例稍后被加入了/colors这个等级资源。初始化时,ColorRoot使用putChild方法插入ColorIndexPage这个资源座位''资源。这意味着所有对/colors/的请求都由ColorIndexPage对象来处理。

你可以把他们想象为等价的,但是/stuff和/stuff/是不同的。浏览器在解释相对路径时,对是否加上斜线的处理方法是不同的。在第一个例子中,对"otherpage"的请求会解释为"http://example.com/otherpage",在第二个例子中解释为"http://example.com/stuff/otherpage"。

如果你不清楚(explicit)服务器代码,这个问题可能会再次郁闷你。最好是预先设计好是否需要在URI末尾加上斜线,并重定向请求。Resource类将会简化这些操作。如果设置了addSlash属性为True,一个Resource会自动在找不到对应资源时自动在URL末尾添加斜线来再次查找。

4.4 管理资源等级

 

4.6 运行HTTP代理服务器

 

除了HTTP服务器和客户端以外,twisted.web还包含了HTTP代理服务器的支持。一个代理服务器是一个服务器和一个客户端。他接受来自客户端的请求(作为服务器)并将他们转发到服务器(作为客户端)。然后将响应发送回客户端。HTTP代理服务器可以提供很多有用的服务:缓存、过滤和使用情况报告。下面的例子展示了如何使用Twisted构建一个HTTP代理服务器。

 

4.6.1 下面如何做?

 

twisted.web包包含了twisted.web.proxy,这个模块包含了HTTP代理服务器。例子4-7构建了一个简单的代理服务器。

 

复制代码
代码
     
     
from twisted.web import proxy,http from twisted.internet import reactor from twisted.python import log import sys log.startLogging(sys.stdout) class ProxyFactory(http.HTTPFactory): protocol = proxy.Proxy reactor.listenTCP( 8001 ,ProxyFactory()) reactor.run()
复制代码

 

运行simpleproxy.py脚本将会在8001端口启动代理服务器。在浏览器中设置这个代理服务器可以作为代理进行测试。对log.startLogging的调用将会把HTTP日志信息记录在stdout中,并可以直接查看。

 

$ python simpleproxy.py

2005/06/13 00:22 EDT [-] Log opened.

2005/06/13 00:22 EDT [-] __main__.ProxyFactory starting on 8001

... ...

 

这虽然给出了一个代理服务器,但是实际上没什么用处。例子4-8提供了更多的功能,可以跟踪最常使用的网页。

 

代码

 

运行wordcountproxy.py将浏览器的代理服务器设置到8001端口。浏览其他站点,或者访问http://localhost:8000/,将可以看到访问过的站点的单词频率。

 

4.6.2 它是如何工作的?

 

在例子4-8中有很多个类,但大多数是连接用的。只有很少的几个做实际工作。最开始的两个类WordParser和WordCounter,用于从HTML文档中解出单词符号并计算频率。第三个类WordCountProxy客户端包含了查找HTML文档并调用WordParser的任务。

因为代理服务器同时作为客户端和服务器,所以需要使用大量的类。有一个ProxyClientFactory和ProxyClient,提供了Factory/Protocol对来支持客户端连接。为了响应客户端的连接,需要使用ProxyRequest,它是HTTPFactory的子类,还有Proxy,是http.HTTPChannel的子类。它们对建立一个普通的HTTP服务器是有必要的:HTTPFactory使用Proxy作它的协议(Protocol),而代理Proxy HTTPChannel使用ProxyRequest作为它的RequestFactory。如下是客户端发送请求的事件处理流程:

·客户端建立到代理服务器的连接。这个连接被HTTPFactory所处理。

·HTTPFactory.buildProtocol会创建一个Proxy对象用来对客户端发送和接收数据。

·当客户端发送请求时,Proxy创建ProxyRequest来处理。

·ProxyRequest查找客户端请求的服务器。并创建ProxyClientFactory并调用reactor.connectTCP来通过factory连接服务器。

·一旦ProxyClientFactory连接到服务器,就会创建ProxyClient这个Protocol对象来发送和接收数据。

·ProxyClient发送原始请求。作为响应,它将客户端发来的请求发送给服务器。这是通过调用self.father.transport.write实现的。self.father是一个Proxy对象,正在管理着客户端连接对象。

这是一大串类,但实际上是分工明确的将工作由一个类传递到另一个类。但这是很重要的。为代理模块的每一个类提供一个子类,你可以完成每一步的控制。

整个例子4-8中最重要的一个技巧。ProxyClientFactory类有一个buildProtocol方法,可以包装好,供ProxyClient作为Protocol。它并不提供任何简单的方法来提供你自己的ProxyClient子类。解决办法是使用Python的__class__属性来替换升级ProxyClient对象来放回ProxyClientFactory.buildProtocol,这些将ProxyClient改变为WordCountProxyClient。

作为代理服务器的附加功能。例子4-8提供了标准的WEB服务器,在8000端口,可以显示从代理服务器来的当前单词统计数量。由此可见,在你的应用中包含一个内嵌的HTTP服务器是多么的方便,这种方式可以很好的提供给远程来显示相关状态信息。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值