HTTP Agent that keeps socket connections alive between keep-alive requests
npx @tessl/cli install tessl/npm-forever-agent@0.6.0Forever Agent is an HTTP Agent implementation that maintains persistent socket connections between keep-alive requests. It extends Node.js's built-in HTTP Agent with intelligent socket pooling that maintains a configurable minimum number of idle sockets per host/port combination, optimizing network performance by reusing existing connections rather than creating new ones for each request.
npm install forever-agentconst ForeverAgent = require('forever-agent');ES6 imports:
import ForeverAgent from 'forever-agent';const ForeverAgent = require('forever-agent');
const http = require('http');
// Create HTTP agent with persistent connections
const agent = new ForeverAgent({
maxSockets: 10, // Maximum sockets per host
minSockets: 5 // Minimum idle sockets to maintain
});
// Create HTTPS agent for SSL connections
const httpsAgent = new ForeverAgent.SSL({
maxSockets: 10,
minSockets: 3
});
// Use with http.request
const options = {
hostname: 'example.com',
port: 80,
path: '/api/data',
method: 'GET',
agent: agent // Use the forever agent
};
const req = http.request(options, (res) => {
console.log(`Status: ${res.statusCode}`);
res.on('data', (chunk) => {
console.log(chunk.toString());
});
});
req.end();Forever Agent extends Node.js's built-in HTTP Agent with the following key components:
Creates a new Forever Agent instance for HTTP connections.
/**
* Creates a Forever Agent for HTTP connections with persistent socket pooling
* @param {Object} options - Configuration options
* @param {number} options.maxSockets - Maximum sockets per host (default: Agent.defaultMaxSockets)
* @param {number} options.minSockets - Minimum idle sockets per host (default: ForeverAgent.defaultMinSockets = 5)
* @returns {ForeverAgent} New agent instance
*/
function ForeverAgent(options);
// Static property
ForeverAgent.defaultMinSockets = 5;Creates a new Forever Agent instance for HTTPS connections.
/**
* Creates a Forever Agent for HTTPS connections with persistent socket pooling
* @param {Object} options - Configuration options (same as ForeverAgent plus TLS options)
* @returns {ForeverAgentSSL} New SSL agent instance
*/
function ForeverAgentSSL(options);
// Access via main export
ForeverAgent.SSL = ForeverAgentSSL;Adds HTTP requests to the agent with intelligent socket reuse.
/**
* Adds a request to the agent, reusing idle sockets when possible
* @param {http.ClientRequest} req - HTTP request object
* @param {string|Object} host - Hostname string or options object with host/port
* @param {number} port - Port number (if host is string)
*/
ForeverAgent.prototype.addRequest = function(req, host, port);
/**
* Adds a request without socket reuse (fallback to standard Agent behavior)
* @param {http.ClientRequest} req - HTTP request object
* @param {string|Object} host - Hostname string or options object
* @param {number} port - Port number (if host is string)
*/
ForeverAgent.prototype.addRequestNoreuse = function(req, host, port);Manages socket lifecycle and pool maintenance.
/**
* Removes a socket from the agent pools and handles cleanup
* @param {net.Socket} socket - Socket to remove
* @param {string} name - Connection name
* @param {string} host - Hostname
* @param {number} port - Port number
*/
ForeverAgent.prototype.removeSocket = function(socket, name, host, port);
/**
* Creates a new connection (HTTP)
* @param {number|Object} port - Port number or options object
* @param {string|Object} host - Hostname or options object
* @param {Object} options - Connection options
* @returns {net.Socket} New socket connection
*/
ForeverAgent.prototype.createConnection = function(port, host, options);
/**
* Creates a new SSL/TLS connection (HTTPS)
* @param {number|Object} port - Port number or options object
* @param {string|Object} host - Hostname or options object
* @param {Object} options - TLS connection options
* @returns {tls.TLSSocket} New TLS socket connection
*/
ForeverAgentSSL.prototype.createConnection = function(port, host, options);Agent configuration and internal state management.
// Configuration properties
agent.options; // Object - Configuration options passed to constructor
agent.maxSockets; // number - Maximum sockets per host
agent.minSockets; // number - Minimum idle sockets per host
// Internal state (read-only access)
agent.requests; // Object - Pending requests by connection name
agent.sockets; // Object - Active sockets by connection name
agent.freeSockets; // Object - Available idle sockets by connection name/**
* Configuration options for ForeverAgent
*/
interface AgentOptions {
maxSockets?: number; // Maximum sockets per host (inherited from http.Agent)
minSockets?: number; // Minimum idle sockets per host (Forever Agent specific)
}
/**
* Connection name format: "host:port" or "host:port:localAddress:"
*/
type ConnectionName = string;
/**
* Socket pools organized by connection name
*/
interface SocketPools {
[connectionName: string]: net.Socket[];
}
/**
* Request queues organized by connection name
*/
interface RequestQueues {
[connectionName: string]: http.ClientRequest[];
}Forever Agent includes automatic error handling for idle sockets:
// Example with error handling
const agent = new ForeverAgent({ minSockets: 3 });
agent.on('free', (socket, host, port) => {
// Internal event - handled automatically by Forever Agent
// Manages socket reuse and idle pool maintenance
});
// Idle sockets automatically handle errors
// No manual error handling required for idle socket managementconst ForeverAgent = require('forever-agent');
const http = require('http');
const agent = new ForeverAgent({
maxSockets: 5,
minSockets: 2
});
function makeRequest(path) {
return new Promise((resolve, reject) => {
const req = http.request({
hostname: 'api.example.com',
port: 80,
path: path,
method: 'GET',
agent: agent
}, (res) => {
let data = '';
res.on('data', chunk => data += chunk);
res.on('end', () => resolve(data));
});
req.on('error', reject);
req.end();
});
}
// Multiple requests will reuse connections
Promise.all([
makeRequest('/users'),
makeRequest('/posts'),
makeRequest('/comments')
]).then(results => {
console.log('All requests completed with connection reuse');
});const ForeverAgent = require('forever-agent');
const https = require('https');
const httpsAgent = new ForeverAgent.SSL({
maxSockets: 10,
minSockets: 3
});
const options = {
hostname: 'secure-api.example.com',
port: 443,
path: '/secure-data',
method: 'GET',
agent: httpsAgent
};
https.request(options, (res) => {
console.log(`Secure request status: ${res.statusCode}`);
res.on('data', (chunk) => {
process.stdout.write(chunk);
});
}).end();const ForeverAgent = require('forever-agent');
const request = require('request'); // or any HTTP client library
const agent = new ForeverAgent({
maxSockets: 8,
minSockets: 4
});
// Configure request library to use Forever Agent
const requestWithAgent = request.defaults({
agent: agent
});
requestWithAgent('http://example.com/api', (error, response, body) => {
if (!error && response.statusCode === 200) {
console.log('Request completed with persistent connection');
}
});