python测试接口 怎么在header和cookie里赋值_根据源码分析python中headers中的Cookie和cookies参数的优先级...

本文分析了在Python使用requests库进行接口测试时,如何在headers和cookies参数中设置cookie。当同时在两者中设置时,headers中的Cookie字段会覆盖方法参数中的cookies。详细讲解了requests库的内部处理流程,从`requests.get()`到`Session`对象,再到`PreparedRequest`的准备过程,展示了cookie如何被添加到请求头中,并指出只有在headers中不存在Cookie时,才会从cookies参数中添加。
摘要由CSDN通过智能技术生成

环境:

fiddler 搭建本地代理,代理地址为 127.0.0.1:8888

python 版本:3.6.7

requests 版本:2.21.0

1. 执行的测试python脚本为:

requests.get('http://localhost:5000/test',proxies={'http':'127.0.0.1:8888'},headers={'Cookie':'c=d'},cookies={'a':'b'})

以上脚本同时在headers和get方法的参数中设置了cookie

2.

get方法位于 requests/api.py

内容为:

def get(url, params=None, **kwargs):

r"""Sends a GET request.

:param url: URL for the new :class:`Request` object.

:param params: (optional) Dictionary, list of tuples or bytes to send

in the body of the :class:`Request`.

:param \*\*kwargs: Optional arguments that ``request`` takes.

:return: :class:`Response ` object

:rtype: requests.Response"""kwargs.setdefault('allow_redirects', True)return request('get', url, params=params, **kwargs)

View Code

可看到返回request方法的值,

一系列参数传给了Session对象的request方法:

1 def request(method, url, **kwargs):2 """Constructs and sends a :class:`Request `.3 :param method: method for the new :class:`Request` object.4 :param url: URL for the new :class:`Request` object.5 :param params: (optional) Dictionary, list of tuples or bytes to send6 in the body of the :class:`Request`.7 :param data: (optional) Dictionary, list of tuples, bytes, or file-like8 object to send in the body of the :class:`Request`.9 :param json: (optional) A JSON serializable Python object to send in the body of the :class:`Request`.10 :param headers: (optional) Dictionary of HTTP Headers to send with the :class:`Request`.11 :param cookies: (optional) Dict or CookieJar object to send with the :class:`Request`.12 :param files: (optional) Dictionary of ``'name': file-like-objects`` (or ``{'name': file-tuple}``) for multipart encoding upload.13 ``file-tuple`` can be a 2-tuple ``('filename', fileobj)``, 3-tuple ``('filename', fileobj, 'content_type')``14 or a 4-tuple ``('filename', fileobj, 'content_type', custom_headers)``, where ``'content-type'`` is a string15 defining the content type of the given file and ``custom_headers`` a dict-like object containing additional headers16 to add for the file.17 :param auth: (optional) Auth tuple to enable Basic/Digest/Custom HTTP Auth.18 :param timeout: (optional) How many seconds to wait for the server to send data19 before giving up, as a float, or a :ref:`(connect timeout, read20 timeout) ` tuple.21 :type timeout: float or tuple22 :param allow_redirects: (optional) Boolean. Enable/disable GET/OPTIONS/POST/PUT/PATCH/DELETE/HEAD redirection. Defaults to ``True``.23 :type allow_redirects: bool24 :param proxies: (optional) Dictionary mapping protocol to the URL of the proxy.25 :param verify: (optional) Either a boolean, in which case it controls whether we verify26 the server's TLS certificate, or a string, in which case it must be a path27 to a CA bundle to use. Defaults to ``True``.28 :param stream: (optional) if ``False``, the response content will be immediately downloaded.29 :param cert: (optional) if String, path to ssl client cert file (.pem). If Tuple, ('cert', 'key') pair.30 :return: :class:`Response ` object31 :rtype: requests.Response32 Usage::33 >>> import requests34 >>> req = requests.request('GET', 'https://httpbin.org/get')35 36 """

37

38 #By using the 'with' statement we are sure the session is closed, thus we

39 #avoid leaving sockets open which can trigger a ResourceWarning in some

40 #cases, and look like a memory leak in others.

41 with sessions.Session() as session:42 return session.request(method=method, url=url, **kwargs)

View Code

实例化一个Request对象然后prepare_request:

1 defrequest(self, method, url,2 params=None, data=None, headers=None, cookies=None, files=None,3 auth=None, timeout=None, allow_redirects=True, proxies=None,4 hooks=None, stream=None, verify=None, cert=None, json=None):5 """Constructs a :class:`Request `, prepares it and sends it.6 Returns :class:`Response ` object.7 :param method: method for the new :class:`Request` object.8 :param url: URL for the new :class:`Request` object.9 :param params: (optional) Dictionary or bytes to be sent in the query10 string for the :class:`Request`.11 :param data: (optional) Dictionary, list of tuples, bytes, or file-like12 object to send in the body of the :class:`Request`.13 :param json: (optional) json to send in the body of the14 :class:`Request`.15 :param headers: (optional) Dictionary of HTTP Headers to send with the16 :class:`Request`.17 :param cookies: (optional) Dict or CookieJar object to send with the18 :class:`Request`.19 :param files: (optional) Dictionary of ``'filename': file-like-objects``20 for multipart encoding upload.21 :param auth: (optional) Auth tuple or callable to enable22 Basic/Digest/Custom HTTP Auth.23 :param timeout: (optional) How long to wait for the server to send24 data before giving up, as a float, or a :ref:`(connect timeout,25 read timeout) ` tuple.26 :type timeout: float or tuple27 :param allow_redirects: (optional) Set to True by default.28 :type allow_redirects: bool29 :param proxies: (optional) Dictionary mapping protocol or protocol and30 hostname to the URL of the proxy.31 :param stream: (optional) whether to immediately download the response32 content. Defaults to ``False``.33 :param verify: (optional) Either a boolean, in which case it controls whether we verify34 the server's TLS certificate, or a string, in which case it must be a path35 to a CA bundle to use. Defaults to ``True``.36 :param cert: (optional) if String, path to ssl client cert file (.pem).37 If Tuple, ('cert', 'key') pair.38 :rtype: requests.Response39 """

40 #Create the Request.

41 req =Request(42 method=method.upper(),43 url=url,44 headers=headers,45 files=files,46 data=data or{},47 json=json,48 params=params or{},49 auth=auth,50 cookies=cookies,51 hooks=hooks,52 )53 prep =self.prepare_request(req)54

55 proxies = proxies or{}56

57 settings =self.merge_environment_settings(58 prep.url, proxies, stream, verify, cert59 )60

61 #Send the request.

62 send_kwargs ={63 'timeout': timeout,64 'allow_redirects': allow_redirects,65 }66 send_kwargs.update(settings)67 resp = self.send(prep, **send_kwargs)68

69 return resp

View Code

实例化一个PreparedRequest对象然后prepare(此时cookie还没受影响):

1 defprepare_request(self, request):2 """Constructs a :class:`PreparedRequest ` for3 transmission and returns it. The :class:`PreparedRequest` has settings4 merged from the :class:`Request ` instance and those of the5 :class:`Session`.6 :param request: :class:`Request` instance to prepare with this7 session's settings.8 :rtype: requests.PreparedRequest9 """

10 cookies = request.cookies or{}11

12 #Bootstrap CookieJar.

13 if notisinstance(cookies, cookielib.CookieJar):14 cookies =cookiejar_from_dict(cookies)15

16 #Merge with session cookies

17 merged_cookies =merge_cookies(18 merge_cookies(RequestsCookieJar(), self.cookies), cookies)19

20 #Set environment's basic authentication if not explicitly set.

21 auth =request.auth22 if self.trust_env and not auth and notself.auth:23 auth =get_netrc_auth(request.url)24

25 p =PreparedRequest()26 p.prepare(27 method=request.method.upper(),28 url=request.url,29 files=request.files,30 data=request.data,31 json=request.json,32 headers=merge_setting(request.headers, self.headers, dict_class=CaseInsensitiveDict),33 params=merge_setting(request.params, self.params),34 auth=merge_setting(auth, self.auth),35 cookies=merged_cookies,36 hooks=merge_hooks(request.hooks, self.hooks),37 )38 return p

View Code

prepare时的操作:

1 defprepare(self,2 method=None, url=None, headers=None, files=None, data=None,3 params=None, auth=None, cookies=None, hooks=None, json=None):4 """Prepares the entire request with the given parameters."""

5

6 self.prepare_method(method)7 self.prepare_url(url, params)8 self.prepare_headers(headers)9 self.prepare_cookies(cookies)10 self.prepare_body(data, files, json)11 self.prepare_auth(auth, url)12

13 #Note that prepare_auth must be last to enable authentication schemes

14 #such as OAuth to work on a fully prepared request.

15

16 #This MUST go after prepare_auth. Authenticators could add a hook

17 self.prepare_hooks(hooks)

View Code

prepare_headers,此时self.headers['Cookie']会被赋值:

1 defprepare_headers(self, headers):2 """Prepares the given HTTP headers."""

3

4 self.headers =CaseInsensitiveDict()5 ifheaders:6 for header inheaders.items():7 #Raise exception on invalid header value.

8 check_header_validity(header)9 name, value =header10 self.headers[to_native_string(name)] = value

View Code

prepare_cookies,此步骤中关键在于cookie_header 变量是不是None:

1 defprepare_cookies(self, cookies):2 """Prepares the given HTTP cookie data.3 This function eventually generates a ``Cookie`` header from the4 given cookies using cookielib. Due to cookielib's design, the header5 will not be regenerated if it already exists, meaning this function6 can only be called once for the life of the7 :class:`PreparedRequest ` object. Any subsequent calls8 to ``prepare_cookies`` will have no actual effect, unless the "Cookie"9 header is removed beforehand.10 """

11 ifisinstance(cookies, cookielib.CookieJar):12 self._cookies =cookies13 else:14 self._cookies =cookiejar_from_dict(cookies)15

16 cookie_header =get_cookie_header(self._cookies, self)17 if cookie_header is notNone:18 self.headers['Cookie'] = cookie_header

View Code

可看到get_cookie_header 函数中先模拟一个请求对象,然后将cookie添加近该模拟的请求对象中,然后获取其header的Cookie:

1 defget_cookie_header(jar, request):2 """

3 Produce an appropriate Cookie header string to be sent with `request`, or None.4 :rtype: str5 """

6 r =MockRequest(request)7 jar.add_cookie_header(r)8 return r.get_new_headers().get('Cookie')

View Code

以上代码中jar是一个cookielib.CookieJar类的对象,根据requests/compat.py 文件中中的内容可得知在python3中cookielib是 from http import cookiejar as cookielib 得来的,在python的http/cookiejar.py 源码中,可看到

add_cookie_header方法只有在request的headers中没有Cookie的时候把cookie的信息添加进headers:

1 defadd_cookie_header(self, request):2 """Add correct Cookie: header to request (urllib.request.Request object).3 The Cookie2 header is also added unless policy.hide_cookie2 is true.4 """

5 _debug("add_cookie_header")6 self._cookies_lock.acquire()7 try:8

9 self._policy._now = self._now =int(time.time())10

11 cookies =self._cookies_for_request(request)12

13 attrs =self._cookie_attrs(cookies)14 ifattrs:15 if not request.has_header("Cookie"):16 request.add_unredirected_header(17 "Cookie", ";".join(attrs))18

19 #if necessary, advertise that we know RFC 2965

20 if (self._policy.rfc2965 and not self._policy.hide_cookie2 and

21 not request.has_header("Cookie2")):22 for cookie incookies:23 if cookie.version != 1:24 request.add_unredirected_header("Cookie2", '$Version="1"')25 break

26

27 finally:28 self._cookies_lock.release()29

30 self.clear_expired_cookies()

View Code

如上文所述,同时在headers中和方法参数中设置cookie的时候只有headers中的cookie有效。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值