requests.get 异常hang住

这两天优化端口扫描脚本,在获取HTTP页面内容时,发现requests.get hang住了(之前httplib不会)。

requests.get 提供了超时参数timeout,但在实际使用过程中,仍发现get请求可能被hang住。

原因在于非HTTP  Server,response中一直没有出现换行符\n,导致_read_status()在获取状态码的时候就hang住了。

一个简单的解决方法,可以创建新的线程,示例代码参考如下,这部分代码是无法直接工作的:

def do_get_thread(url, ret):
    try:
        headers = {
            'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 6_0 like Mac OS X) AppleWebKit/536.26 '
                          '(KHTML, like Gecko) Version/6.0 Mobile/10A5376e Safari/8536.25',
            'Range': 'bytes=0-10240',
            'Connection': 'Close'}
        ret.append(requests.get(url, headers=headers, timeout=(4, 30)))
    except:
        pass


def get_http_title(ip, port, service, log_queue):
    if service.lower().find('https') >= 0 or service.lower().find('ssl') >= 0:
        service = 'https'
    else:
        service = 'http'
    url = '%s://%s:%s' % (service, ip, port)
    msg = 'Get http title %s' % url
    log_queue.put(msg)

    try:
        start_time = time.time()
        ret = []
        t = threading.Thread(target=do_get_thread, args=(url, ret))
        t.daemon = True
        t.start()
        while t.isAlive():
            if time.time() - start_time > 31:
                log_queue.put('[get_http_title timed out] %s' % url)
                return {}, ''
            else:
                time.sleep(1.0)
        if not ret:
            return {}, ''
        resp = ret[0]
        headers = resp.headers
        m = re.search('<title>(.*?)</title>', resp.text, re.IGNORECASE)
        http_title = m.group(1).strip() if m else ''
        if http_title:
            http_title = decode_response_text(http_title)
        else:
            http_title = resp.text.replace('\n', ' ').strip()[0:200]

        return headers, http_title
    except requests.exceptions.RequestException, e:
        pass
    except Exception, e:
        log_queue.put('[get_http_title.exception] %s' % str(e))
    return {}, ''