server: handle redirects in signed get

part of FoundKeyGang/FoundKey#288

Changelog: Fixed
This commit is contained in:
Johann150 2022-12-20 22:06:54 +01:00
parent d75e295ee8
commit aa33708b90
Signed by untrusted user: Johann150
GPG key ID: 9EE6577A2A06F8F1
2 changed files with 30 additions and 18 deletions

View file

@ -35,7 +35,7 @@ export async function getHtml(url: string, accept = 'text/html, */*', timeout =
return await res.text();
}
export async function getResponse(args: { url: string, method: string, body?: string, headers: Record<string, string>, timeout?: number, size?: number }) {
export async function getResponse(args: { url: string, method: string, body?: string, headers: Record<string, string>, timeout?: number, size?: number, redirect: 'follow' | 'manual' | 'error' = 'follow' }) {
const timeout = args.timeout || 10 * SECOND;
const controller = new AbortController();
@ -47,8 +47,9 @@ export async function getResponse(args: { url: string, method: string, body?: st
method: args.method,
headers: args.headers,
body: args.body,
redirect: args.redirect,
timeout,
size: args.size || 10 * 1024 * 1024,
size: args.size || 10 * 1024 * 1024, // 10 MiB
agent: getAgentByUrl,
signal: controller.signal,
});

View file

@ -1,3 +1,4 @@
import { URL } from 'node:url';
import config from '@/config/index.js';
import { getUserKeypair } from '@/misc/keypair-store.js';
import { User } from '@/models/entities/user.js';
@ -37,6 +38,7 @@ export async function request(user: { id: User['id'] }, url: string, object: any
export async function signedGet(url: string, user: { id: User['id'] }): Promise<any> {
const keypair = await getUserKeypair(user.id);
for (let redirects = 0; redirects < 3; redirects++) {
const req = createSignedGet({
key: {
privateKeyPem: keypair.privateKey,
@ -54,5 +56,14 @@ export async function signedGet(url: string, user: { id: User['id'] }): Promise<
headers: req.request.headers,
});
if (res.status >= 300 && res.status < 400) {
// Have been redirected, need to make a new signature.
// Use Location header and fetched URL as the base URL.
url = new URL(res.headers.get('Location'), url).href;
} else {
return await res.json();
}
}
throw new Error('too many redirects');
}