file_get_contents 失败,但 POST 请求成功

file_get_contents fails, but POST request is made successfully

剧透*前面复杂的代码

上下文

main.php有一个command-line like input,文件的form action属性是submit.phpsubmit.php 根据来自 main.php 的输入决定要调用的其他文件。在 submit.php 中,我调整变量 $url 和 $data,基于在输入上,然后使用这些参数调用 file_get_contents

对于没有 session header 的 post 请求我没有任何问题,但是一旦我需要这些并尝试发送它们,我遇到了障碍:

示例和症状

我在 main.php 上点击提交以使用参数调用 submit.php 来制作 post 请求 list/access/index.php:

当我返回 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()

感谢所有评论的人。