解决urllib2的DNS远端解析问题,另Django-social-auth很好的支持本地调试

常俊侠
2023-12-01

Django-social-auth是一个很好的集成第三方认证的库,其支持的库种类非常多,包括常用的Facebook,twitter,google,msn,甚至还包括weibo。如果期望能够快速的集成这些账户的话,这个库是一个很好的开始。

因为众所周知的原因,在国内是没有办法访问facebook等服务的,很自然的我们希望可以通过代理的方式来让这个库工作正常。经过简单分析,这个库在底层的数据通讯方面,使用urllib2。入手点就在让urllib2支持代理了。在Python的原始库中,urllib2仅仅支持http代理,而我们使用SSH之类的用的是sock5。

经搜索发现已有网友提供了方案:

http://panweizeng.com/python-urllib2-socks-proxy.html

可是这个方法只解决了一半的问题,另一半就是DNS解析。于是又找到如下方案:

http://blog.antmanler.com/?p=471

需要说明的是,上边连接中的_create_connection与python2.7的不兼容,需要增加一个source_address=None的参数即可。

好了,至此让urllib2支持sock5的准备工作全部就绪,剩下的就是修改django-social-auth。查看其源代码,很快就能找到,这个库调用urlib2的地方被统一打包utils.py中到一个叫做dsa_open的函数。直接将上边两个链接中提到的方法,给这个函数打个补丁即可。

修改完成后的版本如下:

def dsa_urlopen(*args, **kwargs):
    """Like urllib2.urlopen but sets a timeout defined by
    SOCIAL_AUTH_URLOPEN_TIMEOUT setting if defined (and not already in
    kwargs)."""
    timeout = setting('SOCIAL_AUTH_URLOPEN_TIMEOUT')
    if timeout and 'timeout' not in kwargs:
        kwargs['timeout'] = timeout
    import socks
    import socket

    socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, "127.0.0.1", 1080)
    socket.socket = socks.socksocket
    def _create_connection(address, timeout=socket._GLOBAL_DEFAULT_TIMEOUT,source_address=None):
        msg = "getaddrinfo returns an empty list"
        host, port = address
        for res in socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM):
            af, socktype, proto, canonname, sa = res
            sock = None
            try:
                sock = socket.socket(af, socktype, proto)
                if timeout is not socket._GLOBAL_DEFAULT_TIMEOUT:
                    sock.settimeout(timeout)
                sock.connect(address)
                return sock

            except socket.error, msg:
                if sock is not None:
                    sock.close()

        raise socket.error, msg

    socket.create_connection = _create_connection

    return urlopen(*args, **kwargs)

对了,这个方案需要一个叫做socksipy_branch库的支持。可以使用pip安装。

此方法仍未完全解决DNS问题,最终方案需参照:http://www.cnblogs.com/Ankh/archive/2012/12/21/2827386.html

转载于:https://www.cnblogs.com/Ankh/archive/2012/12/19/2824459.html

 类似资料: