main.php has a command-line like input, the file's form action attribute is submit.php. submit.php decides what other file to call, based on the input from main.php. In submit.php I adjust variables $url and $data, based on the input, then call file_get_contents with these parameters.
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:
I hit submit on main.php to call submit.php with parameters to make a post request for list/access/index.php:
On timeout I get the following output.
Warning: file_get_contents(http://localhost/example/list/access/index.php): failed to open stream: HTTP request failed! in /Users/josetaveras/Sites/example/php_toolbox/toolbox.php on line 83
Warning: Cannot modify header information - headers already sent by (output started at /Users/josetaveras/Sites/example/php_toolbox/toolbox.php:83) in /Users/josetaveras/Sites/example/list/submit.php on line 373
When I go back to my main.php I know the post request is completed successfully because the request made in list/access/index.php simply sets a session variable. This variable is visible when going back to 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;
}
I used How do I send a POST request with PHP? to construct my post_request.
It is redundant to say that I am not so deft with PHP, and I know and understand that I have bad habits. This leads to a little bit of disorder in the code and many poor choices. My impression is that overall this pattern feels fragile. I'm not trying to reinvent the wheel, but I am pointedly avoiding libraries and packages that facilitate any part of this. I understand that a routing package might help me with all of this. I appreciate any feedback you may have on this question. All criticism is welcome and I will try to answer as soon as I can but I have limited connectivity and access to my computing devices. Having said all of that, thank you for reading up to this point.
After a few months I finally found the reason why this was happening.
The worst aspect of this is that I am familiar with error_reporting(E_ALL)
and ini('error_notice',1)
but I completely forgot about it. I did learn about var_dump($http_response_header)
so there is that.
Honestly it was in the documentation and I should have found it sooner. Oh well.
I quote myself
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
I was not familiar exactly with how session mechanics work in general, so i mostly ignored the documentation until I found it a few minutes ago. I refer to session_write_close as what I should have read before diving into sessions (or more specifically, attempting to open multiple sessions in a chain of requests (that I thought of as a single request)):
session data is locked to prevent concurrent writes only one script may operate on a session at any time
In my submit.php I open the session to access some variables. I basically forgot to close it before making a new request which itself attempted to modify session data. The fix was to use session_write_close()
right before post_request()
.
Thank you to all who commented.