Ok, with a bit of experimenting - I've found a way to do it.
What it looks like - is that if an http request is cancelled/timed out by the client while the server is writing/flushing the output then the error will be thrown. (NB. It appears as if the size of the response also matters - see my note at the end).
There are three things that can happen:
Condition 1: Server writes and flushes output before client timeouts.
Response is sent back to client.
Condition 2: Client times out before server writes and flushes output.
Client does not receive response, no server error.
Condition 3: Client times out while server is writing output.
Client does not receive response. Server throws ClientAbortException
(java.io.IOException
).
To simulate these three conditions, we play with three variables:
- The time client takes to timeout
- Time server burns getting its result.
- The size of the server response.
Here is the test code to simulate it:
Server side (This is a Spring MVC controller).
@RequestMapping(value = { "/debugGet" }, method = RequestMethod.GET)
@ResponseBody
public List<String> debugGet(@RequestParam int timeout, int numObjects) throws InterruptedException {
Thread.sleep(timeout);
List<String> l = new ArrayList<String>();
for (int i =0; i< numObjects; i++){
l.add(new String());
}
return l;
}
Client side (Angular)
this.debugGet = function(server, client, numObjects){
var httpProm = $http({
method: "GET",
url: "debugGet",
timeout: client,
params : {
timeout: server,
numObjects: numObjects}
});
httpProm.then(function(data){
console.log(data);
}, function(data){
console.log("error");
console.log(data);
});
};
Using this I can simulate the three conditions with the following params:
Client Timeout Server Burn Time Num Strings
Condition 1: 1000 900 10000
Condition 2: 1000 2000 100
Condition 3: 1000 950 10000
NB It appears as if the size of response also matters.
For example:
Client Timeout Server Burn Time Num Strings
Condition 2: 1000 2000 100
Condition 3: 1000 2000 10000
Here for the 10000 Strings, we get the java.io.IOException
even though the flush occurs well after the client has timed out, whereas it doesn't for the 100 Strings.