Skip to content

Commit

Permalink
[https-proxy-agent] Emit "proxyConnect" event on HTTP req (#154)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
TooTallNate committed May 5, 2023
1 parent 0471aef commit fd6209c
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 15 deletions.
5 changes: 5 additions & 0 deletions .changeset/blue-buses-build.md
@@ -0,0 +1,5 @@
---
'https-proxy-agent': minor
---

Emit "proxyConnect" event on HTTP `request` object (part of #153)
7 changes: 4 additions & 3 deletions packages/https-proxy-agent/src/index.ts
Expand Up @@ -5,7 +5,7 @@ import assert from 'assert';
import createDebug from 'debug';
import { OutgoingHttpHeaders } from 'http';
import { Agent, AgentConnectOpts } from 'agent-base';
import parseProxyResponse from './parse-proxy-response';
import { parseProxyResponse } from './parse-proxy-response';

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

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

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

const { statusCode, buffered } = await proxyResponsePromise;
const { connect, buffered } = await proxyResponsePromise;
req.emit('proxyConnect', connect);

if (statusCode === 200) {
if (connect.statusCode === 200) {
req.once('socket', resume);

if (opts.secureEndpoint) {
Expand Down
48 changes: 37 additions & 11 deletions packages/https-proxy-agent/src/parse-proxy-response.ts
@@ -1,16 +1,18 @@
import createDebug from 'debug';
import { IncomingHttpHeaders } from 'http';
import { Readable } from 'stream';

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

export interface ProxyResponse {
export interface ConnectResponse {
statusCode: number;
buffered: Buffer;
statusText: string;
headers: IncomingHttpHeaders;
}

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

const firstLine = buffered.toString(
'ascii',
0,
buffered.indexOf('\r\n')
);
const statusCode = +firstLine.split(' ')[1];
const headerParts = buffered.toString('ascii').split('\r\n');
const firstLine = headerParts.shift();
if (!firstLine) {
throw new Error('No header received');
}
const firstLineParts = firstLine.split(' ');
const statusCode = +firstLineParts[1];
const statusText = firstLineParts.slice(2).join(' ');
const headers: IncomingHttpHeaders = {};
for (const header of headerParts) {
if (!header) continue;
const firstColon = header.indexOf(':');
if (firstColon === -1) {
throw new Error(`Invalid header: "${header}"`);
}
const key = header.slice(0, firstColon).toLowerCase();
const value = header.slice(firstColon + 1).trimStart();
const current = headers[key];
if (typeof current === 'string') {
headers[key] = [current, value];
} else if (Array.isArray(current)) {
current.push(value);
} else {
headers[key] = value;
}
}
debug('got proxy server response: %o', firstLine);
cleanup();
resolve({
statusCode,
connect: {
statusCode,
statusText,
headers,
},
buffered,
});
}
Expand Down
8 changes: 7 additions & 1 deletion packages/https-proxy-agent/test/test.ts
Expand Up @@ -106,7 +106,13 @@ describe('HttpsProxyAgent', () => {

const agent = new HttpsProxyAgent(proxyUrl);

const res = await req(serverUrl, { agent });
const r = req(serverUrl, { agent });
const [connect] = await once(r, 'proxyConnect');
expect(connect.statusCode).toEqual(200);
expect(connect.statusText).toEqual('Connection established');
expect('date' in connect.headers).toBe(true);

const res = await r;
const body = await json(res);
assert.equal(serverUrl.host, body.host);
});
Expand Down

1 comment on commit fd6209c

@vercel
Copy link

@vercel vercel bot commented on fd6209c May 5, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

proxy-agents – ./

proxy-agents-tootallnate.vercel.app
proxy-agents-git-main-tootallnate.vercel.app
proxy-agents.vercel.app

Please sign in to comment.