From 230f50a61090078928c934e7600c55ad5f255979 Mon Sep 17 00:00:00 2001 From: mrjvs Date: Tue, 16 Sep 2025 23:49:12 +0200 Subject: [PATCH 1/2] fix: set content length for file streaming so it doesn't use transfer-encoding: chunked --- src/cdn.ts | 25 ++++++++++++++++++------- src/services/npdi.ts | 2 +- src/services/npdl.ts | 2 +- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/cdn.ts b/src/cdn.ts index 164dfd2..110558c 100644 --- a/src/cdn.ts +++ b/src/cdn.ts @@ -38,7 +38,7 @@ function buildLocalCDNPath(fullKey: string): string { return path.join(config.cdn.disk_path, fullKey); } -export async function getCDNFileAsStream(namespace: CDNNamespace, key: string): Promise { +export async function getCDNFileAsStream(namespace: CDNNamespace, key: string): Promise<{ size: number | null; stream: Readable } | null> { const fullKey = buildKey(namespace, key); if (!s3) { @@ -49,7 +49,10 @@ export async function getCDNFileAsStream(namespace: CDNNamespace, key: string): return null; } - return fs.createReadStream(filePath); + return { + stream: fs.createReadStream(filePath), + size: fileInfo.size + }; } const response = await s3.send(new GetObjectCommand({ @@ -61,15 +64,18 @@ export async function getCDNFileAsStream(namespace: CDNNamespace, key: string): return null; } - return response.Body; + return { + stream: response.Body, + size: response.ContentLength ?? null + }; } export async function getCDNFileAsBuffer(namespace: CDNNamespace, key: string): Promise { - const stream = await getCDNFileAsStream(namespace, key); - if (!stream) { + const streamOutput = await getCDNFileAsStream(namespace, key); + if (!streamOutput) { return null; } - return bufferConsumer(stream); + return bufferConsumer(streamOutput.stream); } export async function uploadCDNFile(namespace: CDNNamespace, key: string, data: Buffer): Promise { @@ -111,8 +117,13 @@ export async function deleteCDNFile(namespace: CDNNamespace, key: string): Promi })); } -export function streamFileToResponse(response: Response, stream: Readable, headers: Record = {}): void { +export function streamFileToResponse(response: Response, stream: Readable, size: number | null, headers: Record = {}): void { response.setHeaders(new Headers(headers)); + + if (size !== null) { + response.setHeader('Content-Length', size); + } + Stream.pipeline(stream, response, (err) => { if (err) { logger.error('Error with response stream: ' + err.message); diff --git a/src/services/npdi.ts b/src/services/npdi.ts index a9b5ee9..596e9d1 100644 --- a/src/services/npdi.ts +++ b/src/services/npdi.ts @@ -23,7 +23,7 @@ npdi.get('/p01/data/1/:bossAppId/:dataId/:fileHash', async (request, response) = throw new Error('File not found in CDN'); } - return streamFileToResponse(response, fileStream, { + return streamFileToResponse(response, fileStream.stream, fileStream.size, { // * The misspelling here is intentional, it's what the official server sets 'Content-Type': 'applicatoin/octet-stream', 'Content-Disposition': 'attachment', diff --git a/src/services/npdl.ts b/src/services/npdl.ts index a167299..e934949 100644 --- a/src/services/npdl.ts +++ b/src/services/npdl.ts @@ -35,7 +35,7 @@ npdl.get([ return; } - return streamFileToResponse(response, readStream, { + return streamFileToResponse(response, readStream.stream, readStream.size, { 'Last-Modified': new Date(Number(file.updated)).toUTCString() }); }); From c4b244ab135eee8301502d3ace19ad336eea8a51 Mon Sep 17 00:00:00 2001 From: mrjvs Date: Wed, 17 Sep 2025 00:18:18 +0200 Subject: [PATCH 2/2] Use actual main branch for latest tag --- .github/workflows/docker.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 2691cb2..519695f 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -9,7 +9,7 @@ env: REGISTRY: ghcr.io IMAGE_NAME: ${{ github.repository }} DEFAULT_BRANCH: ${{ format('refs/heads/{0}', github.event.repository.default_branch) }} - SHOULD_PUSH_IMAGE: ${{ (github.event_name == 'push' && (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) || github.ref == 'refs/heads/dev')) || github.event_name == 'workflow_dispatch' }} + SHOULD_PUSH_IMAGE: ${{ (github.event_name == 'push' && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/dev')) || github.event_name == 'workflow_dispatch' }} jobs: build-publish-amd64: @@ -41,7 +41,7 @@ jobs: with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} tags: | - type=raw,value=latest,enable=${{ github.ref == env.DEFAULT_BRANCH }} + type=raw,value=latest,enable=${{ github.ref == 'refs/heads/master' }} type=raw,value=edge,enable=${{ github.ref == 'refs/heads/dev' }} type=sha @@ -85,7 +85,7 @@ jobs: with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} tags: | - type=raw,value=latest-arm,enable=${{ github.ref == env.DEFAULT_BRANCH }} + type=raw,value=latest-arm,enable=${{ github.ref == 'refs/heads/master' }} type=raw,value=edge-arm,enable=${{ github.ref == 'refs/heads/dev' }} type=sha,suffix=-arm