Je conçois et implémente actuellement une API RESTful en PHP. Cependant, je n'ai pas réussi à implémenter ma conception initiale.
GET /users # list of users
GET /user/1 # get user with id 1
POST /user # create new user
PUT /user/1 # modify user with id 1
DELETE /user/1 # delete user with id 1
Jusqu'à présent assez standard, non?
Mon problème est avec le premier GET /users
. J'envisageais d'envoyer des paramètres dans le corps de la demande pour filtrer la liste. C'est parce que je veux pouvoir spécifier des filtres complexes sans avoir une URL super longue, comme:
GET /users?parameter1=value1¶meter2=value2¶meter3=value3¶meter4=value4
Au lieu de cela, je voulais avoir quelque chose comme:
GET /users
# Request body:
{
"parameter1": "value1",
"parameter2": "value2",
"parameter3": "value3",
"parameter4": "value4"
}
qui est beaucoup plus lisible et vous offre de grandes possibilités pour définir des filtres complexes.
Quoi qu'il en soit, file_get_contents('php://input')
n'a pas renvoyé le corps de la demande pour les GET
demandes. J'ai également essayé http_get_request_body()
, mais l'hébergement partagé que j'utilise n'a pas pecl_http
. Pas sûr que cela aurait aidé de toute façon.
J'ai trouvé cette question et j'ai réalisé que GET n'est probablement pas censé avoir un corps de demande. C'était un peu peu concluant, mais ils l'ont déconseillé.
Alors maintenant, je ne sais pas quoi faire. Comment concevez-vous une fonction de recherche / filtrage RESTful?
Je suppose que je pourrais utiliser POST
, mais cela ne semble pas très reposant.
Réponses:
La meilleure façon d'implémenter une recherche RESTful est de considérer la recherche elle-même comme une ressource. Ensuite, vous pouvez utiliser le verbe POST car vous créez une recherche. Vous n'avez pas besoin de créer littéralement quelque chose dans une base de données pour utiliser un POST.
Par exemple:
Vous créez une recherche du point de vue de l'utilisateur. Les détails de mise en œuvre de cela ne sont pas pertinents. Certaines API RESTful peuvent même ne pas avoir besoin de persistance. C'est un détail d'implémentation.
la source
Si vous utilisez le corps de la demande dans une demande GET, vous ne respectez pas le principe REST, car votre demande GET ne pourra pas être mise en cache, car le système de cache utilise uniquement l'URL.
Et pire encore, votre URL ne peut pas être mise en signet, car l'URL ne contient pas toutes les informations nécessaires pour rediriger l'utilisateur vers cette page
Utilisez des paramètres d'URL ou de requête au lieu des paramètres de corps de demande.
par exemple:
En fait, le HTTP RFC 7231 dit que:
Une charge utile dans un message de demande GET n'a pas de sémantique définie; l'envoi d'un corps de charge utile sur une demande GET peut entraîner le rejet de la demande par certaines implémentations existantes.
Pour plus d'informations jetez un œil ici
la source
Il semble que le filtrage / recherche de ressources puisse être implémenté de manière RESTful. L'idée est d'introduire un nouveau noeud final appelé
/filters/
ou/api/filters/
.L'utilisation de ce filtre de point de terminaison peut être considérée comme une ressource et donc créée via une
POST
méthode. De cette façon - bien sûr - le corps peut être utilisé pour transporter tous les paramètres ainsi que des structures de recherche / filtre complexes peuvent être créées.Après avoir créé un tel filtre, il existe deux possibilités pour obtenir le résultat de la recherche / du filtre.
Une nouvelle ressource avec un ID unique sera retournée avec le
201 Created
code d'état. Ensuite, en utilisant cet ID, uneGET
demande peut être faite pour/api/users/
aimer:Une fois le nouveau filtre créé via,
POST
il ne répondra pas avec201 Created
mais immédiatement avec l'303 SeeOther
en-Location
tête pointant vers/api/users/?filterId=1234-abcd
. Cette redirection sera automatiquement gérée via la bibliothèque sous-jacente.Dans les deux scénarios, deux demandes doivent être faites pour obtenir les résultats filtrés - cela peut être considéré comme un inconvénient, en particulier pour les applications mobiles. Pour les applications mobiles, j'utiliserais un seul
POST
appel à/api/users/filter/
.Comment conserver les filtres créés?
Ils peuvent être stockés dans DB et utilisés plus tard. Ils peuvent également être stockés dans un stockage temporaire, par exemple redis et avoir un TTL après lequel ils expireront et seront supprimés.
Quels sont les avantages de cette idée?
Les filtres, les résultats filtrés peuvent être mis en cache et peuvent même être mis en signet.
la source
Je pense que vous devriez utiliser les paramètres de demande, mais seulement tant qu'il n'y a pas d'en-tête HTTP approprié pour accomplir ce que vous voulez faire. La spécification HTTP ne dit pas explicitement que GET ne peut pas avoir de corps. Cependant, ce document déclare:
la source
Comme j'utilise un backend laravel / php, j'ai tendance à aller avec quelque chose comme ça:
PHP transforme automatiquement les
[]
paramètres en tableau, donc dans cet exemple, je vais me retrouver avec une$filter
variable qui contient un tableau / objet de filtres, ainsi qu'une page et toutes les ressources connexes que je veux ardemment chargées.Si vous utilisez une autre langue, cela peut toujours être une bonne convention et vous pouvez créer un analyseur à convertir
[]
en tableau.la source
[
et]
. L'utilisation de représentations codées de ces caractères pour regrouper les paramètres de requête est une pratique bien connue. Il est même utilisé dans la spécification JSON: API .Ne vous inquiétez pas trop si votre API initiale est entièrement RESTful ou non (surtout lorsque vous êtes juste au stade alpha). Faites fonctionner la plomberie principale en premier. Vous pouvez toujours faire une sorte de transformation / réécriture d'URL pour mapper les choses, en affinant de manière itérative jusqu'à ce que vous obteniez quelque chose d'assez stable pour des tests généralisés ("beta").
Vous pouvez définir des URI dont les paramètres sont codés par position et convention sur les URI eux-mêmes, préfixés par un chemin que vous savez que vous mapperez toujours à quelque chose. Je ne connais pas PHP, mais je suppose qu'une telle fonctionnalité existe (comme elle existe dans d'autres langages avec des frameworks web):
.c'est à dire. Effectuez une recherche de type "utilisateur" avec param [i] = valeur [i] pour i = 1..4 sur le magasin # 1 (avec valeur1, valeur2, valeur3, ... comme raccourci pour les paramètres de requête URI):
ou
ou comme suit (bien que je ne le recommanderais pas, plus à ce sujet plus tard)
Avec l'option 1, vous mappez tous les URI préfixés avec
/store1/search/user
le gestionnaire de recherche (ou la désignation PHP) par défaut pour effectuer des recherches de ressources sous store1 (équivalent à/search?location=store1&type=user
.Par convention documentée et appliquée par l'API, les valeurs des paramètres 1 à 4 sont séparées par des virgules et présentées dans cet ordre.
L'option 2 ajoute le type de recherche (dans ce cas
user
) comme paramètre positionnel # 1. L'une ou l'autre option n'est qu'un choix esthétique.L'option 3 est également possible, mais je ne pense pas que je l'aimerais. Je pense que la capacité de recherche dans certaines ressources devrait être présentée dans l'URI lui-même précédant la recherche elle-même (comme si elle indiquait clairement dans l'URI que la recherche est spécifique au sein de la ressource.)
L'avantage de cela sur le passage de paramètres sur l'URI est que la recherche fait partie de l'URI (traitant ainsi une recherche comme une ressource, une ressource dont le contenu peut - et changera - au fil du temps.) L'inconvénient est que l'ordre des paramètres est obligatoire .
Une fois que vous avez fait quelque chose comme ça, vous pouvez utiliser GET, et ce serait une ressource en lecture seule (puisque vous ne pouvez pas POST ou PUT - il est mis à jour quand il est GET). Ce serait également une ressource qui n'existerait que lorsqu'elle serait invoquée.
On pourrait également y ajouter plus de sémantique en mettant en cache les résultats pendant un certain temps ou avec une SUPPRESSION entraînant la suppression du cache. Cependant, cela peut aller à l'encontre de ce que les gens utilisent généralement pour SUPPRIMER (et parce que les gens contrôlent généralement la mise en cache avec des en-têtes de mise en cache.)
La façon dont vous allez procéder serait une décision de conception, mais ce serait la façon dont je procéderais. Ce n'est pas parfait, et je suis sûr qu'il y aura des cas où ce n'est pas la meilleure chose à faire (spécialement pour des critères de recherche très complexes).
la source
FYI: Je sais que c'est un peu tard mais pour tous ceux qui sont intéressés. Cela dépend de la façon dont vous voulez être RESTful, vous devrez implémenter vos propres stratégies de filtrage car la spécification HTTP n'est pas très claire à ce sujet. Je voudrais suggérer de coder par URL tous les paramètres de filtre, par exemple
Je sais que c'est moche mais je pense que c'est la façon la plus reposante de le faire et devrait être facile à analyser côté serveur :)
la source