J'ai besoin de concevoir une API de requête RESTful, qui renvoie un ensemble d'objets basé sur quelques filtres. La méthode HTTP habituelle pour cela est GET. Le seul problème est qu'il peut avoir au moins une douzaine de filtres, et si nous les passons tous en tant que paramètres de requête, l'URL peut devenir assez longue (assez longue pour être bloquée par un pare-feu).
La réduction du nombre de paramètres n'est pas une option.
Une alternative à laquelle je pourrais penser est d'utiliser la méthode POST sur l'URI et d'envoyer les filtres dans le cadre du corps POST. Est-ce contre RESTfull (faire un appel POST pour interroger des données)
Quelqu'un a-t-il de meilleures suggestions de conception?
api
rest
http-parameters
missionE46
la source
la source
Réponses:
N'oubliez pas qu'avec une API REST, tout dépend de votre point de vue.
Les deux concepts clés d'une API REST sont les points de terminaison et les ressources (entités). En gros, un point de terminaison retourne des ressources via GET ou accepte des ressources via POST et PUT et ainsi de suite (ou une combinaison des éléments ci-dessus).
Il est admis qu'avec POST, les données que vous envoyez peuvent ou non entraîner la création d'une nouvelle ressource et de son ou ses points de terminaison associés, qui ne «vivront» probablement pas sous l'URL POSTée. En d'autres termes, lorsque vous POSTEZ, vous envoyez des données quelque part pour les manipuler. Le point de terminaison POST n'est pas l'endroit où la ressource peut normalement être trouvée.
Citant la RFC 2616 (avec les parties non pertinentes omises et les parties pertinentes mises en évidence):
Nous nous sommes habitués aux points de terminaison et aux ressources représentant des «choses» ou des «données», que ce soit un utilisateur, un message, un livre - quel que soit le domaine du problème. Cependant, un point de terminaison peut également exposer une ressource différente, par exemple des résultats de recherche.
Prenons l'exemple suivant:
Il s'agit d'un CRUD REST typique. Mais que faire si nous ajoutions:
Il n'y a rien de non-RESTful à propos de ce point de terminaison. Il accepte des données (entité) sous la forme du corps de la requête. Ces données sont les critères de recherche - un DTO comme les autres. Ce point de terminaison produit une ressource (entité) en réponse à la demande: Résultats de la recherche . La ressource de résultats de recherche est temporaire, servie immédiatement au client, sans redirection et sans être exposée à partir d'une autre URL canonique.
Il s'agit toujours de REST, sauf que les entités ne sont pas des livres - l'entité de demande est des critères de recherche de livres et l'entité de réponse est des résultats de recherche de livres.
la source
BooksSearchCriteriaDTO
etBooksSearchResultsDTO
.POST
est utilisé pour la partie C de CRUD. J'irais avec le vieux 200, éventuellement avec 204 pour les résultats de recherche vides.Beaucoup de gens ont accepté la pratique selon laquelle un GET avec une chaîne de requête trop longue ou trop complexe (par exemple, les chaînes de requête ne gèrent pas facilement les données imbriquées) peut être envoyé en tant que POST à la place, avec les données complexes / longues représentées dans le corps de la demande.
Recherchez la spécification POST dans la spécification HTTP. C'est incroyablement large. (Si vous voulez naviguer sur un cuirassé à travers une faille dans REST ... utilisez POST.)
Vous perdez certains des avantages de la sémantique GET ... comme les tentatives automatiques parce que GET est idempotent, mais si vous pouvez vivre avec cela, il pourrait être plus facile d'accepter le traitement de requêtes très longues ou compliquées avec POST.
(lol longue digression ... J'ai récemment découvert que par la spécification HTTP, GET peut contenir un corps de document. Il y a une section qui dit, paraphrasant, "Toute requête peut avoir un corps de document sauf ceux listés dans cette section" ... et la section à laquelle il se réfère n'en répertorie aucun. J'ai cherché et trouvé un fil de discussion où les auteurs HTTP en parlaient, et c'était intentionnel, de sorte que les routeurs et autres n'auraient pas à faire la différence entre les différents messages. Cependant, dans pratiquez beaucoup de pièces d'infrastructure font tomber le corps d'un GET. Vous pouvez donc GET avec des filtres représentés dans le corps, comme POST, mais vous lanceriez les dés.)
la source
En un mot: créez un POST mais remplacez la méthode HTTP à l'aide de l'en- tête X-HTTP-Method-Override .
Vraie demande
POST / livres
Corps d'entité
{"title": "Ipsum", "year": 2017}
En-têtes
X-HTTP-Method-Override: GET
Du côté du serveur, vérifiez si l'en-tête X-HTTP-Method-Override existe, puis prenez sa valeur comme méthode pour construire la route vers le point de terminaison final dans le backend. Prenez également le corps de l'entité comme chaîne de requête. D'un point de vue backend, la requête est devenue un simple GET.
De cette façon, vous gardez la conception en harmonie avec les principes REST.
Edit: Je sais que cette solution était à l'origine destinée à résoudre le problème du verbe PATCH dans certains navigateurs et serveurs, mais cela fonctionne aussi pour moi avec le verbe GET dans le cas d'une URL très longue qui est le problème décrit dans la question.
la source
X-
suppression existante et 1.5. il ne remplace pas les spécifications existantes. ...X-
l'OMI restera-t-elle ici.Si vous développez en Java et JAX-RS, je vous recommande d'utiliser @QueryParam avec @GET
J'avais la même question quand j'avais besoin de parcourir une liste.
Voir exemple:
Modèle d'URI: "poc / test? Code = 1 & code = 2 & code = 3
@QueryParam convertira automatiquement le paramètre de requête «orderBy = age & orderBy = name» en java.util.List.
la source