76 lines
2.8 KiB
TypeScript
76 lines
2.8 KiB
TypeScript
import { NextResponse } from 'next/server';
|
|
import type { NextRequest } from 'next/server';
|
|
|
|
export async function middleware(request: NextRequest) {
|
|
const hostname = request.headers.get('host') || '';
|
|
const url = request.nextUrl;
|
|
|
|
const apiBase = process.env.API_INTERNAL_URL || 'http://backend:8080';
|
|
|
|
// Extrair subdomínio (remover porta se houver)
|
|
const hostnameWithoutPort = hostname.split(':')[0];
|
|
const subdomain = hostnameWithoutPort.split('.')[0];
|
|
|
|
// Se tem subdomínio (ex: vivo.localhost), SEMPRE validar se existe
|
|
if (hostname.includes('.')) {
|
|
try {
|
|
const res = await fetch(`${apiBase}/api/tenant/check?subdomain=${subdomain}`, {
|
|
cache: 'no-store',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
}
|
|
});
|
|
|
|
if (!res.ok) {
|
|
console.error(`❌ Tenant check failed for ${subdomain}: ${res.status}`);
|
|
|
|
if (res.status === 404) {
|
|
console.error(`❌ Tenant ${subdomain} não encontrado - BLOQUEANDO ACESSO`);
|
|
// Tenant não existe, redirecionar para página principal (sem subdomínio)
|
|
const baseHost = hostname.split('.').slice(1).join('.') || 'localhost';
|
|
const redirectUrl = new URL(`http://${baseHost}/`);
|
|
return NextResponse.redirect(redirectUrl);
|
|
}
|
|
}
|
|
|
|
// Se passou pela validação, tenant existe - continuar
|
|
console.log(`✅ Tenant ${subdomain} validado com sucesso`);
|
|
} catch (err) {
|
|
console.error('❌ Middleware error:', err);
|
|
// Em caso de erro de rede, bloquear por segurança
|
|
const baseHost = hostname.split('.').slice(1).join('.') || 'localhost';
|
|
const redirectUrl = new URL(`http://${baseHost}/`);
|
|
return NextResponse.redirect(redirectUrl);
|
|
}
|
|
}
|
|
|
|
// Para requisições de API, adicionar headers com informações do tenant
|
|
if (url.pathname.startsWith('/api/')) {
|
|
// Cria um header customizado com o subdomain
|
|
const requestHeaders = new Headers(request.headers);
|
|
requestHeaders.set('X-Tenant-Subdomain', subdomain);
|
|
requestHeaders.set('X-Original-Host', hostname);
|
|
|
|
return NextResponse.rewrite(url, {
|
|
request: {
|
|
headers: requestHeaders,
|
|
},
|
|
});
|
|
}
|
|
|
|
// Permitir acesso normal
|
|
return NextResponse.next();
|
|
}
|
|
|
|
export const config = {
|
|
matcher: [
|
|
/*
|
|
* Match all request paths except for the ones starting with:
|
|
* - _next/static (static files)
|
|
* - _next/image (image optimization files)
|
|
* - favicon.ico (favicon file)
|
|
*/
|
|
'/((?!_next/static|_next/image|favicon.ico).*)',
|
|
],
|
|
};
|