如何使用PHP读取CURL PUT数据?

时间:2016-11-27 08:17:40

标签: php curl

如何在PHP中读取使用CURL PUT发送的数据?我有POST和GET工作,但PUT不起作用。我发现你必须使用php://input读取数据。我如何解析数据?

这是PUT文件test15.php:

<?php
// CURL PUT Test

$browser     = $_SERVER['HTTP_USER_AGENT'];
$url  = 'http://localhost/curltest/test15_put.php';  
// echo "URL: $url <br>";

$headers = array( 
  "Accept: application/json" 
); 

// set post fields
$post = array(
    'firstname'  => 'John',
    'lastname'   => 'Doe',
    'email'      => 'email@domain.com',
    'notes'      => 'Test user to test CURL PUT request'
    );
$post2 = json_encode($post);

$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_USERAGENT, $browser);
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "PUT");
curl_setopt($curl, CURLOPT_POSTFIELDS, $post);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, True);
$response = curl_exec($curl);

echo "<pre>";
print_r($response);
echo "</pre>";
?>

这是接收文件test15_put.php:

<?php
parse_str(file_get_contents("php://input"), $post_vars);

$firstname  = $post_vars['firstname'];
$lastname   = $post_vars['lastname'];

$value = array('firstname' => $firstname, 'lastname' => $lastname);
echo json_encode($value);
?>

这是我得到的数据:

Array
(
    [--------------------------f7bdbb5224ed4e09
Content-Disposition:_form-data;_name] => "firstname"

John
--------------------------f7bdbb5224ed4e09
Content-Disposition: form-data; name="lastname"

Doe
--------------------------f7bdbb5224ed4e09
Content-Disposition: form-data; name="email"

email@domain.com
--------------------------f7bdbb5224ed4e09
Content-Disposition: form-data; name="notes"

Test user to test CURL PUT request
--------------------------f7bdbb5224ed4e09--

)

是否有其他方法可以发送数据并获得更好的响应?

更新 2016-11-29 这是返回的$ GLOBALS数据:

 [GLOBALS] => Array
 *RECURSION*
  [browser] => Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36
  [url] => http://localhost/milk/test15_put.php
  [headers] => Array
      (
          [0] => Accept: application/json
      )

  [post] => Array
      (
          [firstname] => John
          [lastname] => Doe
          [email] => email@domain.com
          [notes] => Test user to test CURL PUT request
      )

  [post2] => {"firstname":"John","lastname":"Doe","email":"email@domain.com","notes":"Test user to test CURL PUT request"}
  [curl] => Resource id #2
  [response] => 

更新3 - 2016-12-08

我尝试使用 S.Pinkus 中的代码。我使用运行XAMPP和PHP 5.6.21的Windows PC。我仍然得到返回的空数组,而不是我需要的值。我也编写我的PHP代码并从浏览器运行,而不是命令行。这是我修改后的 S.Pinkus 代码和输出:

<?php
// CURL PUT Test

$browser     = $_SERVER['HTTP_USER_AGENT'];
$url  = 'http://localhost/curltesting/test16_put.php';  
// echo "URL: $url <br>";

$payload = ['x' => 1, 'y' => 2];
// PUT JSON. \$_POST is not set server side. php://input gives the JSON payload.
print "<br>### TEST 1 (application/json):<br>";
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_HTTPHEADER, ["Content-Type: application/json"]);
curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "PUT");
curl_setopt($curl, CURLOPT_RETURNTRANSFER, True);
$response = curl_exec($curl);
var_dump($response);

// PUT form data. \$_POST is set by PHP server side.\n";
echo "<br>### TEST 2 (multipart/form-data):<br>";
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_HTTPHEADER, []);
curl_setopt($curl, CURLOPT_POSTFIELDS, $payload);
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "PUT");
curl_setopt($curl, CURLOPT_RETURNTRANSFER, True);
$response = curl_exec($curl);
var_dump($response);

?>

这是test16_put.php代码:

<?php
ini_set('log_errors', true);
ini_set('display_errors', true);
ini_set('error_reporting', E_ALL);
echo "\n### \$_POST: <br>";
echo "<pre>";
print_r($_POST);
echo "</pre><br>";
echo "<br><br>### Request Body: <br>";
echo file_get_contents('php://input') . "<br>";

?>

这是我得到的输出:

### TEST 1 (application/json):
string(89) " ### $_POST: 
Array
(
)

### Request Body: 
{"x":1,"y":2}
" 
### TEST 2 (multipart/form-data):
string(304) " ### $_POST: 
Array
(
)

### Request Body: 
--------------------------8f21ab28aa12c814 Content-Disposition: 
form-data; name="x" 1 --------------------------8f21ab28aa12c814 
Content-Disposition: form-data; name="y" 2 
--------------------------8f21ab28aa12c814-- 
"

似乎我只获得Request Body字符串中返回的所需数据,而没有其他地方......

1 个答案:

答案 0 :(得分:2)

问题&#34;如何通过PHP&#34; 中的HTTP PUT请求读取数据,答案是,有两种(正常)方式。您使用哪种方式取决于您发送数据的方式 - 特别是您发送的Content-Type

如果您将CURLOPT_POSTFIELDS数组一起使用,则Curl将发送Content-Type: multipart/form-data的请求。 PHP将识别此Content-Type并将正文解析为$_POST超全局数组(无论它是PUT还是POST请求)。一旦PHP完成了这个解析,你就无法通过php://input anymore来检索正文的内容 - 我不完全确定为什么会这样,但是因为它&#39 ;在$ _POST中没有理由想要。

但是如果你只是想发送一个任意的主体(比如说JSON或TXT或XML ......)将数据放在CURLOPT_POSTFIELDS中作为一个字符串(你也可以在那里放一个文件的引用但是这超出了问题的范围),并适当地设置Content-Type。 PHP 赢了填充$_POST,您阅读数据的方式是php://input

更新:示例:

(旁白:通过以下测试,我发现PHP(5.6无论如何)解析application/json个有效负载到$ _POST。但在这种情况下,它仍然会离开php://stdin所以你可以通过任何一种方法检索一个JSON有效载荷。这必须是一个仅限于application/json有效载荷的便利,因为其他有效载荷不会明显扩展到一个数组......)。

这是一个测试客户端( curl-put-debug-script.php ):

<?php
isset($argv[1]) or die("Usage: {$argv[0]} <URL>\n");
$payload = ['x' => 1, 'y' => 2];
// PUT JSON. \$_POST is not set server side. php://input gives the JSON payload.
print "\n### TEST 1 (application/json):\n";
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $argv[1]);
curl_setopt($curl, CURLOPT_HTTPHEADER, ["Content-Type: application/json"]);
curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "PUT");
curl_setopt($curl, CURLOPT_RETURNTRANSFER, True);
$response = curl_exec($curl);
var_dump($response);

// PUT form data. \$_POST is set by PHP server side.\n";
print "\n### TEST 2 (multipart/form-data):\n";
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $argv[1]);
curl_setopt($curl, CURLOPT_HTTPHEADER, []);
curl_setopt($curl, CURLOPT_POSTFIELDS, $payload);
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "PUT");
curl_setopt($curl, CURLOPT_RETURNTRANSFER, True);
$response = curl_exec($curl);
var_dump($response);

这是一个简单的测试终点,你可以进行调试( curl-debug-svr.php ):

<?php
ini_set('log_errors', true);
ini_set('display_errors', true);
ini_set('error_reporting', E_ALL);
print "\n### \$_POST:\n";
print_r($_POST);
print "### Request Body:\n";
print file_get_contents('php://input') . "\n";

现在,运行服务器,并使用这样的测试脚本点击它 - 假设您在当前工作目录中有两个脚本:

php -S 127.0.0.1:8000 2>/dev/null &
php curl-put-debug-script.php "http://127.0.0.1:8000/curl-debug-svr.php"

给出以下内容:

### TEST 1 (JSON):
string(81) "
### $_POST:
Array
(
    [x] => 1
    [y] => 2
)
### Request Body:
{"x":1,"y":2}
"

### TEST 2 (multipart/form-data):
string(68) "
### $_POST:
Array
(
    [x] => 1
    [y] => 2
)
### Request Body:

"

这表明php://stdin没有为multipart / form-data返回任何内容(即,当你给CURLOPT_POSTFIELDS数组时)。

更新:解决您的代码示例

简而言之:

  1. 我不确定你为什么设置Accept: application/json标题。在这种情况下,这没有任何影响。如果您要发送JSON,则需要设置Content-Type: application/json。但是你没有在你的例子中发送JSON。
  2. 如上所列,您正在传递服务器表单数据(因为此行curl_setopt($curl, CURLOPT_POSTFIELDS, $post);)。执行此操作时,您必须从$_POST超级全局读取数据。您无法(或至少your not supposed)从stdin://input读取。
  3. 混乱&#34;输出&#34;您显示的数据在服务器端看起来像$post_var。关于尝试parse_str()多部分/表单数据编码主体的权利。但我不确定为什么std://input会返回任何内容。让我想知道你使用的PHP版本。