I've a php based website and would like browser to cache the images for 30 days .. i am using a shared hosting solution where I do not have access to apache config to enable mod-headers or other modules and so can not use htaccess mechanisms for this.
my site is a regular php app, and has both html contents and images. I would like browser to cache images only. I've seen php's "header" function, but couldn't find a way to force only image cache .. How do i go about it ?
Thanks
As far as I know, if you can't get access to Apache to set the headers, your only other option is to serve images from a PHP script so you can use the PHP Header methods to set the headers.
In this case, you'd need to write a PHP image handler, and replace all your image tags with calls to this handler (e.g. http://mysite.com/imagehandler.php?image=logo.png). You would then have you imagehandler.php script retrieve the image from the file system, set the mime type and cache control headers, and stream the image back to the client.
You could write your own, or if you google, you will find image handler PHP scripts. Either way, make sure you focus on security - don't allow the client to retrieve arbitrary files from your web server, because that would be a fairly major security hole....
Related
What I want to do is the following:
A User initates a HTTP GET request for a static file (for example an image or an mp3 file for HTML5 audio)
A PHP script intercepts these requests (for example via mod_rewrite) and checks the cookie for valid authentification
If successful, the file is delivered to the User, or the User gets a 401
Now, it would be perfect and most simple if the PHP script could "pass through" a successful request and return control to Apache, so that Apache can deliver the file as if it was the original request. Since we have also caching and the need to deliver audio files (including chunked requests) this would free the php script from manually creating the response headers etc.
Is this possible at all?
And if not, what would be the easiest, simplest solution to achieve this, so that caching and (chunked) requests for audio files still works as intended?
I think what you want is X-Sendfile.
Indeed, you can use mod_rewrite to let PHP deal with whatever-mime files, and then return an error or the wanted file via the X-Sendfile header (note that you’ll have to activate the eponymous module within apache).
Didn’t test it though. It seems to be a pretty important issue. OwnCloud, for example, still use PHP to serve files...
Background info:
I am working on a website which will provide image and video content via a subscription service. That is, users should ONLY have access to the image and video content so long as they are logged in successfully. (Note: the log in system uses a combination of MySQL DB - to store the username and password - and php to create new user sessions / authentication etc.)
The problem:
How do I stop a user (logged in or not) from directly accessing the image and video files? For example, a user who is not logged in could access the file directly as follows: www.domain.com/testvideo.mp4 - this would render the video content in the browser for them to watch or share with others. (NOTE: I still need to be able to use / display the image and video files on-site via HTML, CSS, PHP etc)
I have tried several .htaccess solutions (including: RewriteCond/RewriteRule & .htpassword) which have successfully prevented direct access BUT have prevented the ability to use the files on-site via HTML, CSS, PHP etc.
I was thinking that this must be a very common problem and if so, what the best way to resolve it was?
It is a pretty common problem with a pretty common solution. In order to force access control you have to invoke a PHP script before serving the file and verify the credentials. Then, if the credentials are valid, serve the actual file.
You may be tempted to serve the file directly from PHP script using something like readfile. This is going to kill your server performance and break download resuming for the client.
Luckily there is a solution, when you can hand over the actual file serving back to the web-server.
This works as following:
The web-server receives the request to /file.mp4.
According to the rewrite rules you've set up it directs it to your PHP script /serve.php instead.
Your script verifies the credentials, e.g. something from the session or cookies.
If the credentials are valid, the script issues specially crafted header. It tells the web-server to actually serve the static file. If not, you may as well output a 403 HTTP code.
The example script can be something like:
$file = '/tmp/file.mp4'; // it is in your best interest to make this file inaccessible for a direct download
header('X-Sendfile: ' . $file);
header('Content-Type: ' . contentType($file));
header('Content-Disposition: inline;');
In order for this to work you'll have to have mod_xsendfile (https://tn123.org/mod_xsendfile/) installed on your Apache, which is probably already the case for your hoster. You'll also have to drop in some lines to configure it and setup a proper rewrite.
You can fine a lot of stuff on Google by issuing "mod_xsendfile php", which might also help a great deal.
Hope that makes sense!
You cannot avoid that as long as your files are publicly available.
The most common way is to not serve the files directly, but to serve them through php so that you can check the users access before you serve the file. And the files can then reside anywhere on the server where the web-server user (www, apache, etc.) has access but the visitor hasn't.
Check the examples in the php manual on readfile and header to see how you can serve a file through php. You will find lots of examples here on SO as well.
I am a developer of Wave Framework, a lightweight framework that includes a number of functionality that makes it easier to deploy API's and serve resources dynamically.
One of those features is on-demand image editing. For example, on my server I have this file:
http://www.waher.net/w/resources/images/logo.png
But in my HTML, I load my image from a URL like this:
http://www.waher.net/w/resources/images/160x160&logo.png
This '160x160&logo.png' file does not actually exist and the only file that exists is 'logo.png'. Every HTTP request is routed to PHP and parameters in the file URL are parsed in order to apply additional functionality, like picture resolution.
Why is this useful? If my system has a large number of user avatars and my design changes, I can easily change the avatar picture URL's and everything works as expected. I never have to regenerate all the avatars of all my users, especially of those users that do not exist in my system anymore and just waste resources.
But here's my problem, if I want to implement Nginx to serve static files on my server, my system does not work. This is because Nginx will attempt to load static files itself and throws a 404 Not Found message if picture was not found. I assume that the same is true with Apache and Squid.
One of my clients specifically requested that they wish to serve images and resources through Nginx instead, but they would still like the dynamic images for the ease of development and design.
Is it possible to tell Nginx or Squid to send the request to PHP, if the image file itself is not found, get the 'dynamic' image from PHP and then send it to a user through Nginx? And at the same time always serving it from Nginx cache in any subsequent request to the same file?
I want to have the flexibility of dynamically loaded image files, but also have the speed of Nginx when serving image files. Is something like this possible? Do I need to set specific file headers in PHP that allow for this? (I already set cache and expire headers).
Thank you!
Signed URLs are paths like below, is that the correct name for those?
http://mydomain.tld/<randomhash>.<extension>
They mostly protect access to an image and are often only available a certain amount of time. If you know the path and filename, you get access.
This seems to be acceptable user access restriction for many webmail and other web application and it seems to be a common pattern.
Alternatively you could serve files or images through a script that checks access for each request, which allows tracking and user credential check on each access as described in here: Serve image with PHP script vs direct loading an image
So the trade of between the two would be, and here I would like to know if that is complete or if there is more to consider:
signed urls need to be generated, served, discarded after t
the longer t the more insecure
the shorter the path the more insecure
even when served via https sniffing the url gives anyone access during timeout of t
access after generation is
While serving through php has the issues:
each time accessed generating load on script engine checking user and serving image, not allowing web server a direct file path access
What would be the better approach in general? If that cannot be said, which other perspectives/issues are to be considered?
Using PHP (or any other language) is a good option here with no much overhead. What I would do:
using Nginx or other webserver with X-forward capabilities (see e.g. mod_xsendfile on Apache)
using the hash in GET parameter not be able to sniffed on a https channel (e.g.: http://mydomain.tld/image?hash=<randomhash>)
on page load PHP can check if the given hash is right (even without a database with a simple file_exists call to the <hash>.png/jpeg/etc.) and give back the required headers with the X-forwarded image
delete/remove unneeded images from protected folder after duration of time
Say I have the URL of an image, and URL file-access is disabled in the server configuration, and that's not something I can (or want) to change, is there an easy way to get it's height/width using PHP?
I'd prefer not to use javascript if possible.
umm, so you're going to pull the image over the network into your PHP application "find" the size, and then presumably emit an HTML img take with the size? seems kind of funky to me.
This doesn't really make much sense since if you can view the image on a web page, the image should be directly accessible via the URL. Why, in other words, would you have a url to an image that can't be accessed via url?
Regardless, you can use any number of http/url libraries to set a user-agent in the header of the request. Essentially, you trick the server into believing that a browser is accessing the file, rather than an anonymous service.
Here is a list of browser user agents you can use for this purpose.
In order to examine a remote image, you're going to have to request it somehow. You can't determine properties of something you can't see. If remote file access is disabled for your PHP installation, you might have to farm this out to a system level process, such as wget, cURL, or ftp.
Odds are if your host has disabled remote file access, they've probably disabled shell access too, but as an example, you could do something like:
exec("wget ".$url);
Another option might be to use the built-in cURL package, if by some odd configuration it's installed and active despite not having remote file access.
If you can figure out a way to download the image from the remote server, you can use getimagesize() on it.