6

我想“ping”一个服务器,检查标头响应以查看链接是否损坏,如果没有损坏,则实际下载响应正文。

传统上,使用模块的同步方法requests,您可以发送get带有参数的请求stream = True,并在响应正文下载之前捕获标头,在出现错误(例如未找到)的情况下决定中止连接。

我的问题是,使用异步库执行此操作,grequests或者requests-futures对于我减少的知识库来说已成为不可能。

我已经尝试将流参数设置为 truerequest-futures但没有用,它仍然会下载响应正文,而不会让我在获得响应标头后立即进行干预。即使是这样,我也不确定如何进行。

这是我尝试过的:

测试.py

from requests_futures.sessions import FuturesSession

session = FuturesSession()
session.stream = True

future = session.get('http://www.google.com')
response = future.result()
print(response.status_code) # Here I would assume the response body hasn't been loaded

调试后,我发现它以任何一种方式下载响应正文。

我将不胜感激最初问题的任何解决方案,无论它是否符合我的逻辑。

4

2 回答 2

2

我相信你想要的是一个 HTTP HEAD 请求:

session.head('http://www.google.com')

根据w3.org,“HEAD 方法与 GET 相同,只是服务器不得在响应中返回消息体。” 如果您喜欢状态码和标头,您可以跟进正常的 GET 请求。

对于评论,看起来您可能也有兴趣在单个请求中执行此操作。可以直接使用套接字执行此操作。发送正常的 GET 请求,对第一个块做一个接收,如果你不喜欢结果,关闭连接,否则循环剩余的块。

以下是如何通过单个请求有条件地下载的概念证明:

import socket

def fetch_on_header_condition(host, resource, condition, port=80):
    request =  'GET %s HTTP/1.1\r\n' % resource
    request += 'Host: %s\r\n' % host
    request += 'Connection: close\r\n'
    request += '\r\n'

    s = socket.socket()
    try:
        s.connect((host, port))
        s.send(request)
        first_block = s.recv(4096)
        if not condition(first_block):
            return False, ''
        blocks = [first_block]
        while True:
            block = s.recv(4096)
            if not block:
                break
            blocks.append(block)
        return True, ''.join(blocks)
    finally:
        s.close()

if __name__ == '__main__':
    print fetch_on_header_condition(
        host = 'www.jython.org',
        port = 80,
        resource = '/',
        condition = lambda s: 'Content-Type: text/xml' in s,
    )
于 2017-03-29T05:01:17.563 回答
1

只需检查头部请求的状态并相应地进行:

header = session.head('https://google.com')

if header.ok is True:
    session.get('https://google.com')
于 2017-03-29T04:57:00.587 回答