21年12月3日回顾此文,觉得 Response 虽然放到 dict 也能接受,但现在看来我建议还是封装为一个 Response 类。
上次我们完善了登录注册相关页面,还有后端接口,算是从 0 到 1 完成了一个功能的编码工作。可能前端部分会讲的比较粗糙,因为第一可能是笔者造诣不够,第二也跟我们直接从现有的框架进行改造有关,很多东西不是从0
写到1
,而是从1
到1.1
,但是后面不一样:
后面的页面都是咱们自己写,自己用,从0写到1
终端输入pip3 install requests
并执行。
要知道,咱们这是一个接口测试平台 (后续可能会集成 UI 自动化,但是这个笔者也还没有想好)。一个接口自动化平台,最核心的当然是对 api 的请求操作,所以咱们刻不容缓,加快进度,趁热打铁,来点干货吧。用requests
来协助我们完成接口自动化请求。
我们新建一个文件: middleware/HttpClient.py
import datetime
import requests
class Request(object):
def __init__(self, url, session=False, **kwargs):
self.url = url
self.session = session
self.kwargs = kwargs
if self.session:
self.client = requests.session()
return
self.client = requests
def get(self):
return self.request("GET")
@staticmethod
def get_elapsed(timer: datetime.timedelta):
if timer.seconds > 0:
return f"{timer.seconds}.{timer.microseconds // 1000}s"
return f"{timer.microseconds // 100}ms"
def request(self, method: str):
status_code = 0
elapsed = "-1ms"
try:
if method.upper() == "GET":
response = self.client.get(self.url, **self.kwargs)
elif method.upper() == 'POST':
response = self.client.post(self.url, **self.kwargs)
else:
response = self.client.request(method, self.url, **self.kwargs)
status_code = response.status_code
if status_code != 200:
return Request.response(False, status_code)
elapsed = Request.get_elapsed(response.elapsed)
data = response.json()
return Request.response(True, 200, data, response.headers, response.request.headers, elapsed=elapsed)
except Exception as e:
return Request.response(False, status_code, msg=str(e), elapsed=elapsed)
def post(self):
return self.request("POST")
@staticmethod
def response(status, status_code=200, response=None, response_header=None,
request_header=None, elapsed=None, msg="success"):
request_header = {k: v for k, v in request_header.items()}
response_header = {k: v for k, v in response_header.items()}
return {
"status": status, "response": response, "status_code": status_code,
"response_header": response_header, "request_header": request_header,
"msg": msg, "elapsed": elapsed,
}
如果我是产品经理的话,那么 postman 就是我的原型图:
讲解一下各个方法,首先这是一个Request
请求类,他拥有核心方法: request
,目前咱们暂时先只做到支持 json 类的请求,后续补全form
, file
等类型的请求。
其实这个类做的事情很简单,就是把 requests 相关的方法剥离了出来,封装了一层。
其中构造函数提供了一些选项,包括请求的信息,url,是否以 session 的方式请求等等,kwargs 涵盖了 requests 原生的参数,只要你想传,你都可以传进来。
get_elapsed
是根据 postman 为参照,对请求时间做的一个处理,如果大于 1s 的请求响应时间,那我们以秒
为单位显示,否则以毫秒
为单位显示。
response
是构造返回结构对象,对本次请求的数据进行整理。
request
就封装了 requests 库的核心操作,基本上属于原生处理,并且判断了 http 状态码。
新建 controllers/request/http.py
from flask import Blueprint
from flask import jsonify
from flask import request
from app.middleware.HttpClient import Request
req = Blueprint("request", __name__, url_prefix="/request")
@req.route("/http", methods=['POST'])
def http_request():
data = request.get_json()
method = data.get("method")
if not method:
return jsonify(dict(code=101, msg="请求方式不能为空"))
url = data.get("url")
if not url:
return jsonify(dict(code=101, msg="请求地址不能为空"))
body = data.get("body")
headers = data.get("headers")
r = Request(url, data=body, headers=headers)
response = r.request(method)
return jsonify(dict(code=0, data=response, msg="操作成功"))
其实和登录/注册接口都很相似,基本上就是创立了一个 blueprint,前缀是/request,后续就是引入刚才的 request 类,进行 http 请求,最后返回 response。
我们新建了一个蓝图,需要去 run.py 进行注册:
from app.controllers.request.http import req
pity.register_blueprint(req)
本节内容就到这里了,下一节咱们编写属于自己的第一个组件: postman
。又是前端内容了,咱们做一个接近 postman 的页面,实现基础的在线发送 http 请求的功能即可。
后端代码地址: https://github.com/wuranxu/pity
前端代码地址: https://github.com/wuranxu/pityWeb