【问题标题】:Pushing data once a URL is requested请求 URL 后推送数据
【发布时间】:2010-04-05 02:58:48
【问题描述】:

鉴于,当用户在我的服务器上请求 /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

如何从初始响应中获得第二个触发此请求?我正计划创建一个花哨的 [支持 multipart/x-mixed-replace (目前只有 Gecko)] 的电子邮件 web 应用程序,它不需要任何 JavaScript 就可以执行服务器推送和 Ajax 效果,只是为了好玩。

【问题讨论】:

    标签: python wsgi


    【解决方案1】:

    没有完整的答案,但是:

    在您的问题中,您描述的是Comet 风格的架构。关于在 Python/WSGI 中对 Comet 风格技术的支持,有一个 StackOverflow question,它讨论了各种 Python 服务器,它们支持长时间运行的请求,例如 Comet。

    Python Web-SIG 中的这个邮件线程也很有趣:"Could WSGI handle Asynchronous response?"。 2008年5月,Web-SIG就asynchronous requests in WSGI这个话题进行了广泛的讨论。

    最近的一个发展是evserver,一个轻量级的WSGI服务器,它实现了Christopher Stawarz在2008年5月在Web-SIG提出的Asynchronous WSGI extension

    最后,Tornado web server 支持non-blocking asynchronous requests。它有一个使用长轮询的聊天示例应用程序,它与您的要求有相似之处。

    【讨论】:

    • 你可能没有意识到,multipart/x-mixed-replace彗星的一种形式;唯一不需要 JavaScript 的表单。如果我可以让它与 Tornado 的异步请求一起工作,我会接受这个答案。
    • 很清楚 multipart/x-mixed-replace 是彗星的一种形式,但我认为 你不是 ;-),因为你没有不要在您的问题中提及流行语。我做了一些改写。
    【解决方案2】:

    如果问题是将一些命令从 /bar 应用程序传递到 /foo 应用程序,并且您正在使用一些类似 servlet 的方法(Python 代码只加载一次,而不是像在 CGI 中那样为每个请求加载),您可以更改一些/foo 应用程序的类属性,并准备好对 /foo 实例中的更改做出反应(通过检查属性状态)。

    显然 /foo 应用程序不应在第一次请求后立即返回并逐行产生内容。

    认为这只是理论,我自己没有尝试过。

    【讨论】:

    • 如果不使用完整的数据库(因为这太过分了),我怎样才能轻松更改共享状态对象?
    • 如我所说,如果代码只加载一次,那么每个新请求只是应用程序类的一个新实例。然后,您可以使用一些模块级别或类(而不是实例)属性来交换信息。
    【解决方案3】:

    我创建了一些小例子(只是为了好玩,你知道:))

    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服务器是线程化的。

    【讨论】:

      【解决方案4】:

      不确定这是否正是您要寻找的,但有一种相当古老的方式使用 multipart/x-mixed-replace 的 mime 内容进行服务器推送

      基本上,您将响应组合为内容类型为 multipart/x-mixed-replace 的 mime 对象,并向下发送文档的第一个“版本”。浏览器将保持套接字打开。

      然后,当服务器决定推送更多数据时,服务器会发送文档的新“版本”,浏览器将智能地替换(在包含内容的任何框架/iframe 内)内容。

      这是一种早期的网络摄像头方式,服务器会一个接一个地发送(推送)图像,而浏览器只会不断地替换文档中的图像。这也是通过单个 HTTP 请求执行“正在加载...”消息的一种方式。

      【讨论】:

      • 回答我的问题有什么关系?我知道multipart/x-mixed-replace 是什么以及如何使用它,如问题所示。我在问一个 Python wsgi 问题,我将如何处理这种情况。
      猜你喜欢
      • 2014-02-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-30
      • 1970-01-01
      • 1970-01-01
      • 2020-11-02
      • 1970-01-01
      相关资源
      最近更新 更多