SPIP-Contrib

SPIP-Contrib

عربي | Deutsch | English | Español | français | italiano | Nederlands

286 Plugins, 197 contribs sur SPIP-Zone, 243 visiteurs en ce moment

Accueil > Outils pour plugins > Plugin HTTP > Serveur HTTP abstrait

Serveur HTTP abstrait

25 novembre 2013 – par RastaPopoulos – commentaires

12 votes

Un plugin-outil pour aider les développeurs à implémenter des API orientées REST, basées sur les méthodes HTTP (get, post, put, delete).

Ce plugin a pour but premier de normaliser des URL que l’on pourra appeler pour manipuler les données du site. À chaque URL, il cherche une fonction plus précise, qui va implémenter une fonctionnalité. Et il ne fait quasiment que cela : c’est à vous, développeuses et développeurs, d’implémenter ces fonctionnalités suivant l’API que vous cherchez à fournir.

Pour cela, il fournit une unique action « http.api » qui va gérer trois paramètres :

  • un format : c’est le nom de l’API réellement implémentée
  • une collection : le type des données qu’on veut utiliser, par exemple le nom d’un objet éditorial de SPIP
  • une ressource : l’identifiant unique d’un contenu

Ces trois paramètres sont tout simplement ajoutés à la suite dans l’URL, séparés par des « / ». Seul le premier est toujours obligatoire, les autres sont ajoutés suivant ce que l’on veut manipuler. On se retrouve alors avec trois familles d’URL. Par exemple avec le format « atom » :

  • http://site.example/http.api/atom
    désigne l’index du format, et peut être utilisé pour lister les collections réellement disponibles (si ce format prévoit ce genre d’index !)
  • http://site.example/http.api/atom/articles
    désigne la collection des articles, et doit donc fournir une liste de plusieurs articles, à priori tous s’il n’y a pas de paramètres de filtrages supplémentaires
  • http://site.example/http.api/atom/articles/1234
    désigne l’URL d’un article précis dans ce format

Pour chacun de ces URLs, on cherche enfin la méthode HTTP utilisée pour l’appeler : get, post, put ou delete. Suivant la conjonction de tous ces paramètres, le plugin appelle la bonne fonction.

Bien entendu, chaque développeur doit adapter ce cadre à l’API qu’il désire réellement implémenter.

Utilisation de la librairie HTTPFoundation

Petite précision : afin de ne pas gérer nous-mêmes les affres des requêtes et des réponses en HTTP, ce plugin intègre et utilise la librairie HTTPFoundation fournie par Symfony.

Vous trouverez la documentation de ce module par ici :
http://symfony.com/fr/doc/current/components/http_foundation/introduction.html

Ce plugin crée donc dès le début un objet Request et un objet Response, qui seront ensuite trimbalés et modifiés au fil du temps dans les fonctions d’implémentation.

Nos trois paramètres essentiels sont déjà ajoutés à l’objet Request dans la propriété des attributs persos :

  • $requete->attributes->get('format')
  • $requete->attributes->get('collection')
  • $requete->attributes->get('ressource')

Implémentation d’une API

Pour implémenter une API (la votre ou un standard reconnu du monde entier), vous devez tout d’abord créer un fichier /http/*format*.php où « *format* » est le nom donné à votre API.
Par exemple /http/atom.php (nous utiliserons cet exemple pour la suite).

Ensuite, vous devez créer une fonction pour chaque cas d’utilisation que vous souhaitez pouvoir gérer. Chacune de ces fonctions DOIT renvoyer l’objet Response valide, en l’ayant à priori modifié au passage, par exemple pour changer le statut de la réponse ($reponse->setStatusCode()), ou encore son contenu ($reponse->setContent()).

http_atom_get_index($requete, $reponse)

Vue générale d’un format, par exemple pour afficher la liste des collections disponibles.

Pour le format « atom » par exemple, il existe déjà une norme pour décrire cela. On trouve un exemple dans la documentation du standard « APP » (Atom Publishing Protocol) :
http://tools.ietf.org/html/rfc5023#section-8.2

http_atom_get_collection($requete, $reponse)

Liste le contenu de la collection dont le nom est dans la variable $requete->attributes->get('collection').

Pour le format « atom », ça serait un flux atom des articles (ou des résumés), par exemple.

Bien entendu, votre implémentation peut parfaitement accepter ou demander des paramètres supplémentaires, pour filtrer le contenu final. Tel que ?recherche=truc&id_rubrique=321.

http_atom_get_ressource($requete, $reponse)

La vue d’une ressource précise (un article par exemple), dans le format attendu. L’identifiant de la ressource (l’id_article si c’en est un) est dans la variable $requete->attributes->get('ressource').

http_atom_post_collection($requete, $reponse)

Créer une nouvelle ressource dans la collection (créer un nouvel article). Normalement, l’utilisateur devrait avoir envoyé une représentation de la ressource dans le format géré par votre API. Par exemple un article au format atom.

Vous devez donc savoir lire ce format, et et le traiter pour créer la ressource correspondante (ajouter un article dans la base).

http_atom_put_ressource($requete, $reponse)

Ce cas est sensiblement le même que le précédent, à ceci près que l’on travaille sur la modification d’une ressource précise. Tout comme les formulaires CVT « editer_truc » savent gérer à la fois la création et la modification, il y a de grandes chances pour que ces deux dernières fonctions soient souvent similaires.

http_atom_delete_ressource($requete, $reponse)

Supprimer définitivement une ressource. Attention ce n’est pas pareil que modifier un statut (qui se ferait avec PUT à priori). Cela dépend donc des usages et des objets. Par exemple par défaut dans SPIP, on ne supprime pas un article mais on change le statut à « poubelle », et quelques temps plus tard, une tâche de fond le supprimera réellement.

Gestion générique des erreurs

Lors de l’implémentation, une fonction supplémentaire est obligatoire, pour que le plugin HTTP sache quoi renvoyer s’il trouve une erreur avant vous (avant vos fonctions précises) :
http_atom_erreur_dist($code, $requete, $reponse)

Cette fonction prend en paramètre supplémentaire un code d’erreur HTTP (401, 404, etc) et doit savoir renvoyer une réponse, si possible dans le format en rapport avec votre API.

Pour le format « atom », il n’y a malheureusement pas de syntaxe pour décrire les erreurs. Mais dans d’autres format, en JSON ou autre, il existe des manières pour lister la ou les erreurs.

Lors que le plugin HTTP rencontre une erreur d’autorisations (401) ou qu’il ne trouve pas d’implémentation pour une URL (404), il utilise cette fonction générique pour renvoyer les erreurs plus proprement.

Cela ne vous empêche pas de générer d’autres erreurs plus complexes par la suite, dans vos fonctions d’implémentation.

Gestion des autorisations

Pour chaque action demandée, le plugin HTTP teste déjà une autorisation, avec comme paramètres :

  • le verbe HTTP accolé au type d’URL : « get_collection », « put_ressource », etc
  • le nom de la collection si présent : « articles », « patates »
  • l’identifiant de la ressource si présent : 1234

Comme on le voit, le format n’est pas présent dans le calcul de ces autorisations. En effet, on considère que si on peut faire une action (créer un article) en « atom », on peut le faire en « json » aussi, bref, quelque soit le format.

Par ailleurs, par défaut, le plugin défini déjà ces autorisations quelque soit le type de collection, en les calquant sur les fonctions déjà utilisées dans SPIP : « modifier », « creer », etc.

Dans la grande majorité des cas, vous n’aurez donc même pas à définir ces autorisations, car les utilisateurs de votre API auront tout simplement les mêmes droits que dans les interfaces de SPIP (ie : s’ils ne peuvent pas modifier tel article dans l’admin, ils ne pourront pas non plus par l’API).

Si vous devez malgré tout les préciser, l’une de vos autorisations pourrait donc ressembler à :
autoriser_article_put_ressource($faire, $quoi, $id, $qui, $opt)

Exemples

Un exemple d’implémentation presque complet est le plugin « Collection+JSON » qui propose de manipuler les objets du site dans ce format (JSON n’étant qu’un conteneur, la grammaire interne peut être n’importe quoi, ce format est une des manières de faire).
http://zone.spip.org/trac/spip-zone/browser/_plugins_/collection_json/trunk

Un autre exemple non complet, qui ne gère pour l’instant que les « GET », est le plugin « APP ». Celui ci propose d’aller chercher des squelettes /http/app/patates.html et /http/app/patates-ressource.html correspondant respectivement au flux de la collection « patates », et à la vue d’une seule patate, dans le format Atom.
http://zone.spip.org/trac/spip-zone/browser/_plugins_/app/trunk

Voir en ligne : http://plugins.spip.net/http

Dernière modification de cette page le 16 mars 2016

Retour en haut de la page

Vos commentaires

  • Le 31 août 2016 à 16:49, par Luis Speciale En réponse à : Serveur HTTP abstrait

    Hola Rasta ;

    J’avais besoin de faire remonter une variable d’un squelette inclus jusqu’au parent,
    pour qu’il puisse ensuite répercuter cette variable à un troisième squelette inclus.
    Globalement c’est ça…

                 __  Enfant A
                |      ↓
                |     /
                |    /
    Parent   ___| ←
                |  →
                |    \
                |     \
                |      ↓
                |__  Enfant B

    J’ai passé un certain temps à vouloir implémenter cette élégante solution
    https://contrib.spip.net/Astuces-longues-pour-SPIP#a1
    mais sans succès aucun. Pommé comme un pingouin chez le Minotaure.

    Donc, est-ce que je pourrais émettre un flux provenant de Enfant A que Enfant B pourrait lire ?
    Par exemple…

    1. <BOUCLE_ENFANT_A(ARTICLES){O,2}{doublons enfant_a}>
    2. Comment écrire (ou encore créer ou supprimer)
    3. dans le flux le résultat de cette boucle?
    4. </BOUCLE_ENFANT_A>

    Télécharger


    FLUX

    1. <BOUCLE_ENFANT_B(ARTICLES){doublons enfant_a}>
    2. Et comment le lire ensuite ?
    3. </BOUCLE_ENFANT_B>

    Télécharger

    J’ai vu que en allant à
    #URL_SITE_SPIP/collectionjson/articles/1
    J’ai

    
    « collection » : 
      « version » : « 1.0 »,
      « href » : « http:\/\/site\/http.api\/collectionjson\/articles\/1 »,
      « items » : [
        « href » : « http:\/\/site\/http.api\/collectionjson\/articles\/1 »,
        « links » : [
          « rel » : « edit »,
          « href » : « http:\/\/site\/http.api\/collectionjson\/articles\/1 »
        , 
          « rel » : « alternate »,
          « type » : « text\/html »,
          « href » : « http:\/\/site\/spip.php ?article1 »
        ],
        « data » : [
          « name » : « surtitre »,
          « value » : « Surtitre de l’article »
        , 
          « name » : « titre »,
          « value » : « Titre de l’article »
          ]
      ]
    


    Où il fait la différence entre edit (l’URI)

          « rel » : « edit »,
          « href » : « http:\/\/site\/http.api\/collectionjson\/articles\/1 »
    

    et alternate (l’URL)

          « rel » : « alternate »,
          « type » : « text\/html »,
          « href » : « http:\/\/site\/spip.php ?article1 »

    Et là je coince. Il me faudrait un exemple concret

    • Le 1er septembre 2016 à 00:16, par RastaPopoulos En réponse à : Serveur HTTP abstrait

      Bah elle est très bien l’astuce du premier lien. Faire un squelette dédié qui génère un tableau (serialize ou JSON peu importe) et l’appeler avec #INCLURE pour pouvoir le mettre dans un #SET.

      Je comprends le besoin expliqué au départ (et ça correspond bien à l’astuce en question), mais je ne vois pas en quoi le plugin HTTP ou le plugin Collection-JSON pourrait faire quelque chose de plus.

    • Le 1er septembre 2016 à 16:43, par Luis Speciale En réponse à : Serveur HTTP abstrait

      Pour faire quelque chose de plus, il faudrait que au moins ça arrive à marcher mal, parce que là, ça ne marche pas.
      J’ai un squelette parent et deux enfants : un qui a la première boucle (qui devrait émettre) et l’autre ayant la boucle qui devrait recevoir.
      Comme ça fait un moment que je bataille avec, je me suis dit que le REST était peut-être une piste. Et en plus, le plaisir d’apprendre un truc nouveau.
      Je me disais qu’il me fallait un exemple de boucles pour lire,créer, modifier et détruire (et une manière de sécuriser). Mais il se peut que ce soit trop compliqué pour moi. En tout cas, ce sûr que là je ne pige pas.

    Répondre à ce message

  • Le 13 juin 2014 à 18:06, par Thomas Weiss En réponse à : Serveur HTTP abstrait

    Très intéressant.
    Cela ouvre des perspectives pour la mobilité...

    Répondre à ce message

Répondre à cet article

Qui êtes-vous ?

Pour afficher votre trombine avec votre message, enregistrez-la d’abord sur gravatar.com (gratuit et indolore) et n’oubliez pas d’indiquer votre adresse e-mail ici.

Ajoutez votre commentaire ici Les choses à faire avant de poser une question (Prolégomènes aux rapports de bugs. )
Ajouter un document

Retour en haut de la page

Ça discute par ici

  • Cycle2

    7 août 2014 – 104 commentaires

    La seconde version de la librairie Javascript « jQuery Cycle », qui permet de produire des diaporamas, se nomme « Cycle2 » : http://jquery.malsup.com/cycle2/. Voici cette nouvelle librairie mise en plugin pour SPIP. Si vous utilisez déjà « jQuery (...)

  • CleverMail

    20 janvier 2010 – 635 commentaires

    CleverMail est un plugin permettant d’envoyer des lettres d’informations à des abonnés depuis SPIP. Issu au départ d’un développement libre complètement indépendant de SPIP, il a connu une première version pour SPIP 1.9 avant d’être complètement réécris (...)

  • SPMC : Squelette par mot clé V2.0

    21 septembre 2009 – 48 commentaires

    Ce plugin prend la suite de squelette par mot clef V1.92 qui ne fonctionnait plus sous SPIP 2.0.x. Avec l’accord de Mortimer qui n’a plus le temps de le maintenir, je prend donc la suite. Présentation du plugin « Squelette par mot clé V2.0 » Le (...)

  • Sarka-SPIP 3

    15 septembre 2009 – 211 commentaires

    Si la lignée 3 de Sarka-SPIP a été l’occasion de refaire presque entièrement le code du squelette elle continue à évoluer et à s’améliorer au fil des versions. Nous ne saurions trop conseiller aux nouveaux utilisateurs - et aussi aux anciens - (...)

  • Paiement avec Formidable

    16 février 2015 – 53 commentaires

    Ce plugin « Paiement avec Formidable » permet d’ajouter une étape de paiement à la fin de la saisie d’un formulaire créé par le plugin Formidable. Il le complète et nécessite par ailleurs le plugin bank qui gère l’interface technique avec les prestataires (...)