HTTPS请求导致在Windows与Python 3的重置连接 [英] HTTPS request results in reset connection in Windows with Python 3

查看:272
本文介绍了HTTPS请求导致在Windows与Python 3的重置连接的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我在cygwin中使用Python 3.2.3包中的以下函数时,它会挂起对任何https主机的任何请求。它会抛出与此错误:[Errno 104]连接重置对等体,60秒后。

When I use the following function with the Python 3.2.3 package in cygwin it hangs on any request to any https host. It will throw with this error: [Errno 104] Connection reset by peer, after 60 seconds.

更新:我认为它只限于cygwin,但这也发生在Windows 7 64位与Python 3.3。我现在尝试3.2。使用windows命令shell时出现的错误是:
urlopen错误[WinError 10054]现有连接被远程主机强行关闭

UPDATE: I thought it was limited to only cygwin, but this also happens in Windows 7 64bit with Python 3.3. I'll try 3.2 right now. The error when using the windows command shell is: urlopen error [WinError 10054] An existing connection was forcibly closed by the remote host

UPDATE2(Electric-Bugaloo ):这仅限于我试图使用的几个网站。我测试了对谷歌和其他主要网站没有问题。它似乎与此错误相关:

UPDATE2(Electric-Bugaloo): This is limited to a couple of sites that I'm trying to use. I tested against google and other major sites with no issue. It appears it's related to this bug:

http:// bugs.python.org/issue16361

具体来说,服务器挂在客户端hello之后。这是由于python3.2和3.3的编译版本附带的openssl的版本。它错误识别服务器的ssl版本。现在我需要代码来自动降级我的版本的ssl到sslv3时打开受影响的网站,像这篇文章中的连接:

Specifically, the server is hanging after the client-hello. It's due to the version of openssl that shipped with the compiled versions of python3.2 and 3.3. It's mis-identifying the ssl version of the server. Now I need code to auto downgrade my version of ssl to sslv3 when opening a connection to the affected sites like in this post:

如何使用urllib2获取使用SSLv3加密的网页

但我不能让它工作。

def worker(url, body=None, bt=None):
    '''This function does all the requests to wherever for data

    takes in a url, optional body utf-8 encoded please, and optional body type'''

    hdrs = {'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
                   'Accept-Language': 'en-us,en;q=0.5',
                   'Accept-Encoding': 'gzip,deflate',
                   'User-Agent': "My kewl Python tewl!"}
    if 'myweirdurl' in url:
        hdrs = {'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
                   'Accept-Language': 'en-us,en;q=0.5',
                   'Accept-Encoding': 'gzip,deflate',
                   'User-Agent': "Netscape 6.0"}

    if bt:
        hdrs['Content-Type'] = bt
    urlopen = urllib.request.urlopen
    Request = urllib.request.Request
    start_req = time.time()
    logger.debug('request start: {}'.format(datetime.now().ctime()))
    if 'password' not in url:
        logger.debug('request url: {}'.format(url))
    req = Request(url, data=body, headers=hdrs)
    try:
        if body:
            logger.debug("body: {}".format(body))
            handle = urlopen(req, data=body, timeout=298)
        else:
            handle = urlopen(req, timeout=298)
    except socket.error as se:
        logger.error(se)
        logger.error(se.errno)
        logger.error(type(se))
        if hasattr(se, 'errno') == 60: 
            logger.error("returning: Request Timed Out")
            return 'Request Timed Out'
    except URLError as ue:
        end_time = time.time()
        logger.error(ue)
        logger.error(hasattr(ue, 'code'))
        logger.error(hasattr(ue, 'errno'))
        logger.error(hasattr(ue, 'reason'))
        if hasattr(ue, 'code'):
            logger.warn('The server couldn\'t fulfill the request.')
            logger.error('Error code: {}'.format(ue.code))
            if ue.code == 404:
                return "Resource Not Found (404)"
        elif hasattr(ue, 'reason') :
            logger.warn('We failed to reach a server with {}'.format(url))
            logger.error('Reason: {}'.format(ue.reason))

            logger.error(type(ue.reason))
            logger.error(ue.reason.errno)
            if ue.reason == 'Operation timed out':
                logger.error("Arrggghh, timed out!")
            else:
                logger.error("Why U no match my reason?")
                if ue.reason.errno == 60:
                    return "Operation timed out"
        elif hasattr(ue, 'errno'):
            logger.warn(ue.reason)
            logger.error('Error code: {}'.format(ue.errno))
            if ue.errno == 60:
                return "Operation timed out"
        logger.error("req time: {}".format(end_time - start_req))
        logger.error("returning: Server Error")
        return "Server Error"
    else:
        resp_headers = dict(handle.info())
        logger.debug('Here are the headers of the page : {}'.format(resp_headers))
        logger.debug("The true URL in case of redirects {}".format(handle.geturl()))           
        try:
            ce = resp_headers['Content-Encoding']
        except KeyError as ke:
            ce = None
        else:
            logger.debug('Content-Encoding: {}'.format(ce))
        try:
            ct = resp_headers['Content-Type']
        except KeyError as ke:
            ct = None            
        else:
            logger.debug('Content-Type: {}'.format(ct))
        if ce == "gzip":
            logger.debug("Unzipping payload")
            bi = BytesIO(handle.read())
            gf = GzipFile(fileobj=bi, mode="rb")
            if "charset=utf-8" in ct.lower() or ct == 'text/html' or ct == 'text/plain':
                payload = gf.read().decode("utf-8")
            else:
                logger.debug("Unknown content type: {}".format(ct))
                sys.exit()
            return payload
        else:
            if ct is not None and "charset=utf-8" in ct.lower() or ct == 'text/html' or ct == 'text/plain':
                return handle.read().decode("utf-8")
            else:
                logger.debug("Unknown content type: {}".format(ct))
                sys.exit()


推荐答案

我想出了,下面是在Windows上使这个工作需要的代码块:

I figured it out, here's the code block necessary to make this work on Windows:

'''had to add this windows specific block to handle this bug in urllib2:
http://bugs.python.org/issue11220
'''
if "windows" in platform().lower():
    if 'my_wacky_url' or 'my_other_wacky_url' in url.lower():
        import ssl
        ssl_context = urllib.request.HTTPSHandler(
                                              context=ssl.SSLContext(ssl.PROTOCOL_TLSv1))
        opener = urllib.request.build_opener(ssl_context)
        urllib.request.install_opener(opener)
#end of urllib workaround

我在第一次尝试之前添加了这个blob:block,它像一个charm。感谢您的帮助和帮助!

I added this blob right before the first try: block and it worked like a charm. Thanks for the assistance andrean!

这篇关于HTTPS请求导致在Windows与Python 3的重置连接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆