
本文详解如何通过 php 的 stream_context_create 和 file_get_contents 正确发起带表单数据的 post 请求,并在服务端可靠获取请求头及原始参数,避免 exec + curl 的安全隐患与上下文误用问题。
本文详解如何通过 php 的 stream_context_create 和 file_get_contents 正确发起带表单数据的 post 请求,并在服务端可靠获取请求头及原始参数,避免 exec + curl 的安全隐患与上下文误用问题。
在 PHP 中向远程 URL 发起 POST 请求并传递表单数据(如 application/x-www-form-urlencoded),关键在于正确构造请求上下文,并在目标服务器端准确解析传入的请求头与请求体。您当前代码存在两个核心问题:
- 误用 exec() 拼接 $context:$context 是一个资源句柄(resource),不能直接拼入 shell 命令字符串;curl --data "$context" 实际上传递的是无意义的资源标识符,导致请求体丢失,仅发送了默认 curl 请求头;
- 服务端仅读取请求头,未解析请求体:apache_request_headers() 仅返回 HTTP 头信息(如 Content-Type, Host),而您的查询参数(feed_them_social=yes&...)实际位于请求体(request body)中,需通过 $_POST 或 file_get_contents('php://input') 获取。
✅ 正确做法如下:
① 客户端:使用 file_get_contents() + stream_context_create 发送 POST
$postdata = http_build_query([
'feed_them_social' => 'yes',
'refresh_token' => get_option('custom_refresh_token'),
'time' => esc_html(get_option('custom_token_exp_time')),
]);
$opts = [
'http' => [
'method' => 'POST',
'header' => "Content-type: application/x-www-form-urlencoded\r\n" .
"Content-Length: " . strlen($postdata) . "\r\n",
'content' => $postdata,
]
];
$context = stream_context_create($opts);
$response = file_get_contents('https://my-url.com', false, $context);
if ($response === false) {
error_log('POST request failed: ' . print_r(error_get_last(), true));
} else {
echo '<pre class="brush:php;toolbar:false;">'; print_r($response); echo '';
}
✅ 注意:手动添加 Content-Length 头是良好实践(虽部分环境可省略),且换行符必须为 \r\n(RFC 规范)。
② 服务端:同时检查请求头与请求体
在 https://my-url.com 对应的 PHP 脚本中,按需获取不同信息:
// 1. 获取所有 HTTP 请求头(含自定义头)
$headers = apache_request_headers();
echo "<h3>Request Headers:</h3><pre class="brush:php;toolbar:false;">";
foreach ($headers as $key => $value) {
echo "$key: $value\n";
}
echo "";
// 2. 获取已解析的 POST 参数(推荐,适用于 x-www-form-urlencoded)
echo "POST Data (via \$_POST):
"; print_r($_POST); echo ""; // 3. 获取原始请求体(适用于调试或非标准编码) echo "
Raw Request Body:
";
$rawBody = file_get_contents('php://input');
echo htmlspecialchars($rawBody);
echo "";
⚠️ 重要注意事项:
- 确保目标服务器启用 mod_rewrite 或正确配置 .htaccess,避免 Apache 吞掉 Content-Type 头;
- 若使用 Nginx,apache_request_headers() 不可用,请改用 getallheaders()(需启用 fastcgi_param 配置)或遍历 $_SERVER 中 HTTP_* 变量;
- file_get_contents() 默认不返回响应头;如需获取响应头,请改用 cURL 并设置 CURLOPT_HEADER => true,或使用 get_headers() 单独请求;
- 生产环境严禁使用 exec() 执行动态拼接的 shell 命令,存在严重命令注入风险。
通过以上修正,您将能稳定发送结构化 POST 数据,并在服务端完整、安全地捕获请求头与业务参数。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











