Plesk Webserver responds with 304 instead 200 - php

I have the following simple script:
$ts = 1510317885;
header("Last-Modified: ".gmdate("D, d M Y H:i:s", $ts )." GMT" );
header("Cache-Control: no-cache, must-revalidate");
echo 'content';
I would expect that this script could never answer with a 304 Not modified.
But i have one server which is running Plesk 17.5 which responds with a 304 on every 2+ request. Other servers I manage behave as expected.
I'm trying to find out what's the cause of this. The browser requests the page, apache gets the request, all php code is run, still I see a 304 in the apache log and also in the browser a 304. I assume there might be an Apache module which answers with a 304 when If-Modified-Since matches Last-Modified, but i could not find such a thing. Or maybe a PHP setting? If I remove the Last-Modified Header it works as expected. But I want to keep it.
Can you tell me why the webserver answers here with a 304?

Related

Set-Cookie cached , even with F5 ? (unless I press CTRL+F5)

I obviously see, that in specific cases, after SetCookie() function, when I reload the page (or re-enter that page), I don't see the cookies set, unless i press CTRL+F5 (which is cache-cleared request).
have you ever met such occasion (this happens only on http version of the file, not on https).
this didn't help:
header('Expires: Sun, 01 Jan 2014 00:00:00 GMT');
header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
What I should do in order to get cookies read on next page-enter?
Cookies generally are hard to debug when they go wrong. What you are describing does seem to be related to caching but it sounds very odd.
Here's what you can try doing to see what's wrong.
Make sure you are setting the cookie in the correct domain and path . If your page is e.g. at www.example.com the domain should either be .example.com or www.example.com. The idea is same for the path (if you access www.exampl.com/path then the path needs to either be / or /path
If you need the cookie to be available on http then you should not set the secure attribute on it.
Make sure the cookie is not already expired when set, browsers will probably ignore it if it is.
A few basic things to check.
Assume that you have cookie line:
setcookie('name', 'value', time()+10000,'/test','.example.com');
Open the Chrome (or your favourite browser's) developer console and when you make the request check the cookies being set. There should be something along the lines of:
The duration must not be 0 and the rest should be correct.
When you make the next request the cookie should be sent as well.
This should be an entry in the "Request cookies".
If the cookie is received, but then not sent to the server it might be worth opening the browser settings and finding the stored cookies manually for any hints as to why this is happening. In chrome this would be in chrome://settings/siteData
If you still don't find anything wrong with any of these then check if there's any intermediate caching layer running, that would override the No-Cache header you are setting.
I've found that there was some kind on Nginx caching enabled, causing the browser not to recall the execution from server.
I've fixed that by including the random() string in the url, voiding the cache for that page-call.

Request timeout with 200 and refresh header

I have a simple php script running on Ubuntu 14, Apache 2.4.7 and PHP 5.5.9. Every once and a while the request seems to stall, and after about 40 secs (normally < 100ms), it responds with an empty page, 200 OK and a Refresh header to the same URL. I think it's happening more often, if there hasn't been a recent request to the script for a while.
Response:
HTTP/1.1 200 OK
Content-Type: text/html
Pragma: no-cache
Refresh: 1; URL=http://xxx.xxx.xxx.xxx/script.php?t=1407272586793
Connection: Close
Script content:
<?php
//# Provide server time
header('Access-Control-Allow-Origin: *');
echo '{"time":"'. gmdate("Y-m-d H:i:s") .' +0000"}';
There doesn't seem to be a record of the request in either the Apache access or error logs.
I'm not sure how to find at what point this is stalling. Has anyone experienced this before, or have any suggestion on how I might debug this further?

Test if X-Sendfile header is working

I am looking for a way to confirm if X-Sendfile is properly handling requests handed back to the webserver by a script (PHP). Images are being served correctly but I thought I would see the header in curl requests.
$ curl -I http://blog2.stageserver.net/wp-includes/ms-files.php?file=/2011/05/amos-lee-feature.jpg
HTTP/1.1 200 OK
Date: Wed, 04 Jan 2012 17:19:45 GMT
Server: Cherokee/1.2.100 (Arch Linux)
ETag: "4dd2e306=9da0"
Last-Modified: Tue, 17 May 2011 21:05:10 GMT
Content-Type: image/jpeg
Content-Length: 40352
X-Powered-By: PHP/5.3.8
Content-Disposition: inline; filename="amos-lee-feature.jpg"
Configuration
Cherokee 1.2.100 with PHP-FPM 5.3.8 in FastCGI:
cherokee.conf: vserver!20!rule!500!handler!xsendfile = 1
(Set by vServer > Behavior > Extensions php > Handler: Allow X-Sendfile [check Enabled])
Wordpress Network / WPMU 3.3.1:
define('WPMU_SENDFILE',true); is set in the wp-config.php the following just before wp-settings.php is included. This will trigger the following code to be executed in WP's wp-includes/ms-files.php:50 serves up files for a particular blog:
header( 'X-Sendfile: ' . $file );
exit;
I have confirmed that the above snippet is executing by adding an additional header for disposition right before the exit(); call. That Content-Disposition is present with curl results above and not originally in the ms-files.php code. The code that was added is:
header('Content-Disposition: inline; filename="'.basename($file).'"');
Research
I have:
Rebooted php-fpm / cherokee daemons after making configuration changes.
Tried several tricks in the comments over at php.net/readfile and replaced the simple header in ms-files.php with more complete code from examples.
php.net/manual/en/function.readfile.php
www.jasny.net/articles/how-i-php-x-sendfile/
*codeutopia.net/blog/2009/03/06/sending-files-better-apache-mod_xsendfile-and-php/*
Confirmed [cherokee support][5] and tested [with and without][6] compression even though I don't think it would apply since my images are serving correctly. I also found a suspiciously similar problem from a lighttpd post.
*cherokee-project.com/doc/other_goodies.html*
code.google.com/p/cherokee/issues/detail?id=1228
webdevrefinery.com/forums/topic/4761-x-sendfile/
Found a blurb here on SO that may indicate the header gets stripped
stackoverflow.com/questions/7296642/django-understanding-x-sendfile
Tested that the headers above are consistent from curl, wget, Firefox, Chrome, and web-sniffer.net.
Found out that I can't post more than 2 links yet due to lack of reputation.
Questions
Will X-Sendfile be present in the headers when it is working correctly or is it stripped out?
Can the access logs be used to determine if X-Sendfile is working?
I am looking for general troubleshooting tips or information here, not necessarily specific to PHP / Cherokee.
Update
I have found a suitable way to confirm X-Sendfile or X-Accel-Redirect in a test or sandbox environment: Disable X-Sendfile and check the headers.
With Allow X-Sendfile disabled in Cherokee:
$ curl -I http://blog2.stageserver.net/wp-includes/ms-files.php?file=/2011/05/amos-lee-feature.jpg
HTTP/1.1 200 OK
Date: Fri, 06 Jan 2012 15:34:49 GMT
Server: Cherokee/1.2.101 (Ubuntu)
X-Powered-By: PHP/5.3.6-13ubuntu3.3
Content-Type: image/jpeg
X-Sendfile: /srv/http/wordpress/wp-content/blogs.dir/2/files/2011/05/amos-lee-feature.jpg
Content-Length: 40352
The image will not load in browsers but you can see that the header is present. After re-enabling Allow X-Sendfile the image loads and you can be confident that X-Sendfile is working.
According to the source on github X-Sendfile headers will be stripped.
If I'm skimming the file correctly, it's only logging success if it's been compiled in debug mode.
You could check memory usage of sending large files with and without xsendfile.
They are being stripped, simply because having them present will prevent one of the reasons to use it, namely having the file served without the recepient knowing the location of the file being served.

Caching a GET request for audio with PHP

I have a PHP script that responds to a GET request for audio resources. An HTML5 Audio tag requests an audio file such as:
<audio src="get_audio.php?f=fun" preload></audio>
There is no need for the user to download that same audio file every time so I would like to cache it. In my PHP file I have:
header("Cache-Control: max-age=2419200");
header("Content-Type: audio/mpeg");
...
echo file_get_contents($path);
but when I view the Network tab of Chrome developer tools I see that it re-downloads the audio clip everytime rather than saying "from cache" and if I look in the Response headers I do see the Cache-Control header that I set. Why would it ignore this? Amidoingitright?
It's been a while since I did this in PHP, but try adding:
header("Pragma: public");
above the cache-control header.
I also think you need the expires header:
header('Expires: ' . gmdate('D, d M Y H:i:s', time()+2419200) . ' GMT');
Other than that you could start using the get_headers() function in PHP to debug where it's going wrong.
Do you see a header in the second request called If-Modified-Since:?
This is what you need to catch, parse and respond to - if you don't want to send the file again, you respond with HTTP/1.1 304 Not Modified. If you are using Apache, you can check for the header in the result of apache_request_headers(). If you are not using Apache, you may find it hard to handle this - you will probably have to find a way for the web server to set the headers as environment variables, so they are available in $_ENV or $_SERVER. There is a way to do this in Apache using mod_rewrite (see latest comment on page linked above), so there is probably a way to do it in other server environments as well.
Caching in HTTP 1.1 permits (and indeed, encourages) this behaviour - it means that the cached copy will always be up-to-date.

Can HTTP 304 message be avoided?

When using Codeigniter or a simple php page, loadin my test page once I get the normal 200 status but if it is cached I get the 304 message. I realize this is just a signal that the resource is cached but could I avoid it?
If so, how?
Thank you.
... or you could just do
header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past
in your PHP files right at the top. That way you have control over which pages not to cache and leave Apache running as it should.
If you don't want the page to be cached by browsers you need to configure the apache server to send the appropriate headers.

Categories