requests源碼

以前看到過一篇關於requests代碼分析的文章,它是從最先版本開始的。論文筆,不及對方十之一二,論思路,十分佩服。要知道,我口口聲聲說看代碼都是從最新代碼看,收穫有限。可是從初始版本看起,對本身大有裨益。做者的思路、代碼的組織、技術的運用都是很值得去體會和學習的。json

0.2.0

先看起頭的這個類api

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都是類,只能這麼介紹了,由於太簡單了,沒什麼可說的app

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

關於認證的函數dom

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信息。測試

相關文章
相關標籤/搜索