1. 程式人生 > >web_custom_request函式詳解(轉載) web_custom_request函式詳解

web_custom_request函式詳解(轉載) web_custom_request函式詳解

web_custom_request函式詳解

 

  在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=\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中的截圖:

複製程式碼
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\\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);
複製程式碼

 

 傳送資料包的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,'\0',sizeof(sendbufhex));
 8 
 9 for(i=0;i<sendbuflen;i+=2)
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 
20 lr_output_message("Notify:sendbufhex:%s",sendbufhex);
21 
22 lr_save_string(sendbufhex,"sendbufhexParam");
23 
24 lr_output_message("Notify:sendbufhexParam:%s",lr_eval_string("{sendbufhexParam}"));
25 
26 web_custom_request("web_custom_request",
27 "URL=http://www.baidu.com",
28 "Method=POST",
29 "TargetFrame=",
30 "Resource=0",
31 "Referer=",
32 "Mode=HTTP",
33 "BodyBinary={sendbufhexParam}",
34 LAST);    
複製程式碼

 

特別注意:拼接的引數中只需要一個飯斜槓而不是兩個飯斜槓,”3d009d1defa4000441000042"  ==》 "\x3d\x00\x9d\x1d\xef\xa4\x00\x04\x41\x00\x00\x42"

變數替換寫法程式碼如下:

複製程式碼
 1 char sendbuf[100] ="3d009d1defa4000441000042";
 2 char sendbufhex[100];
 3 char temp[100];
 4 int sendbuflen,i;
 5 sendbuflen = strlen(sendbuf);
 6 lr_output_message("Notify:sendbuflen:%d",sendbuflen);
 7 
 8 memset(sendbufhex,'\0',sizeof(sendbufhex));
 9 strcat(sendbufhex,"BodyBinary=");
10 
11 for(i=0;i<sendbuflen;i+=2)
12 {
13     memset(temp,'\0',sizeof(temp));
14     temp[0] = '\\';
15     temp[1] = 'x';
16     temp[2] = sendbuf[i];
17     temp[3] = sendbuf[i+1]    ;
18     lr_output_message("Notify:temp:%s",temp);
19     strcat(sendbufhex,temp);
20 }
21 
22 lr_output_message("Notify:sendbufhex:%s",sendbufhex);
23 
24 web_custom_request("web_custom_request",
25 "URL=http://www.baidu.com",
26 "Method=POST",
27 "TargetFrame=",
28 "Resource=0",
29 "Referer=",
30 "Mode=HTTP",
31 sendbufhex,
32 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, <List of Attributes>,[EXTRARES, <List of Resource Attributes>,] 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 選項中,可以設定把這些資源錄製在當前的操作中(預設是此設定)還是作為單獨的步驟來錄製。

  在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=\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中的截圖:

複製程式碼
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\\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);
複製程式碼

 

 傳送資料包的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,'\0',sizeof(sendbufhex));
 8 
 9 for(i=0;i<sendbuflen;i+=2)
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 
20 lr_output_message("Notify:sendbufhex:%s",sendbufhex);
21 
22 lr_save_string(sendbufhex,"sendbufhexParam");
23 
24 lr_output_message("Notify:sendbufhexParam:%s",lr_eval_string("{sendbufhexParam}"));
25 
26 web_custom_request("web_custom_request",
27 "URL=http://www.baidu.com",
28 "Method=POST",
29 "TargetFrame=",
30 "Resource=0",
31 "Referer=",
32 "Mode=HTTP",
33 "BodyBinary={sendbufhexParam}",
34 LAST);    
複製程式碼

 

特別注意:拼接的引數中只需要一個飯斜槓而不是兩個飯斜槓,”3d009d1defa4000441000042"  ==》 "\x3d\x00\x9d\x1d\xef\xa4\x00\x04\x41\x00\x00\x42"

變數替換寫法程式碼如下:

複製程式碼
 1 char sendbuf[100] ="3d009d1defa4000441000042";
 2 char sendbufhex[100];
 3 char temp[100];
 4 int sendbuflen,i;
 5 sendbuflen = strlen(sendbuf);
 6 lr_output_message("Notify:sendbuflen:%d",sendbuflen);
 7 
 8 memset(sendbufhex,'\0',sizeof(sendbufhex));
 9 strcat(sendbufhex,"BodyBinary=");
10 
11 for(i=0;i<sendbuflen;i+=2)
12 {
13     memset(temp,'\0',sizeof(temp));
14     temp[0] = '\\';
15     temp[1] = 'x';
16     temp[2] = sendbuf[i];
17     temp[3] = sendbuf[i+1]    ;
18     lr_output_message("Notify:temp:%s",temp);
19     strcat(sendbufhex,temp);
20 }
21 
22 lr_output_message("Notify:sendbufhex:%s",sendbufhex);
23 
24 web_custom_request("web_custom_request",
25 "URL=http://www.baidu.com",
26 "Method=POST",
27 "TargetFrame=",
28 "Resource=0",
29 "Referer=",
30 "Mode=HTTP",
31 sendbufhex,
32 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, <List of Attributes>,[EXTRARES, <List of Resource Attributes>,] 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 選項中,可以設定把這些資源錄製在當前的操作中(預設是此設定)還是作為單獨的步驟來錄製。