Lazy import proxy-agent

This commit is contained in:
Fedor Indutny 2024-03-20 11:05:10 -07:00 committed by GitHub
parent 83e8f4b59d
commit 091b50c414
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 60 additions and 39 deletions

View file

@ -338,7 +338,7 @@ describe('updater/differential', () => {
await assert.isRejected(
download(outFile, data, {
gotOptions: {
...getGotOptions(),
...(await getGotOptions()),
timeout: {
connect: 0.5 * durations.SECOND,
lookup: 0.5 * durations.SECOND,

View file

@ -19,6 +19,7 @@ import * as durations from '../util/durations';
import { sleep } from '../util/sleep';
import { drop } from '../util/drop';
import { createProxyAgent } from '../util/createProxyAgent';
import type { ProxyAgent } from '../util/createProxyAgent';
import { SocketStatus } from '../types/SocketStatus';
import * as Errors from '../types/errors';
import * as Bytes from '../Bytes';
@ -84,7 +85,7 @@ export class SocketManager extends EventListener {
private credentials?: WebAPICredentials;
private readonly proxyAgent?: ReturnType<typeof createProxyAgent>;
private proxyAgent?: ProxyAgent;
private status = SocketStatus.CLOSED;
@ -105,10 +106,6 @@ export class SocketManager extends EventListener {
constructor(private readonly options: SocketManagerOptions) {
super();
if (options.proxyUrl) {
this.proxyAgent = createProxyAgent(options.proxyUrl);
}
this.hasStoriesDisabled = options.hasStoriesDisabled;
}
@ -338,6 +335,11 @@ export class SocketManager extends EventListener {
url: string;
extraHeaders?: Record<string, string>;
}): Promise<WebSocket> {
// Create proxy agent lazily
if (this.options.proxyUrl && !this.proxyAgent) {
this.proxyAgent = await createProxyAgent(this.options.proxyUrl);
}
return connectWebSocket({
name: 'art-creator-provisioning',
url,

View file

@ -31,6 +31,7 @@ import { toWebSafeBase64, fromWebSafeBase64 } from '../util/webSafeBase64';
import { getBasicAuth } from '../util/getBasicAuth';
import { createHTTPSAgent } from '../util/createHTTPSAgent';
import { createProxyAgent } from '../util/createProxyAgent';
import type { ProxyAgent } from '../util/createProxyAgent';
import type { SocketStatus } from '../types/SocketStatus';
import { VerificationTransport } from '../types/VerificationTransport';
import { toLogFormat } from '../types/errors';
@ -120,7 +121,7 @@ const GET_ATTACHMENT_CHUNK_TIMEOUT = 10 * durations.SECOND;
type AgentCacheType = {
[name: string]: {
timestamp: number;
agent: ReturnType<typeof createProxyAgent> | Agent;
agent: ProxyAgent | Agent;
};
};
const agents: AgentCacheType = {};
@ -259,7 +260,7 @@ async function _promiseAjax(
}
agents[cacheKey] = {
agent: proxyUrl
? createProxyAgent(proxyUrl)
? await createProxyAgent(proxyUrl)
: createHTTPSAgent({
keepAlive: !options.disableSessionResumption,
maxCachedSessions: options.disableSessionResumption ? 0 : undefined,
@ -1382,17 +1383,23 @@ export function initialize({
log.warn(`${logId}: Done`);
}
let fetchAgent: Agent;
if (proxyUrl) {
fetchAgent = createProxyAgent(proxyUrl);
} else {
fetchAgent = createHTTPSAgent({
keepAlive: false,
maxCachedSessions: 0,
});
}
const fetchForLinkPreviews: linkPreviewFetch.FetchFn = (href, init) =>
fetch(href, { ...init, agent: fetchAgent });
let fetchAgent: Agent | undefined;
const fetchForLinkPreviews: linkPreviewFetch.FetchFn = async (
href,
init
) => {
if (!fetchAgent) {
if (proxyUrl) {
fetchAgent = await createProxyAgent(proxyUrl);
} else {
fetchAgent = createHTTPSAgent({
keepAlive: false,
maxCachedSessions: 0,
});
}
}
return fetch(href, { ...init, agent: fetchAgent });
};
// Thanks, function hoisting!
return {

View file

@ -9,7 +9,7 @@ import { strictAssert } from '../util/assert';
import { explodePromise } from '../util/explodePromise';
import { getUserAgent } from '../util/getUserAgent';
import * as durations from '../util/durations';
import type { createProxyAgent } from '../util/createProxyAgent';
import type { ProxyAgent } from '../util/createProxyAgent';
import { createHTTPSAgent } from '../util/createHTTPSAgent';
import * as log from '../logging/log';
import * as Timers from '../Timers';
@ -28,7 +28,7 @@ export type ConnectOptionsType<Resource extends IResource> = Readonly<{
url: string;
certificateAuthority?: string;
version: string;
proxyAgent?: ReturnType<typeof createProxyAgent>;
proxyAgent?: ProxyAgent;
timeout?: number;
extraHeaders?: Record<string, string>;

View file

@ -10,6 +10,7 @@ import type { LoggerType } from '../../types/Logging';
import { isOlderThan } from '../../util/timestamp';
import { HOUR } from '../../util/durations';
import { createProxyAgent } from '../../util/createProxyAgent';
import type { ProxyAgent } from '../../util/createProxyAgent';
// It is 24 hours, but we don't want latency between server and client to be
// count.
@ -30,15 +31,11 @@ export abstract class CDSBase<
Options extends CDSBaseOptionsType = CDSBaseOptionsType
> {
protected readonly logger: LoggerType;
protected readonly proxyAgent?: ReturnType<typeof createProxyAgent>;
protected proxyAgent?: ProxyAgent;
protected cachedAuth?: CachedAuthType;
constructor(protected readonly options: Options) {
this.logger = options.logger;
if (options.proxyUrl) {
this.proxyAgent = createProxyAgent(options.proxyUrl);
}
}
public abstract request(
@ -46,6 +43,11 @@ export abstract class CDSBase<
): Promise<CDSResponseType>;
protected async getAuth(): Promise<CDSAuthType> {
// Lazily create proxy agent
if (!this.proxyAgent && this.options.proxyUrl) {
this.proxyAgent = await createProxyAgent(this.options.proxyUrl);
}
if (this.cachedAuth) {
if (isOlderThan(this.cachedAuth.timestamp, CACHED_AUTH_TTL)) {
this.cachedAuth = undefined;

View file

@ -602,7 +602,7 @@ export abstract class Updater {
this.logger.info(`downloadUpdate: Downloading signature ${signatureUrl}`);
const signature = Buffer.from(
await got(signatureUrl, getGotOptions()).text(),
await got(signatureUrl, await getGotOptions()).text(),
'hex'
);
@ -614,7 +614,10 @@ export abstract class Updater {
this.logger.info(
`downloadUpdate: Downloading blockmap ${blockMapUrl}`
);
const blockMap = await got(blockMapUrl, getGotOptions()).buffer();
const blockMap = await got(
blockMapUrl,
await getGotOptions()
).buffer();
await writeFile(tempBlockMapPath, blockMap);
} catch (error) {
this.logger.warn(
@ -751,7 +754,7 @@ export abstract class Updater {
targetUpdatePath: string,
updateOnProgress = false
): Promise<void> {
const downloadStream = got.stream(updateFileUrl, getGotOptions());
const downloadStream = got.stream(updateFileUrl, await getGotOptions());
const writeStream = createWriteStream(targetUpdatePath);
await new Promise<void>((resolve, reject) => {
@ -930,7 +933,7 @@ export function parseYaml(yaml: string): JSONUpdateSchema {
async function getUpdateYaml(): Promise<string> {
const targetUrl = getUpdateCheckUrl();
const body = await got(targetUrl, getGotOptions()).text();
const body = await got(targetUrl, await getGotOptions()).text();
if (!body) {
throw new Error('Got unexpected response back from update check');

View file

@ -15,6 +15,7 @@ import { strictAssert } from '../util/assert';
import { wrapEventEmitterOnce } from '../util/wrapEventEmitterOnce';
import type { LoggerType } from '../types/Logging';
import { getGotOptions } from './got';
import type { GotOptions } from './got';
import { checkIntegrity } from './util';
const gunzip = promisify(nativeGunzip);
@ -74,7 +75,7 @@ export type DownloadOptionsType = Readonly<{
logger?: LoggerType;
// Testing
gotOptions?: ReturnType<typeof getGotOptions>;
gotOptions?: GotOptions;
}>;
export type DownloadRangesOptionsType = Readonly<{
@ -86,7 +87,7 @@ export type DownloadRangesOptionsType = Readonly<{
chunkStatusCallback: (chunkSize: number) => void;
// Testing
gotOptions?: ReturnType<typeof getGotOptions>;
gotOptions?: GotOptions;
}>;
export function getBlockMapFileName(fileName: string): string {
@ -212,7 +213,7 @@ export async function prepareDownload({
const newBlockMapData = await got(
getBlockMapFileName(newUrl),
getGotOptions()
await getGotOptions()
).buffer();
const newBlockMap = await parseBlockMap(newBlockMapData);
@ -343,7 +344,7 @@ export async function downloadRanges(
logger,
abortSignal,
chunkStatusCallback,
gotOptions = getGotOptions(),
gotOptions = await getGotOptions(),
} = options;
logger?.info('updater/downloadRanges: downloading ranges', ranges.length);

View file

@ -24,13 +24,15 @@ export function getCertificateAuthority(): string {
return config.get('certificateAuthority');
}
export function getGotOptions(): GotOptions {
export type { GotOptions };
export async function getGotOptions(): Promise<GotOptions> {
const certificateAuthority = getCertificateAuthority();
const proxyUrl = getProxyUrl();
const agent = proxyUrl
? {
http: createProxyAgent(proxyUrl),
https: createProxyAgent(proxyUrl),
http: await createProxyAgent(proxyUrl),
https: await createProxyAgent(proxyUrl),
}
: {
http: new HTTPAgent(),

View file

@ -1,8 +1,8 @@
// Copyright 2023 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { ProxyAgent } from 'proxy-agent';
import net from 'net';
import type { ProxyAgent } from 'proxy-agent';
import { URL } from 'url';
import type { LookupOptions, LookupAddress } from 'dns';
import { lookup } from 'dns/promises';
@ -25,7 +25,9 @@ const SOCKS_PROTOCOLS = new Set([
'socks5h:',
]);
export function createProxyAgent(proxyUrl: string): ProxyAgent {
export type { ProxyAgent };
export async function createProxyAgent(proxyUrl: string): Promise<ProxyAgent> {
const { port: portStr, hostname: proxyHost, protocol } = new URL(proxyUrl);
let defaultPort: number | undefined;
if (protocol === 'http:') {
@ -96,6 +98,8 @@ export function createProxyAgent(proxyUrl: string): ProxyAgent {
}
}
const { ProxyAgent } = await import('proxy-agent');
return new ProxyAgent({
lookup:
port !== undefined