Loading packages/fedify/src/vocab/lookup.ts +6 −0 Original line number Diff line number Diff line Loading @@ -46,6 +46,11 @@ export interface LookupObjectOptions { * @since 1.3.0 */ tracerProvider?: TracerProvider; /** * AbortSignal for cancelling the request. */ signal?: AbortSignal; } /** Loading Loading @@ -145,6 +150,7 @@ async function lookupObjectInternal( tracerProvider: options.tracerProvider, allowPrivateAddress: "allowPrivateAddress" in options && options.allowPrivateAddress === true, signal: options.signal, }); if (jrd?.links == null) return null; for (const l of jrd.links) { Loading packages/fedify/src/webfinger/lookup.test.ts +99 −0 Original line number Diff line number Diff line Loading @@ -216,6 +216,105 @@ test({ ); }); fetchMock.removeRoutes(); fetchMock.get( "begin:https://example.com/.well-known/webfinger?", () => new Promise((resolve) => { const timeoutId = setTimeout(() => { resolve({ body: expected }); }, 1000); return () => clearTimeout(timeoutId); }), ); await t.step("request cancellation", async () => { // Test cancelling a request immediately using AbortController const controller = new AbortController(); const promise = lookupWebFinger("acct:johndoe@example.com", { signal: controller.signal, }); // Abort the request right after starting it controller.abort(); assertEquals(await promise, null); }); fetchMock.removeRoutes(); let redirectCount2 = 0; fetchMock.get( "begin:https://example.com/.well-known/webfinger", () => { redirectCount2++; if (redirectCount2 === 1) { return { status: 302, headers: { Location: "/.well-known/webfinger2" }, }; } return new Promise((resolve) => { const timeoutId = setTimeout(() => { resolve({ body: expected }); }, 1000); return () => clearTimeout(timeoutId); }); }, ); await t.step("cancellation during redirection", async () => { // Test cancelling a request during redirection process const controller = new AbortController(); const promise = lookupWebFinger("acct:johndoe@example.com", { signal: controller.signal, }); // Cancel during the delayed second request after redirection setTimeout(() => controller.abort(), 100); assertEquals(await promise, null); }); fetchMock.removeRoutes(); fetchMock.get( "begin:https://example.com/.well-known/webfinger?", () => new Promise((resolve) => { const timeoutId = setTimeout(() => { resolve({ body: expected }); }, 500); return () => clearTimeout(timeoutId); }), ); await t.step("cancellation with immediate abort", async () => { // Test starting a request with an already aborted AbortController const controller = new AbortController(); controller.abort(); // Use a signal that was already aborted before starting the request const result = await lookupWebFinger("acct:johndoe@example.com", { signal: controller.signal, }); assertEquals(result, null); }); fetchMock.removeRoutes(); fetchMock.get( "begin:https://example.com/.well-known/webfinger?", { body: expected }, ); await t.step("successful request with signal", async () => { // Test successful request with a normal AbortController signal const controller = new AbortController(); const result = await lookupWebFinger("acct:johndoe@example.com", { signal: controller.signal, }); assertEquals(result, expected); }); fetchMock.hardReset(); }, }); Loading packages/fedify/src/webfinger/lookup.ts +6 −0 Original line number Diff line number Diff line Loading @@ -52,6 +52,11 @@ export interface LookupWebFingerOptions { * is used. */ tracerProvider?: TracerProvider; /** * AbortSignal for cancelling the request. */ signal?: AbortSignal; } /** Loading Loading @@ -149,6 +154,7 @@ async function lookupWebFingerInternal( : getUserAgent(options.userAgent), }, redirect: "manual", signal: options.signal, }); } catch (error) { logger.debug( Loading Loading
packages/fedify/src/vocab/lookup.ts +6 −0 Original line number Diff line number Diff line Loading @@ -46,6 +46,11 @@ export interface LookupObjectOptions { * @since 1.3.0 */ tracerProvider?: TracerProvider; /** * AbortSignal for cancelling the request. */ signal?: AbortSignal; } /** Loading Loading @@ -145,6 +150,7 @@ async function lookupObjectInternal( tracerProvider: options.tracerProvider, allowPrivateAddress: "allowPrivateAddress" in options && options.allowPrivateAddress === true, signal: options.signal, }); if (jrd?.links == null) return null; for (const l of jrd.links) { Loading
packages/fedify/src/webfinger/lookup.test.ts +99 −0 Original line number Diff line number Diff line Loading @@ -216,6 +216,105 @@ test({ ); }); fetchMock.removeRoutes(); fetchMock.get( "begin:https://example.com/.well-known/webfinger?", () => new Promise((resolve) => { const timeoutId = setTimeout(() => { resolve({ body: expected }); }, 1000); return () => clearTimeout(timeoutId); }), ); await t.step("request cancellation", async () => { // Test cancelling a request immediately using AbortController const controller = new AbortController(); const promise = lookupWebFinger("acct:johndoe@example.com", { signal: controller.signal, }); // Abort the request right after starting it controller.abort(); assertEquals(await promise, null); }); fetchMock.removeRoutes(); let redirectCount2 = 0; fetchMock.get( "begin:https://example.com/.well-known/webfinger", () => { redirectCount2++; if (redirectCount2 === 1) { return { status: 302, headers: { Location: "/.well-known/webfinger2" }, }; } return new Promise((resolve) => { const timeoutId = setTimeout(() => { resolve({ body: expected }); }, 1000); return () => clearTimeout(timeoutId); }); }, ); await t.step("cancellation during redirection", async () => { // Test cancelling a request during redirection process const controller = new AbortController(); const promise = lookupWebFinger("acct:johndoe@example.com", { signal: controller.signal, }); // Cancel during the delayed second request after redirection setTimeout(() => controller.abort(), 100); assertEquals(await promise, null); }); fetchMock.removeRoutes(); fetchMock.get( "begin:https://example.com/.well-known/webfinger?", () => new Promise((resolve) => { const timeoutId = setTimeout(() => { resolve({ body: expected }); }, 500); return () => clearTimeout(timeoutId); }), ); await t.step("cancellation with immediate abort", async () => { // Test starting a request with an already aborted AbortController const controller = new AbortController(); controller.abort(); // Use a signal that was already aborted before starting the request const result = await lookupWebFinger("acct:johndoe@example.com", { signal: controller.signal, }); assertEquals(result, null); }); fetchMock.removeRoutes(); fetchMock.get( "begin:https://example.com/.well-known/webfinger?", { body: expected }, ); await t.step("successful request with signal", async () => { // Test successful request with a normal AbortController signal const controller = new AbortController(); const result = await lookupWebFinger("acct:johndoe@example.com", { signal: controller.signal, }); assertEquals(result, expected); }); fetchMock.hardReset(); }, }); Loading
packages/fedify/src/webfinger/lookup.ts +6 −0 Original line number Diff line number Diff line Loading @@ -52,6 +52,11 @@ export interface LookupWebFingerOptions { * is used. */ tracerProvider?: TracerProvider; /** * AbortSignal for cancelling the request. */ signal?: AbortSignal; } /** Loading Loading @@ -149,6 +154,7 @@ async function lookupWebFingerInternal( : getUserAgent(options.userAgent), }, redirect: "manual", signal: options.signal, }); } catch (error) { logger.debug( Loading