HTTP管线化请求文本示例

14

以下是一个使用HTTP 1.1的示例请求,仅请求单个页面:

GET /jq.js HTTP/1.1
Host: 127.0.0.1
Accept: */*

我知道使用HTTP Pipelining,可以在不断开连接的情况下发送多个请求。

  • 请问有人能提供一些文本示例,展示如何通过命令行或PHP套接字发送此类请求吗?
  • 网页服务器是否需要支持管线化才能使用此功能?
  • 主流的Web服务器(如Apache、Nginx)是否默认支持pipeline,还是需要手动开启此功能?
  • 1个回答

    23

    根据w3c协议详细信息:

    8.1.2.2 管道传输

    支持持久连接的客户端可以使用“管道传输”它的请求(即,在等待每个响应之前发送多个请求)。服务器必须按接收请求的相同顺序发送其响应。

    假定支持持久连接并在连接建立后立即使用管道的客户端应该准备好在第一次管道尝试失败时重试其连接。 如果客户端进行此类重试,则在知道连接是持久的之前,不得使用管道。如果服务器在发送所有相应之前关闭连接,则客户端必须准备好重新发送它的请求。

    客户端不应该使用非幂等方法或非幂等方法序列进行管道请求(请参见9.1.2节)。否则,传输连接的过早终止可能导致不确定的结果。希望发送非幂等请求的客户端应该等到收到先前请求的响应状态再发送该请求。

    因此,第一个事实是您应该处于KeepAlive状态。 因此,在您的请求标头中应该添加Connection:keep-alive 关键字,但某些Web服务器可能仍会接受没有此保持活动状态的管道传输。 另一方面,该连接可能被服务器拒绝或接受,不管是保持活动还是非活动状态,您都可以在任何时候通过单个连接发送3个请求,并只收到一个响应。

    这个gist我们可以找到使用telnet测试它的好方法。

    使用Connection:keep-alive 标头请求保持活动:

    (echo -en "GET /index.html HTTP/1.1\nHost: foo.com\nConnection: keep-alive\n\nGET /index.html HTTP/1.1\nHost: foo.com\n\n"; sleep 10) | telnet localhost 80
    
    Trying 127.0.0.1...
    Connected to localhost.lan.
    Escape character is '^]'.
    HTTP/1.1 200 OK
    Date: Sun, 27 Oct 2013 17:51:58 GMT
    Server: Apache/2.2.22 (Debian)
    Last-Modified: Sun, 04 Mar 2012 15:00:29 GMT
    ETag: "56176e-3e-4ba6c121c4761"
    Accept-Ranges: bytes
    Content-Length: 62
    Vary: Accept-Encoding
    Keep-Alive: timeout=5, max=100  <======= Keepalive!
    Connection: Keep-Alive
    Content-Type: text/html; charset=utf-8
    
    <html>
        <body>
            <h1>test</h1>
        </body>
    </html>
    HTTP/1.1 200 OK
    Date: Sun, 27 Oct 2013 17:51:58 GMT
    Server: Apache/2.2.22 (Debian)
    Last-Modified: Sun, 04 Mar 2012 15:00:29 GMT
    ETag: "56176e-3e-4ba6c121c4761"
    Accept-Ranges: bytes
    Content-Length: 62
    Vary: Accept-Encoding
    Content-Type: text/html; charset=utf-8
    
    <html>
        <body>
            <h1>test</h1>
        </body>
    </html>
    

    它有效。

    无需请求保持连接:

    (echo -en "GET /index.html HTTP/1.1\nHost: foo.com\nConnection: keep-alive\n\nGET /index.html HTTP/1.1\nHost: foo.com\n\n"; sleep 10) | telnet localhost 80
    
    Trying 127.0.0.1...
    Connected to localhost.lan.
    Escape character is '^]'.
    HTTP/1.1 200 OK
    Date: Sun, 27 Oct 2013 17:49:37 GMT
    Server: Apache/2.2.22 (Debian)
    Last-Modified: Sun, 04 Mar 2012 15:00:29 GMT
    ETag: "56176e-3e-4ba6c121c4761"
    Accept-Ranges: bytes
    Content-Length: 62
    Vary: Accept-Encoding
    Content-Type: text/html; charset=utf-8
    
    <html>
        <body>
            <h1>test</h1>
        </body>
    </html>
    HTTP/1.1 200 OK
    Date: Sun, 27 Oct 2013 17:49:37 GMT
    Server: Apache/2.2.22 (Debian)
    Last-Modified: Sun, 04 Mar 2012 15:00:29 GMT
    ETag: "56176e-3e-4ba6c121c4761"
    Accept-Ranges: bytes
    Content-Length: 62
    Vary: Accept-Encoding
    Content-Type: text/html; charset=utf-8
    
    <html>
        <body>
            <h1>test</h1>
        </body>
    </html>
    Connection closed by foreign host.
    

    相同的结果,虽然我没有请求,但它看起来像是Keepalive响应(在5秒后关闭,这是Apache中设置的值)。而且是一个管线化的响应,我收到了我的两个页面。

    现在,如果我通过设置来防止在Apache中使用任何Keepalive连接:

    Keepalive Off
    

    并重新启动它:

    (echo -en "GET /index.html HTTP/1.1\nHost: foo.com\nConnection: keep-alive\n\nGET /index.html HTTP/1.1\nHost: foo.com\n\n"; sleep 10) | telnet localhost 80
    
    Trying 127.0.0.1...
    Connected to localhost.lan.
    Escape character is '^]'.
    HTTP/1.1 200 OK
    Date: Sun, 27 Oct 2013 18:02:41 GMT
    Server: Apache/2.2.22 (Debian)
    Last-Modified: Sun, 04 Mar 2012 15:00:29 GMT
    ETag: "56176e-3e-4ba6c121c4761"
    Accept-Ranges: bytes
    Content-Length: 62
    Vary: Accept-Encoding
    Connection: close
    Content-Type: text/html; charset=utf-8
    
    <html>
        <body>
            <h1>test</h1>
        </body>
    </html>
    Connection closed by foreign host.
    

    只有一个答案......所以服务器可以拒绝我的流水线请求。

    现在,关于服务器和浏览器的支持,我认为你的维基百科来源已经足够了 :-)


    我希望他们把多个请求头放在那里...我想我应该尝试一下,然后把它放在那里。感谢您详细的回复! - DMin
    我认为保持连接活跃(keep-alive)是你最不用担心的事情。在HTTP/1.1中,连接:keep-alive是默认行为。目前HTTP管线化存在更重要的问题需要解决。 - yakya
    @sotn 完全同意,例如 HTTP 走私等问题。 - regilero

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接