请求URL时推送数据
假设当用户在我的服务器上请求 /foo
时,我会发送以下的HTTP响应(连接不会关闭):
Content-Type: multipart/x-mixed-replace; boundary=-----------------------
-----------------------
Content-Type: text/html
<a href="/bar">foo</a>
当用户访问 /bar
时(这个请求会返回 204 No Content
,所以页面不会改变),我想在最初的响应中发送以下数据。
-----------------------
Content-Type: text/html
bar
我该如何让第二个请求从最初的响应中触发这个呢?我打算可能会创建一个只支持 [engines that support multipart/x-mixed-replace (目前只有Gecko)] 的邮件网页应用,它可以在不使用任何JavaScript的情况下实现服务器推送和Ajax效果,纯粹是为了好玩。
4 个回答
我做了一个小例子(只是为了好玩,你懂的 :)
import threading
num = 0
cond = threading.Condition()
def app(environ, start_response):
global num
cond.acquire()
num += 1
cond.notifyAll()
cond.release()
start_response("200 OK", [("Content-Type", "multipart/x-mixed-replace; boundary=xxx")])
while True:
n = num
s = "--xxx\r\nContent-Type: text/html\r\n\r\n%s\n" % n
yield s
# wait for num change:
cond.acquire()
while num == n:
cond.wait()
cond.release()
from cherrypy.wsgiserver import CherryPyWSGIServer
server = CherryPyWSGIServer(("0.0.0.0", 3000), app)
try:
server.start()
except KeyboardInterrupt:
server.stop()
# Now whenever you visit http://127.0.0.1:3000/, the number increases.
# It also automatically increases in all previously opened windows/tabs.
共享变量和线程同步的想法(使用条件变量对象)是基于这样一个事实:CherryPyWSGIServer 提供的 WSGI 服务器是多线程的。
如果你的问题是要把某个命令从 /bar 应用程序传递到 /foo 应用程序,并且你使用的是类似于 servlet 的方法(也就是说,Python 代码只加载一次,而不是像 CGI 那样每次请求都加载),那么你可以直接修改 /foo 应用程序的某个类属性,然后准备好在 /foo 实例中对这个变化做出反应(通过检查这个属性的状态)。
显然,/foo 应用程序在处理完第一次请求后不应该立即返回,而是应该逐行输出内容。
虽然这只是理论上的想法,我自己还没有尝试过。
虽然没有完整的答案,但可以分享一些信息:
在你的问题中,你提到的是一种叫做Comet的架构。关于Python/WSGI中对Comet风格技术的支持,有一个StackOverflow的问题,讨论了几种支持长时间请求的Python服务器,这些服务器类似于Comet。
还有一个有趣的邮件讨论线程在Python的Web-SIG中:“WSGI能处理异步响应吗?”。在2008年5月,Web-SIG中对WSGI中的异步请求进行了广泛的讨论。
最近的一个发展是evserver,这是一个轻量级的WSGI服务器,它实现了在2008年5月由Christopher Stawarz在Web-SIG中提出的异步WSGI扩展。
最后,Tornado web服务器支持非阻塞异步请求。它有一个使用长轮询的聊天示例应用程序,这与您的需求有相似之处。