Loadrunner-http请求脚本编写
1、基本知识
一般的http报文可以简单分成三个部分组成:请求行、请求头部以及请求包体,如下
POST /view/all/createItem HTTP/1.1
Host: 127.0.0.1:8080
Content-Length: 133
Cache-Control: max-age=0
sec-ch-ua: "Not:A-Brand";v="99", "Chromium";v="112"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Linux"
Upgrade-Insecure-Requests: 1
Origin: http://127.0.0.1:8080
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.5615.50 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: http://127.0.0.1:8080/view/all/newJob
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Cookie: security_level=0; jms_csrftoken=322BxA9O9q2ldCnt0WtlhdZjEPiqzVqK; SESSION_COOKIE_NAME_PREFIX=jms_; jms_public_key="LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlHZk1BMEdDU3FHU0liM0RRRUJBUVVBQTRHTkFEQ0JpUUtCZ1FEcENvV1A1aFljenREeW91L243Nlgwb254WApiU2Y4N3RUbEdnMVpsZ1ZOd000R0ZkRWFmTUpWMDMwLzM1TnNHSzFlVXpIOWVJVC9USi9YWTEwVnYzL3lnbjFNCmZpTDF4VlZlOXFobk4xY3JPa2xOaGx3TlNMTVU2bXE4S0dHU3BJblpuTGlKcUxMVHI0V003WUZCVXRKeVdwQ0sKeHgwb1BZd015d0pGWUV4UlB3SURBUUFCCi0tLS0tRU5EIFBVQkxJQyBLRVktLS0tLQ=="; jms_sessionid=207rc0jrmea7r7d0gmt2ahkr7lcne9qy; JSESSIONID=node01t7r0zibe4j74u62seqxgmwtn0.node0; screenResolution=1918x918; iconSize=16x16; JSESSIONID.7d6d4932=18q02hpt9i0yq1mnhram5ujinn
Connection: close
name=demo&mode=hudson.model.FreeStyleProject&json=%7B%22name%22%3A+%22demo%22%2C+%22mode%22%3A+%22hudson.model.FreeStyleProject%22%7D
其中请求行信息主要包括请求方法、url、协议版本,如下
POST /view/all/createItem HTTP/1.1
一般常见的请求方法有:GET、POST、DELETE、PUT等等。
请求头部信息主要包括Host、Content-Length、Content-Type、User-Agent、Accept、Referer、Accept-Encoding、Accept-Language、Cookie、Authorization等等。
Host: 127.0.0.1:8080
Content-Length: 133
Cache-Control: max-age=0
sec-ch-ua: "Not:A-Brand";v="99", "Chromium";v="112"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Linux"
Upgrade-Insecure-Requests: 1
Origin: http://127.0.0.1:8080
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.5615.50 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: http://127.0.0.1:8080/view/all/newJob
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Cookie: security_level=0; jms_csrftoken=322BxA9O9q2ldCnt0WtlhdZjEPiqzVqK; SESSION_COOKIE_NAME_PREFIX=jms_; jms_public_key="LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlHZk1BMEdDU3FHU0liM0RRRUJBUVVBQTRHTkFEQ0JpUUtCZ1FEcENvV1A1aFljenREeW91L243Nlgwb254WApiU2Y4N3RUbEdnMVpsZ1ZOd000R0ZkRWFmTUpWMDMwLzM1TnNHSzFlVXpIOWVJVC9USi9YWTEwVnYzL3lnbjFNCmZpTDF4VlZlOXFobk4xY3JPa2xOaGx3TlNMTVU2bXE4S0dHU3BJblpuTGlKcUxMVHI0V003WUZCVXRKeVdwQ0sKeHgwb1BZd015d0pGWUV4UlB3SURBUUFCCi0tLS0tRU5EIFBVQkxJQyBLRVktLS0tLQ=="; jms_sessionid=207rc0jrmea7r7d0gmt2ahkr7lcne9qy; JSESSIONID=node01t7r0zibe4j74u62seqxgmwtn0.node0; screenResolution=1918x918; iconSize=16x16; JSESSIONID.7d6d4932=18q02hpt9i0yq1mnhram5ujinn
Connection: close
其中Content-Type的值比较常见的有:application/json、application/x-www-form-urlencoded、multipart/form-data;boundary=–、text/xml等。
在Connection以下的部分信息就是请求包体信息,如下
name=demo&mode=hudson.model.FreeStyleProject&json=%7B%22name%22%3A+%22demo%22%2C+%22mode%22%3A+%22hudson.model.FreeStyleProject%22%7D
2、Loadrunner http请求脚本代码示例&方法使用说明
1、GET请求示例代码
web_url("checkJobName",
"URL=http://192.168.139.129:8080/view/all/checkJobName?value=t",
"Resource=0",
"RecContentType=text/html",
"Referer=http://192.168.139.129:8080/view/all/newJob",
"Snapshot=t28.inf",
"Mode=HTML",
LAST);
2、POST请求示例代码
web_custom_request("start",
"URL=http://192.168.139.129:8080/$stapler/bound/04f3d797-1440-4d42-b143-ad5e7e3ddda4/start",
"Method=POST",
"Resource=0",
"Referer=http://192.168.139.129:8080/view/all/builds",
"Snapshot=t14.inf",
"Mode=HTML",
"EncType=application/x-stapler-method-invocation;charset=UTF-8",
"Body=[]",
LAST);
web_submit_data("data_10",
"Action=http://192.168.139.129:8080/view/all/timeline/data/",
"Method=POST",
"RecContentType=application/javascript",
"Referer=http://192.168.139.129:8080/view/all/builds",
"Snapshot=t25.inf",
"Mode=HTML",
ITEMDATA,
"Name=min", "Value=1706659200000", ENDITEM,
"Name=max", "Value=1706745600000", ENDITEM,
LAST);
在上面的示例中是常见的三种http请求方法web_url()
、web_custom_request()
、web_submit_data()
。
3、Loadrunner三种常见http请求方法使用说明
-
web_url
: 加载指定页面数据(GET请求)int web_url( const char *StepName, const char *url, <List of Attributes>, [EXTRARES, <List of Resource Attributes>,] LAST );
在web_url方法中主要接受三个参数–请求步骤名称、url以及属性列表,它还可以接受扩展属性列表,主要装载请求中可能需要的其他资源,最后参数LAST表示参数结束标识。
在示例代码中checkJobName是请求步骤名称,可以供后续其他函数的调用。
常见的 List of Attributes 如下属性名称 属性解释 RecContentType 在录制过程中,响应头的内容类型,例如text/html,application/json,这是为了确定目标URL是否是可记录的资源 Referer 引用网页的URL。引用当前页面的页面。如果位置是明确表示的,则省略此属性 Resource 描述该url是否为资源,0表示不是静态资源,1表示是静态资源 Snapshot 快照文件的文件名(inf扩展名) Mode 录制级别:HTML或HTTP。在并发组中的web_url请求上不允许使用“Mode=HTML”。在并发组中,不解析下载的资源寻找要下载的附加对象的响应。单击录制级别/模式(Web)以获取详细信息 UserAgent 标识将执行该步骤的浏览器以外的组件,例如,在浏览器下运行的ActiveX组件。此用户代理标头是为步骤发出的请求而发送的。不进行任何检查以确认用户代理参数是否与浏览器的用户代理运行时设置匹配。非浏览器步骤不会影响模拟的浏览器上下文,也不会根据结果构建新的上下文 -
web_custom_request()
:允许使用http支持的任何方法创建自定义http请求int web_custom_request( const char *RequestName, <List of Attributes>, [EXTRARES, <List of Resource Attributes>,] LAST);
在web_custom_request方法是一个操作函数,可以使用任何方法或主体创建自定义http请求,在action的脚本中使用这个函数时,可以配合web_add_header
或web_add_auto_header
函数一起使用。
常见的 List of Attributes 如下属性名称 属性解释 RecContentType 在录制过程中,响应头的内容类型,例如text/html,application/json,这是为了确定目标URL是否是可记录的资源 URL 可以是HTTP、HTTPS或FTP协议 Method HTTP协议支持的任何方法 EncType EncType指定了Content-Type,比如"text/html",作为当前重播的"Content-Type"请求头的值。web_custom_request不执行任何主体编码。任何EncType规范都会默默地覆盖任何web_add_[auto_]header的Content-Type。如果指定"EncType=“(空值),则不会生成"Content-Type"请求标头。如果省略了"EncType”,则使用任何适用的web_add_[auto_]header。如果没有标头并且"Method=POST",则使用"application/x–www–form–urlencoded"作为默认值。否则,不会生成Content-Type请求标头。 Body参数指定要按原样使用的主体。如果需要主体编码,则应已将其应用于脚本中输入的Body参数。因此,指定与主体不匹配的EncType可能会导致服务器端错误。一般来说,建议您不要编辑记录的EncType RecContentType 指定“Content-Type”响应头值为记录的内容,例如text/html,application/x-javascript。当未指定Resource属性时,RecContentType值用于确定目标URL是否为资源 Referer 引用网页的URL。引用当前页面的页面。如果位置是明确表示的,则省略此属性 Body, BodyBinary, BodyUnicode, or RAW_BODY_START 请求的主体作为属性参数Body、BodyBinary或BodyUnicode的值传递。主体可以是单个参数,也可以被分成多个主体段,也就是一系列的参数。例如,对web_custom_request的以下调用将主体分成三个段:一个unicode部分,然后是一个二进制部分,最后是常规文本。最终的主体是所有三个部分按照它们传递给函数的顺序连接在一起的结果 Row Body 指向请求主体的指针被传递给函数 BodyFilePath 作为请求正文传递的文件的路径名。指定完整路径名或相对于脚本文件夹的路径名。BodyFilePath不能与Body或任何Body属性或原始Body属性一起使用:BodyBinary、BodyUnicode或Raw_Body_START -
web_submit_data()
:执行无条件或无上下文的表单提交。int web_submit_data( const char *StepName, const char *Action, <List of Attributes>, ITEMDATA, <List of data>, [ EXTRARES, <List of Resource Attributes>,] LAST );
web_submit_data函数是一个执行“无条件”或“无上下文”表单提交的操作函数。(脚本中的每个Web操作函数都会使浏览器显示新的网页或框架。VuGen可以记录所有Web操作函数。)此函数允许您生成HTML表单发出的GET和POST请求。执行此请求不需要表单上下文。只有当VuGen处于基于URL的录制模式,或处于基于HTML的录制模式且选中“仅包含明确URL的脚本”选项时(请参阅VuGen的录制选项),才会录制web_submit_data。该方法指示如何将表单的数据发送到服务器,无论是作为URL中的查询(GET),还是作为请求体(POST)。当VuGen设置为以HTTP(来自服务器的所有请求)记录模式记录web会话时,会生成此函数。VuGen还会在提交表单且无法生成web_submit_form语句时记录一个web_submit _data语句。
EncType属性指定要指定为“Content–Type”请求头的内容类型。它指示用于从其他参数生成HTTP请求的编码类型(URL编码或多部分编码)。允许的规格为:
-
“EncType=application/x–www–form–urlencoded”
-
“EncType=multipart/form–data” (any “; boundary=” is silently ignored)
-
“EncType=” (一个空字符串,表示不生成“Content–Type”请求头)
Item Data属性,用来存放data的参数集合,比如在一个表单提交请求里,如下
POST /securityRealm/createAccountByAdmin HTTP/1.1 Host: 127.0.0.1:8080 Content-Length: 242 Cache-Control: max-age=0 sec-ch-ua: "Not:A-Brand";v="99", "Chromium";v="112" sec-ch-ua-mobile: ?0 sec-ch-ua-platform: "Linux" Upgrade-Insecure-Requests: 1 Origin: http://127.0.0.1:8080 Content-Type: application/x-www-form-urlencoded User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.5615.50 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7 Sec-Fetch-Site: same-origin Sec-Fetch-Mode: navigate Sec-Fetch-User: ?1 Sec-Fetch-Dest: document Referer: http://127.0.0.1:8080/securityRealm/addUser Accept-Encoding: gzip, deflate Accept-Language: en-US,en;q=0.9 Cookie: security_level=0; jms_csrftoken=322BxA9O9q2ldCnt0WtlhdZjEPiqzVqK; SESSION_COOKIE_NAME_PREFIX=jms_; jms_public_key="LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlHZk1BMEdDU3FHU0liM0RRRUJBUVVBQTRHTkFEQ0JpUUtCZ1FEcENvV1A1aFljenREeW91L243Nlgwb254WApiU2Y4N3RUbEdnMVpsZ1ZOd000R0ZkRWFmTUpWMDMwLzM1TnNHSzFlVXpIOWVJVC9USi9YWTEwVnYzL3lnbjFNCmZpTDF4VlZlOXFobk4xY3JPa2xOaGx3TlNMTVU2bXE4S0dHU3BJblpuTGlKcUxMVHI0V003WUZCVXRKeVdwQ0sKeHgwb1BZd015d0pGWUV4UlB3SURBUUFCCi0tLS0tRU5EIFBVQkxJQyBLRVktLS0tLQ=="; jms_sessionid=207rc0jrmea7r7d0gmt2ahkr7lcne9qy; JSESSIONID=node01t7r0zibe4j74u62seqxgmwtn0.node0; iconSize=16x16; JSESSIONID.7d6d4932=18q02hpt9i0yq1mnhram5ujinn; screenResolution=1918x1038; JSESSIONID.09357c90=udalyoeq50dq1bsg0vl260fd4 Connection: close username=visitor&password1=visi2024&password2=visi2024&fullname=visitor&json=%7B%22username%22%3A+%22visitor%22%2C+%22password1%22%3A+%22visi2024%22%2C+%22password2%22%3A+%22visi2024%22%2C+%22fullname%22%3A+%22visitor%22%7D&Submit=Create+User
对应的ItemData内容,如下
ITEMDATA, "Name=username", "Value=visitor", ENDITEM, "Name=password1", "Value=visi2024", ENDITEM, "Name=password2", "Value=visi2024", ENDITEM, "Name=fullname", "Value=visitor", ENDITEM, "Name=json", "Value={\"username\": \"visitor\", \"password1\": \"visi2024\", \"password2\": \"visi2024\", \"fullname\": \"visitor\"}", ENDITEM, "Name=Submit", "Value=新建用户", ENDITEM,
这里的Name是参数名称,value是对应的值,ENDITEM是一个结束标识符。
比如在一个文件上传的请求里,如下POST /vulnerabilities/upload/ HTTP/1.1 Host: 127.0.0.1:81 Content-Length: 532 Cache-Control: max-age=0 sec-ch-ua: "Not:A-Brand";v="99", "Chromium";v="112" sec-ch-ua-mobile: ?0 sec-ch-ua-platform: "Linux" Upgrade-Insecure-Requests: 1 Origin: http://127.0.0.1:81 Content-Type: multipart/form-data boundary=----WebKitFormBoundaryBJ11egIvXUskACMd User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.5615.50 Safari/537.36 Connection: close ------WebKitFormBoundaryBJ11egIvXUskACMd Content-Disposition: form-data; name="MAX_FILE_SIZE" 100000 ------WebKitFormBoundaryBJ11egIvXUskACMd Content-Disposition: form-data; name="uploaded"; filename="demo.txt" Content-Type: text/plain Hello world ------WebKitFormBoundaryBJ11egIvXUskACMd Content-Disposition: form-data; name="Upload" Upload ------WebKitFormBoundaryBJ11egIvXUskACMd Content-Disposition: form-data; name="user_token" 3ce9fd94590f21dbe49a27d771bad123 ------WebKitFormBoundaryBJ11egIvXUskACMd--
对应的ITEMDATA内容
"EncType=multipart/form-data", "RecContentType=text/html", "Mode=HTML", ITEMDATA, "Name=MAX_FILE_SIZE", "Value=100000", ENDITEM, "Name=uploaded", "Value=demo.txt", "File=Yes", ENDITEM, "Name=Upload", "Value=Upload", ENDITEM, "Name=user_token", "Value=decb4201680fd4cf177ceb98941d5f77", ENDITEM,
-
常见的参数化使用说明
常见的参数化大致可分为两种:一是对于某个参数值赋予一个由函数生成或文件读取的变量值,一是通过一个请求的返回结果中的某个参数值赋给一个变量值。
在jmeter中设置变量可以通过【测试计划】中的【用户定义的变量】、【CSV Data Set Config】、【Bean shell前/后处理程序】、【正则提取器】完成,变量值赋予可以通过【函数助手工具】、提取器(正则、json、边界、jquery等)、文件数据读取。
在loadrunner里可以通过定义变量或使用函数web_reg_save_param()/web_reg_save_param_ex()、web_reg_save_param_regexp()、lr_save_timestamp()、lr_save_string()等
1、loadrunner的变量定义
1、常见定义变量,如下示例代码
Action()
{
// 声明变量Max_len值为4
#define Max_len 4
// 定义字符指针
char *demo = NULL;
char string_var[] = "base for you";
lr_log_message("%s", string_var);
// 通过strcpy函数给指针demo赋值
strcpy(&demo, string_var);
lr_log_message("%s", &demo);
return 0;
}
2、通过函数定义变量和读取变量值,常用函数有lr_save_string()、lr_eval_string(),详细使用见下例代码
Action()
{
// 声明变量Max_len值为4
#define Max_len 4
// 定义字符指针
char *demo = NULL;
char string_var[] = "base for you";
//通过lr_save_string函数将字符串值赋给string_var变量
lr_save_string("base for you", "string_var");
// 通过lr_eval_string函数读取变量string_var的值
lr_log_message("%s", lr_eval_string("{string_var}"));
// 通过strcpy函数给指针demo赋值
strcpy(&demo, lr_eval_string("{string_var}"));
lr_log_message("%s", &demo);
// 截取string_var的Max_len的值赋给new_var
lr_save_var(lr_eval_string("{string_var}"), Max_len, 0, "new_var");lr_log_message("%s", lr_eval_string("{new_var}"));
return 0;
}
3、通过web_reg_save函数定义变量并赋值,它的放置位置要在http请求的前面,执行效果类似jmeter的后置处理器效果
-
web_reg_save_param()/web_reg_save_param_ex()
,其中web_reg_save_param()
函数在C版本里不支持,在C语言版本用web_reg_save_param_ex()
替代。int web_reg_save_param_ex( "ParamName=<output parameter name>", [LB[/IC][BIN]=<value>, ] [RB[/IC][BIN]=<value>, ] <List of Attributes>, <SEARCH FILTERS>, LAST);
其中LB、RB对应的是指定内容的截取边界。LB不指定值,或者设置为空字符串,则web_reg_save_param_ex将使用数据的开头作为左边界。LB/IC表示边界也会匹配,LB/BIN表示匹配转义的二进制代码匹配边界。
在loadrunner中可以通过【Steps Toolbox】来插入内部函数,如下图
示例代码如下:Action() { web_reg_save_param_ex( "ParamName=token_value", "LB=data:{\"token\":\"", "RB=\"", SEARCH_FILTERS, "Scope=BODY", LAST); web_custom_request("demotoken", "URL=http://127.0.0.1:8990/login/token", "Method=POST", "TargetFrame=", "Resource=0", "Referer=", "Body={\"username\":\"admin\",\"password\":\"ZGVtbw==\"}", LAST); return 0; }
-
web_reg_save_param_regexp()
实现通过正则表达式将请求返回的动态数据保存到一个变量中。示例代码如下Action() { web_reg_save_param_regexp( "ParamName=token", "RegExp=(?<=token\": \").+(?=\",)", "Group=0", SEARCH_FILTERS, "Scope=BODY", LAST); web_submit_data("login.php", "Action=http://127.0.0.1:9080/login/token", "Method=POST", "RecContentType=text/html", "Snapshot=t147.inf", "Mode=HTML", ITEMDATA, "Name=username", "Value=admin", ENDITEM, "Name=password", "Value=password", ENDITEM, LAST); lr_log_message("%s", lr_eval_string("{token}")); return 0; }