I'm using Nginx as web server and Firefox to view response headers. For testing, I had two files on the server with the same content: test.html and test.php. In the Nginx configuration file, the expires directive is set to 30d in the server context.
When accessing test.html in a web browser multiple times, the browser first obtains a 304 Not Modified response and serves a copy cached in the browser. However, when accessing test.php, the browser always makes a full request to the server (200 OK) without using the browser cache.
The questions are:
Is the behaviour (i.e. different treatment of HTML and PHP generated files) normal?
What could be done to make web browsers cache HTML and PHP generated files in the same way?
nginx sets the response header for the static file, included in the headers are:
Cache-Control
Expires
Last-Modified
Cache-Control tells the client (at least) how to cache the content.
Expires and Last-Modified allow the client to determine when to fetch new content.
What you must do is ensure that PHP sends the same headers, or sensible headers if not exactly the same; Now that you know which headers are important, inspecting the requests in your browser will tell you how to achieve this.
Related
I am currently trying to configure the response headers for a Wordpress website.
Web Server: Apache 2
Operating System: Ubuntu 16.04
Right now, I have figured out that I am able to modify the HTTP response headers for the website through 3 different ways:
Configuring apache2.conf in /etc/apache2
Configuring the .htaccess file within the Wordpress directory
(I do not have mod_headers.c therefore I cannot use this method)
Directly specifying the headers to use in the header.php file of the current Wordpress theme
Previously I set the website's response headers through directly specifying the HTTP headers in the header.php file (which contains all the scripts and whatnot to be used for each page). However right now, I'm trying to move all header configuration into apache2.conf such that all sites hosted on the server have the same response headers.
However, after restarting the Apache server, I am getting duplicate response headers even though I had removed all header declarations from the header.php file, and I am not sure why...
Because of security issues, the authorities of the main domain that my department's site is on is requiring us to only specify one instance of each HTTP header.
Does anyone know how to resolve this issue, also, what are the best practices for setting HTTP response headers for sites hosted on an Apache 2 server?
I have added the following line in my .htaccess file to set the HSTS header
Header always set Strict-Transport-Security "max-age=63072000;includeSubDomains;"
To test the HSTS header, I have done the below steps:
Access the application in the chrome browser
Open the developer tool and check the HSTS header in the Response headers
The first time when I access the application and verified it in the developer tool, I could see the HSTS header in all the PHP files, image files, CSS files, and JS files.
Again when I load the application, I could see images, CSS, and JS files are loaded from the memory/disk cache and these files are missing the HSTS header in response headers.
However, PHP files still shows the HSTS header in the reponse headers.
Missing HSTS header in the resource files(image/CSS/JS files) is accepted? OR It is considered as security hole? If so how can I fix this?
Thank you in advance
The idea behind an HSTS header is that content is always downloaded over an encrypted connection.
Once the files are downloaded and put in your memory/disk cache they are no longer encrypted.
When your browser gets the files from memory/disk cache they also don't need to be downloaded over any connection. The memory/disk cache is a trusted resource. That's why the HSTS header is not needed.
I combined all my css files into a .php file to reduce the number of requests for each access to my webpage.
I set expiration date header to 1 day after request at my .php file
The problem is that the browsers don't use cache for .php files. I mean it doesn't send a IF-MODIFIED header field at request and therefore all subsequent requests will be responded with HTTP Response Code 200 (instead of 304).
You could use mod_rewrite to set up a rewrite rule to send all requests for a "fake" css path to your php file on the server. For instance, send all requests for all.css to combine_css.php.
I'm serving images two different ways:
Using a PHP script for profile pictures for example
By pointing to them directly, for icons and backgrounds for example
I'm in the process of handling their caching properly, and i'm totally new to this.
For the PHP script, i'm just adding a Last-Modified header to the response, and delivering a 304 status code if it's called again, if the file hasn't changed (using filemtime()).
For direct accesses, i'm using HTACCESS, but every rule i saw so far doesn't allow me to do the same as in my PHP script (checking if the file has changed, then serving a 304 or the file itself).
Here's the HTACCESS rule i'm planning to use:
Header unset Pragma
FileETag None
Header unset ETag
# cache images/pdf docs for 10 days
<FilesMatch "\.(ico|pdf|jpg|jpeg|png|gif)$">
Header set Cache-Control "max-age=864000, public, must-revalidate"
Header unset Last-Modified
</FilesMatch>
From what i understand, the only way of updating a cached image is to rename it. Does someone know a way around it? By checking the image's last modification date for instance?
You could use mod_expires, if available:
<FilesMatch "\.(ico|pdf|jpg|jpeg|png|gif)$">
ExpiresDefault "modification plus 10 days"
</FilesMatch>
What you are doing with PHP should do apache automatically for static files. It will set the Last-Modified header and respond with 304 if it will find if-Modified-since in the request. This is done automatically and has nothing to do with caching. It will not prevent repeated requests to your server, it will just save you bandwidth (and loading times for user) when the file is not modified by returning just 304 info instead of the whole file.
To prevent those repeated requests to your server, browser (and proxy servers) has to do some caching. You can control the caching either via HTTP headers or for HTML also via META tags. When you specify that the file is cacheable for 1 week, browser won't try to contact your server for 1 week (although most browsers are set to revalidate cache entries on first access after startup).
So you will either live with the possibility that some users will use old cached copy for some time (depends on the expiry header) or you must change your URL as Gerben suggested. Only then you can be 100% sure that everyone will get the new version (this is important for javascript as having some of the js files old and some new can make very strange errors). Nowadays almost every high performance website uses the file.ext?v=3 approach, so that they can set the expiry header to large values like 6 months.
As #Gumbo pointed out, "Apache should already do that for static files".
And that's true, Apache does that, so that kind of stuff works fine:
<FilesMatch "\.(ico|pdf|jpg|jpeg|png|gif)$">
Header set Cache-Control "max-age=864000, public, must-revalidate"
</FilesMatch>
ps: Sorry #Gumbo, but i asked you to change your answer so that i can accept it, but you wouldnt do it and i had to close that question eventually, so.
Is this by design?
On my Debian (Etch) server I noticed that Apache (2.2) will not send a Last-Modified header when serving PHP (mod_5.2.0) files (we're talking plain-jane echo 'Hello World'; PHP files).
Additionally, I noticed that the header Accept-Ranges is also not served by Apache for PHP files, although my main conern for the moment is the Last-Modified header.
PHP are dynamic page that can change. So Apache can't know the Last-Modified header.
You can add your own header with:
header('Last-Modified: GMT time');
Of course if you need this header maybe you are looking to manage the request header If-Modified-Since too.
You can find it in $_SERVER['HTTP_IF_MODIFIED_SINCE']
it only sends this with static files. php files aren't static.
but you can send them yourself, see http://www.php.net/manual/en/function.getlastmod.php#30514 for an example.