美文网首页
HTTP接口测试 | Requests库的高级用法:会话对象、S

HTTP接口测试 | Requests库的高级用法:会话对象、S

作者: 金融测试民工 | 来源:发表于2020-02-15 12:54 被阅读0次

        在本篇文档我们讲一下 Requests 的一些高级特性。

    会话对象

        会话对象让你能够跨请求保持某些参数。它也会在同一个 Session 实例发出的所有请求之间保持 cookie, 期间使用 urllib3 的 connection pooling 功能。所以如果你向同一主机发送多个请求,底层的 TCP 连接将会被重用,从而带来显著的性能提升。 

        会话对象具有主要的 Requests API 的所有方法。我们来跨请求保持一些 cookie:

    s = requests.Session()

    s.get('http://httpbin.org/cookies/set/sessioncookie/123456789')

    r = s.get("http://httpbin.org/cookies")

    print(r.text)

    # '{"cookies": {"sessioncookie":"123456789"}}'

        会话也可用来为请求方法提供缺省数据。这是通过为会话对象的属性提供数据来实现的:

    s = requests.Session()

    s.auth = ('user','pass')

    s.headers.update({'x-test':'true'})

    # both'x-test'and'x-test2'are sent

    s.get('http://httpbin.org/headers', headers={'x-test2':'true'})

        任何你传递给请求方法的字典都会与已设置会话层数据合并。方法层的参数覆盖会话的参数。不过需要注意,就算使用了会话,方法级别的参数也不会被跨请求保持。下面的例子只会和第一个请求发送 cookie ,而非第二个:

    s = requests.Session()

    r = s.get('http://httpbin.org/cookies', cookies={'from-my':'browser'})

    print(r.text)                                                            #'{"cookies": {"from-my": "browser"}}'

    r = s.get('http://httpbin.org/cookies')

    print(r.text)                                                            #'{"cookies": {}}'

        如果你要手动为会话添加 cookie,就使用 Cookie utility 函数 来操纵 Session.cookies

        会话还可以用作前后文管理器:

    withrequests.Session()ass:

    s.get('http://httpbin.org/cookies/set/sessioncookie/123456789')

    这样就能确保 with 区块退出后会话能被关闭,即使发生了异常也一样。

    有时你会想省略字典参数中一些会话层的键。要做到这一点,你只需简单地在方法层参数中将那个键的值设置为 None ,那个键就会被自动省略掉。

    包含在一个会话中的所有数据你都可以直接使用。

    准备的请求 (Prepared Request)

        当你从 API 或者会话调用中收到一个 Response 对象时,request 属性其实是使用了 PreparedRequest。有时在发送请求之前,你需要对 body 或者 header (或者别的什么东西)做一些额外处理,下面演示了一个简单的做法:

    from requests import Request, Session

    s = Session()

    req = Request('GET', url,

        data=data,

        headers=header

    )

    prepped = req.prepare()

    # do something with prepped.body

    # do something with prepped.headers

    resp = s.send(prepped,

        stream=stream,

        verify=verify,

        proxies=proxies,

        cert=cert,

        timeout=timeout

    )

    print(resp.status_code)

        由于你没有对 Request 对象做什么特殊事情,你立即准备和修改了 PreparedRequest 对象,然后把它和别的参数一起发送到 requests.* 或者 Session.*

        然而,上述代码会失去 Requests Session 对象的一些优势, 尤其 Session 级别的状态,例如 cookie 就不会被应用到你的请求上去。要获取一个带有状态的 PreparedRequest, 请用 Session.prepare_request() 取代 Request.prepare() 的调用,如下所示:

    from requests import Request, Session

    s = Session()

    req = Request('GET',  url,

        data=data

        headers=headers

    )

    prepped = s.prepare_request(req)

    # do something with prepped.body

    # do something with prepped.headers

    resp = s.send(prepped,

        stream=stream,

        verify=verify,

        proxies=proxies,

        cert=cert,

        timeout=timeout

    )

    print(resp.status_code)



    SSL 证书验证

        Requests 可以为 HTTPS 请求验证 SSL 证书,就像 web 浏览器一样。SSL 验证默认是开启的,如果证书验证失败,Requests 会抛出 SSLError:

    >>> requests.get('https://requestb.in')

    requests.exceptions.SSLError: hostname'requestb.in' doesn'tmatch eitherof'*.herokuapp.com','herokuapp.com'

        在该域名上我没有设置 SSL,所以失败了。但 Github 设置了 SSL:

    >>> requests.get('https://github.com', verify=True)

    <Response [200]>

    你可以为 verify 传入 CA_BUNDLE 文件的路径,或者包含可信任 CA 证书文件的文件夹路径:

    >>> requests.get('https://github.com', verify='/path/to/certfile')

        或者将其保持在会话中:

    s = requests.Session()

    s.verify= '/path/to/certfile'

    注解

        如果 verify 设为文件夹路径,文件夹必须通过 OpenSSL 提供的 c_rehash 工具处理。

        你还可以通过 REQUESTS_CA_BUNDLE 环境变量定义可信任 CA 列表。

        如果你将 verify 设置为 False,Requests 也能忽略对 SSL 证书的验证。

    >>> requests.get('https://kennethreitz.org', verify=False)

    <Response [200]>

        默认情况下, verify 是设置为 True 的。选项 verify 仅应用于主机证书。

        # 对于私有证书,你也可以传递一个 CA_BUNDLE 文件的路径给 verify。你也可以设置 # REQUEST_CA_BUNDLE 环境变量。

    客户端证书

        你也可以指定一个本地证书用作客户端证书,可以是单个文件(包含密钥和证书)或一个包含两个文件路径的元组:

    >>> requests.get('https://kennethreitz.org', cert=('/path/client.cert','/path/client.key'))

    <Response [200]>

        或者保持在会话中:

    s= requests.Session()

    s.cert ='/path/client.cert'

        但如果你指定了一个错误路径或一个无效的证书就会报错:SSLError: [Errno 336265225] _ssl.c:347: error:140B0009:SSL routines:SSL_CTX_use_PrivateKey_file:PEM lib。

    警告:

        本地证书的私有 key 必须是解密状态。目前,Requests 不支持使用加密的 key。

    保持活动状态(持久连接)

        归功于 urllib3,同一会话内的持久连接是完全自动处理的!同一会话内你发出的任何请求都会自动复用恰当的连接!

    注意:只有所有的响应体数据被读取完毕连接才会被释放为连接池;所以确保将 stream 设置为 False 或读取 Response 对象的 content 属性。


    块编码请求

        对于出去和进来的请求,Requests 也支持分块传输编码。要发送一个块编码的请求,仅需为你的请求体提供一个生成器(或任意没有具体长度的迭代器):

    defgen():

        yield'hi'

        yield'there'

    requests.post('http://some.url/chunked', data=gen())

        对于分块的编码请求,我们最好使用 Response.iter_content() 对其数据进行迭代。在理想情况下,你的 request 会设置 stream=True,这样你就可以通过调用 iter_content 并将分块大小参数设为 None,从而进行分块的迭代。如果你要设置分块的最大体积,你可以把分块大小参数设为任意整数。

    POST 多个分块编码的文件

        你可以在一个请求中发送多个文件。例如,假设你要上传多个图像文件到一个 HTML 表单,使用一个多文件 field 叫做 "images":

    <input type="file" name="images" multiple="true" required="true"/>

        要实现,只要把文件设到一个元组的列表中,其中元组结构为 (form_field_name, file_info):

    url ='http://httpbin.org/post'

    multiple_files = [

    ('images', ('foo.png', open('foo.png','rb'),'image/png')),

    ('images', ('bar.png', open('bar.png','rb'),'image/png'))]

    r = requests.post(url, files=multiple_files)

    >>> r.text

    {

      ...

      'files': {'images':'data:image/png;base64,iVBORw ....'}

      'Content-Type':'multipart/form-data; boundary=3131623adb2043caaeb5538cc7aa0b3a',

      ...

    }

    警告

        我们强烈建议你用二进制模式(binary mode)打开文件。这是因为 requests 可能会为你提供 header 中的 Content-Length,在这种情况下该值会被设为文件的字节数。如果你用文本模式打开文件,就可能碰到错误。

    BYE

    *本文来源网络,如有侵权,请联系删除。

    相关文章

      网友评论

          本文标题:HTTP接口测试 | Requests库的高级用法:会话对象、S

          本文链接:https://www.haomeiwen.com/subject/symefhtx.html