diff --git a/packages/apify/src/actor.ts b/packages/apify/src/actor.ts index 870a5977eb..fe8dc4e4e1 100644 --- a/packages/apify/src/actor.ts +++ b/packages/apify/src/actor.ts @@ -1374,6 +1374,10 @@ export class Actor { * ``` * { useApifyProxy: false } * ``` + * + * As part of the init process, we verify the configuration by checking the proxy status endpoint. + * This can make the init slower, to opt-out of this, use `checkAccess: false` (defaults to `true`). + * * @ignore */ async createProxyConfiguration( @@ -1383,7 +1387,8 @@ export class Actor { ): Promise { // Compatibility fix for Input UI where proxy: None returns { useApifyProxy: false } // Without this, it would cause proxy to use the zero config / auto mode. - const { useApifyProxy, ...options } = proxyConfigurationOptions; + const { useApifyProxy, checkAccess, ...options } = + proxyConfigurationOptions; const dontUseApifyProxy = useApifyProxy === false; const dontUseCustomProxies = !proxyConfigurationOptions.proxyUrls; @@ -1393,7 +1398,7 @@ export class Actor { const proxyConfiguration = new ProxyConfiguration(options, this.config); - if (await proxyConfiguration.initialize()) { + if (await proxyConfiguration.initialize({ checkAccess })) { return proxyConfiguration; } @@ -2183,6 +2188,9 @@ export class Actor { * ``` * { useApifyProxy: false } * ``` + * + * As part of the init process, we verify the configuration by checking the proxy status endpoint. + * This can make the init slower, to opt-out of this, use `checkAccess: false` (defaults to `true`). */ static async createProxyConfiguration( proxyConfigurationOptions: ProxyConfigurationOptions & { diff --git a/packages/apify/src/proxy_configuration.ts b/packages/apify/src/proxy_configuration.ts index bb55c963aa..16a0545a99 100644 --- a/packages/apify/src/proxy_configuration.ts +++ b/packages/apify/src/proxy_configuration.ts @@ -65,6 +65,12 @@ export interface ProxyConfigurationOptions ProxyConfigurationOptions, keyof CoreProxyConfigurationOptions | 'tieredProxyConfig' >[]; + + /** + * As part of the init process, we verify the configuration by checking the proxy status endpoint. + * This can make the init slower, to opt-out of this, use `checkAccess: false` (defaults to `true`). + */ + checkAccess?: boolean; } /** @@ -256,8 +262,11 @@ export class ProxyConfiguration extends CoreProxyConfiguration { * * You should use the {@apilink createProxyConfiguration} function to create a pre-initialized * `ProxyConfiguration` instance instead of calling this manually. + * + * As part of the init process, we verify the configuration by checking the proxy status endpoint. + * This can make the init slower, to opt-out of this, use `checkAccess: false`. */ - async initialize(): Promise { + async initialize(options?: { checkAccess?: boolean }): Promise { if (this.usesApifyProxy) { if (!this.password) { await this._setPasswordIfToken(); @@ -280,7 +289,9 @@ export class ProxyConfiguration extends CoreProxyConfiguration { } } - return this._checkAccess(); + if (options?.checkAccess !== false) { + return this._checkAccess(); + } } return true; diff --git a/test/apify/proxy_configuration.test.ts b/test/apify/proxy_configuration.test.ts index 917e4d45bb..3418699ed1 100644 --- a/test/apify/proxy_configuration.test.ts +++ b/test/apify/proxy_configuration.test.ts @@ -567,6 +567,11 @@ describe('Actor.createProxyConfiguration()', () => { const proxyUrl = proxyUrlNoSession; const url = 'http://proxy.apify.com/?format=json'; gotScrapingSpy.mockResolvedValueOnce({ body: status } as any); + const checkAccessSpy = vitest.spyOn( + ProxyConfiguration.prototype, + // @ts-ignore protected method + '_checkAccess', + ); const proxyConfiguration = await Actor.createProxyConfiguration(basicOpts); @@ -582,6 +587,7 @@ describe('Actor.createProxyConfiguration()', () => { expect(proxyConfiguration.hostname).toBe(hostname); // @ts-expect-error private property expect(proxyConfiguration.port).toBe(port); + expect(checkAccessSpy).toHaveBeenCalled(); expect(gotScrapingSpy).toBeCalledWith({ url, @@ -591,6 +597,37 @@ describe('Actor.createProxyConfiguration()', () => { }); }); + test('disabling `checkAccess`', async () => { + const status = { connected: true }; + const proxyUrl = proxyUrlNoSession; + const url = 'http://proxy.apify.com/?format=json'; + gotScrapingSpy.mockResolvedValueOnce({ body: status } as any); + const checkAccessSpy = vitest.spyOn( + ProxyConfiguration.prototype, + // @ts-ignore protected method + '_checkAccess', + ); + + const proxyConfiguration = await Actor.createProxyConfiguration({ + ...basicOpts, + checkAccess: false, + }); + + expect(proxyConfiguration).toBeInstanceOf(ProxyConfiguration); + // @ts-expect-error private property + expect(proxyConfiguration.groups).toBe(groups); + // @ts-expect-error private property + expect(proxyConfiguration.countryCode).toBe(countryCode); + // @ts-expect-error private property + expect(proxyConfiguration.password).toBe(password); + // @ts-expect-error private property + expect(proxyConfiguration.hostname).toBe(hostname); + // @ts-expect-error private property + expect(proxyConfiguration.port).toBe(port); + expect(checkAccessSpy).not.toHaveBeenCalled(); + expect(gotScrapingSpy).not.toHaveBeenCalled(); + }); + test('should work without password (with token)', async () => { process.env.APIFY_TOKEN = '123456789'; const opts: Dictionary = { ...basicOpts };