requests源码

之前看到过一篇关于requests代码分析的文章,它是从最早版本开始的。论文笔,不及对方十之一二,论思路,十分佩服。要知道,我口口声声说看代码都是从最新代码看,收获有限。但是从初始版本看起,对自己大有裨益。作者的思路、代码的组织、技术的运用都是很值得去体会和学习的。

0.2.0

先看起头的这个类

class _Request(urllib2.Request):
    """Hidden wrapper around the urllib2.Request object. Allows for manual
    setting of HTTP methods.
    """
    
    def __init__(self, url,
                    data=None, headers={}, origin_req_host=None,
                    unverifiable=False, method=None):
        urllib2.Request.__init__( self, url, data, headers, origin_req_host,
                                  unverifiable)
           self.method = method

    def get_method(self):
        if self.method:
            return self.method

        return urllib2.Request.get_method(self)

可以看出,_Request是urllib2.Request的子类,这里重写了父类的get_method方法。如果有method,返回;如果没有,返回父类的get_method
在Request的send方法中可以看到其调用

GET:
if isinstance(self.params, dict):
    params = urllib.urlencode(self.params)
else:
    params = self.params
req = _Request(("%s?%s" % (self.url, params)), method=self.method)
PUT:
req = _Request(self.url, method='PUT')
POST:
req = _Request(self.url, method='POST')
# 如果设置了headers,就会把headers赋值给req.headers
if self.headers:
    req.headers = self.headers

# self._get_operner对认证做了判断,如果需要认证,则会执行以下代码
# authr = urllib2.HTTPPasswordMgrWithDefaultRealm()
# 
# authr.add_password(None, self.url, self.auth.username, self.auth.password)
# handler = urllib2.HTTPBasicAuthHandler(authr)
# opener = urllib2.build_opener(handler)
# return opener.open
# 实质上还是在用urllib2的open方法

opener = self._get_opener()

try:
    # 将req对象传给open方法,发出请求
    resp = opener(req)
    # 将结果信息赋值给response对象
    self.response.status_code = resp.code
    self.response.headers = resp.info().dict
    if self.method.lower() == 'get':
        self.response.content = resp.read()

    success = True
except urllib2.HTTPError, why:
    # 接收异常,why?why?why?,我充其量会写except urllib2.HTTPError, e。
    self.response.status_code = why.code

Response、AuthObject都是类,只能这么介绍了,因为太简单了,没什么可说的

class Response(object):
    """The :class:`Request` object. All :class:`Request` objects contain a
    :class:`Request.response <response>` attribute, which is an instance of
    this class.
    """

    def __init__(self):
        self.content = None
        self.status_code = None
        self.headers = dict()
        
    def __repr__(self):
        try:
            repr = '<Response [%s]>' % (self.status_code)
        except:
            repr = '<Response object>'
        return repr

    
class AuthObject(object):
    """The :class:`AuthObject` is a simple HTTP Authentication token. When
    given to a Requests function, it enables Basic HTTP Authentication for that
    Request. You can also enable Authorization for domain realms with AutoAuth.
    See AutoAuth for more details.s
    
    :param username: Username to authenticate with.
    :param password: Password for given username.
    """
    
    def __init__(self, username, password):
        self.username = username
        self.password = password

关于认证的函数

def add_autoauth(url, authobject):
    global AUTOAUTHS
    AUTOAUTHS.append((url, authobject))

def _detect_auth(url, auth):
    return _get_autoauth(url) if not auth else auth

def _get_autoauth(url):
    for (autoauth_url, auth) in AUTOAUTHS:
        if autoauth_url in url: 
            return auth 
    return None

一开始实在是没领会到add_autoauth的深意,在本版本中没有其他地方对其进行调用,后来发现如下注释:

>>> c_auth = requests.AuthObject('kennethreitz', 'xxxxxxx')
>>> requests.add_autoauth('https://convore.com/api/', c_auth)
>>> r = requests.get('https://convore.com/api/account/verify.json')

截取测试get的代码如下:

def get(url, params={}, headers={}, auth=None):
    r = Request()
    r.method = 'GET'
    r.url = url
    r.params = params
    r.headers = headers
    r.auth = _detect_auth(url, auth)
    r.send()
    return r.response

分析下在使用认证时的过程
实例化AuthObject对象成c_auth,并传入add_autoauth函数。这时全局变量AUTOAUTHS=[('https://convore.com/api/', c_auth)]。
在调用_detect_aut时,会比对当前的url是否在AUTOAUTHS中,如果在,就返回对应的auth。这里我感觉AUTOAUTHS是缓存了请求的url和认证信息。get请求时,如果auth函数为None,而且请求的url在AUTOAUTHS中,则会使用AUTOAUTHS的auth信息。

posted @ 2018-02-09 17:05  微波~  阅读(156)  评论(0编辑  收藏  举报