file_get_contents失败,但POST请求成功

时间:2018-01-06 21:08:46

标签: php http-post file-get-contents

扰乱*错综复杂的代码

上下文

main.php 具有类似输入的命令行,文件的操作属性为 submit.php submit.php 根据 main.php 的输入决定要调用的其他文件。在 submit.php 中,我根据输入调整变量$ url 和$ 数据,然后调用 file_get_contents 这些参数。

对于没有会话标题的帖子请求我没有任何问题,但是一旦我需要这些并尝试发送它们,我就遇到了障碍:

  • 函数 file_get_contents 本身失败。
  • 该功能的请求已成功完成

示例和症状

我在 main.php 上点击提交以使用参数调用 submit.php 来发送 list / access / index.php :

  • 服务器挂起,直到超时
  • 在超时时,我得到以下输出。

    警告:file_get_contents(http://localhost/example/list/access/index.php):无法打开流:HTTP请求失败!在/Users/josetaveras/Sites/example/php_toolbox/toolbox.php第83行

    警告:无法修改标头信息 - 已在/Users/josetaveras/Sites/example/list/submit.php中发送的标头(在/Users/josetaveras/Sites/example/php_toolbox/toolbox.php:83处开始输出)在第373行

当我回到 main.php 时,我知道发布请求已成功完成,因为在 list / access / index.php 中发出的请求只是设置了一个会话变量。返回 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不那么敏捷是多余的,我知道并且明白我有坏习惯。这导致代码中的一点点混乱和许多糟糕的选择。我的印象是整体上这个模式感觉很脆弱。我并不是想重新发明轮子,但是我有针对性地避免使用可以促进任何部分的库和包。我知道路由包可以帮助我完成所有这些。 我感谢您对此问题的任何反馈。所有的批评都是受欢迎的,我会尽快回答,但我的连接和访问我的计算设备有限。说完这一切之后,感谢您阅读到目前为止。

1 个答案:

答案 0 :(得分:0)

几个月后,我终于找到了发生这种情况的原因。 最糟糕的是,我对error_reporting(E_ALL)ini('error_notice',1)很熟悉,但是我完全忘记了。我确实了解了var_dump($http_response_header),所以确实有。 老实说,它在文档中,我应该早点找到它。哦,很好。

我引用自己

  

对于没有会话标题的帖子请求,我没有任何问题,但是一旦我需要这些标题并尝试发送它们,我就遇到了障碍

我并不完全了解会话机制的总体工作原理,因此直到几分钟前我发现它之前,我大部分都忽略了该文档。我将session_write_close称为进入会话之前(或更具体地说,尝试在请求链中打开多个会话(我认为是单个请求))之前应该阅读的内容:

  

会话数据被锁定以防止并发写入,任何时候任何一个会话上都只能操作一个脚本

在我的 submit.php 中,我打开会话以访问一些变量。我基本上忘了在发出新请求之前先关闭它,该请求本身试图修改会话数据。解决方法是在session_write_close()之前使用post_request()

感谢所有发表评论的人。