2
votes

I have the following PHP file:

<?php

Header('Content-Type: application/javascript');

echo "// Some dynamically generated JavaScript here...";

So it's a .php file but it's interpreted as a JavaScript file. I would load it in a web page like so:

<script type='text/javascript' src='myjavascript.php'></script>

My question is regarding the HTTP code that is sent when accessing this file. Every time I request this file (either directly or via a webpage that is requesting it) Chrome Dev Tools shows a Status of 200 OK. It is never a 304, even if the content hasn't changed.

Is it possible to get a 304 Not Modified for a dynamically generated file like this in the case that the content hasn't changed? If not, why?

I have also used some PHP framworks that allow for routes like: /js/myjavascript.js. So I can put the above code in that route, dynamically generating the JavaScript in the same way. But again, still a 200 every time, even though the content hasn't changed AND the URI is a .js file.

Is there a solution for this? In my situation, the contents of this javascript/php file changes about once a day. So I need my visitors browsers to cache the file most of the time (304 Not Modified) but when it does change, I need their browser to download and cache the new version (200 OK).

1
FYI, this problem has nothing to do with the fact that you are generating JavaScript, specifically. I've seen this question on StackOverflow before for a general page... can't find it at the moment, but you might have better luck if you search for creating proper cacheable responses from PHP in general.Brad
check out these, they might have what you're looking for.Sammitch

1 Answers

1
votes

The 304 Not Modified header should only get sent if the client included an If-Modified-Since header in the request.

I have a PHP script that always generates the same consistent output (it happens to be image/png) depending on what options are fed to it by a Rewrite rule. For my script, I assume that ANY If-Modified-Since reflects valid cache data in the browser, so my script includes:

// If they've got it, they should use it.
if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && strlen($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
    header("HTTP/1.0 304 Not Modified");
    exit;
}

If you want to be smarter about this, you can parse the variable and compare it to whatever is important to your script. You need to think about how you will detect whether the content has changed in the context of a PHP script which dynamically generates content each time it is run.

For additional wisdom on how browser caching works in PHP, check out this comment on PHP: header.

You can test this behaviour using cURL from a command line:

[ghoti@pc ~]$ curl -sL -w "%{http_code} %{url_effective}\\n" https://www.google.com/images/srpr/logo3w.png -o /dev/null
200 https://www.google.com/images/srpr/logo3w.png
[ghoti@pc ~]$ curl -H"If-Modified-Since: Sat, 31 Dec 2011 00:00:00 GMT" -sL -w "%{http_code} %{url_effective}\\n" https://www.google.com/images/srpr/logo3w.png -o /dev/null
200 https://www.google.com/images/srpr/logo3w.png
[ghoti@pc ~]$ curl -H"If-Modified-Since: Mon, 31 Dec 2012 00:00:00 GMT" -sL -w "%{http_code} %{url_effective}\\n" https://www.google.com/images/srpr/logo3w.png -o /dev/null
304 https://www.google.com/images/srpr/logo3w.png
[ghoti@pc ~]$ 

Note the different dates.

If you're having trouble with Chrome thinking that not enough headers have been sent, you might try duplicating what other popular sites provide in the way of headers:

[ghoti@pc ~]$ curl -H"If-Modified-Since: Mon, 31 Dec 2012 00:00:00 GMT" -sLI https://www.google.com/images/srpr/logo3w.png
HTTP/1.1 304 Not Modified
Date: Wed, 05 Dec 2012 17:40:52 GMT
Expires: Thu, 13 Dec 2012 17:40:52 GMT
Age: 241012
Server: GFE/2.0

No doubt, Server: can be ignored, but you may have less complaints from Chrome if you include the other three. Though, as I said, YOU will have to come up with the criteria you want to use to determine what "age" you consider your dynamically-generated content, since the filesystem timestamp on a static file as detected by Apache is no longer usable.