如何使用内容类型为application/x-www-form-urlencoded
的PHP curl发送原始JSON?
让我解释一下:
我正在与一个接受 HTTP POST 请求的网络服务器进行通信,其中JSON对象是请求的主体,通常我们习惯于查看HTTP查询参数。
在我的情况下,我需要发送一个包含以下内容类型的请求
内容类型:application / x-www-form-urlencoded
正文必须是原始的JSON。
所以,有很多可能性。我尝试了以下方法:
<?php
$server_url = "http://server.com";
$curl = curl_init($server_url);
$data_array = array("a"=> "a_val", "b" => array("c"=>"c_val", "d"=>"d_val") );
$options = array(
CURLOPT_POST => TRUE,
CURLOPT_HTTPHEADER => array('Content-Type: application/x-www-form-urlencoded'),
CURLOPT_POSTFIELDS => json_encode($data_array),
CURLOPT_COOKIEJAR => realpath('tmp/cookie.txt'),
CURLOPT_COOKIEFILE => realpath('tmp/cookie.txt')
);
curl_setopt_array($curl, $options);
$return = curl_exec($curl);
var_dump($return);
curl_close($curl);
?>
我也试图逃避json_encode()
:
...
CURLOPT_POSTFIELDS => "\"" . json_encode($data_array) . "\"" ,
...
如果服务器能够解析html参数,我可以这样做:
...
CURLOPT_POSTFIELDS => http_build_query($data_array)
...
然而,事实并非如此,我需要一种解决方法。
请注意,更改内容类型不起作用。我尝试使用text/plain
,但服务器不接受它。
答案 0 :(得分:1)
通常application/x-www-form-urlencoded
需要HTTP post的键值配对参数。因此,如果没有看到示例POST数据格式,很难向您推荐任何内容。根据文档,您必须将URLencoded数据与变量放在一起。例如,您的JSON应该是这样的。
$post_data = "data=".urlencode(json_encode($data_array))
您可以尝试在没有任何关键参数的情况下发送数据,但它不起作用
$post_data = urlencode(json_encode($data_array))
答案 1 :(得分:0)
我不完全确定我理解你的问题,所以我将回答两个不同的版本。
application/x-www-form-urlencoded
内容类型我不知道你为什么要这样做,但如果你这样做,那应该相当简单。
$data_array = array(
'a' => 'a_val',
'b' => array(
'c' => 'c_val',
'd' => 'd_val'
)
);
$json = json_encode($data_array);
$c = curl_init();
curl_setopt($c, CURLOPT_URL, $url);
curl_setopt($c, CURLOPT_POST, true);
curl_setopt($c, CURLOPT_USERAGENT, 'PHP/' . phpversion());
curl_setopt($c, CURLOPT_RETURNTRANSFER, true);
curl_setopt($c, CURLOPT_POSTFIELDS, $json);
curl_setopt($c, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded'));
$result = curl_exec($c);
if (curl_errno($c)) {
return trigger_error('CURL error [' . curl_errno($c) . '] ' . curl_error($c));
}
curl_close($c);
echo $result;
请记住,您在这里向服务器发送故意不准确的数据。您正在发送JSON,但称其为urlencoded。你可能不想这样做;如果,出于某种原因,你确实需要这样做,你可能最好修复任何真正的问题,而不是使用这个hacky解决方法。
如果你使用的是Guzzle而不是cURL,那可能会有点棘手。 Guzzle内置了对JSON和urlencoded的支持,但是如果你想这样搞乱,你最好不要使用它。自己生成JSON数据(使用$json = json_encode($data)
),并手动设置Guzzle中的Content-Type。
这是一个奇怪的设置,但准确。至少你不会在你的HTTP标题中。
基本上与上面相同,但添加:
$json = json_encode($data_array);
$data = array('JSON' => $json);
$body = http_build_query($data);
然后将CURLOPT_POSTFIELDS
设置为$body
而不是$json
。
在大多数情况下,您最好发送JSON数据(如示例一),并将Content-Type设置为application/json
。这是比示例2更小的数据大小(urlencoding步骤增加了数据的大小),并且它具有准确的标题数据。