Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add reusedSocket property on client request #82

Merged
merged 1 commit into from Oct 12, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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