skip to Main Content

THE PROBLEM

I am mantaining a webpage that’s running in a server hosted by Inmotion and using PHP 7.2.34. Let’s call it "https://company-website.net/"

Inside this page we need to read a JSON file. The file for sure is there, one can go to the url and open it and the JSON file is located in "https://company-website.net/locale.json"

And from one day to another, on January 10th 2024, file_get_contents suddenly returned this php error:

file_get_contents(https://company-website.net/locale.json): failed to open stream: HTTP request failed! HTTP/1.1 406 Not Acceptable

The code looked like this:

$fileUrl = 'https://'.$_SERVER['SERVER_NAME'].'/locale.json';
$file = file_get_contents($fileUrl);

I tried something else

I tried setting an Accept header like it said on this stack overflow thread (just changed Accept-Language: en for Accept: /:
PHP file_get_contents() and setting request headers

So, the code ended like this:

$fileUrl = 'https://'.$_SERVER['SERVER_NAME'].'/locale.json';
$opts = [
    "http" => [
        "method" => "GET",
        "header" => "Accept: */*"
    ]
];
$context = stream_context_create($opts);
$file = file_get_contents($fileUrl, false, $context);

But nothing

THE SOLUTION IN THE END

Then I ended up changing file get contents for curl, as mentioned in this thread:
PHP file_get_contents() returns "failed to open stream: HTTP request failed!"

so it ended up like this:

$fileUrl = 'https://'.$_SERVER['SERVER_NAME'].'/locale.json';
$curl_handle=curl_init();
curl_setopt($curl_handle, CURLOPT_URL, $fileUrl);
curl_setopt($curl_handle, CURLOPT_CONNECTTIMEOUT, 2);
curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl_handle, CURLOPT_USERAGENT, 'Company Name');
$file = curl_exec($curl_handle);
curl_close($curl_handle);

AND IT WORKED.

But still I’m baffled as to WHY it stopped working form one day to the other, not sure if it has something to do with PHP deprecation, with Inmotion changing something security wise, really lost here. I still want to try and use file_get_contents and understand what the issue could be. If anyone can give any insight, I’d be more than thankful.

3

Answers


  1. Chosen as BEST ANSWER

    In the end if you are interested in reading a file using a http request, as shingo said, is adding one of 2 elements to the header, in my case it was adding an User-Agent, even if it's anything. So the code ended up like this:

    $fileUrl = 'https://'.$_SERVER['SERVER_NAME'].'/locale.json';
    $opts = [
        "http" => [
            "method" => "GET",
            "header" => "User-Agent: Company Name"
        ]
    ];
    $context = stream_context_create($opts);
    $file = file_get_contents($fileUrl, false, $context);
    

    And it's working once more without the need of using curl. :)

    ON THE OTHER HAND The real issue was me not understanding that I could look up the file without having to input an URL to file_get_contents. I thought it would be the same, I have learned now that using $_SERVER['DOCUMENT_ROOT'] instead of 'https://'.$_SERVER['SERVER_NAME'] enables file_get_contents to read the file without an http request (as the path given is not pointing to an https url). All of this thanks to and mentioned by . ADyson and CBroe. The code would then have to be:

    $fileUrl = $_SERVER['DOCUMENT_ROOT'].'/locale.json';
    $file = file_get_contents($fileUrl, false, $context);
    

    Thanks everyone for the help!


  2. using PHP 7.2.34

    The biggest difference between file_get_contents and curl in PHP 7 is that file_get_contents defaults to using http/1.0, while curl uses http/1.1. Based on the returned 406 error, I believe it is highly likely that this is the reason. (Don’t feel strange, even if your request is sent with http/1.0, the server can response an http/1.1 error, see this question)

    Additionally, your curl code has added UA, which may be another issue.

    Try to add these two items to the context:

    "protocol_version" => "1.1"
    "user_agent" => "Company Name"
    
    Login or Signup to reply.
  3. It’s unclear why you’ve used a HTTP request at all here, since the JSON file appears to be on the same server as the PHP script. Direct filesystem access should be possible, and will be more performant.

    You could try something like:

    $filepath = $_SERVER['DOCUMENT_ROOT'] . '/locale.json';
    $file = file_get_contents($filepath);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search