在LR中当使用HTML录制方式时,录制的脚本中主要由函数web_link()、web_submit_form()、web_url()、web_submit_data()组成,当使用HTTP录制方式时,录制的脚本中主要由函数web_url()、web_submit_data()组成,主要区别在于:
当使用HTML录制时得到的函数更接近用户的实际操作,脚本代码相对较少且易于理解一些,但是函数之间有前后依赖关系,耦合度较高,其中web_link()用于模拟用户点击页面上的链接;web_url()用于请求某个链接,Mode的值为HTML,如果某个链接页面上有大量的非html元素,例如:js、css、vbs、activeX、applets、各种格式的图片等,则按照录制时的设置来处理,默认为也录制到脚本步骤中,即web_url()函数的EXTRARES选项中,另外,也可以设置成不录制或录制到并发组web_concurrent_start(NULL)和web_concurrent_end(NULL)之间的web_url()函数中。
当使用HTTP录制时得到的函数将包含所有请求内容,每一项需要请求的内容都会得到一个web_url()函数,Mode的值为HTTP,因此脚本中会有大量的web_url()函数,且一般不带EXTRARES选项,得到的脚本没有很强的前后依赖关系,相对HTMP脚本的耦合度低一些,请求的内容也更全一些,一般只在很标准B/S模式下才会选用HTML,多数时候都可以选用HTTP的方式来录制。另外在该录制模式下,也可以设置选择是否使用并发组函数web_concurrent_start()和web_concurrent_end(),如选择则在很多非HTML的元素的请求前后都会加上并发组函数,还可以选择是否只使用自定义函数web_custom_request(),如选择则得到的脚本中所有的web_url()、web_submit_data()函数都将由函数web_custom_request()替代之。
本文的主角web_custom_request()终于上场了,web_custom_request()函数是一个可以用于自定义http请求的“万能”函数,具有web_link()、web_url()、web_submit_data()函数的功能,一般当自定义请求时可以配合函数web_add_auto_header()、web_add_header()等系列函数来自定义其请求头,web_custom_request()函数的Mode字段为HTML时相当于使用HTML录制方式的函数,Mode字段为HTTP时相当于使用URL录制方式的函数,Method字段可以为GET和POST分别用于模拟http的get和post请求。
该函数web_custom_request()的具体参数说明可以参见本片文章结尾的附录。
当使用web_custom_request()函数来发送http的get和post请求时,如果不使用web_add_header相关函数来自定义添加头部,请求中是否带有默认的头部字段?通过使用抓包工具来查看发出的请求中的头部字段:
脚本一:
web_custom_request("web_custom_request",
"URL=http://www.baidu.com",
"Method=GET",
"TargetFrame=",
"Resource=0",
"Referer=",
"Mode=HTTP",
"Body=123",
LAST);
脚本一实际发出的请求:
GET / HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT)
Accept-Encoding: gzip, deflate
Accept: */*
Connection: Keep-Alive
Host: www.baidu.com
Content-Length: 3
123
脚本二:
web_custom_request("web_custom_request",
"URL=http://www.baidu.com",
"Method=POST",
"TargetFrame=",
"Resource=0",
"Referer=",
"Mode=HTTP",
"Body=abcd",
LAST);
脚本二实际发出的请求:
POST / HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Cache-Control: no-cache
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT)
Accept-Encoding: gzip, deflate
Accept: */*
Connection: Keep-Alive
Host: www.baidu.com
Content-Length: 4
abcd
由此可知,在使用web_custom_request()函数来模拟HTTP请求时,发出的请求中默认带有部分的http请求头部字段,具体字段如上,如需要修改默认的头部字段或增加其他头部字段就在web_custom_request()函数的前面使用web_add_header()函数来添加,如果要减少某个头部字段或全部自动添加的头部字段就在web_custom_request()函数的前面使用web_remove_auto_header()和web_revert_auto_header(),头部字段所有请求中公共的一些头部可以放在web_add_auto_header()函数中,配合web_add_header系列函数来完成自定义的业务脚本。
web_custom_request函数之Body详解:
1. Body:
一般情况下Body中内容是作为字面值进行发送的,Body中也可以发送二进制流(用十六进制表示),方法如下,但仅限二进制流中不含空字符x00,如果一段Body的二进制流中有空字符,则web_custom_request实际发送的内容为第一个空字符之前的数据,其后的数据(包括空)都会被截断。
例如:
1.1 Body内容不含空字符x00
1 web_custom_request("web_custom_request", 2 "URL=http://www.baidu.com", 3 "Method=POST", 4 "TargetFrame=", 5 "Resource=0", 6 "Referer=", 7 "Mode=HTTP", 8 "Body=x3dx9dx1dxefxa4x04x41", 9 LAST);
发送数据包的Body内容为:
1.2 Body内容含空字符x00
1 web_custom_request("web_custom_request", 2 "URL=http://www.baidu.com", 3 "Method=POST", 4 "TargetFrame=", 5 "Resource=0", 6 "Referer=", 7 "Mode=HTTP", 8 "Body=x3dx00x9dx1dxefxa4x00x04x41", 9 LAST);
发送数据包的Body内容为:
因此使用Body是无法发送含有空的二进制数据流的,此外,Body中的内容可以使用参数替代,web_custom_request函数的整个Body字符串参数("Body=abcd")也是可以使用一个变量(数组或字符指针)来替代的,注意点:1、变量中的内容不需要含有双引号,例如:char BodyVar[20] = "Body=abcd"; 2、使用变量时后面加一个逗号,例如:BodyVar, 。
2. BodyBinary:
当要发送的二进制数据流中含有空时可以使用BodyBinary来发送,注意下面的代码,发送的请求中第一个空之后的数据仍然被截断, 发送数据包的Body内容同1.2中的截图:
1 web_custom_request("web_custom_request", 2 "URL=http://www.baidu.com", 3 "Method=POST", 4 "TargetFrame=", 5 "Resource=0", 6 "Referer=", 7 "Mode=HTTP", 8 "BodyBinary=x3dx00x9dx1dxefxa4x00x04x41x00x00x42", 9 LAST);
正确的写法如下,使用两个转义字符:
1 web_custom_request("web_custom_request", 2 "URL=http://www.baidu.com", 3 "Method=POST", 4 "TargetFrame=", 5 "Resource=0", 6 "Referer=", 7 "Mode=HTTP", 8 "BodyBinary=\x3d\x00\x9d\x1d\xef\xa4\x00\x04\x41\x00\x00\x42", 9 LAST);
也可以如下这样写,只在出现空的地方用两个反斜杠:
1 web_custom_request("web_custom_request", 2 "URL=http://www.baidu.com", 3 "Method=POST", 4 "TargetFrame=", 5 "Resource=0", 6 "Referer=", 7 "Mode=HTTP", 8 "BodyBinary=x3d\x00x9dx1dxefxa4\x00x04x41\x00\x00x42", 9 LAST);
发送数据包的Body内容为:
即二进制数据流中含有空也是可以发送的,上面一栏显示的是八进制表示。BodyBinary中的内容同样可以使用参数替代,整个BodyBinary字符串参数同样可以使用变量替换。如下:
1 char *sendbufhex = "\x3d\x00\x9d\x1d\xef\xa4\x00\x04\x41\x00\x00\x42"; 2 lr_save_string(sendbufhex,"sendbufhexParam"); 3 4 web_custom_request("web_custom_request", 5 "URL=http://www.baidu.com", 6 "Method=POST", 7 "TargetFrame=", 8 "Resource=0", 9 "Referer=", 10 "Mode=HTTP", 11 "BodyBinary={sendbufhexParam}", 12 LAST);
1 char *sendbufhexBody = "BodyBinary=\x3d\x00\x9d\x1d\xef\xa4\x00\x04\x41\x00\x00\x42"; 2 3 4 web_custom_request("web_custom_request", 5 "URL=http://www.baidu.com", 6 "Method=POST", 7 "TargetFrame=", 8 "Resource=0", 9 "Referer=", 10 "Mode=HTTP", 11 sendbufhexBody, 12 LAST);
但是当参数或变量中的内容并不是上面这样直接赋值一个常量字符串,而是通过其他拆分拼接而来时,就只需要使用一个反斜杆,比如:我要发送的的一串二进制流的十六进制字符串为:3d009d1defa4000441000042,参数写法代码如下:
1 char sendbuf[100] ="3d009d1defa4000441000042"; 2 char sendbufhex[100]; 3 char temp[100]; 4 int sendbuflen,i; 5 6 sendbuflen = strlen(sendbuf); 7 memset(sendbufhex,'