feat: add ETag handling to stream based responses

This commit is contained in:
mrjvs 2025-09-29 22:28:00 +02:00
parent 91bc93ed93
commit 599ef7812d
3 changed files with 26 additions and 1 deletions

View File

@ -3,6 +3,7 @@ import { restrictHostnames } from '@/middleware/host-limit';
import { config } from '@/config-manager';
import { getCDNFileAsStream, streamFileToResponse } from '@/cdn';
import { getTaskFileByDataID } from '@/database';
import { handleEtag, sendEtagCacheResponse } from '@/util';
const npdi = express.Router();
@ -18,6 +19,11 @@ npdi.get('/p01/data/1/:bossAppId/:dataId/:fileHash', async (request, response) =
return response.sendStatus(404);
}
const { clientHasCached } = handleEtag(request, response, file.hash);
if (clientHasCached) {
return sendEtagCacheResponse(response);
}
const fileStream = await getCDNFileAsStream('taskFile', file.file_key);
if (!fileStream) {
throw new Error('File not found in CDN');

View File

@ -3,6 +3,7 @@ import { getTaskFile } from '@/database';
import { config } from '@/config-manager';
import { restrictHostnames } from '@/middleware/host-limit';
import { getCDNFileAsStream, streamFileToResponse } from '@/cdn';
import { handleEtag, sendEtagCacheResponse } from '@/util';
const npdl = express.Router();
@ -29,6 +30,11 @@ npdl.get([
return;
}
const { clientHasCached } = handleEtag(request, response, file.hash);
if (clientHasCached) {
return sendEtagCacheResponse(response);
}
const readStream = await getCDNFileAsStream('taskFile', file.file_key);
if (!readStream) {
response.sendStatus(404);

View File

@ -10,7 +10,7 @@ import type { AccountClient } from '@pretendonetwork/grpc/account/account_servic
import type { GetNEXDataResponse } from '@pretendonetwork/grpc/account/get_nex_data_rpc';
import type { GetUserDataResponse } from '@pretendonetwork/grpc/account/get_user_data_rpc';
import type { GetUserFriendPIDsResponse } from '@pretendonetwork/grpc/friends/get_user_friend_pids_rpc';
import type { Response } from 'express';
import type { Request, Response } from 'express';
import type { Stats } from 'node:fs';
const gRPCAccountChannel = createChannel(`${config.grpc.account.address}:${config.grpc.account.port}`);
@ -148,3 +148,16 @@ export async function getFriends(pid: number): Promise<GetUserFriendPIDsResponse
return null;
}
}
export function handleEtag(request: Request, response: Response, hash: string): { clientHasCached: boolean } {
const etag = `"${hash}"`;
response.setHeader('ETag', etag);
if (request.headers['if-none-match'] === etag) {
return { clientHasCached: true };
}
return { clientHasCached: false };
}
export function sendEtagCacheResponse(response: Response): void {
response.sendStatus(304).end();
}