@comunica/actor-http-fetch 4.5.0 → 5.0.2

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 CHANGED
@@ -5,6 +5,9 @@
5
5
  An [HTTP](https://github.com/comunica/comunica/tree/master/packages/bus-http) actor that
6
6
  uses [fetch](https://fetch.spec.whatwg.org/) to perform HTTP requests.
7
7
 
8
+ When this actor is used in Node.js, a memory-based cache will be initialized.
9
+ This cache is only used when the `httpCache` context flag is enabled.
10
+
8
11
  This module is part of the [Comunica framework](https://github.com/comunica/comunica),
9
12
  and should only be used by [developers that want to build their own query engine](https://comunica.dev/docs/modify/).
10
13
 
@@ -25,7 +28,7 @@ After installing, this package can be added to your engine's configuration as fo
25
28
  ```json
26
29
  {
27
30
  "@context": [
28
- "https://linkedsoftwaredependencies.org/bundles/npm/@comunica/actor-http-fetch/^4.0.0/components/context.jsonld"
31
+ "https://linkedsoftwaredependencies.org/bundles/npm/@comunica/actor-http-fetch/^5.0.0/components/context.jsonld"
29
32
  ],
30
33
  "actors": [
31
34
  {
@@ -38,4 +41,8 @@ After installing, this package can be added to your engine's configuration as fo
38
41
 
39
42
  ### Config Parameters
40
43
 
44
+ * `cacheMaxSize`: Maximum size of the cache (in bytes). Defaults to `104857600` (100MB).
45
+ * `cacheMaxCount`: Maximum number of documents to store in the cache. Defaults to `1000`.
46
+ * `cacheMaxEntrySize`: Maximum size of an entry in the cache (in bytes). Defaults to `5242880` (5MB).
47
+ * `httpInvalidator`: A mediator over the [HTTP invalidate bus](https://github.com/comunica/comunica/tree/master/packages/bus-http-invalidate).
41
48
  * `agentOptions`: The agent JSON options for the HTTP agent in Node.js environments. _(optional)_
@@ -1,8 +1,9 @@
1
1
  {
2
2
  "@context": [
3
- "https://linkedsoftwaredependencies.org/bundles/npm/@comunica/actor-http-fetch/^4.0.0/components/context.jsonld",
4
- "https://linkedsoftwaredependencies.org/bundles/npm/@comunica/bus-http/^4.0.0/components/context.jsonld",
5
- "https://linkedsoftwaredependencies.org/bundles/npm/@comunica/core/^4.0.0/components/context.jsonld"
3
+ "https://linkedsoftwaredependencies.org/bundles/npm/@comunica/actor-http-fetch/^5.0.0/components/context.jsonld",
4
+ "https://linkedsoftwaredependencies.org/bundles/npm/@comunica/bus-http-invalidate/^5.0.0/components/context.jsonld",
5
+ "https://linkedsoftwaredependencies.org/bundles/npm/@comunica/bus-http/^5.0.0/components/context.jsonld",
6
+ "https://linkedsoftwaredependencies.org/bundles/npm/@comunica/core/^5.0.0/components/context.jsonld"
6
7
  ],
7
8
  "@id": "npmd:@comunica/actor-http-fetch",
8
9
  "components": [
@@ -14,6 +15,33 @@
14
15
  "cbh:components/ActorHttp.jsonld#ActorHttp"
15
16
  ],
16
17
  "parameters": [
18
+ {
19
+ "@id": "cahf:components/ActorHttpFetch.jsonld#ActorHttpFetch_args_cacheMaxSize",
20
+ "range": "xsd:integer",
21
+ "default": "104857600",
22
+ "comment": "Maximum size of the cache (in bytes). Defaults to 100MB."
23
+ },
24
+ {
25
+ "@id": "cahf:components/ActorHttpFetch.jsonld#ActorHttpFetch_args_cacheMaxCount",
26
+ "range": "xsd:integer",
27
+ "default": "1000",
28
+ "comment": "Maximum number of documents to store in the cache."
29
+ },
30
+ {
31
+ "@id": "cahf:components/ActorHttpFetch.jsonld#ActorHttpFetch_args_cacheMaxEntrySize",
32
+ "range": "xsd:integer",
33
+ "default": "5242880",
34
+ "comment": "Maximum size of an entry in the cache (in bytes). Defaults to 5MB."
35
+ },
36
+ {
37
+ "@id": "cahf:components/ActorHttpFetch.jsonld#ActorHttpFetch_args_httpInvalidator",
38
+ "range": "cbhi:components/ActorHttpInvalidateListenable.jsonld#ActorHttpInvalidateListenable",
39
+ "default": {
40
+ "@id": "cahf:components/ActorHttpFetch.jsonld#IActorHttpFetchArgs_default_invalidator",
41
+ "@type": "npmd:@comunica/bus-http-invalidate/^5.0.0/components/ActorHttpInvalidateListenable.jsonld#ActorHttpInvalidateListenable"
42
+ },
43
+ "comment": "An actor that listens to HTTP invalidation events"
44
+ },
17
45
  {
18
46
  "@id": "cahf:components/ActorHttpFetch.jsonld#ActorHttpFetch_args_agentOptions",
19
47
  "range": {
@@ -54,37 +82,37 @@
54
82
  "genericTypeInstances": [
55
83
  {
56
84
  "@type": "ParameterRangeGenericTypeReference",
57
- "parameterRangeGenericType": "npmd:@comunica/actor-abstract-mediatyped/^4.0.0/components/ActorAbstractMediaTyped.jsonld#ActorAbstractMediaTyped__generic_I"
85
+ "parameterRangeGenericType": "npmd:@comunica/actor-abstract-mediatyped/^5.0.0/components/ActorAbstractMediaTyped.jsonld#ActorAbstractMediaTyped__generic_I"
58
86
  },
59
87
  {
60
88
  "@type": "ParameterRangeGenericTypeReference",
61
- "parameterRangeGenericType": "npmd:@comunica/actor-abstract-mediatyped/^4.0.0/components/ActorAbstractMediaTyped.jsonld#ActorAbstractMediaTyped__generic_T"
89
+ "parameterRangeGenericType": "npmd:@comunica/actor-abstract-mediatyped/^5.0.0/components/ActorAbstractMediaTyped.jsonld#ActorAbstractMediaTyped__generic_T"
62
90
  },
63
91
  {
64
92
  "@type": "ParameterRangeGenericTypeReference",
65
- "parameterRangeGenericType": "npmd:@comunica/actor-abstract-mediatyped/^4.0.0/components/ActorAbstractMediaTyped.jsonld#ActorAbstractMediaTyped__generic_O"
93
+ "parameterRangeGenericType": "npmd:@comunica/actor-abstract-mediatyped/^5.0.0/components/ActorAbstractMediaTyped.jsonld#ActorAbstractMediaTyped__generic_O"
66
94
  },
67
95
  {
68
96
  "@type": "ParameterRangeGenericTypeReference",
69
- "parameterRangeGenericType": "npmd:@comunica/actor-abstract-mediatyped/^4.0.0/components/ActorAbstractMediaTyped.jsonld#ActorAbstractMediaTyped__generic_TS"
97
+ "parameterRangeGenericType": "npmd:@comunica/actor-abstract-mediatyped/^5.0.0/components/ActorAbstractMediaTyped.jsonld#ActorAbstractMediaTyped__generic_TS"
70
98
  }
71
99
  ]
72
100
  },
73
101
  {
74
102
  "@type": "ParameterRangeGenericTypeReference",
75
- "parameterRangeGenericType": "npmd:@comunica/actor-abstract-mediatyped/^4.0.0/components/ActorAbstractMediaTyped.jsonld#ActorAbstractMediaTyped__generic_I"
103
+ "parameterRangeGenericType": "npmd:@comunica/actor-abstract-mediatyped/^5.0.0/components/ActorAbstractMediaTyped.jsonld#ActorAbstractMediaTyped__generic_I"
76
104
  },
77
105
  {
78
106
  "@type": "ParameterRangeGenericTypeReference",
79
- "parameterRangeGenericType": "npmd:@comunica/actor-abstract-mediatyped/^4.0.0/components/ActorAbstractMediaTyped.jsonld#ActorAbstractMediaTyped__generic_T"
107
+ "parameterRangeGenericType": "npmd:@comunica/actor-abstract-mediatyped/^5.0.0/components/ActorAbstractMediaTyped.jsonld#ActorAbstractMediaTyped__generic_T"
80
108
  },
81
109
  {
82
110
  "@type": "ParameterRangeGenericTypeReference",
83
- "parameterRangeGenericType": "npmd:@comunica/actor-abstract-mediatyped/^4.0.0/components/ActorAbstractMediaTyped.jsonld#ActorAbstractMediaTyped__generic_O"
111
+ "parameterRangeGenericType": "npmd:@comunica/actor-abstract-mediatyped/^5.0.0/components/ActorAbstractMediaTyped.jsonld#ActorAbstractMediaTyped__generic_O"
84
112
  },
85
113
  {
86
114
  "@type": "ParameterRangeGenericTypeReference",
87
- "parameterRangeGenericType": "npmd:@comunica/actor-abstract-mediatyped/^4.0.0/components/ActorAbstractMediaTyped.jsonld#ActorAbstractMediaTyped__generic_TS"
115
+ "parameterRangeGenericType": "npmd:@comunica/actor-abstract-mediatyped/^5.0.0/components/ActorAbstractMediaTyped.jsonld#ActorAbstractMediaTyped__generic_TS"
88
116
  }
89
117
  ]
90
118
  },
@@ -121,19 +149,19 @@
121
149
  "genericTypeInstances": [
122
150
  {
123
151
  "@type": "ParameterRangeGenericTypeReference",
124
- "parameterRangeGenericType": "npmd:@comunica/actor-abstract-mediatyped/^4.0.0/components/ActorAbstractMediaTyped.jsonld#ActorAbstractMediaTyped__generic_I"
152
+ "parameterRangeGenericType": "npmd:@comunica/actor-abstract-mediatyped/^5.0.0/components/ActorAbstractMediaTyped.jsonld#ActorAbstractMediaTyped__generic_I"
125
153
  },
126
154
  {
127
155
  "@type": "ParameterRangeGenericTypeReference",
128
- "parameterRangeGenericType": "npmd:@comunica/actor-abstract-mediatyped/^4.0.0/components/ActorAbstractMediaTyped.jsonld#ActorAbstractMediaTyped__generic_T"
156
+ "parameterRangeGenericType": "npmd:@comunica/actor-abstract-mediatyped/^5.0.0/components/ActorAbstractMediaTyped.jsonld#ActorAbstractMediaTyped__generic_T"
129
157
  },
130
158
  {
131
159
  "@type": "ParameterRangeGenericTypeReference",
132
- "parameterRangeGenericType": "npmd:@comunica/actor-abstract-mediatyped/^4.0.0/components/ActorAbstractMediaTyped.jsonld#ActorAbstractMediaTyped__generic_O"
160
+ "parameterRangeGenericType": "npmd:@comunica/actor-abstract-mediatyped/^5.0.0/components/ActorAbstractMediaTyped.jsonld#ActorAbstractMediaTyped__generic_O"
133
161
  },
134
162
  {
135
163
  "@type": "ParameterRangeGenericTypeReference",
136
- "parameterRangeGenericType": "npmd:@comunica/actor-abstract-mediatyped/^4.0.0/components/ActorAbstractMediaTyped.jsonld#ActorAbstractMediaTyped__generic_TS"
164
+ "parameterRangeGenericType": "npmd:@comunica/actor-abstract-mediatyped/^5.0.0/components/ActorAbstractMediaTyped.jsonld#ActorAbstractMediaTyped__generic_TS"
137
165
  }
138
166
  ]
139
167
  }
@@ -180,6 +208,30 @@
180
208
  {
181
209
  "@id": "cahf:components/ActorHttpFetch.jsonld#ActorHttpFetch_args__constructorArgument",
182
210
  "fields": [
211
+ {
212
+ "keyRaw": "cacheMaxSize",
213
+ "value": {
214
+ "@id": "cahf:components/ActorHttpFetch.jsonld#ActorHttpFetch_args_cacheMaxSize"
215
+ }
216
+ },
217
+ {
218
+ "keyRaw": "cacheMaxCount",
219
+ "value": {
220
+ "@id": "cahf:components/ActorHttpFetch.jsonld#ActorHttpFetch_args_cacheMaxCount"
221
+ }
222
+ },
223
+ {
224
+ "keyRaw": "cacheMaxEntrySize",
225
+ "value": {
226
+ "@id": "cahf:components/ActorHttpFetch.jsonld#ActorHttpFetch_args_cacheMaxEntrySize"
227
+ }
228
+ },
229
+ {
230
+ "keyRaw": "httpInvalidator",
231
+ "value": {
232
+ "@id": "cahf:components/ActorHttpFetch.jsonld#ActorHttpFetch_args_httpInvalidator"
233
+ }
234
+ },
183
235
  {
184
236
  "keyRaw": "agentOptions",
185
237
  "value": {
@@ -220,6 +272,22 @@
220
272
  "requireElement": "IActorHttpFetchArgs",
221
273
  "parameters": [],
222
274
  "memberFields": [
275
+ {
276
+ "@id": "cahf:components/ActorHttpFetch.jsonld#IActorHttpFetchArgs__member_cacheMaxSize",
277
+ "memberFieldName": "cacheMaxSize"
278
+ },
279
+ {
280
+ "@id": "cahf:components/ActorHttpFetch.jsonld#IActorHttpFetchArgs__member_cacheMaxCount",
281
+ "memberFieldName": "cacheMaxCount"
282
+ },
283
+ {
284
+ "@id": "cahf:components/ActorHttpFetch.jsonld#IActorHttpFetchArgs__member_cacheMaxEntrySize",
285
+ "memberFieldName": "cacheMaxEntrySize"
286
+ },
287
+ {
288
+ "@id": "cahf:components/ActorHttpFetch.jsonld#IActorHttpFetchArgs__member_httpInvalidator",
289
+ "memberFieldName": "httpInvalidator"
290
+ },
223
291
  {
224
292
  "@id": "cahf:components/ActorHttpFetch.jsonld#IActorHttpFetchArgs__member_agentOptions",
225
293
  "memberFieldName": "agentOptions"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "@context": [
3
- "https://linkedsoftwaredependencies.org/bundles/npm/@comunica/actor-http-fetch/^4.0.0/components/context.jsonld"
3
+ "https://linkedsoftwaredependencies.org/bundles/npm/@comunica/actor-http-fetch/^5.0.0/components/context.jsonld"
4
4
  ],
5
5
  "@id": "npmd:@comunica/actor-http-fetch",
6
6
  "@type": "Module",
@@ -3,11 +3,23 @@
3
3
  "https://linkedsoftwaredependencies.org/bundles/npm/componentsjs/^6.0.0/components/context.jsonld",
4
4
  {
5
5
  "npmd": "https://linkedsoftwaredependencies.org/bundles/npm/",
6
- "cahf": "npmd:@comunica/actor-http-fetch/^4.0.0/",
6
+ "cahf": "npmd:@comunica/actor-http-fetch/^5.0.0/",
7
7
  "ActorHttpFetch": {
8
8
  "@id": "cahf:components/ActorHttpFetch.jsonld#ActorHttpFetch",
9
9
  "@prefix": true,
10
10
  "@context": {
11
+ "args_cacheMaxSize": {
12
+ "@id": "cahf:components/ActorHttpFetch.jsonld#ActorHttpFetch_args_cacheMaxSize"
13
+ },
14
+ "args_cacheMaxCount": {
15
+ "@id": "cahf:components/ActorHttpFetch.jsonld#ActorHttpFetch_args_cacheMaxCount"
16
+ },
17
+ "args_cacheMaxEntrySize": {
18
+ "@id": "cahf:components/ActorHttpFetch.jsonld#ActorHttpFetch_args_cacheMaxEntrySize"
19
+ },
20
+ "args_httpInvalidator": {
21
+ "@id": "cahf:components/ActorHttpFetch.jsonld#ActorHttpFetch_args_httpInvalidator"
22
+ },
11
23
  "args_agentOptions": {
12
24
  "@id": "cahf:components/ActorHttpFetch.jsonld#ActorHttpFetch_args_agentOptions"
13
25
  },
@@ -24,6 +36,18 @@
24
36
  "@id": "cahf:components/ActorHttpFetch.jsonld#ActorHttpFetch_args_beforeActors",
25
37
  "@container": "@list"
26
38
  },
39
+ "cacheMaxSize": {
40
+ "@id": "cahf:components/ActorHttpFetch.jsonld#ActorHttpFetch_args_cacheMaxSize"
41
+ },
42
+ "cacheMaxCount": {
43
+ "@id": "cahf:components/ActorHttpFetch.jsonld#ActorHttpFetch_args_cacheMaxCount"
44
+ },
45
+ "cacheMaxEntrySize": {
46
+ "@id": "cahf:components/ActorHttpFetch.jsonld#ActorHttpFetch_args_cacheMaxEntrySize"
47
+ },
48
+ "httpInvalidator": {
49
+ "@id": "cahf:components/ActorHttpFetch.jsonld#ActorHttpFetch_args_httpInvalidator"
50
+ },
27
51
  "agentOptions": {
28
52
  "@id": "cahf:components/ActorHttpFetch.jsonld#ActorHttpFetch_args_agentOptions"
29
53
  },
@@ -1,5 +1,6 @@
1
1
  import type { IActionHttp, IActorHttpOutput, IActorHttpArgs } from '@comunica/bus-http';
2
2
  import { ActorHttp } from '@comunica/bus-http';
3
+ import type { ActorHttpInvalidateListenable } from '@comunica/bus-http-invalidate';
3
4
  import type { TestResult } from '@comunica/core';
4
5
  import type { IMediatorTypeTime } from '@comunica/mediatortype-time';
5
6
  export declare class ActorHttpFetch extends ActorHttp {
@@ -24,6 +25,31 @@ export declare class ActorHttpFetch extends ActorHttp {
24
25
  static stringToBase64(value: string): string;
25
26
  }
26
27
  export interface IActorHttpFetchArgs extends IActorHttpArgs {
28
+ /**
29
+ * Maximum size of the cache (in bytes).
30
+ * Defaults to 100MB.
31
+ * @range {integer}
32
+ * @default {104857600}
33
+ */
34
+ cacheMaxSize: number;
35
+ /**
36
+ * Maximum number of documents to store in the cache.
37
+ * @range {integer}
38
+ * @default {1000}
39
+ */
40
+ cacheMaxCount: number;
41
+ /**
42
+ * Maximum size of an entry in the cache (in bytes).
43
+ * Defaults to 5MB.
44
+ * @range {integer}
45
+ * @default {5242880}
46
+ */
47
+ cacheMaxEntrySize: number;
48
+ /**
49
+ * An actor that listens to HTTP invalidation events
50
+ * @default {<default_invalidator> a <npmd:@comunica/bus-http-invalidate/^5.0.0/components/ActorHttpInvalidateListenable.jsonld#ActorHttpInvalidateListenable>}
51
+ */
52
+ httpInvalidator: ActorHttpInvalidateListenable;
27
53
  /**
28
54
  * The agent options for the HTTP agent
29
55
  * @range {json}
@@ -4,13 +4,18 @@ exports.ActorHttpFetch = void 0;
4
4
  const bus_http_1 = require("@comunica/bus-http");
5
5
  const context_entries_1 = require("@comunica/context-entries");
6
6
  const core_1 = require("@comunica/core");
7
+ // eslint-disable-next-line ts/no-require-imports
8
+ const CachePolicy = require("http-cache-semantics");
7
9
  // eslint-disable-next-line import/extensions
8
10
  const package_json_1 = require("../package.json");
11
+ const CachePolicyHttpCacheSemanticsWrapper_1 = require("./CachePolicyHttpCacheSemanticsWrapper");
9
12
  const FetchInitPreprocessor_1 = require("./FetchInitPreprocessor");
10
13
  class ActorHttpFetch extends bus_http_1.ActorHttp {
14
+ fetchInitPreprocessor;
15
+ static userAgent = bus_http_1.ActorHttp.createUserAgent('ActorHttpFetch', package_json_1.version);
11
16
  constructor(args) {
12
17
  super(args);
13
- this.fetchInitPreprocessor = new FetchInitPreprocessor_1.FetchInitPreprocessor(args.agentOptions);
18
+ this.fetchInitPreprocessor = new FetchInitPreprocessor_1.FetchInitPreprocessor(args);
14
19
  }
15
20
  async test(_action) {
16
21
  return (0, core_1.passTest)({ time: Number.POSITIVE_INFINITY });
@@ -32,16 +37,34 @@ class ActorHttpFetch extends bus_http_1.ActorHttp {
32
37
  const httpTimeout = action.context.get(context_entries_1.KeysHttp.httpTimeout);
33
38
  const httpBodyTimeout = action.context.get(context_entries_1.KeysHttp.httpBodyTimeout);
34
39
  const fetchFunction = action.context.get(context_entries_1.KeysHttp.fetch) ?? fetch;
35
- const requestInit = await this.fetchInitPreprocessor.handle(init);
40
+ const requestInit = await this.fetchInitPreprocessor.handle(init, action.context);
36
41
  let timeoutCallback;
37
42
  let timeoutHandle;
43
+ const abortSignal = action.context.get(context_entries_1.KeysHttp.httpAbortSignal);
44
+ if (abortSignal) {
45
+ requestInit.signal = AbortSignal
46
+ .any([...requestInit.signal ? [requestInit.signal] : [], abortSignal]);
47
+ }
38
48
  if (httpTimeout) {
39
49
  const abortController = new AbortController();
40
- requestInit.signal = abortController.signal;
50
+ requestInit.signal = AbortSignal
51
+ .any([...requestInit.signal ? [requestInit.signal] : [], abortController.signal]);
41
52
  timeoutCallback = () => abortController.abort(new Error(`Fetch timed out for ${bus_http_1.ActorHttp.getInputUrl(action.input).href} after ${httpTimeout} ms`));
42
53
  timeoutHandle = setTimeout(() => timeoutCallback(), httpTimeout);
43
54
  }
44
55
  const response = await fetchFunction(action.input, requestInit);
56
+ response.fromCache = response.headers.get('x-comunica-cache') === 'HIT';
57
+ if (response.fromCache) {
58
+ this.logInfo(action.context, `Cache hit for ${bus_http_1.ActorHttp.getInputUrl(action.input).href}`);
59
+ }
60
+ response.cachePolicy = new CachePolicyHttpCacheSemanticsWrapper_1.CachePolicyHttpCacheSemanticsWrapper(new CachePolicy(await CachePolicyHttpCacheSemanticsWrapper_1.CachePolicyHttpCacheSemanticsWrapper.convertFromFetchRequest(action, this.fetchInitPreprocessor), {
61
+ status: response.status,
62
+ headers: bus_http_1.ActorHttp.headersToHash(response.headers),
63
+ }, {
64
+ // Disabled "shared" ensures responses with set-cookie are also cached.
65
+ // For example, for https://www.w3.org/ns/activitystreams
66
+ shared: false,
67
+ }), action.context.get(context_entries_1.KeysInitQuery.queryTimestampHighResolution), this.fetchInitPreprocessor);
45
68
  if (httpTimeout && (!httpBodyTimeout || !response.body)) {
46
69
  clearTimeout(timeoutHandle);
47
70
  }
@@ -82,5 +105,4 @@ class ActorHttpFetch extends bus_http_1.ActorHttp {
82
105
  }
83
106
  }
84
107
  exports.ActorHttpFetch = ActorHttpFetch;
85
- ActorHttpFetch.userAgent = bus_http_1.ActorHttp.createUserAgent('ActorHttpFetch', package_json_1.version);
86
108
  //# sourceMappingURL=ActorHttpFetch.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ActorHttpFetch.js","sourceRoot":"","sources":["ActorHttpFetch.ts"],"names":[],"mappings":"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","sourcesContent":["import type { IActionHttp, IActorHttpOutput, IActorHttpArgs } from '@comunica/bus-http';\nimport { ActorHttp } from '@comunica/bus-http';\nimport { KeysHttp } from '@comunica/context-entries';\nimport type { TestResult } from '@comunica/core';\nimport { passTest } from '@comunica/core';\nimport type { IMediatorTypeTime } from '@comunica/mediatortype-time';\n\n// eslint-disable-next-line import/extensions\nimport { version as actorVersion } from '../package.json';\n\nimport { FetchInitPreprocessor } from './FetchInitPreprocessor';\nimport type { IFetchInitPreprocessor } from './IFetchInitPreprocessor';\n\nexport class ActorHttpFetch extends ActorHttp {\n private readonly fetchInitPreprocessor: IFetchInitPreprocessor;\n\n private static readonly userAgent = ActorHttp.createUserAgent('ActorHttpFetch', actorVersion);\n\n public constructor(args: IActorHttpFetchArgs) {\n super(args);\n this.fetchInitPreprocessor = new FetchInitPreprocessor(args.agentOptions);\n }\n\n public async test(_action: IActionHttp): Promise<TestResult<IMediatorTypeTime>> {\n return passTest({ time: Number.POSITIVE_INFINITY });\n }\n\n public async run(action: IActionHttp): Promise<IActorHttpOutput> {\n const headers = this.prepareRequestHeaders(action);\n\n const init: RequestInit = { method: 'GET', ...action.init, headers };\n\n this.logInfo(action.context, `Requesting ${ActorHttp.getInputUrl(action.input).href}`, () => ({\n headers: ActorHttp.headersToHash(headers),\n method: init.method,\n }));\n\n // TODO: remove this workaround once this has a fix: https://github.com/inrupt/solid-client-authn-js/issues/1708\n if (action.context.has(KeysHttp.fetch)) {\n init.headers = ActorHttp.headersToHash(headers);\n }\n\n if (action.context.get(KeysHttp.includeCredentials)) {\n init.credentials = 'include';\n }\n\n const httpTimeout = action.context.get(KeysHttp.httpTimeout);\n const httpBodyTimeout = action.context.get(KeysHttp.httpBodyTimeout);\n const fetchFunction = action.context.get(KeysHttp.fetch) ?? fetch;\n const requestInit = await this.fetchInitPreprocessor.handle(init);\n\n let timeoutCallback: () => void;\n let timeoutHandle: NodeJS.Timeout | undefined;\n\n if (httpTimeout) {\n const abortController = new AbortController();\n requestInit.signal = abortController.signal;\n timeoutCallback = () => abortController.abort(new Error(`Fetch timed out for ${ActorHttp.getInputUrl(action.input).href} after ${httpTimeout} ms`));\n timeoutHandle = setTimeout(() => timeoutCallback(), httpTimeout);\n }\n\n const response = await fetchFunction(action.input, requestInit);\n\n if (httpTimeout && (!httpBodyTimeout || !response.body)) {\n clearTimeout(timeoutHandle);\n }\n\n return response;\n }\n\n /**\n * Prepares the request headers, taking into account the environment.\n * @param {IActionHttp} action The HTTP action\n * @returns {Headers} Headers\n */\n public prepareRequestHeaders(action: IActionHttp): Headers {\n const headers = new Headers(action.init?.headers);\n\n if (ActorHttp.isBrowser()) {\n // When running in a browser, the User-Agent header should never be set\n headers.delete('user-agent');\n } else if (!headers.has('user-agent')) {\n // Otherwise, if no header value is provided, use the actor one\n headers.set('user-agent', ActorHttpFetch.userAgent!);\n }\n\n const authString = action.context.get(KeysHttp.auth);\n if (authString) {\n headers.set('Authorization', `Basic ${ActorHttpFetch.stringToBase64(authString)}`);\n }\n\n return headers;\n }\n\n /**\n * Converts a string, including ones with Unicode symbols, to Base64 encoding.\n * This function was adapted from the MDN example function here:\n * https://developer.mozilla.org/en-US/docs/Glossary/Base64#the_unicode_problem\n * @param {string} value The string value to encode\n * @returns {string} The Base64-encoded value\n */\n public static stringToBase64(value: string): string {\n const bytes = new TextEncoder().encode(value);\n const binString = Array.from(bytes, byte => String.fromCodePoint(byte)).join('');\n return btoa(binString);\n }\n}\n\nexport interface IActorHttpFetchArgs extends IActorHttpArgs {\n /**\n * The agent options for the HTTP agent\n * @range {json}\n * @default {{ \"keepAlive\": true, \"maxSockets\": 5 }}\n */\n agentOptions?: Record<string, any>;\n}\n"]}
1
+ {"version":3,"file":"ActorHttpFetch.js","sourceRoot":"","sources":["ActorHttpFetch.ts"],"names":[],"mappings":"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","sourcesContent":["import type { IActionHttp, IActorHttpOutput, IActorHttpArgs } from '@comunica/bus-http';\nimport { ActorHttp } from '@comunica/bus-http';\nimport type { ActorHttpInvalidateListenable } from '@comunica/bus-http-invalidate';\nimport { KeysHttp, KeysInitQuery } from '@comunica/context-entries';\nimport type { TestResult } from '@comunica/core';\nimport { passTest } from '@comunica/core';\nimport type { IMediatorTypeTime } from '@comunica/mediatortype-time';\n\n// eslint-disable-next-line ts/no-require-imports\nimport CachePolicy = require('http-cache-semantics');\n\n// eslint-disable-next-line import/extensions\nimport { version as actorVersion } from '../package.json';\n\nimport { CachePolicyHttpCacheSemanticsWrapper } from './CachePolicyHttpCacheSemanticsWrapper';\nimport { FetchInitPreprocessor } from './FetchInitPreprocessor';\nimport type { IFetchInitPreprocessor } from './IFetchInitPreprocessor';\n\nexport class ActorHttpFetch extends ActorHttp {\n private readonly fetchInitPreprocessor: IFetchInitPreprocessor;\n\n private static readonly userAgent = ActorHttp.createUserAgent('ActorHttpFetch', actorVersion);\n\n public constructor(args: IActorHttpFetchArgs) {\n super(args);\n this.fetchInitPreprocessor = new FetchInitPreprocessor(args);\n }\n\n public async test(_action: IActionHttp): Promise<TestResult<IMediatorTypeTime>> {\n return passTest({ time: Number.POSITIVE_INFINITY });\n }\n\n public async run(action: IActionHttp): Promise<IActorHttpOutput> {\n const headers = this.prepareRequestHeaders(action);\n\n const init: RequestInit = { method: 'GET', ...action.init, headers };\n\n this.logInfo(action.context, `Requesting ${ActorHttp.getInputUrl(action.input).href}`, () => ({\n headers: ActorHttp.headersToHash(headers),\n method: init.method,\n }));\n\n // TODO: remove this workaround once this has a fix: https://github.com/inrupt/solid-client-authn-js/issues/1708\n if (action.context.has(KeysHttp.fetch)) {\n init.headers = ActorHttp.headersToHash(headers);\n }\n\n if (action.context.get(KeysHttp.includeCredentials)) {\n init.credentials = 'include';\n }\n\n const httpTimeout = action.context.get(KeysHttp.httpTimeout);\n const httpBodyTimeout = action.context.get(KeysHttp.httpBodyTimeout);\n const fetchFunction = action.context.get(KeysHttp.fetch) ?? fetch;\n const requestInit = await this.fetchInitPreprocessor.handle(init, action.context);\n\n let timeoutCallback: () => void;\n let timeoutHandle: NodeJS.Timeout | undefined;\n\n const abortSignal = action.context.get(KeysHttp.httpAbortSignal);\n if (abortSignal) {\n requestInit.signal = AbortSignal\n .any([ ...requestInit.signal ? [ requestInit.signal ] : [], abortSignal ]);\n }\n\n if (httpTimeout) {\n const abortController = new AbortController();\n requestInit.signal = AbortSignal\n .any([ ...requestInit.signal ? [ requestInit.signal ] : [], abortController.signal ]);\n timeoutCallback = () => abortController.abort(new Error(`Fetch timed out for ${ActorHttp.getInputUrl(action.input).href} after ${httpTimeout} ms`));\n timeoutHandle = setTimeout(() => timeoutCallback(), httpTimeout);\n }\n\n const response: IActorHttpOutput = await fetchFunction(action.input, requestInit);\n\n response.fromCache = response.headers.get('x-comunica-cache') === 'HIT';\n if (response.fromCache) {\n this.logInfo(action.context, `Cache hit for ${ActorHttp.getInputUrl(action.input).href}`);\n }\n\n response.cachePolicy = new CachePolicyHttpCacheSemanticsWrapper(new CachePolicy(\n await CachePolicyHttpCacheSemanticsWrapper.convertFromFetchRequest(action, this.fetchInitPreprocessor),\n {\n status: response.status,\n headers: ActorHttp.headersToHash(response.headers),\n },\n {\n // Disabled \"shared\" ensures responses with set-cookie are also cached.\n // For example, for https://www.w3.org/ns/activitystreams\n shared: false,\n },\n ), action.context.get(KeysInitQuery.queryTimestampHighResolution), this.fetchInitPreprocessor);\n\n if (httpTimeout && (!httpBodyTimeout || !response.body)) {\n clearTimeout(timeoutHandle);\n }\n\n return response;\n }\n\n /**\n * Prepares the request headers, taking into account the environment.\n * @param {IActionHttp} action The HTTP action\n * @returns {Headers} Headers\n */\n public prepareRequestHeaders(action: IActionHttp): Headers {\n const headers = new Headers(action.init?.headers);\n\n if (ActorHttp.isBrowser()) {\n // When running in a browser, the User-Agent header should never be set\n headers.delete('user-agent');\n } else if (!headers.has('user-agent')) {\n // Otherwise, if no header value is provided, use the actor one\n headers.set('user-agent', ActorHttpFetch.userAgent!);\n }\n\n const authString = action.context.get(KeysHttp.auth);\n if (authString) {\n headers.set('Authorization', `Basic ${ActorHttpFetch.stringToBase64(authString)}`);\n }\n\n return headers;\n }\n\n /**\n * Converts a string, including ones with Unicode symbols, to Base64 encoding.\n * This function was adapted from the MDN example function here:\n * https://developer.mozilla.org/en-US/docs/Glossary/Base64#the_unicode_problem\n * @param {string} value The string value to encode\n * @returns {string} The Base64-encoded value\n */\n public static stringToBase64(value: string): string {\n const bytes = new TextEncoder().encode(value);\n const binString = Array.from(bytes, byte => String.fromCodePoint(byte)).join('');\n return btoa(binString);\n }\n}\n\nexport interface IActorHttpFetchArgs extends IActorHttpArgs {\n /**\n * Maximum size of the cache (in bytes).\n * Defaults to 100MB.\n * @range {integer}\n * @default {104857600}\n */\n cacheMaxSize: number;\n /**\n * Maximum number of documents to store in the cache.\n * @range {integer}\n * @default {1000}\n */\n cacheMaxCount: number;\n /**\n * Maximum size of an entry in the cache (in bytes).\n * Defaults to 5MB.\n * @range {integer}\n * @default {5242880}\n */\n cacheMaxEntrySize: number;\n /* eslint-disable max-len */\n /**\n * An actor that listens to HTTP invalidation events\n * @default {<default_invalidator> a <npmd:@comunica/bus-http-invalidate/^5.0.0/components/ActorHttpInvalidateListenable.jsonld#ActorHttpInvalidateListenable>}\n */\n httpInvalidator: ActorHttpInvalidateListenable;\n /* eslint-enable max-len */\n /**\n * The agent options for the HTTP agent\n * @range {json}\n * @default {{ \"keepAlive\": true, \"maxSockets\": 5 }}\n */\n agentOptions?: Record<string, any>;\n}\n"]}
@@ -0,0 +1,21 @@
1
+ import { type IActionHttp } from '@comunica/bus-http';
2
+ import type { ICachePolicy, ICacheResponseHead, IRevalidationPolicy } from '@comunica/types';
3
+ import CachePolicy = require('http-cache-semantics');
4
+ import type { IFetchInitPreprocessor } from './IFetchInitPreprocessor';
5
+ /**
6
+ * Wrapper over the cache policy of http-cache-semantics to expose it as an ICachePolicy.
7
+ */
8
+ export declare class CachePolicyHttpCacheSemanticsWrapper implements ICachePolicy<IActionHttp> {
9
+ private readonly cachePolicy;
10
+ private readonly queryTimestamp;
11
+ private readonly fetchInitPreprocessor;
12
+ constructor(cachePolicy: CachePolicy, queryTimestamp: number | undefined, fetchInitPreprocessor: IFetchInitPreprocessor);
13
+ storable(): boolean;
14
+ satisfiesWithoutRevalidation(action: IActionHttp): Promise<boolean>;
15
+ responseHeaders(): Headers;
16
+ timeToLive(): number;
17
+ revalidationHeaders(newAction: IActionHttp): Promise<Headers>;
18
+ revalidatedPolicy(revalidationAction: IActionHttp, revalidationResponse: ICacheResponseHead): Promise<IRevalidationPolicy<IActionHttp>>;
19
+ static convertFromFetchRequest(request: IActionHttp, fetchInitPreprocessor: IFetchInitPreprocessor): Promise<CachePolicy.Request>;
20
+ static convertToFetchHeaders(headers: CachePolicy.Headers): Headers;
21
+ }
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CachePolicyHttpCacheSemanticsWrapper = void 0;
4
+ const bus_http_1 = require("@comunica/bus-http");
5
+ const context_entries_1 = require("@comunica/context-entries");
6
+ /**
7
+ * Wrapper over the cache policy of http-cache-semantics to expose it as an ICachePolicy.
8
+ */
9
+ class CachePolicyHttpCacheSemanticsWrapper {
10
+ cachePolicy;
11
+ queryTimestamp;
12
+ fetchInitPreprocessor;
13
+ constructor(cachePolicy, queryTimestamp, fetchInitPreprocessor) {
14
+ this.cachePolicy = cachePolicy;
15
+ this.queryTimestamp = queryTimestamp;
16
+ this.fetchInitPreprocessor = fetchInitPreprocessor;
17
+ }
18
+ storable() {
19
+ return this.cachePolicy.storable();
20
+ }
21
+ async satisfiesWithoutRevalidation(action) {
22
+ // We always allow full caching within the context of a single query execution
23
+ if (this.queryTimestamp && action.context.get(context_entries_1.KeysInitQuery.queryTimestampHighResolution) === this.queryTimestamp) {
24
+ return true;
25
+ }
26
+ // Otherwise, determine through cache policy
27
+ return this.cachePolicy.satisfiesWithoutRevalidation(await CachePolicyHttpCacheSemanticsWrapper
28
+ .convertFromFetchRequest(action, this.fetchInitPreprocessor));
29
+ }
30
+ responseHeaders() {
31
+ return CachePolicyHttpCacheSemanticsWrapper.convertToFetchHeaders(this.cachePolicy.responseHeaders());
32
+ }
33
+ timeToLive() {
34
+ return this.cachePolicy.timeToLive();
35
+ }
36
+ async revalidationHeaders(newAction) {
37
+ return CachePolicyHttpCacheSemanticsWrapper.convertToFetchHeaders(this.cachePolicy
38
+ .revalidationHeaders(await CachePolicyHttpCacheSemanticsWrapper
39
+ .convertFromFetchRequest(newAction, this.fetchInitPreprocessor)));
40
+ }
41
+ async revalidatedPolicy(revalidationAction, revalidationResponse) {
42
+ const revalidatedPolicy = this.cachePolicy.revalidatedPolicy(await CachePolicyHttpCacheSemanticsWrapper
43
+ .convertFromFetchRequest(revalidationAction, this.fetchInitPreprocessor), {
44
+ status: revalidationResponse.status,
45
+ headers: revalidationResponse.headers ? bus_http_1.ActorHttp.headersToHash(revalidationResponse.headers) : {},
46
+ });
47
+ return {
48
+ policy: new CachePolicyHttpCacheSemanticsWrapper(revalidatedPolicy.policy, this.queryTimestamp, this.fetchInitPreprocessor),
49
+ modified: revalidatedPolicy.modified,
50
+ matches: revalidatedPolicy.matches,
51
+ };
52
+ }
53
+ static async convertFromFetchRequest(request, fetchInitPreprocessor) {
54
+ let headers = typeof request.input === 'string' ? request.init?.headers : request.input.headers;
55
+ headers = (await fetchInitPreprocessor.handle({ headers }, request.context)).headers;
56
+ return {
57
+ url: typeof request.input === 'string' ? request.input : request.input.url,
58
+ method: request.init?.method ?? 'GET',
59
+ headers: headers ? bus_http_1.ActorHttp.headersToHash(new Headers(headers)) : {},
60
+ };
61
+ }
62
+ static convertToFetchHeaders(headers) {
63
+ const fetchHeaders = new Headers();
64
+ for (const [key, value] of Object.entries(headers)) {
65
+ if (Array.isArray(value)) {
66
+ for (const valueEntry of value) {
67
+ fetchHeaders.append(key, valueEntry);
68
+ }
69
+ }
70
+ else if (value) {
71
+ fetchHeaders.append(key, value);
72
+ }
73
+ }
74
+ return fetchHeaders;
75
+ }
76
+ }
77
+ exports.CachePolicyHttpCacheSemanticsWrapper = CachePolicyHttpCacheSemanticsWrapper;
78
+ //# sourceMappingURL=CachePolicyHttpCacheSemanticsWrapper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CachePolicyHttpCacheSemanticsWrapper.js","sourceRoot":"","sources":["CachePolicyHttpCacheSemanticsWrapper.ts"],"names":[],"mappings":"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","sourcesContent":["import { ActorHttp, type IActionHttp } from '@comunica/bus-http';\nimport { KeysInitQuery } from '@comunica/context-entries';\nimport type { ICachePolicy, ICacheResponseHead, IRevalidationPolicy } from '@comunica/types';\n\n// eslint-disable-next-line ts/no-require-imports\nimport CachePolicy = require('http-cache-semantics');\nimport type { IFetchInitPreprocessor } from './IFetchInitPreprocessor';\n\n/**\n * Wrapper over the cache policy of http-cache-semantics to expose it as an ICachePolicy.\n */\nexport class CachePolicyHttpCacheSemanticsWrapper implements ICachePolicy<IActionHttp> {\n public constructor(\n private readonly cachePolicy: CachePolicy,\n private readonly queryTimestamp: number | undefined,\n private readonly fetchInitPreprocessor: IFetchInitPreprocessor,\n ) {}\n\n public storable(): boolean {\n return this.cachePolicy.storable();\n }\n\n public async satisfiesWithoutRevalidation(action: IActionHttp): Promise<boolean> {\n // We always allow full caching within the context of a single query execution\n if (this.queryTimestamp && action.context.get(KeysInitQuery.queryTimestampHighResolution) === this.queryTimestamp) {\n return true;\n }\n // Otherwise, determine through cache policy\n return this.cachePolicy.satisfiesWithoutRevalidation(await CachePolicyHttpCacheSemanticsWrapper\n .convertFromFetchRequest(action, this.fetchInitPreprocessor));\n }\n\n public responseHeaders(): Headers {\n return CachePolicyHttpCacheSemanticsWrapper.convertToFetchHeaders(this.cachePolicy.responseHeaders());\n }\n\n public timeToLive(): number {\n return this.cachePolicy.timeToLive();\n }\n\n public async revalidationHeaders(newAction: IActionHttp): Promise<Headers> {\n return CachePolicyHttpCacheSemanticsWrapper.convertToFetchHeaders(this.cachePolicy\n .revalidationHeaders(await CachePolicyHttpCacheSemanticsWrapper\n .convertFromFetchRequest(newAction, this.fetchInitPreprocessor)));\n }\n\n public async revalidatedPolicy(\n revalidationAction: IActionHttp,\n revalidationResponse: ICacheResponseHead,\n ): Promise<IRevalidationPolicy<IActionHttp>> {\n const revalidatedPolicy = this.cachePolicy.revalidatedPolicy(\n await CachePolicyHttpCacheSemanticsWrapper\n .convertFromFetchRequest(revalidationAction, this.fetchInitPreprocessor),\n {\n status: revalidationResponse.status,\n headers: revalidationResponse.headers ? ActorHttp.headersToHash(revalidationResponse.headers) : {},\n },\n );\n return {\n policy: new CachePolicyHttpCacheSemanticsWrapper(\n revalidatedPolicy.policy,\n this.queryTimestamp,\n this.fetchInitPreprocessor,\n ),\n modified: revalidatedPolicy.modified,\n matches: revalidatedPolicy.matches,\n };\n }\n\n public static async convertFromFetchRequest(\n request: IActionHttp,\n fetchInitPreprocessor: IFetchInitPreprocessor,\n ): Promise<CachePolicy.Request> {\n let headers = typeof request.input === 'string' ? request.init?.headers : request.input.headers;\n headers = (await fetchInitPreprocessor.handle({ headers }, request.context)).headers;\n return {\n url: typeof request.input === 'string' ? request.input : request.input.url,\n method: request.init?.method ?? 'GET',\n headers: headers ? ActorHttp.headersToHash(new Headers(headers)) : {},\n };\n }\n\n public static convertToFetchHeaders(headers: CachePolicy.Headers): Headers {\n const fetchHeaders = new Headers();\n for (const [ key, value ] of Object.entries(headers)) {\n if (Array.isArray(value)) {\n for (const valueEntry of value) {\n fetchHeaders.append(key, valueEntry);\n }\n } else if (value) {\n fetchHeaders.append(key, value);\n }\n }\n return fetchHeaders;\n }\n}\n"]}
File without changes
File without changes
File without changes
@@ -1,13 +1,19 @@
1
- /// <reference types="node" />
2
1
  import { Agent as HttpAgent } from 'node:http';
2
+ import type { IActionContext } from '@comunica/types';
3
+ import type { Dispatcher } from 'undici';
4
+ import type { IActorHttpFetchArgs } from './ActorHttpFetch';
3
5
  import type { IFetchInitPreprocessor } from './IFetchInitPreprocessor';
4
6
  /**
5
7
  * Overrides the HTTP agent to perform better in Node.js.
6
8
  */
7
9
  export declare class FetchInitPreprocessor implements IFetchInitPreprocessor {
8
10
  private readonly agent;
9
- constructor(agentOptions: any);
10
- handle(init: RequestInit): Promise<RequestInit & {
11
+ private dispatcher;
12
+ private cache;
13
+ constructor(args: IActorHttpFetchArgs);
14
+ protected createCache(args: IActorHttpFetchArgs): void;
15
+ handle(init: RequestInit, context: IActionContext): Promise<RequestInit & {
11
16
  agent: (url: URL) => HttpAgent;
17
+ dispatcher?: Dispatcher;
12
18
  }>;
13
19
  }
@@ -4,16 +4,47 @@ exports.FetchInitPreprocessor = void 0;
4
4
  /* eslint-disable import/no-nodejs-modules */
5
5
  const node_http_1 = require("node:http");
6
6
  const node_https_1 = require("node:https");
7
+ const context_entries_1 = require("@comunica/context-entries");
8
+ const undici_1 = require("undici");
9
+ const MetadataWrappingCacheStore_1 = require("./MetadataWrappingCacheStore");
10
+ // eslint-disable-next-line ts/no-require-imports,ts/no-var-requires
11
+ const cacheStores = require('undici').cacheStores;
12
+ // TODO: the require above can be replaced with import when undici updates.
7
13
  /**
8
14
  * Overrides the HTTP agent to perform better in Node.js.
9
15
  */
10
16
  class FetchInitPreprocessor {
11
- constructor(agentOptions) {
12
- const httpAgent = new node_http_1.Agent(agentOptions);
13
- const httpsAgent = new node_https_1.Agent(agentOptions);
17
+ agent;
18
+ dispatcher;
19
+ cache;
20
+ constructor(args) {
21
+ const httpAgent = new node_http_1.Agent(args.agentOptions);
22
+ const httpsAgent = new node_https_1.Agent(args.agentOptions);
14
23
  this.agent = (_parsedURL) => _parsedURL.protocol === 'http:' ? httpAgent : httpsAgent;
24
+ this.createCache(args);
25
+ args.httpInvalidator.addInvalidateListener(({ url }) => {
26
+ if (url) {
27
+ const parsedUrl = new URL(url);
28
+ // eslint-disable-next-line ts/no-floating-promises
29
+ this.cache.delete({ origin: parsedUrl.origin, path: parsedUrl.pathname + parsedUrl.search, method: 'GET' });
30
+ }
31
+ else {
32
+ this.createCache(args);
33
+ }
34
+ });
15
35
  }
16
- async handle(init) {
36
+ createCache(args) {
37
+ this.cache = new cacheStores.MemoryCacheStore({
38
+ maxSize: args.cacheMaxSize,
39
+ maxCount: args.cacheMaxCount,
40
+ maxEntrySize: args.cacheMaxEntrySize,
41
+ });
42
+ this.dispatcher = new undici_1.Agent().compose(undici_1.interceptors.cache({
43
+ store: new MetadataWrappingCacheStore_1.MetadataWrappingCacheStore(this.cache),
44
+ methods: ['GET', 'HEAD'],
45
+ }));
46
+ }
47
+ async handle(init, context) {
17
48
  // Add 'Accept-Encoding' headers
18
49
  const headers = new Headers(init.headers);
19
50
  if (!headers.has('Accept-Encoding')) {
@@ -27,6 +58,7 @@ class FetchInitPreprocessor {
27
58
  ...init,
28
59
  ...init.body ? { keepalive: false, duplex: 'half' } : { keepalive: true },
29
60
  agent: this.agent,
61
+ dispatcher: context.get(context_entries_1.KeysHttp.httpCache) ? this.dispatcher : undefined,
30
62
  };
31
63
  }
32
64
  }
@@ -1 +1 @@
1
- {"version":3,"file":"FetchInitPreprocessor.js","sourceRoot":"","sources":["FetchInitPreprocessor.ts"],"names":[],"mappings":";;;AAAA,6CAA6C;AAC7C,yCAA+C;AAC/C,2CAAiD;AAKjD;;GAEG;AACH,MAAa,qBAAqB;IAGhC,YAAmB,YAAiB;QAClC,MAAM,SAAS,GAAG,IAAI,iBAAS,CAAC,YAAY,CAAC,CAAC;QAC9C,MAAM,UAAU,GAAG,IAAI,kBAAU,CAAC,YAAY,CAAC,CAAC;QAChD,IAAI,CAAC,KAAK,GAAG,CAAC,UAAe,EAAa,EAAE,CAAC,UAAU,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC;IACxG,CAAC;IAEM,KAAK,CAAC,MAAM,CAAC,IAAiB;QACnC,gCAAgC;QAChC,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC1C,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,EAAE,CAAC;YACpC,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,iBAAiB,CAAC,CAAC;YAClD,IAAI,GAAG,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,CAAC;QAC9B,CAAC;QAED,+EAA+E;QAC/E,gCAAgC;QAChC,mCAAmC;QACnC,OAAO;YACL,GAAG,IAAI;YACP,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE;YACzE,KAAK,EAAE,IAAI,CAAC,KAAK;SAClB,CAAC;IACJ,CAAC;CACF;AA1BD,sDA0BC","sourcesContent":["/* eslint-disable import/no-nodejs-modules */\nimport { Agent as HttpAgent } from 'node:http';\nimport { Agent as HttpsAgent } from 'node:https';\n\n/* eslint-enable import/no-nodejs-modules */\nimport type { IFetchInitPreprocessor } from './IFetchInitPreprocessor';\n\n/**\n * Overrides the HTTP agent to perform better in Node.js.\n */\nexport class FetchInitPreprocessor implements IFetchInitPreprocessor {\n private readonly agent: (url: URL) => HttpAgent;\n\n public constructor(agentOptions: any) {\n const httpAgent = new HttpAgent(agentOptions);\n const httpsAgent = new HttpsAgent(agentOptions);\n this.agent = (_parsedURL: URL): HttpAgent => _parsedURL.protocol === 'http:' ? httpAgent : httpsAgent;\n }\n\n public async handle(init: RequestInit): Promise<RequestInit & { agent: (url: URL) => HttpAgent }> {\n // Add 'Accept-Encoding' headers\n const headers = new Headers(init.headers);\n if (!headers.has('Accept-Encoding')) {\n headers.set('Accept-Encoding', 'br,gzip,deflate');\n init = { ...init, headers };\n }\n\n // The Fetch API requires specific options to be set when sending body streams:\n // - 'keepalive' can not be true\n // - 'duplex' must be set to 'half'\n return {\n ...init,\n ...init.body ? { keepalive: false, duplex: 'half' } : { keepalive: true },\n agent: this.agent,\n };\n }\n}\n"]}
1
+ {"version":3,"file":"FetchInitPreprocessor.js","sourceRoot":"","sources":["FetchInitPreprocessor.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable import/no-nodejs-modules */\nimport { Agent as HttpAgent } from 'node:http';\nimport { Agent as HttpsAgent } from 'node:https';\nimport type { IActionHttpInvalidate } from '@comunica/bus-http-invalidate';\nimport { KeysHttp } from '@comunica/context-entries';\nimport type { IActionContext } from '@comunica/types';\nimport type { Dispatcher } from 'undici';\nimport { Agent, interceptors } from 'undici';\n\n/* eslint-enable import/no-nodejs-modules */\nimport CacheHandler from 'undici/types/cache-interceptor';\nimport type { IActorHttpFetchArgs } from './ActorHttpFetch';\nimport type { IFetchInitPreprocessor } from './IFetchInitPreprocessor';\nimport { MetadataWrappingCacheStore } from './MetadataWrappingCacheStore';\nimport CacheStore = CacheHandler.CacheStore;\n\n// eslint-disable-next-line ts/no-require-imports,ts/no-var-requires\nconst cacheStores = require('undici').cacheStores;\n// TODO: the require above can be replaced with import when undici updates.\n\n/**\n * Overrides the HTTP agent to perform better in Node.js.\n */\nexport class FetchInitPreprocessor implements IFetchInitPreprocessor {\n private readonly agent: (url: URL) => HttpAgent;\n private dispatcher!: Dispatcher;\n private cache!: CacheStore;\n\n public constructor(args: IActorHttpFetchArgs) {\n const httpAgent = new HttpAgent(args.agentOptions);\n const httpsAgent = new HttpsAgent(args.agentOptions);\n this.agent = (_parsedURL: URL): HttpAgent => _parsedURL.protocol === 'http:' ? httpAgent : httpsAgent;\n this.createCache(args);\n args.httpInvalidator.addInvalidateListener(\n ({ url }: IActionHttpInvalidate) => {\n if (url) {\n const parsedUrl = new URL(url);\n // eslint-disable-next-line ts/no-floating-promises\n this.cache.delete({ origin: parsedUrl.origin, path: parsedUrl.pathname + parsedUrl.search, method: 'GET' });\n } else {\n this.createCache(args);\n }\n },\n );\n }\n\n protected createCache(args: IActorHttpFetchArgs): void {\n this.cache = new cacheStores.MemoryCacheStore({\n maxSize: args.cacheMaxSize,\n maxCount: args.cacheMaxCount,\n maxEntrySize: args.cacheMaxEntrySize,\n });\n this.dispatcher = new Agent().compose(interceptors.cache({\n store: new MetadataWrappingCacheStore(this.cache),\n methods: [ 'GET', 'HEAD' ],\n }));\n }\n\n public async handle(\n init: RequestInit,\n context: IActionContext,\n ): Promise<RequestInit & { agent: (url: URL) => HttpAgent; dispatcher?: Dispatcher }> {\n // Add 'Accept-Encoding' headers\n const headers = new Headers(init.headers);\n if (!headers.has('Accept-Encoding')) {\n headers.set('Accept-Encoding', 'br,gzip,deflate');\n init = { ...init, headers };\n }\n\n // The Fetch API requires specific options to be set when sending body streams:\n // - 'keepalive' can not be true\n // - 'duplex' must be set to 'half'\n return {\n ...init,\n ...init.body ? { keepalive: false, duplex: 'half' } : { keepalive: true },\n agent: this.agent,\n dispatcher: context.get(KeysHttp.httpCache) ? this.dispatcher : undefined,\n };\n }\n}\n"]}
@@ -1,6 +1,7 @@
1
+ import type { IActionContext } from '@comunica/types';
1
2
  /**
2
3
  * Can modify a fetch init object.
3
4
  */
4
5
  export interface IFetchInitPreprocessor {
5
- handle: (init: RequestInit) => Promise<RequestInit>;
6
+ handle: (init: RequestInit, context: IActionContext) => Promise<RequestInit>;
6
7
  }
File without changes
@@ -1 +1 @@
1
- {"version":3,"file":"IFetchInitPreprocessor.js","sourceRoot":"","sources":["IFetchInitPreprocessor.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * Can modify a fetch init object.\n */\nexport interface IFetchInitPreprocessor {\n handle: (init: RequestInit) => Promise<RequestInit>;\n}\n"]}
1
+ {"version":3,"file":"IFetchInitPreprocessor.js","sourceRoot":"","sources":["IFetchInitPreprocessor.ts"],"names":[],"mappings":"","sourcesContent":["import type { IActionContext } from '@comunica/types';\n\n/**\n * Can modify a fetch init object.\n */\nexport interface IFetchInitPreprocessor {\n handle: (init: RequestInit, context: IActionContext) => Promise<RequestInit>;\n}\n"]}
@@ -0,0 +1,13 @@
1
+ import type { Writable } from 'node:stream';
2
+ import CacheHandler from 'undici/types/cache-interceptor';
3
+ import CacheStore = CacheHandler.CacheStore;
4
+ /**
5
+ * A wrapper around a cache store that adds the `x-comunica-cache: HIT` header to cached responses.
6
+ */
7
+ export declare class MetadataWrappingCacheStore implements CacheStore {
8
+ private readonly cacheStore;
9
+ constructor(cacheStore: CacheStore);
10
+ get(key: CacheHandler.CacheKey): Promise<CacheHandler.GetResult | undefined>;
11
+ createWriteStream(key: CacheHandler.CacheKey, val: CacheHandler.CacheValue): Writable | undefined;
12
+ delete(key: CacheHandler.CacheKey): void | Promise<void>;
13
+ }
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MetadataWrappingCacheStore = void 0;
4
+ /**
5
+ * A wrapper around a cache store that adds the `x-comunica-cache: HIT` header to cached responses.
6
+ */
7
+ class MetadataWrappingCacheStore {
8
+ cacheStore;
9
+ constructor(cacheStore) {
10
+ this.cacheStore = cacheStore;
11
+ }
12
+ async get(key) {
13
+ const ret = await this.cacheStore.get(key);
14
+ if (ret) {
15
+ ret.headers['x-comunica-cache'] = 'HIT';
16
+ }
17
+ return ret;
18
+ }
19
+ createWriteStream(key, val) {
20
+ return this.cacheStore.createWriteStream(key, val);
21
+ }
22
+ delete(key) {
23
+ return this.cacheStore.delete(key);
24
+ }
25
+ }
26
+ exports.MetadataWrappingCacheStore = MetadataWrappingCacheStore;
27
+ //# sourceMappingURL=MetadataWrappingCacheStore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MetadataWrappingCacheStore.js","sourceRoot":"","sources":["MetadataWrappingCacheStore.ts"],"names":[],"mappings":";;;AAKA;;GAEG;AACH,MAAa,0BAA0B;IACD;IAApC,YAAoC,UAAsB;QAAtB,eAAU,GAAV,UAAU,CAAY;IAAG,CAAC;IAEvD,KAAK,CAAC,GAAG,CAAC,GAA0B;QACzC,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAE,CAAC;QAC5C,IAAI,GAAG,EAAE,CAAC;YACR,GAAG,CAAC,OAAO,CAAC,kBAAkB,CAAC,GAAG,KAAK,CAAC;QAC1C,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAEM,iBAAiB,CAAC,GAA0B,EAAE,GAA4B;QAC/E,OAAO,IAAI,CAAC,UAAU,CAAC,iBAAiB,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IACrD,CAAC;IAEM,MAAM,CAAC,GAA0B;QACtC,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACrC,CAAC;CACF;AAlBD,gEAkBC","sourcesContent":["// eslint-disable-next-line import/no-nodejs-modules\nimport type { Writable } from 'node:stream';\nimport CacheHandler from 'undici/types/cache-interceptor';\nimport CacheStore = CacheHandler.CacheStore;\n\n/**\n * A wrapper around a cache store that adds the `x-comunica-cache: HIT` header to cached responses.\n */\nexport class MetadataWrappingCacheStore implements CacheStore {\n public constructor(private readonly cacheStore: CacheStore) {}\n\n public async get(key: CacheHandler.CacheKey): Promise<CacheHandler.GetResult | undefined> {\n const ret = await this.cacheStore.get(key)!;\n if (ret) {\n ret.headers['x-comunica-cache'] = 'HIT';\n }\n return ret;\n }\n\n public createWriteStream(key: CacheHandler.CacheKey, val: CacheHandler.CacheValue): Writable | undefined {\n return this.cacheStore.createWriteStream(key, val);\n }\n\n public delete(key: CacheHandler.CacheKey): void | Promise<void> {\n return this.cacheStore.delete(key);\n }\n}\n"]}
package/lib/index.d.ts CHANGED
@@ -1 +1,2 @@
1
1
  export * from './ActorHttpFetch';
2
+ export * from './CachePolicyHttpCacheSemanticsWrapper';
package/lib/index.js CHANGED
@@ -15,4 +15,5 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./ActorHttpFetch"), exports);
18
+ __exportStar(require("./CachePolicyHttpCacheSemanticsWrapper"), exports);
18
19
  //# sourceMappingURL=index.js.map
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,mDAAiC","sourcesContent":["export * from './ActorHttpFetch';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,mDAAiC;AACjC,yEAAuD","sourcesContent":["export * from './ActorHttpFetch';\nexport * from './CachePolicyHttpCacheSemanticsWrapper';\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@comunica/actor-http-fetch",
3
- "version": "4.5.0",
3
+ "version": "5.0.2",
4
4
  "description": "A fetch http actor",
5
5
  "lsd:module": true,
6
6
  "license": "MIT",
@@ -39,13 +39,18 @@
39
39
  "build:components": "componentsjs-generator"
40
40
  },
41
41
  "dependencies": {
42
- "@comunica/bus-http": "^4.5.0",
43
- "@comunica/context-entries": "^4.5.0",
44
- "@comunica/core": "^4.5.0",
45
- "@comunica/mediatortype-time": "^4.5.0"
42
+ "@comunica/bus-http": "^5.0.2",
43
+ "@comunica/bus-http-invalidate": "^5.0.2",
44
+ "@comunica/context-entries": "^5.0.2",
45
+ "@comunica/core": "^5.0.2",
46
+ "@comunica/mediatortype-time": "^5.0.2",
47
+ "@comunica/types": "^5.0.0",
48
+ "@types/http-cache-semantics": "^4.0.4",
49
+ "http-cache-semantics": "^4.2.0",
50
+ "undici": "^7.16.0"
46
51
  },
47
52
  "browser": {
48
53
  "./lib/FetchInitPreprocessor.js": "./lib/FetchInitPreprocessor-browser.js"
49
54
  },
50
- "gitHead": "2bcd98c387a021fc5c08d375793c205ca3d1bf0d"
55
+ "gitHead": "3b29f914010fd2fc56682a0ceff962ef6ff24f32"
51
56
  }