| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -116,6 +116,10 @@ http.get({ | |||
| 116 | 116 | <!-- YAML | |
| 117 | 117 | added: v0.3.4 | |
| 118 | 118 | changes: | |
| 119 | + - version: | ||
| 120 | + - REPLACEME | ||
| 121 | + pr-url: https://github.com/nodejs/node/pull/59315 | ||
| 122 | + description: Add support for `agentKeepAliveTimeoutBuffer`. | ||
| 119 | 123 | - version: | |
| 120 | 124 | - v15.6.0 | |
| 121 | 125 | - v14.17.0 | |
@@ -148,6 +152,12 @@ changes: | |||
| 148 | 152 | the [initial delay][] | |
| 149 | 153 | for TCP Keep-Alive packets. Ignored when the | |
| 150 | 154 | `keepAlive` option is `false` or `undefined`. **Default:** `1000`. | |
| 155 | + * `agentKeepAliveTimeoutBuffer` {number} Milliseconds to subtract from | ||
| 156 | + the server-provided `keep-alive: timeout=...` hint when determining socket | ||
| 157 | + expiration time. This buffer helps ensure the agent closes the socket | ||
| 158 | + slightly before the server does, reducing the chance of sending a request | ||
| 159 | + on a socket that’s about to be closed by the server. | ||
| 160 | + **Default:** `1000`. | ||
| 151 | 161 | * `maxSockets` {number} Maximum number of sockets to allow per host. | |
| 152 | 162 | If the same host opens multiple concurrent connections, each request | |
| 153 | 163 | will use new socket until the `maxSockets` value is reached. | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -22,6 +22,7 @@ | |||
| 22 | 22 | 'use strict'; | |
| 23 | 23 | ||
| 24 | 24 | const { | |
| 25 | + NumberIsFinite, | ||
| 25 | 26 | NumberParseInt, | |
| 26 | 27 | ObjectKeys, | |
| 27 | 28 | ObjectSetPrototypeOf, | |
@@ -50,8 +51,6 @@ const kOnKeylog = Symbol('onkeylog'); | |||
| 50 | 51 | const kRequestOptions = Symbol('requestOptions'); | |
| 51 | 52 | const kRequestAsyncResource = Symbol('requestAsyncResource'); | |
| 52 | 53 | ||
| 53 | - // TODO(jazelly): make this configurable | ||
| 54 | - const HTTP_AGENT_KEEP_ALIVE_TIMEOUT_BUFFER = 1000; | ||
| 55 | 54 | // New Agent code. | |
| 56 | 55 | ||
| 57 | 56 | // The largest departure from the previous implementation is that | |
@@ -105,6 +104,13 @@ function Agent(options) { | |||
| 105 | 104 | this.maxTotalSockets = this.options.maxTotalSockets; | |
| 106 | 105 | this.totalSocketCount = 0; | |
| 107 | 106 | ||
| 107 | + this.agentKeepAliveTimeoutBuffer = | ||
| 108 | + typeof this.options.agentKeepAliveTimeoutBuffer === 'number' && | ||
| 109 | + this.options.agentKeepAliveTimeoutBuffer >= 0 && | ||
| 110 | + NumberIsFinite(this.options.agentKeepAliveTimeoutBuffer) ? | ||
| 111 | + this.options.agentKeepAliveTimeoutBuffer : | ||
| 112 | + 1000; | ||
| 113 | + | ||
| 108 | 114 | validateOneOf(this.scheduling, 'scheduling', ['fifo', 'lifo']); | |
| 109 | 115 | ||
| 110 | 116 | if (this.maxTotalSockets !== undefined) { | |
@@ -481,7 +487,7 @@ Agent.prototype.keepSocketAlive = function keepSocketAlive(socket) { | |||
| 481 | 487 | if (hint) { | |
| 482 | 488 | // Let the timer expire before the announced timeout to reduce | |
| 483 | 489 | // the likelihood of ECONNRESET errors | |
| 484 | - let serverHintTimeout = (NumberParseInt(hint) * 1000) - HTTP_AGENT_KEEP_ALIVE_TIMEOUT_BUFFER; | ||
| 490 | + let serverHintTimeout = (NumberParseInt(hint) * 1000) - this.agentKeepAliveTimeoutBuffer; | ||
| 485 | 491 | serverHintTimeout = serverHintTimeout > 0 ? serverHintTimeout : 0; | |
| 486 | 492 | if (serverHintTimeout === 0) { | |
| 487 | 493 | // Cannot safely reuse the socket because the server timeout is | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,44 @@ | |||
| 1 | + 'use strict'; | ||
| 2 | + | ||
| 3 | + const common = require('../common'); | ||
| 4 | + const assert = require('assert'); | ||
| 5 | + const http = require('http'); | ||
| 6 | + | ||
| 7 | + // Ensure agentKeepAliveTimeoutBuffer option sets the correct value or falls back to default. | ||
| 8 | + { | ||
| 9 | + const agent1 = new http.Agent({ agentKeepAliveTimeoutBuffer: 1500, keepAlive: true }); | ||
| 10 | + assert.strictEqual(agent1.agentKeepAliveTimeoutBuffer, 1500); | ||
| 11 | + | ||
| 12 | + const agent2 = new http.Agent({ agentKeepAliveTimeoutBuffer: -100, keepAlive: true }); | ||
| 13 | + assert.strictEqual(agent2.agentKeepAliveTimeoutBuffer, 1000); | ||
| 14 | + | ||
| 15 | + const agent3 = new http.Agent({ agentKeepAliveTimeoutBuffer: Infinity, keepAlive: true }); | ||
| 16 | + assert.strictEqual(agent3.agentKeepAliveTimeoutBuffer, 1000); | ||
| 17 | + | ||
| 18 | + const agent4 = new http.Agent({ keepAlive: true }); | ||
| 19 | + assert.strictEqual(agent4.agentKeepAliveTimeoutBuffer, 1000); | ||
| 20 | + } | ||
| 21 | + | ||
| 22 | + // Integration test with server sending Keep-Alive timeout header. | ||
| 23 | + { | ||
| 24 | + const SERVER_TIMEOUT = 3; | ||
| 25 | + const BUFFER = 1500; | ||
| 26 | + | ||
| 27 | + const server = http.createServer((req, res) => { | ||
| 28 | + res.setHeader('Keep-Alive', `timeout=${SERVER_TIMEOUT}`); | ||
| 29 | + res.end('ok'); | ||
| 30 | + }); | ||
| 31 | + | ||
| 32 | + server.listen(0, common.mustCall(() => { | ||
| 33 | + const agent = new http.Agent({ agentKeepAliveTimeoutBuffer: BUFFER, keepAlive: true }); | ||
| 34 | + assert.strictEqual(agent.agentKeepAliveTimeoutBuffer, BUFFER); | ||
| 35 | + | ||
| 36 | + http.get({ port: server.address().port, agent }, (res) => { | ||
| 37 | + res.resume(); | ||
| 38 | + res.on('end', () => { | ||
| 39 | + agent.destroy(); | ||
| 40 | + server.close(); | ||
| 41 | + }); | ||
| 42 | + }); | ||
| 43 | + })); | ||
| 44 | + } | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments