为啥当我使用 Perl 的 REST::Client 发送 POST 请求,而不是使用 Perl 的 LWP::UserAgent 或 Python 时,我得到“405: Method Not All
Posted
技术标签:
【中文标题】为啥当我使用 Perl 的 REST::Client 发送 POST 请求,而不是使用 Perl 的 LWP::UserAgent 或 Python 时,我得到“405: Method Not Allowed”?【英文标题】:Why do I get "405: Method Not Allowed" when I send a POST request with Perl's REST::Client, but not with Perl's LWP::UserAgent or Python?为什么当我使用 Perl 的 REST::Client 发送 POST 请求,而不是使用 Perl 的 LWP::UserAgent 或 Python 时,我得到“405: Method Not Allowed”? 【发布时间】:2016-06-12 18:30:56 【问题描述】:当我使用 Perl 的 REST::Client
发送 POST 请求时,我得到以下响应:
405: Method Not Allowed
但是,当我使用 Perl 的 LWP::UserAgent
或 Python 的 Requests
向同一个 URL 发送 POST 请求时,我得到一个“成功”响应。 GET 请求适用于 REST::Client
和 Python。
我该如何解决这个问题?
这是使用REST::Client
的代码(返回 HTTP 405):
use REST::Client;
use JSON;
$header =
'Auth' => '04211b77df',
'Accept' => 'application/json',
'Content-type' => 'application/json'
;
%body = (
'sid' => '001',
'pid' => 'c7b3d83',
'file' => [
'name' => 'file1.txt',
'location' => 'folderA'
,
'name' => 'file2.txt',
'location' => 'folderB'
]
);
$client = REST::Client->new();
$client->POST('URL', encode_json(\%body), $header);
这是使用LWP::UserAgent
(返回HTTP 200)的代码:
#!/use/bin/perl -w
use strict;
use LWP::UserAgent;
use Data::Dumper;
use JSON;
my $ua = LWP::UserAgent->new;
my $req = HTTP::Request->new(POST => 'URL');
$req->header('Auth' => '04211b77df');
$req->header('Content-type' => 'application/json');
$req->header('Accept' => 'application/json');
my %body = (
'sid' => '001',
'pid' => 'c7b3d83',
'file' => [
'name' => 'file1.txt',
'location' => 'folderA'
,
'name' => 'file2.txt',
'location' => 'folderB'
]
);
$req->content(encode_json(\%body));
$ua->request($req);
这是 Python 代码(返回 HTTP 200):
import requests, json, sys
headers =
'Auth': '04211b77df'
'Accept': 'application/json'
'Content-type': 'application/json'
data=
'sid': '001',
'pid': 'c7b3d83',
'file': [
'name': 'file1.txt',
'location': 'folderA'
,
'name': 'file2.txt',
'location': 'folderB'
]
requests.request('POST', 'URL', data=data, headers=headers)
【问题讨论】:
如果您希望收到任何有用的答案,您需要edit 您的问题以包含minimal reproducible example。 如果您能够从一个客户端获得成功的结果,而在另一个客户端失败,我会查看客户端,而不是服务器。启动wireshark并观察来自两个客户端的流量,并寻找差异。 附带说明,您应该在编写的每个 Perl 脚本中使用use strict; use warnings 'all';
。
@PaulMcGuire 谢谢你会尝试一下
好的,我认为我看到了这个问题。 (REST::Client 实际上在幕后使用 LWP::UserAgent,因此您的最新编辑有助于缩小范围。) REST::Client 调用 $ua->simple_request
而不是 $ua->request
:“与 request()
的区别是simple_request()
不会尝试处理重定向或身份验证响应。”我猜身份验证正在阻碍。我认为这是 REST::Client 中的一个错误。投票重新提出您的问题。
【参考方案1】:
您的 REST::Client 代码和您的 LWP::UserAgent 代码生成几乎相同的请求。* 但是,在后台使用 LWP::UserAgent 的 REST::Client 使用 $ua->simple_request()
发送请求,而您的 LWP ::UserAgent 代码使用$ua->request()
。
根据documentation:
与
request()
的区别在于simple_request()
不会尝试处理重定向或身份验证响应。
我猜是身份验证导致了这个问题。我还猜测您使用的 API 不需要对 GET 请求进行身份验证,因为您说这些正在使用 REST::Client。
要修复,请在构造函数中将follow
选项设置为1
:
my $client = REST::Client->new(follow => 1);
或调用setFollow
方法:
my $client = REST::Client->new();
$client->setFollow(1);
这将正确处理身份验证响应,但它也将遵循重定向。不幸的是,您不能单独设置重定向和身份验证的行为,即long-standing bug。
* 唯一的区别是 REST::Client 添加了一个Content-length
标头,我认为这并不重要。
发送前转储 REST::Client 请求:
$VAR1 = bless(
'_content' => '"sid":"001","pid":"c7b3d83","file":["location":"folderA","name":"file1.txt","location":"folderB","name":"file2.txt"]',
'_uri' => bless( do\(my $o = 'http://www.example.com'), 'URI::http' ),
'_headers' => bless(
'auth' => '04211b77df',
'content-type' => 'application/json',
'accept' => 'application/json',
'content-length' => 122,
'::std_case' =>
'auth' => 'Auth'
, 'HTTP::Headers' ),
'_method' => 'POST'
, 'HTTP::Request' );
发送前转储 LWP::UserAgent 请求:
$VAR1 = bless(
'_content' => '"sid":"001","pid":"c7b3d83","file":["location":"folderA","name":"file1.txt","location":"folderB","name":"file2.txt"]',
'_uri' => bless( do\(my $o = 'http://www.example.com'), 'URI::http' ),
'_headers' => bless(
'auth' => '04211b77df',
'content-type' => 'application/json',
'accept' => 'application/json',
'::std_case' =>
'auth' => 'Auth'
, 'HTTP::Headers' ),
'_method' => 'POST'
, 'HTTP::Request' );
实际发送请求时还会有其他细微差别,例如用户代理字符串,但我认为它们与您的问题无关。
【讨论】:
以上是关于为啥当我使用 Perl 的 REST::Client 发送 POST 请求,而不是使用 Perl 的 LWP::UserAgent 或 Python 时,我得到“405: Method Not All的主要内容,如果未能解决你的问题,请参考以下文章
为啥 ncat -exec 可以与 shell 脚本一起使用,但不能与 perl 脚本一起使用?
为啥 Perl 的两个 arg open 似乎去掉了换行符?