打开我们上次没写完的P_apis.htm
找到这个error_play函数,我们已经替换好了请求体,那么接下来就把新请求体和接口id传递给后台即可
在以下俩个位置加上对应传递后台的代码:
我们把接口id和新请求体传给后台。所以去写urls.py:
然后去写views.py:
这个函数的功能就是实际发出请求获取请求体,再把请求体返回给前端了。
整个代码和我们调试层传递的类似。但是调试层发送请求的函数的所有接口数据都是从前端获取。而异常值发送请求函数的所有接口数据基本是靠着接口id从数据库获取,然后请求体用前端传过来的新请求体:
代码如下:
# 异常值发送请求
def error_request(request):
api_id = request.GET['api_id']
new_body = request.GET['new_body']
api = DB_apis.objects.filter(id=api_id)[0]
method = api.api_method
url = api.api_url
host = api.api_host
header = api.api_header
body_method = api.body_method
header = json.loads(header)
if host[-1] == '/' and url[0] =='/': #都有/
url = host[:-1] + url
elif host[-1] != '/' and url[0] !='/': #都没有/
url = host+ '/' + url
else: #肯定有一个有/
url = host + url
if body_method == 'form-data':
files = []
payload = {}
for i in eval(new_body):
payload[i[0]] = i[1]
response = requests.request(method.upper(), url, headers=header, data=payload, files=files)
elif body_method == 'x-www-form-urlencoded':
header['Content-Type'] = 'application/x-www-form-urlencoded'
payload = {}
for i in eval(new_body):
payload[i[0]] = i[1]
response = requests.request(method.upper(), url, headers=header, data=payload)
elif body_method == 'Json':
header['Content-Type'] = 'text/plain'
response = requests.request(method.upper(), url, headers=header, data=new_body.encode('utf-8'))
else:
return HttpResponse('非法的请求体类型')
# 把返回值传递给前端页面
response.encoding = "utf-8"
return HttpResponse(response.text)
当然我现在不知道这个接口是否存在bug,在未进行测试的前提下,没人能保证没问题。
所以我们加入点print,来看看有没有问题,因为咱手里现在也没有能正常访问的接口。大家看看请求体没问题就可以了:
当然前端页面我们上节就证明没问题了:
后端加入:
开始测试:
经过测试,发现出现了问题。这个问题的情况就是后台没有成功获取到替换后的请求体,我们可以理解为,这个传输过程发生了错误或传输成功,但是后台解析不了。
那么具体什么错误呢?前端明明可以正常发出去,为啥后台就解析不了呢?
原因是请求体中的二维数组无法直接传递,必须变成字符串。包括我们常见的json,其实都是json格式的字符串而已。只能等到后台接收到之后,再用eval来进行还原成二维数组或字符串了。
所以前端我们要进行变换:
然后我们再测试看看后台输出:
可以看到,虽然输出的并不完善,但是起码解析出来了。
我们忽略掉 这个请求根本没有返回值的报错:(因为url都是随便写,我们可以之后用自己公司的实际接口测试,但是要注意,这个请求频率非常快,接近并发,请不要随意尝试,一瞬间几百个请求出去,你们服务器可能会报警...)
这里我们发现了一个bug,就是我们貌似所有的替换值 都变成了字符串?明明我们要测试的场景里还有整形等。
其实是因为我们之前在js中进行替换的时候,全部当成字符串替换,其实应该替换的是忠实的原始用户需求格式,也就是我们需要对其进行求值再替换:所以这里变成eval()
然后我们开始测试raw-json的格式替换了:
代码中加上我们之前的俩处修正:
点击开始测试,看看前端console.log的输出如何:
看起来没啥问题,后台输出也可以正常获取解析新请求体:
接下来就要开始这个功能的最后一个部分了。
那就是返回值的显示效果。当然我们现在接口都请求不通,也就没有返回值。那么没返回值的情况怎么办呢?我们也不能等着服务器后台报错。所以这里请求我们加上一个try来捕获吧。
一个简单的方法是把下面的整个大请求代码段都try了。
然后测试发现不报错了。
然后我们前端其实此时已经成功拿到了返回值,虽然返回值现在都是“对不起,接口未通!” 我们就来做一下动态生成html代码,来看看最终效果,之后我们有机会再找个可以请求通的接口来测试。
再次打开P_apis.html
我们本应该在这俩个请求的返回函数中 都写上这段动态生成的代码,但是考虑到代码量应该不少,所以我们最好是新建一个js函数,专门负责展示。然后在这俩个返回函数中调用它即可:
声明了一个error_show_response后,在下面俩处进行调用:
我们把返回值ret 作为参数传递貌似不够,因为我们还要知道这个ret对应的替换规则是什么。
所以我们这里要进行替换规则这个字符串的构造:
这个span_text 就是我们的替换标题
接下来给error_show_response(ret) 加上这个参数:
之后我们把注意力全部放在这个error_show_response(span_text,ret)里吧:
我们现在分析下,我们已经拿到了返回体。那么就应该新建一个多行文本框或者来显示就好了,格式就和我们最开始的demo一样,demo等我们写完代码后就删除了。
所以代码如下:
function error_show_response(span_text,ret) {
var error_div = document.getElementById('error_div'); // 声明这个请求体展示窗口
var s = document.createElement('span'); //创造替换标题
s.innerText = span_text;
var t = document.createElement('textarea'); //传教替换内容多行文本
t.style = 'width: 99%;height: 50px;border-radius: 5px;color: black;margin-bottom: 10px';
t.value = ret;
error_div.appendChild(s);
error_div.appendChild(t);
}
然后进行测试,发现结果如下:
貌似全部展示成功了。但是仔细观察却发现了一个超大的bug,就是所有的替换标题文案 ,都一样...
那么这里问题出在哪了呢?
我们只能在各个位置,打印这些文案,看看究竟出在哪了
如上图,我们在最小的这个循环体内,俩个位置分别打印了这个span_text,并且前面加上了标记 1 和2 然后看看最终效果
这里我们发现,是因为2开头的时候,输出的貌似都出了问题。那么这个原因我们可以来猜测一下:
首先奇怪的是,明明12次循环,为啥下面的2开头输出,会在最后位置输出?
还有就是,为啥显示的都是12次循环最后一次的值 b-->中文 ?
聪明的同学已经知道原因所在了,就是这个js循环的执行顺序是 12次循环先执行完,发出去请求就不管了,并不会等到第一次请求返回,再开始第二次循环。
简单来说,就是12次请求 先执行完,过了一会,12次请求的返回体才陆续到位,而这时span_text这个变量早已被12次请求的最后一次b-->中文赋值了。
所以显示的都是这最后一个值。
那么这个问题我们要怎么解决呢?
这里提供几种思路:
3. 在变量上想办法,做一个变量标题数组,存入所有标题,当调用的时候再依次提取。
4. 在发出请求的时候,带上这个替换标题,再原封不动的返回。
其实这个现象很好比喻:
就像你有12门火炮。 你可以按顺序,依次发射。但是你无法预测和决定炮弹落地的顺序。然后你要炮弹落地后,根据现场混乱的弹坑,来分辨出都是哪门火炮炸的,这显然很困难。
所以我们在上述四个方案中,选择最简单的,第四种。让炮弹发射出去的时候,贴上标签。落地后标签掉在弹坑里,你就自然能分清了。
后台函数:
那么后台我们之前每次返回基本都是只返回一个字符串,也就是一般只返回一个参数字段。那么我们现在要返回的是俩个。要怎么做呢?
你可以进行字符串拼接,然后前端拿到后再给分割开。
你也可以标准一点,做一个json串来加入,前端再进行解析即可。
我们采用标准方法,所以返回代码这么写:
然后前端接收到之后 这么解析:
重启服务,刷新页面,开始测试:
发现其实效果已经不错了,没有出现对不上号的情况,我们把对应的修改 给放入到上面的二维数组中吧:
放好后,我们修改接口的请求体类型为form-data,来测试一下:
发现仍然可以成功。
但是最后我们仍然留下了一个小问题,就是貌似他们的显示顺序并不是一开始我们排好的预期的。这是因为各个请求体的返回速度不同,先回来的就先抢到了位置了。其实这并不影响实际使用,实际使用中,基本是几百个请求返回体,没人关注他们的摆放顺序,基本就是大致扫一眼,看看没有服务器严重报错的情况就结束测试了。发现有引起服务器报错的,就看一下替换标题记录下来就可以了。
最后别忘了删除那个demo:
然后最后就要解决一下我们上节遗留的bug了
就是请求体raw-json格式带换行的情况下,打开报错怎么处理。
发生问题的原因,在于我们html代码中,调用error_test时,按钮的html代码因为换行导致了浏览器解析它失败。
解决方案有很多。其实严格来说,一般区区一个按钮内的onclick要传这么大量的数据,本就不是一个好办法。万一数据中含有一些引号,双引号,括号,<>等 其实相当于 破坏了html结构,属于一种变异的病毒攻击常用手段。 换行符只是其中一种引起报错的情况,即便我们解决了换行符,后面也许还会经常互相各种特殊符合引起的html结构错乱的报错。
所以我们这里最好放弃这么直接传输,那么我们可能马上就想到,通过其他拐弯抹角的方式 把这个值传给error_play。但是其实进入页面的时候,我们给的接口数据,只是给了html。js没有办法直接获得,只能张嘴等html传给它,或者html里用比如input记录下,然后js根据接口id去提取。
所以这里公布俩种解决方案:
我们选用第一种简单方式。
先加入隐藏的input :
注意这个input我开始没有隐藏,和放入的位置。看看页面显示效果:
值是成功存储的,再看看动态id:
然后我们给它隐藏:
现在去掉我们之前旧的传输参数
给error_test 加入自己提取api_body的代码:
然后再来测试下,我们之前打开报错的带换行情况的接口:
发现已经可以成功打开并且开启异常测试了!
好了,异常测试的章节 暂时告一段落了。后续我们还会进行优化和功能添加。