Object Storage - Écritures conditionnelles
Découvrez comment utiliser les en-têtes conditionnels If-Match et If-None-Match pour prévenir les écrasements et éviter les conditions de course sur vos buckets OVHcloud Object Storage
Objectif
Ce guide explique comment utiliser les en-têtes HTTP conditionnels If-Match et If-None-Match sur les requêtes PutObject, DeleteObject et CompleteMultipartUpload de vos buckets OVHcloud Object Storage.
Prérequis
- Disposer d'un projet Public Cloud dans votre compte OVHcloud
- Avoir créé un utilisateur Object Storage
- Avoir installé et configuré l'AWS CLI
En pratique
Pourquoi utiliser les écritures conditionnelles ?
L'Object Storage est par nature concurrent - plusieurs instances d'application, microservices ou traitements en arrière-plan peuvent lire et écrire le même objet simultanément. Sans coordination, ces écritures concurrentes peuvent s'écraser silencieusement, entraînant des pertes de données difficiles à détecter et à reproduire.
Les écritures conditionnelles résolvent ce problème au niveau de la couche de stockage, sans nécessiter de service de coordination externe comme une base de données ou un gestionnaire de verrous distribués. En associant une précondition à un appel API S31, vous garantissez que l'opération ne se déroule que si l'objet est dans l'état attendu au moment où la requête est évaluée.
Bénéfices clés :
- Intégrité des données en environnement concurrent : Évitez qu'une écriture n'écrase silencieusement les modifications d'un autre processus survenues entre votre lecture et votre écriture (la classique race condition de type vérifier-puis-agir).
- Primitive de verrouillage distribué : Implémentez un verrou léger natif au stockage avec
If-None-Match: *surPutObject- seul le premier qui écrit réussit ; tous les autres reçoivent412 Precondition Failed. - Comparer-et-échanger atomique : Lisez l'ETag d'un objet, modifiez-le, puis réécrivez-le avec
If-Match: <etag_original>. L'écriture est rejetée si l'objet a été modifié entre-temps - un modèle de concurrence optimiste sûr. - Aucune infrastructure supplémentaire : La coordination s'effectue directement au sein du service Object Storage - pas besoin de bases de données, files de messages ou gestionnaires de verrous supplémentaires.
- Tout client compatible S3 : Les en-têtes conditionnels font partie du standard HTTP (RFC 9110) et de l'API S3 - ils fonctionnent avec AWS CLI, n'importe quel SDK S3 et les appels HTTP directs.
Vue d'ensemble
Les requêtes conditionnelles vous permettent d'associer une précondition à un appel API S3, basée sur l'état actuel de l'objet cible. L'Object Storage OVHcloud évalue la condition de manière atomique avant d'exécuter l'opération. Si la condition n'est pas satisfaite, la requête est rejetée sans modifier aucune donnée.
Deux en-têtes HTTP sont supportés, conformément à la RFC 9110 :
Opérations supportées :
Format de l'ETag : Lors de l'utilisation de If-Match, fournissez l'ETag sous forme de chaîne brute sans guillemets - par exemple d41d8cd98f00b204e9800998ecf8427e, et non "d41d8cd98f00b204e9800998ecf8427e".
Pour récupérer l'ETag courant d'un objet, utilisez aws s3api head-object --bucket <nom_du_bucket> --key <clé_de_l_objet> et lisez le champ ETag dans la réponse en supprimant les guillemets entourants.
Il n'est pas possible d'envoyer à la fois If-Match et If-None-Match dans la même requête. Cela retourne une erreur HTTP 400 Bad Request.
Codes de réponse
Versioning et marqueurs de suppression
Toutes les conditions sont évaluées par rapport à la version courante de l'objet, que le versioning soit activé ou non sur le bucket.
Un marqueur de suppression (delete marker) dans un bucket versionné n'est pas considéré comme un objet existant :
If-Match(avec un ETag ou*) →404 Not Foundlorsque la version courante est un marqueur de suppression.If-None-Match: *→ réussit lorsque la version courante est un marqueur de suppression (traité comme inexistant).
Support du chiffrement : Les écritures conditionnelles sont supportées pour les objets non chiffrés et les objets chiffrés avec SSE-S3. Le support des objets chiffrés avec SSE-C sera disponible dans une prochaine version.
PutObject - écriture conditionnelle
Ajoutez une précondition à l'upload d'un objet pour éviter les écrasements accidentels ou implémenter une logique de premier arrivé, premier servi.
Cas d'usage :
- Premier arrivé, premier servi / verrou distribué : Plusieurs processus tentent de créer le même objet simultanément. Seul le premier appel avec
If-None-Match: *réussit - tous les autres reçoivent412. - Écrasement sécurisé : Lisez un objet, modifiez-le, puis réécrivez-le avec
If-Match: <etag_original>. Si un autre client a modifié l'objet entre-temps, l'écriture est rejetée. - Initialisation idempotente : Créez un objet de configuration sans risque d'écraser une version existante.
Téléversement réussi :
Téléversement refusé (condition non satisfaite) :
Comportement selon l'état du versioning pour PutObject
DeleteObject - suppression conditionnelle
Supprimez un objet uniquement si la condition ETag est satisfaite. Seul If-Match est supporté pour DeleteObject - If-None-Match n'est pas applicable à la suppression.
Cas d'usage :
- Suppression sécurisée : Lisez l'ETag d'un objet, puis supprimez-le avec
If-Match: <etag>. La suppression est rejetée si l'objet a été modifié entre votre lecture et votre suppression. - Supprimer-si-existe : Utilisez
If-Match: *pour supprimer un objet uniquement s'il existe actuellement.
Lorsque --version-id est spécifié, l'ETag est évalué par rapport à cette version spécifique, et non par rapport à la version courante.
Dans un bucket versionné, une suppression réussie via DeleteObject crée un marqueur de suppression comme nouvelle version courante - elle ne supprime pas définitivement l'objet. Pour supprimer définitivement une version spécifique, incluez --version-id dans la requête.
Comportement selon l'état du versioning pour DeleteObject
CompleteMultipartUpload - finalisation conditionnelle
Associez une précondition à l'étape finale d'un upload multipart. La condition est évaluée au moment de l'appel à CompleteMultipartUpload, et non lors de l'initiation avec CreateMultipartUpload.
Cas d'usage :
- Remplacement atomique de fichier volumineux : Démarrez un upload multipart d'un fichier de remplacement. À la finalisation, utilisez
If-Match: <etag>pour vous assurer que l'objet cible n'a pas été modifié pendant l'upload. - Premier arrivé, premier servi pour les fichiers volumineux : Utilisez
If-None-Match: *à la finalisation pour qu'un seul upload multipart concurrent crée définitivement l'objet.
En cas d'erreur 409 ConditionalRequestConflict sur CompleteMultipartUpload, vous devez redémarrer entièrement la séquence d'upload multipart :
- Appelez
AbortMultipartUploadpour nettoyer l'upload en cours. - Récupérez l'ETag courant avec
HeadObject. - Appelez
CreateMultipartUploadpour démarrer un nouvel upload. - Re-téléversez toutes les parties avec
UploadPart. - Relancez
CompleteMultipartUploadavec la condition mise à jour.
Comportement selon l'état du versioning pour CompleteMultipartUpload
Considérations importantes
- Atomicité : La vérification de la condition et l'opération s'exécutent en une seule unité atomique. Aucune opération concurrente ne peut modifier l'objet entre la vérification et l'écriture.
- Un seul en-tête par requête : Vous ne pouvez pas combiner
If-MatchetIf-None-Matchdans la même requête - cela retourne une erreur400 Bad Request. - Nouvelle tentative sur 409 pour PutObject / DeleteObject : En cas de
409 ConditionalRequestConflict, récupérez l'ETag courant de l'objet avecHeadObjectet relancez votre requête avec la valeur mise à jour. - Aucune modification IAM requise : Aucune permission supplémentaire n'est nécessaire. Les permissions existantes
s3:PutObjectets3:DeleteObjectsont suffisantes. - Compatibilité avec Object Lock : Les en-têtes conditionnels sont évalués indépendamment des règles Object Lock (WORM). Les deux contraintes s'appliquent.
Aller plus loin
Échangez avec notre communauté d'utilisateurs.
1 : S3 est une marque déposée appartenant à Amazon Technologies, Inc. Les services de OVHcloud ne sont pas sponsorisés, approuvés, ou affiliés de quelque manière que ce soit.