[英]Perl HTTP Request POST fails with TeamCity REST API
我有一個Perl腳本,通過REST API備份我們的TeamCity服務器,如下所示:
use strict;
use LWP::UserAgent;
use HTTP::Request::Common qw{ POST GET }
# ... code ommitted for brevity ... #
my $url = 'http://teamcity:8080/httpAuth/app/rest/server/backup';
my $req = POST( $url . '?includeConfigs=true&includeDatabase=true&includeBuildLogs=true&fileName=' . $filename);
$req->authorization_basic($username, $password);
my $resp = $ua->request($req);
我嘗試根據HTTP:Request的文檔發布內容,但由於某種原因它失敗,並抱怨我沒有指定文件名:
# This fails
my $req= POST( $url, [ 'includeConfigs' => 'true',
'includeDatabase' => 'true',
'includeBuildLogs' => 'true',
'fileName' => $filename,
] );
但是,當我查看TeamCity的后端REST日志時,完整的請求似乎使它完整無缺,並且與上面傳遞的請求相同。
成功命令的日志:
[2012-12-13 15:02:38,574] DEBUG [www-perl/5.805 ] - rver.server.rest.APIController - REST API request received: POST '/httpAuth/app/rest/server/backup?includeConfigs=true&includeDatabase=true&includeBuildLogs=true&fileName=foo', from client 10.126.31.219, authenticated as jsmith
失敗命令的日志:
[2012-12-13 14:57:00,649] DEBUG [www-perl/5.805 ] - rver.server.rest.APIController - REST API request received: POST '/httpAuth/app/rest/server/backup?includeConfigs=true&includeDatabase=true&includeBuildLogs=true&fileName=foo', from client 10.126.31.219, authenticated as jsmith
發出POST請求的兩種方法之間是否存在其他可能導致失敗的隱藏差異?
更新:這是通過Data :: Dumper打印時每個請求的結果
成功的POST:
$VAR1 = bless( {
'_content' => '',
'_uri' => bless( do{\(my $o = 'http://teamcity:8080/httpAuth/app/rest/server/backup?includeConfigs=true&includeDatabase=true&includeBuildLogs=true&fileName=foo')}, 'URI::http' ),
'_headers' => bless( {
'content-type' => 'application/x-www-form-urlencoded',
'content-length' => 0,
'authorization' => 'Basic c3lzQnVpbGRTeXN0ZW1JOnBhaWQuZmFpdGg='
}, 'HTTP::Headers' ),
'_method' => 'POST'
}, 'HTTP::Request' );
POST不成功:
$VAR1 = bless( {
'_content' => 'includeConfigs=true&includeDatabase=true&includeBuildLogs=true&fileName=foo',
'_uri' => bless( do{\(my $o = 'http://teamcity:8080/httpAuth/app/rest/server/backup')}, 'URI::http' ),
'_headers' => bless( {
'content-type' => 'application/x-www-form-urlencoded',
'content-length' => 75,
'authorization' => 'Basic c3lzQnVpbGRTeXN0ZW1JOnBhaWQuZmFpdGg='
}, 'HTTP::Headers' ),
'_method' => 'POST'
}, 'HTTP::Request' );
我認為您的服務器端腳本只能處理URL中編碼的GET
參數,而不能處理通過標准輸入傳輸的POST
數據。 請注意,HTTP描述了幾種不同的方法,分別是GET
, POST
, HEAD
, DELETE
等。然后,有兩種方法可以將數據傳遞到服務器上的應用程序。 最常見的一種方式也稱為GET parameters
,另一種方式稱為POST data
因為GET parameters
通常與HTTP GET
方法一起使用,而POST data
通常用於HTTP POST
方法。 但是,他們不必這樣做。 而且我認為您在成功情況下將HTTP POST
方法與GET parameters
混合在一起,在失敗情況下與POST data
混合在一起。
GET parameters
是通過URL傳遞的,通常是通過附加?
來傳遞的?
網址,后跟實際的鍵/值pais。 這些可以通過某些環境變量在服務器上運行的腳本中使用。 由腳本來拆分&
處的變量,在=
上拆分鍵/值對並撤消轉義。
對於POST data
,環境變量CONTENT_LENGTH
告訴腳本從其標准輸入讀取多少字節。 實際的鍵/值對通過不同的編碼(通常作為多部分編碼的內容)傳輸。 是的, POST
HTTP請求(主要來自HTML <form>
)也可以像GET parameters
一樣通過URL編碼發送,但是HTTP標准對包括所有參數的URL施加了長度限制。 因此,通過標准輸入而不是通過URL傳輸數據的方法。
現在看來,您的服務器端腳本可以評估URL編碼的參數(也稱為GET parameters
)參數,但不能評估通過標准輸入發布到該參數的數據。 即使您使用POST
HTTP方法/動詞,在成功的情況下,實際上也不會通過標准輸入將值作為POST data
傳輸。 在這種情況下,您可以簡單地將POST(...)
換成GET(...)
,它仍然可以正常工作。
在不成功的情況下,請使用POST
HTTP方法和POST data
傳輸值的方式。
在某些情況下,我在這里的說法可能是錯誤的,但基本原理仍然可以。
my $url= my $url = 'http://teamcity:8080/httpAuth/app/rest/server/backup';
my $req= POST( $url, { 'includeConfigs' => 'true',
'includeDatabase' => 'true',
'includeBuildLogs' => 'true',
'fileName' => $filename,
} );
注意“ {}”(哈希引用,而不是數組引用)。 同樣,不將查詢字符串(GET)語法與POST語法混合使用也很有助於弄清問題。
干杯。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.