Loading CHANGES.md +2 −0 Original line number Diff line number Diff line Loading @@ -11,6 +11,8 @@ To be released. - Removed `expand` option of `Object.toJsonLd()` method, which was deprecated in version 0.14.0. Use `format: "expand"` option instead. - Added `Context.lookupObject()` method. - Default document loaders now recognize `alternate` ActivityStreams objects in the `Link` header. - Added `allowPrivateAddress` option to `CreateFederationOptions` interface. - Renamed the short option `-c` for `--compact` of `fedify lookup` command to `-C` to avoid conflict with the short option `-c` for `--cache-dir`. Loading src/runtime/docloader.test.ts +30 −5 Original line number Diff line number Diff line Loading @@ -52,16 +52,17 @@ test("fetchDocumentLoader()", async (t) => { }); }); mf.mock("GET@/object2", (_req) => mf.mock("GET@/link-ctx", (_req) => new Response( JSON.stringify({ id: "https://example.com/object2", id: "https://example.com/link-ctx", name: "Fetched object", type: "Object", }), { status: 200, headers: { "Content-Type": "application/activity+json", Link: "<https://www.w3.org/ns/activitystreams>; " + 'rel="http://www.w3.org/ns/json-ld#context"; ' + 'type="application/ld+json"', Loading @@ -69,12 +70,36 @@ test("fetchDocumentLoader()", async (t) => { }, )); mf.mock("GET@/link-obj", (_req) => new Response( "", { status: 200, headers: { "Content-Type": "text/html; charset=utf-8", Link: '<https://example.com/object>; rel="alternate"; ' + 'type="application/activity+json"', }, }, )); await t.step("Link header", async () => { assertEquals(await fetchDocumentLoader("https://example.com/object2"), { assertEquals(await fetchDocumentLoader("https://example.com/link-ctx"), { contextUrl: "https://www.w3.org/ns/activitystreams", documentUrl: "https://example.com/object2", documentUrl: "https://example.com/link-ctx", document: { id: "https://example.com/link-ctx", name: "Fetched object", type: "Object", }, }); assertEquals(await fetchDocumentLoader("https://example.com/link-obj"), { contextUrl: null, documentUrl: "https://example.com/object", document: { id: "https://example.com/object2", "@context": "https://www.w3.org/ns/activitystreams", id: "https://example.com/object", name: "Fetched object", type: "Object", }, Loading src/runtime/docloader.ts +35 −7 Original line number Diff line number Diff line Loading @@ -94,6 +94,7 @@ function logRequest(request: Request) { async function getRemoteDocument( url: string, response: Response, fetch: (url: string) => Promise<RemoteDocument>, ): Promise<RemoteDocument> { const documentUrl = response.url === "" ? url : response.url; if (!response.ok) { Loading @@ -110,10 +111,16 @@ async function getRemoteDocument( `HTTP ${response.status}: ${documentUrl}`, ); } const contentType = response.headers.get("Content-Type"); const jsonLd = contentType == null || contentType === "application/activity+json" || contentType === "application/ld+json" || contentType.startsWith("application/ld+json;"); const linkHeader = response.headers.get("Link"); let contextUrl: string | null = null; if (linkHeader != null) { const link = new HTTPHeaderLink(linkHeader); if (jsonLd) { const entries = link.getByRel("http://www.w3.org/ns/json-ld#context"); for (const [uri, params] of entries) { if ("type" in params && params.type === "application/ld+json") { Loading @@ -121,6 +128,23 @@ async function getRemoteDocument( break; } } } else { const entries = link.getByRel("alternate"); for (const [uri, params] of entries) { if ( "type" in params && (params.type === "application/activity+json" || params.type === "application/ld+json" || params.type.startsWith("application/ld+json;")) ) { logger.debug( "Found alternate document: {alternateUrl} from {url}", { alternateUrl: uri, url: documentUrl }, ); return await fetch(uri); } } } } logger.debug( "Fetched document: {status} {url} {headers}", Loading Loading @@ -189,7 +213,11 @@ export async function fetchDocumentLoader( ) { return fetchDocumentLoader(response.headers.get("Location")!); } return getRemoteDocument(url, response); return getRemoteDocument( url, response, (url) => fetchDocumentLoader(url, allowPrivateAddress), ); } /** Loading Loading @@ -236,7 +264,7 @@ export function getAuthenticatedDocumentLoader( ) { return load(response.headers.get("Location")!); } return getRemoteDocument(url, response); return getRemoteDocument(url, response, load); } return load; } Loading Loading
CHANGES.md +2 −0 Original line number Diff line number Diff line Loading @@ -11,6 +11,8 @@ To be released. - Removed `expand` option of `Object.toJsonLd()` method, which was deprecated in version 0.14.0. Use `format: "expand"` option instead. - Added `Context.lookupObject()` method. - Default document loaders now recognize `alternate` ActivityStreams objects in the `Link` header. - Added `allowPrivateAddress` option to `CreateFederationOptions` interface. - Renamed the short option `-c` for `--compact` of `fedify lookup` command to `-C` to avoid conflict with the short option `-c` for `--cache-dir`. Loading
src/runtime/docloader.test.ts +30 −5 Original line number Diff line number Diff line Loading @@ -52,16 +52,17 @@ test("fetchDocumentLoader()", async (t) => { }); }); mf.mock("GET@/object2", (_req) => mf.mock("GET@/link-ctx", (_req) => new Response( JSON.stringify({ id: "https://example.com/object2", id: "https://example.com/link-ctx", name: "Fetched object", type: "Object", }), { status: 200, headers: { "Content-Type": "application/activity+json", Link: "<https://www.w3.org/ns/activitystreams>; " + 'rel="http://www.w3.org/ns/json-ld#context"; ' + 'type="application/ld+json"', Loading @@ -69,12 +70,36 @@ test("fetchDocumentLoader()", async (t) => { }, )); mf.mock("GET@/link-obj", (_req) => new Response( "", { status: 200, headers: { "Content-Type": "text/html; charset=utf-8", Link: '<https://example.com/object>; rel="alternate"; ' + 'type="application/activity+json"', }, }, )); await t.step("Link header", async () => { assertEquals(await fetchDocumentLoader("https://example.com/object2"), { assertEquals(await fetchDocumentLoader("https://example.com/link-ctx"), { contextUrl: "https://www.w3.org/ns/activitystreams", documentUrl: "https://example.com/object2", documentUrl: "https://example.com/link-ctx", document: { id: "https://example.com/link-ctx", name: "Fetched object", type: "Object", }, }); assertEquals(await fetchDocumentLoader("https://example.com/link-obj"), { contextUrl: null, documentUrl: "https://example.com/object", document: { id: "https://example.com/object2", "@context": "https://www.w3.org/ns/activitystreams", id: "https://example.com/object", name: "Fetched object", type: "Object", }, Loading
src/runtime/docloader.ts +35 −7 Original line number Diff line number Diff line Loading @@ -94,6 +94,7 @@ function logRequest(request: Request) { async function getRemoteDocument( url: string, response: Response, fetch: (url: string) => Promise<RemoteDocument>, ): Promise<RemoteDocument> { const documentUrl = response.url === "" ? url : response.url; if (!response.ok) { Loading @@ -110,10 +111,16 @@ async function getRemoteDocument( `HTTP ${response.status}: ${documentUrl}`, ); } const contentType = response.headers.get("Content-Type"); const jsonLd = contentType == null || contentType === "application/activity+json" || contentType === "application/ld+json" || contentType.startsWith("application/ld+json;"); const linkHeader = response.headers.get("Link"); let contextUrl: string | null = null; if (linkHeader != null) { const link = new HTTPHeaderLink(linkHeader); if (jsonLd) { const entries = link.getByRel("http://www.w3.org/ns/json-ld#context"); for (const [uri, params] of entries) { if ("type" in params && params.type === "application/ld+json") { Loading @@ -121,6 +128,23 @@ async function getRemoteDocument( break; } } } else { const entries = link.getByRel("alternate"); for (const [uri, params] of entries) { if ( "type" in params && (params.type === "application/activity+json" || params.type === "application/ld+json" || params.type.startsWith("application/ld+json;")) ) { logger.debug( "Found alternate document: {alternateUrl} from {url}", { alternateUrl: uri, url: documentUrl }, ); return await fetch(uri); } } } } logger.debug( "Fetched document: {status} {url} {headers}", Loading Loading @@ -189,7 +213,11 @@ export async function fetchDocumentLoader( ) { return fetchDocumentLoader(response.headers.get("Location")!); } return getRemoteDocument(url, response); return getRemoteDocument( url, response, (url) => fetchDocumentLoader(url, allowPrivateAddress), ); } /** Loading Loading @@ -236,7 +264,7 @@ export function getAuthenticatedDocumentLoader( ) { return load(response.headers.get("Location")!); } return getRemoteDocument(url, response); return getRemoteDocument(url, response, load); } return load; } Loading