【藏经阁】http请求的网络测试环境构造

百度QA2018-11-08 17:52:26

在日常测试中,有时候需要构造服务返回的各种情况,比如HTTP测试中,对不同下游返回的情况,服务应该做出不同的处理,本文先介绍一次HTTP请求的过程,然后介绍如何构造不同的返回结果来进行测试。

 

01

一次完整的HTTP请求过程


图一 简单http请求示意图


以上是简单的一次http请求的过程示意,其中client向server发送请求的时候,构造的http的请求报文如下:


图二 请求包报文


请求方法有8种:GET、POST、PUT、DELETE、PATCH、HEAD、OPTIONS、TRACE,下面异常构造主要是用get方法。


在请求数据中可以有name=test&target=get的形式,就是以键值对形式编码成一个格式化串,它承载多个请求参数的数据。不但报文体可以传递请求参数,请求URL也可以通过类似于“/test.html?name=test&target=get”的方式传递请求参数,在第二部分中构造任意错误码返回的时候,会使用在url中设置参数的方式传送数据。


响应报文主要是协议版本,状态码,响应报文头和响应报文体。其中协议版本与请求报文一致,状态码描述是对状态码的简单描述。


状态代码为3位数字。

1xx:指示信息--表示请求已接收,继续处理。

2xx:成功--表示请求已被成功接收、理解、接受。

3xx:重定向--要完成请求必须进行更进一步的操作。

4xx:客户端错误--请求有语法错误或请求无法实现。

5xx:服务器端错误--服务器未能实现合法的请求。     


主要针对 4XX 和5XX的构造异常状态,一般真实构造以上错误码没种情况不一样会比较麻烦,所以第二部分构造根据客户端给出的code可以让server真实返回的错误码也是code。


02

构造不同返回状态码


本段是client向server发出请求之后,server能返回各种不同的状态码,可以在支持php的webroot下进行配置index.php。


代码如下:

<?php

$return_code = 200;

if  (isset($_GET["code"])) {

      $return_code  = intval($_GET["code"]);

}

header('Temporary-Header: True',  true, $return_code);

header_remove('Temporary-Header');

 

以上代码的内容是默认返回状态码为200,如果收到的get请求中包含code字段,那么在相应包的返回码设置上请求包的状态码。


然后使用header函数返回原生的HTTP头,header的定义如下:

void header ( string $string [,  bool $replace = true [, int $http_response_code ]] )

 

在php版本5.3之上。可以使用:

header('Temporary-Header: True', true,  $return_code);

header_remove('Temporary-Header');


设置返回包的头包含的状态码,就是第三个字段是设置的状态码,这样就强制给设置的机器发送http请求带的code会被server返回的包带上。


示意图如下:

图三 构造状态码示意图


依据以上示例,在测试的时候可以发送各种错误码给配置好的server,然后就会返回相应的错误码,如下图所示是使用浏览器发送了一个带有code=404的请求,在client收到返回后的包头的状态码就是404.


图四 简server返回client发送的状态码

 

03

构造异常网络情况


01

iptables构造网络异常

在测试中,有时候需要构造一些网络异常情况,比如读写超时、连接重置、慢连接等,本文介绍iptables用来模拟以上异常情况的方法。


Iptables命令是linux上常用的防火墙软件,通过控制Linux内核netfilter模块,来管理网络数据包的流动与转送。


使用基本语法是:

iptables [-t 表名] 命令选项 [链名] [条件匹配][-j 目标动作或跳转]

 

1)首先了解一下在什么样的网络状况下会出现连接重置

网络层协议TCP正常的网络连接需要三次握手,而断开连接需要四次挥手,有些网络情况下会导致无法完成四次挥手释放连接,此时TCP有一种异常终止连接的方法,就是tcp-reset。以下列举了两个常见会出现RESET的情况:


  • client与server交互过程中,如果某一方发生异常,比如请求量过大,程序异常崩溃等,出问题的端会向对方发送连接重置

  • 建立TCP连接之后的交互双方,在传输过程一端长期没有收到对方的报文,并且超出重传次数和时间后,会向对方发送连接重置


下面使用iptables设置防火墙INPUT链规则,直接server端返回tcp-reset来构造连接重置的情况。


2)设置连接过来的请求的过滤规则

iptables -I INPUT -p tcp --dport 80 -m string --algobm  --string "RESET" -j REJECT --reject-with tcp-reset

 

图五 设置防火墙构造连接重置


以上命令设置的是对输入链INPUT新增规则,发送到8240端口的 tcp请求,如果链接带了RESET字段,就直接tcp-reset,也就是连接重置。

 

3)sudo iptables-L -n --line-numbers,显示现有防火墙策略是否设置成功,可以看到设置的规则。


图六 防火墙设置


4)那么设置成功之后,我们发送http://host:80/RESET。只要包含RESET字段的链接都会收到以下返回:Connection reset by peer。

   

图七 连接重置返回


5)iptables还可以构造其他网络异常情况,有连接超时、读、写超时、读写中连接断开和慢连接。


02

TC+netem网络流量控制工具,

构造网络异常

netem是网络模拟功能模块,可以模拟出复杂的互联网传输性能,诸如低带宽、传输延迟、丢包等等情况。而tc用来控制netem的工作模式。


1)Tc+netem模拟网络丢包

tc  qdisc  add   dev  eth0  root   netem  loss  6%

该命令将 eth0 网卡的传输设置为随机丢掉 6% 的数据包。


本文设置100%丢包后,设置丢包之后通过ping给设置的服务器发包查看:

图八 tc+netem丢包设置


会100%丢包,慎用! 100%会导致登录机器都登录失败。


2)tc和netem还可以用来进行模拟延迟传输、模拟包重复、模拟包损坏和乱序。


3)iptables同样可以模拟网络丢包


以上我们是用tcnetem模拟网络丢包,iptables同样可以模拟网络丢包,我们使用:

iptables -I INPUT -p  tcp --dport 80  -m statistic --mode  random --probability 0.31  -j DROP

 

同样类似以上服务重置的配置,这里设置了INPUT表中每个访问80端口的tcp包都有0.31的丢包概率。


设置后之后,在设置前后访问被设置丢包的服务,分别抓取TCP包如图九:

图九 丢包前抓取TCP包


从图中可以看到,交互的三次握手后,http应用层包的交互,之后是完整的四次挥手。


设置丢包之后的抓包情况如图十:

图十 丢包后抓取TCP包


传输层的tcp包有概率性丢包,所以从图中看到箭头标记的重传包,实在丢包之后进行可靠性重传,最后同样能获取到server的数据。


作者介绍

贾金莉

贾金莉,华中科技大学计算机科学与技术硕士,现为百度个人云部测试开发工程师,负责百度网盘的测试工作。




Copyright © 丰城计算器学习组@2017