:orphan: ================== TP n°7 : API Web ================== .. highlight:: json Votre travail ============= Ajoutez au site développé au `TP n°4 `:doc: une API, répondant au patron "collection/éléments" vus en cours. Plus précisément, votre API comportera : * une collection de gènes ``/api/genes/``, * un élément par gène ``/api/genes/``. On vous suggère de procéder dans cet ordre : ``GET /api/genes/`` fournit la `représentation détaillée`_ du gène correspondant. Si l'identifiant fourni ne correspond à aucun gène, retourne un `objet erreur`_ avec le code 404. ``GET /api/genes/`` fournit les 100 premièrs gènes de la base (triés selon ``Ensembl_Gene_ID``), sous la forme d'une liste de `représentations compactes`_. Si un paramètre ``?offset=X`` est fourni, fournit les 100 premiers gènes de la base *à partir du (X+1)-ième*. .. _api_post_gene: ``POST /api/genes/`` accepte une `représentation détaillée`_ d'un gène à l'exception de l'attribut ``transcripts``, et l'ajoute à la base si les conditions suivantes sont remplies ; + ``Ensemble_Gene_ID`` est renseigné, est une chaîne, et n'est pas un identifiant déjà présent dans la base ; + ``Chromosome_Name`` est renseigné, et est une chaîne ; + ``Band`` est une chaîne ; + ``Strand`` est un entier (ou non renseigné) ; + ``Gene_Start`` est renseigné, et est un entier ; + ``Gene_End`` est renseigné, est un entier, et est supérieur à ``Gene_Start`` ; + ``Associated_Gene_Name`` est une chaîne (ou non renseigné) ; + l'objet ne possède aucun autre attribut. En cas de violation d'une de ces contraintes, retourne un `objet erreur`_ avec le code 4xx adéquat. En cas de succès, retourne le code 201 (`created`:en:) avec un objet de la forme :: { "created": ["URL du gène créé"] } ``DELETE /api/Genes/`` supprime le gène correspondant (s'il existe), et retourne avec un code 200 un objet de la forme :: { "deleted": "" } Si le gène correspondant n'existe pas, la *même* réponse (avec un code 200) doit être retournée. Pour aller plus loin -------------------- * Intégrez la gestion des etags pour les requêtes GET (en utilisant, par exemple, la date de modification du fichier sqlite). * Améliorez la route ``GET /api/Genes/`` ainsi a : elle fournit désormais un objet JSON de la forme :: { "items": [ "100 représentations compactes" ], "first": 101, "last": 200, "prev": "http://localhost:5000/api/Genes/?offset=0", "next": "http://localhost:5000/api/Genes/?offset=200", } * Améliorez la route ``POST /api/Genes/`` ainsi : accepte désormais également une *liste* de d'objets correspondant chacun au modèle décrit ci-dessus. En cas d'échec, aucun des gènes n'est créé. En cas de succès, l'objet retourné est de la forme :: { "created": [ "URL du 1er gène créé", "URL du 2ème gène créé", "..." ] } * Ajoutez la route ``PUT /api/genes/`` acceptant le même type de données que ``POST /api/Genes/``, avec comme contrainte supplémentaire que ``Ensemble_Gene_ID`` doit être égal à la valeur ```` passée dans l'URL. Si le gène correspondant existe, il doit être modifié conformément aux données passées. S'il n'existe pas, il doit être créé (alternative au ``POST`` sur la collection). * Intégrez la gestion des etags pour le requête PUT (en cas de modification d'un gène existant). Représentations JSON ==================== .. _représentation compacte: .. _représentations compactes: Représentation compacte d'un gène --------------------------------- On appelle représentation compacte d'un gène un objet JSON contenant les valeurs de la table *Genes*, ainsi qu'un attribut ``href`` contenant l'URL du gène. Par exemple :: { "Ensembl_Gene_ID": "ENSG00000000003", "Associated_Gene_Name": "TSPAN6", "Chromosome_Name": "X", "Band": "q22.1", "Strand": -1, "Gene_End": 99894988, "Gene_Start": 99883667, "Transcript_count": 4, "href": "http://localhost:5000/api/Genes/ENSG00000000003" } .. _représentation détaillée: Représentation détaillée d'un gène ---------------------------------- On appelle représentation détaillée d'un gène un objet JSON contenant les valeurs de la table *Genes*, ou le champs ``Transcript_count`` est remplacé par un attribut ``transcripts`` contenant les transcrits associés sous forme d'une liste d'objets, contenant chacun le nom du transcrit, sa position de départ, et sa position de fin. Par exemple :: { "Ensembl_Gene_ID": "ENSG00000000003", "Associated_Gene_Name": "TSPAN6", "Chromosome_Name": "X", "Band": "q22.1", "Strand": -1, "Gene_End": 99894988, "Gene_Start": 99883667, "transcripts": [ { "Ensembl_Transcript_ID": "ENST00000373020", "Transcript_End": 99891803, "Transcript_Start": 99883667 }, { "Ensembl_Transcript_ID": "ENST00000431386", "Transcript_End": 99891848, "Transcript_Start": 99884765 }, { "Ensembl_Transcript_ID": "ENST00000496771", "Transcript_End": 99891686, "Transcript_Start": 99887538 }, { "Ensembl_Transcript_ID": "ENST00000494424", "Transcript_End": 99894988, "Transcript_Start": 99888439 } ] } .. _objet erreur: Objet erreur ------------ On appelle objet erreur un objet JSON possédant un unique attribut ``error`` dont la valeur est un message explicatif. Exemple :: { "error": "Ce gène n'existe pas" }