From 88aa5cc99301c46d98260901c181b37dff9aa2e5 Mon Sep 17 00:00:00 2001 From: Cody <36463298+ugcodrr@users.noreply.github.com> Date: Mon, 19 Oct 2026 19:33:09 -0400 Subject: [PATCH 1/2] fix(api-client): send the API key in a header for image downloads --- packages/api-client/src/api.service.ts | 15 ++++++++++----- packages/rendering/src/hooks/loadImage.ts | 2 +- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/packages/api-client/src/api.service.ts b/packages/api-client/src/api.service.ts index f43108367..582e3526a 100644 --- a/packages/api-client/src/api.service.ts +++ b/packages/api-client/src/api.service.ts @@ -33,12 +33,13 @@ import { } from "#responses"; import { User, UserFooter, UserTheme } from "@statsify/schemas"; import { config } from "@statsify/util"; -import { loadImage } from "@statsify/rendering"; +import { IMAGE_DOWNLOAD_TIMEOUT, loadImage } from "@statsify/rendering"; interface ExtraData { headers?: AxiosRequestHeaders; body?: Record | Buffer | string; responseType?: ResponseType; + timeout?: number; } // TODO: Move dtos in api to @statsify/api-client @@ -286,7 +287,7 @@ export class ApiService { url: string, params: Record | undefined, method: Method = "GET", - { body, headers, responseType }: ExtraData = {} + { body, headers, responseType, timeout }: ExtraData = {} ): Promise { const transaction = Sentry.getCurrentHub().getScope()?.getTransaction(); @@ -302,6 +303,7 @@ export class ApiService { headers, data: body, responseType, + timeout, }); child?.setHttpStatus(res.status); @@ -314,10 +316,13 @@ export class ApiService { return data; } + // Through the client like every other request, so the key goes in a header instead of the URL private async requestImage(url: string, params?: Record) { - const uri = this.axios.getUri({ url, params: { key: this.apiKey, ...params } }); - const image = await loadImage(uri); + const data = await this.request(url, params, "GET", { + responseType: "arraybuffer", + timeout: IMAGE_DOWNLOAD_TIMEOUT, + }); - return image; + return loadImage(Buffer.from(data)); } } diff --git a/packages/rendering/src/hooks/loadImage.ts b/packages/rendering/src/hooks/loadImage.ts index ab969c2dc..a1daf4a21 100644 --- a/packages/rendering/src/hooks/loadImage.ts +++ b/packages/rendering/src/hooks/loadImage.ts @@ -14,7 +14,7 @@ import { readFile } from "node:fs/promises"; * Idle timeout for remote images. A skin can need a Mojang lookup and a render on the API * before any data arrives, which is why this isn't shorter. */ -const IMAGE_DOWNLOAD_TIMEOUT = 5_000; +export const IMAGE_DOWNLOAD_TIMEOUT = 5_000; const bufferToImage = (buffer: Buffer): Image => { const image = new Image(buffer); From ed2736413a3ad71999167fc1daf790ac554516d3 Mon Sep 17 00:00:00 2001 From: Cody <36463298+ugcodrr@users.noreply.github.com> Date: Thu, 22 Oct 2026 00:47:21 -0400 Subject: [PATCH 2/2] refactor(api-client): load image downloads from the response buffer --- packages/api-client/src/api.service.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/api-client/src/api.service.ts b/packages/api-client/src/api.service.ts index 582e3526a..1dd8f5fe6 100644 --- a/packages/api-client/src/api.service.ts +++ b/packages/api-client/src/api.service.ts @@ -316,13 +316,12 @@ export class ApiService { return data; } - // Through the client like every other request, so the key goes in a header instead of the URL private async requestImage(url: string, params?: Record) { - const data = await this.request(url, params, "GET", { + const buffer = await this.request(url, params, "GET", { responseType: "arraybuffer", timeout: IMAGE_DOWNLOAD_TIMEOUT, }); - return loadImage(Buffer.from(data)); + return loadImage(buffer); } }