API Submit
API Submit
Documentation technique
Type de ressource : Route Astro (Endpoint API)
Fichier source :src/pages/api/submit.ts
Statut : Actif
1. Vue d’ensemble
1.1. Description
Endpoint API pour la soumission du formulaire de contact. Valide les données, envoie vers le form-handler Worker (local ou production via Cloudflare binding), et retourne le résultat. Partie intégrante du flux L1+L2+L3.
1.2. Objectif
- Recevoir les soumissions du formulaire de contact
- Valider les données
- Envoyer vers le backend L3 (Cloudflare Workers)
- Retourner le résultat au frontend
1.3. Caractéristiques
| Propriété | Valeur |
|---|---|
| URL publique | /api/submit |
| Mode de rendu | SSR |
| Type | Endpoint API (JSON) |
| Méthode HTTP | POST |
| Authentification requise | Non |
| Cache | No-store |
2. Architecture et flux
[Formulaire soumis] │ • POST /api/submit ▼[Endpoint /api/submit] │ • Détection de l'environnement (local vs production) ▼[Local] │ • Fetch vers http://localhost:8789/test-direct ▼[Form-handler Worker (local)] │ • Validation Zod │ • Création directe dans Sanity ▼[Sanity CMS]
[Production] │ • Utilisation du service binding FORM_HANDLER ▼[Form-handler Worker (Cloudflare)] │ • Validation Zod │ • Mise en queue dans submissions-queue ▼[Queue Cloudflare] │ ▼[Submission-processor Worker] │ • Création du document Sanity ▼[Sanity CMS]2.2. Composants impliqués
| Composant | Rôle | Couche |
|---|---|---|
api/submit.ts |
Définition de l’endpoint | L2 (Astro) |
| Form-handler Worker | Validation et mise en queue | L3 (Cloudflare) |
| Submission-processor Worker | Création document Sanity | L3 (Cloudflare) |
| Queue Cloudflare | Queue asynchrone | L3 (Cloudflare) |
| Sanity CMS | Stockage des soumissions | L1 (Sanity) |
3. Implémentation
3.1. Code de l’endpoint1/2
3.1. Code de l’endpoint2/2
import type { APIRoute } from 'astro';import { env } from 'cloudflare:workers';export const prerender = false;
export const POST: APIRoute = async (context) => { const { request } = context;
try { const data = await request.json();
const url = new URL(request.url); const isLocal = url.hostname === 'localhost' || url.hostname === '127.0.0.1' || url.port === '4321';
let response: Response;
if (isLocal) { // En local, on continue d'appeler le port local en HTTP classique response = await fetch('http://localhost:8789/test-direct', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data), }); } else { // En production : Utilisation de l'import natif validé par Astro v6 const formHandler = (env as any).FORM_HANDLER;
if (!formHandler) { const keys = Object.keys(env || {}); throw new Error(`Le Service Binding 'FORM_HANDLER' est introuvable. Éléments dispo dans env: [${keys.join(', ')}]`); }
// Appel sécurisé via le binding avec l'URL interne response = await formHandler.fetch('http://internal/api/submit', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data), }); }
const responseText = await response.text();
try { const result = JSON.parse(responseText); return new Response(JSON.stringify(result), { status: response.status, headers: { 'Content-Type': 'application/json' }, }); } catch { return new Response(JSON.stringify({ success: false, error: 'Invalid JSON response from downstream worker', details: responseText }), { status: response.status, headers: { 'Content-Type': 'application/json' }, }); }
} catch (error: any) { console.error('Erreur réelle détectée lors de la soumission :', error.stack || error.message || error);
return new Response(JSON.stringify({ success: false, error: 'Failed to process submission', debugMessage: error.message, debugStack: error.stack }), { status: 500, headers: { 'Content-Type': 'application/json' }, }); }};4. Données et requêtes GROQ
Aucune requête GROQ n’est utilisée dans cet endpoint (la logique est déléguée aux Workers).
5. Paramètres et validation
5.1. Body JSON
| Champ | Type | Obligatoire | Validation |
|---|---|---|---|
name |
string |
✅ | Min 2, Max 100 (validé par Worker) |
email |
string |
✅ | Format email (validé par Worker) |
message |
string |
✅ | Min 10, Max 2000 (validé par Worker) |
5.2. Gestion des erreurs
| Code HTTP | Condition | Réponse |
|---|---|---|
| 200 | Succès | JSON avec success: true |
| 400 | Validation échouée | JSON avec error: validation |
| 500 | Erreur serveur | JSON avec error + debug info |
6. Stratégie de cache
6.1. En-têtes de cache
| Mode | Cache-Control |
Rationale |
|---|---|---|
| API (POST) | Non configuré | À configurer (no-store recommandé) |
6.2. Implémentation dans l’endpoint
Non implémenté - pas de headers de cache explicites.
7. SEO et métadonnées
Non applicable (endpoint API).
8. Composants UI utilisés
Aucun composant UI n’est utilisé (endpoint API).
9. Sécurité
9.1. Accès et authentification
| Condition | Comportement |
|---|---|
| Accès public | Endpoint accessible sans authentification |
9.2. Validation des entrées
- ✅ Validation côté serveur via Zod (Worker)
- ✅ Validation côté client (HTML5)
9.3. En-têtes de sécurité
Non implémenté dans cet endpoint (à configurer via Middleware Cloudflare).
10. Débogage et troubleshooting
10.1. Problèmes courants
| Symptôme | Cause probable | Solution |
|---|---|---|
| Service binding introuvable | FORM_HANDLER non configuré | Vérifier apps/web/wrangler.toml |
| Erreur 500 | Worker inaccessible | Vérifier que le form-handler Worker est démarré |
| JSON invalide | Worker retourne une réponse non-JSON | Vérifier les logs du Worker |
10.2. Logs et monitoring
# Logs de développementnpm run dev
# Logs du form-handler Workerwrangler tail form-handler
# Logs du submission-processor Workerwrangler tail submission-processor10.3. Tests manuels
# Test de l'endpoint en localcurl -X POST http://localhost:4321/api/submit \ -H "Content-Type: application/json" \ -d '{"name":"Test","email":"test@example.com","message":"Test message"}'11. Bonnes pratiques
11.1. Architecture
- ✅ Détection automatique de l’environnement (local vs production)
- ✅ Utilisation des Cloudflare bindings en production
- ✅ Fallback vers HTTP local en développement
- ✅ Logging des erreurs avec stack trace
11.2. Performance
- ✅ Asynchrone (pas de blocage)
- ✅ Queue pour le traitement en arrière-plan
11.3. Maintenance
- ✅ Vérifier la configuration des bindings Cloudflare
- ✅ Surveiller les logs des Workers
12. Évolutions et roadmap
12.1. Améliorations planifiées
- Configuration des headers de cache (no-store)
- Ajout de rate limiting
- Ajout de CAPTCHA
12.2. Limitations connues
- ❌ Headers de cache non configurés
- ❌ Pas de rate limiting
- ❌ Pas de CAPTCHA
- ⚠️ Utilisation de
as anypour le binding FORM_HANDLER
13. Ressources liées
- Documentation Astro : Endpoints
- Documentation Cloudflare : Service Bindings
- Fichiers concernés :
src/pages/api/submit.tsservices/form-handler/src/index.tsservices/submission-processor/src/index.tsapps/web/wrangler.toml
14. Historique des modifications
| Date | Version | Description | Auteur |
|---|---|---|---|
| 2026-09-15 | 1.0 | Création initiale | Devin |