web_custom_request()函數是一個可以用于自定義http請求的“萬能”函數,一般當自定義請求時可以配合函數web_add_auto_header()、web_add_header()等系列函數來自定義其請求頭,web_custom_request()函數的Mode字段為HTML時相當于使用HTML錄制方式的函數,Mode字段為HTTP時相當于使用URL錄制方式的函數,Method字段可以為GET和POST分別用于模擬http的get和post請求。
請求頭的內容,可以結合抓包工具進行分析(比如:fiddler)
腳本一:
1 web_custom_request("test1",
2 "URL=http://www.baidu.com",
3 "Method=GET",
4 ?"TargetFrame=",
5 "Resource=0",
6 "Referer=",
7 "Mode=HTTP",
8 "Body=123",
9 LAST);
腳本一實際發出的請求:
10 GET / HTTP/1.1
11 User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT)
12 Accept-Encoding: gzip, deflate
13 Accept: */*
14 Connection: Keep-Alive
15 Host: www.baidu.com
1 6 Content-Length: 3
123
25腳本二:
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=abcd",
9 LAST);
腳本二實際發出的請求:
1 POST / HTTP/1.1
2 Content-Type: application/x-www-form-urlencoded
3 Cache-Control: no-cache
4 User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT)
5 Accept-Encoding: gzip, deflate
6 Accept: */*
7 Connection: Keep-Alive
8 Host: www.baidu.com
9 Content-Length: 4
10 abcd
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=\x3d\x9d\x1d\xef\xa4\x04\x41",
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=\x3d\x00\x9d\x1d\xef\xa4\x00\x04\x41",
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中的截圖:
1web_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\\x00\\x9d\\x1d\\xef\\xa4\\x00\\x04\\x41\\x00\\x00\\x42",
9 LAST);
即二進制數據流中含有空也是可以發送的,上面一欄顯示的是八進制表示。
BodyBinary中的內容同樣可以使用參數替代,整個BodyBinary字符串參數同樣可以使用變量替換。如下:
1 char*sendbufhex ="\\x3d\\x00\\x9d\\x1d\\xef\\xa4\\x00\\x04\\x41\\x00\\x00\\x42";
2 lr_save_string(sendbufhex,"sendbufhexParam");
3 web_custom_request("web_custom_request",
4 "URL=http://www.baidu.com",
5 "Method=POST",
6 "TargetFrame=",
7 "Resource=0",
8 "Referer=",
9 "Mode=HTTP",
10 "BodyBinary={sendbufhexParam}",
11 LAST);
12 char*sendbufhexBody ="BodyBinary=\\x3d\\x00\\x9d\\x1d\\xef\\xa4\\x00\\x04\\x41\\x00\\x00\\x42";
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 sendbufhexBody,
9 LAST);
但是當參數或變量中的內容并不是上面這樣直接賦值一個常量字符串,而是通過其他拆分拼接而來時,就只需要使用一個反斜桿,比如:我要發送的的一串二進制流的十六進制字符串為:3d009d1defa4000441000042,參數寫法代碼如下:
1 charsendbuf[100] ="3d009d1defa4000441000042";
2 charsendbufhex[100];
3 chartemp[100];
4 intsendbuflen,i;
5 sendbuflen = strlen(sendbuf);
6 memset(sendbufhex,'\0',sizeof(sendbufhex));
7 for(i=0;i
8 {
9 memset(temp,'\0',sizeof(temp));
10 temp[0] ='\\';
11 temp[1] ='x';
12 temp[2] = sendbuf[i];
13 temp[3] = sendbuf[i+1];
14 lr_output_message("Notify:temp:%s",temp);
15 strcat(sendbufhex,temp);
16 }
17 lr_output_message("Notify:sendbufhex:%s",sendbufhex);
18 lr_save_string(sendbufhex,"sendbufhexParam");
19 lr_output_message("Notify:sendbufhexParam:%s",lr_eval_string("{sendbufhexParam}"));
20 web_custom_request("web_custom_request",
21 "URL=http://www.baidu.com",
22 "Method=POST",
23 "TargetFrame=",
24 "Resource=0",
25 "Referer=",
26 "Mode=HTTP",
27 "BodyBinary={sendbufhexParam}",
28 LAST);
特別注意:拼接的參數中只需要一個飯斜杠而不是兩個飯斜杠,”3d009d1defa4000441000042" ?==》 "\x3d\x00\x9d\x1d\xef\xa4\x00\x04\x41\x00\x00\x42"
變量替換寫法代碼如下:
1 charsendbuf[100] ="3d009d1defa4000441000042";
2 charsendbufhex[100];
3 chartemp[100];
4 intsendbuflen,i;
5 sendbuflen = strlen(sendbuf);
6 lr_output_message("Notify:sendbuflen:%d",sendbuflen);
7 memset(sendbufhex,'\0',sizeof(sendbufhex));
8 strcat(sendbufhex,"BodyBinary=");
9 for(i=0;i
10 {
11 memset(temp,'\0',sizeof(temp));
12 temp[0] ='\\';
13 temp[1] ='x';
14 temp[2] = sendbuf[i];
15 temp[3] = sendbuf[i+1]??? ;
16 lr_output_message("Notify:temp:%s",temp);
17 strcat(sendbufhex,temp);
18 }
19 lr_output_message("Notify:sendbufhex:%s",sendbufhex);
20 web_custom_request("web_custom_request",
21 "URL=http://www.baidu.com",
22 "Method=POST",
23 ?"TargetFrame=",
24 "Resource=0",
25 "Referer=",
26 "Mode=HTTP",
27 sendbufhex,
28 LAST);
3.?RAW_BODY
可用于發送json格式的數據:
1 ?web_custom_request("request",//隨便寫個名字
2 ?"Method=POST",//請求的方法
3 ?"URL=http://www.baidu.com",??????? //請求地址
4 ?"RecContentType=application/json",//指定相應頭的Content-Type,這里是JSON
5 ?"EncType=application/json",//指定請求頭的Content-Type,這里也是JSON
6 ?"Mode=HTML",
7 ?RAW_BODY_START,//請求BODY開始的標識符
8 "{\"userIds\":[1300000001,1300002029,1300003163],\"type\":0}",//BODY的內容
? 9 55,//上面一行BODY內容的長度
10 RAW_BODY_END,//請求BODY結束的標識符
11 LAST);
實際發送的數據內容為:
web_custom_request函數語法詳解
語法:
Int web_custom_request (const char *RequestName, ,[EXTRARES, ,] LAST );
返回值:
LR_PASS(0)代表成功
LR_FAIL(1)代表失敗。
參數:
1、RequestName:步驟的名稱,VuGen中樹形視圖中顯示的名稱。
2、List of Attribute:支持的屬性有以下幾種:
1)URL:
頁面地址。
2)Method :
頁面的提交方式,POST或GET。
3)EncType:
編碼類型。此參數給出一個內容類型(Content-Type),指定其做為回放腳本時“Content-Type”請求頭的值,例如“text/html”。Web_custom_request函數不處理未編碼的請求體。請求體參數將會使用已經指定的編碼方式。因此,如果指定了不匹配HTTP請求體的“EncType”,會引發服務端的錯誤。通常我們建議不要手動修改錄制時的“EncType”值。
任何對于“EncType”的指定都會覆蓋web_add_[auto_]header函數指定的Content-Type。當指定了“EncType=”(空值)時,不會產生“Content-Type” 請求頭。當省略了“EncType”時,任何一個web_add_[auto_]header函數都會起作用。如果既沒有指定EncType也沒有web_add_[auto_]header函且“Method=POST”,
“application/x-www-form-urlencoded”會做為默認值來使用。其他情況下,不會產生Content-Type請求頭。
4)BodyFilePath:
作為請求體傳送的文件的路徑。它不能與下面的屬性一起使用:Body,或者其他Body屬性或Raw Body屬性包括BodyBinary,BodyUnicode,RAW_BODY_START或Binary=1。
5)UserAgent:
用戶代理,它是一個HTTP頭的名字,用來標識應用程序,通常是瀏覽器,它呈現的是用戶和服務器的交互。
例如:頭信息“User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)”識別的是Window NT下的IE瀏覽器6.0。其他的User-Agent的值用來描述其他的瀏覽器,或者非瀏覽器程序。通常,一個應用程序中所有的請求都使用相同的用戶代理,錄制者作為一個運行時參數來指定(Run-Time Setting—Browser Emulation—User Agent)。不管怎么說,即使是在一個簡單的瀏覽器進程中,仍有可能會用到直接與服務器交互的非瀏覽器組件(例如ActiveX控件),通常他們有著不同于瀏覽器的用戶代理屬性。指定“UserAgent”表示這是一個非瀏覽器的請求。指定的字符串被HTTP頭“User-Agent:” 使用,在某些情況下,它同時會影響回放腳本時的行為。例如,不使用瀏覽器緩存,假設指定的URL屬于資源等等。(LoadRunner本身不檢查指定的字符串與瀏覽器本身的值是否相同)
6)Binary:
“Binary=1”表示頁面請求體中的每一個以file://x/##形式出現的值(在這里“##”代表2個十六進制數字),都會被替換為單字節的十六進制的值。如果“Binary=0”(默認值),所有的字符序列只是按照字面的值傳遞。需要注意雙斜杠的用法。在C編譯器中雙斜杠被解釋為單斜杠。如果不需要零字節,單斜杠可以在Binary不等于1的情況下使用(例如,使用\x20代替file://x20/)。如果需要零字節,那么只能使用file://x00/且設置 “Binary=1”,\x00在邏輯上會被截斷。
7)ContentEncoding
指定請求體的使用指定的方式(gzip或者deflate)進行編碼(例如,壓縮),相應的“Content-Encoding:” HTTP頭會和此請求一起發送。這個參數適用于web_custom_request和web_submit_data。
8)FtpAscii:
“1”使用ASCII模式處理FTP操作;"0" 使用二進制模式。
9)TargetFrame:
當前鏈接或資源所在Frame的名稱。除了Frame的名字,還可以指定下面的參數:
_BLANK:打開一個空窗口。
_PARENT:把最新更改過的的Frame替換為它的上級。
_SELF:替換最新更改過的的Frame。
_TOP:替換整個頁面。
10)RecContentType:
錄制腳本時響應頭的內容類型。例如text/html、 application/x-javascript等。當沒有設置Resource屬性時,用它來確定目標URL是否是可記錄的資源。此屬性包含主要的和次要的資源。最頻繁使用的類型是 text、application、image。次要的類型根據資源不同變化很多。例如:"RecContentType=text/html":表示html文本。"RecContentType=application/msword":表示當前使用的是Msword。
11)Referer:
當前頁面關聯的頁面。如果已經顯式指定了url的地址,此項可以省略。
12)Resource:
指示URL是否屬于資源。1 是;0 不是。設置了這個參數后,RecContentType參數被忽略。“Resource=1”,意味著當前操作與所在腳本的成功與否關系不大。在下載資源時如果發生錯誤,是當作警告而不是錯誤來處理的;URL是否被下載受“Run-Time Setting—Browser Emulation--Download non-HTML resources” 這個選項的影響。此操作的響應信息是不做為HTML來解析的。“Resource=0”,表明此URL是重要的,不受發送請求(RTS)的影響,在需要時也會解析它。
13)ResourceByteLimit:
web頁面下載資源的極限大小。當達到設置的極限后,無法下載其他資源。僅僅對需要下載的資源有效。下載過程:如果總計下載大小小于極限值,則正常開始下載。如果當下載時達到了設置的極限值,資源大小可知(在HTTP響應頭中指定了Content-Length),這中情況下,如果只需要一個緩沖區,那么下載可以正常完成。如果需要的不止一個緩沖區,或者資源大小不可知,下載就會中斷同時關閉當前連接。這個特性可以用來模擬用戶不等待一個頁面下載完成時導航到另一個頁面的情況。在HTTP模式中無法使用,在Concurrent Groups(Vuser腳本中的一個區,此區中的所有函數并發執行)區中也無法使用。僅僅適用于Sockets的回放,WinInet也是不適用的。
14)Snapshot:
快照的文件名。
15)Mode:
兩種錄制級別HTML、HTTP。HTML級別--在當前Web界面上錄制直觀的HTML動作。以一步步的web_url、web_link、web_image、web_submit_form來錄制這些動作。VuGen僅僅錄制返回HTML頁面的請求,不處理腳本和應用程序。HTTP級別--VuGen把所有的請求錄制為web_url指令,不生成web_link、web_image、web_submit_form這些函數。這種方法更為靈活,但是生成的腳本不夠直觀。
16)ExtraResBaseDir:
根URL,放在EXTRARES組里。它是用來解析相對URL的(譯者加:類似于Windows的相對路徑和絕對路徑)。URL可以是絕對路徑(例如http://weather.abc.com/weather/forecast.jsp?locCode=LFPO),也可以是相對路徑(例如“forecast.jsp?locCode=LFPO”)。真正的URL的下載是通過絕對路徑進行的,所以相對URL路徑必須使用根路徑URL去解析。例如,使用http://weather.abc.com/weather/做為根路徑來解析“forecast.jsp?locCode=LFPO”,最后的URL是:http://weather.abc.com/weather/forecast.jsp?locCode=LFPO。如果沒有指定“ExtraResBaseDir”,默認的根URL是主頁面的URL。
17)Body:
請求體。不同的應用中,請求體分別通過Body、BodyBinary或者BodyUnicode參數來傳遞。請求體可以只使用其中一個參數,也可以使用一連串的分開的參數組成多請求體。例如:
web_custom_request(
……
"BodyUnicode=REPRICE"
"BodyBinary=\\x08\\x00\\xCC\\x02\\x00\\x00"
"Body=.\r\n"
"-dxjjtbw/(.tp?eg:ch/6--\r\n",
LAST);
在上面的代碼中,使用了3個參數來劃分請求體,一個是Unicode段,一個是二進制段,最后一個是常規的字符串。最終的請求體是這3個參數按照在函數中的順序連接起來的值。還有一個很少用到的參數,Binary。它也能描述二進制請求體,但只允許函數中只有一個請求體參數。所有的請求體都是ASCII字符,以null結束。
Body--表示規則的,可打印的字符串。無法表示空字節。所有的字符都以一個反斜杠表示。注意:在舊的腳本中,可以看見不可打印的字符在請求體中以16進制方式進行編碼。(例如 “\\x5c”),在這種情況下,必須使用“Binary=1”來標識。空字節使用"file://0.0.0.0/"來表示。 相反,新腳本則會把把請求體分開放在不同的參數中("Body=...", "BodyBinary=...", Body=...")。
BodyBinary--表示二進制代碼。不可打印的字符在請求體中以16進制方式file://xhh/進行編碼。在這里HH 表示十六進制值。空字節使用"file://0.0.0.0/"來表示。
BodyUnicode--美國英語,特指拉丁UTF-16LE(little-endian)編碼。這種編碼方式會在在每個字符末尾附加一個0字節,以便使字符更可讀。但是在VuGen中實際的參數把所有的0字節都去掉的。但是在發送給Web服務器之前, web_custom_request函數會重新添加0字節的。對于不可打印的字符,使用單反斜杠表示,無法表示空字節。
注意:如果請求體大于100K,會使用一個變量來代替Body參數。變量是在 lrw_custom_body.h中定義的。
18)Raw Body:
請求體是作為指針傳遞的,此指針指向一串數據。 二進制的請求體可以使用BodyBinary 屬性來發送(或者使用Body 屬性來傳遞,前提是必設置
"Binary=1" )。無論如何,這種方法需要使用轉義字符反斜杠把不可打印的字符轉換為ASCII字符。為了能有一種更簡便的表現原始數據的方式,Raw Body屬性應運而生,可以傳遞指向二進制數據的指針。使用4個連續的參數集來表示指針,而且必須按照順序排列:
RAW_BODY_START
指向數據緩沖區的指針
(int) 長度
RAW_BODY_END
例子:
char *abc= .../* a pointer to the raw data */
web_custom_request("StepName",
"URL=http://some.url ",
"Method=POST",
RAW_BODY_START,
"abc",
3,
RAW_BODY_END,
LAST);
在應用中,即使設置了數據的長度為0,指針也必須有值,不能為空。在“Binary=1”時,不能使用上面的語法傳遞原始數據。數據緩沖區中的數據不能使用參數化。也就時說,緩沖區中的任何參數(例如 "{MyParam}")不能被正確的替代為相應的值,只會以字面值發送。
3、EXTRARES:表明下面的參數將會是List Of Resource Attributes了。
4、LAST :結尾的標示符。
5、List of Resource Attributes
僅僅當Recording Options--Recording --HTML-based script-- Record within the current script step選項被選中時,List of Resource Attributes才會被插入到代碼中。Web頁面中的非HTML機制產生了資源列表,包含了Javascript, ActiveX, Java applets and Flash所請求的資源。VuGen's 的Recording 選項中,可以設置把這些資源錄制在當前的操作中(默認是此設置)還是作為單獨的步驟來錄制。
不斷的總結,才能不斷的提高;不斷的思考,才能不斷的進步!