无法从 Web 应用发出 Curl POST 请求

Can't make Curl POST request from web app

我正在使用的服务器似乎拒绝出站 HTTP 请求。我认为这是因为我已经尝试 Guzzlecurl 对 API.

的请求

API 与 Web 服务器位于同一域中(这是根据客户请求临时设置的)。我可以通过 Postman(Chrome 插件)向 API 服务器发出请求,但是当我 运行 服务器上的相同请求时,它不会 return 随便什么。

这是来自 'Postman' 请求的 headers:

POST /api2/user/session HTTP/1.1
Host: example.com
Connection: keep-alive
Content-Length: 49
Cache-Control: no-cache
Origin: chrome-extension://fdmmgilgnpjigdojojpjoooidkmcomcm
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.76 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Accept: */*
Accept-Encoding: gzip, deflate 
Accept-Language: en-US,en;q=0.8
Cookie: PHPSESSID=d9ad79c4c0822fc5c86f4d8799307f1b; _ga=GA1.2.1674422587.1425409444

Post数据:

token=a559d5bba5a9e9517d5c3ed7aeb62db6&user=30972

这行得通。它 return 是数据。但是当我从我的网络应用程序中调用同一个端点时,我什么也没得到。

$data = urlencode("token=a559d5bba5a9e9517d5c3ed7aeb62db6&user=30972");

$ch = curl_init('http://example.com/api2/user/session');
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
    'Content-Type: application/x-www-form-urlencoded',
    'Content-Length: ' . strlen($data))
);

$result = curl_exec($ch);

我不明白的是我可以 运行 以下内容,它 return 的内容是:

print file_get_contents("http://www.google.com");

当我 var_dump 端点 user/session 上的 $_POST 字段时,它 return 使用 Postman 的 post 数据数组但是$_POST 通过网络应用程序发送时,字段为空白。甚至在它向数据库发出任何请求之前,post 字段应该设置正确吗?

通过 SSH 这也有效:

curl -F token=a559d5bba5a9e9517d5c3ed7aeb62db6 -F user=30972 http://example.com/api2/user/session

按照我试过的评论中的建议:

var_dump(function_exists('curl_version'));

// bool(true)

我搞不懂这是怎么回事。

编辑:这行得通 ...但我不想使用套接字。一定是卷曲问题。

$fp = fsockopen('example.com', 80);

$vars = array(
    'token' => 'a559d5bba5a9e9517d5c3ed7aeb62db6',
    'user' => '30972'
);
$content = http_build_query($vars);

fwrite($fp, "POST /api2/user/session HTTP/1.1\r\n");
fwrite($fp, "Host: example.com\r\n");
fwrite($fp, "Content-Type: application/x-www-form-urlencoded\r\n");
fwrite($fp, "Content-Length: ".strlen($content)."\r\n");
fwrite($fp, "Connection: close\r\n");
fwrite($fp, "\r\n");

fwrite($fp, $content);

header('Content-type: text/plain');
while (!feof($fp)) {
    echo fgets($fp, 1024);
}

编辑:

curl_error() 也 return 没有错误。

原来我需要用http_build_query

$vars = array(
    'token' => 'a559d5bba5a9e9517d5c3ed7aeb62db6',
    'user' => '30972'
);

$content = http_build_query($vars);

$ch = curl_init('http://example.com/api2/user/session');
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
    'Content-Type: application/x-www-form-urlencoded',
    'Content-Length: ' . strlen($content))
);

$result = curl_exec($ch);

这可能是由会话锁定引起的...如果您使用curl 访问同一台服务器,则使用同一会话。虽然脚本是 运行,但默认情况下会话是锁定的,这意味着当前请求必须在同一会话处理另一个请求之前完成。这可以解释 curl 中的请求超时,因为您的第一个请求未完成,另一个请求...

curl_exec 之前使用 session_write_close() 将解锁会话并更正问题。

为了更好地理解 PHP 代码和 cURL 之间的区别,我创建了一个 RequestBin 实例并尝试了这两种方法。他们产生了截然不同的结果:

似乎来自 PHP 脚本的 POST 数据对发送的内容产生了错误的结果。这可以通过使用 built-in PHP 函数 http_build_query.

来解决

它会产生更合适的结果: