0

我有一个 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 打印时每个请求的结果

成功发布:

$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' );
4

2 回答 2

2

我认为您的服务器端脚本只能处理GETURL 中编码的参数,而不是POST通过标准输入传输的数据。请注意,HTTP 描述了几种不同的方法,它们是GETPOSTHEADDELETE。然后有两种方法可以将数据传递到服务器上的应用程序。大多数情况下,其中一种方式也被调用GET parameters,而另一种方式也被调用,POST data因为GET parameters它们通常与 HTTPGET方法一起使用,并且POST data通常用于 HTTPPOST方法。但是,他们不必这样做。而且我认为您将HTTPPOST方法与GET parameters成功案例和POST data不成功案例混为一谈。

GET parameters通过 URL 传递,通常是附加?到 URL 后跟实际的键/值组。这些可以通过某些环境变量提供给在服务器上运行的脚本。由脚本来拆分&,拆分键/值对上的变量=并撤消转义。

POST data环境变量CONTENT_LENGTH告诉脚本从其标准输入中读取多少字节。实际的键/值对通过不同的编码传输,通常作为多部分编码内容。是的,POSTHTTP 请求(主要来自 HTML <form>s)也可以像 一样发送 URL 编码GET parameters,但是 HTTP 标准对包括所有参数的 URL 施加了长度限制。因此,通过标准输入而不是通过 URL 传输数据的方法。

现在看起来您的服务器端脚本可以评估 URL 编码参数(又名。GET parameters)参数,但不能评估通过标准输入发布给它的数据。即使您使用HTTP 方法/动词,在您的成功案例中,您POST实际上并没有通过标准输入传输值。在这种情况下,POST data您可以简单地交换它,它应该仍然可以工作。POST(...)GET(...)

在您不成功的情况下,您使用POSTHTTP 方法和POST data传输值的方式。

在某些情况下,我在这里的措辞可能是错误的,但基本面应该仍然可以。

于 2012-12-13T17:48:12.097 回答
-1
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 语法混用对澄清问题大有帮助。

干杯。

于 2012-12-13T16:09:01.000 回答