file_get_contents 失败,但 POST 请求成功
file_get_contents fails, but POST request is made successfully
剧透*前面复杂的代码
上下文
main.php有一个command-line like input,文件的form action属性是submit.php。 submit.php 根据来自 main.php 的输入决定要调用的其他文件。在 submit.php 中,我调整变量 $url 和 $data,基于在输入上,然后使用这些参数调用 file_get_contents。
对于没有 session header 的 post 请求我没有任何问题,但是一旦我需要这些并尝试发送它们,我遇到了障碍:
- 函数file_get_contents本身失败了。
- 函数请求成功完成
示例和症状
我在 main.php 上点击提交以使用参数调用 submit.php 来制作 post 请求 list/access/index.php:
- 服务器挂起直到超时
超时时,我得到以下输出。
警告:file_get_contents(http://localhost/example/list/access/index.php):无法打开流:HTTP 请求失败!在 /Users/josetaveras/Sites/example/php_toolbox/toolbox.php 第 83 行
警告:无法修改 header 信息 - headers 已经由 /Users/josetaveras/Sites/example/list/submit 中的(输出开始于 /Users/josetaveras/Sites/example/php_toolbox/toolbox.php:83)发送。 php 第 373 行
当我返回 main.php 时,我知道 post 请求已成功完成,因为在 list/access/index.php 只是设置了一个 session 变量。返回 main.php.
时可以看到此变量
相关代码
submit.php
$result = post_request($url,$data,$headers);
header(
'Location: '
.$root_folder_path
.'list/?h='
.$hash
);}
// after post_request we get back to main.php with simple header redirect
toolbox.php
/*
* recursive merging 2 arrays
*/
function rec_array_merge($ar1,$ar2){
foreach($ar2 as $k=>$v){
if(is_array($v)){
if(isset($ar1[$k])){
$ar1[$k] = rec_array_merge($ar1[$k],$v);
}else{
$ar1[$k]=$v;
}
}else{
$ar1[$k]=$v;
}
}
return $ar1;
}
function serialize_array($array,$map_symbol,$separator_symbol){
$returnstr = "";
foreach($array as $k=>$v){
$returnstr.=$k.$map_symbol.$v.$separator_symbol;
}
return $returnstr;
}
function post_request($url,$data,$headers=NULL){
$post_content = http_build_query($data);
$default_headers = Array(
"Content-type"=>"application/x-www-form-urlencoded"
,"Content-Length"=>strlen($post_content)
);
if(isset($headers)){
try{
$headers = rec_array_merge($default_headers,$headers);
}
catch(Exception $e){
print_r($e);
}
}else{
$headers = $default_headers;
}
$serialized = serialize_array($headers,": ","\r\n");
$options = array(
'http' => array(
'header' => $serialized
,'method' => 'POST'
,'content' => $post_content
,'timeout' => 1 // for debugging purposes
)
);
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context); // line 83 on toolbox.php
return $result;
}
参考资料
我用 How do I send a POST request with PHP? 构建了我的 post_request。
最后的想法
说我对PHP不是很熟练是多余的,我知道也明白我有坏习惯。这导致代码有点乱,还有很多糟糕的选择。我的印象是,总体而言,这种 模式 感觉很脆弱。我并不是要重新发明轮子,但我有意避免使用促进这一切的库和包。我知道路由包可能会帮助我完成所有这些。
感谢您对这个问题的任何反馈。欢迎所有批评,我会尽快回复,但我的计算设备连接和访问权限有限。说了这么多,感谢您阅读到这里。
几个月后,我终于找到了发生这种情况的原因。
最糟糕的是我熟悉 error_reporting(E_ALL)
和 ini('error_notice',1)
但我完全忘记了。我确实了解了 var_dump($http_response_header)
所以就是这样。
老实说它在文档中,我应该早点找到它。好吧。
我自己引用
With post requests that do not have session headers I do not have any problem, but once I needed these and tried sending them, I hit a roadblock
我并不完全了解会话机制的一般工作原理,所以我基本上忽略了文档,直到几分钟前才找到它。我将 session_write_close 称为我在深入会话之前应该阅读的内容(或者更具体地说,尝试在请求链中打开多个会话(我认为是单个请求)):
session data is locked to prevent concurrent writes only one script may operate on a session at any time
在我的 submit.php 中,我打开会话以访问一些变量。在发出一个本身试图修改会话数据的新请求之前,我基本上忘记了关闭它。解决方法是在 post_request()
.
之前使用 session_write_close()
感谢所有评论的人。
剧透*前面复杂的代码
上下文
main.php有一个command-line like input,文件的form action属性是submit.php。 submit.php 根据来自 main.php 的输入决定要调用的其他文件。在 submit.php 中,我调整变量 $url 和 $data,基于在输入上,然后使用这些参数调用 file_get_contents。
对于没有 session header 的 post 请求我没有任何问题,但是一旦我需要这些并尝试发送它们,我遇到了障碍:
- 函数file_get_contents本身失败了。
- 函数请求成功完成
示例和症状
我在 main.php 上点击提交以使用参数调用 submit.php 来制作 post 请求 list/access/index.php:
- 服务器挂起直到超时
超时时,我得到以下输出。
警告:file_get_contents(http://localhost/example/list/access/index.php):无法打开流:HTTP 请求失败!在 /Users/josetaveras/Sites/example/php_toolbox/toolbox.php 第 83 行
警告:无法修改 header 信息 - headers 已经由 /Users/josetaveras/Sites/example/list/submit 中的(输出开始于 /Users/josetaveras/Sites/example/php_toolbox/toolbox.php:83)发送。 php 第 373 行
当我返回 main.php 时,我知道 post 请求已成功完成,因为在 list/access/index.php 只是设置了一个 session 变量。返回 main.php.
时可以看到此变量相关代码
submit.php
$result = post_request($url,$data,$headers);
header(
'Location: '
.$root_folder_path
.'list/?h='
.$hash
);}
// after post_request we get back to main.php with simple header redirect
toolbox.php
/*
* recursive merging 2 arrays
*/
function rec_array_merge($ar1,$ar2){
foreach($ar2 as $k=>$v){
if(is_array($v)){
if(isset($ar1[$k])){
$ar1[$k] = rec_array_merge($ar1[$k],$v);
}else{
$ar1[$k]=$v;
}
}else{
$ar1[$k]=$v;
}
}
return $ar1;
}
function serialize_array($array,$map_symbol,$separator_symbol){
$returnstr = "";
foreach($array as $k=>$v){
$returnstr.=$k.$map_symbol.$v.$separator_symbol;
}
return $returnstr;
}
function post_request($url,$data,$headers=NULL){
$post_content = http_build_query($data);
$default_headers = Array(
"Content-type"=>"application/x-www-form-urlencoded"
,"Content-Length"=>strlen($post_content)
);
if(isset($headers)){
try{
$headers = rec_array_merge($default_headers,$headers);
}
catch(Exception $e){
print_r($e);
}
}else{
$headers = $default_headers;
}
$serialized = serialize_array($headers,": ","\r\n");
$options = array(
'http' => array(
'header' => $serialized
,'method' => 'POST'
,'content' => $post_content
,'timeout' => 1 // for debugging purposes
)
);
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context); // line 83 on toolbox.php
return $result;
}
参考资料
我用 How do I send a POST request with PHP? 构建了我的 post_request。
最后的想法
说我对PHP不是很熟练是多余的,我知道也明白我有坏习惯。这导致代码有点乱,还有很多糟糕的选择。我的印象是,总体而言,这种 模式 感觉很脆弱。我并不是要重新发明轮子,但我有意避免使用促进这一切的库和包。我知道路由包可能会帮助我完成所有这些。 感谢您对这个问题的任何反馈。欢迎所有批评,我会尽快回复,但我的计算设备连接和访问权限有限。说了这么多,感谢您阅读到这里。
几个月后,我终于找到了发生这种情况的原因。
最糟糕的是我熟悉 error_reporting(E_ALL)
和 ini('error_notice',1)
但我完全忘记了。我确实了解了 var_dump($http_response_header)
所以就是这样。
老实说它在文档中,我应该早点找到它。好吧。
我自己引用
With post requests that do not have session headers I do not have any problem, but once I needed these and tried sending them, I hit a roadblock
我并不完全了解会话机制的一般工作原理,所以我基本上忽略了文档,直到几分钟前才找到它。我将 session_write_close 称为我在深入会话之前应该阅读的内容(或者更具体地说,尝试在请求链中打开多个会话(我认为是单个请求)):
session data is locked to prevent concurrent writes only one script may operate on a session at any time
在我的 submit.php 中,我打开会话以访问一些变量。在发出一个本身试图修改会话数据的新请求之前,我基本上忘记了关闭它。解决方法是在 post_request()
.
session_write_close()
感谢所有评论的人。