Skip to content

Commit 132b5dc

Browse files
authored
fix: prefer proxy password from env var (#385)
- Fetch proxy password from `/user/me` using `APIFY_ENV_VARS.TOKEN` only when `APIFY_ENV_VARS.PROXY_PASSWORD` is not provided - Proxy init no longer logs when there is a difference between the proxy password from the environmental variable and the one obtained from the API, since only one is going to be taken into consideration. When running on Apify, the passwords will always be different. - should solve the second part of: https://console.apify.com/actors/RB9HEZitC8hIUXAha/issues/exVPDR4pOsgqlkE5T Closes [#20502](apify/apify-core#20502)
1 parent 0f5b126 commit 132b5dc

File tree

2 files changed

+37
-60
lines changed

2 files changed

+37
-60
lines changed

packages/apify/src/proxy_configuration.ts

Lines changed: 32 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import type {
44
} from '@crawlee/core';
55
import { ProxyConfiguration as CoreProxyConfiguration } from '@crawlee/core';
66
import { gotScraping } from '@crawlee/utils';
7-
import type { UserProxy } from 'apify-client';
87
import ow from 'ow';
98

109
import { APIFY_ENV_VARS, APIFY_PROXY_VALUE_REGEX } from '@apify/consts';
@@ -260,7 +259,27 @@ export class ProxyConfiguration extends CoreProxyConfiguration {
260259
*/
261260
async initialize(): Promise<boolean> {
262261
if (this.usesApifyProxy) {
263-
await this._setPasswordIfToken();
262+
if (!this.password) {
263+
await this._setPasswordIfToken();
264+
}
265+
266+
if (!this.password) {
267+
if (Actor.isAtHome()) {
268+
throw new Error(
269+
`Apify Proxy password must be provided using options.password or the "${APIFY_ENV_VARS.PROXY_PASSWORD}" environment variable. ` +
270+
`You can also provide your Apify token via the "${APIFY_ENV_VARS.TOKEN}" environment variable, ` +
271+
`so that the SDK can fetch the proxy password from Apify API, when ${APIFY_ENV_VARS.PROXY_PASSWORD} is not defined`,
272+
);
273+
} else {
274+
this.log.warning(
275+
`No proxy password or token detected, running without proxy. To use Apify Proxy locally, ` +
276+
`provide options.password or "${APIFY_ENV_VARS.PROXY_PASSWORD}" environment variable. ` +
277+
`You can also provide your Apify token via the "${APIFY_ENV_VARS.TOKEN}" environment variable, ` +
278+
`so that the SDK can fetch the proxy password from Apify API, when ${APIFY_ENV_VARS.PROXY_PASSWORD} is not defined`,
279+
);
280+
}
281+
}
282+
264283
return this._checkAccess();
265284
}
266285

@@ -415,55 +434,23 @@ export class ProxyConfiguration extends CoreProxyConfiguration {
415434
}
416435

417436
/**
418-
* Checks if Apify Token is provided in env and gets the password via API and sets it to env
437+
* Fetch & set the proxy password from Apify API if an Apify token is provided.
419438
*/
439+
// TODO: Make this private
420440
protected async _setPasswordIfToken(): Promise<void> {
421441
const token = this.config.get('token');
422442

423-
if (token) {
424-
let proxy: UserProxy;
425-
426-
try {
427-
const user = await Actor.apifyClient.user().get();
428-
proxy = user.proxy!;
429-
} catch (error) {
430-
if (Actor.isAtHome()) {
431-
throw error;
432-
} else {
433-
this.log.warning(
434-
`Failed to fetch user data based on token, disabling proxy.`,
435-
{ error },
436-
);
437-
return;
438-
}
439-
}
440-
441-
const { password } = proxy!;
442-
443-
if (this.password) {
444-
if (this.password !== password) {
445-
this.log.warning(
446-
'The Apify Proxy password you provided belongs to' +
447-
' a different user than the Apify token you are using. Are you sure this is correct?',
448-
);
449-
}
450-
} else {
451-
this.password = password;
452-
}
453-
}
454-
455-
if (!this.password) {
443+
if (!token) return;
444+
try {
445+
const user = await Actor.apifyClient.user().get();
446+
this.password = user.proxy?.password;
447+
} catch (error) {
456448
if (Actor.isAtHome()) {
457-
throw new Error(
458-
`Apify Proxy password must be provided using options.password or the "${APIFY_ENV_VARS.PROXY_PASSWORD}" environment variable. ` +
459-
`If you add the "${APIFY_ENV_VARS.TOKEN}" environment variable, the password will be automatically inferred.`,
460-
);
449+
throw error;
461450
} else {
462-
this.log.warning(
463-
`No proxy password or token detected, running without proxy. To use Apify Proxy locally, ` +
464-
`provide options.password or "${APIFY_ENV_VARS.PROXY_PASSWORD}" environment variable. ` +
465-
`If you add the "${APIFY_ENV_VARS.TOKEN}" environment variable, the password will be automatically inferred.`,
466-
);
451+
this.log.warning(`Failed to fetch user data using token`, {
452+
error,
453+
});
467454
}
468455
}
469456
}

test/apify/proxy_configuration.test.ts

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -619,26 +619,16 @@ describe('Actor.createProxyConfiguration()', () => {
619619
getUserSpy.mockRestore();
620620
});
621621

622-
test('should show warning log', async () => {
623-
process.env.APIFY_TOKEN = '123456789';
622+
test(`shouldn't request password from API when both PROXY_PASSWORD and TOKEN envs are provided`, async () => {
623+
process.env[APIFY_ENV_VARS.TOKEN] = 'some_token';
624+
process.env[APIFY_ENV_VARS.PROXY_PASSWORD] = 'proxy_password';
624625

625626
const getUserSpy = vitest.spyOn(UserClient.prototype, 'get');
626-
const status = { connected: true };
627-
const fakeUserData = {
628-
proxy: { password: 'some-other-users-password' },
629-
};
630-
getUserSpy.mockResolvedValueOnce(fakeUserData as any);
631-
gotScrapingSpy.mockResolvedValueOnce({ body: status } as any);
632-
633-
const proxyConfiguration = new ProxyConfiguration(basicOpts);
634-
// @ts-expect-error
635-
const logMock = vitest.spyOn(proxyConfiguration.log, 'warning');
627+
const proxyConfiguration = new ProxyConfiguration();
636628
await proxyConfiguration.initialize();
637-
expect(logMock).toBeCalledTimes(1);
629+
expect(getUserSpy).toBeCalledTimes(0);
638630

639-
logMock.mockRestore();
640631
getUserSpy.mockRestore();
641-
gotScrapingSpy.mockRestore();
642632
});
643633

644634
// TODO: test that on platform we throw but locally we only print warning

0 commit comments

Comments
 (0)