fix(tlon): add timeouts to file upload HTTP requests (#102903)

* fix(tlon): add timeouts to file upload HTTP requests

* fix(tlon): allow slow bounded uploads

---------

Co-authored-by: chengzhichao-xydt <chengzhichao-xydt@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
This commit is contained in:
chengzhichao-xydt
2026-07-15 20:41:34 +08:00
committed by GitHub
parent 2808507c3b
commit e58dc0955f
2 changed files with 12 additions and 0 deletions
+3
View File
@@ -139,6 +139,7 @@ describe("uploadFile memex upload hardening", () => {
expect(firstCall?.auditContext).toBe("tlon-memex-upload-url");
expect(firstCall?.capture).toBe(false);
expect(firstCall?.maxRedirects).toBe(0);
expect(firstCall?.timeoutMs).toBe(30_000);
const firstBodyRaw = firstCall?.init?.body;
expect(typeof firstBodyRaw).toBe("string");
const firstBody = JSON.parse(firstBodyRaw as string) as Record<string, unknown>;
@@ -156,6 +157,7 @@ describe("uploadFile memex upload hardening", () => {
expect(secondCall?.auditContext).toBe("tlon-memex-upload");
expect(secondCall?.capture).toBe(false);
expect(secondCall?.maxRedirects).toBe(0);
expect(secondCall?.timeoutMs).toBe(300_000);
expect(secondCall?.init?.body).toBeInstanceOf(Blob);
expect(mockRelease).toHaveBeenCalledTimes(2);
});
@@ -509,6 +511,7 @@ describe("uploadFile custom S3 upload hardening", () => {
expect(uploadCall?.auditContext).toBe("tlon-custom-s3-upload");
expect(uploadCall?.capture).toBe(false);
expect(uploadCall?.maxRedirects).toBe(0);
expect(uploadCall?.timeoutMs).toBe(300_000);
expect(uploadCall?.policy).toBeUndefined();
expect(mockRelease).toHaveBeenCalledTimes(1);
expect(vi.mocked(globalThis.fetch)).not.toHaveBeenCalled();
+9
View File
@@ -50,6 +50,12 @@ const MEMEX_BASE_URL = "https://memex.tlon.network";
/** Max bytes to read from the Memex upload JSON response. */
const MEMEX_UPLOAD_RESPONSE_MAX_BYTES = 64 * 1024;
/** Total deadline for the Memex upload URL lookup, including DNS and response reading. */
const TLON_MEMEX_UPLOAD_URL_TIMEOUT_MS = 30_000;
/** Total deadline for Memex and custom S3 PUTs, including DNS and the full upload. */
const TLON_UPLOAD_TIMEOUT_MS = 300_000;
let currentClientConfig: ClientConfig | null = null;
export function configureClient(params: ClientConfig): void {
@@ -251,6 +257,7 @@ async function getMemexUploadUrl(params: {
auditContext: "tlon-memex-upload-url",
capture: false,
maxRedirects: 0,
timeoutMs: TLON_MEMEX_UPLOAD_URL_TIMEOUT_MS,
});
release = guarded.release;
if (!guarded.response.ok) {
@@ -318,6 +325,7 @@ export async function uploadFile(params: UploadFileParams): Promise<UploadResult
auditContext: "tlon-memex-upload",
capture: false,
maxRedirects: 0,
timeoutMs: TLON_UPLOAD_TIMEOUT_MS,
});
release = guarded.release;
assertTrustedMemexUploadUrl(guarded.finalUrl, "Memex final upload URL");
@@ -376,6 +384,7 @@ export async function uploadFile(params: UploadFileParams): Promise<UploadResult
capture: false,
maxRedirects: 0,
policy: privateNetworkPolicy,
timeoutMs: TLON_UPLOAD_TIMEOUT_MS,
});
release = guarded.release;
if (!guarded.response.ok) {