Écrivez le code comme s'il serait accompagné d'un psychopathe violent qui sait où vous vivez.
Bonjour à tous!
Je travaille en tant que chef d'équipe de l'équipe de développement de l'intégration dans le service de réservation d'hôtel en ligne Ostrovok.ru et aujourd'hui, je voudrais partager mon expérience avec diverses API.

En tant que développeur d'un système travaillant avec des fournisseurs externes, je rencontre souvent différentes API - le plus souvent c'est SOAP / REST ou quelque chose de similaire. Cependant, travailler avec beaucoup d'entre eux laisse l'impression qu'ils ont été écrits, non guidés par des règles techniques ou le bon sens - comme s'ils venaient du livre «Bad Advice» de Grigory Oster. Dans cet article, je vais essayer de décrire de tels cas dans le style de «mauvais conseils» et de considérer des exemples liés à XML. Les commentaires et discussions sont les bienvenus.
Contexte historique
SOAP (de l'anglais. Simple Object Access Protocol - un protocole simple pour accéder aux objets) - un protocole pour échanger des messages structurés dans un environnement informatique distribué. SOAP était initialement destiné principalement à l'implémentation d'un appel de procédure distante (RPC). Maintenant, le protocole est utilisé pour échanger des messages arbitraires au format XML, et pas seulement pour appeler des procédures.
Allez aux exemples
1. Passer du xml à l'url
Qu'est-ce que les utilisateurs d'API veulent le plus? Bien sûr, simplicité, fiabilité et concision. Alors ne lisons pas le corps de la requête, mais acceptons XML comme information encodée en URL comme paramètre du chemin de la requête! Quoi de mieux:
http://exapmple.com/xml/form.jsp?RequestName%3DHotelRequest2%26XML%3D%3C%3Fxml%2Bversion%3D%221.0%22%2Bencoding%3D%22UTF-8%22%3F%3E%0A%3CHotelRequest2%2BBuyerId%3D%22test%22%2BUserId%3D%22test%22%2BPassword%3D%22test%22%2BLanguage%3D%22en%22%2BHotel%3D%22-100%22%2BProductCode%3D%221--%22%2BArrivalDate%3D%2223.12.2018%22%2BDepartureDate%3D%2224.12.2018%22%2BArrivalTime%3D%22%22%2BDepartureTime%3D%22%22%2BCurrency%3D%222%22%2BWhereToPay%3D%223%22%2BNumberOfGuests%3D%220%22%2BNumberOfExtraBedsAdult%3D%220%22%2BNumberOfExtraBedsChild%3D%220%22%2BNumberOfExtraBedsInfant%3D%220%22%2B%2F%3E
Tout devient simple, et il n'est pas nécessaire de soustraire du corps à la requête - vous ne savez jamais quels problèmes il peut y avoir.
SpoilerJe ne sais pas pourquoi cela a été fait. Les problèmes sont les suivants: de nombreux serveurs ont une limite sur la longueur du chemin de demande qui peut les traverser. Si le XML est volumineux en volume de données, vous pouvez provoquer l'erreur 413 Entité trop grande dans l'un des scénarios. De plus, la quantité d'informations augmente, car nous effectuons le codage des URL avant l'envoi.
2. Transfert d'informations par imbrication excessive d'objets de données
Réfléchissons à la façon de rendre les informations dans les réponses aussi difficiles que possible? Utilisons des structures imbriquées, et même dans différents formats! Aussitôt dit, aussitôt fait -
<Request> <InnerRequest> <RQ>[{"someInfo":"base64Data"}] </RQ> </InnerRequest> </Request>
En effet, le xml de niveau supérieur, à l'intérieur, est un autre xml, et à l'intérieur, c'est json, dans lequel les données sont présentées en base64, et encore json, et il contiendra déjà les informations dont nous avons besoin! Une excellente solution, presque comme un conte de fées sur la mort de Koshchei, cachée dans un œuf.
SpoilerL'un des inconvénients les plus notables est le ralentissement de l'analyse de la réponse jusqu'à ce que toutes les structures imbriquées soient traversées, et il peut ensuite s'avérer que le code d'erreur est câblé en json, plutôt qu'à des niveaux supérieurs. Je comprends que l'encodage de données binaires en base64 dans xml / json est une pratique courante, mais encoder un format différent dans un format différent est déjà au-delà du bien et du mal.
3. Ajout d'informations non liées aux données de la demande et non valides dans le format de données
Supposons que XML nous parvienne dans le corps de la demande, nous le traitons et donnons une réponse. Cela semble trop compliqué pour un système bien conçu et lourdement chargé. Obligons les utilisateurs à envoyer le type de données dans le corps de la demande. Comment faire ça? Bien sûr, dans le corps de la demande.
XML= <Request> ... </Request>
D'une manière aussi simple, nous saurons toujours que nous avons reçu une demande au format XML.
SpoilerIl s'avère que nous devons ajouter plus d'octets de tête au corps déjà formé de la demande et seulement après cela, il sera possible de faire une demande. Heureusement si vous n'avez pas besoin de modifier les octets principaux en fonction du type de données de demande. Dans ce cas, il serait préférable d'utiliser l'en-tête http pour indiquer le type de données et non pour modifier le corps de la demande.
4. Duplication de données sans besoin
Supposons que nous ayons des informations très, très importantes dans la structure de la réponse XML. Comment montrer cela à l'utilisateur? Le plus évident - montrons-le plusieurs fois dans le cadre de la réponse, alors il y fera certainement attention.
<Response> <Obj Info="Important"> <ObjSetting Info="Important"/> <Name>SomeName</Name> <Info>Important</Info> </Obj> </Response>
Après cela, l'utilisateur final fera certainement attention au champ Info.
SpoilerDans ce cas, j'y ai pensé et j'ai même demandé à la société qui a fourni l'API la signification du champ Info et si les informations dans les balises à différents niveaux seraient différentes. La réponse était: non, ce ne sera pas le cas - ils se dupliquent. Pourquoi induire les utilisateurs en erreur et rendre la réponse plus difficile si cela n'est pas nécessaire?
5. Passer des paramètres du même type individuellement, pas un tableau
Dans l'une des API que nous utilisons pour rechercher des hôtels, des champs indiquent l'âge des clients. Quel format de présentation est le mieux utilisé pour transmettre ces informations? Que le format soit le suivant: chaque âge sera une balise XML obligatoire distincte, et nous considérerons la valeur 0 comme l'absence de ce paramètre.
<Request> <Age1>20</Age> <Age2>20</Age> <Age3>0</Age> <Age4>0</Age> </Request>
SpoilerIl y a plusieurs problèmes ici à la fois: non extensibilité, informations redondantes, en plus, l'âge peut vraiment être nul si les invités sont des nouveau-nés. Dans ce cas, vous devez utiliser un tableau plutôt que des balises de nom unique.
6. Transfert des informations des demandes précédentes dans le cadre de la chaîne d'appels API
Il est temps de penser à la sécurité de notre API. Comment comprenons-nous que l'utilisateur reçoit des informations de nos réponses précédentes? Laissez-le nous envoyer notre réponse, bien sûr!
<Request> <RequestInfo/> <PreviosResp> ... </PreviosResp> </Request>
SpoilerPour continuer à travailler avec l'API, il est nécessaire d'envoyer toute la réponse du système externe à partir des étapes précédentes de l'API, et non certaines données importantes de celui-ci, ou même un hachage qui correspondra certainement à cette réponse. Excès de données dans toute sa splendeur.
7. N'utilisez pas de marqueurs d'une erreur qui s'est produite, comme une balise d'erreur ou un code http
Nous avons créé notre belle API et l'avons présentée au monde. Mais une fois que quelque chose s'est mal passé, nous n'avons pas pu formuler de réponse à l'utilisateur en raison d'une erreur interne. Que faire dans ce cas? Donnez simplement un modèle de réponse, sans données, sans codes d'erreur ni aucune autre information. Personne ne devrait savoir que notre API idéale peut parfois ne pas fonctionner!
Un exemple d'une telle réponse:
<Response> <ImportantInfo/> </Response>
- avec un code de réponse de 200 OK.
SpoilerÉtouffer les erreurs commises est une très mauvaise pratique. Le problème est que tout semble ne poser aucun problème dans la réponse: il n'y a pas de <Error>
, le statut http indique que tout est en ordre. Dans ce cas, il est nécessaire d'effectuer une validation supplémentaire des informations reçues afin qu'il n'y ait pas de conséquences imprévues déjà dans notre système.
Conclusion
Malgré la grande quantité de documentation sur l'utilisation des technologies SOAP / XML et la conception d'API, de nombreux problèmes sont toujours d'actualité et certaines solutions sont contraires au bon sens. J'espère qu'avec cet article je serai en mesure d'attirer l'attention des développeurs sur les approches les moins réussies afin de réduire leur nombre à l'avenir.