diff --git a/src/activity.ts b/src/activity.ts index 08e912c..45e229a 100644 --- a/src/activity.ts +++ b/src/activity.ts @@ -210,6 +210,8 @@ export const sendAccept = async (user: User, followId: string, follower: string, console.log("response status:", result.status); const response = await streamToString(result.body as ReadableStream); console.log("Response body:", response); + + if (result.status >= 400) throw "bad http status code"; }; export const sendAll = async (keyId: string, privateKey: string, activity: Record | string, inboxes: string[]) => { diff --git a/src/net.ts b/src/net.ts index b11d5a0..a3cd12d 100644 --- a/src/net.ts +++ b/src/net.ts @@ -18,10 +18,10 @@ export interface SignedInit { }; // TODO: Handle redirects. -export const signedFetch = async (url: string, init: RequestInit, signedInit: SignedInit) => { +export const signedFetch = async (url: string, init: RequestInit, signedInit: SignedInit): Promise => { const signedHeaders: HeadersInit = [ - ["Date", new Date().toUTCString()], ["Host", new URL(url).host], + ["Date", new Date().toUTCString()] ]; const headerNames = ["(request-target)", "host", "date"]; @@ -57,33 +57,39 @@ export const signedFetch = async (url: string, init: RequestInit, signedInit: Si const newHeaders = new Headers( [ + ...signedHeaders, ["Signature", signature], ["Content-Type", `application/ld+json; profile="${CONTEXT}"`] ] ); - if (Array.isArray(init.headers) || !init.headers) { - for (const header of (init.headers || [])) { - if (Array.isArray(header)) - newHeaders.set(header[0], header[1]); - else throw "unsupported headers type"; // Lazy. - } - - for (const [key, value] of signedHeaders) { - newHeaders.set(key, value); - } - } - else throw "unsupported headers type"; // Lazy. + if (Array.isArray(init.headers)) + init.headers + .filter((header) => Array.isArray(header)) + .forEach(([key, value]) => newHeaders.set(key, value)); console.log("Headers:"); for (const [key, value] of newHeaders) { console.log(`${key}: ${value}`); } - return fetch(url, { + const result = await fetch(url, { ...init, headers: newHeaders }); + + if (result.status >= 300 && result.status <= 399) { + const newUrl = result.headers.get("location"); + if (newUrl) { + return await signedFetch(newUrl, init, { + // Omit premade digest since url changed, it is invalid. + privateKey: signedInit.privateKey, + keyId: signedInit.keyId + }); + } + else throw "signed fetch redirect without location header"; + } + else return result; }; export const getActor = async (actorUrl: string, signedInit: SignedInit): Promise => {