Erreurs CORS sur API Gateway : activer CORS et configurer les headers Lambda
Votre frontend reçoit une erreur CORS en appelant API Gateway — c'est l'un des problèmes les plus fréquents en production, et la plupart du temps la cause n'est pas là où on la cherche. Activer CORS dans la console ne suffit pas : si votre fonction Lambda ne renvoie pas les bons headers dans chaque réponse, le navigateur bloquera quand même la requête.
Résumé (TL;DR) — Erreurs CORS API Gateway
| Étape | Action requise | Responsable |
|---|---|---|
| 1 | Activer CORS sur la ressource API Gateway | Console / CLI API Gateway |
| 2 | Déployer le stage après modification | Console / CLI API Gateway |
| 3 | Inclure les headers CORS dans la réponse Lambda | Code Lambda |
| 4 | Vérifier que les erreurs 4xx/5xx incluent aussi les headers | Code Lambda + Gateway Responses |
Comment CORS fonctionne avec API Gateway
CORS (Cross-Origin Resource Sharing) est un mécanisme de sécurité imposé par le navigateur, pas par AWS. Quand votre frontend sur https://app.example.com appelle https://api.example.com, le navigateur envoie d'abord une requête preflight HTTP OPTIONS avant la vraie requête. Cette requête preflight demande à l'API si elle autorise l'origine, la méthode et les headers concernés.
API Gateway doit répondre à cette requête OPTIONS avec les headers appropriés. Ensuite, la réponse de votre Lambda à la vraie requête (GET, POST, etc.) doit elle aussi inclure ces headers — sinon le navigateur bloque la réponse même si le statut HTTP est 200.
- Preflight OPTIONS : le navigateur envoie une requête OPTIONS à API Gateway avant la vraie requête.
- Réponse OPTIONS : API Gateway répond avec les headers CORS configurés (mock integration ou Lambda).
- Requête réelle : le navigateur envoie la vraie requête (POST, GET…) si le preflight est accepté.
- Réponse Lambda : Lambda doit inclure les headers CORS dans sa réponse — API Gateway ne les injecte pas automatiquement en mode proxy.
- Validation navigateur : le navigateur autorise ou bloque la réponse selon les headers reçus.
Analogie : le preflight CORS, c'est comme un videur qui vérifie votre liste d'invités avant de laisser entrer quelqu'un. Si votre nom n'est pas sur la liste (origine non autorisée), vous n'entrez pas — peu importe ce que vous portez (le contenu de la requête).
Activer CORS sur API Gateway REST (console)
La procédure varie selon le type d'API. Les étapes ci-dessous concernent une API REST (pas HTTP API ni WebSocket).
- Dans la console API Gateway, sélectionnez votre API REST.
- Dans le panneau Resources, sélectionnez la ressource concernée (ex.
/items). - Dans le menu Actions, cliquez sur Enable CORS.
- Configurez les champs :
Access-Control-Allow-Origin,Access-Control-Allow-Headers,Access-Control-Allow-Methods. - Cliquez sur Enable CORS and replace existing CORS headers.
- Déployez le stage — sans déploiement, aucune modification n'est active.
Ce que fait cette action concrètement : elle crée une méthode OPTIONS sur la ressource avec une mock integration qui renvoie les headers configurés. Elle ajoute aussi les headers dans les réponses de méthode de vos autres verbes HTTP — mais uniquement dans la configuration de la méthode, pas dans la réponse Lambda.
Activer CORS via AWS CLI sur une API REST
Si vous gérez votre infrastructure en dehors de la console, voici comment créer la méthode OPTIONS avec une mock integration. Remplacez les valeurs par les vôtres.
🔽 Cliquez pour afficher les commandes CLI
# 1. Créer la méthode OPTIONS sur la ressource
aws apigateway put-method \
--rest-api-id abc123def4 \
--resource-id xyz789 \
--http-method OPTIONS \
--authorization-type NONE \
--region us-east-1
# 2. Configurer une mock integration
aws apigateway put-integration \
--rest-api-id abc123def4 \
--resource-id xyz789 \
--http-method OPTIONS \
--type MOCK \
--request-templates '{"application/json": "{\"statusCode\": 200}"}' \
--region us-east-1
# 3. Configurer la réponse de méthode pour OPTIONS
aws apigateway put-method-response \
--rest-api-id abc123def4 \
--resource-id xyz789 \
--http-method OPTIONS \
--status-code 200 \
--response-parameters '{"method.response.header.Access-Control-Allow-Headers": false, "method.response.header.Access-Control-Allow-Methods": false, "method.response.header.Access-Control-Allow-Origin": false}' \
--region us-east-1
# 4. Configurer la réponse d'intégration avec les valeurs des headers
aws apigateway put-integration-response \
--rest-api-id abc123def4 \
--resource-id xyz789 \
--http-method OPTIONS \
--status-code 200 \
--response-parameters '{"method.response.header.Access-Control-Allow-Headers": "'\''Content-Type,Authorization'\''", "method.response.header.Access-Control-Allow-Methods": "'\''OPTIONS,GET,POST'\''", "method.response.header.Access-Control-Allow-Origin": "'\''https://app.example.com'\''"}' \
--region us-east-1
# 5. Déployer le stage
aws apigateway create-deployment \
--rest-api-id abc123def4 \
--stage-name prod \
--region us-east-1
Headers CORS obligatoires dans la réponse Lambda
C'est là que la majorité des erreurs CORS persistent après avoir activé CORS dans la console. En mode Lambda Proxy Integration (le mode par défaut), API Gateway transmet la réponse Lambda telle quelle au client. Il n'injecte pas les headers CORS automatiquement. Votre fonction Lambda doit les inclure dans chaque réponse.
Les trois headers minimum requis :
Access-Control-Allow-Origin— l'origine autorisée (ex.https://app.example.com) ou*pour toutes les origines (déconseillé en production avec credentials).Access-Control-Allow-Headers— les headers que le frontend peut envoyer (ex.Content-Type, Authorization).Access-Control-Allow-Methods— les méthodes HTTP autorisées.
# Exemple de réponse Lambda (Python) avec headers CORS
import json
def lambda_handler(event, context):
return {
'statusCode': 200,
'headers': {
'Access-Control-Allow-Origin': 'https://app.example.com',
'Access-Control-Allow-Headers': 'Content-Type,Authorization',
'Access-Control-Allow-Methods': 'OPTIONS,GET,POST'
},
'body': json.dumps({'message': 'OK'})
}
Si vous utilisez Access-Control-Allow-Credentials: true, la valeur de Access-Control-Allow-Origin ne peut pas être * — elle doit être une origine explicite. C'est une contrainte du standard CORS, pas d'AWS.
Le piège le plus courant : les erreurs 4xx et 5xx sans headers CORS
Voici le scénario classique : vous activez CORS, vous testez avec une requête valide, ça marche. Puis en production, une validation échoue, Lambda renvoie un 400 — et le navigateur affiche une erreur CORS au lieu du message d'erreur réel.
Pourquoi ? Parce que votre code Lambda ne renvoie les headers CORS que dans le chemin de succès. Quand une exception est levée ou qu'une validation échoue, la réponse d'erreur n'inclut pas les headers. Le navigateur voit une réponse sans Access-Control-Allow-Origin et bloque tout.
dans la réponse erreur ?} F -- Oui --> G[Navigateur reçoit l'erreur] F -- Non --> H[Navigateur bloque — erreur CORS] B -- Non
Auth/Throttle --> I[Gateway Response] I --> J{Gateway Response
configurée avec CORS ?} J -- Oui --> K[Navigateur reçoit l'erreur gateway] J -- Non --> H
- Succès (200) : Lambda renvoie les headers CORS — le navigateur reçoit la réponse normalement.
- Erreur Lambda (400/500) : si les headers CORS sont absents de la réponse d'erreur, le navigateur bloque et affiche une erreur CORS — masquant l'erreur réelle.
- Erreur Gateway (502/504) : API Gateway génère lui-même la réponse — Lambda n'est pas impliqué. Les Gateway Responses doivent être configurées séparément.
La correction : incluez les headers CORS dans tous les chemins de réponse, y compris les blocs except.
# Pattern recommandé — headers CORS dans tous les cas
import json
CORS_HEADERS = {
'Access-Control-Allow-Origin': 'https://app.example.com',
'Access-Control-Allow-Headers': 'Content-Type,Authorization',
'Access-Control-Allow-Methods': 'OPTIONS,GET,POST'
}
def lambda_handler(event, context):
try:
# logique métier
result = process(event)
return {
'statusCode': 200,
'headers': CORS_HEADERS,
'body': json.dumps(result)
}
except ValueError as e:
return {
'statusCode': 400,
'headers': CORS_HEADERS,
'body': json.dumps({'error': str(e)})
}
except Exception as e:
return {
'statusCode': 500,
'headers': CORS_HEADERS,
'body': json.dumps({'error': 'Internal server error'})
}
Configurer les Gateway Responses pour les erreurs API Gateway
Quand API Gateway génère lui-même une erreur (authentification échouée, throttling, mauvaise route), Lambda n'est pas appelé. Ces réponses n'ont pas de headers CORS par défaut. Il faut configurer les Gateway Responses pour les ajouter.
# Ajouter les headers CORS aux Gateway Responses (ex. DEFAULT_4XX)
aws apigateway put-gateway-response \
--rest-api-id abc123def4 \
--response-type DEFAULT_4XX \
--response-parameters '{"gatewayresponse.header.Access-Control-Allow-Origin": "'\''https://app.example.com'\''", "gatewayresponse.header.Access-Control-Allow-Headers": "'\''Content-Type,Authorization'\''"}' \
--region us-east-1
# Faire de même pour DEFAULT_5XX
aws apigateway put-gateway-response \
--rest-api-id abc123def4 \
--response-type DEFAULT_5XX \
--response-parameters '{"gatewayresponse.header.Access-Control-Allow-Origin": "'\''https://app.example.com'\''", "gatewayresponse.header.Access-Control-Allow-Headers": "'\''Content-Type,Authorization'\''"}' \
--region us-east-1
CORS sur HTTP API (API Gateway v2)
Si vous utilisez une HTTP API (API Gateway v2, pas REST API), la configuration CORS est centralisée et gérée par API Gateway nativement — vous n'avez pas besoin de créer une méthode OPTIONS manuellement.
# Configurer CORS sur une HTTP API v2
aws apigatewayv2 update-api \
--api-id abc123def4 \
--cors-configuration AllowOrigins='https://app.example.com',AllowMethods='GET,POST,OPTIONS',AllowHeaders='Content-Type,Authorization' \
--region us-east-1
Avec HTTP API et la configuration CORS native, API Gateway injecte automatiquement les headers CORS dans les réponses — y compris les réponses d'erreur générées par la gateway. Votre Lambda n'a pas besoin de les inclure. Si votre Lambda les inclut quand même, des headers dupliqués peuvent apparaître selon la configuration.
Diagnostic : vérifier la configuration CORS en place
Avant de modifier quoi que ce soit, vérifiez l'état réel de votre API. Un déploiement manquant est responsable d'une bonne partie des cas où 'CORS est activé mais ne fonctionne pas'.
# Lister les méthodes sur une ressource (vérifier la présence d'OPTIONS)
aws apigateway get-resource \
--rest-api-id abc123def4 \
--resource-id xyz789 \
--region us-east-1
# Vérifier les Gateway Responses configurées
aws apigateway get-gateway-responses \
--rest-api-id abc123def4 \
--region us-east-1
# Vérifier les déploiements existants
aws apigateway get-deployments \
--rest-api-id abc123def4 \
--region us-east-1
Vous pouvez aussi tester le preflight directement depuis votre terminal sans passer par le navigateur :
# Simuler une requête preflight OPTIONS
curl -v -X OPTIONS https://abc123def4.execute-api.us-east-1.amazonaws.com/prod/items \
-H 'Origin: https://app.example.com' \
-H 'Access-Control-Request-Method: POST' \
-H 'Access-Control-Request-Headers: Content-Type,Authorization'
La réponse doit contenir un statut 200 et les headers Access-Control-Allow-Origin, Access-Control-Allow-Methods, Access-Control-Allow-Headers. Si l'un d'eux est absent, le navigateur bloquera la requête réelle.
Conclusion et prochaines étapes — Résoudre les erreurs CORS sur API Gateway
Les erreurs CORS sur API Gateway ont presque toujours l'une de ces trois causes : la méthode OPTIONS n'est pas configurée, le stage n'a pas été redéployé après modification, ou la fonction Lambda n'inclut pas les headers dans ses réponses d'erreur. Traitez ces trois points dans l'ordre et la majorité des cas se résolvent.
Pour aller plus loin :
- Documentation officielle AWS — Enable CORS for REST APIs
- Documentation officielle AWS — CORS pour HTTP APIs
- Documentation officielle AWS — Gateway Responses
Glossaire
| Terme | Définition |
|---|---|
| CORS | Cross-Origin Resource Sharing — mécanisme de sécurité navigateur contrôlant les requêtes entre origines différentes. |
| Preflight | Requête OPTIONS envoyée automatiquement par le navigateur avant une requête cross-origin pour vérifier les permissions. |
| Lambda Proxy Integration | Mode d'intégration où API Gateway transmet la requête et la réponse Lambda sans transformation — les headers doivent être gérés par Lambda. |
| Gateway Response | Réponse générée directement par API Gateway (sans invoquer Lambda) pour les erreurs d'authentification, throttling, etc. |
| HTTP API (v2) | Version allégée d'API Gateway avec configuration CORS native centralisée, distincte de l'API REST (v1). |
Commentaires
Enregistrer un commentaire