Enable private caching headers for segment audio routes

This commit is contained in:
Richard R 2026-05-13 23:44:13 -06:00
parent ef2ee09064
commit da629b3ecd
4 changed files with 41 additions and 3 deletions

View file

@ -1,6 +1,7 @@
import { NextRequest, NextResponse } from 'next/server';
import { isS3Configured } from '@/lib/server/storage/s3';
import {
buildSegmentAudioCacheHeaders,
resolveCompletedSegmentAudio,
streamAudioBuffer,
ttsSegmentsS3NotConfiguredResponse,
@ -20,7 +21,7 @@ export async function GET(request: NextRequest) {
return new NextResponse(streamAudioBuffer(audio), {
headers: {
'Content-Type': 'audio/mpeg',
'Cache-Control': 'no-store',
...buildSegmentAudioCacheHeaders('fallback'),
},
});
} catch (error) {

View file

@ -1,6 +1,7 @@
import { NextRequest, NextResponse } from 'next/server';
import { isS3Configured } from '@/lib/server/storage/s3';
import {
buildSegmentAudioCacheHeaders,
resolveCompletedSegmentAudio,
ttsSegmentsS3NotConfiguredResponse,
} from '@/lib/server/tts/segments-audio';
@ -24,13 +25,13 @@ export async function GET(request: NextRequest) {
});
return NextResponse.redirect(fallbackUrl, {
status: 307,
headers: { 'Cache-Control': 'no-store' },
headers: buildSegmentAudioCacheHeaders('redirect'),
});
}
return NextResponse.redirect(directUrl, {
status: 307,
headers: { 'Cache-Control': 'no-store' },
headers: buildSegmentAudioCacheHeaders('redirect'),
});
} catch (error) {
console.error('Error creating segment audio signature:', error);

View file

@ -11,6 +11,10 @@ export type ResolvedSegmentAudio = {
audioKey: string;
};
export const TTS_SEGMENT_REDIRECT_CACHE_CONTROL = 'private, max-age=60, stale-while-revalidate=30';
export const TTS_SEGMENT_FALLBACK_CACHE_CONTROL = 'private, max-age=300, stale-while-revalidate=60';
export const TTS_SEGMENT_AUDIO_VARY = 'Cookie, Authorization';
export function ttsSegmentsS3NotConfiguredResponse(): NextResponse {
return NextResponse.json(
{ error: 'TTS segments storage is not configured. Set S3_* environment variables.' },
@ -27,6 +31,15 @@ export function streamAudioBuffer(buffer: Buffer): ReadableStream<Uint8Array> {
});
}
export function buildSegmentAudioCacheHeaders(kind: 'redirect' | 'fallback'): Record<string, string> {
return {
'Cache-Control': kind === 'redirect'
? TTS_SEGMENT_REDIRECT_CACHE_CONTROL
: TTS_SEGMENT_FALLBACK_CACHE_CONTROL,
Vary: TTS_SEGMENT_AUDIO_VARY,
};
}
export async function resolveCompletedSegmentAudio(
request: NextRequest,
): Promise<ResolvedSegmentAudio | Response> {

View file

@ -0,0 +1,23 @@
import { expect, test } from '@playwright/test';
import {
buildSegmentAudioCacheHeaders,
TTS_SEGMENT_AUDIO_VARY,
TTS_SEGMENT_FALLBACK_CACHE_CONTROL,
TTS_SEGMENT_REDIRECT_CACHE_CONTROL,
} from '../../src/lib/server/tts/segments-audio';
test.describe('tts segment audio cache headers', () => {
test('builds redirect cache headers', () => {
expect(buildSegmentAudioCacheHeaders('redirect')).toEqual({
'Cache-Control': TTS_SEGMENT_REDIRECT_CACHE_CONTROL,
Vary: TTS_SEGMENT_AUDIO_VARY,
});
});
test('builds fallback cache headers', () => {
expect(buildSegmentAudioCacheHeaders('fallback')).toEqual({
'Cache-Control': TTS_SEGMENT_FALLBACK_CACHE_CONTROL,
Vary: TTS_SEGMENT_AUDIO_VARY,
});
});
});