Skip to content

Commit fd6209c

Browse files
authored
[https-proxy-agent] Emit "proxyConnect" event on HTTP req (#154)
Part of #153. I'd like to also emit this event on the `agent` instance itself, but this is currently blocked by DefinitelyTyped/DefinitelyTyped#65408.
1 parent 0471aef commit fd6209c

File tree

4 files changed

+53
-15
lines changed

4 files changed

+53
-15
lines changed

.changeset/blue-buses-build.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'https-proxy-agent': minor
3+
---
4+
5+
Emit "proxyConnect" event on HTTP `request` object (part of #153)

packages/https-proxy-agent/src/index.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import assert from 'assert';
55
import createDebug from 'debug';
66
import { OutgoingHttpHeaders } from 'http';
77
import { Agent, AgentConnectOpts } from 'agent-base';
8-
import parseProxyResponse from './parse-proxy-response';
8+
import { parseProxyResponse } from './parse-proxy-response';
99

1010
const debug = createDebug('https-proxy-agent');
1111

@@ -130,9 +130,10 @@ export class HttpsProxyAgent<Uri extends string> extends Agent {
130130

131131
socket.write(`${payload}\r\n`);
132132

133-
const { statusCode, buffered } = await proxyResponsePromise;
133+
const { connect, buffered } = await proxyResponsePromise;
134+
req.emit('proxyConnect', connect);
134135

135-
if (statusCode === 200) {
136+
if (connect.statusCode === 200) {
136137
req.once('socket', resume);
137138

138139
if (opts.secureEndpoint) {

packages/https-proxy-agent/src/parse-proxy-response.ts

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
import createDebug from 'debug';
2+
import { IncomingHttpHeaders } from 'http';
23
import { Readable } from 'stream';
34

45
const debug = createDebug('https-proxy-agent:parse-proxy-response');
56

6-
export interface ProxyResponse {
7+
export interface ConnectResponse {
78
statusCode: number;
8-
buffered: Buffer;
9+
statusText: string;
10+
headers: IncomingHttpHeaders;
911
}
1012

11-
export default function parseProxyResponse(
13+
export function parseProxyResponse(
1214
socket: Readable
13-
): Promise<ProxyResponse> {
15+
): Promise<{ connect: ConnectResponse; buffered: Buffer }> {
1416
return new Promise((resolve, reject) => {
1517
// we need to buffer any HTTP traffic that happens with the proxy before we get
1618
// the CONNECT response, so that if the response is anything other than an "200"
@@ -60,16 +62,40 @@ export default function parseProxyResponse(
6062
return;
6163
}
6264

63-
const firstLine = buffered.toString(
64-
'ascii',
65-
0,
66-
buffered.indexOf('\r\n')
67-
);
68-
const statusCode = +firstLine.split(' ')[1];
65+
const headerParts = buffered.toString('ascii').split('\r\n');
66+
const firstLine = headerParts.shift();
67+
if (!firstLine) {
68+
throw new Error('No header received');
69+
}
70+
const firstLineParts = firstLine.split(' ');
71+
const statusCode = +firstLineParts[1];
72+
const statusText = firstLineParts.slice(2).join(' ');
73+
const headers: IncomingHttpHeaders = {};
74+
for (const header of headerParts) {
75+
if (!header) continue;
76+
const firstColon = header.indexOf(':');
77+
if (firstColon === -1) {
78+
throw new Error(`Invalid header: "${header}"`);
79+
}
80+
const key = header.slice(0, firstColon).toLowerCase();
81+
const value = header.slice(firstColon + 1).trimStart();
82+
const current = headers[key];
83+
if (typeof current === 'string') {
84+
headers[key] = [current, value];
85+
} else if (Array.isArray(current)) {
86+
current.push(value);
87+
} else {
88+
headers[key] = value;
89+
}
90+
}
6991
debug('got proxy server response: %o', firstLine);
7092
cleanup();
7193
resolve({
72-
statusCode,
94+
connect: {
95+
statusCode,
96+
statusText,
97+
headers,
98+
},
7399
buffered,
74100
});
75101
}

packages/https-proxy-agent/test/test.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,13 @@ describe('HttpsProxyAgent', () => {
106106

107107
const agent = new HttpsProxyAgent(proxyUrl);
108108

109-
const res = await req(serverUrl, { agent });
109+
const r = req(serverUrl, { agent });
110+
const [connect] = await once(r, 'proxyConnect');
111+
expect(connect.statusCode).toEqual(200);
112+
expect(connect.statusText).toEqual('Connection established');
113+
expect('date' in connect.headers).toBe(true);
114+
115+
const res = await r;
110116
const body = await json(res);
111117
assert.equal(serverUrl.host, body.host);
112118
});

0 commit comments

Comments
 (0)