This commit is contained in:
Copilot 2026-06-22 02:05:03 +00:00 committed by GitHub
commit 8ab3c2484d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 47 additions and 0 deletions

View file

@ -112,6 +112,14 @@ export class FileServerFileResolver {
};
}
// Verify the file actually exists on disk before returning.
// Unlike the thumbnail/webpublic cases above where detectType() implicitly
// checks this, the original file path is returned without an existence check.
// Without this check, the handler would set immutable cache headers before
// discovering the file is missing, causing CDN caches to cache the error
// response for 1 year (max-age=31536000, immutable) instead of max-age=300.
await fs.promises.access(path);
return {
kind: 'stored',
fileRole: 'original',

View file

@ -479,6 +479,24 @@ describe('FileServerService', () => {
expect(res.headers['cache-control']).toBe('max-age=86400');
});
test('GET /files/:key DBに存在するがストレージ上に存在しないファイルにアクセスしたときエラーのキャッシュをimmutableにしない', async () => {
const accessKey = randomString();
// Insert into DB as storedInternal but do NOT write the file to disk
await insertDriveFile({
accessKey,
storedInternal: true,
isLink: false,
});
const res = await fastify.inject({
method: 'GET',
url: `/files/${accessKey}`,
});
expect(res.statusCode).toBe(500);
expect(res.headers['cache-control']).toBe('max-age=300');
});
test('GET /files/:key 外部リンクを取得して配信する', async () => {
const accessKey = randomString();
await insertDriveFile({
@ -766,5 +784,26 @@ describe('FileServerService', () => {
expect(res.headers['cache-control']).toBe('max-age=31536000, immutable');
expect(res.headers['content-disposition'] ?? '').toContain('dummy.png');
});
test('GET /proxy/:url* DBに存在するがストレージ上に存在しないファイルにアクセスしたときエラーのキャッシュをimmutableにしない', async () => {
const accessKey = randomString();
// Insert into DB as storedInternal but do NOT write the file to disk
await insertDriveFile({
accessKey,
storedInternal: true,
isLink: false,
});
const res = await fastify.inject({
method: 'GET',
url: `/proxy/any?url=${encodeURIComponent(`${config.url}/files/${accessKey}`)}&origin=1`,
headers: {
'user-agent': 'Mozilla/5.0',
},
});
expect(res.statusCode).toBe(500);
expect(res.headers['cache-control']).toBe('max-age=300');
});
});
});