Let's assume you have a server in koa and you have a POST route which takes ~ 3 minutes to return a request.
According to the various sources, you set-up your server with the timeout by setting up
let app = new Koa();
let server=app.listen(3000);
server.timeout=5*60*1000; // set to 5 minutes
On the client side, you set-up a timeout as well and you send the post request with the timeout
const request = await axios.post('https://somewebsite.herokuapp.com/testkeepalive', {}, {timeout:240000})
console.log('request is ', request)
Why when sending the above, on the server it still returns a timeout error and doesn't execute as intended?
Info about /testkeepalive
.post('/testkeepalive', async ctx => {
console.log('request received')
ctx.request.socket.setTimeout(5 * 60 * 1000)
ctx.request.socket.setKeepAlive(true)
await delay(3 * 60 * 1000) // we delay 3 mintues before returning the request
ctx.body = "nice"
ctx.status = 202
})
EDIT: Code above is correct. The only issue was that I was using Heroku which times out to 30seconds. Moving the server elsewhere (e.g AWS EC2 + deploy server with https ssl certificate) made it work.
If you still want to use heroku, you can only do it by implementing background jobs. https://devcenter.heroku.com/articles/background-jobs-queueing
Axios is showing you ERR_NETWORK
so I think that means that some intermediary (perhaps a proxy in your hosting environment) has closed the socket.
Below is a test app I wrote that lets me separately set the serverTimeout
, the clientTimeout
and the serverDelay
before sending a response. This allows you to simulate either client or server timeout and see exactly what the axios response is. This is generic Express since I'm not a koa person, but presumably, it is the same http server object in either case.
With these values configured such that the serverDelay
is less than both serverTimeout
and clientTimeout
:
const serverTimeout = 10 * 1000;
const clientTimeout = 8 * 1000;
const serverDelay = 7 * 1000;
Then, I get the appropriate response from the server (no error).
With these values configured such that the serverTimeout
is shorter than the serverDelay
:
const serverTimeout = 5 * 1000;
const clientTimeout = 8 * 1000;
const serverDelay = 7 * 1000;
Then, I get Error socket hang up ECONNRESET
.
With these values configured such that the clientTimeout
is shorter than the serverDelay
or serverTimeout
:
const serverTimeout = 10 * 1000;
const clientTimeout = 5 * 1000;
const serverDelay = 7 * 1000;
Then, I get Error timeout of 5000ms exceeded ECONNABORTED
.
So, it all seems to be working for me with no extra infrastructure in between the client and server. So, that plus the ERR_NETWORK
error you see from Axios makes me think that a proxy in your hosting infrastructure is responsible for the error.
Here's the code I used:
import express from 'express';
import axios from 'axios';
const serverTimeout = 10 * 1000;
const clientTimeout = 8 * 1000;
const serverDelay = 7 * 1000;
function delay(t) {
return new Promise(resolve => {
setTimeout(resolve, t);
})
}
const app = express();
app.get("/timeout", async (req, res) => {
await delay(serverDelay);
res.send("Hello");
});
const server = app.listen(80);
server.timeout = serverTimeout;
try {
let result = await axios.get("http://localhost/timeout", { timeout: clientTimeout });
console.log("Got Result", result.data);
} catch (e) {
console.log("Error", e.message, e.code);
}
server.close();
Note also that there is no need to set a timeout separately on each incoming socket. The server timeout itself will handle that for you.