@crawlee/http 4.0.0-beta.80 → 4.0.0-beta.81
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/internals/http-crawler.d.ts +15 -50
- package/internals/http-crawler.js +13 -13
- package/package.json +7 -7
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import type { BasicCrawlerOptions, CrawlingContext, ErrorHandler, GetUserDataFromRequest, Request as CrawleeRequest, RequestHandler, RequireContextPipeline, RouterHandler, RouterRoutes, RouteSchemas, RoutesFromSchemas } from '@crawlee/basic';
|
|
2
2
|
import { BasicCrawler, ContextPipeline } from '@crawlee/basic';
|
|
3
3
|
import { type LoadedRequest } from '@crawlee/core';
|
|
4
|
-
import type { Awaitable, Dictionary
|
|
4
|
+
import type { Awaitable, Dictionary } from '@crawlee/types';
|
|
5
5
|
import { type CheerioRoot } from '@crawlee/utils';
|
|
6
|
-
import type { RequestLike, ResponseLike } from 'content-type';
|
|
7
6
|
import type { JsonValue } from 'type-fest';
|
|
8
7
|
export type HttpErrorHandler<UserData extends Dictionary = any, // with default to Dictionary we cant use a typed router in untyped crawler
|
|
9
8
|
JSONData extends JsonValue = any, // with default to Dictionary we cant use a typed router in untyped crawler
|
|
@@ -228,14 +227,14 @@ JSONData extends JsonValue = any> = RequestHandler<HttpCrawlingContext<UserData,
|
|
|
228
227
|
* @category Crawlers
|
|
229
228
|
*/
|
|
230
229
|
export declare class HttpCrawler<Context extends InternalHttpCrawlingContext<any, any> = InternalHttpCrawlingContext, ContextExtension = Dictionary<never>, ExtendedContext extends Context = Context & ContextExtension> extends BasicCrawler<Context, ContextExtension, ExtendedContext> {
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
230
|
+
private preNavigationHooks;
|
|
231
|
+
private postNavigationHooks;
|
|
232
|
+
private saveResponseCookies;
|
|
233
|
+
private navigationTimeoutMillis;
|
|
234
|
+
private ignoreSslErrors;
|
|
235
|
+
private suggestResponseEncoding?;
|
|
236
|
+
private forceResponseEncoding?;
|
|
237
|
+
private readonly supportedMimeTypes;
|
|
239
238
|
protected static optionsShape: {
|
|
240
239
|
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
241
240
|
navigationTimeoutSecs: import("ow").NumberPredicate & import("ow").BasePredicate<number | undefined>;
|
|
@@ -337,64 +336,30 @@ export declare class HttpCrawler<Context extends InternalHttpCrawlingContext<any
|
|
|
337
336
|
* on the request such as only downloading the request body if the
|
|
338
337
|
* received content type matches text/html, application/xml, application/xhtml+xml.
|
|
339
338
|
*/
|
|
340
|
-
|
|
339
|
+
private requestFunction;
|
|
341
340
|
/**
|
|
342
341
|
* Encodes and parses response according to the provided content type
|
|
343
342
|
*/
|
|
344
|
-
|
|
345
|
-
response: Response;
|
|
346
|
-
contentType: {
|
|
347
|
-
type: string;
|
|
348
|
-
encoding: BufferEncoding;
|
|
349
|
-
};
|
|
350
|
-
body: string;
|
|
351
|
-
} | {
|
|
352
|
-
body: Buffer<ArrayBuffer>;
|
|
353
|
-
response: Response;
|
|
354
|
-
contentType: {
|
|
355
|
-
type: string;
|
|
356
|
-
encoding: BufferEncoding;
|
|
357
|
-
};
|
|
358
|
-
}>;
|
|
343
|
+
private parseResponse;
|
|
359
344
|
/**
|
|
360
345
|
* Combines the provided `requestOptions` with mandatory (non-overridable) values.
|
|
361
346
|
*/
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
365
|
-
method: import("@crawlee/types").AllowedHttpMethods;
|
|
366
|
-
proxyUrl: string | undefined;
|
|
367
|
-
timeout: number;
|
|
368
|
-
sessionToken: ISession;
|
|
369
|
-
headers: Record<string, string> | undefined;
|
|
370
|
-
https: {
|
|
371
|
-
rejectUnauthorized: boolean;
|
|
372
|
-
};
|
|
373
|
-
body: string | undefined;
|
|
374
|
-
};
|
|
375
|
-
protected _encodeResponse(request: CrawleeRequest, response: Response, encoding: BufferEncoding): {
|
|
376
|
-
encoding: BufferEncoding;
|
|
377
|
-
response: Response;
|
|
378
|
-
};
|
|
347
|
+
private getRequestOptions;
|
|
348
|
+
private encodeResponse;
|
|
379
349
|
/**
|
|
380
350
|
* Checks and extends supported mime types
|
|
381
351
|
*/
|
|
382
|
-
|
|
352
|
+
private extendSupportedMimeTypes;
|
|
383
353
|
/**
|
|
384
354
|
* Handles timeout request
|
|
385
355
|
*/
|
|
386
|
-
|
|
356
|
+
private handleRequestTimeout;
|
|
387
357
|
private _abortDownloadOfBody;
|
|
388
358
|
/**
|
|
389
359
|
* @internal wraps public utility for mocking purposes
|
|
390
360
|
*/
|
|
391
361
|
private _requestAsBrowser;
|
|
392
362
|
}
|
|
393
|
-
interface RequestFunctionOptions {
|
|
394
|
-
request: CrawleeRequest;
|
|
395
|
-
session: ISession;
|
|
396
|
-
proxyUrl?: string;
|
|
397
|
-
}
|
|
398
363
|
/**
|
|
399
364
|
* Creates new {@link Router} instance that works based on request labels.
|
|
400
365
|
* This instance can then serve as a `requestHandler` of your {@link HttpCrawler}.
|
|
@@ -129,7 +129,7 @@ export class HttpCrawler extends BasicCrawler {
|
|
|
129
129
|
});
|
|
130
130
|
this.supportedMimeTypes = new Set([...HTML_AND_XML_MIME_TYPES, APPLICATION_JSON_MIME_TYPE]);
|
|
131
131
|
if (additionalMimeTypes.length)
|
|
132
|
-
this.
|
|
132
|
+
this.extendSupportedMimeTypes(additionalMimeTypes);
|
|
133
133
|
if (suggestResponseEncoding && forceResponseEncoding) {
|
|
134
134
|
this.log.warning('Both forceResponseEncoding and suggestResponseEncoding options are set. Using forceResponseEncoding.');
|
|
135
135
|
}
|
|
@@ -188,7 +188,7 @@ export class HttpCrawler extends BasicCrawler {
|
|
|
188
188
|
tryCancel();
|
|
189
189
|
const { request, session } = crawlingContext;
|
|
190
190
|
const proxyUrl = crawlingContext.proxyInfo?.url;
|
|
191
|
-
const httpResponse = await addTimeoutToPromise(async () => this.
|
|
191
|
+
const httpResponse = await addTimeoutToPromise(async () => this.requestFunction({ request, session, proxyUrl }), this.navigationTimeoutMillis, `request timed out after ${this.navigationTimeoutMillis / 1000} seconds.`);
|
|
192
192
|
tryCancel();
|
|
193
193
|
request.loadedUrl = httpResponse?.url;
|
|
194
194
|
request.state = RequestState.AFTER_NAV;
|
|
@@ -215,7 +215,7 @@ export class HttpCrawler extends BasicCrawler {
|
|
|
215
215
|
};
|
|
216
216
|
}
|
|
217
217
|
tryCancel();
|
|
218
|
-
const parsed = await this.
|
|
218
|
+
const parsed = await this.parseResponse(crawlingContext.request, crawlingContext.response);
|
|
219
219
|
tryCancel();
|
|
220
220
|
const response = parsed.response;
|
|
221
221
|
const contentType = parsed.contentType;
|
|
@@ -291,15 +291,15 @@ export class HttpCrawler extends BasicCrawler {
|
|
|
291
291
|
* on the request such as only downloading the request body if the
|
|
292
292
|
* received content type matches text/html, application/xml, application/xhtml+xml.
|
|
293
293
|
*/
|
|
294
|
-
async
|
|
295
|
-
const opts = this.
|
|
294
|
+
async requestFunction({ request, session, proxyUrl }) {
|
|
295
|
+
const opts = this.getRequestOptions(request, session, proxyUrl);
|
|
296
296
|
try {
|
|
297
297
|
return await this._requestAsBrowser(opts, session);
|
|
298
298
|
}
|
|
299
299
|
catch (e) {
|
|
300
300
|
if (e instanceof Error && e.constructor.name === 'TimeoutError') {
|
|
301
|
-
this.
|
|
302
|
-
return new Response(); // this will never happen, as
|
|
301
|
+
this.handleRequestTimeout(session);
|
|
302
|
+
return new Response(); // this will never happen, as handleRequestTimeout always throws
|
|
303
303
|
}
|
|
304
304
|
if (this.isProxyError(e)) {
|
|
305
305
|
throw new SessionError(this._getMessageFromError(e));
|
|
@@ -312,10 +312,10 @@ export class HttpCrawler extends BasicCrawler {
|
|
|
312
312
|
/**
|
|
313
313
|
* Encodes and parses response according to the provided content type
|
|
314
314
|
*/
|
|
315
|
-
async
|
|
315
|
+
async parseResponse(request, response) {
|
|
316
316
|
const { status } = response;
|
|
317
317
|
const { type, charset } = parseContentTypeFromResponse(response);
|
|
318
|
-
const { response: reencodedResponse, encoding } = this.
|
|
318
|
+
const { response: reencodedResponse, encoding } = this.encodeResponse(request, response, charset);
|
|
319
319
|
const contentType = { type, encoding };
|
|
320
320
|
if (status >= 400 && status <= 599) {
|
|
321
321
|
this.stats.registerStatusCode(status);
|
|
@@ -361,7 +361,7 @@ export class HttpCrawler extends BasicCrawler {
|
|
|
361
361
|
/**
|
|
362
362
|
* Combines the provided `requestOptions` with mandatory (non-overridable) values.
|
|
363
363
|
*/
|
|
364
|
-
|
|
364
|
+
getRequestOptions(request, session, proxyUrl) {
|
|
365
365
|
const requestOptions = {
|
|
366
366
|
url: request.url,
|
|
367
367
|
method: request.method,
|
|
@@ -389,7 +389,7 @@ export class HttpCrawler extends BasicCrawler {
|
|
|
389
389
|
requestOptions.body = request.payload ?? '';
|
|
390
390
|
return requestOptions;
|
|
391
391
|
}
|
|
392
|
-
|
|
392
|
+
encodeResponse(request, response, encoding) {
|
|
393
393
|
if (this.forceResponseEncoding) {
|
|
394
394
|
encoding = this.forceResponseEncoding;
|
|
395
395
|
}
|
|
@@ -425,7 +425,7 @@ export class HttpCrawler extends BasicCrawler {
|
|
|
425
425
|
/**
|
|
426
426
|
* Checks and extends supported mime types
|
|
427
427
|
*/
|
|
428
|
-
|
|
428
|
+
extendSupportedMimeTypes(additionalMimeTypes) {
|
|
429
429
|
for (const mimeType of additionalMimeTypes) {
|
|
430
430
|
if (mimeType === '*/*') {
|
|
431
431
|
this.supportedMimeTypes.add(mimeType);
|
|
@@ -443,7 +443,7 @@ export class HttpCrawler extends BasicCrawler {
|
|
|
443
443
|
/**
|
|
444
444
|
* Handles timeout request
|
|
445
445
|
*/
|
|
446
|
-
|
|
446
|
+
handleRequestTimeout(session) {
|
|
447
447
|
session.markBad();
|
|
448
448
|
throw new Error(`request timed out after ${this.navigationTimeoutMillis / 1000} seconds.`);
|
|
449
449
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crawlee/http",
|
|
3
|
-
"version": "4.0.0-beta.
|
|
3
|
+
"version": "4.0.0-beta.81",
|
|
4
4
|
"description": "The scalable web crawling and scraping library for JavaScript/Node.js. Enables development of data extraction and web automation jobs (not only) with headless Chrome and Puppeteer.",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=22.0.0"
|
|
@@ -49,11 +49,11 @@
|
|
|
49
49
|
"dependencies": {
|
|
50
50
|
"@apify/timeout": "^0.3.2",
|
|
51
51
|
"@apify/utilities": "^2.15.5",
|
|
52
|
-
"@crawlee/basic": "4.0.0-beta.
|
|
53
|
-
"@crawlee/core": "4.0.0-beta.
|
|
54
|
-
"@crawlee/http-client": "4.0.0-beta.
|
|
55
|
-
"@crawlee/types": "4.0.0-beta.
|
|
56
|
-
"@crawlee/utils": "4.0.0-beta.
|
|
52
|
+
"@crawlee/basic": "4.0.0-beta.81",
|
|
53
|
+
"@crawlee/core": "4.0.0-beta.81",
|
|
54
|
+
"@crawlee/http-client": "4.0.0-beta.81",
|
|
55
|
+
"@crawlee/types": "4.0.0-beta.81",
|
|
56
|
+
"@crawlee/utils": "4.0.0-beta.81",
|
|
57
57
|
"@types/content-type": "^1.1.8",
|
|
58
58
|
"cheerio": "^1.0.0",
|
|
59
59
|
"content-type": "^1.0.5",
|
|
@@ -70,5 +70,5 @@
|
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
72
|
},
|
|
73
|
-
"gitHead": "
|
|
73
|
+
"gitHead": "80dc6b4fc82237e63a51a71153809ec8dfd0cc50"
|
|
74
74
|
}
|