Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions 4 package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion 2 package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "apify-client",
"version": "2.9.7",
"version": "2.9.8",
"description": "Apify API client for JavaScript",
"main": "dist/index.js",
"module": "dist/index.mjs",
Expand Down
3 changes: 3 additions & 0 deletions 3 src/apify_client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export class ApifyClient {
requestInterceptors: ow.optional.array,
timeoutSecs: ow.optional.number,
token: ow.optional.string,
userAgentSuffix: ow.optional.any(ow.string, ow.array.ofType(ow.string)),
}));

const {
Expand All @@ -77,6 +78,7 @@ export class ApifyClient {
timeoutSecs,
logger: this.logger,
token: this.token,
userAgentSuffix: options.userAgentSuffix,
});
}

Expand Down Expand Up @@ -341,4 +343,5 @@ export interface ApifyClientOptions {
/** @default 360 */
timeoutSecs?: number;
token?: string;
userAgentSuffix?: string | string[];
}
20 changes: 11 additions & 9 deletions 20 src/http_client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ import KeepAliveAgent from 'agentkeepalive';
import retry, { RetryFunction } from 'async-retry';
import axios, {
AxiosError,
AxiosHeaders,
AxiosInstance,
AxiosRequestConfig,
InternalAxiosRequestConfig,
AxiosResponse,
AxiosHeaders,
InternalAxiosRequestConfig,
} from 'axios';

import { ApifyApiError } from './apify_api_error';
Expand All @@ -21,12 +21,7 @@ import {
responseInterceptors,
} from './interceptors';
import { Statistics } from './statistics';
import {
isNode,
getVersionData,
cast,
isStream,
} from './utils';
import { asArray, cast, getVersionData, isNode, isStream } from './utils';

const { version } = getVersionData();

Expand Down Expand Up @@ -116,7 +111,12 @@ export class HttpClient {
if (isNode()) {
// Works only in Node. Cannot be set in browser
const isAtHome = !!process.env[APIFY_ENV_VARS.IS_AT_HOME];
const userAgent = `ApifyClient/${version} (${os.type()}; Node/${process.version}); isAtHome/${isAtHome}`;
let userAgent = `ApifyClient/${version} (${os.type()}; Node/${process.version}); isAtHome/${isAtHome}`;

if (options.userAgentSuffix) {
userAgent += `; ${asArray(options.userAgentSuffix).join('; ')}`;
}

this.axios.defaults.headers['User-Agent'] = userAgent;
}

Expand Down Expand Up @@ -288,4 +288,6 @@ export interface HttpClientOptions {
logger: Log;
token?: string;
workflowKey?: string;
/** @internal */
userAgentSuffix?: string | string[];
}
8 changes: 8 additions & 0 deletions 8 src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,14 @@ export function cast<T>(input: unknown): T {
return input as T;
}

export function asArray<T>(value: T | T[]): T[] {
if (Array.isArray(value)) {
return value;
}

return [value];
}

export type Dictionary<T = unknown> = Record<PropertyKey, T>;

export type DistributiveOptional<T, K extends keyof T> = T extends any ? Omit<T, K> & Partial<Pick<T, K>> : never;
26 changes: 8 additions & 18 deletions 26 test/http_client.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,7 @@ describe('HttpClient', () => {
baseUrl,
timeoutSecs: 1,
maxRetries: 0,
requestInterceptors: [(config) => {
config.headers = {};
return config;
}],
userAgentSuffix: ['SDK/3.1.1', 'Crawlee/3.11.5'],
});
});
afterEach(async () => {
Expand All @@ -41,20 +38,13 @@ describe('HttpClient', () => {
const context = { delayMillis: 3000 };
const resourceId = Buffer.from(JSON.stringify(context)).toString('hex');

expect.assertions(2);
try {
await client.actor(resourceId).get();
} catch (err) {
expect(err.message).toMatch('timeout of 1000ms exceeded');
}
await expect(client.actor(resourceId).get()).rejects.toThrow('timeout of 1000ms exceeded');
const ua = mockServer.getLastRequest().headers['user-agent'];
expect(ua).toMatch(/ApifyClient\/\d+\.\d+\.\d+/);
expect(ua).toMatch('isAtHome/false; SDK/3.1.1; Crawlee/3.11.5');

try {
const r = await page.evaluate((rId) => client.task(rId).get(), resourceId);
expect(r).toBeDefined();
} catch (err) {
expect(err).toBeInstanceOf(Error);
// this is failing after axios upgrade, the error is returned with a wrong name and message
// expect(err.message).toMatch('timeout of 1000ms exceeded');
}
await expect(page.evaluate((rId) => client.task(rId).get(), resourceId)).rejects.toThrow();
// this is failing after axios upgrade, the error is returned with a wrong name and message
// expect(err.message).toMatch('timeout of 1000ms exceeded');
});
});
Morty Proxy This is a proxified and sanitized view of the page, visit original site.