4

当我将 HTTP/1.1 与 SimpleHTTPRequestHandler 一起使用时,加载一个拉入其他资源的页面将在第二个资源之后挂起。

这是一个小型复制器:

from SimpleHTTPServer import SimpleHTTPRequestHandler
from BaseHTTPServer import HTTPServer

class MyRequestHandler(SimpleHTTPRequestHandler):
    #protocol_version = "HTTP/1.0"   # works
    protocol_version = "HTTP/1.1"   # hangs

server = HTTPServer(("localhost", 7080), MyRequestHandler)
server.serve_forever()

使用上述服务器,当浏览器尝试加载时,以下 HTML 将挂起b.png

<html>
    <body>
        <img src="a.png">
        <img src="b.png">
    </body>
</html>

HTTP/1.1 可以与 SimpleHTTPServer 模块一起使用吗?如果可以,如何使用?请注意,将 ForkingMixIn 或 ThreadingMixIn 添加到服务器将允许事情进行,但是,似乎没有这些 mixin 中的任何一个都应该是可能的。

4

1 回答 1

7

您看到的行为是由于三个原因:

  • BaseHTTPServer.HTTPServer默认情况下一次只能处理一个请求
  • 大多数用户代理(浏览器)一次打开多个到任何给定主机的连接
  • 大多数用户代理使用keep-aliveHTTP 1.1 的特性,并且在收到请求的实体后不会立即关闭连接

您看到的是,浏览器能够使用它打开到服务器的第一个连接来获取所有请求的实体。这是页面本身,也可能是它的一些资源。同时浏览器打开额外的连接来获取剩余的资源,但这些连接无法继续,因为服务器与第一个连接。服务器与第一个绑定的原因是,尽管浏览器已经接收到使用此连接请求的实体,但它不会立即关闭它,以防它可以在不久的将来被重用以获取更多实体(服务器不会关闭连接它的一方要么作为浏览器指定版本 1.1 的 HTTP 并发送Connection: keep-alive标题)。只有在第一个连接超时后,服务器才开始处理下一个等待连接,因此正在下载额外的资源(所有这些都是使用此特定连接请求的)。如果您等待足够长的时间,浏览器会设法获取所有资源。network.http.max-persistent-connections-per-server当您在 Firefox 中将首选项设置为 1(而不是默认值 6)或在其他浏览器中设置类似时,您可以观察到差异。然后,由于使用相同的连接请求所有资源,因此一旦检索到前一个,就会立即开始检索每个资源,而不会有任何延迟。

我要感谢freenode.net 上#python IRC 频道的 marienz 对这个问题的帮助。

于 2013-04-14T18:14:19.823 回答