NeahNew/app/api/missions/test-n8n-config/route.ts
2026-01-08 09:34:10 +01:00

140 lines
4.8 KiB
TypeScript

import { NextResponse } from 'next/server';
import { getServerSession } from 'next-auth';
import { authOptions } from "@/app/api/auth/options";
import { logger } from '@/lib/logger';
/**
* GET /api/missions/test-n8n-config
*
* Endpoint de test pour vérifier la configuration N8N
* Permet de diagnostiquer les problèmes de connexion entre Next.js et N8N
*
* Authentification: Requise (session utilisateur)
*/
export async function GET(request: Request) {
try {
// Vérifier l'authentification
const session = await getServerSession(authOptions);
if (!session?.user) {
return NextResponse.json(
{ error: 'Unauthorized' },
{ status: 401 }
);
}
// Récupérer les variables d'environnement
const n8nApiKey = process.env.N8N_API_KEY;
const n8nWebhookUrl = process.env.N8N_WEBHOOK_URL || 'https://brain.slm-lab.net/webhook/mission-created';
const n8nRollbackWebhookUrl = process.env.N8N_ROLLBACK_WEBHOOK_URL || 'https://brain.slm-lab.net/webhook/mission-rollback';
const missionApiUrl = process.env.NEXT_PUBLIC_API_URL || 'https://api.slm-lab.net/api';
const n8nDeleteWebhookUrl = process.env.N8N_DELETE_WEBHOOK_URL;
// Construire la réponse
const config = {
// Variables d'environnement
environment: {
hasN8NApiKey: !!n8nApiKey,
n8nApiKeyLength: n8nApiKey?.length || 0,
n8nApiKeyPrefix: n8nApiKey ? `${n8nApiKey.substring(0, 4)}...` : 'none',
n8nWebhookUrl,
n8nRollbackWebhookUrl,
n8nDeleteWebhookUrl: n8nDeleteWebhookUrl || 'not configured',
missionApiUrl,
},
// URLs construites
urls: {
webhookUrl: n8nWebhookUrl,
callbackUrl: `${missionApiUrl}/api/missions/mission-created`,
rollbackUrl: n8nRollbackWebhookUrl,
deleteUrl: n8nDeleteWebhookUrl || 'not configured',
},
// Statut de configuration
status: {
configured: !!n8nApiKey && !!missionApiUrl,
missingApiKey: !n8nApiKey,
missingApiUrl: !missionApiUrl,
ready: !!n8nApiKey && !!missionApiUrl,
},
// Recommandations
recommendations: [] as string[],
};
// Ajouter des recommandations basées sur la configuration
if (!n8nApiKey) {
config.recommendations.push('❌ N8N_API_KEY n\'est pas défini. Ajoutez-le à vos variables d\'environnement.');
} else {
config.recommendations.push('✅ N8N_API_KEY est configuré');
}
if (!missionApiUrl) {
config.recommendations.push('⚠️ NEXT_PUBLIC_API_URL n\'est pas défini. Utilisation de la valeur par défaut.');
} else {
config.recommendations.push('✅ NEXT_PUBLIC_API_URL est configuré');
}
if (n8nApiKey && n8nApiKey.length < 10) {
config.recommendations.push('⚠️ N8N_API_KEY semble trop court. Vérifiez qu\'il est correct.');
}
// Tester la connectivité au webhook N8N (optionnel, peut être lent)
const testWebhook = request.headers.get('x-test-webhook') === 'true';
if (testWebhook) {
try {
logger.debug('Testing N8N webhook connectivity', { url: n8nWebhookUrl });
const testResponse = await fetch(n8nWebhookUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': n8nApiKey || '',
},
body: JSON.stringify({ test: true }),
signal: AbortSignal.timeout(5000), // 5 secondes timeout
});
config.urls.webhookTest = {
status: testResponse.status,
statusText: testResponse.statusText,
reachable: testResponse.status !== 0,
note: testResponse.status === 404
? 'Webhook non enregistré (workflow inactif?)'
: testResponse.status === 200 || testResponse.status === 400 || testResponse.status === 500
? 'Webhook actif (peut échouer avec des données de test)'
: 'Réponse inattendue',
};
} catch (error) {
config.urls.webhookTest = {
error: error instanceof Error ? error.message : 'Unknown error',
reachable: false,
note: 'Impossible de joindre le webhook N8N',
};
}
} else {
config.urls.webhookTest = {
note: 'Ajoutez le header "x-test-webhook: true" pour tester la connectivité',
};
}
return NextResponse.json({
success: true,
timestamp: new Date().toISOString(),
...config,
});
} catch (error) {
logger.error('Error in test-n8n-config endpoint', {
error: error instanceof Error ? error.message : String(error)
});
return NextResponse.json(
{
success: false,
error: 'Failed to check N8N configuration',
details: error instanceof Error ? error.message : 'Unknown error'
},
{ status: 500 }
);
}
}