Files
aggios.app/front-end-agency/middleware.ts
2025-12-17 13:36:23 -03:00

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).*)',
],
};