Éviter les doublons avec REST

j'ai utilisé POST dans une API REST pour créer des objets. De temps en temps, le serveur crée l'objet, mais le client est déconnecté avant de recevoir la réponse 201 Created . Le client ne voit qu'une requête POST échouée, et essaie de nouveau plus tard, et le serveur crée heureusement un objet dupliqué...

D'autres ont dû avoir ce problème, non? Mais je cherche sur google, et tout le monde semble l'ignorer.

j'ai 2 solutions:

a)utilisez PUT à la place, et créez L'ID (GU) du client.

B) Ajouter un GUID à tous les objets créés sur le client, et demander au serveur de renforcer leur UNIQUE -ness.

A ne correspond pas très bien aux cadres existants, et B se sent comme un piratage. Comment les autres résolvent ça, dans le monde réel?

Edit:

Avec Colonne Vertébrale.js, vous pouvez définir une directive comme l'id quand vous créer un objet sur le client. Quand il est sauvegardé, Backbone va faire une requête PUT. Faites votre arrière-plan de repos gérer mis à l'id non-existants, et vous êtes prêt.

26
demandé sur geon 2013-03-01 17:46:35

6 réponses

j'utilise toujours B -- détection de dups en raison de n'importe quel problème appartient du côté du serveur.

5
répondu Kyle Banerjee 2013-03-01 13:53:48

une autre solution qui a été proposée Pour cela est POST Once Exactly (POE) , dans lequel le serveur génère des URIs de courrier à usage unique qui, lorsqu'ils sont utilisés plus d'une fois, provoqueront le retour d'une réponse 405.

les inconvénients sont que 1) le projet de POE a été laissé à expiration sans aucun progrès supplémentaire sur la normalisation, et donc 2) la mise en œuvre nécessite des changements aux clients pour faire usage des nouveaux en-têtes POE, et le travail supplémentaire par serveurs pour mettre en œuvre la sémantique POE.

en googlant vous pouvez trouver quelques API qui l'utilisent cependant.

une autre idée que j'avais pour résoudre ce problème est celle d'un POST conditionnel, que j'ai décrit et demandé des commentaires sur ici .

il ne semble pas y avoir de consensus sur la meilleure façon d'empêcher la création de ressources en double dans les cas où la génération URI unique est incapable d'être mis sur le client et par conséquent, POST est nécessaire.

8
répondu Chris Toomey 2017-05-23 12:34:39

la détection de doublons est un kludge, et peut devenir très compliquée. De véritables requêtes distinctes mais similaires peuvent arriver en même temps, peut-être parce qu'une connexion réseau est restaurée. Et les demandes répétées peuvent arriver des heures ou des jours d'intervalle si une connexion réseau tombe en panne.

toute la discussion sur les identificateurs dans les autres anwsers est dans le but de donner une erreur en réponse aux requêtes en double, mais cela ne fera normalement qu'inciter un client à obtenir ou générez une nouvelle id et réessayez.

un modèle simple et robuste pour résoudre ce problème est comme suit: les applications de serveur doivent stocker toutes les réponses aux requêtes dangereuses, puis, s'ils voient une requête dupliquée, ils peuvent répéter la réponse précédente et ne rien faire d'autre . faites ceci pour toutes les demandes dangereuses et vous résoudrez un tas de problèmes épineux. "Doublon" est déterminé par un niveau de l'application id, soit un un GUID généré par le client ou un numéro de séquence généré par le serveur. Dans ce second cas, une requête-réponse devrait être consacrée uniquement à l'échange de la carte d'identité. J'aime cette solution parce que l'étape dédiée fait les clients pensent qu'ils obtiennent quelque chose de précieux qu'ils ont besoin de s'occuper. S'ils peuvent générer leurs propres identificateurs, ils sont plus susceptibles de mettre cette ligne dans la boucle et chaque requête sanglante aura un nouvel identifiant.

en utilisant ce schéma, tous les messages sont vides, et POST est utilisé uniquement pour récupérer un identifiant d'action. Toutes les options PUTs et DELETEs sont entièrement idempotent: les requêtes successives obtiennent la même réponse (stockée et rejouée) et ne provoquent plus rien. La plus belle chose au sujet de ce modèle est sa qualité de Kung-Fu (Panda). Il prend une faiblesse: la propension des clients à répéter une demande toute fois qu'ils obtiennent une réponse inattendue, et il se transforme en une force :-)

j'ai un petit google doc ici si toute personne s'en soucie.

3
répondu bbsimonbb 2017-08-30 12:32:39

vous pouvez essayer une approche en deux étapes. Vous demandez un objet à créer, qui renvoie un token. Puis dans une seconde requête, demandez un statut en utilisant le token. Jusqu'à ce que le statut soit demandé en utilisant le token, vous le laissez dans un État de "mise en scène".

si le client se déconnecte après la première demande, il n'aura pas le jeton et l'objet RESTERA" mis en scène " indéfiniment ou jusqu'à ce que vous le supprimiez avec un autre processus.

Si la première demande réussit, vous avez un jeton valide et vous pouvez saisir l'objet créé autant de fois que vous le voulez sans qu'il ne recrée quoi que ce soit.

il n'y a aucune raison pour que le token ne puisse pas être L'ID de l'objet dans la mémoire. Vous pouvez créer l'objet lors de la première requête. La seconde requête ne fait que mettre à jour le champ" mise en scène".

2
répondu Travis Parks 2013-03-01 14:05:37

identificateurs émis par le serveur

si vous avez affaire au cas où c'est le serveur qui émet les identificateurs, créez l'objet dans un état temporaire, par étapes. (Il s'agit d'une opération intrinsèquement non-idempotent, donc il devrait être fait avec POST.) Le client doit alors Effectuer une autre opération sur elle pour la transférer de l'état progressif dans l'état actif / préservé (qui pourrait être un PUT d'une propriété de la ressource, ou un poste approprié à la ressource).

chaque client devrait être en mesure d'obtenir une liste de leurs ressources dans l'état de mise en scène d'une façon ou d'une autre (peut-être mélangé avec d'autres ressources) et devrait être en mesure de supprimer les ressources qu'ils ont créé si elles sont encore juste mis en scène. Vous pouvez également supprimer périodiquement les ressources par étapes qui sont inactives depuis un certain temps.

vous n'avez pas besoin de révéler les ressources mises en scène d'un client à un autre client; elles doivent exister globalement seulement après l'étape de confirmation.

identificateurs émis par le Client

l'alternative est que le client délivre les identificateurs. Ceci est principalement utile lorsque vous modelez quelque chose comme un filestore, car les noms de fichiers sont typiquement significatifs pour le code utilisateur. Dans ce cas, vous pouvez utiliser PUT pour faire la création de la ressource comme vous pouvez le faire tout idempotently.

le côté négatif de ceci est que les clients sont capables de créer des ID, et donc vous n'avez aucun contrôle du tout sur quelles pièces d'identité qu'ils utilisent.

1
répondu Donal Fellows 2013-03-01 15:11:06

il y a une autre variante de ce problème. Le fait qu'un client génère un identifiant unique indique que nous demandons à un client de résoudre ce problème pour nous. Prenons l'exemple d'un environnement dans lequel nous avons un IPA exposé au public et une centaine de clients qui s'intègrent à ces IPA. Pratiquement, nous n'avons aucun contrôle sur le code client et la justesse de sa mise en œuvre de l'unicité. Par conséquent, il serait probablement préférable d'avoir des renseignements pour comprendre si une demande est un duplicata. Un l'approche simple ici serait de calculer et de stocker la somme de contrôle de chaque requête basée sur les attributs d'une entrée utilisateur, de définir un certain seuil de temps (X minutes) et de comparer chaque nouvelle requête du même client avec ceux reçus dans le passé X minutes. Si la somme de contrôle correspond, il peut s'agir d'une requête dupliquée et d'ajouter un mécanisme de contestation pour qu'un client puisse résoudre ce problème. Si un client fait deux demandes différentes avec les mêmes paramètres dans les x minutes, il pourrait être utile de s'assurer que c'est intentionnel même s'il vient avec un identifiant de requête unique. Cette approche peut ne pas convenir à tous les cas d'utilisation, mais je pense que cela sera utile dans les cas où l'impact commercial de l'exécution du deuxième appel est élevé et peut éventuellement coûter un client. Considérons une situation de moteur de traitement des paiements où une couche intermédiaire finit par retracer une requête manquée ou un client double cliqué résultant en la soumission de deux requêtes par couche client.

0
répondu Neeraj 2018-04-19 17:51:48