Skip to content

Commit

Permalink
feat: Add reusedSocket property on client request (#82)
Browse files Browse the repository at this point in the history
  • Loading branch information
starkwang authored and fengmk2 committed Oct 12, 2019
1 parent 77ba744 commit fe33b80
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 0 deletions.
24 changes: 24 additions & 0 deletions README.md
Expand Up @@ -165,6 +165,30 @@ setTimeout(() => {
}, 2000);
```

### Support `req.reusedSocket`

This agent implements the `req.reusedSocket` to determine whether a request is send through a reused socket.

When server closes connection at unfortunate time ([keep-alive race](https://code-examples.net/en/q/28a8069)), the http client will throw a `ECONNRESET` error. Under this circumstance, `req.reusedSocket` is useful when we want to retry the request automatically.

```js
const http = require('http');
const Agent = require('agentkeepalive');
const agent = new Agent();

const req = http
.get('http://localhost:3000', { agent }, (res) => {
// ...
})
.on('error', (err) => {
if (req.reusedSocket && err.code === 'ECONNRESET') {
// retry the request or anything else...
}
})
```

This behavior is consistent with Node.js core. But through `agentkeepalive`, you can use this feature in older Node.js version.

## [Benchmark](https://github.com/node-modules/agentkeepalive/tree/master/benchmark)

run the benchmark:
Expand Down
2 changes: 2 additions & 0 deletions lib/agent.js
Expand Up @@ -140,6 +140,8 @@ class Agent extends OriginalAgent {
// reuseSocket(socket, req)
super.reuseSocket(...args);
const socket = args[0];
const req = args[1];
req.reusedSocket = true;
const agentTimeout = this.options.timeout;
if (getSocketTimeout(socket) !== agentTimeout) {
// reset timeout before use
Expand Down
37 changes: 37 additions & 0 deletions test/agent.test.js
Expand Up @@ -1495,6 +1495,43 @@ describe('test/agent.test.js', () => {
assert(Object.keys(agentkeepalive.sockets).length === 1);
});

it('should set req.reusedSocket to true when reuse socket', done => {
const agent = new Agent({
keepAlive: true,
});

// First request
const req1 = http.get({
port,
path: '/',
agent,
}, res => {
assert(res.statusCode === 200);
res.on('data', () => {});
res.on('end', () => {
setTimeout(() => {
// Second request
const req2 = http.get({
port,
path: '/',
agent,
}, res => {
assert(res.statusCode === 200);
res.on('data', () => {});
res.on('end', () => {
done();
});
});
// Second request reuses the socket
assert(req2.reusedSocket);
}, 10);
});
});

// First request doesn't reuse the socket
assert(!req1.reusedSocket);
});

describe('request timeout > agent timeout', () => {
it('should use request timeout', done => {
const agent = new Agent({
Expand Down

0 comments on commit fe33b80

Please sign in to comment.