@crawlee/core 4.0.0-beta.15 → 4.0.0-beta.150
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/README.md +14 -14
- package/autoscaling/autoscaled_pool.d.ts +73 -177
- package/autoscaling/autoscaled_pool.js +182 -329
- package/autoscaling/concurrency_system.d.ts +268 -0
- package/autoscaling/concurrency_system.js +364 -0
- package/autoscaling/cpu_load_signal.d.ts +43 -0
- package/autoscaling/cpu_load_signal.js +47 -0
- package/autoscaling/event_loop_load_signal.d.ts +51 -0
- package/autoscaling/event_loop_load_signal.js +60 -0
- package/autoscaling/index.d.ts +6 -1
- package/autoscaling/index.js +6 -1
- package/autoscaling/load_signal.d.ts +98 -0
- package/autoscaling/load_signal.js +103 -0
- package/autoscaling/memory_load_signal.d.ts +47 -0
- package/autoscaling/memory_load_signal.js +106 -0
- package/autoscaling/snapshotter.d.ts +58 -163
- package/autoscaling/snapshotter.js +45 -263
- package/autoscaling/storage_backend_load_signal.d.ts +56 -0
- package/autoscaling/storage_backend_load_signal.js +73 -0
- package/autoscaling/system_status.d.ts +67 -89
- package/autoscaling/system_status.js +92 -122
- package/autoscaling/weighted_avg.d.ts +5 -0
- package/autoscaling/weighted_avg.js +14 -0
- package/byte_utils.d.ts +17 -0
- package/byte_utils.js +42 -0
- package/configuration.d.ts +96 -223
- package/configuration.js +170 -222
- package/cookie_utils.d.ts +3 -2
- package/cookie_utils.js +18 -7
- package/crawlers/context_pipeline.d.ts +10 -1
- package/crawlers/context_pipeline.js +31 -8
- package/crawlers/crawler_commons.d.ts +90 -126
- package/crawlers/crawler_commons.js +1 -108
- package/crawlers/error_snapshotter.d.ts +2 -5
- package/crawlers/error_snapshotter.js +7 -8
- package/crawlers/error_tracker.d.ts +0 -1
- package/crawlers/error_tracker.js +0 -1
- package/crawlers/index.d.ts +1 -3
- package/crawlers/index.js +0 -3
- package/crawlers/internals/types.d.ts +0 -1
- package/crawlers/internals/types.js +0 -1
- package/crawlers/statistics.d.ts +187 -64
- package/crawlers/statistics.js +354 -165
- package/debug.d.ts +36 -0
- package/debug.js +70 -0
- package/enqueue_links/enqueue_links.d.ts +61 -154
- package/enqueue_links/enqueue_links.js +40 -232
- package/enqueue_links/index.d.ts +0 -1
- package/enqueue_links/index.js +0 -1
- package/enqueue_links/shared.d.ts +55 -28
- package/enqueue_links/shared.js +116 -69
- package/errors.d.ts +72 -4
- package/errors.js +89 -5
- package/events/event_manager.d.ts +35 -9
- package/events/event_manager.js +12 -13
- package/events/index.d.ts +0 -1
- package/events/index.js +0 -1
- package/events/local_event_manager.d.ts +15 -3
- package/events/local_event_manager.js +39 -13
- package/http.d.ts +9 -0
- package/http.js +28 -0
- package/index.d.ts +7 -5
- package/index.js +8 -4
- package/iterables.d.ts +79 -0
- package/iterables.js +134 -0
- package/log.d.ts +77 -1
- package/log.js +104 -1
- package/memory-storage/consts.d.ts +4 -0
- package/memory-storage/consts.js +4 -0
- package/memory-storage/index.d.ts +1 -0
- package/memory-storage/index.js +1 -0
- package/memory-storage/memory-storage.d.ts +44 -0
- package/memory-storage/memory-storage.js +160 -0
- package/memory-storage/resource-clients/common/base-client.d.ts +4 -0
- package/memory-storage/resource-clients/common/base-client.js +6 -0
- package/memory-storage/resource-clients/dataset.d.ts +40 -0
- package/memory-storage/resource-clients/dataset.js +106 -0
- package/memory-storage/resource-clients/key-value-store.d.ts +63 -0
- package/memory-storage/resource-clients/key-value-store.js +199 -0
- package/memory-storage/resource-clients/request-queue.d.ts +77 -0
- package/memory-storage/resource-clients/request-queue.js +407 -0
- package/memory-storage/utils.d.ts +16 -0
- package/memory-storage/utils.js +41 -0
- package/owned_or_injected.d.ts +58 -0
- package/owned_or_injected.js +98 -0
- package/package.json +13 -12
- package/proxy_configuration.d.ts +22 -128
- package/proxy_configuration.js +32 -144
- package/recoverable_state.d.ts +83 -51
- package/recoverable_state.js +163 -72
- package/request.d.ts +57 -16
- package/request.js +130 -69
- package/router.d.ts +193 -21
- package/router.js +188 -43
- package/serialization.d.ts +0 -1
- package/serialization.js +15 -15
- package/service_locator.d.ts +165 -0
- package/service_locator.js +253 -0
- package/session_pool/consts.d.ts +1 -2
- package/session_pool/consts.js +1 -2
- package/session_pool/errors.d.ts +0 -1
- package/session_pool/errors.js +0 -1
- package/session_pool/fingerprint.d.ts +9 -0
- package/session_pool/fingerprint.js +30 -0
- package/session_pool/index.d.ts +0 -2
- package/session_pool/index.js +0 -2
- package/session_pool/session.d.ts +39 -89
- package/session_pool/session.js +102 -159
- package/session_pool/session_pool.d.ts +67 -91
- package/session_pool/session_pool.js +196 -187
- package/storages/batched_adds.d.ts +37 -0
- package/storages/batched_adds.js +73 -0
- package/storages/dataset.d.ts +109 -56
- package/storages/dataset.js +284 -149
- package/storages/index.d.ts +9 -9
- package/storages/index.js +7 -9
- package/storages/key_value_store.d.ts +183 -48
- package/storages/key_value_store.js +444 -171
- package/storages/key_value_store_codec.d.ts +32 -0
- package/storages/key_value_store_codec.js +113 -0
- package/storages/request_dedup_cache.d.ts +22 -0
- package/storages/request_dedup_cache.js +48 -0
- package/storages/request_list.d.ts +53 -115
- package/storages/request_list.js +194 -167
- package/storages/request_loader.d.ts +133 -0
- package/storages/request_loader.js +36 -0
- package/storages/request_manager.d.ts +109 -0
- package/storages/request_manager.js +1 -0
- package/storages/request_manager_tandem.d.ts +55 -23
- package/storages/request_manager_tandem.js +139 -57
- package/storages/request_queue.d.ts +286 -48
- package/storages/request_queue.js +757 -218
- package/storages/{sitemap_request_list.d.ts → sitemap_request_loader.d.ts} +43 -91
- package/storages/sitemap_request_loader.js +439 -0
- package/storages/storage_instance_manager.d.ts +87 -0
- package/storages/storage_instance_manager.js +256 -0
- package/storages/storage_stats.d.ts +48 -0
- package/storages/storage_stats.js +29 -0
- package/storages/throttling_request_manager.d.ts +222 -0
- package/storages/throttling_request_manager.js +780 -0
- package/storages/transaction.d.ts +252 -0
- package/storages/transaction.js +251 -0
- package/storages/utils.d.ts +59 -11
- package/storages/utils.js +75 -15
- package/system-info/cpu-info.d.ts +67 -0
- package/system-info/cpu-info.js +216 -0
- package/system-info/memory-info.d.ts +31 -0
- package/system-info/memory-info.js +115 -0
- package/system-info/ps-tree.d.ts +17 -0
- package/system-info/ps-tree.js +144 -0
- package/system-info/runtime.d.ts +14 -0
- package/system-info/runtime.js +80 -0
- package/typedefs.d.ts +0 -6
- package/typedefs.js +0 -1
- package/url.d.ts +9 -0
- package/url.js +11 -0
- package/validators.d.ts +22 -18
- package/validators.js +13 -18
- package/autoscaling/autoscaled_pool.d.ts.map +0 -1
- package/autoscaling/autoscaled_pool.js.map +0 -1
- package/autoscaling/index.d.ts.map +0 -1
- package/autoscaling/index.js.map +0 -1
- package/autoscaling/snapshotter.d.ts.map +0 -1
- package/autoscaling/snapshotter.js.map +0 -1
- package/autoscaling/system_status.d.ts.map +0 -1
- package/autoscaling/system_status.js.map +0 -1
- package/configuration.d.ts.map +0 -1
- package/configuration.js.map +0 -1
- package/cookie_utils.d.ts.map +0 -1
- package/cookie_utils.js.map +0 -1
- package/crawlers/context_pipeline.d.ts.map +0 -1
- package/crawlers/context_pipeline.js.map +0 -1
- package/crawlers/crawler_commons.d.ts.map +0 -1
- package/crawlers/crawler_commons.js.map +0 -1
- package/crawlers/crawler_utils.d.ts +0 -10
- package/crawlers/crawler_utils.d.ts.map +0 -1
- package/crawlers/crawler_utils.js +0 -12
- package/crawlers/crawler_utils.js.map +0 -1
- package/crawlers/error_snapshotter.d.ts.map +0 -1
- package/crawlers/error_snapshotter.js.map +0 -1
- package/crawlers/error_tracker.d.ts.map +0 -1
- package/crawlers/error_tracker.js.map +0 -1
- package/crawlers/index.d.ts.map +0 -1
- package/crawlers/index.js.map +0 -1
- package/crawlers/internals/types.d.ts.map +0 -1
- package/crawlers/internals/types.js.map +0 -1
- package/crawlers/statistics.d.ts.map +0 -1
- package/crawlers/statistics.js.map +0 -1
- package/enqueue_links/enqueue_links.d.ts.map +0 -1
- package/enqueue_links/enqueue_links.js.map +0 -1
- package/enqueue_links/index.d.ts.map +0 -1
- package/enqueue_links/index.js.map +0 -1
- package/enqueue_links/shared.d.ts.map +0 -1
- package/enqueue_links/shared.js.map +0 -1
- package/errors.d.ts.map +0 -1
- package/errors.js.map +0 -1
- package/events/event_manager.d.ts.map +0 -1
- package/events/event_manager.js.map +0 -1
- package/events/index.d.ts.map +0 -1
- package/events/index.js.map +0 -1
- package/events/local_event_manager.d.ts.map +0 -1
- package/events/local_event_manager.js.map +0 -1
- package/http_clients/base-http-client.d.ts +0 -140
- package/http_clients/base-http-client.d.ts.map +0 -1
- package/http_clients/base-http-client.js +0 -40
- package/http_clients/base-http-client.js.map +0 -1
- package/http_clients/form-data-like.d.ts +0 -67
- package/http_clients/form-data-like.d.ts.map +0 -1
- package/http_clients/form-data-like.js +0 -5
- package/http_clients/form-data-like.js.map +0 -1
- package/http_clients/got-scraping-http-client.d.ts +0 -20
- package/http_clients/got-scraping-http-client.d.ts.map +0 -1
- package/http_clients/got-scraping-http-client.js +0 -85
- package/http_clients/got-scraping-http-client.js.map +0 -1
- package/http_clients/index.d.ts +0 -3
- package/http_clients/index.d.ts.map +0 -1
- package/http_clients/index.js +0 -3
- package/http_clients/index.js.map +0 -1
- package/index.d.ts.map +0 -1
- package/index.js.map +0 -1
- package/log.d.ts.map +0 -1
- package/log.js.map +0 -1
- package/proxy_configuration.d.ts.map +0 -1
- package/proxy_configuration.js.map +0 -1
- package/recoverable_state.d.ts.map +0 -1
- package/recoverable_state.js.map +0 -1
- package/request.d.ts.map +0 -1
- package/request.js.map +0 -1
- package/router.d.ts.map +0 -1
- package/router.js.map +0 -1
- package/serialization.d.ts.map +0 -1
- package/serialization.js.map +0 -1
- package/session_pool/consts.d.ts.map +0 -1
- package/session_pool/consts.js.map +0 -1
- package/session_pool/errors.d.ts.map +0 -1
- package/session_pool/errors.js.map +0 -1
- package/session_pool/events.d.ts +0 -3
- package/session_pool/events.d.ts.map +0 -1
- package/session_pool/events.js +0 -3
- package/session_pool/events.js.map +0 -1
- package/session_pool/index.d.ts.map +0 -1
- package/session_pool/index.js.map +0 -1
- package/session_pool/session.d.ts.map +0 -1
- package/session_pool/session.js.map +0 -1
- package/session_pool/session_pool.d.ts.map +0 -1
- package/session_pool/session_pool.js.map +0 -1
- package/storages/access_checking.d.ts +0 -13
- package/storages/access_checking.d.ts.map +0 -1
- package/storages/access_checking.js +0 -14
- package/storages/access_checking.js.map +0 -1
- package/storages/dataset.d.ts.map +0 -1
- package/storages/dataset.js.map +0 -1
- package/storages/index.d.ts.map +0 -1
- package/storages/index.js.map +0 -1
- package/storages/key_value_store.d.ts.map +0 -1
- package/storages/key_value_store.js.map +0 -1
- package/storages/request_list.d.ts.map +0 -1
- package/storages/request_list.js.map +0 -1
- package/storages/request_list_adapter.d.ts +0 -58
- package/storages/request_list_adapter.d.ts.map +0 -1
- package/storages/request_list_adapter.js +0 -81
- package/storages/request_list_adapter.js.map +0 -1
- package/storages/request_manager_tandem.d.ts.map +0 -1
- package/storages/request_manager_tandem.js.map +0 -1
- package/storages/request_provider.d.ts +0 -371
- package/storages/request_provider.d.ts.map +0 -1
- package/storages/request_provider.js +0 -585
- package/storages/request_provider.js.map +0 -1
- package/storages/request_queue.d.ts.map +0 -1
- package/storages/request_queue.js.map +0 -1
- package/storages/request_queue_v2.d.ts +0 -87
- package/storages/request_queue_v2.d.ts.map +0 -1
- package/storages/request_queue_v2.js +0 -438
- package/storages/request_queue_v2.js.map +0 -1
- package/storages/sitemap_request_list.d.ts.map +0 -1
- package/storages/sitemap_request_list.js +0 -430
- package/storages/sitemap_request_list.js.map +0 -1
- package/storages/storage_manager.d.ts +0 -58
- package/storages/storage_manager.d.ts.map +0 -1
- package/storages/storage_manager.js +0 -105
- package/storages/storage_manager.js.map +0 -1
- package/storages/utils.d.ts.map +0 -1
- package/storages/utils.js.map +0 -1
- package/typedefs.d.ts.map +0 -1
- package/typedefs.js.map +0 -1
- package/validators.d.ts.map +0 -1
- package/validators.js.map +0 -1
|
@@ -1,24 +1,6 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { Cookie, SerializedCookieJar } from 'tough-cookie';
|
|
1
|
+
import type { Dictionary, ISession, ProxyInfo, SessionFingerprint, SessionState } from '@crawlee/types';
|
|
3
2
|
import { CookieJar } from 'tough-cookie';
|
|
4
|
-
import type {
|
|
5
|
-
import type { ProxyInfo } from '../proxy_configuration.js';
|
|
6
|
-
/**
|
|
7
|
-
* Persistable {@link Session} state.
|
|
8
|
-
*/
|
|
9
|
-
export interface SessionState {
|
|
10
|
-
id: string;
|
|
11
|
-
cookieJar: SerializedCookieJar;
|
|
12
|
-
proxyInfo?: ProxyInfo;
|
|
13
|
-
userData: object;
|
|
14
|
-
errorScore: number;
|
|
15
|
-
maxErrorScore: number;
|
|
16
|
-
errorScoreDecrement: number;
|
|
17
|
-
usageCount: number;
|
|
18
|
-
maxUsageCount: number;
|
|
19
|
-
expiresAt: string;
|
|
20
|
-
createdAt: string;
|
|
21
|
-
}
|
|
3
|
+
import type { CrawleeLogger } from '../log.js';
|
|
22
4
|
export interface SessionOptions {
|
|
23
5
|
/** Id of session used for generating fingerprints. It is used as proxy session name. */
|
|
24
6
|
id?: string;
|
|
@@ -46,7 +28,10 @@ export interface SessionOptions {
|
|
|
46
28
|
errorScoreDecrement?: number;
|
|
47
29
|
/** Date of creation. */
|
|
48
30
|
createdAt?: Date;
|
|
49
|
-
/**
|
|
31
|
+
/**
|
|
32
|
+
* Date of expiration.
|
|
33
|
+
* @default createdAt + maxAgeSecs
|
|
34
|
+
*/
|
|
50
35
|
expiresAt?: Date;
|
|
51
36
|
/**
|
|
52
37
|
* Indicates how many times the session has been used.
|
|
@@ -59,12 +44,22 @@ export interface SessionOptions {
|
|
|
59
44
|
* @default 50
|
|
60
45
|
*/
|
|
61
46
|
maxUsageCount?: number;
|
|
62
|
-
/**
|
|
63
|
-
|
|
64
|
-
|
|
47
|
+
/**
|
|
48
|
+
* Marks the session as already retired. Used when restoring a previously persisted session
|
|
49
|
+
* so that `isUsable()` reflects the terminal state regardless of error score or usage count.
|
|
50
|
+
* @default false
|
|
51
|
+
*/
|
|
52
|
+
retired?: boolean;
|
|
53
|
+
log?: CrawleeLogger;
|
|
65
54
|
errorScore?: number;
|
|
66
55
|
cookieJar?: CookieJar;
|
|
67
56
|
proxyInfo?: ProxyInfo;
|
|
57
|
+
/**
|
|
58
|
+
* Browser / HTTP client fingerprint tied to this session. Backends use this to make
|
|
59
|
+
* repeated requests with the same session look consistent (same user-agent, headers,
|
|
60
|
+
* TLS profile). See {@link SessionFingerprint}.
|
|
61
|
+
*/
|
|
62
|
+
fingerprint?: SessionFingerprint;
|
|
68
63
|
}
|
|
69
64
|
/**
|
|
70
65
|
* Sessions are used to store information such as cookies and can be used for generating fingerprints and proxy sessions.
|
|
@@ -72,21 +67,10 @@ export interface SessionOptions {
|
|
|
72
67
|
* Session internal state can be enriched with custom user data for example some authorization tokens and specific headers in general.
|
|
73
68
|
* @category Scaling
|
|
74
69
|
*/
|
|
75
|
-
export declare class Session {
|
|
70
|
+
export declare class Session implements ISession {
|
|
71
|
+
#private;
|
|
76
72
|
readonly id: string;
|
|
77
|
-
|
|
78
|
-
userData: Dictionary;
|
|
79
|
-
private _maxErrorScore;
|
|
80
|
-
private _errorScoreDecrement;
|
|
81
|
-
private _createdAt;
|
|
82
|
-
private _expiresAt;
|
|
83
|
-
private _usageCount;
|
|
84
|
-
private _maxUsageCount;
|
|
85
|
-
private sessionPool;
|
|
86
|
-
private _errorScore;
|
|
87
|
-
private _proxyInfo?;
|
|
88
|
-
private _cookieJar;
|
|
89
|
-
private log;
|
|
73
|
+
readonly userData: Dictionary;
|
|
90
74
|
get errorScore(): number;
|
|
91
75
|
get usageCount(): number;
|
|
92
76
|
get maxErrorScore(): number;
|
|
@@ -96,10 +80,17 @@ export declare class Session {
|
|
|
96
80
|
get maxUsageCount(): number;
|
|
97
81
|
get cookieJar(): CookieJar;
|
|
98
82
|
get proxyInfo(): ProxyInfo | undefined;
|
|
83
|
+
get fingerprint(): SessionFingerprint | undefined;
|
|
84
|
+
set fingerprint(fingerprint: SessionFingerprint | undefined);
|
|
85
|
+
/**
|
|
86
|
+
* `true` once {@link Session.retire|`retire()`} has been called. Retirement is terminal:
|
|
87
|
+
* a retired session is never picked by the pool and cannot be revived via `markGood()`.
|
|
88
|
+
*/
|
|
89
|
+
get retired(): boolean;
|
|
99
90
|
/**
|
|
100
91
|
* Session configuration.
|
|
101
92
|
*/
|
|
102
|
-
constructor(options
|
|
93
|
+
constructor(options?: SessionOptions);
|
|
103
94
|
/**
|
|
104
95
|
* Indicates whether the session is blocked.
|
|
105
96
|
* Session is blocked once it reaches the `maxErrorScore`.
|
|
@@ -118,7 +109,7 @@ export declare class Session {
|
|
|
118
109
|
isMaxUsageCountReached(): boolean;
|
|
119
110
|
/**
|
|
120
111
|
* Indicates whether the session can be used for next requests.
|
|
121
|
-
* Session is usable when it is not expired, not blocked and the maximum usage count has not be reached.
|
|
112
|
+
* Session is usable when it is not retired, not expired, not blocked and the maximum usage count has not be reached.
|
|
122
113
|
*/
|
|
123
114
|
isUsable(): boolean;
|
|
124
115
|
/**
|
|
@@ -132,11 +123,11 @@ export declare class Session {
|
|
|
132
123
|
*/
|
|
133
124
|
getState(): SessionState;
|
|
134
125
|
/**
|
|
135
|
-
*
|
|
136
|
-
*
|
|
137
|
-
*
|
|
138
|
-
*
|
|
139
|
-
*
|
|
126
|
+
* Permanently retires the session — `isUsable()` will return `false` from here on,
|
|
127
|
+
* and no `markGood()` / `markBad()` can revive it. Calling `retire()` again is a no-op.
|
|
128
|
+
*
|
|
129
|
+
* Use this when you're confident the session itself is the problem (e.g. a `403` response).
|
|
130
|
+
* For transient external failures (such as `5XX` responses), use `markBad()` instead.
|
|
140
131
|
*/
|
|
141
132
|
retire(): void;
|
|
142
133
|
/**
|
|
@@ -144,60 +135,19 @@ export declare class Session {
|
|
|
144
135
|
* Should be used when the session has been used unsuccessfully. For example because of timeouts.
|
|
145
136
|
*/
|
|
146
137
|
markBad(): void;
|
|
147
|
-
/**
|
|
148
|
-
* With certain status codes: `401`, `403` or `429` we can be certain
|
|
149
|
-
* that the target website is blocking us. This function helps to do this conveniently
|
|
150
|
-
* by retiring the session when such code is received. Optionally, the default status
|
|
151
|
-
* codes can be extended in the second parameter.
|
|
152
|
-
* @param statusCode HTTP status code.
|
|
153
|
-
* @returns Whether the session was retired.
|
|
154
|
-
*/
|
|
155
|
-
retireOnBlockedStatusCodes(statusCode: number): boolean;
|
|
156
|
-
/**
|
|
157
|
-
* Saves cookies from an HTTP response to be used with the session.
|
|
158
|
-
* It expects an object with a `headers` property that's either an `Object`
|
|
159
|
-
* (typical Node.js responses) or a `Function` (Puppeteer Response).
|
|
160
|
-
*
|
|
161
|
-
* It then parses and saves the cookies from the `set-cookie` header, if available.
|
|
162
|
-
*/
|
|
163
|
-
setCookiesFromResponse(response: Response): void;
|
|
164
|
-
/**
|
|
165
|
-
* Saves an array with cookie objects to be used with the session.
|
|
166
|
-
* The objects should be in the format that
|
|
167
|
-
* [Puppeteer uses](https://pptr.dev/#?product=Puppeteer&version=v2.0.0&show=api-pagecookiesurls),
|
|
168
|
-
* but you can also use this function to set cookies manually:
|
|
169
|
-
*
|
|
170
|
-
* ```
|
|
171
|
-
* [
|
|
172
|
-
* { name: 'cookie1', value: 'my-cookie' },
|
|
173
|
-
* { name: 'cookie2', value: 'your-cookie' }
|
|
174
|
-
* ]
|
|
175
|
-
* ```
|
|
176
|
-
*/
|
|
177
|
-
setCookies(cookies: CookieObject[], url: string): void;
|
|
178
|
-
/**
|
|
179
|
-
* Returns cookies in a format compatible with puppeteer/playwright and ready to be used with `page.setCookie`.
|
|
180
|
-
* @param url website url. Only cookies stored for this url will be returned
|
|
181
|
-
*/
|
|
182
|
-
getCookies(url: string): CookieObject[];
|
|
183
138
|
/**
|
|
184
139
|
* Returns cookies saved with the session in the typical
|
|
185
140
|
* key1=value1; key2=value2 format, ready to be used in
|
|
186
141
|
* a cookie header or elsewhere.
|
|
187
142
|
* @returns Represents `Cookie` header.
|
|
188
143
|
*/
|
|
189
|
-
getCookieString(url: string): string
|
|
144
|
+
getCookieString(url: string): Promise<string>;
|
|
190
145
|
/**
|
|
191
146
|
* Sets a cookie within this session for the specific URL.
|
|
192
147
|
*/
|
|
193
|
-
setCookie(rawCookie: string, url: string): void
|
|
194
|
-
/**
|
|
195
|
-
* Sets cookies.
|
|
196
|
-
*/
|
|
197
|
-
protected _setCookies(cookies: Cookie[], url: string): void;
|
|
148
|
+
setCookie(rawCookie: string, url: string): Promise<void>;
|
|
198
149
|
/**
|
|
199
150
|
* Checks if session is not usable. if it is not retires the session.
|
|
200
151
|
*/
|
|
201
|
-
|
|
152
|
+
private maybeSelfRetire;
|
|
202
153
|
}
|
|
203
|
-
//# sourceMappingURL=session.d.ts.map
|
package/session_pool/session.js
CHANGED
|
@@ -1,10 +1,27 @@
|
|
|
1
|
-
import { EventEmitter } from 'node:events';
|
|
2
|
-
import ow from 'ow';
|
|
3
1
|
import { CookieJar } from 'tough-cookie';
|
|
2
|
+
import { z } from 'zod';
|
|
4
3
|
import { cryptoRandomObjectId } from '@apify/utilities';
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
|
|
4
|
+
import { serviceLocator } from '../service_locator.js';
|
|
5
|
+
import { parseArgument, schemas, validators } from '../validators.js';
|
|
6
|
+
// `schemas.anyObject` passes values through by reference (object schemas return a pruned plain
|
|
7
|
+
// copy), so class instances like cookie jars and loggers keep their prototype.
|
|
8
|
+
const sessionOptionsSchema = z.strictObject({
|
|
9
|
+
id: z.string().default(() => `session_${cryptoRandomObjectId(10)}`),
|
|
10
|
+
cookieJar: schemas.anyObject.default(() => new CookieJar()),
|
|
11
|
+
proxyInfo: schemas.anyObject.optional(),
|
|
12
|
+
maxAgeSecs: schemas.anyNumber.default(3000),
|
|
13
|
+
userData: schemas.anyObject.default(() => ({})),
|
|
14
|
+
maxErrorScore: schemas.anyNumber.default(3),
|
|
15
|
+
errorScoreDecrement: schemas.anyNumber.default(0.5),
|
|
16
|
+
createdAt: z.date().default(() => new Date()),
|
|
17
|
+
expiresAt: z.date().optional(),
|
|
18
|
+
usageCount: schemas.anyNumber.default(0),
|
|
19
|
+
errorScore: schemas.anyNumber.default(0),
|
|
20
|
+
maxUsageCount: schemas.anyNumber.default(50),
|
|
21
|
+
retired: z.boolean().default(false),
|
|
22
|
+
log: validators.logger.default(() => serviceLocator.getLogger()),
|
|
23
|
+
fingerprint: schemas.anyObject.optional(),
|
|
24
|
+
});
|
|
8
25
|
/**
|
|
9
26
|
* Sessions are used to store information such as cookies and can be used for generating fingerprints and proxy sessions.
|
|
10
27
|
* You can imagine each session as a specific user, with its own cookies, IP (via proxy) and potentially a unique browser fingerprint.
|
|
@@ -13,83 +30,81 @@ import { EVENT_SESSION_RETIRED } from './events.js';
|
|
|
13
30
|
*/
|
|
14
31
|
export class Session {
|
|
15
32
|
id;
|
|
16
|
-
maxAgeSecs;
|
|
17
33
|
userData;
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
34
|
+
#maxErrorScore;
|
|
35
|
+
#errorScoreDecrement;
|
|
36
|
+
#createdAt;
|
|
37
|
+
#expiresAt;
|
|
38
|
+
#usageCount;
|
|
39
|
+
#maxUsageCount;
|
|
40
|
+
#errorScore;
|
|
41
|
+
#retired = false;
|
|
42
|
+
#proxyInfo;
|
|
43
|
+
#cookieJar;
|
|
44
|
+
#fingerprint;
|
|
45
|
+
#log;
|
|
29
46
|
get errorScore() {
|
|
30
|
-
return this
|
|
47
|
+
return this.#errorScore;
|
|
31
48
|
}
|
|
32
49
|
get usageCount() {
|
|
33
|
-
return this
|
|
50
|
+
return this.#usageCount;
|
|
34
51
|
}
|
|
35
52
|
get maxErrorScore() {
|
|
36
|
-
return this
|
|
53
|
+
return this.#maxErrorScore;
|
|
37
54
|
}
|
|
38
55
|
get errorScoreDecrement() {
|
|
39
|
-
return this
|
|
56
|
+
return this.#errorScoreDecrement;
|
|
40
57
|
}
|
|
41
58
|
get expiresAt() {
|
|
42
|
-
return this
|
|
59
|
+
return this.#expiresAt;
|
|
43
60
|
}
|
|
44
61
|
get createdAt() {
|
|
45
|
-
return this
|
|
62
|
+
return this.#createdAt;
|
|
46
63
|
}
|
|
47
64
|
get maxUsageCount() {
|
|
48
|
-
return this
|
|
65
|
+
return this.#maxUsageCount;
|
|
49
66
|
}
|
|
50
67
|
get cookieJar() {
|
|
51
|
-
return this
|
|
68
|
+
return this.#cookieJar;
|
|
52
69
|
}
|
|
53
70
|
get proxyInfo() {
|
|
54
|
-
return this
|
|
71
|
+
return this.#proxyInfo;
|
|
72
|
+
}
|
|
73
|
+
get fingerprint() {
|
|
74
|
+
return this.#fingerprint;
|
|
75
|
+
}
|
|
76
|
+
set fingerprint(fingerprint) {
|
|
77
|
+
this.#fingerprint = fingerprint;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* `true` once {@link Session.retire|`retire()`} has been called. Retirement is terminal:
|
|
81
|
+
* a retired session is never picked by the pool and cannot be revived via `markGood()`.
|
|
82
|
+
*/
|
|
83
|
+
get retired() {
|
|
84
|
+
return this.#retired;
|
|
55
85
|
}
|
|
56
86
|
/**
|
|
57
87
|
* Session configuration.
|
|
58
88
|
*/
|
|
59
|
-
constructor(options) {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
maxErrorScore: ow.optional.number,
|
|
68
|
-
errorScoreDecrement: ow.optional.number,
|
|
69
|
-
createdAt: ow.optional.date,
|
|
70
|
-
expiresAt: ow.optional.date,
|
|
71
|
-
usageCount: ow.optional.number,
|
|
72
|
-
errorScore: ow.optional.number,
|
|
73
|
-
maxUsageCount: ow.optional.number,
|
|
74
|
-
log: ow.optional.object,
|
|
75
|
-
}));
|
|
76
|
-
const { sessionPool, id = `session_${cryptoRandomObjectId(10)}`, cookieJar = new CookieJar(), proxyInfo = undefined, maxAgeSecs = 3000, userData = {}, maxErrorScore = 3, errorScoreDecrement = 0.5, createdAt = new Date(), usageCount = 0, errorScore = 0, maxUsageCount = 50, log = defaultLog, } = options;
|
|
77
|
-
const { expiresAt = getDefaultCookieExpirationDate(maxAgeSecs) } = options;
|
|
78
|
-
this.log = log.child({ prefix: 'Session' });
|
|
79
|
-
this._cookieJar = cookieJar.setCookie ? cookieJar : CookieJar.fromJSON(JSON.stringify(cookieJar));
|
|
80
|
-
this._proxyInfo = proxyInfo;
|
|
89
|
+
constructor(options = {}) {
|
|
90
|
+
const { id, cookieJar, proxyInfo, maxAgeSecs, userData, maxErrorScore, errorScoreDecrement, createdAt, usageCount, errorScore, maxUsageCount, retired, log, fingerprint,
|
|
91
|
+
// Anchored to `createdAt` rather than to "now", so the documented `createdAt + maxAgeSecs` holds.
|
|
92
|
+
expiresAt = new Date(createdAt.getTime() + maxAgeSecs * 1000), } = parseArgument(options, sessionOptionsSchema);
|
|
93
|
+
this.#log = log.child({ prefix: 'Session' });
|
|
94
|
+
this.#cookieJar = cookieJar.setCookie ? cookieJar : CookieJar.fromJSON(JSON.stringify(cookieJar));
|
|
95
|
+
this.#proxyInfo = proxyInfo;
|
|
96
|
+
this.#fingerprint = fingerprint;
|
|
81
97
|
this.id = id;
|
|
82
|
-
this.maxAgeSecs = maxAgeSecs;
|
|
83
98
|
this.userData = userData;
|
|
84
|
-
this
|
|
85
|
-
this
|
|
99
|
+
this.#maxErrorScore = maxErrorScore;
|
|
100
|
+
this.#errorScoreDecrement = errorScoreDecrement;
|
|
86
101
|
// Internal
|
|
87
|
-
this
|
|
88
|
-
this
|
|
89
|
-
this
|
|
90
|
-
this
|
|
91
|
-
this
|
|
92
|
-
this
|
|
102
|
+
this.#expiresAt = expiresAt;
|
|
103
|
+
this.#createdAt = createdAt;
|
|
104
|
+
this.#usageCount = usageCount; // indicates how many times the session has been used
|
|
105
|
+
this.#errorScore = errorScore; // indicates number of markBaded request with the session
|
|
106
|
+
this.#maxUsageCount = maxUsageCount;
|
|
107
|
+
this.#retired = retired;
|
|
93
108
|
}
|
|
94
109
|
/**
|
|
95
110
|
* Indicates whether the session is blocked.
|
|
@@ -115,21 +130,21 @@ export class Session {
|
|
|
115
130
|
}
|
|
116
131
|
/**
|
|
117
132
|
* Indicates whether the session can be used for next requests.
|
|
118
|
-
* Session is usable when it is not expired, not blocked and the maximum usage count has not be reached.
|
|
133
|
+
* Session is usable when it is not retired, not expired, not blocked and the maximum usage count has not be reached.
|
|
119
134
|
*/
|
|
120
135
|
isUsable() {
|
|
121
|
-
return !this.isBlocked() && !this.isExpired() && !this.isMaxUsageCountReached();
|
|
136
|
+
return !this.#retired && !this.isBlocked() && !this.isExpired() && !this.isMaxUsageCountReached();
|
|
122
137
|
}
|
|
123
138
|
/**
|
|
124
139
|
* This method should be called after a successful session usage.
|
|
125
140
|
* It increases `usageCount` and potentially lowers the `errorScore` by the `errorScoreDecrement`.
|
|
126
141
|
*/
|
|
127
142
|
markGood() {
|
|
128
|
-
this
|
|
129
|
-
if (this
|
|
130
|
-
this
|
|
143
|
+
this.#usageCount += 1;
|
|
144
|
+
if (this.#errorScore > 0) {
|
|
145
|
+
this.#errorScore -= this.#errorScoreDecrement;
|
|
131
146
|
}
|
|
132
|
-
this.
|
|
147
|
+
this.maybeSelfRetire();
|
|
133
148
|
}
|
|
134
149
|
/**
|
|
135
150
|
* Gets session state for persistence in KeyValueStore.
|
|
@@ -139,8 +154,9 @@ export class Session {
|
|
|
139
154
|
return {
|
|
140
155
|
id: this.id,
|
|
141
156
|
cookieJar: this.cookieJar.toJSON(),
|
|
142
|
-
proxyInfo: this
|
|
157
|
+
proxyInfo: this.#proxyInfo,
|
|
143
158
|
userData: this.userData,
|
|
159
|
+
fingerprint: this.#fingerprint,
|
|
144
160
|
maxErrorScore: this.maxErrorScore,
|
|
145
161
|
errorScoreDecrement: this.errorScoreDecrement,
|
|
146
162
|
expiresAt: this.expiresAt.toISOString(),
|
|
@@ -148,89 +164,31 @@ export class Session {
|
|
|
148
164
|
usageCount: this.usageCount,
|
|
149
165
|
maxUsageCount: this.maxUsageCount,
|
|
150
166
|
errorScore: this.errorScore,
|
|
167
|
+
retired: this.#retired,
|
|
151
168
|
};
|
|
152
169
|
}
|
|
153
170
|
/**
|
|
154
|
-
*
|
|
155
|
-
*
|
|
156
|
-
*
|
|
157
|
-
*
|
|
158
|
-
*
|
|
171
|
+
* Permanently retires the session — `isUsable()` will return `false` from here on,
|
|
172
|
+
* and no `markGood()` / `markBad()` can revive it. Calling `retire()` again is a no-op.
|
|
173
|
+
*
|
|
174
|
+
* Use this when you're confident the session itself is the problem (e.g. a `403` response).
|
|
175
|
+
* For transient external failures (such as `5XX` responses), use `markBad()` instead.
|
|
159
176
|
*/
|
|
160
177
|
retire() {
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
this
|
|
164
|
-
|
|
165
|
-
this
|
|
178
|
+
if (this.#retired)
|
|
179
|
+
return;
|
|
180
|
+
this.#errorScore += this.#maxErrorScore;
|
|
181
|
+
this.#usageCount += 1;
|
|
182
|
+
this.#retired = true;
|
|
166
183
|
}
|
|
167
184
|
/**
|
|
168
185
|
* Increases usage and error count.
|
|
169
186
|
* Should be used when the session has been used unsuccessfully. For example because of timeouts.
|
|
170
187
|
*/
|
|
171
188
|
markBad() {
|
|
172
|
-
this
|
|
173
|
-
this
|
|
174
|
-
this.
|
|
175
|
-
}
|
|
176
|
-
/**
|
|
177
|
-
* With certain status codes: `401`, `403` or `429` we can be certain
|
|
178
|
-
* that the target website is blocking us. This function helps to do this conveniently
|
|
179
|
-
* by retiring the session when such code is received. Optionally, the default status
|
|
180
|
-
* codes can be extended in the second parameter.
|
|
181
|
-
* @param statusCode HTTP status code.
|
|
182
|
-
* @returns Whether the session was retired.
|
|
183
|
-
*/
|
|
184
|
-
retireOnBlockedStatusCodes(statusCode) {
|
|
185
|
-
// eslint-disable-next-line dot-notation -- accessing private property
|
|
186
|
-
const isBlocked = this.sessionPool['blockedStatusCodes'].includes(statusCode);
|
|
187
|
-
if (isBlocked) {
|
|
188
|
-
this.retire();
|
|
189
|
-
}
|
|
190
|
-
return isBlocked;
|
|
191
|
-
}
|
|
192
|
-
/**
|
|
193
|
-
* Saves cookies from an HTTP response to be used with the session.
|
|
194
|
-
* It expects an object with a `headers` property that's either an `Object`
|
|
195
|
-
* (typical Node.js responses) or a `Function` (Puppeteer Response).
|
|
196
|
-
*
|
|
197
|
-
* It then parses and saves the cookies from the `set-cookie` header, if available.
|
|
198
|
-
*/
|
|
199
|
-
setCookiesFromResponse(response) {
|
|
200
|
-
try {
|
|
201
|
-
const cookies = getCookiesFromResponse(response).filter((c) => c);
|
|
202
|
-
this._setCookies(cookies, response.url);
|
|
203
|
-
}
|
|
204
|
-
catch (e) {
|
|
205
|
-
const err = e;
|
|
206
|
-
// if invalid Cookie header is provided just log the exception.
|
|
207
|
-
this.log.exception(err, 'Could not get cookies from response');
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
/**
|
|
211
|
-
* Saves an array with cookie objects to be used with the session.
|
|
212
|
-
* The objects should be in the format that
|
|
213
|
-
* [Puppeteer uses](https://pptr.dev/#?product=Puppeteer&version=v2.0.0&show=api-pagecookiesurls),
|
|
214
|
-
* but you can also use this function to set cookies manually:
|
|
215
|
-
*
|
|
216
|
-
* ```
|
|
217
|
-
* [
|
|
218
|
-
* { name: 'cookie1', value: 'my-cookie' },
|
|
219
|
-
* { name: 'cookie2', value: 'your-cookie' }
|
|
220
|
-
* ]
|
|
221
|
-
* ```
|
|
222
|
-
*/
|
|
223
|
-
setCookies(cookies, url) {
|
|
224
|
-
const normalizedCookies = cookies.map((c) => browserPoolCookieToToughCookie(c, this.maxAgeSecs));
|
|
225
|
-
this._setCookies(normalizedCookies, url);
|
|
226
|
-
}
|
|
227
|
-
/**
|
|
228
|
-
* Returns cookies in a format compatible with puppeteer/playwright and ready to be used with `page.setCookie`.
|
|
229
|
-
* @param url website url. Only cookies stored for this url will be returned
|
|
230
|
-
*/
|
|
231
|
-
getCookies(url) {
|
|
232
|
-
const cookies = this.cookieJar.getCookiesSync(url);
|
|
233
|
-
return cookies.map((c) => toughCookieToBrowserPoolCookie(c));
|
|
189
|
+
this.#errorScore += 1;
|
|
190
|
+
this.#usageCount += 1;
|
|
191
|
+
this.maybeSelfRetire();
|
|
234
192
|
}
|
|
235
193
|
/**
|
|
236
194
|
* Returns cookies saved with the session in the typical
|
|
@@ -238,41 +196,26 @@ export class Session {
|
|
|
238
196
|
* a cookie header or elsewhere.
|
|
239
197
|
* @returns Represents `Cookie` header.
|
|
240
198
|
*/
|
|
241
|
-
getCookieString(url) {
|
|
242
|
-
return this.cookieJar.
|
|
199
|
+
async getCookieString(url) {
|
|
200
|
+
return this.cookieJar.getCookieString(url, {});
|
|
243
201
|
}
|
|
244
202
|
/**
|
|
245
203
|
* Sets a cookie within this session for the specific URL.
|
|
246
204
|
*/
|
|
247
|
-
setCookie(rawCookie, url) {
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
/**
|
|
251
|
-
* Sets cookies.
|
|
252
|
-
*/
|
|
253
|
-
_setCookies(cookies, url) {
|
|
254
|
-
const errorMessages = [];
|
|
255
|
-
for (const cookie of cookies) {
|
|
256
|
-
try {
|
|
257
|
-
this.cookieJar.setCookieSync(cookie, url, { ignoreError: false });
|
|
258
|
-
}
|
|
259
|
-
catch (e) {
|
|
260
|
-
const err = e;
|
|
261
|
-
errorMessages.push(err.message);
|
|
262
|
-
}
|
|
205
|
+
async setCookie(rawCookie, url) {
|
|
206
|
+
try {
|
|
207
|
+
await this.cookieJar.setCookie(rawCookie, url);
|
|
263
208
|
}
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
this.log.debug('Could not set cookies.', { errorMessages });
|
|
209
|
+
catch (e) {
|
|
210
|
+
this.#log.warning('Could not set cookie.', { url, error: e.message });
|
|
267
211
|
}
|
|
268
212
|
}
|
|
269
213
|
/**
|
|
270
214
|
* Checks if session is not usable. if it is not retires the session.
|
|
271
215
|
*/
|
|
272
|
-
|
|
216
|
+
maybeSelfRetire() {
|
|
273
217
|
if (!this.isUsable()) {
|
|
274
218
|
this.retire();
|
|
275
219
|
}
|
|
276
220
|
}
|
|
277
221
|
}
|
|
278
|
-
//# sourceMappingURL=session.js.map
|