@fedify/fedify 1.6.0-dev.777 → 1.6.0-dev.790
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/CHANGES.md +17 -0
- package/CONTRIBUTING.md +7 -0
- package/README.md +1 -1
- package/SPONSORS.md +1 -1
- package/esm/deno.js +3 -1
- package/esm/deps/jsr.io/@std/crypto/1.0.4/timing_safe_equal.js +55 -0
- package/esm/federation/builder.js +1 -0
- package/esm/federation/handler.js +1 -1
- package/esm/federation/middleware.js +31 -3
- package/esm/federation/send.js +6 -7
- package/esm/runtime/docloader.js +4 -16
- package/esm/sig/http.js +528 -9
- package/esm/sig/key.js +4 -1
- package/esm/testing/fixtures/remote.domain/users/bob +20 -0
- package/esm/vocab/vocab.js +308 -176
- package/package.json +2 -1
- package/types/deno.d.ts +2 -0
- package/types/deps/jsr.io/@std/crypto/1.0.4/timing_safe_equal.d.ts +34 -0
- package/types/deps/jsr.io/@std/crypto/1.0.4/timing_safe_equal.d.ts.map +1 -0
- package/types/deps/jsr.io/@std/http/{1.0.14 → 1.0.15}/_negotiation/common.d.ts.map +1 -1
- package/types/deps/jsr.io/@std/http/{1.0.14 → 1.0.15}/_negotiation/encoding.d.ts.map +1 -1
- package/types/deps/jsr.io/@std/http/{1.0.14 → 1.0.15}/_negotiation/language.d.ts.map +1 -1
- package/types/deps/jsr.io/@std/http/{1.0.14 → 1.0.15}/_negotiation/media_type.d.ts.map +1 -1
- package/types/deps/jsr.io/@std/http/{1.0.14 → 1.0.15}/negotiation.d.ts.map +1 -1
- package/types/federation/builder.d.ts.map +1 -1
- package/types/federation/middleware.d.ts +22 -3
- package/types/federation/middleware.d.ts.map +1 -1
- package/types/federation/send.d.ts +6 -0
- package/types/federation/send.d.ts.map +1 -1
- package/types/runtime/docloader.d.ts +17 -1
- package/types/runtime/docloader.d.ts.map +1 -1
- package/types/sig/http.d.ts +128 -0
- package/types/sig/http.d.ts.map +1 -1
- package/types/sig/key.d.ts.map +1 -1
- package/types/sig/mod.d.ts +1 -1
- package/types/sig/mod.d.ts.map +1 -1
- package/types/vocab/vocab.d.ts.map +1 -1
- package/esm/deps/jsr.io/@std/bytes/1.0.5/copy.js +0 -50
- package/esm/deps/jsr.io/@std/bytes/1.0.5/ends_with.js +0 -36
- package/esm/deps/jsr.io/@std/bytes/1.0.5/equals.js +0 -82
- package/esm/deps/jsr.io/@std/bytes/1.0.5/includes_needle.js +0 -42
- package/esm/deps/jsr.io/@std/bytes/1.0.5/index_of_needle.js +0 -68
- package/esm/deps/jsr.io/@std/bytes/1.0.5/last_index_of_needle.js +0 -65
- package/esm/deps/jsr.io/@std/bytes/1.0.5/mod.js +0 -34
- package/esm/deps/jsr.io/@std/bytes/1.0.5/repeat.js +0 -43
- package/esm/deps/jsr.io/@std/bytes/1.0.5/starts_with.js +0 -34
- package/types/deps/jsr.io/@std/bytes/1.0.5/copy.d.ts +0 -41
- package/types/deps/jsr.io/@std/bytes/1.0.5/copy.d.ts.map +0 -1
- package/types/deps/jsr.io/@std/bytes/1.0.5/ends_with.d.ts +0 -24
- package/types/deps/jsr.io/@std/bytes/1.0.5/ends_with.d.ts.map +0 -1
- package/types/deps/jsr.io/@std/bytes/1.0.5/equals.d.ts +0 -22
- package/types/deps/jsr.io/@std/bytes/1.0.5/equals.d.ts.map +0 -1
- package/types/deps/jsr.io/@std/bytes/1.0.5/includes_needle.d.ts +0 -38
- package/types/deps/jsr.io/@std/bytes/1.0.5/includes_needle.d.ts.map +0 -1
- package/types/deps/jsr.io/@std/bytes/1.0.5/index_of_needle.d.ts +0 -45
- package/types/deps/jsr.io/@std/bytes/1.0.5/index_of_needle.d.ts.map +0 -1
- package/types/deps/jsr.io/@std/bytes/1.0.5/last_index_of_needle.d.ts +0 -42
- package/types/deps/jsr.io/@std/bytes/1.0.5/last_index_of_needle.d.ts.map +0 -1
- package/types/deps/jsr.io/@std/bytes/1.0.5/mod.d.ts +0 -33
- package/types/deps/jsr.io/@std/bytes/1.0.5/mod.d.ts.map +0 -1
- package/types/deps/jsr.io/@std/bytes/1.0.5/repeat.d.ts +0 -33
- package/types/deps/jsr.io/@std/bytes/1.0.5/repeat.d.ts.map +0 -1
- package/types/deps/jsr.io/@std/bytes/1.0.5/starts_with.d.ts +0 -24
- package/types/deps/jsr.io/@std/bytes/1.0.5/starts_with.d.ts.map +0 -1
- /package/esm/deps/jsr.io/@std/http/{1.0.14 → 1.0.15}/_negotiation/common.js +0 -0
- /package/esm/deps/jsr.io/@std/http/{1.0.14 → 1.0.15}/_negotiation/encoding.js +0 -0
- /package/esm/deps/jsr.io/@std/http/{1.0.14 → 1.0.15}/_negotiation/language.js +0 -0
- /package/esm/deps/jsr.io/@std/http/{1.0.14 → 1.0.15}/_negotiation/media_type.js +0 -0
- /package/esm/deps/jsr.io/@std/http/{1.0.14 → 1.0.15}/negotiation.js +0 -0
- /package/types/deps/jsr.io/@std/http/{1.0.14 → 1.0.15}/_negotiation/common.d.ts +0 -0
- /package/types/deps/jsr.io/@std/http/{1.0.14 → 1.0.15}/_negotiation/encoding.d.ts +0 -0
- /package/types/deps/jsr.io/@std/http/{1.0.14 → 1.0.15}/_negotiation/language.d.ts +0 -0
- /package/types/deps/jsr.io/@std/http/{1.0.14 → 1.0.15}/_negotiation/media_type.d.ts +0 -0
- /package/types/deps/jsr.io/@std/http/{1.0.14 → 1.0.15}/negotiation.d.ts +0 -0
package/CHANGES.md
CHANGED
@@ -22,6 +22,23 @@ To be released.
|
|
22
22
|
|
23
23
|
- Added `Router.trailingSlashInsensitive` property.
|
24
24
|
|
25
|
+
- Implemented HTTP Message Signatures ([RFC 9421]) with double-knocking.
|
26
|
+
Currently, it only works with RSA-PKCS#1-v1.5. [[#208]]
|
27
|
+
|
28
|
+
- Added `HttpMessageSignaturesSpec` type.
|
29
|
+
- Added `SignRequestOptions.spec` option.
|
30
|
+
- Added `SignRequestOptions.currentTime` option.
|
31
|
+
- Added `VerifyRequestOptions.spec` option.
|
32
|
+
- Added `GetAuthenticatedDocumentLoaderOptions.specDeterminer` option.
|
33
|
+
- Added `GetAuthenticatedDocumentLoaderOptions.traceProvider` option.
|
34
|
+
- Added `HttpMessageSignaturesSpecDeterminer` interface.
|
35
|
+
- Added `--first-knock` option to `fedify lookup` command.
|
36
|
+
|
37
|
+
- The `exportJwk()` function now populates the `alg` property of a returned
|
38
|
+
`JsonWebKey` object with `"Ed25519"` if the input key is an Ed25519 key.
|
39
|
+
|
40
|
+
[RFC 9421]: https://www.rfc-editor.org/rfc/rfc9421
|
41
|
+
[#208]: https://github.com/fedify-dev/fedify/issues/208
|
25
42
|
[#227]: https://github.com/fedify-dev/fedify/issues/227
|
26
43
|
|
27
44
|
|
package/CONTRIBUTING.md
CHANGED
@@ -232,6 +232,13 @@ the following command:
|
|
232
232
|
deno task -f @fedify/fedify test
|
233
233
|
~~~~
|
234
234
|
|
235
|
+
Or you can use `--filter` option to run a specific test. For example, if you
|
236
|
+
want to run the `verifyRequest` test:
|
237
|
+
|
238
|
+
~~~~ bash
|
239
|
+
deno task -f @fedify/fedify test --filter verifyRequest
|
240
|
+
~~~~
|
241
|
+
|
235
242
|
If the tests pass, you should run `deno task test-all` command to test
|
236
243
|
the library with Deno, Node.js, and [Bun]:
|
237
244
|
|
package/README.md
CHANGED
@@ -105,7 +105,7 @@ financial contributors:[^2]
|
|
105
105
|
|
106
106
|
### Backers
|
107
107
|
|
108
|
-
Robin Riley, yamanoku,
|
108
|
+
Robin Riley, yamanoku, taye, Encyclia, okin, Andy Piper, box464, Evan Prodromou, Rafael Goulart, malte
|
109
109
|
|
110
110
|
### One-time donations
|
111
111
|
|
package/SPONSORS.md
CHANGED
@@ -26,7 +26,7 @@ Supporters
|
|
26
26
|
Backers
|
27
27
|
-------
|
28
28
|
|
29
|
-
Robin Riley, yamanoku,
|
29
|
+
Robin Riley, yamanoku, taye, Encyclia, okin, Andy Piper, box464, Evan Prodromou, Rafael Goulart, malte
|
30
30
|
|
31
31
|
One-time donations
|
32
32
|
------------------
|
package/esm/deno.js
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
export default {
|
2
2
|
"name": "@fedify/fedify",
|
3
|
-
"version": "1.6.0-dev.
|
3
|
+
"version": "1.6.0-dev.790+3f8325df",
|
4
4
|
"license": "MIT",
|
5
5
|
"exports": {
|
6
6
|
".": "./mod.ts",
|
@@ -29,6 +29,7 @@ export default {
|
|
29
29
|
"@std/async": "jsr:@std/async@^1.0.5",
|
30
30
|
"@std/bytes": "jsr:@std/bytes@^1.0.2",
|
31
31
|
"@std/collections": "jsr:@std/collections@^1.0.6",
|
32
|
+
"@std/crypto": "jsr:@std/crypto@^1.0.4",
|
32
33
|
"@std/encoding": "jsr:@std/encoding@1.0.7",
|
33
34
|
"@std/http": "jsr:@std/http@^1.0.6",
|
34
35
|
"@std/testing": "jsr:@std/testing@^0.224.0",
|
@@ -42,6 +43,7 @@ export default {
|
|
42
43
|
"mock_fetch": "jsr:@hongminhee/deno-mock-fetch@^0.3.2",
|
43
44
|
"multicodec": "npm:multicodec@^3.2.1",
|
44
45
|
"pkijs": "npm:pkijs@^3.2.4",
|
46
|
+
"structured-field-values": "npm:structured-field-values@^2.0.4",
|
45
47
|
"uri-template-router": "npm:uri-template-router@^0.0.17",
|
46
48
|
"url-template": "npm:url-template@^3.1.1"
|
47
49
|
},
|
@@ -0,0 +1,55 @@
|
|
1
|
+
// Copyright 2018-2025 the Deno authors. MIT license.
|
2
|
+
// This module is browser compatible.
|
3
|
+
function toDataView(value) {
|
4
|
+
if (value instanceof DataView) {
|
5
|
+
return value;
|
6
|
+
}
|
7
|
+
return ArrayBuffer.isView(value)
|
8
|
+
? new DataView(value.buffer, value.byteOffset, value.byteLength)
|
9
|
+
: new DataView(value);
|
10
|
+
}
|
11
|
+
/**
|
12
|
+
* When checking the values of cryptographic hashes are equal, default
|
13
|
+
* comparisons can be susceptible to timing based attacks, where attacker is
|
14
|
+
* able to find out information about the host system by repeatedly checking
|
15
|
+
* response times to equality comparisons of values.
|
16
|
+
*
|
17
|
+
* It is likely some form of timing safe equality will make its way to the
|
18
|
+
* WebCrypto standard (see:
|
19
|
+
* {@link https://github.com/w3c/webcrypto/issues/270 | w3c/webcrypto#270}), but until
|
20
|
+
* that time, `timingSafeEqual()` is provided:
|
21
|
+
*
|
22
|
+
* @example Usage
|
23
|
+
* ```ts
|
24
|
+
* import { timingSafeEqual } from "@std/crypto/timing-safe-equal";
|
25
|
+
* import { assert } from "@std/assert";
|
26
|
+
*
|
27
|
+
* const a = await crypto.subtle.digest(
|
28
|
+
* "SHA-384",
|
29
|
+
* new TextEncoder().encode("hello world"),
|
30
|
+
* );
|
31
|
+
* const b = await crypto.subtle.digest(
|
32
|
+
* "SHA-384",
|
33
|
+
* new TextEncoder().encode("hello world"),
|
34
|
+
* );
|
35
|
+
*
|
36
|
+
* assert(timingSafeEqual(a, b));
|
37
|
+
* ```
|
38
|
+
*
|
39
|
+
* @param a The first value to compare.
|
40
|
+
* @param b The second value to compare.
|
41
|
+
* @returns `true` if the values are equal, otherwise `false`.
|
42
|
+
*/
|
43
|
+
export function timingSafeEqual(a, b) {
|
44
|
+
if (a.byteLength !== b.byteLength)
|
45
|
+
return false;
|
46
|
+
const dataViewA = toDataView(a);
|
47
|
+
const dataViewB = toDataView(b);
|
48
|
+
const length = a.byteLength;
|
49
|
+
let out = 0;
|
50
|
+
let i = -1;
|
51
|
+
while (++i < length) {
|
52
|
+
out |= dataViewA.getUint8(i) ^ dataViewB.getUint8(i);
|
53
|
+
}
|
54
|
+
return out === 0;
|
55
|
+
}
|
@@ -34,6 +34,7 @@ export class FederationBuilderImpl {
|
|
34
34
|
const trailingSlashInsensitiveValue = f.router.trailingSlashInsensitive;
|
35
35
|
f.router = this.router;
|
36
36
|
f.router.trailingSlashInsensitive = trailingSlashInsensitiveValue;
|
37
|
+
f._initializeRouter();
|
37
38
|
f.actorCallbacks = this.actorCallbacks;
|
38
39
|
f.nodeInfoDispatcher = this.nodeInfoDispatcher;
|
39
40
|
f.objectCallbacks = this.objectCallbacks;
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import { getLogger } from "@logtape/logtape";
|
2
2
|
import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
|
3
|
-
import { accepts } from "../deps/jsr.io/@std/http/1.0.
|
3
|
+
import { accepts } from "../deps/jsr.io/@std/http/1.0.15/negotiation.js";
|
4
4
|
import metadata from "../deno.js";
|
5
5
|
import { verifyRequest } from "../sig/http.js";
|
6
6
|
import { detachSignature, verifyJsonLd } from "../sig/ld.js";
|
@@ -7,7 +7,7 @@ import metadata from "../deno.js";
|
|
7
7
|
import { getNodeInfo } from "../nodeinfo/client.js";
|
8
8
|
import { handleNodeInfo, handleNodeInfoJrd } from "../nodeinfo/handler.js";
|
9
9
|
import { getAuthenticatedDocumentLoader, getDocumentLoader, kvCache, } from "../runtime/docloader.js";
|
10
|
-
import { verifyRequest } from "../sig/http.js";
|
10
|
+
import { verifyRequest, } from "../sig/http.js";
|
11
11
|
import { exportJwk, importJwk, validateCryptoKey } from "../sig/key.js";
|
12
12
|
import { hasSignature, signJsonLd } from "../sig/ld.js";
|
13
13
|
import { getKeyOwner } from "../sig/owner.js";
|
@@ -66,6 +66,7 @@ export class FederationImpl extends FederationBuilderImpl {
|
|
66
66
|
activityIdempotence: ["_fedify", "activityIdempotence"],
|
67
67
|
remoteDocument: ["_fedify", "remoteDocument"],
|
68
68
|
publicKey: ["_fedify", "publicKey"],
|
69
|
+
httpMessageSignaturesSpec: ["_fedify", "httpMessageSignaturesSpec"],
|
69
70
|
},
|
70
71
|
...(options.kvPrefixes ?? {}),
|
71
72
|
};
|
@@ -121,8 +122,7 @@ export class FederationImpl extends FederationBuilderImpl {
|
|
121
122
|
}
|
122
123
|
this.router.trailingSlashInsensitive = options.trailingSlashInsensitive ??
|
123
124
|
false;
|
124
|
-
this.
|
125
|
-
this.router.add("/.well-known/nodeinfo", "nodeInfoJrd");
|
125
|
+
this._initializeRouter();
|
126
126
|
if (options.allowPrivateAddress || options.userAgent != null) {
|
127
127
|
if (options.documentLoader != null) {
|
128
128
|
throw new TypeError("Cannot set documentLoader with allowPrivateAddress or " +
|
@@ -180,6 +180,8 @@ export class FederationImpl extends FederationBuilderImpl {
|
|
180
180
|
((identity) => getAuthenticatedDocumentLoader(identity, {
|
181
181
|
allowPrivateAddress,
|
182
182
|
userAgent,
|
183
|
+
specDeterminer: new KvSpecDeterminer(this.kv, this.kvPrefixes.httpMessageSignaturesSpec),
|
184
|
+
tracerProvider: this.tracerProvider,
|
183
185
|
}));
|
184
186
|
this.userAgent = userAgent;
|
185
187
|
this.onOutboxError = options.onOutboxError;
|
@@ -193,6 +195,10 @@ export class FederationImpl extends FederationBuilderImpl {
|
|
193
195
|
getDefaultActivityTransformers();
|
194
196
|
this.tracerProvider = options.tracerProvider ?? trace.getTracerProvider();
|
195
197
|
}
|
198
|
+
_initializeRouter() {
|
199
|
+
this.router.add("/.well-known/webfinger", "webfinger");
|
200
|
+
this.router.add("/.well-known/nodeinfo", "nodeInfoJrd");
|
201
|
+
}
|
196
202
|
_getTracer() {
|
197
203
|
return this.tracerProvider.getTracer(metadata.name, metadata.version);
|
198
204
|
}
|
@@ -369,6 +375,7 @@ export class FederationImpl extends FederationBuilderImpl {
|
|
369
375
|
inbox: new URL(message.inbox),
|
370
376
|
sharedInbox: message.sharedInbox,
|
371
377
|
headers: new Headers(message.headers),
|
378
|
+
specDeterminer: new KvSpecDeterminer(this.kv, this.kvPrefixes.httpMessageSignaturesSpec),
|
372
379
|
tracerProvider: this.tracerProvider,
|
373
380
|
});
|
374
381
|
}
|
@@ -671,6 +678,7 @@ export class FederationImpl extends FederationBuilderImpl {
|
|
671
678
|
headers: collectionSync == null ? undefined : new Headers({
|
672
679
|
"Collection-Synchronization": await buildCollectionSynchronizationHeader(collectionSync, inboxes[inbox].actorIds),
|
673
680
|
}),
|
681
|
+
specDeterminer: new KvSpecDeterminer(this.kv, this.kvPrefixes.httpMessageSignaturesSpec),
|
674
682
|
tracerProvider: this.tracerProvider,
|
675
683
|
}));
|
676
684
|
}
|
@@ -1936,6 +1944,7 @@ export class InboxContextImpl extends ContextImpl {
|
|
1936
1944
|
inbox: new URL(inbox),
|
1937
1945
|
sharedInbox: inboxes[inbox].sharedInbox,
|
1938
1946
|
tracerProvider: this.tracerProvider,
|
1947
|
+
specDeterminer: new KvSpecDeterminer(this.federation.kv, this.federation.kvPrefixes.httpMessageSignaturesSpec),
|
1939
1948
|
}));
|
1940
1949
|
}
|
1941
1950
|
await Promise.all(promises);
|
@@ -1994,6 +2003,25 @@ export class InboxContextImpl extends ContextImpl {
|
|
1994
2003
|
}
|
1995
2004
|
}
|
1996
2005
|
}
|
2006
|
+
export class KvSpecDeterminer {
|
2007
|
+
kv;
|
2008
|
+
prefix;
|
2009
|
+
defaultSpec;
|
2010
|
+
constructor(kv, prefix, defaultSpec = "rfc9421") {
|
2011
|
+
this.kv = kv;
|
2012
|
+
this.prefix = prefix;
|
2013
|
+
this.defaultSpec = defaultSpec;
|
2014
|
+
}
|
2015
|
+
async determineSpec(origin) {
|
2016
|
+
return await this.kv.get([
|
2017
|
+
...this.prefix,
|
2018
|
+
origin,
|
2019
|
+
]) ?? this.defaultSpec;
|
2020
|
+
}
|
2021
|
+
async rememberSpec(origin, spec) {
|
2022
|
+
await this.kv.set([...this.prefix, origin], spec);
|
2023
|
+
}
|
2024
|
+
}
|
1997
2025
|
function notFound(_request) {
|
1998
2026
|
return new Response("Not Found", { status: 404 });
|
1999
2027
|
}
|
package/esm/federation/send.js
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
import { getLogger } from "@logtape/logtape";
|
2
2
|
import { SpanKind, SpanStatusCode, trace, } from "@opentelemetry/api";
|
3
3
|
import metadata from "../deno.js";
|
4
|
-
import {
|
4
|
+
import { doubleKnock, } from "../sig/http.js";
|
5
5
|
/**
|
6
6
|
* Extracts the inbox URLs from recipients.
|
7
7
|
* @param parameters The parameters to extract the inboxes.
|
@@ -65,11 +65,11 @@ export function sendActivity(options) {
|
|
65
65
|
}
|
66
66
|
});
|
67
67
|
}
|
68
|
-
async function sendActivityInternal({ activity, activityId, keys, inbox, headers, tracerProvider, }) {
|
68
|
+
async function sendActivityInternal({ activity, activityId, keys, inbox, headers, specDeterminer, tracerProvider, }) {
|
69
69
|
const logger = getLogger(["fedify", "federation", "outbox"]);
|
70
70
|
headers = new Headers(headers);
|
71
71
|
headers.set("Content-Type", "application/activity+json");
|
72
|
-
|
72
|
+
const request = new Request(inbox, {
|
73
73
|
method: "POST",
|
74
74
|
headers,
|
75
75
|
body: JSON.stringify(activity),
|
@@ -93,12 +93,11 @@ async function sendActivityInternal({ activity, activityId, keys, inbox, headers
|
|
93
93
|
})),
|
94
94
|
});
|
95
95
|
}
|
96
|
-
else {
|
97
|
-
request = await signRequest(request, rsaKey.privateKey, rsaKey.keyId, { tracerProvider });
|
98
|
-
}
|
99
96
|
let response;
|
100
97
|
try {
|
101
|
-
response =
|
98
|
+
response = rsaKey == null
|
99
|
+
? await fetch(request)
|
100
|
+
: await doubleKnock(request, rsaKey, { tracerProvider, specDeterminer });
|
102
101
|
}
|
103
102
|
catch (error) {
|
104
103
|
logger.error("Failed to send activity {activityId} to {inbox}:\n{error}", {
|
package/esm/runtime/docloader.js
CHANGED
@@ -4,7 +4,7 @@ import { HTTPHeaderLink } from "@hugoalh/http-header-link";
|
|
4
4
|
import { getLogger } from "@logtape/logtape";
|
5
5
|
import process from "node:process";
|
6
6
|
import metadata from "../deno.js";
|
7
|
-
import {
|
7
|
+
import { doubleKnock, } from "../sig/http.js";
|
8
8
|
import { validateCryptoKey } from "../sig/key.js";
|
9
9
|
import preloadedContexts from "./contexts.js";
|
10
10
|
import { UrlError, validatePublicUrl } from "./url.js";
|
@@ -238,7 +238,7 @@ export function fetchDocumentLoader(url, allowPrivateAddress = false) {
|
|
238
238
|
* @throws {TypeError} If the key is invalid or unsupported.
|
239
239
|
* @since 0.4.0
|
240
240
|
*/
|
241
|
-
export function getAuthenticatedDocumentLoader(identity, { allowPrivateAddress, userAgent } = {}) {
|
241
|
+
export function getAuthenticatedDocumentLoader(identity, { allowPrivateAddress, userAgent, specDeterminer, tracerProvider } = {}) {
|
242
242
|
validateCryptoKey(identity.privateKey);
|
243
243
|
async function load(url) {
|
244
244
|
if (!allowPrivateAddress) {
|
@@ -252,20 +252,8 @@ export function getAuthenticatedDocumentLoader(identity, { allowPrivateAddress,
|
|
252
252
|
throw error;
|
253
253
|
}
|
254
254
|
}
|
255
|
-
|
256
|
-
|
257
|
-
logRequest(request);
|
258
|
-
const response = await fetch(request, {
|
259
|
-
// Since Bun has a bug that ignores the `Request.redirect` option,
|
260
|
-
// to work around it we specify `redirect: "manual"` here too:
|
261
|
-
// https://github.com/oven-sh/bun/issues/10754
|
262
|
-
redirect: "manual",
|
263
|
-
});
|
264
|
-
// Follow redirects manually to get the final URL:
|
265
|
-
if (response.status >= 300 && response.status < 400 &&
|
266
|
-
response.headers.has("Location")) {
|
267
|
-
return load(response.headers.get("Location"));
|
268
|
-
}
|
255
|
+
const originalRequest = createRequest(url, { userAgent });
|
256
|
+
const response = await doubleKnock(originalRequest, identity, { specDeterminer, log: logRequest, tracerProvider });
|
269
257
|
return getRemoteDocument(url, response, load);
|
270
258
|
}
|
271
259
|
return load;
|