cURL、WireShark。设置标头以发布数据并获取 xml
这是 WireShark 的转储:
POST /drm/drm_production_v2.php HTTP/1.1
content-length: 278
content-type: text/xml
User-Agent: UserAgent 1.0
Connection: Keep-Alive
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=
host: www.example.com
<methodCall>
<methodName>aMethod</methodName>
<params>
<param>
<value>
<base64>dXNlcm5hbWU6cGFzc3dvcmQ=</base64>
</value>
</param>
<param>
<value>
<struct/>
</value>
</param>
</params>
</methodCall>
我将 xml 保存到单独的文件中。这就是我正在做的事情:
<?php
function httpsPost($Url, $xml_data, $headers)
{
// Initialisation
$ch=curl_init();
// Set parameters
curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
curl_setopt($ch, CURLOPT_FRESH_CONNECT, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_URL, $Url);
// Return a variable instead of posting it directly
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_USERPWD,"username:password");
// Activate the POST method
curl_setopt($ch, CURLOPT_POST, 1) ;
curl_setopt($ch,CURLOPT_USERAGENT,"UserAgent 1.0");
// Request
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml_data);
curl_setopt($ch, CURLOPT_TIMEOUT, 999);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
// execute the connexion
$result = curl_exec($ch);
// Close it
curl_close($ch);
return $result;
}
$str='username:password';
$auth=base64_encode($str);
$request_file = "./request.xml";
$fh = fopen($request_file, 'r');
$filesize=filesize($request_file);
echo $filesize;
$xml_data = fread($fh,$filesize);
fclose($fh);
$url = 'http://www.example.com';
$header = array();
$header[] = "POST /drm/drm_production_v2.php HTTP/1.1";
$header[] = "Content-type: text/xml";
$header[] = "content-length: ".$filesize. "\r\n";
$header[] = "User-Agent: UserAgent 1.0";
$header[] = "Connection: Keep-Alive";
$header[] = "Authorization: Basic ".$auth;
$header[] = "host: www.example.com";
$Response = httpsPost($url, $xml_data, $header);
echo $Response;
?>
它从服务器返回“错误请求”。有什么建议吗?
Here is the dump from WireShark:
POST /drm/drm_production_v2.php HTTP/1.1
content-length: 278
content-type: text/xml
User-Agent: UserAgent 1.0
Connection: Keep-Alive
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=
host: www.example.com
<methodCall>
<methodName>aMethod</methodName>
<params>
<param>
<value>
<base64>dXNlcm5hbWU6cGFzc3dvcmQ=</base64>
</value>
</param>
<param>
<value>
<struct/>
</value>
</param>
</params>
</methodCall>
I have the xml saved into a seperate file. Here's what I am doing:
<?php
function httpsPost($Url, $xml_data, $headers)
{
// Initialisation
$ch=curl_init();
// Set parameters
curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
curl_setopt($ch, CURLOPT_FRESH_CONNECT, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_URL, $Url);
// Return a variable instead of posting it directly
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_USERPWD,"username:password");
// Activate the POST method
curl_setopt($ch, CURLOPT_POST, 1) ;
curl_setopt($ch,CURLOPT_USERAGENT,"UserAgent 1.0");
// Request
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml_data);
curl_setopt($ch, CURLOPT_TIMEOUT, 999);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
// execute the connexion
$result = curl_exec($ch);
// Close it
curl_close($ch);
return $result;
}
$str='username:password';
$auth=base64_encode($str);
$request_file = "./request.xml";
$fh = fopen($request_file, 'r');
$filesize=filesize($request_file);
echo $filesize;
$xml_data = fread($fh,$filesize);
fclose($fh);
$url = 'http://www.example.com';
$header = array();
$header[] = "POST /drm/drm_production_v2.php HTTP/1.1";
$header[] = "Content-type: text/xml";
$header[] = "content-length: ".$filesize. "\r\n";
$header[] = "User-Agent: UserAgent 1.0";
$header[] = "Connection: Keep-Alive";
$header[] = "Authorization: Basic ".$auth;
$header[] = "host: www.example.com";
$Response = httpsPost($url, $xml_data, $header);
echo $Response;
?>
It returns a 'Bad Request' from the server. Any suggestions?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我的第一个猜测是,内容长度标头后面的额外“\r\n”使服务器认为帖子内容从那里开始。我还将“内容长度”、“内容类型”和“主机”更改为“内容长度”、“Contnet-类型”和“主机”,以防万一。
编辑:那,以及罗纳德·布曼的回答。
My first guess is that the extra "\r\n" after the content-length header makes the server think that the post content starts there. I'd also change "content-length", "Content-type", and "host" to "Content-Length", "Contnet-Type", and "Host", just in case.
Edit: That, and Ronald Bouman's answer.
我认为你的论点
是不正确的。 postfields 选项应该是 URL 编码的名称/值对。来自文档:
“
这可以作为 urlencoded 字符串(如“para1=val1¶2=val2&...”)传递,也可以作为以字段名称作为键、字段数据作为值的数组传递。如果 value 是一个数组,则 Content-Type 标头将设置为 multipart/form-data
"
请参阅 http://php.net/manual/en/function.curl- setopt.php
I think your argument to
is not correct. The postfields option should be URL encoded name/value pairs. From the docs:
"
This can either be passed as a urlencoded string like 'para1=val1¶2=val2&...' or as an array with the field name as key and field data as value. If value is an array, the Content-Type header will be set to multipart/form-data
"
see http://php.net/manual/en/function.curl-setopt.php
有一个 pcap2curl 工具,它允许将 HTTP 请求的 pcap 文件转换为 cURL。
但是,如果您想从浏览器重放某些 Web 请求,那么您可以不使用 Wireshark,而是在浏览器中进入 Web 开发人员模式。然后,您转到网络请求视图并右键单击感兴趣的请求,然后在大多数现代浏览器中,有一个选项复制为 cURL,然后您可以将生成的命令粘贴到终端中并使用
curl
工具重新运行您认为合适的捕获的命令。某些浏览器(例如 Mozilla)还提供在浏览器内编辑和重新发送的选项。There's the pcap2curl tool that allows one to convert a pcap file of HTTP requests into cURL.
But if you want to replay some web requests from your browser then you can do it without Wireshark and instead enter Web developer mode in the browser. You then go to the network requests view and right click on the request of interest then, in most modern browsers, there is an option to Copy as cURL after which you can then paste the resulting command into a terminal and rerun the captured command as you see fit using the
curl
tool. Some browsers (e.g. Mozilla) also offer the option to edit and resend from within the browser.