[Nom de la Pages Function]
Type de ressource : Cloudflare Pages Function (Endpoint SSR Astro / API Route)
Fichier source :src/pages/api/[endpoint].tsoufunctions/[path].ts
Statut : [Actif / Déprécié / En développement]
1. Vue dâoverview
Section titled â1. Vue dâoverviewâ1.1. Description
Section titled â1.1. Descriptionâ[Description concise du rĂŽle de cette Pages Function dans lâarchitecture SSR du site]
1.2. Objectif
Section titled â1.2. Objectifâ- [Objectif principal : ex. fournir un endpoint SSR pour le mode Preview Sanity]
- [BĂ©nĂ©fice pour lâarchitecture : ex. exĂ©cution Edge sans infrastructure serveur dĂ©diĂ©e]
1.3. Caractéristiques
Section titled â1.3. CaractĂ©ristiquesâ| PropriĂ©tĂ© | Valeur |
|---|---|
| Type | [Endpoint API / Route SSR / Middleware] |
| Méthode HTTP | [GET / POST / PUT / DELETE / Les deux] |
| Route publique | /api/[endpoint] ou /[path] |
| Mode de rendu | SSR (Server-Side Rendering) |
| Cache | [Voir §7] |
| Authentification | [Aucune / Cookie / Token / Les deux] |
2. Architecture et flux
Section titled â2. Architecture et fluxâ2.1. Diagramme de flux
Section titled â2.1. Diagramme de fluxâ[RequĂȘte client] â âŒ[Cloudflare Pages] â âą Routage vers la Pages Function â âą Injection des bindings (Env) âŒ[Pages Function] â âą Validation des entrĂ©es â âą Logique mĂ©tier â âą Interaction avec les bindings (KV, R2, Queue) âŒ[Services tiers / Storage] â âą Sanity API / CRM / R2 / KV âŒ[RĂ©ponse HTTP]2.2. Positionnement dans lâarchitecture
Section titled â2.2. Positionnement dans lâarchitectureâ[Client] â âŒ[Middleware Global (Worker L3)] â SĂ©curitĂ©, CSP, cookies â âŒ[Cloudflare Pages] â âŒ[Pages Function (SSR)] â Cette ressource â âŒ[Astro SSR / Services tiers]2.3. Composants impliquĂ©s
Section titled â2.3. Composants impliquĂ©sâ| Composant | RĂŽle | Type |
|---|---|---|
| Pages Function | Endpoint SSR | Cloudflare Pages |
| Middleware Global | Sécurité + Preview cookie | Worker L3 |
| Bindings Cloudflare | KV / R2 / Queue | Services Cloudflare |
| Astro SSR | Rendu des pages dynamiques | Framework |
3. Configuration
Section titled â3. Configurationâ3.1. Emplacement des fichiers
Section titled â3.1. Emplacement des fichiersâ# Option 1 : Routes API Astro (recommandĂ©)src/pages/âââ api/â âââ preview.ts # Activation du mode Previewâ âââ exit-preview.ts # Sortie du mode Previewâ âââ contact.ts # Endpoint formulaireâ âââ [autre-endpoint].ts
# Option 2 : Functions directory (pour routes non-Astro)functions/âââ api/â âââ webhook.tsâ âââ [autre-endpoint].ts3.2. Variables dâenvironnement requises
Section titled â3.2. Variables dâenvironnement requisesâ| Variable | Description | Obligatoire | Valeur par dĂ©faut |
|---|---|---|---|
| [Variable] | [Description] | [â /â] | [Valeur] |
3.3. Bindings Cloudflare disponibles
Section titled â3.3. Bindings Cloudflare disponiblesâ| Binding | Type | Nom | Description |
|---|---|---|---|
| [Nom] | [KV / R2 / Queue / Secret] | [Binding name] | [Description] |
3.4. Configuration dans astro.config.mjs
Section titled â3.4. Configuration dans astro.config.mjsâimport cloudflare from '@astrojs/cloudflare';
export default defineConfig({ output: 'hybrid', // SSG par défaut, SSR explicite adapter: cloudflare({ platformProxy: { enabled: true, // Facilite le développement local avec Wrangler }, }),});4. Implémentation
Section titled â4. ImplĂ©mentationâ4.1. Variante : Endpoint API (POST)
Section titled â4.1. Variante : Endpoint API (POST)âimport type { APIContext } from 'astro';
export const prerender = false; // SSR obligatoire
export async function POST({ request, locals }: APIContext) { try { const body = await request.json();
// Validation des entrées if (!body.email || !body.message) { return new Response(JSON.stringify({ error: 'Champs manquants' }), { status: 400, headers: { 'Content-Type': 'application/json' }, }); }
// Interaction avec les bindings await locals.runtime.env.SUBMISSIONS_QUEUE.send({ email: body.email, message: body.message, submittedAt: new Date().toISOString(), });
return new Response(JSON.stringify({ success: true }), { status: 200, headers: { 'Content-Type': 'application/json', 'Cache-Control': 'no-store', }, }); } catch (error) { console.error('Erreur API contact:', error); return new Response(JSON.stringify({ error: 'Erreur serveur' }), { status: 500, headers: { 'Content-Type': 'application/json' }, }); }}4.2. Variante : Endpoint Preview (GET)
Section titled â4.2. Variante : Endpoint Preview (GET)âimport type { APIContext } from 'astro';
export const prerender = false;
export async function GET({ request, cookies, redirect }: APIContext) { const url = new URL(request.url); const secret = url.searchParams.get('secret'); const slug = url.searchParams.get('slug') || '/';
// Validation du secret (déjà faite par le Middleware, mais double vérification) if (!secret || secret !== import.meta.env.SANITY_PREVIEW_SECRET) { return new Response('Jeton invalide', { status: 401 }); }
// Pose du cookie de preview cookies.set('sanity-preview', 'true', { path: '/', httpOnly: true, secure: true, sameSite: 'lax', maxAge: 3600, // 1 heure });
// Redirection vers la page demandée return redirect(slug, 307);}4.3. Variante : Endpoint Exit Preview (GET)
Section titled â4.3. Variante : Endpoint Exit Preview (GET)âimport type { APIContext } from 'astro';
export const prerender = false;
export async function GET({ cookies, redirect }: APIContext) { // Suppression du cookie de preview cookies.delete('sanity-preview', { path: '/' });
// Redirection vers l'accueil return redirect('/', 302);}4.4. Variante : Page SSR dynamique
Section titled â4.4. Variante : Page SSR dynamiqueâ---export const prerender = false; // SSR obligatoire
import ContactForm from '../components/interactive/ContactForm';import BaseLayout from '../layouts/BaseLayout.astro';
// AccĂšs aux bindings via locals.runtime.envconst env = Astro.locals.runtime.env;
// Logique SSR (si nécessaire)const siteConfig = await env.KV_BINDING.get('site-config', 'json');---
<BaseLayout title="Contact" description="Formulaire de contact"> <ContactForm apiEndpoint="/api/contact" /></BaseLayout>5. AccĂšs aux bindings Cloudflare
Section titled â5. AccĂšs aux bindings Cloudflareâ5.1. Via locals.runtime.env (Astro)
Section titled â5.1. Via locals.runtime.env (Astro)â// Dans une page ou endpoint Astroexport async function GET({ locals }: APIContext) { const env = locals.runtime.env;
// AccĂšs KV const value = await env.KV_BINDING.get('key');
// AccĂšs R2 const object = await env.R2_BUCKET.get('path/to/file');
// AccĂšs Queue await env.QUEUE_BINDING.send({ data: 'value' });
// AccĂšs Secret const secret = env.SECRET_NAME;
return new Response('OK');}5.2. Via env (Pages Functions standalone)
Section titled â5.2. Via env (Pages Functions standalone)âexport interface Env { KV_BINDING: KVNamespace; R2_BUCKET: R2Bucket; QUEUE_BINDING: Queue; SECRET_NAME: string;}
export const onRequestPost: PagesFunction<Env> = async (context) => { const { env, request } = context;
// Utilisation des bindings await env.KV_BINDING.put('key', 'value');
return new Response('OK');};6. Sécurité
Section titled â6. SĂ©curitĂ©â6.1. Validation des entrĂ©es
Section titled â6.1. Validation des entrĂ©esâ- â Valider tous les paramĂštres dâURL et query strings
- â Valider les corps de requĂȘte (JSON, FormData)
- â Utiliser des schĂ©mas de validation (Zod, Yup)
- â Sanitiser les entrĂ©es avant traitement
6.2. Protection CSRF
Section titled â6.2. Protection CSRFâ// VĂ©rification du token CSRF (si applicable)const csrfToken = request.headers.get('x-csrf-token');if (!csrfToken || csrfToken !== expectedToken) { return new Response('CSRF token invalide', { status: 403 });}6.3. Rate Limiting
Section titled â6.3. Rate Limitingâ// Rate limiting simple via KV (si nĂ©cessaire)const ip = request.headers.get('cf-connecting-ip');const rateLimitKey = `rate-limit:${ip}`;const currentCount = await env.KV_BINDING.get(rateLimitKey, 'json') || 0;
if (currentCount >= 10) { // 10 requĂȘtes max return new Response('Too Many Requests', { status: 429 });}
await env.KV_BINDING.put(rateLimitKey, currentCount + 1, { expirationTtl: 60 });6.4. RÚgles de sécurité
Section titled â6.4. RĂšgles de sĂ©curitĂ©â- â Ne jamais exposer les secrets dans les rĂ©ponses
- â Valider cryptographiquement les webhooks (HMAC)
- â Utiliser des comparaisons Ă temps constant pour les secrets
- â Limiter les mĂ©thodes HTTP autorisĂ©es (GET, POST uniquement)
- â Appliquer une CSP stricte (via Middleware)
7. Stratégie de cache
Section titled â7. StratĂ©gie de cacheâ7.1. En-tĂȘtes de cache par type
Section titled â7.1. En-tĂȘtes de cache par typeâ| Type de route | Cache-Control | CDN-Cache-Control | Rationale |
|---|---|---|---|
| Endpoint API (GET) | public, max-age=60 |
max-age=300 |
Données semi-dynamiques |
| Endpoint API (POST) | no-store |
no-store |
Jamais en cache |
| Page SSR Preview | no-store, no-cache, must-revalidate, private |
no-store |
Contenu draft |
| Page SSR standard | public, max-age=60 |
max-age=300, stale-while-revalidate=86400 |
Contenu semi-dynamique |
7.2. Implémentation
Section titled â7.2. ImplĂ©mentationâ// Dans un endpoint ou page SSRAstro.response.headers.set('Cache-Control', 'public, max-age=60');Astro.response.headers.set('CDN-Cache-Control', 'max-age=300, stale-while-revalidate=86400');
// Pour les réponses POSTreturn new Response(JSON.stringify(data), { headers: { 'Cache-Control': 'no-store', 'Content-Type': 'application/json', },});8. Performance et limites
Section titled â8. Performance et limitesâ8.1. Limites Cloudflare Pages Functions
Section titled â8.1. Limites Cloudflare Pages Functionsâ| Limite | Valeur | StratĂ©gie dâoptimisation |
|---|---|---|
| Mémoire RAM | 128 MB | Streaming, URLs présignées |
| CPU time | 30s (Free) / 50s (Paid) | Optimisation des traitements |
| Nombre de sous-requĂȘtes | 50 | Minimiser les appels externes |
| Taille requĂȘte/rĂ©ponse | 100 MB | Streaming pour gros volumes |
8.2. Optimisations appliquées
Section titled â8.2. Optimisations appliquĂ©esâ- â Utiliser le streaming HTTP pour les gros volumes
- â DĂ©porter les uploads lourds via URLs prĂ©signĂ©es
- â Mettre en cache les donnĂ©es frĂ©quemment lues (KV)
- â Minimiser le nombre de sous-requĂȘtes
- â
Utiliser
stale-while-revalidatepour les pages SSR
9. Monitoring et observabilité
Section titled â9. Monitoring et observabilitĂ©â9.1. Logs structurĂ©s
Section titled â9.1. Logs structurĂ©sâconsole.log(JSON.stringify({ function: 'api-contact', method: 'POST', status: 'success', duration: 123, metadata: { email: 'user@example.com' }}));9.2. MĂ©triques clĂ©s
Section titled â9.2. MĂ©triques clĂ©sâ| MĂ©trique | Seuil dâalerte | Canal |
|---|---|---|
| Taux dâerreur 5xx | > 1% sur 5 min | Slack |
| Latence p95 | > 500ms | Slack |
| Nombre de requĂȘtes | > 1000/min |
9.3. Commandes de debug
Section titled â9.3. Commandes de debugâ# Logs en temps rĂ©elwrangler pages deployment tail --project-name=[project]
# Liste des déploiementswrangler pages deployment list --project-name=[project]10. Déploiement
Section titled â10. DĂ©ploiementâ10.1. Pipeline de dĂ©ploiement
Section titled â10.1. Pipeline de dĂ©ploiementâ# Build Astro (inclut les Pages Functions)npm run build
# Déploiement automatique via Cloudflare Pages# (déclenché par git push ou webhook)10.2. Rollback
Section titled â10.2. Rollbackâ# Via le Dashboard Cloudflare# Cloudflare Dashboard â Pages â [Project] â Deployments â Rollback10.3. Tests manuels
Section titled â10.3. Tests manuelsâ# Test en localnpm run dev
# Test d'un endpointcurl -X POST http://localhost:4321/api/contact \ -H "Content-Type: application/json" \ -d '{"email": "test@example.com", "message": "Test"}'
# Test en productioncurl -X POST https://votresite.com/api/contact \ -H "Content-Type: application/json" \ -d '{"email": "test@example.com", "message": "Test"}'11. Débogage et troubleshooting
Section titled â11. DĂ©bogage et troubleshootingâ11.1. ProblĂšmes courants
Section titled â11.1. ProblĂšmes courantsâ| SymptĂŽme | Cause probable | Solution |
|---|---|---|
| 500 Internal Server Error | Erreur dans le code | Vérifier les logs Cloudflare |
| 404 Not Found | Route mal configurĂ©e | VĂ©rifier lâemplacement du fichier |
| Bindings non disponibles | Configuration wrangler.toml manquante | Vérifier la configuration |
| Timeout | Traitement trop long | Optimiser ou déporter vers un Worker |
| CORS error | Headers manquants | Ajouter les headers CORS |
11.2. Erreurs fréquentes
Section titled â11.2. Erreurs frĂ©quentesâ| Code HTTP | Signification | Action |
|---|---|---|
| 400 | RequĂȘte malformĂ©e | Valider les entrĂ©es |
| 401 | Non authentifié | Vérifier les tokens/cookies |
| 403 | AccÚs refusé | Vérifier les permissions |
| 404 | Route non trouvĂ©e | VĂ©rifier lâemplacement du fichier |
| 429 | Rate limit dépassé | Implémenter rate limiting |
| 500 | Erreur serveur | Vérifier les logs |
12. Bonnes pratiques
Section titled â12. Bonnes pratiquesâ12.1. Architecture
Section titled â12.1. Architectureâ- â
Préférer les routes API Astro (
src/pages/api/) aux Functions standalone - â Centraliser la logique mĂ©tier dans des services rĂ©utilisables
- â Valider toutes les entrĂ©es (Zod, schĂ©mas custom)
- â GĂ©rer explicitement les erreurs (try/catch)
- â Logger de maniĂšre structurĂ©e (JSON)
12.2. Code
Section titled â12.2. Codeâ- â Typer strictement les bindings et les rĂ©ponses
- â
Utiliser
export const prerender = falsepour les routes SSR - â Retourner des rĂ©ponses JSON avec les bons headers
- â Ne jamais exposer les secrets dans les rĂ©ponses
- â Utiliser les bindings Cloudflare plutĂŽt que des appels HTTP internes
12.3. Sécurité
Section titled â12.3. SĂ©curitĂ©â- â Valider cryptographiquement les webhooks (HMAC)
- â Utiliser des comparaisons Ă temps constant pour les secrets
- â Appliquer une CSP stricte (via Middleware)
- â Limiter les mĂ©thodes HTTP autorisĂ©es
- â ImplĂ©menter un rate limiting si nĂ©cessaire
12.4. Performance
Section titled â12.4. Performanceâ- â Utiliser le streaming HTTP pour les gros volumes
- â DĂ©porter les uploads lourds via URLs prĂ©signĂ©es
- â Mettre en cache les donnĂ©es frĂ©quemment lues
- â Minimiser le nombre de sous-requĂȘtes
- â
Utiliser
stale-while-revalidatepour les pages SSR
13. Ăvolutions et roadmap
Section titled â13. Ăvolutions et roadmapâ13.1. AmĂ©liorations planifiĂ©es
Section titled â13.1. AmĂ©liorations planifiĂ©esâ- [Ăvolution 1 : ex. Ajout de endpoints API pour le headless CMS]
- [Ăvolution 2 : ex. ImplĂ©mentation de GraphQL API]
- [Ăvolution 3 : ex. Support de WebSocket pour le temps rĂ©el]
13.2. Limitations connues
Section titled â13.2. Limitations connuesâ- â Les Pages Functions ont une limite de 128 MB de RAM
- â Le CPU time est limitĂ© Ă 30s (Free) / 50s (Paid)
- â Pas de support natif pour WebSocket (nĂ©cessite Workers)
- â Les bindings ne sont pas disponibles en mode SSG
14. Ressources liées
Section titled â14. Ressources liĂ©esâ- Documentation Cloudflare Pages : Functions
- Documentation Astro : Cloudflare Adapter
- DAT L2 : §2.1 - Mode Hybride & Adaptateur Cloudflare
- DAT L3 : §4 - Pages Functions Astro (SSR)
- Pages Functions associées :
src/pages/api/preview.tssrc/pages/api/exit-preview.tssrc/pages/api/contact.ts
- Fichiers concernés :
src/pages/api/*.tsfunctions/**/*.ts(si applicable)astro.config.mjs
15. Historique des modifications
Section titled â15. Historique des modificationsâ| Date | Version | Description | Auteur |
|---|---|---|---|
| YYYY-MM-DD | 1.0 | Création initiale | [Nom] |
| YYYY-MM-DD | 1.1 | [Modification] | [Nom] |
---
**Points clés de ce template :**- Couvre les deux approches (routes API Astro et Functions standalone)- Détaille l'accÚs aux bindings Cloudflare via `locals.runtime.env`- Inclut la stratégie de cache par type de route- Documente les limites Cloudflare et les stratégies d'optimisation- Fournit les commandes de debug et de rollback- Sépare clairement les bonnes pratiques par catégorie (architecture, code, sécurité, performance)