http协议Python版

Http协议介绍

在做接口测试的过程中,都会遇到一些http协议,什么是http协议?

什么是http协议

HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于从万维网(WWW:World Wide Web )服务器传输超文本到本地浏览器的传送协议。基于TCP的应用层协议,它不关心数据传输的细节,HTTP(超文本传输协议)是一个基于请求与响应模式的、无状态的、应用层的协议,只有遵循统一的 HTTP 请求格式,服务器才能正确解析不同客户端发的请求,同样地,服务器遵循统一的响应格式,客户端才得以正确解析不同网站发过来的响应。
在这里插入图片描述

什么是HTTPS

HTTPS 的全称是Hyper Text Transfer Protocol over Secure Socket Layer ,是以安全为目标的HTTP通道,简单的讲是HTTP的安全版本,即HTTP下加入SSL层,简称HTTPS

其中HTTPS的安全基础为SSL,因此通过它的传输的内容都是经过SSL加密的,它的主要作用可以分为两种:
1、建立一个信息安全通道来保证数据传输的安全
2、确保网站的真实性,凡是使用了HTTPS 的网站,都可以通过点击浏览器地址栏的锁头标志来查看网站认证之后的真实信息。

HTTP请求内容

HTTP 请求由请求行、请求头、空行、请求体组成
在这里插入图片描述
请求行:请求方式 + URL + 协议版本

  • 常见的请求方法有 GET、POST、PUT、DELETE、HEAD
GET :select(查询)
POST:create(添加)
PUT :update(更新)
DELETE:delete(删除)
  • 客户端要获取的资源路径(所谓的URL)
  • 客户端使用的 HTTP 协议版本号(目前使用的是http1.1)

请求头:客户端向服务器发送请求的补充说明

  • host:请求地址
  • User-Agent: 客户端使用的操作系统和浏览器的名称和版本.
  • Content-Length:发送给HTTP服务器数据的长度。
  • Content-Type:参数的数据类型
  • Cookie:将cookie的值发送给HTTP 服务器
  • Accept-Charset:自己接收的字符集
  • Accept-Language:浏览器自己接收的语言
  • Accept:浏览器接受的媒体类型

请求体:一般携带的请求参数

  • application/json:{“name”:“value”,“name1”:"value2”}
  • application/x-www-form-urlencoded: name1=value1&name2=value2
  • multipart/from-data:表格形式
  • text/xml
  • content-type:octets/stream

HTTP响应内容

HTTP 响应格式与请求的格式很相似,也是由响应行、响应头、空行、响应体组成。
状态行:HTTP 版本号 + 响应状态码 + 状态说明
响应状态码有 1XX、2XX、3XX、4XX、5XX、5XX。

  • 1XX 提示信息 - 表示请求已被成功接收,继续处理
  • 2XX 成功 - 表示请求已被成功接收,理解,接受
  • 3XX 重定向 - 要完成请求必须进行更进一步的处理
  • 4XX 客户端错误 - 请求有语法错误或请求无法实现
  • 5XX 服务器端错误 - 服务器未能实现合法的请求响应头
① 客户方错误 
100  继续 
101  交换协议 
② 成功 
200  OK 
201  已创建 
202  接收 
203  非认证信息 
204  无内容 
205  重置内容 
206  部分内容 
③ 重定向 
300  多路选择 
301  永久转移 
302  暂时转移 
303  参见其它 
304  未修改(Not Modified) 
305  使用代理 
④ 客户方错误 
400  错误请求(Bad Request) 
401  未认证 
402  需要付费 
403  禁止(Forbidden) 
404  未找到(Not Found) 
405  方法不允许 
406  不接受 
407  需要代理认证 
408  请求超时 
409  冲突 
410  失败 
411  需要长度 
412  条件失败 
413  请求实体太大 
414  请求URI太长 
415  不支持媒体类型 
⑤ 服务器错误 
500  服务器内部错误 
501  未实现(Not Implemented) 
502  网关失败 
504  网关超时 
505 HTTP版本不支持 

响应头:响应头与请求头对应,是服务器对该响应的一些附加说明
响应体:它才是真正的响应数据,这些数据其实就是网页的 HTML 源代码

什么是URL

URL(Uniform Resource Locator,统一资源定位符),是WWW的统一资源定位标志,就是指网络地址

# URL格式
https://host:port/path?xxx=aaa&ooo=bbb

##  http/https:这个是协议类型
##  host:服务器的IP地址或者域名
##  port:HTTP服务器的默认端口是80
##  path:访问资源的路径,代码中常用uri表示
##  url里面的?这个符号是个分割线,用来区分问号前面的是path,问号后面的是参数。通常url代表整个地址,但有些习惯url代表https://host:port,uri代表/path,如robotframework
##  url-params:问号后面的是请求参数,格式:xxx=aaa
##  多个参数用&符号连接

协议版本

HTTP/1.1 协议规定的 HTTP 请求方法有
OPTIONSGETHEADPOSTPUTDELETETRACECONNECT 这几种

  • get:请求指定的页面信息,并返回实体主体。
  • post:向指定资源提交数据进行处理请求,数据被包含在请求体中。
  • HEAD:返回的响应中没有具体的内容,用于获取报头。
  • OPTIONS:返回服务器针对特定资源所支持的HTTP请求方法,也可以利用向web服务器发送‘*’的请求来测试服务器的功能性
  • PUT:向指定资源位置上传其最新内容
  • DELETE:请求服务器删除Request-URL所标识的资源
  • TRACE:回显服务器收到的请求,主要用于测试或诊断
  • CONNECT:HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。

GET请求介绍

GET通常用于获取服务端数据。
常见发起GET请求的方式有:URL 、src/href、表单(form)。
GET方式提交数据的格式:

  • 格式:index.php?userName=jack&password=123 (注意:index.php?key=value&key=value。 userName=jack&password=123 叫做查询字符串)
  • 参数名与参数值之间没有空格
  • 参数值不需要使用单双引号包括
    GET方式提交数据特点:
    1、get方式在url后面拼接参数,只能以文本的形式传递参数。
    2、传递的数据量小,4kb左右(不同浏览器会有差异)。
    3、安全性低,会将信息显示在地址栏。
    4、速度快,通常用于对安全性要求不高的请求。

POST请求数据格式

服务端通常是根据请求头(headers)中的 Content-Type 字段来获知请求中的消息主体是用何种方式编码,再对主体进行解析。所以说到 POST 提交数据方案,包含了 Content-Type 和消息主体编码方式两部分。

1. application/json

消息主体是序列化后的 JSON 字符串。
请求内容样式如下:

POST http://www.eg.com/post HTTP/1.1 
Content-Type: application/json;charset=utf-8
 
{"title":"test","sub":[1,2,3]}

如果用fiddler模拟请求的话,请求头和请求主体的内容可以这样构造:
在这里插入图片描述

代码实现

import requests
import json

url = 'http://www.example/post'
params = json.dumps({'key1': 'value1', 'key2': 'value2'})
headers = {"Content-Type": "application/json"}
r = requests.post(url, data=params , headers=headers)
print (r.text)

2. application/x-www-form-urlencoded

当HTTP交互中,服务器端指定了application/x-www-form-urlencoded的Content-Type类型,需要对Body报文实体进行url编码。
这是post请求最常见也是默认的数据提交格式。它要求数据名称(name)和数据值(value)之间以等号相连,与另一组name/value值之间用&相连。例如:parameter1=12345&parameter2=23456。

请求内容样式如下:

POST http://www.eg.com/post HTTP/1.1
Content-Type: application/x-www-form-urlencoded;charset=utf-8
 
title=test&sub%5B%5D=1&sub%5B%5D=2&sub%5B%5D=3

如果用fiddler模拟请求的话,请求头和请求主体的内容可以这样构造:在这里插入图片描述

代码实现

方法1:

import requests
import json
from urllib import parse

# 定义请求header
HEADERS = {'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8'}
# 定义请求地址
url = "http://www.eg.com/post"
# 通过字典方式定义请求body
FormData = {'parameter1':'12345','parameter2':'23456'}
# 字典转换k1=v1 & k2=v2 模式
data = parse.urlencode(FormData)
# 请求方式
content = requests.post(url=url, headers=HEADERS, data=data).text
content = json.loads(content)
print(content)

方法2:

datas = {'parameter1':'12345','parameter2':'23456'}
r = requests.post('http://www.eg.com/post',data=datas)
print(r.content)
print(r.status_code)

3. multipart/form-data

多部分对象集合
有的时候传输的内容,不仅仅是一些字符串,还有可能是一些图片,字符,音乐二进制等混杂的内容。这就需要使用多部分对象集合,multipart,例如在使用java编写web上传文件的代码时,需要在form中指定form的编码格式。设置form的enctype属性的值为multipart/form-data。这是因为默认的情况下form使用的编码格式是:applicatin/x-www-form-urlencoded,这种编码格式会把所有的内容进行编码,不适合上传文件这种情况。
这两种编码格式的区别主要是:multipart/form-data 会以控件为基准,编码form中的内容。application/x-www-form-urlencoded 会把form中的内容编码成键值对的形式。

这是一个常见的 POST 数据提交的方式。我们使用表单上传文件时,可以设置请求headers的Content-Type等于 multipart/form-data。
请求内容样式如下:

POST http://www.eg.com/post HTTP/1.1
Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryrGKCBY7qhFd3TrwA
 
------WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name="text"
 
title
------WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name="file"; filename="chrome.png"
Content-Type: image/png
 
PNG ... content of chrome.png ...
------WebKitFormBoundaryrGKCBY7qhFd3TrwA--

首先生成了一个 boundary 用于分割不同的字段,为了避免与正文内容重复,boundary 很长很复杂,每次post浏览器都会生成一个随机的30-40位长度的随机字符串。
然后 Content-Type 里指明了数据是以 multipart/form-data 来编码,本次请求的 boundary 是什么内容。
消息主体里按照字段个数又分为多个结构类似的部分,每部分都是以 –boundary 开始,紧接着是内容描述信息,然后是回车,最后是字段具体内容(文本或二进制)。
如果传输的是文件,还要包含文件名和文件类型信息。消息主体最后以 –boundary– 标示结束。
如果用fiddler模拟请求的话,请求头和请求主体的内容可以这样构造:
第一步,先设置好请求头格式,然后点击upload file…
在这里插入图片描述
第二步,上传你的文件,这里上传一个png的图片
在这里插入图片描述

代码实现

方法1:

  • 此方式如需headers,不需要赋值Content-Type,不然可能会报错
  • 此方式既可以上传文件,也可以不上传文件
    1. 仅发送文件和参数
import requests

"""
#将参数值转成元组对象,如下4种格式:
1-tuples (None, "username_value")
2-tuples (filename, fileobj), 
3-tuples (filename, fileobj, contentype),
4-tuples (filename, fileobj, contentype, custom_headers)

接口参数
	参数1:username
	参数2:password
"""
url = "http://www.eg.com/post"
file_data= {"username": (None, "billy"),
         "password": (None, "abcd1234"),
         'picUrl': ('pic.png', open('E:\\download\\pic.png', 'rb'), 'image/png')}

res = requests.post(url, files=file_data)

2. 仅发送文件

import requests

url = 'http://www.eg.com/post'
files = {'file': open('C://Users//Someone//Desktop//2.png', 'rb')}
r = requests.post(url, files=files)
print(r.text)

3. 仅发送文件 定制文件名

import requests

url = 'http://www.eg.com/post'
files = {
    'file': ('test.png', open('C:\\Users\\Someone\\Desktop\\2.png', 'rb'))
    }
r = requests.post(url, files=files)
print(r.text)

方法2:
安装requests_toolbelt
pip install requests-toolbelt

1. 发送文件和参数

from requests_toolbelt import MultipartEncoder
import requests
 
m = MultipartEncoder(
 fields={'field0': 'value', 
 	'field1': 'value',
	'field2': ('filename', open('file.py', 'rb'), 'text/plain')})
r = requests.post('http://www.eg.com/post', data=m, headers={'Content-Type': m.content_type})

2. 仅发送参数,不发送文件

from requests_toolbelt import MultipartEncoder
import requests

m = MultipartEncoder(
  fields={'field0': 'value', 
  	'field1': 'value'})
r = requests.post('http://www.eg.com/post', data=m, headers={'Content-Type': m.content_type})

4. text/xml

它是一种使用 HTTP 作为传输协议,XML 作为编码方式的远程调用规范。典型的 XML-RPC
请求内容样式如下:

POST http://www.example.com HTTP/1.1 
Content-Type: text/xml
 
<?xml version="1.0"?>
<methodCall>
    <methodName>examples.getStateName</methodName>
    <params>
        <param>
            <value><i4>41</i4></value>
        </param>
    </params>
</methodCall>

如果用fiddler模拟请求的话,请求头和请求主体的内容可以这样构造:
在这里插入图片描述

代码实现

方法1:

import requests

xml = """my xml"""
headers = {'Content-Type': 'application/xml'}
requests.post('http://www.eg.com/post', data=xml, headers=headers)

方法2:
把xml作为一个文件来传输

import requests

def request_ws(request):
	with open(archivo_request,"r") as archivo:
    	request_data = archivo.read()

target_url = "http://www.eg.com/post"
headers = {'Content-type':'text/xml'}
data_response = requests.post(target_url, data=request_data, headers=headers)

requests.request解析

def request(method, url, **kwargs):
    """Constructs and sends a :class:`Request <Request>`.

    :param method: method for the new :class:`Request` object.
    :param url: URL for the new :class:`Request` object.
    :param params: (optional) Dictionary or bytes to be sent in the query string for the :class:`Request`.
    :param data: (optional) Dictionary, bytes, or file-like object to send in the body of the :class:`Request`.
    :param json: (optional) json data to send in the body of the :class:`Request`.
    :param headers: (optional) Dictionary of HTTP Headers to send with the :class:`Request`.
    :param cookies: (optional) Dict or CookieJar object to send with the :class:`Request`.
    :param files: (optional) Dictionary of ``'name': file-like-objects`` (or ``{'name': file-tuple}``) for multipart encoding upload.
        ``file-tuple`` can be a 2-tuple ``('filename', fileobj)``, 3-tuple ``('filename', fileobj, 'content_type')``
        or a 4-tuple ``('filename', fileobj, 'content_type', custom_headers)``, where ``'content-type'`` is a string
        defining the content type of the given file and ``custom_headers`` a dict-like object containing additional headers
        to add for the file.
    :param auth: (optional) Auth tuple to enable Basic/Digest/Custom HTTP Auth.
    :param timeout: (optional) How long to wait for the server to send data
        before giving up, as a float, or a :ref:`(connect timeout, read
        timeout) <timeouts>` tuple.
    :type timeout: float or tuple
    :param allow_redirects: (optional) Boolean. Set to True if POST/PUT/DELETE redirect following is allowed.
    :type allow_redirects: bool
    :param proxies: (optional) Dictionary mapping protocol to the URL of the proxy.
    :param verify: (optional) whether the SSL cert will be verified. A CA_BUNDLE path can also be provided. Defaults to ``True``.
    :param stream: (optional) if ``False``, the response content will be immediately downloaded.
    :param cert: (optional) if String, path to ssl client cert file (.pem). If Tuple, ('cert', 'key') pair.
    :return: :class:`Response <Response>` object
    :rtype: requests.Response

    Usage::

      >>> import requests
      >>> req = requests.request('GET', 'http://httpbin.org/get')
      <Response [200]>
    """

请求参数-代码示例

def param_method_url():
    # requests.request(method='get', url='http://127.0.0.1:8000/test/')
    # requests.request(method='post', url='http://127.0.0.1:8000/test/')
    pass


def param_param():
    # - 可以是字典
    # - 可以是字符串
    # - 可以是字节(ascii编码以内)

    # requests.request(method='get',
    # url='http://127.0.0.1:8000/test/',
    # params={'k1': 'v1', 'k2': '水电费'})

    # requests.request(method='get',
    # url='http://127.0.0.1:8000/test/',
    # params="k1=v1&k2=水电费&k3=v3&k3=vv3")

    # requests.request(method='get',
    # url='http://127.0.0.1:8000/test/',
    # params=bytes("k1=v1&k2=k2&k3=v3&k3=vv3", encoding='utf8'))

    # 错误
    # requests.request(method='get',
    # url='http://127.0.0.1:8000/test/',
    # params=bytes("k1=v1&k2=水电费&k3=v3&k3=vv3", encoding='utf8'))
    pass


def param_data():
    # 可以是字典
    # 可以是字符串
    # 可以是字节
    # 可以是文件对象

    # requests.request(method='POST',
    # url='http://127.0.0.1:8000/test/',
    # data={'k1': 'v1', 'k2': '水电费'})

    # requests.request(method='POST',
    # url='http://127.0.0.1:8000/test/',
    # data="k1=v1; k2=v2; k3=v3; k3=v4"
    # )

    # requests.request(method='POST',
    # url='http://127.0.0.1:8000/test/',
    # data="k1=v1;k2=v2;k3=v3;k3=v4",
    # headers={'Content-Type': 'application/x-www-form-urlencoded'}
    # )

    # requests.request(method='POST',
    # url='http://127.0.0.1:8000/test/',
    # data=open('data_file.py', mode='r', encoding='utf-8'), # 文件内容是:k1=v1;k2=v2;k3=v3;k3=v4
    # headers={'Content-Type': 'application/x-www-form-urlencoded'}
    # )
    pass


def param_json():
    # 将json中对应的数据进行序列化成一个字符串,json.dumps(...)
    # 然后发送到服务器端的body中,并且Content-Type是 {'Content-Type': 'application/json'}
    requests.request(method='POST',
                     url='http://127.0.0.1:8000/test/',
                     json={'k1': 'v1', 'k2': '水电费'})


def param_headers():
    # 发送请求头到服务器端
    requests.request(method='POST',
                     url='http://127.0.0.1:8000/test/',
                     json={'k1': 'v1', 'k2': '水电费'},
                     headers={'Content-Type': 'application/x-www-form-urlencoded'}
                     )


def param_cookies():
    # 发送Cookie到服务器端
    requests.request(method='POST',
                     url='http://127.0.0.1:8000/test/',
                     data={'k1': 'v1', 'k2': 'v2'},
                     cookies={'cook1': 'value1'},
                     )
    # 也可以使用CookieJar(字典形式就是在此基础上封装)
    from http.cookiejar import CookieJar
    from http.cookiejar import Cookie

    obj = CookieJar()
    obj.set_cookie(Cookie(version=0, name='c1', value='v1', port=None, domain='', path='/', secure=False, expires=None,
                          discard=True, comment=None, comment_url=None, rest={'HttpOnly': None}, rfc2109=False,
                          port_specified=False, domain_specified=False, domain_initial_dot=False, path_specified=False)
                   )
    requests.request(method='POST',
                     url='http://127.0.0.1:8000/test/',
                     data={'k1': 'v1', 'k2': 'v2'},
                     cookies=obj)


def param_files():
    # 发送文件
    # file_dict = {
    # 'f1': open('readme', 'rb')
    # }
    # requests.request(method='POST',
    # url='http://127.0.0.1:8000/test/',
    # files=file_dict)

    # 发送文件,定制文件名
    # file_dict = {
    # 'f1': ('test.txt', open('readme', 'rb'))
    # }
    # requests.request(method='POST',
    # url='http://127.0.0.1:8000/test/',
    # files=file_dict)

    # 发送文件,定制文件名
    # file_dict = {
    # 'f1': ('test.txt', "hahsfaksfa9kasdjflaksdjf")
    # }
    # requests.request(method='POST',
    # url='http://127.0.0.1:8000/test/',
    # files=file_dict)

    # 发送文件,定制文件名
    # file_dict = {
    #     'f1': ('test.txt', "hahsfaksfa9kasdjflaksdjf", 'application/text', {'k1': '0'})
    # }
    # requests.request(method='POST',
    #                  url='http://127.0.0.1:8000/test/',
    #                  files=file_dict)

    pass


def param_auth():
    from requests.auth import HTTPBasicAuth, HTTPDigestAuth

    ret = requests.get('https://api.github.com/user', auth=HTTPBasicAuth('wupeiqi', 'sdfasdfasdf'))
    print(ret.text)

    # ret = requests.get('http://192.168.1.1',
    # auth=HTTPBasicAuth('admin', 'admin'))
    # ret.encoding = 'gbk'
    # print(ret.text)

    # ret = requests.get('http://httpbin.org/digest-auth/auth/user/pass', auth=HTTPDigestAuth('user', 'pass'))
    # print(ret)
    #


def param_timeout():
    # ret = requests.get('http://google.com/', timeout=1)
    # print(ret)

    # ret = requests.get('http://google.com/', timeout=(5, 1))
    # print(ret)
    pass


def param_allow_redirects():
    ret = requests.get('http://127.0.0.1:8000/test/', allow_redirects=False)
    print(ret.text)


def param_proxies():
    # proxies = {
    # "http": "61.172.249.96:80",
    # "https": "http://61.185.219.126:3128",
    # }

    # proxies = {'http://10.20.1.128': 'http://10.10.1.10:5323'}

    # ret = requests.get("http://www.proxy360.cn/Proxy", proxies=proxies)
    # print(ret.headers)


    # from requests.auth import HTTPProxyAuth
    #
    # proxyDict = {
    # 'http': '77.75.105.165',
    # 'https': '77.75.105.165'
    # }
    # auth = HTTPProxyAuth('username', 'mypassword')
    #
    # r = requests.get("http://www.google.com", proxies=proxyDict, auth=auth)
    # print(r.text)

    pass


def param_stream():
    ret = requests.get('http://127.0.0.1:8000/test/', stream=True)
    print(ret.content)
    ret.close()

    # from contextlib import closing
    # with closing(requests.get('http://httpbin.org/get', stream=True)) as r:
    # # 在此处理响应。
    # for i in r.iter_content():
    # print(i)


def requests_session():
    import requests

    session = requests.Session()

    ### 1、首先登陆任何页面,获取cookie

    i1 = session.get(url="http://dig.chouti.com/help/service")

    ### 2、用户登陆,携带上一次的cookie,后台对cookie中的 gpsd 进行授权
    i2 = session.post(
        url="http://dig.chouti.com/login",
        data={
            'phone': "8615131255089",
            'password': "xxxxxx",
            'oneMonth': ""
        }
    )

    i3 = session.post(
        url="http://dig.chouti.com/link/vote?linksId=8589623",
    )
    print(i3.text)

requests.Response

requests.Response是服务器对服务器响应的封装,这里不详细介绍,其属性和方法请看如下源码。

  • 属性:可以直接调用获取响应中对应的数据,如 response.status_code 获取响应码,调用时无小括号
  • 方法:可调用方法获取信息,如 response.json() 获取响中的json内容
# 属性列表
__attrs__ = [
        '_content', 'status_code', 'headers', 'url', 'history',
        'encoding', 'reason', 'cookies', 'elapsed', 'request'
    ]
        status_code
		#: Integer Code of responded HTTP Status, e.g. 404 or 200.

        headers
        #: Case-insensitive Dictionary of Response Headers.
        #: For example, ``headers['content-encoding']`` will return the
        #: value of a ``'Content-Encoding'`` response header.

        raw
        #: File-like object representation of response (for advanced usage).
        #: Use of ``raw`` requires that ``stream=True`` be set on the request.
        #: This requirement does not apply for use internally to Requests.

        url
        #: Final URL location of Response.

        encoding
        #: Encoding to decode with when accessing r.text.

        history
        #: A list of :class:`Response <Response>` objects from
        #: the history of the Request. Any redirect responses will end
        #: up here. The list is sorted from the oldest to the most recent request.

        reason
        #: Textual reason of responded HTTP Status, e.g. "Not Found" or "OK".

        cookies
        #: A CookieJar of Cookies the server sent back.

        elapsed
        #: The amount of time elapsed between sending the request
        #: and the arrival of the response (as a timedelta).
        #: This property specifically measures the time taken between sending
        #: the first byte of the request and finishing parsing the headers. It
        #: is therefore unaffected by consuming the response content or the
        #: value of the ``stream`` keyword argument.

        request
        #: The :class:`PreparedRequest <PreparedRequest>` object to which this
        #: is a response.
@property
    def ok(self):
        """Returns True if :attr:`status_code` is less than 400, False if not.

        This attribute checks if the status code of the response is between
        400 and 600 to see if there was a client error or a server error. If
        the status code is between 200 and 400, this will return True. This
        is **not** a check to see if the response code is ``200 OK``.
        """
@property
    def is_redirect(self):
        """True if this Response is a well-formed HTTP redirect that could have
        been processed automatically (by :meth:`Session.resolve_redirects`).
        """
@property
    def is_permanent_redirect(self):
        """True if this Response one of the permanent versions of redirect."""
@property
    def next(self):
        """Returns a PreparedRequest for the next request in a redirect chain, if there is one."""
@property
    def apparent_encoding(self):
        """The apparent encoding, provided by the chardet library."""
    def iter_content(self, chunk_size=1, decode_unicode=False):
        """Iterates over the response data.  When stream=True is set on the
        request, this avoids reading the content at once into memory for
        large responses.  The chunk size is the number of bytes it should
        read into memory.  This is not necessarily the length of each item
        returned as decoding can take place.

        chunk_size must be of type int or None. A value of None will
        function differently depending on the value of `stream`.
        stream=True will read data as it arrives in whatever size the
        chunks are received. If stream=False, data is returned as
        a single chunk.

        If decode_unicode is True, content will be decoded using the best
        available encoding based on the response.
        """
@property
    def content(self):
        """Content of the response, in bytes."""
@property
    def text(self):
        """Content of the response, in unicode.

        If Response.encoding is None, encoding will be guessed using
        ``chardet``.

        The encoding of the response content is determined based solely on HTTP
        headers, following RFC 2616 to the letter. If you can take advantage of
        non-HTTP knowledge to make a better guess at the encoding, you should
        set ``r.encoding`` appropriately before accessing this property.
        """
@property
    def links(self):
        """Returns the parsed header links of the response, if any."""

以下是对象方法

    def json(self, **kwargs):
        r"""Returns the json-encoded content of a response, if any.

        :param \*\*kwargs: Optional arguments that ``json.loads`` takes.
        :raises ValueError: If the response body does not contain valid json.
        """
    def close(self):
        """Releases the connection back to the pool. Once this method has been
        called the underlying ``raw`` object must not be accessed again.

        *Note: Should not normally need to be called explicitly.*
        """
    def iter_lines(self, chunk_size=ITER_CHUNK_SIZE, decode_unicode=False, delimiter=None):
        """Iterates over the response data, one line at a time.  When
        stream=True is set on the request, this avoids reading the
        content at once into memory for large responses.

        .. note:: This method is not reentrant safe.
        """

WEB式接口介绍和实现

WEB式接口

在接口测试中,除了常规的独立接口测试,经常出现的场景还有另外一种测试WEB接口,抓包web请求,实现web接口的调用。
比如模拟web登陆,登陆后做其他的接口调用操作。

接口请求思路

实现思路如下:

  1. 创建一个session
  2. 通过session发起登陆请求:注意请求方式和参数,可以从响应内容中判断是否是登陆成功后的html,此时session已经是登陆后的状态
  3. 通过session发送POST/GET请求
  4. 若系统存在其他站点跳转,可通过session请求站点的首页进行session状态的跳转,再做站点的WEB请求

代码实现

# -*- coding:utf-8 -*-
import requests

account = "test11"
password = "pwd1234"
url = "http://www.eg.com"

def by_session():
    # 创建session,登陆系统
    session = requests.Session()
    login_url = url + "/login"  # 登陆地址
    data = {"account": account, "password": password}
    response = session.post(login_url, data=data)
    print(response.status_code)
    print("--------------------------------------")
    
    # 跳转到其他站点,让session拥有其他站点的登陆状态
    other_website = "http://www.demo.com/index.html"
    response = session.get(other_website)  # 有参数可以添加参数
    print(response.status_code)
    print("--------------------------------------")

    # 访问接口
    urls = "http://www.demo.com/getInfo"
    data = {"key1": "value1", "key2": "value2"}
    response = session.post(urls, data=data)
    print(response.status_code)
    print(response.text)


if __name__ == '__main__':
    by_session()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值