@crawlee/http 4.0.0-beta.211 → 4.0.0-beta.213

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.
@@ -49,7 +49,6 @@ export type FileDownloadRequestHandler<UserData extends Dictionary = any> = Requ
49
49
  export declare class FileDownload extends BasicCrawler<FileDownloadCrawlingContext> {
50
50
  #private;
51
51
  constructor(options?: Omit<BasicCrawlerOptions<FileDownloadCrawlingContext>, 'contextPipelineBuilder'>);
52
- private initiateDownload;
53
52
  }
54
53
  /**
55
54
  * Creates new {@link Router} instance that works based on request labels.
@@ -44,9 +44,9 @@ export class FileDownload extends BasicCrawler {
44
44
  });
45
45
  }
46
46
  #buildContextPipeline() {
47
- return ContextPipeline.create().compose(this.initiateDownload.bind(this));
47
+ return ContextPipeline.create().compose(this.#initiateDownload.bind(this));
48
48
  }
49
- async initiateDownload(context, onCleanup) {
49
+ async #initiateDownload(context, onCleanup) {
50
50
  const response = await this.httpClient.sendRequest(context.request.intoFetchAPIRequest(), {
51
51
  session: context.session,
52
52
  });
@@ -381,38 +381,7 @@ export declare class HttpCrawler<Context extends InternalHttpCrawlingContext<any
381
381
  /** @internal */
382
382
  protected createDefaultConcurrencySystem(options: ConcurrencySystemOptions): ConcurrencySystem;
383
383
  protected buildContextPipeline(): ContextPipeline<CrawlingContext, InternalHttpCrawlingContext>;
384
- private prepareHttpRequest;
385
384
  private makeHttpRequest;
386
- private processHttpResponse;
387
- private handleBlockedRequestByContent;
388
- /**
389
- * Function to make the HTTP request. It performs optimizations
390
- * on the request such as only downloading the request body if the
391
- * received content type matches text/html, application/xml, application/xhtml+xml.
392
- */
393
- private requestFunction;
394
- /**
395
- * Encodes and parses response according to the provided content type
396
- */
397
- private parseResponse;
398
- /**
399
- * Combines the provided `requestOptions` with mandatory (non-overridable) values.
400
- */
401
- private getRequestOptions;
402
- private encodeResponse;
403
- /**
404
- * Checks and extends supported mime types
405
- */
406
- private extendSupportedMimeTypes;
407
- /**
408
- * Handles timeout request
409
- */
410
- private handleRequestTimeout;
411
- private abortDownloadOfBody;
412
- /**
413
- * @internal wraps public utility for mocking purposes
414
- */
415
- private requestAsBrowser;
416
385
  }
417
386
  /**
418
387
  * Creates new {@link Router} instance that works based on request labels.
@@ -147,7 +147,7 @@ export class HttpCrawler extends BasicCrawler {
147
147
  });
148
148
  this.#supportedMimeTypes = new Set([...HTML_AND_XML_MIME_TYPES, APPLICATION_JSON_MIME_TYPE]);
149
149
  if (additionalMimeTypes.length)
150
- this.extendSupportedMimeTypes(additionalMimeTypes);
150
+ this.#extendSupportedMimeTypes(additionalMimeTypes);
151
151
  if (suggestResponseEncoding && forceResponseEncoding) {
152
152
  this.log.warning('Both forceResponseEncoding and suggestResponseEncoding options are set. Using forceResponseEncoding.');
153
153
  }
@@ -160,7 +160,7 @@ export class HttpCrawler extends BasicCrawler {
160
160
  // members `extendContext` added at runtime.
161
161
  this.#preNavigationHooks = preNavigationHooks;
162
162
  this.#postNavigationHooks = [
163
- ({ request, response }) => this.abortDownloadOfBody(request, response),
163
+ ({ request, response }) => this.#abortDownloadOfBody(request, response),
164
164
  ...postNavigationHooks,
165
165
  ];
166
166
  this.#saveResponseCookies = saveResponseCookies;
@@ -191,7 +191,7 @@ export class HttpCrawler extends BasicCrawler {
191
191
  }
192
192
  return addTimeoutToPromise(async () => step(ctx), remaining, navigationTimedOut);
193
193
  });
194
- let pipeline = ContextPipeline.create().compose(this.prepareHttpRequest.bind(this));
194
+ let pipeline = ContextPipeline.create().compose(this.#prepareHttpRequest.bind(this));
195
195
  for (const hook of this.#preNavigationHooks) {
196
196
  pipeline = pipeline.compose(windowGuard(hook));
197
197
  }
@@ -200,20 +200,23 @@ export class HttpCrawler extends BasicCrawler {
200
200
  pipelineWithNavigation = pipelineWithNavigation.compose(windowGuard(hook));
201
201
  }
202
202
  return pipelineWithNavigation
203
- .compose(this.processHttpResponse.bind(this))
204
- .compose(this.handleBlockedRequestByContent.bind(this));
203
+ .compose(this.#processHttpResponse.bind(this))
204
+ .compose(this.#handleBlockedRequestByContent.bind(this));
205
205
  }
206
- async prepareHttpRequest(crawlingContext) {
206
+ async #prepareHttpRequest(crawlingContext) {
207
207
  const { request } = crawlingContext;
208
208
  if (request.skipNavigation) {
209
209
  return {
210
210
  request: new Proxy(request, {
211
- get(target, propertyName, receiver) {
211
+ get(target, propertyName) {
212
212
  if (propertyName === 'loadedUrl') {
213
213
  throw new NavigationSkippedError('The `request.loadedUrl` property is not available - `skipNavigation` was used');
214
214
  }
215
- return Reflect.get(target, propertyName, receiver);
215
+ // `target` as receiver and bound methods, or `#` members throw on the proxy
216
+ const value = Reflect.get(target, propertyName, target);
217
+ return typeof value === 'function' ? value.bind(target) : value;
216
218
  },
219
+ set: (target, propertyName, value) => Reflect.set(target, propertyName, value, target),
217
220
  }),
218
221
  get response() {
219
222
  throw new NavigationSkippedError('The `response` property is not available - `skipNavigation` was used');
@@ -231,13 +234,13 @@ export class HttpCrawler extends BasicCrawler {
231
234
  // Bound the request by whatever is left of the shared navigation window (the pre-navigation hooks may
232
235
  // have already spent part of it), so it produces a clean navigation-timeout error rather than the raw
233
236
  // client abort.
234
- const httpResponse = await addTimeoutToPromise(async () => this.requestFunction({ request, session, proxyUrl }), Math.max(1, remainingNavigationWindowMillis(crawlingContext, this.#navigationTimeoutMillis)), `Navigation timed out after ${this.#navigationTimeoutMillis / 1000} seconds.`);
237
+ const httpResponse = await addTimeoutToPromise(async () => this.#requestFunction({ request, session, proxyUrl }), Math.max(1, remainingNavigationWindowMillis(crawlingContext, this.#navigationTimeoutMillis)), `Navigation timed out after ${this.#navigationTimeoutMillis / 1000} seconds.`);
235
238
  tryCancel();
236
239
  request.loadedUrl = httpResponse?.url;
237
240
  request.state = RequestState.AFTER_NAV;
238
241
  return { request: request, response: httpResponse };
239
242
  }
240
- async processHttpResponse(crawlingContext) {
243
+ async #processHttpResponse(crawlingContext) {
241
244
  if (crawlingContext.request.skipNavigation) {
242
245
  return {
243
246
  get contentType() {
@@ -276,7 +279,7 @@ export class HttpCrawler extends BasicCrawler {
276
279
  if (remaining <= 0) {
277
280
  throw new TimeoutError(`Navigation timed out after ${this.#navigationTimeoutMillis / 1000} seconds.`);
278
281
  }
279
- const parsed = await addTimeoutToPromise(async () => this.parseResponse(crawlingContext.request, crawlingContext.response), remaining, `Navigation timed out after ${this.#navigationTimeoutMillis / 1000} seconds.`);
282
+ const parsed = await addTimeoutToPromise(async () => this.#parseResponse(crawlingContext.request, crawlingContext.response), remaining, `Navigation timed out after ${this.#navigationTimeoutMillis / 1000} seconds.`);
280
283
  tryCancel();
281
284
  const response = parsed.response;
282
285
  const contentType = parsed.contentType;
@@ -330,7 +333,7 @@ export class HttpCrawler extends BasicCrawler {
330
333
  body: parsed.body,
331
334
  };
332
335
  }
333
- async handleBlockedRequestByContent(crawlingContext) {
336
+ async #handleBlockedRequestByContent(crawlingContext) {
334
337
  if (this.retryOnBlocked) {
335
338
  const error = await this.#isRequestBlocked(crawlingContext);
336
339
  if (error)
@@ -356,14 +359,14 @@ export class HttpCrawler extends BasicCrawler {
356
359
  * on the request such as only downloading the request body if the
357
360
  * received content type matches text/html, application/xml, application/xhtml+xml.
358
361
  */
359
- async requestFunction({ request, session, proxyUrl }) {
360
- const opts = this.getRequestOptions(request, proxyUrl);
362
+ async #requestFunction({ request, session, proxyUrl }) {
363
+ const opts = this.#getRequestOptions(request, proxyUrl);
361
364
  try {
362
- return await this.requestAsBrowser(opts, session);
365
+ return await this.#requestAsBrowser(opts, session);
363
366
  }
364
367
  catch (e) {
365
368
  if (e instanceof Error && e.constructor.name === 'TimeoutError') {
366
- this.handleRequestTimeout(session);
369
+ this.#handleRequestTimeout(session);
367
370
  return new Response(); // this will never happen, as handleRequestTimeout always throws
368
371
  }
369
372
  if (this.isProxyError(e)) {
@@ -377,14 +380,14 @@ export class HttpCrawler extends BasicCrawler {
377
380
  /**
378
381
  * Encodes and parses response according to the provided content type
379
382
  */
380
- async parseResponse(request, response) {
383
+ async #parseResponse(request, response) {
381
384
  const { status } = response;
382
385
  const { type, charset } = parseContentTypeFromResponse(response);
383
386
  if (status >= 400 && status <= 599) {
384
387
  this.statistics.registerStatusCode(status);
385
388
  }
386
389
  if (this.isErrorStatusCode(status)) {
387
- const { response: decoded } = this.encodeResponse(request, response, charset);
390
+ const { response: decoded } = this.#encodeResponse(request, response, charset);
388
391
  const body = await decoded.text(); // TODO - this always uses UTF-8 (see https://developer.mozilla.org/en-US/docs/Web/API/Request/text)
389
392
  // Errors are often sent as JSON, so attempt to parse them,
390
393
  // despite Accept header being set to text/html.
@@ -412,7 +415,7 @@ export class HttpCrawler extends BasicCrawler {
412
415
  : rawBytes.toString('utf8');
413
416
  return { response, contentType: { type, encoding: 'utf-8' }, body };
414
417
  }
415
- const { response: reencodedResponse, encoding } = this.encodeResponse(request, response, charset);
418
+ const { response: reencodedResponse, encoding } = this.#encodeResponse(request, response, charset);
416
419
  const contentType = { type, encoding };
417
420
  if (HTML_AND_XML_MIME_TYPES.includes(type)) {
418
421
  return { response, contentType, body: await reencodedResponse.text() };
@@ -426,7 +429,7 @@ export class HttpCrawler extends BasicCrawler {
426
429
  /**
427
430
  * Combines the provided `requestOptions` with mandatory (non-overridable) values.
428
431
  */
429
- getRequestOptions(request, proxyUrl) {
432
+ #getRequestOptions(request, proxyUrl) {
430
433
  const requestOptions = {
431
434
  url: request.url,
432
435
  method: request.method,
@@ -443,7 +446,7 @@ export class HttpCrawler extends BasicCrawler {
443
446
  requestOptions.body = request.payload ?? '';
444
447
  return requestOptions;
445
448
  }
446
- encodeResponse(request, response, encoding) {
449
+ #encodeResponse(request, response, encoding) {
447
450
  if (this.#forceResponseEncoding) {
448
451
  encoding = this.#forceResponseEncoding;
449
452
  }
@@ -479,7 +482,7 @@ export class HttpCrawler extends BasicCrawler {
479
482
  /**
480
483
  * Checks and extends supported mime types
481
484
  */
482
- extendSupportedMimeTypes(additionalMimeTypes) {
485
+ #extendSupportedMimeTypes(additionalMimeTypes) {
483
486
  for (const mimeType of additionalMimeTypes) {
484
487
  if (mimeType === '*/*') {
485
488
  this.#supportedMimeTypes.add(mimeType);
@@ -497,11 +500,11 @@ export class HttpCrawler extends BasicCrawler {
497
500
  /**
498
501
  * Handles timeout request
499
502
  */
500
- handleRequestTimeout(session) {
503
+ #handleRequestTimeout(session) {
501
504
  session.markBad();
502
505
  throw new Error(`Request timed out after ${this.#navigationTimeoutMillis / 1000} seconds.`);
503
506
  }
504
- abortDownloadOfBody(request, response) {
507
+ #abortDownloadOfBody(request, response) {
505
508
  const { status } = response;
506
509
  const { type } = parseContentTypeFromResponse(response);
507
510
  const isTransientContentType = status >= 500 || this.blockedStatusCodes.has(status);
@@ -514,7 +517,7 @@ export class HttpCrawler extends BasicCrawler {
514
517
  /**
515
518
  * @internal wraps public utility for mocking purposes
516
519
  */
517
- requestAsBrowser = async (options, session) => {
520
+ #requestAsBrowser = async (options, session) => {
518
521
  const opts = processHttpRequestOptions({
519
522
  ...options,
520
523
  responseType: 'text',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crawlee/http",
3
- "version": "4.0.0-beta.211",
3
+ "version": "4.0.0-beta.213",
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": "^1.0.1",
51
51
  "@apify/utilities": "^3.0.1",
52
- "@crawlee/basic": "4.0.0-beta.211",
53
- "@crawlee/core": "4.0.0-beta.211",
54
- "@crawlee/http-client": "4.0.0-beta.211",
55
- "@crawlee/types": "4.0.0-beta.211",
56
- "@crawlee/utils": "4.0.0-beta.211",
52
+ "@crawlee/basic": "4.0.0-beta.213",
53
+ "@crawlee/core": "4.0.0-beta.213",
54
+ "@crawlee/http-client": "4.0.0-beta.213",
55
+ "@crawlee/types": "4.0.0-beta.213",
56
+ "@crawlee/utils": "4.0.0-beta.213",
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": "17bab8ab5b98554ca2db1d09bc5f61c59194a760"
73
+ "gitHead": "99d9370281d90291b8d20b4ad597fc2d0bcbcd80"
74
74
  }