
La configuration CORS (Cross-Origin Resource Sharing) de S3 permet au JavaScript d'un navigateur de lire les réponses d'un point de terminaison Amazon S3 situé sur une autre origine. Les règles du bucket doivent correspondre à l'origine de l'application, à la méthode demandée et aux en-têtes concernés. L'opération S3 doit aussi être autorisée. Une requête préliminaire réussie ne prouve pas que le téléversement ou le téléchargement aboutira.
Ce guide concerne les buckets à usage général d'Amazon S3, avec des exemples pour un bucket privé et des téléversements par URL présignée. Ne supposez pas que tous les services compatibles S3 se comportent de la même façon. Notre guide du stockage cloud Amazon situe S3 parmi les services AWS.
Une page à l'adresse https://app.example.com et un point de terminaison de l'API S3 ont des origines différentes. L'origine comprend le protocole, le nom d'hôte et le port, sans chemin. Passer de HTTP à HTTPS ou du port 3000 au port 5173 change l'origine. Pour diagnostiquer un écart, consultez l'en-tête Origin réellement envoyé par le navigateur.
Les requêtes du navigateur effectuées avec fetch() suivent les règles CORS. Certaines, dont PUT, déclenchent une requête préliminaire OPTIONS, appelée preflight, avant l'opération elle-même. Un GET simple peut éviter cette étape, mais sa réponse doit toujours comporter les en-têtes CORS appropriés pour être lisible par JavaScript. Ouvrir une URL dans la barre d'adresse ou effectuer une requête côté serveur ne constitue pas le même test. Consultez le guide CORS de MDN.
Distinguez les droits d'accès. Une politique de bucket, les permissions IAM et une signature valide peuvent autoriser une requête S3 ; CORS indique au navigateur si sa réponse peut être exposée à l'application. Activer CORS ne rend pas un bucket privé public. Limiter les origines ne bloque pas les clients hors navigateur qui disposent d'un accès valide. AWS confirme que les politiques d'accès continuent de s'appliquer.
Le JSON suivant peut être utilisé dans l'éditeur CORS de la console S3 après remplacement de l'origine d'exemple. Il prend en charge GET, HEAD et PUT depuis une seule application. Il autorise l'en-tête de requête Content-Type et rend l'en-tête de réponse ETag lisible par JavaScript.
[
{
"AllowedOrigins": [
"https://app.example.com"
],
"AllowedMethods": [
"GET",
"HEAD",
"PUT"
],
"AllowedHeaders": [
"Content-Type"
],
"ExposeHeaders": [
"ETag"
],
"MaxAgeSeconds": 300
}
]
Chaque réglage a un rôle distinct :
AllowedOrigins identifie l'application appelante, par exemple https://app.example.com. N'y mettez ni le point de terminaison S3, ni un chemin de page, ni une barre oblique finale.AllowedMethods liste les opérations réelles. S3 accepte GET, HEAD, PUT, POST et DELETE. OPTIONS sert à la requête préliminaire : ne l'ajoutez pas à cette liste.AllowedHeaders couvre les en-têtes demandés pendant le preflight. Ajoutez ceux que votre client envoie réellement, par exemple pour les sommes de contrôle ou les métadonnées. L'exemple ne couvre que Content-Type.ExposeHeaders indique les en-têtes de réponse supplémentaires accessibles à JavaScript. Autoriser un en-tête de requête n'expose pas un en-tête de réponse.MaxAgeSeconds définit une durée de cache du preflight. Ce n'est pas la durée de validité d'une URL présignée.AWS documente les champs de configuration CORS. Retirez les méthodes et en-têtes inutiles plutôt que d'autoriser toutes les valeurs possibles. Pour le développement local, utilisez une origine explicite distincte, telle que http://localhost:5173, dans un environnement de test.
Commencez par consulter la configuration existante. Cette commande en lecture seule nécessite s3:GetBucketCORS. Remplacez le bucket et les 12 chiffres du compte propriétaire, puis utilisez le profil AWS et la région voulus.
aws s3api get-bucket-cors --bucket "amzn-s3-demo-cors-bucket" --expected-bucket-owner "123456789012" --output json
Conservez une copie des règles actuelles et identifiez les applications qui en dépendent. Dans la console S3, ouvrez le bucket, choisissez Permissions, puis modifiez Cross-origin resource sharing (CORS). Intégrez les changements à la liste existante avant d'enregistrer. Suivez les étapes de configuration dans la console.
La console attend le tableau JSON présenté plus haut. Le paramètre --cors-configuration de l'AWS CLI attend un objet contenant ce tableau sous CORSRules. Pour un bucket sans autres règles à conserver, enregistrez cet exemple complet dans cors-cli.json :
{
"CORSRules": [
{
"AllowedOrigins": [
"https://app.example.com"
],
"AllowedMethods": [
"GET",
"HEAD",
"PUT"
],
"AllowedHeaders": [
"Content-Type"
],
"ExposeHeaders": [
"ETag"
],
"MaxAgeSeconds": 300
}
]
}
La commande suivante modifie la configuration du bucket. Elle remplace l'ensemble des règles CORS : incluez donc dans le fichier toutes celles qui doivent être conservées avant de l'exécuter. Elle nécessite s3:PutBucketCORS.
aws s3api put-bucket-cors --bucket "amzn-s3-demo-cors-bucket" --expected-bucket-owner "123456789012" --cors-configuration file://cors-cli.json
La référence PutBucketCORS décrit le format attendu. Après enregistrement, relisez la configuration et comparez-la au fichier prévu. S3 utilise la première règle correspondant à l'origine, à la méthode et aux en-têtes demandés. Examinez les règles qui se recoupent plutôt que de supposer que leurs réglages se cumulent.
Utilisez un point de terminaison de l'API objet dans la région du bucket. Remplacez le bucket, la région, la clé et l'origine d'exemple. Cette commande vérifie les conditions d'un PUT avec Content-Type ; elle ne téléverse aucune donnée. Dans Windows PowerShell, utilisez curl.exe si curl désigne un alias du shell.
curl -i -X OPTIONS "https://amzn-s3-demo-cors-bucket.s3.us-east-1.amazonaws.com/uploads/example.txt" -H "Origin: https://app.example.com" -H "Access-Control-Request-Method: PUT" -H "Access-Control-Request-Headers: content-type"
Examinez le statut et les en-têtes de réponse CORS. Access-Control-Allow-Origin doit correspondre à l'application, Access-Control-Allow-Methods doit inclure PUT et Access-Control-Allow-Headers doit couvrir Content-Type. Curl affiche la réponse sans appliquer les règles CORS du navigateur. Les instructions de test AWS décrivent ce contrôle.
Testez ensuite depuis l'origine réelle de l'application dans le panneau Network du navigateur. Vérifiez OPTIONS, lorsqu'il apparaît, puis le PUT. Un résultat de preflight en cache peut expliquer l'absence d'une nouvelle requête OPTIONS. Un OPTIONS réussi ne prouve ni l'autorisation ni la réussite de l'écriture suivante.
Le backend doit autoriser l'utilisateur et choisir la clé d'objet permise avant de renvoyer une URL de téléversement de courte durée. Transmettez cette URL au navigateur sans la modifier. Si Content-Type a été signé, envoyez la même valeur exacte, sans la déduire de l'extension du fichier. AWS explique ces contraintes dans son guide des téléversements présignés.
Cette fonction reçoit une URL PUT présignée, le File ou Blob sélectionné et le type de contenu convenu avec le backend. Son appel envoie le fichier vers la destination signée ; un objet déjà présent à cette clé peut être remplacé. Utilisez une nouvelle clé ou une procédure d'écriture conditionnelle conçue à cet effet si le remplacement doit être empêché.
async function uploadWithPresignedUrl(url, file, contentType) {
const response = await fetch(url, {
method: "PUT",
mode: "cors",
credentials: "omit",
redirect: "error",
headers: { "Content-Type": contentType },
body: file
});
if (!response.ok) {
throw new Error(`Upload failed with HTTP ${response.status}`);
}
return { status: response.status, etag: response.headers.get("ETag") };
}
L'exemple utilise la signature dans la chaîne de requête de l'URL et omet les identifiants gérés par le navigateur. Il envoie directement le fichier, sans enveloppe FormData. Il refuse les redirections pour qu'un point de terminaison erroné soit examiné plutôt que suivi automatiquement. Le backend et le bucket doivent prendre en charge la requête indépendamment de cette fonction.
La valeur ETag renvoyée peut être null si cet en-tête est absent ou n'est pas exposé. Ne consignez pas et ne publiez pas l'URL présignée complète : elle porte un accès temporaire. Si fetch échoue alors que l'écriture a pu atteindre S3, vérifiez l'objet depuis un backend autorisé avant de réessayer sans contrôle.
Comparez l'Origin exact, Access-Control-Request-Method et tous les en-têtes de Access-Control-Request-Headers à une même règle. Un SDK peut ajouter des en-têtes que l'exemple minimal n'autorise pas. AWS distingue l'absence de configuration d'une requête qui ne correspond pas aux règles.
Examinez la réponse réelle et les diagnostics côté serveur accessibles avec les droits appropriés. Vérifiez l'expiration de l'URL, la méthode et les en-têtes signés, la région et les permissions d'écriture du signataire. Élargir les origines CORS ne répare ni une signature invalide ni un refus d'accès. L'absence d'en-têtes CORS sur une réponse d'erreur peut aussi masquer ses détails à JavaScript.
Vérifiez ExposeHeaders et la réponse réelle. Le panneau Network peut afficher ETag alors que JavaScript ne peut pas le lire. Ajouter ETag à AllowedHeaders concerne l'autre sens de l'échange et ne résout pas ce problème de lecture.
Une origine générique ne convient pas à une réponse CORS avec identifiants ; consultez les explications de MDN. Pour l'exemple signé par l'URL, gardez credentials: "omit". D'autres mécanismes d'authentification nécessitent une analyse distincte.
Passer fetch en mode: "no-cors" ne résout pas un problème de téléversement PUT. Ce mode restreint les méthodes et les en-têtes et empêche JavaScript d'examiner la réponse. Corrigez la configuration du serveur et la requête ; la référence du mode Request détaille ces limites.
Avec CloudFront ou un autre proxy, examinez la prise en charge d'OPTIONS, les en-têtes CORS de requête transmis, les en-têtes de réponse et le cache. Des origines différentes ne doivent pas recevoir une réponse mise en cache à tort. Un test direct du bucket ne valide pas le chemin complet passant par un CDN ou un proxy.
Vérifiez une origine prévue et une origine non autorisée, les en-têtes réellement envoyés et le comportement après expiration de l'URL. Confirmez que le modèle d'autorisation maintient les objets privés. Conservez les règles fonctionnelles avec la configuration de l'application pour éviter qu'un changement du frontend ne casse les téléversements sans être détecté.
Pour les choix plus larges, notamment les interfaces de stockage et les modes d'accès, consultez notre guide du stockage cloud pour les applications. CORS fait partie de cette intégration ; le téléversement abouti dans le navigateur et les contrôles d'accès du serveur permettent d'en vérifier le fonctionnement.
Choisissez une charge de travail d’IA, de calcul ou de stockage à tester sur Hivenet, ou échangez avec notre équipe sur sa mise en production.