Repository navigation
Expand file tree
/
Copy pathproxy.ts
More file actions
107 lines (102 loc) · 3.8 KB
/
Copy pathproxy.ts
File metadata and controls
107 lines (102 loc) · 3.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
/**
* Proxy de Next.js para gestionar la sesión de Supabase
*
* Este proxy se ejecuta en cada request y actualiza las cookies
* de autenticación de Supabase, permitiendo que las Server Actions
* puedan leer correctamente la sesión del usuario.
*
* NOTA: En Next.js 16, el archivo "middleware" fue deprecado en favor de "proxy",
* pero la funcionalidad es idéntica. Este archivo reemplaza a middleware.ts.
*
* @module proxy
*/
import { type NextRequest } from 'next/server';
import { NextResponse } from 'next/server';
import { updateSession } from '@/utils/supabase/middleware';
import { isInvalidRefreshTokenError } from '@/utils/auth-helpers';
// El SDK de @supabase/auth-js llama console.error() internamente cuando
// _callRefreshToken() falla. El error ya está manejado correctamente
// (el middleware hace signOut + limpia cookies), pero el SDK lo imprime
// antes de devolverlo. Filtramos ese ruido específico.
// - refresh_token_not_found: cookie stale tras dev server restart
// - refresh_token_already_used: cookie reusada (otra Mac, pestaña paralela, race)
const SILENCED_AUTH_CODES = new Set([
'refresh_token_not_found',
'refresh_token_already_used',
]);
const _origConsoleError = console.error.bind(console);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
console.error = (...args: any[]) => {
const first = args[0];
if (
first != null &&
typeof first === 'object' &&
first.__isAuthError === true &&
typeof first.code === 'string' &&
SILENCED_AUTH_CODES.has(first.code)
) {
return;
}
_origConsoleError(...args);
};
/**
* Proxy de Next.js
*
* Se ejecuta en cada request antes de que llegue a las rutas.
* Actualiza la sesión de Supabase y devuelve la respuesta con
* las cookies actualizadas.
*
* @param request - Request de Next.js
* @returns Response con cookies actualizadas
*/
export async function proxy(request: NextRequest) {
// Bloquear payloads anormalmente grandes en /login (> 10KB)
// Dificulta ataques de credential stuffing con payloads masivos
if (request.nextUrl.pathname === '/login' && request.method === 'POST') {
const contentLength = request.headers.get('content-length');
if (contentLength && parseInt(contentLength, 10) > 10_240) {
return new NextResponse('Payload demasiado grande', { status: 413 });
}
}
try {
return await updateSession(request);
} catch (error) {
// Token de refresh inválido: no propagar ni loguear (se limpia en updateSession)
if (isInvalidRefreshTokenError(error)) {
return NextResponse.next({ request });
}
// Silenciar errores de conexión abortada (ECONNRESET)
if (error instanceof Error &&
(error.message.includes('aborted') ||
error.message.includes('ECONNRESET') ||
error.message.includes('cancelled'))) {
return new Response(null, { status: 499 }); // Client Closed Request
}
// Para otros errores, loguear y re-lanzar
console.error('[Proxy Error]:', error);
throw error;
}
}
/**
* Configuración del proxy
*
* Define qué rutas deben ejecutar el proxy.
* Ignora archivos estáticos y recursos públicos para mejorar el rendimiento.
*/
export const config = {
matcher: [
/*
* Coincide con todas las rutas excepto:
* - /api/* (rutas de API - deben manejarse por sus propios handlers)
* - _next/static (archivos estáticos)
* - _next/image (optimización de imágenes)
* - _next/api (rutas internas de Next.js)
* - _vercel/* (rutas de Vercel)
* - favicon.ico (favicon)
* - archivos públicos (public folder)
* - archivos de imagen (png, jpg, jpeg, gif, svg, webp)
* - archivos de fuente (woff, woff2, ttf, eot)
*/
'/((?!api/|_next/static|_next/image|_next/api|_vercel|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp|woff|woff2|ttf|eot)$).*)',
],
};