PHP cURL POST返回415 - 不支持的介质类型 [英] PHP cURL POST returns a 415 - Unsupported Media Type
问题描述
我有一个简单的PHP脚本通过cURL发送一个HTTP POST请求,并期待一个json字符串作为响应(会喜欢使用像pecl_http / HTTPRequest这样的现有库,但是不能)。呼叫始终失败,出现415错误 - 不支持的介质类型。我想我没有正确配置cURL,但经过大量搜索,我找不到我做错了。下面是一些代码:
I've got a simple PHP script that sends an HTTP POST request via cURL, and expects a json string in response (would have loved to use an existing library like pecl_http/HTTPRequest for this, but can't). The call consistently fails with a 415 error - Unsupported Media Type. I think I'm not configuring cURL correctly, but after much searching, I can't find out what I'm doing wrong. Here's some code:
class URLRequest
{
public $url;
public $headers;
public $params;
public $body;
public $expectedFormat;
public $method;
public function URLRequest($aUrl, array $aHeaders, array $aParams, $aFormat = "json", $isPost = false, $aBody = "+")
{
$this->url = $aUrl;
$this->headers = $aHeaders;
$this->params = $aParams;
$this->expectedFormat = $aFormat;
$this->method = ($isPost ? "POST" : "GET");
$this->body = $aBody;
}
public function exec()
{
$queryStr = "?";
foreach($this->params as $key=>$val)
$queryStr .= $key . "=" . $val . "&";
//trim the last '&'
$queryStr = rtrim($queryStr, "&");
$url = $this->url . $queryStr;
$request = curl_init();
curl_setopt($request, CURLOPT_URL, $url);
curl_setopt($request, CURLOPT_HEADER, 1);
curl_setopt($request, CURLOPT_HTTPHEADER, $this->headers);
curl_setopt($request, CURLOPT_RETURNTRANSFER, 1);
//curl_setopt($request, CURLOPT_SSL_VERIFYPEER, false);
if($this->method == "POST")
{
curl_setopt($request, CURLOPT_POST, 1);
curl_setopt($request, CURLOPT_POSTFIELDS, $this->body);
//this prevents an additions code 100 from getting returned
//found it in some forum - seems kind of hacky
curl_setopt($request, CURLOPT_HTTPHEADER, array("Expect:"));
}
$response = curl_exec($request);
curl_close($request);
preg_match("%(?<=HTTP/[0-9]\.[0-9] )[0-9]+%", $response, $code);
$resp = "";
if($this->expectedFormat == "json")
{
//parse response
}
elseif($this->expectedFormat == "xml")
{
//parse response
}
return $resp;
}
}
$url = "http://mydomain.com/myrestcall";
$query = array( "arg_1" => "test001",
"arg_2" => "test002",
"arg_3" => "test003");
$headers = array( "Accept-Encoding" => "gzip",
"Content-Type" => "application/json",
"Accept" => "application/json",
"custom_header_1" => "test011",
"custom_header_2" => "test012",
"custom_header_3" => "test013");
$body = array( "body_arg_1" => "test021",
"body_arg_2" => array("test022", "test023"),
"body_arg_3" => "test024");
$request = new URLRequest($url, $headers, $query, "json", true, $body);
$response = $request->exec();
...和回应:
HTTP/1.1 415 Unsupported Media Type
Server: Apache-Coyote/1.1
X-Powered-By: Servlet 2.5; JBoss-5.0/JBossWeb-2.1
Content-Type: text/html;charset=utf-8
Content-Length: 1047
Date: Mon, 18 Jun 2012 16:30:44 GMT
<html><head><title>JBoss Web/2.1.3.GA - Error report</title></head><body><h1>HTTP Status 415 - </h1><p><b>type</b> Status report</p><p><b>message</b> <u></u></p><p><b>description</b> <u>The server refused this request because the request entity is in a format not supported by the requested resource for the requested method ().</u></p><h3>JBoss Web/2.1.3.GA</h3></body></html>
有任何见解或想法吗?
推荐答案
问题解决!以下是问题:
Problem solved! Here's the issue:
发送联想数组的标头不适用于cURL。有几个论坛散布在显示使用关联数组头的示例。不要这样!
Sending an associative-array of headers DOES NOT WORK with cURL. There are several forums scattered around that show examples using an associative array for headers. DON'T DO IT!
正确的方式(它也散布在互联网周围,但是我太密集,没有注意到)是将头部键/值对构造为字符串,并在设置CURLOPT_HTTPHEADER选项时传递这些字符串的标准数组。
The correct way (which is also scattered around the internets, but that I'm too dense to have noticed) is to construct your header key/value pairs as strings, and pass a standard array of these strings when setting the CURLOPT_HTTPHEADER option.
总而言之,
WRONG:
$headers = array( "Accept-Encoding" => "gzip",
"Content-Type" => "application/json",
"custom_header_1" => "test011",
"custom_header_2" => "test012",
"custom_header_3" => "test013");
右键:
$headers = array( "Accept-Encoding: gzip",
"Content-Type: application/json",
"custom_header_1: test011",
"custom_header_2: test012",
"custom_header_3: test013");
我希望这对于其他高贵的doofus来说很方便,
I hope this comes in handy to some other noble doofus down the road before they waste as much time debugging as I did.
如果我不得不猜测,我会假设相同的规则也适用于POST主体键/值对,这就是为什么@ drew010'关于使用 http_build_query()
或 json_encode()
来字符串化您的邮件正文也是一个好主意。
If I had to guess, I would assume that the same rule applies to the POST body key/value pairs as well, which is why @drew010 's comment about using http_build_query()
or json_encode()
to stringify your message body is a great idea as well.
感谢大家对您非常有用的意见,并为您的时间和考虑。最后,并行比较http流量(通过Wireshark捕获)显示了问题。
Thanks to everyone for your very useful comments, and for you time and consideration. In the end, a side by side comparison of the http traffic (captured via Wireshark) revealed the issue.
谢谢!
这篇关于PHP cURL POST返回415 - 不支持的介质类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!