PHP cURL POST 返回 415 - 不支持的媒体类型
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11087872/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
PHP cURL POST returns a 415 - Unsupported Media Type
提问by Ian
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:
我有一个简单的 PHP 脚本,它通过 cURL 发送一个 HTTP POST 请求,并期望一个 json 字符串作为响应(本来希望使用像 pecl_http/HTTPRequest 这样的现有库,但不能)。呼叫始终失败并显示 415 错误 - 不支持的媒体类型。我想我没有正确配置 cURL,但经过多次搜索,我无法找出我做错了什么。这是一些代码:
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();
...and the response:
...和回应:
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>
Any insights or ideas?
任何见解或想法?
Thanks in advance!
提前致谢!
回答by Ian
Problem solved! Here's the issue:
问题解决了!这是问题:
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!
发送标头的关联数组不适用于 cURL。有几个论坛散布在展示使用关联数组作为标题的示例。不要这样做!
The correctway (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.
在正确的方式(也散落在互联网络,但我太密已经注意到)是构建你的头键/值对字符串,并设置CURLOPT_HTTPHEADER选项时传递这些字符串的标准阵列。
So in summary,
所以总结一下,
WRONG:
错误的:
$headers = array( "Accept-Encoding" => "gzip",
"Content-Type" => "application/json",
"custom_header_1" => "test011",
"custom_header_2" => "test012",
"custom_header_3" => "test013");
RIGHT:
对:
$headers = array( "Accept-Encoding: gzip",
"Content-Type: application/json",
"custom_header_1: test011",
"custom_header_2: test012",
"custom_header_3: test013");
I hope this comes in handy to some other noble doofus down the road before they waste as much time debugging as I did.
我希望这对未来的其他一些高尚的傻瓜有用,以免他们像我一样浪费时间进行调试。
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.
如果我不得不猜测,我会假设相同的规则也适用于 POST 正文键/值对,这就是为什么 @drew010 关于使用http_build_query()或json_encode()字符串化您的消息正文的评论也是一个好主意的原因。
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.
感谢大家的非常有用的意见,以及您的时间和考虑。最后,对 http 流量(通过 Wireshark 捕获)的并排比较揭示了这个问题。
Thanks!
谢谢!
回答by drew010
I think the problem is that you are passing an array as the CURLOPT_POSTFIELDSoption. By passing an array, this forces the POSTrequest to use multipart/form-datawhen the server is probably expecting application/x-www-form-urlencoded.
我认为问题在于您正在传递一个数组作为CURLOPT_POSTFIELDS选项。通过传递一个数组,这会强制POST请求multipart/form-data在服务器可能需要application/x-www-form-urlencoded.
Try changing
尝试改变
curl_setopt($request, CURLOPT_POSTFIELDS, $this->body);
to
到
curl_setopt($request, CURLOPT_POSTFIELDS, http_build_query($this->body));
See http_build_queryfor more information and also this answer: My cURL request confuses some servers?
有关更多信息以及此答案,请参阅http_build_query:我的 cURL 请求混淆了某些服务器?
回答by jhonatan_yachi
I had the same problem and I fixed changing the header.
我遇到了同样的问题,我修复了更改标题。
My code:
我的代码:
$authorization = 'authorization: Bearer '.trim($apiKey);
$header = [
'Content-Type: application/json',
$authorization
];
curl_setopt($session, CURLOPT_HTTPHEADER, $header);
I don't know why the array function doesn't work :
我不知道为什么数组函数不起作用:
curl_setopt($session, CURLOPT_HTTPHEADER, array('Content-Type:
application/json',
$authorization));

