spoiler* convoluted code ahead
Context
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:
- the function file_get_contents itself fails.
- the request made by the function is completed successfully
Example and Symptoms
I hit submit on main.php to call submit.php with parameters to make a post request for list/access/index.php:
- Server hangs until timeout
-
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.
Relevant code
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,": ","
");
$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;
}
References
I used How do I send a POST request with PHP? to construct my post_request.
Final thoughts
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.