Welcome Guest, Not a member yet? Register   Sign In
file_get_contents causes a 404 error
#1

Hi,

I am working on my first CodeIgniter project - using 3.1 and liking it so far!

However I have come across an issue which has stumped me and I haven't found anything online about it.

I have a route:

Code:
$route['storage/item/(:any)'] = 'StorageController/item/$1';

which is handled in the StorageController by:

Code:
  public function item($uniqid)
  {
      $filename = APPPATH.'storedData\\'.$uniqid.'.xyz';
      $data['xyz'] = file_get_contents($filename);
      $this->load->view('storage/item',$data);
  }

and the view is simply:

Code:
<?php header('Content-Type: text/plain'); ?>
<?php echo($xyz); ?>

or in other words, just displays the plain text file contents for the $uniqid that is stored in a set location on the webserver.

That works fine in the browser with an internal url of (for example) http://www.domain.com/storage/item/57d952d0a09d0

Now, I have a database table that stores URL's which may be external or internal (i.e. in the above example form) for which I want to retrieve the data.
That I attempt with file_get_contents:


Code:
  public function load($id)
  {
      $data['title'] = 'XYZ Data Load';

      $record = $this->StorageModel->getId($id);

      if($record !== NULL)
      {
        $data['description'] = $record->description;
        $data['url'] = $record->url;
        $data['xyz'] = file_get_contents($data['url']); //problem line

        $this->load->view('templates/head', $data);
        $this->load->view('storage/current/load',$data);
        $this->load->view('templates/footer');
      }
      else
      {
        $data['id'] = $id;
        $this->load->view('templates/head', $data);
        $this->load->view('storage/current/loadFailed',$data);
        $this->load->view('templates/footer');
      }
  }

If the stored URL is external (i.e. not under www.domain.com) then the file_get_contents works fine.
But for an internal URL it causes a 404 error, despite it displaying when typed into the browser address bar.

Can anyone shed some light on what is going on?

Many thanks!
Reply
#2

file_get_contents() will return FALSE if it fails. So before using the returned value check that it isn't FALSE.
Reply
#3

I think your $record would be FALSE rather than NULL if there is no record.
A good decision is based on knowledge and not on numbers. - Plato

Reply
#4

Here's a way to check the return of file_get_contents and, at the same time, make the function a lot more DRY.

Code:
public function load($id)
{
    $data['title'] = 'XYZ Data Load';
    $this->load->view('templates/head', $data);

    $data['id'] = $id;
    $view = 'storage/current/loadFailed';

    $record = $this->StorageModel->getId($id);
    if($record !== NULL)
    {
        $file = file_get_contents($record->url); //problem line
        if($file !== FALSE)
        {
            $data['description'] = $record->description;
            $data['url'] = $record->url;
            $data['xyz'] = $file;
            $view = 'storage/current/load';
        }
        else //else for development debug only. Remove it once you figure out what's going on
        {
            print_r(error_get_last());
        }
    }

    $this->load->view($view, $data)->view('templates/footer');
}
Reply
#5

(09-15-2016, 06:59 AM)salain Wrote: I think your $record would be FALSE rather than NULL if there is no record.

Thanks, for your thought; in this case the record exists (prefabricated testing data) but also the model class method ensures a NULL on failure.
Reply
#6

Thanks for the thoughts; quite agree this isn't yet production code!

So the print_r(error_get_last()); shows:

Quote:Message: file_get_contents(http://www.domain.com/storage/item/57d952d0a09d0): failed to open stream: HTTP request failed! HTTP/1.1 404 Not Found
which is consistent with what I had seen before.

What I have noticed is that when I request http://www.domain.com/storage/item/57d952d0a09d0 in the browser, the page displays BUT in the apache access log it shows:

Quote:127.0.0.1 - - [16/Sep/2016:10:20:57 +0100] "GET /storage/item/57d952d0a09d0 HTTP/1.1" 404 4

In fact ALL page requests result in a 404 code in the access log!
Something to do with the URL handling in the framework I guess.

I suppose it is that 404 code that file_get_contents is receiving.
Reply
#7

Furthermore, if I set the internal URL to

Quote:http://www.domain.com/index.php/storage/...952d0a09d0
then the access log shows

Quote:127.0.0.1 - - [16/Sep/2016:10:47:44 +0100] "GET /index.php/storage/item/57d952d0a09d0 HTTP/1.1" 200 4
and the load method works...

So my confusion now lies in how any of the URL's are working at all, since I have no mod_rewrite specification in httpd.conf and no .htaccess file
Reply
#8

After a bit more digging, I now understand.

In my Apache VirtualHost configuration, I had (among other things)

Code:
<VirtualHost *:80>
  <Directory "/">
    DirectoryIndex index.php
    ErrorDocument 404 /
  </Directory>
</VirtualHost>
which means that any 404 document was getting handled by /index.php which of course then routed it properly and displayed the page correctly.
Removing the ErrorDocument directive then caused a URL such as
http://www.domain.com/storage/item/57d952d0a09d0
to break, whereas in the form
http://www.domain.com/index.php/storage/item/57d952d0a09d0
it works properly.

Having now also discovered the FallbackResource directive, my VirtualHost will look more like

Code:
<VirtualHost *:80>
  <Directory "/">
    DirectoryIndex index.php
  </Directory>
    
  FallbackResource /index.php
</VirtualHost>

since the fallback means there should never be a 404...

So now everything is working as I expected it to with my first cut code. Happy days.

Hopefully this information will ease someone else's pain in the future...

Best wishes,
Gordon
Reply




Theme © iAndrew 2016 - Forum software by © MyBB