Ответы и статусы
JSON
return Response.json({ data });
return NextResponse.json({ data });
return Response.json({ data }, { status: 201 });
NextResponse расширяет Response методами для редиректов и cookies.
HTTP-статусы
return Response.json({ error: 'Bad request' }, { status: 400 });
return Response.json({ error: 'Unauthorized' }, { status: 401 });
return Response.json({ error: 'Forbidden' }, { status: 403 });
return Response.json({ error: 'Not found' }, { status: 404 });
return Response.json({ error: 'Method not allowed' }, { status: 405 });
return Response.json({ error: 'Conflict' }, { status: 409 });
return Response.json({ errors }, { status: 422 });
return Response.json({ error: 'Too many requests' }, { status: 429 });
return Response.json({ error: 'Server error' }, { status: 500 });
Пустой ответ
return new Response(null, { status: 204 });
Текст
return new Response('Hello', {
headers: { 'Content-Type': 'text/plain' },
});
HTML
return new Response('<h1>Hello</h1>', {
headers: { 'Content-Type': 'text/html' },
});
Файл
const file = await fs.readFile('./public/document.pdf');
return new Response(file, {
headers: {
'Content-Type': 'application/pdf',
'Content-Disposition': 'attachment; filename="document.pdf"',
},
});
Stream
const stream = new ReadableStream({
async start(controller) {
for (let i = 0; i < 10; i++) {
controller.enqueue(`chunk ${i}\n`);
await new Promise((r) => setTimeout(r, 100));
}
controller.close();
},
});
return new Response(stream, {
headers: { 'Content-Type': 'text/plain' },
});
Редирект
return NextResponse.redirect(new URL('/login', request.url));
return NextResponse.redirect('https://example.com', 301);
Статусы: 301 (permanent), 302 (temporary), 307, 308.
Rewrite
return NextResponse.rewrite(new URL('/proxy', request.url));
Меняет URL без редиректа на клиенте.
Заголовки
return Response.json(data, {
headers: {
'X-Custom-Header': 'value',
'Cache-Control': 'public, max-age=3600',
'ETag': '"abc123"',
},
});
CORS
const corsHeaders = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
'Access-Control-Max-Age': '86400',
};
export async function OPTIONS() {
return new Response(null, { status: 204, headers: corsHeaders });
}
export async function GET() {
const data = await db.post.findMany();
return Response.json(data, { headers: corsHeaders });
}
Множественные Set-Cookie
const response = Response.json({ ok: true });
response.headers.append('Set-Cookie', 'a=1; HttpOnly');
response.headers.append('Set-Cookie', 'b=2; HttpOnly');
return response;
Кеш
return Response.json(data, {
headers: {
'Cache-Control': 'public, s-maxage=60, stale-while-revalidate=300',
},
});
Итоги
Response.jsonдля JSON- Статусы через
{ status } - 204 для пустого
- Стриминг через
ReadableStream NextResponse.redirect,rewrite- CORS через заголовки