Reading the ssh2 HTTPAgent Source Code
Reading the ssh2 HTTPAgent Source Code
Apr 19, 2023
·
2 min read
·
252
Words
·
-Views
-Comments
The
ssh2package ships HTTP agents that intercept requests and forward them through an SSH connection. I recently needed a custom agent, so I dug through the implementation.
The agent lives in lib/http-agents.js:
const { Agent: HttpAgent } = require('http');
const { Agent: HttpsAgent } = require('https');
for (const ctor of [HttpAgent, HttpsAgent]) {
// ...
exports[ctor === HttpAgent ? 'SSHTTPAgent' : 'SSHTTPSAgent'] = SSHAgent;
}
A loop adapts Node’s built-in Agent constructors and exports derived classes.
Node’s Agent signature:
new Agent([options])
ssh2’s agent accepts two arguments because it also needs SSH configuration:
constructor(connectCfg, agentOptions) {
super(agentOptions);
this._connectCfg = connectCfg;
this._defaultSrcIP = (agentOptions && agentOptions.srcIP) || 'localhost';
}
connectCfgholds SSH connection parameters.agentOptionsis passed to Node’sAgent. ssh2 addssrcIP, controlling the source IP for the TCP socket.
createConnection(options, cb) is invoked by the pooling mechanism to obtain a TCP socket. The agent:
- Creates an SSH
Clientand connects usingconnectCfg. - On
ready, callsforwardOutto open a TCP stream. - Calls
cb(null, decorateStream(stream, ctor, options));so the stream exposes the methods expected by HTTP(S) consumers.
Error-handling highlights:
- If the TCP communication errors, the error is passed to
cband the SSH client closes. - If the TCP connection closes, the SSH client closes; no error is passed to
cbbecause the closure is expected.
When creating the local endpoint, a port must be bound. If localPort isn’t supplied, it defaults to 0, letting the OS choose an ephemeral port (not literally port 0):
const srcPort = (options && options.localPort) || 0;

