Skip to content

Commit

Permalink
feat (backend): permit redirects for AP object lookups
Browse files Browse the repository at this point in the history
  • Loading branch information
2 people authored and atsu1125 committed Mar 31, 2024
1 parent 8878d93 commit 0f5dec0
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 4 deletions.
8 changes: 7 additions & 1 deletion src/misc/fetch.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as http from 'http';
import * as https from 'https';
import CacheableLookup from 'cacheable-lookup';
import fetch from 'node-fetch';
import fetch, { RequestRedirect } from 'node-fetch';
import { HttpProxyAgent, HttpsProxyAgent } from 'hpagent';
import config from '../config';
import { URL } from 'url';
Expand Down Expand Up @@ -42,6 +42,7 @@ export async function getResponse(args: {
headers: Record<string, string>;
timeout?: number;
size?: number;
redirect?: RequestRedirect;
}) {
if (!isValidUrl(args.url)) {
throw new StatusError('Invalid URL', 400);
Expand All @@ -62,8 +63,13 @@ export async function getResponse(args: {
size: args?.size || 10 * 1024 * 1024,
agent: getAgentByUrl,
signal: controller.signal,
redirect: args.redirect,
});

if (args.redirect === 'manual' && [301, 302, 307, 308].includes(res.status)) {
return res;
}

if (!res.ok) {
throw new StatusError(`${res.status} ${res.statusText}`, res.status, res.statusText);
}
Expand Down
28 changes: 25 additions & 3 deletions src/remote/activitypub/request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { createSignedPost, createSignedGet } from './ap-request';
import type { Response } from 'node-fetch';
import { IObject } from './type';
import { isValidUrl } from '../../misc/is-valid-url';
import { apLogger } from './logger';

export default async (user: ILocalUser, url: string, object: any) => {
const body = JSON.stringify(object);
Expand Down Expand Up @@ -37,8 +38,9 @@ export default async (user: ILocalUser, url: string, object: any) => {

/**
* Get ActivityPub object
* @param user http-signature user
* @param url URL to fetch
* @param user http-signature user
* @param redirects whether or not to accept redirects
*/
export async function signedGet(url: string, user: ILocalUser) {
const keypair = await UserKeypairs.findOne({
Expand All @@ -65,7 +67,11 @@ export async function signedGet(url: string, user: ILocalUser) {
return await res.json();
}

export async function apGet(url: string, user?: ILocalUser): Promise<IObject> {
export async function apGet(
url: string,
user?: ILocalUser,
redirects: boolean = true
): Promise<IObject> {
if (!isValidUrl(url)) {
throw new StatusError('Invalid URL', 400);
}
Expand All @@ -91,7 +97,15 @@ export async function apGet(url: string, user?: ILocalUser): Promise<IObject> {
url,
method: req.request.method,
headers: req.request.headers,
redirect: redirects ? 'manual' : 'error',
});

if (redirects && [301, 302, 307, 308].includes(res.status)) {
const newUrl = res.headers.get('location');
if (newUrl == null) throw new Error('apGet got redirect but no target location');
apLogger.debug(`apGet is redirecting to ${newUrl}`);
return apGet(newUrl, user, false);
}
} else {
res = await getResponse({
url,
Expand All @@ -101,12 +115,20 @@ export async function apGet(url: string, user?: ILocalUser): Promise<IObject> {
'application/activity+json, application/ld+json; profile="https://www.w3.org/ns/activitystreams"',
"User-Agent": config.userAgent,
},
redirect: redirects ? 'manual' : 'error',
});

if (redirects && [301, 302, 307, 308].includes(res.status)) {
const newUrl = res.headers.get('location');
if (newUrl == null) throw new Error('apGet got redirect but no target location');
apLogger.debug(`apGet is redirecting to ${newUrl}`);
return apGet(newUrl, undefined, false);
}
}

const contentType = res.headers.get("content-type");
if (contentType == null || !validateContentType(contentType)) {
throw new Error("Invalid Content Type");
throw new Error(`apGet response had unexpected content-type: ${contentType}`);
}

if (res.body == null) throw new Error("body is null");
Expand Down

0 comments on commit 0f5dec0

Please sign in to comment.