API Preview
API Preview
Documentation technique
Type de ressource : Route Astro (Endpoint API)
Fichier source :src/pages/api/preview.ts
Statut : Actif
1. Vue d’ensemble
1.1. Description
Endpoint API pour activer le mode preview Sanity. Vérifie le secret de preview, pose le cookie sanity-preview, et redirige vers la page demandée. Utilisé par le Sanity Studio pour prévisualiser les drafts.
1.2. Objectif
- Activer le mode preview pour visualiser les drafts Sanity
- Sécuriser l’accès via un secret
- Protéger contre les redirections ouvertes (open-redirect)
- Rediriger vers la page demandée
1.3. Caractéristiques
| Propriété | Valeur |
|---|---|
| URL publique | /api/preview |
| Mode de rendu | SSR |
| Type | Endpoint API (Redirect) |
| Méthode HTTP | GET |
| Authentification requise | Secret de preview |
| Cache | No-store |
2. Architecture et flux
[Requête Sanity Studio] │ • secret + slug ▼[Endpoint /api/preview] │ • Vérification du secret │ • Sanitization du slug (open-redirect protection) │ • Pose du cookie sanity-preview ▼[Redirect (307)] │ ▼[Page demandée (ex: /welcome)] │ • Détection du cookie ▼[Rendu avec perspective previewDrafts]2.2. Composants impliqués
| Composant | Rôle | Couche |
|---|---|---|
api/preview.ts |
Définition de l’endpoint | L2 (Astro) |
| Sanity Studio | Déclencheur du preview | L1 (Sanity) |
| Pages avec preview | Consommatrices du cookie | L2 (Astro) |
3. Implémentation
3.1. Code de l’endpoint1/2
3.1. Code de l’endpoint2/2
import type { APIRoute } from 'astro';
export const prerender = false;
export const GET: APIRoute = async ({ request, cookies, redirect }) => { const url = new URL(request.url); const secret = url.searchParams.get('secret'); const slug = url.searchParams.get('slug') || '/welcome';
const expectedSecret = import.meta.env.SANITY_PREVIEW_SECRET || process.env.SANITY_PREVIEW_SECRET || '';
// Vérification du secret de prévisualisation if (!secret || secret !== expectedSecret) { return new Response('Jeton de prévisualisation invalide ou manquant.', { status: 401, }); }
// Protection contre la redirection ouverte (open-redirect) const sanitizedSlug = slug.startsWith('/') && !slug.startsWith('//') ? slug : '/welcome';
// Pose du cookie de preview cookies.set('sanity-preview', 'true', { path: '/', httpOnly: true, secure: true, sameSite: 'lax', maxAge: 3600, // 1 heure });
return redirect(sanitizedSlug, 307);};4. Données et requêtes GROQ
Aucune requête GROQ n’est utilisée dans cet endpoint.
5. Paramètres et validation
5.1. Query strings
| Paramètre | Type | Obligatoire | Description | Validation |
|---|---|---|---|---|
secret |
string |
✅ | Secret de preview | Doit correspondre à SANITY_PREVIEW_SECRET |
slug |
string |
❌ | Page à afficher | Sanitization contre open-redirect |
5.2. Gestion des erreurs
| Code HTTP | Condition | Réponse |
|---|---|---|
| 307 | Succès | Redirect vers le slug |
| 401 | Secret invalide ou manquant | Message d’erreur |
6. Stratégie de cache
6.1. En-têtes de cache
| Mode | Cache-Control |
Rationale |
|---|---|---|
| API (redirect) | 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 |
|---|---|
| Secret valide | Activation du preview et redirect |
| Secret invalide | Erreur 401 |
9.2. Validation des entrées
- ✅ Validation du secret de preview
- ✅ Sanitization du slug contre open-redirect
- ✅ Cookie httpOnly et secure
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 |
|---|---|---|
| Erreur 401 | Secret invalide | Vérifier SANITY_PREVIEW_SECRET |
| Redirect incorrect | Slug mal formé | Vérifier la sanitization du slug |
| Cookie non posé | Erreur de configuration | Vérifier les options du cookie |
10.2. Logs et monitoring
# Logs de développementnpm run dev
# Logs Cloudflare (production)wrangler tail10.3. Tests manuels
# Test de l'endpoint en localcurl "http://localhost:4321/api/preview?secret=YOUR_SECRET&slug=/welcome"
# Test avec secret invalidecurl "http://localhost:4321/api/preview?secret=INVALID&slug=/welcome"# Attendu : 40111. Bonnes pratiques
11.1. Architecture
- ✅ Validation stricte du secret
- ✅ Protection contre open-redirect
- ✅ Cookie sécurisé (httpOnly, secure, sameSite)
- ✅ TTL limité (1 heure)
11.2. Performance
- ✅ Redirect 307 (temporary)
- ✅ Pas de traitement lourd
11.3. Maintenance
- ✅ Rotation régulière du secret de preview
- ✅ Vérifier la configuration du sanity.config.ts
12. Évolutions et roadmap
12.1. Améliorations planifiées
- Configuration des headers de cache (no-store)
- Logging des activations de preview
12.2. Limitations connues
- ❌ Headers de cache non configurés
- ❌ Pas de logging des activations
13. Ressources liées
- Documentation Astro : Endpoints
- Documentation Sanity : Preview Content
- Fichiers concernés :
src/pages/api/preview.tsapps/studio/sanity.config.ts(productionUrl).env(SANITY_PREVIEW_SECRET)
14. Historique des modifications
| Date | Version | Description | Auteur |
|---|---|---|---|
| 2026-09-15 | 1.0 | Création initiale | Devin |