AJAX POST requests that are cached
In my web app, I am sending a POST request to the url /navigate.php
. It works as it should.
The problem is that this web app needs to work offline as well. I have to show a notification when the request cannot be completed due to connectivity issues and the user can sync again when troubleshooting.
When I disconnected the internet connection for debugging purposes, I found that the request still returns with a 200 status code every time.
Am I wrong that the POST request should not be cached by the browser?
After searching in Stack Overflow, I tried the solutions written here.
I added to the cache url (new Date().getTime())
but there was no change. Requests were still coming back from 200.
I tried to send the following headers from the server (PHP / Ubuntu):
header("Expires: Sat, 01 Jan 2005 00:00:00 GMT");
header("Last-Modified: ".gmdate( "D, d M Y H:i:s")."GMT");
header("Cache-Control: no-cache, no-store");
header("Pragma: no-cache");
I am not using jQuery for AJAX (since I only needed to use it for AJAX, nothing else), otherwise I would use its option cache
and set it to false
. But I think it does the same thing, add the cache to the url.
I am using the following code to send a request:
define([],function(){
var a=[
function(){return new XMLHttpRequest()},
function(){return new ActiveXObject("Msxml2.XMLHTTP")},
function(){return new ActiveXObject("Msxml3.XMLHTTP")},
function(){return new ActiveXObject("Microsoft.XMLHTTP")}
];
var o=function(){
var r=false;
for(var i=0;i<a.length;i++) {
try{
r=a[i]();
} catch(e) {
continue;
}
break;
}
return r;
};
var verifyParam = function(param) {
if(typeof param === "undefined" || param === null) {
return false;
} else {
return true;
}
};
var checkParam = function(param,defaultValue) {
if(!verifyParam(param)) {
return defaultValue;
} else {
return param;
}
};
var generateCacheBust = function() {
return (new Date().getTime());
};
var request = function(url,method,dataInPost,initCallback,callback,error) {
var req = o();
if(!req) return false;
initCallback = checkParam(initCallback,function(){});
callback = checkParam(callback,function(){});
error = checkParam(error,function(){});
initCallback(req);
req.open(method,url,true);
if(dataInPost) {
req.setRequestHeader('Content-type','application/x-www-form-urlencoded');
}
req.onreadystatechange = function() {
if(req.readyState!=4) {
return;
}
try {
if(req.status!=200 && req.status!=304) {
error(req.status);
return;
} else {
callback(req);
}
} catch (e) {
error(req.status);
return;
}
}
if(req.readyState == 4) return;
try {
req.send(dataInPost);
} catch (e) {
error(req.status);
return;
}
};
var dataToString = function(data) {
var string = '';
for(var key in data) {
string += (encodeURIComponent(key)+'='+encodeURIComponent(data[key])+'&');
}
return string.substring(0,string.length-1);
}
var formattedResponse = function(req,type) {
var responseData = req.responseText;
if(type=="json") {
return JSON.parse(responseData);
} else {
return responseData;
}
}
var get = function(params) {
if(!verifyParam(params.url)) { return false; }
params.data = checkParam(params.data,{});
params.responseType = checkParam(params.responseType,'text');
params.init = checkParam(params.init,function(){});
params.success = checkParam(params.success,function(){});
params.error = checkParam(params.error,function(){});
params.cache = checkParam(params.cache,true);
if(!params.cache) {params.data.cacheBust = generateCacheBust();}
request(params.url+'?'+dataToString(params.data),"GET",false,params.init,function(req){
params.success(formattedResponse(req,params.responseType));
},params.error);
};
var post = function(params) {
if(!verifyParam(params.url)) { return false; }
params.data = checkParam(params.data,{});
params.responseType = checkParam(params.responseType,'text');
params.init = checkParam(params.init,function(){});
params.success = checkParam(params.success,function(){});
params.error = checkParam(params.error,function(){});
params.cache = checkParam(params.cache,true);
if(!params.cache) {params.url += "?" + "cacheBust=" + generateCacheBust();}
request(params.url,"POST",dataToString(params.data),params.init,function(req){
params.success(formattedResponse(req,params.responseType));
},params.error);
};
return {
get:get,
post:post
};
});
In network log (Firefox), here are the headers shown by firebug
Request header:
POST /explorer/ajax/navigate.php?cacheBust=1412147821832 HTTP/1.1
Host: genortal.com
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:31.0) Gecko/20100101 Firefox/31.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Referer: http://genortal.com/dashboard.php
Content-Length: 12
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Response headers:
HTTP/1.1 200 OK
Date: Wed, 01 Oct 2014 07:17:01 GMT
Server: Apache/2.4.7 (Ubuntu)
X-Powered-By: PHP/5.5.9-1ubuntu4.3
Expires: Sat, 01 Jan 2005 00:00:00 GMT
Cache-Control: no-cache, no-store
Pragma: no-cache
Last-Modified: Wed, 01 Oct 2014 07:17:02GMT
Content-Length: 744
Keep-Alive: timeout=5, max=79
Connection: Keep-Alive
Content-Type: application/json
And here are the headers I get when the internet connection is disconnected:
Request header:
POST /explorer/ajax/navigate.php?cacheBust=1412148166275 HTTP/1.1
Host: genortal.com
Connection: keep-alive
Content-Length: 12
Cache-Control: no-cache
Pragma: no-cache
Origin: http://genortal.com
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36
Content-type: application/x-www-form-urlencoded
Accept: */*
Referer: http://genortal.com/dashboard.php
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Response headers:
HTTP/1.1 200 OK
Date: Wed, 01 Oct 2014 07:22:46 GMT
Server: Apache/2.4.7 (Ubuntu)
X-Powered-By: PHP/5.5.9-1ubuntu4.3
Expires: Sat, 01 Jan 2005 00:00:00 GMT
Cache-Control: no-cache, no-store
Pragma: no-cache
Last-Modified: Wed, 01 Oct 2014 07:22:47GMT
Content-Length: 117
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: application/json
Server side code:
<?php
/**
* Generation Portal
* Date: 24/9/14
* Time: 8:59 PM
*/
require_once '../../start_session.php';
require_once '../../libload.php';
use GenerationPortal\Genortal\Accounts\Session;
use GenerationPortal\Genortal\RequestIn;
use GenerationPortal\Genortal\ErrorDictionary\AjaxErrors;
use GenerationPortal\Genortal\AjaxHandler;
use GenerationPortal\Genortal\Explorer\Navigator;
use GenerationPortal\Genortal\Storage\DatabaseLayer;
use GenerationPortal\Genortal\FileSystem\FileSystem;
header("Expires: Sat, 01 Jan 2005 00:00:00 GMT");
header("Last-Modified: ".gmdate( "D, d M Y H:i:s")."GMT");
header("Cache-Control: no-cache, no-store");
header("Pragma: no-cache");
$requestIn = new RequestIn();
$ajaxHandler = new AjaxHandler();
if(!Session::loggedIn()) {
$ajaxHandler->error('not_signed_in',AjaxErrors::desc('not_signed_in'));
}
if(!$requestIn->paramSet('path')) {
$ajaxHandler->error('missing_parameters',AjaxErrors::desc('missing_parameters'));
}
$navigator = new Navigator();
try {
$databaseLayer = new DatabaseLayer();
$fileSystem = new FileSystem(Session::uid(),$requestIn->param('path'),$databaseLayer);
} catch (\Exception $e) {
$ajaxHandler->error('server_error',AjaxErrors::desc('server_error'));
}
$ajaxHandler->respond($navigator->parseDirectoryListing($fileSystem));
Can anyone have a quick help on what's going on here? Does HTTP caching work?
The problem was not with the code, the browser, or the HTTP caching. The problem was with my operating system. The connection did not disconnect even after I disconnected it. I decided to restart my desktop.
Apologies for wasting a little time! Thank.
For this purpose, you should try to use a cache overflow. I mean pass an extra parameter and variable with your url something like this
www.mydomain.com/navigate.php; //url without cache bust parameter
myRand=parseInt(Math.random()*99999999);
www.mydomain.com/navigate.php?rand=54321 //url with cache bust parameter
So in this cache your server will interpret it as a new request.