基于 Flask 实现的一个简易 Mock 平台,使用标准 json 结构体编写 Mock Api https://github.com/yinquanwang/MockServer
GET
、POST
、PUT
、DELETE
常用 http 请求方式@app.route('/<path:path>', methods=['GET', 'PUT', 'DELETE', 'POST'])
def dispatch_request(path):
"""
mock view logic
:param path: request url for mock server
:return: response msg that use default or custom defined
"""
m = models.Api.query.filter_by(url=request.path, method=request.method).first_or_404()
body = json.loads(m.body)
return domain_server(**body)
@app.errorhandler(404)
def url_not_found(error):
return json.dumps({
"status": 404,
"msg": "the request url not found,please check"
})
VALID = {
"success": True,
"code": "0000",
"msg": "success"
}
INVALID = {
'code': '0020',
'msg': 'request data invalid',
'success': False
}
MISS = {
'code': '0021',
'msg': 'request data missed',
'success': False
}
TYPE_NOT_MATCH = {
"success": False,
"code": "0001",
}
EQUALS = {
"success": False,
"code": "0005",
}
NOT_BETWEEN = {
"success": False,
"code": "0007",
}
STR_NOT_CONTAINS = {
"success": False,
"code": "0004",
}
STR_TOO_LONG = {
"success": False,
"code": "0006",
}
class Validator:
"""
Validator for mock check
"""
@classmethod
def valid(cls, response=None):
return get_response(response, VALID)
@classmethod
def type_not_match(cls, type, data, response=None):
msg = '{data} must be {type} type'.format(data=data, type=type)
TYPE_NOT_MATCH['msg'] = msg
if type == 'int':
if not isinstance(data, int):
return get_response(response, TYPE_NOT_MATCH)
elif type == 'float':
if not isinstance(data, float):
return get_response(response, TYPE_NOT_MATCH)
elif type == 'string':
if not isinstance(data, str):
return get_response(response, TYPE_NOT_MATCH)
elif type == 'bool':
if not isinstance(data, bool):
return get_response(response, TYPE_NOT_MATCH)
elif type == 'list':
if not isinstance(data, list):
return get_response(response, TYPE_NOT_MATCH)
elif type == 'dict':
if not isinstance(data, dict):
return get_response(response, TYPE_NOT_MATCH)
else:
return False
@classmethod
def is_not_equals(cls, data, expect, response=None):
if data != expect:
msg = '{data} must be equals {expect}'.format(data=data, expect=expect)
EQUALS['msg'] = msg
return get_response(response, EQUALS)
else:
return False
@classmethod
def is_not_between(cls, data, between, response=None):
try:
min = between[0]
max = between[1]
except IndexError:
return {'msg': 'mock config error'}
if data > max or min < min:
msg = '{data} must be between in {between}'.format(data=data, between=between)
NOT_BETWEEN['msg'] = msg
return get_response(response, NOT_BETWEEN)
else:
return False
@classmethod
def is_not_contains(cls, data, expect, response=None):
if data not in expect:
msg = '{data} not in {expect}'.format(data=data, expect=expect)
STR_NOT_CONTAINS['msg'] = msg
return get_response(response, STR_NOT_CONTAINS)
else:
return False
@classmethod
def is_too_long(cls, data, length, response=None):
if len(data) > length:
msg = '{data} is too long, max length is {length}'.format(data=data, length=length)
STR_TOO_LONG['msg'] = msg
return get_response(response, STR_TOO_LONG)
else:
return False
def domain_server(**kwargs):
"""
used for POST PUT DELETE
:param kwargs: standard json mock scripts
:return: response msg
"""
data = kwargs.get('data', {})
invalid = kwargs.get('invalid', {})
if request.json:
form = request.json
elif request.form:
form = request.form
elif request.args:
form = request.args
if data is {}: # do not have any parameters
return Validator.valid(response=kwargs.get('valid'))
else:
if len(form) != len(data): # data do not matched
return json.dumps(MISS, ensure_ascii=False)
for key in form.keys():
if key not in data.keys():
return json.dumps(INVALID, ensure_ascii=False)
for key, value in form.items(): # usually validators
expect = data.get(key)
type = expect.get('type')
msg = Validator.type_not_match(type, value, response=invalid.get('type'))
if msg:
return msg
contains = expect.get('contains')
if contains:
msg = Validator.is_not_contains(value, contains, response=invalid.get('contains'))
if msg:
return msg
equals = expect.get('equals')
if equals:
msg = Validator.is_not_equals(value, equals, response=invalid.get('equals'))
if msg:
return msg
long = expect.get('long')
if long:
msg = Validator.is_too_long(value, long, response=invalid.get('length'))
if msg:
return msg
between = expect.get('between')
if between:
msg = Validator.is_not_between(value, between, response=invalid.get('between'))
if msg:
return msg
return Validator.valid(response=kwargs.get('valid'))
json
{
"data": {
"password": {
"equals": "lcc",
"type": "string"
},
"username": {
"equals": "lcc",
"type": "string"
}
},
"invalid": {
"equals": {
"msg": "恭喜啊,查询到该账号了"
},
"type": "类型不匹配啊"
},
"method": "GET",
"name": "查询接口",
"url": "/get/",
"valid": {
"msg": "查询成功啦",
"success": true
}
}
例如上述 json 结构体,此 get 请求有两个参数 username,password, type=string,equals=lcc ,规定了 valid 报文和 invalid 中的 equals 报文json
{
"data": {
"email": {
"equals": {
"lcc": "lcc@qq.com",
"yqw": "yqw@qq.com"
},
"type": "dict"
},
"password": {
"type": "string"
},
"username": {
"equals": "lcc",
"length": 10,
"type": "string"
}
},
"invalid": {
"equals": {
"msg": "哥们,类型不匹配啊"
},
"type": "类型不匹配啊"
},
"method": "POST",
"name": "注册接口",
"url": "/register/",
"valid": {
"msg": "注册成功啦"
}
}
json
{
"data": {
"identity": {
"equals": "1",
"type": "string"
}
},
"invalid": {
"equals": {
"msg": "啊哦 该账号没有记录哦"
},
"type": "类型不匹配啊"
},
"method": "put",
"name": "更新接口",
"url": "/put/",
"valid": {
"msg": "查询成功啦",
"success": true
}
}
json
{
"data": {
"account": {
"equals": "lcc123456",
"length": 10,
"type": "string"
}
},
"invalid": {
"equals": {
"msg": "啊哦 该账号没有记录哦"
},
"type": "类型不匹配啊"
},
"method": "delete",
"name": "删除接口",
"url": "/del/1/",
"valid": {
"msg": "删除成功啦",
"success": true
}
}
## 由于第一次接触 Flask,mock 的理解自己可能也有偏差,所以还请各位大神不要见怪python
USERNAME = 'root'
PASSWORD = 'lcc123456'
HOST = '127.0.0.1'
DB = 'MockServer'
bash
pip install -r requirements.txt
bash
python manage.py db init
python manage.py db migrate
python manage.py db upgrade
bash
python run.py