Form Handler
Type de ressource : Cloudflare Worker (Microservice FaaS)
Fichier source :services/form-handler/src/index.ts
Statut : Actif
1. Vue dâensemble
Section titled â1. Vue dâensembleâ1.1. Description
Section titled â1.1. DescriptionâWorker Cloudflare pour la validation et la mise en queue des soumissions de formulaire. Valide les donnĂ©es entrantes via Zod, crĂ©e un objet de soumission avec mĂ©tadonnĂ©es, et lâenvoie dans la Queue Cloudflare pour un traitement asynchrone.
1.2. Objectif
Section titled â1.2. Objectifâ- Valider les soumissions de formulaire cĂŽtĂ© serveur
- Découpler la validation du traitement asynchrone
- Utiliser une Queue Cloudflare pour le traitement en arriĂšre-plan
- Fournir une réponse immédiate au frontend
1.3. Caractéristiques
Section titled â1.3. CaractĂ©ristiquesâ| PropriĂ©tĂ© | Valeur |
|---|---|
| Type | Microservice métier |
| Trigger | HTTP fetch |
| Route publique | /api/submit, /health |
| Environnements | Development, Production |
| Consommateurs | Astro (frontend), Submission-processor (Queue consumer) |
2. Architecture et flux
Section titled â2. Architecture et fluxâ[EntrĂ©e : Astro / Navigateur] â âą POST /api/submit âŒ[Form Handler Worker] â âą Validation Zod (name, email, message) â âą CrĂ©ation de l'objet de soumission â âą Envoi dans la Queue âŒ[Queue Cloudflare (submissions-queue)] â âŒ[Submission-processor Worker] â âą CrĂ©ation du document Sanity âŒ[Sanity CMS]2.2. Positionnement dans la chaĂźne Edge
Section titled â2.2. Positionnement dans la chaĂźne Edgeâ[Client] â âŒ[Astro Frontend] â âą POST /api/submit âŒ[Form Handler Worker] â âŒ[Queue Cloudflare] â âŒ[Submission-processor Worker] â âŒ[Sanity CMS]2.3. Composants impliquĂ©s
Section titled â2.3. Composants impliquĂ©sâ| Composant | RĂŽle | Type |
|---|---|---|
| Zod | Validation des entrées | BibliothÚque |
| SUBMISSIONS_QUEUE | Queue asynchrone | Cloudflare Binding |
| Submission-processor | Consommateur de la Queue | Cloudflare Worker |
| Sanity API | Stockage des soumissions | Service tiers |
3. Configuration
Section titled â3. Configurationâ3.1. Variables dâenvironnement
Section titled â3.1. Variables dâenvironnementâ| Variable | Description | Obligatoire | Valeur par dĂ©faut |
|---|---|---|---|
ENVIRONMENT |
Environnement (dev/production) | â | dev |
3.2. Bindings Cloudflare
Section titled â3.2. Bindings Cloudflareâ| Binding | Type | Nom | Description |
|---|---|---|---|
| SUBMISSIONS_QUEUE | Queue | SUBMISSIONS_QUEUE | Queue pour les soumissions |
3.3. Configuration Wrangler (wrangler.toml)
Section titled â3.3. Configuration Wrangler (wrangler.toml)âname = "amn-form-handler"main = "src/index.ts"compatibility_date = "2025-07-18"compatibility_flags = ["nodejs_compat"]
[vars]ENVIRONMENT = "dev"
[[queues.producers]]queue = "submissions-queue-dev"binding = "SUBMISSIONS_QUEUE"
[env.dev]name = "amn-form-handler-dev"vars = { ENVIRONMENT = "dev" }
[[env.dev.queues.producers]]queue = "submissions-queue-dev"binding = "SUBMISSIONS_QUEUE"
[env.production]name = "amn-form-handler-prod"vars = { ENVIRONMENT = "production" }
[[env.production.queues.producers]]queue = "submissions-queue-prod"binding = "SUBMISSIONS_QUEUE"3.4. Injection des secrets
Section titled â3.4. Injection des secretsâAucun secret nâest injectĂ© dans ce service.
4. Implémentation
Section titled â4. ImplĂ©mentationâ4.1. Code de production (src/index.ts)
Section titled â4.1. Code de production (src/index.ts)âimport { z } from 'zod'
// Schema validation for form submissionconst SubmissionSchema = z.object({ name: z.string().min(2).max(100), email: z.string().email(), message: z.string().min(10).max(2000),})
export interface Env { SUBMISSIONS_QUEUE: Queue; ENVIRONMENT: string;}
export default { async fetch(request: Request, env: Env): Promise<Response> { const url = new URL(request.url);
// Handle CORS preflight if (request.method === 'OPTIONS') { return handleCors(); }
// Handle POST requests for form submission if (request.method === 'POST' && url.pathname === '/api/submit') { return handleSubmit(request, env); }
// Health check endpoint if (request.method === 'GET' && url.pathname === '/health') { return new Response(JSON.stringify({ status: 'healthy', environment: env.ENVIRONMENT, timestamp: new Date().toISOString() }), { headers: { 'Content-Type': 'application/json' }, }); }
return new Response('Not Found', { status: 404 }); },};
async function handleSubmit(request: Request, env: Env): Promise<Response> { try { const body = await request.json();
// Validate input const validatedData = SubmissionSchema.parse(body);
// Create submission object with metadata const submission = { ...validatedData, submittedAt: new Date().toISOString(), id: crypto.randomUUID(), environment: env.ENVIRONMENT, };
// Send to queue for async processing await env.SUBMISSIONS_QUEUE.send(submission);
// Return immediate success response return new Response(JSON.stringify({ success: true, message: 'Form submitted successfully', id: submission.id, }), { headers: { 'Content-Type': 'application/json', ...corsHeaders(), }, });
} catch (error) { if (error instanceof z.ZodError) { return new Response(JSON.stringify({ success: false, error: 'Validation failed', details: error.issues, }), { status: 400, headers: { 'Content-Type': 'application/json', ...corsHeaders(), }, }); }
console.error('Submission error:', error); return new Response(JSON.stringify({ success: false, error: 'Internal server error', }), { status: 500, headers: { 'Content-Type': 'application/json', ...corsHeaders(), }, }); }}
function corsHeaders(): Record<string, string> { return { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'POST, OPTIONS', 'Access-Control-Allow-Headers': 'Content-Type', };}
function handleCors(): Response { return new Response(null, { status: 204, headers: corsHeaders(), });}4.2. Interfaces et types
Section titled â4.2. Interfaces et typesâ// Schema Zodconst SubmissionSchema = z.object({ name: z.string().min(2).max(100), email: z.string().email(), message: z.string().min(10).max(2000),});
// Interface des bindingsexport interface Env { SUBMISSIONS_QUEUE: Queue; ENVIRONMENT: string;}
// Type de soumissiontype Submission = { name: string; email: string; message: string; submittedAt: string; id: string; environment: string;};5. Sécurité
Section titled â5. SĂ©curitĂ©â5.1. MĂ©canismes de sĂ©curitĂ©
Section titled â5.1. MĂ©canismes de sĂ©curitĂ©â| MĂ©canisme | ImplĂ©mentation | Rationale |
|---|---|---|
| Validation Zod | Validation stricte des entrées | Prévention des injections |
| CORS | Headers CORS permissifs | Permettre les requĂȘtes cross-origin |
| Aucun secret | Pas de secret injecté | Pas de données sensibles dans ce service |
5.2. Validation des entrées
Section titled â5.2. Validation des entrĂ©esâ- â Validation Zod du nom (min 2, max 100)
- â Validation Zod de lâemail (format email)
- â Validation Zod du message (min 10, max 2000)
5.3. Gestion des secrets
Section titled â5.3. Gestion des secretsâNon applicable - aucun secret nâest utilisĂ© dans ce service.
6. Résilience et gestion des erreurs
Section titled â6. RĂ©silience et gestion des erreursâ6.1. StratĂ©gie de retry
Section titled â6.1. StratĂ©gie de retryâ| ScĂ©nario | StratĂ©gie | Rationale |
|---|---|---|
| Queue failure | Pas de retry | Simple retry dans le Queue consumer |
6.2. Safety Locks
Section titled â6.2. Safety LocksâNon implĂ©mentĂ© - pas de lock configurĂ©.
6.3. Gestion des timeouts
Section titled â6.3. Gestion des timeoutsâ- â Timeout global : DĂ©pend de Cloudflare (30s Free / 50s Paid)
- â Timeout par service tiers : DĂ©pend de Cloudflare
7. Performance et limites
Section titled â7. Performance et limitesâ7.1. Limites Cloudflare Workers
Section titled â7.1. Limites Cloudflare Workersâ| Limite | Valeur | StratĂ©gie dâoptimisation |
|---|---|---|
| Mémoire RAM | 128 MB | Pas de traitement lourd en mémoire |
| CPU time | 30s (Free) / 50s (Paid) | Validation rapide |
| Nombre de sous-requĂȘtes | 50 | Pas de sous-requĂȘtes |
| Taille requĂȘte/rĂ©ponse | 100 MB | Payload de formulaire limitĂ© |
7.2. Optimisations appliquées
Section titled â7.2. Optimisations appliquĂ©esâ- â Validation rapide (Zod)
- â Mise en queue asynchrone (pas dâattente pour le traitement)
- â Pas de chargement en mĂ©moire
8. Monitoring et observabilité
Section titled â8. Monitoring et observabilitĂ©â8.1. Logs structurĂ©s
Section titled â8.1. Logs structurĂ©sâNon implĂ©mentĂ© - logs console.error basiques.
8.2. Métriques clés
Section titled â8.2. MĂ©triques clĂ©sâNon implĂ©mentĂ© - aucune mĂ©trique ou alerte nâest configurĂ©e.
8.3. Commandes de debug
Section titled â8.3. Commandes de debugâ# Logs en temps rĂ©elwrangler tail form-handler
# Vérification des bindingswrangler deployments list9. Déploiement
Section titled â9. DĂ©ploiementâ9.1. Pipeline de dĂ©ploiement
Section titled â9.1. Pipeline de dĂ©ploiementâ# Buildnpm run build --workspace=services/form-handler
# Déploiement stagingwrangler deploy --env staging
# Déploiement productionwrangler deploy --env production9.2. Rollback
Section titled â9.2. Rollbackâ# Liste des dĂ©ploiementswrangler deployments list
# Rollback vers une version précédentewrangler deployments rollback --deployment-id=[id]9.3. Tests manuels
Section titled â9.3. Tests manuelsâ# Test HTTPcurl -X POST http://localhost:8789/api/submit \ -H "Content-Type: application/json" \ -d '{"name":"Test","email":"test@example.com","message":"Test message"}'
# Test health checkcurl http://localhost:8789/health10. Débogage et troubleshooting
Section titled â10. DĂ©bogage et troubleshootingâ10.1. ProblĂšmes courants
Section titled â10.1. ProblĂšmes courantsâ| SymptĂŽme | Cause probable | Solution |
|---|---|---|
| Validation échoue | Données invalides | Vérifier les rÚgles Zod |
| Queue non disponible | Binding mal configuré | Vérifier wrangler.toml |
| CORS error | Headers CORS manquants | Vérifier la configuration CORS |
10.2. Erreurs fréquentes
Section titled â10.2. Erreurs frĂ©quentesâ| Code HTTP / Erreur | Signification | Action |
|---|---|---|
| 400 | Validation échouée | Corriger les données du formulaire |
| 500 | Erreur serveur | Vérifier les logs du Worker |
11. Bonnes pratiques
Section titled â11. Bonnes pratiquesâ11.1. Architecture
Section titled â11.1. Architectureâ- â DĂ©coupler la validation du traitement asynchrone
- â Utiliser les bindings Cloudflare plutĂŽt que des appels HTTP internes
- â ResponsabilitĂ© unique (validation et mise en queue)
11.2. Code
Section titled â11.2. Codeâ- â Typer strictement les bindings et les rĂ©ponses
- â Valider toutes les entrĂ©es (Zod)
- â GĂ©rer explicitement les erreurs (try/catch)
- â Logger les erreurs
11.3. Sécurité
Section titled â11.3. SĂ©curitĂ©â- â Valider toutes les entrĂ©es cĂŽtĂ© serveur
- â Utiliser Zod pour la validation
11.4. Performance
Section titled â11.4. Performanceâ- â Validation rapide
- â Mise en queue asynchrone
12. Ăvolutions et roadmap
Section titled â12. Ăvolutions et roadmapâ12.1. AmĂ©liorations planifiĂ©es
Section titled â12.1. AmĂ©liorations planifiĂ©esâ- Configuration de Logpush pour les logs
- Ajout de métriques et alertes
- Ajout de rate limiting
- Amélioration de la validation (CAPTCHA)
12.2. Limitations connues
Section titled â12.2. Limitations connuesâ- â CORS permissif (
*) - Ă restreindre pour la production - â Pas de rate limiting
- â Pas de logs structurĂ©s
- â Pas de monitoring configurĂ©
13. Ressources liées
Section titled â13. Ressources liĂ©esâ- Documentation Cloudflare Workers : Getting Started
- Documentation Cloudflare Queues : Queues
- Documentation Zod : Zod
- Workers associés :
- submission-processor
- Fichiers concernés :
services/form-handler/src/index.tsservices/form-handler/wrangler.tomlservices/form-handler/package.json
14. Historique des modifications
Section titled â14. Historique des modificationsâ| Date | Version | Description | Auteur |
|---|---|---|---|
| 2026-09-15 | 1.0 | Création initiale | Devin |