presentation



presentation

0 0


presentation

presentation

On Github mguillem37 / presentation

Normes ICDC encadrant les développements d'API REST

Formalisme des URI

Les ressources sont identifiées par des URIElles doivent respecter le formalisme suivant :

http://host:port/context/rest/api-name/api-version/path-uri[/...]

    exemple : 
        http://sps-int.serv.cdc.fr/clients/1.0/01AGZ201/contrats

    avec :
      context : nom de l'application web regroupant les API REST (fichier context.xml)
      rest : nom associé au dispatcher Spring MVC (fichier web.xml)
      api-name : nom de la ressource
      api_version : version de l'API au format M.m
      resource-uri : chemin(s) associé à la ressource     

Keep URIs Cool

  • Utilisation du separator "/" au niveau des URI pour indiquer une relation hiérarchique entre ressources

      http://sps-int.serv.cdc.fr/clients/1.0/01AGZ201/contrats
  • Utilisation possible des caractères "_" et "-" au niveau des URI pour les rendre plus lisibles

      http://sps-int.serv.cdc.fr/clients/1.0/recherche-par-nom
  • Utilisation du caractère "&" pour séparer les paramètres attendu par une ressource

      http://sps-int.serv.cdc.fr/clients/1.0?nom=DURAND&limit=30
  • Eviter l'utilisation du caractère "." qui sert principalemnt à séparer le document de son extension

Template URI

  • Pour facilter l'utilisation et la compréhension des APIS, il est possible de les décrire sous la forme de templates.
  • Ces templates doivent être complétés des verbes HTTP adéquats (GET, POST, ...)
  • Swagger et WADL peuvent être utilisés comme formalisme

Versionning

Representation

  • Par défaut, les API Rest doivent supporter JSON (Natural)
  • d'autres représentations (xml, pdf, html) sont autorisées

Type de données

TODO

  • date
  • nombre

Tri, Pagination, Filtrage

Tri

Principe : repose sur l'ajout de paramètre à la requête

Ordre du tri, champ(s) concerné(s)

    ...?sortByAsc=<champ1>[,<champs2>] 
    ...?sortByDesc=<nom du champ>[,<champs2>]

    ces deux paramètres peuvent être mixés pour la même requête

Fixe une limite au nombre d'enregistrements retournés

    ...?limit=<limite>
    ...?max-results=<limite>

    http://sps-int.serv.cdc.fr/clients/1.0?sortByAsc=LEPUSU&limit=30

Critères de recherche

Principe : ajout de paramètres à la requête

    ...?after=
    ...?before=
    ...?contains= 
    ...?like=
    ...?match= 

si besoin il est possible d'indiquer le champ sur lequel porte la recherche ainsi qu'une limite sur le nombre d'élements à retourner

    ...?field=<champs>    ou  ...?<nom du champ>=<valeur>
    ...?criteria=<champs>
    ...?limit=<limite>   ou   ...?max-results=<limite>

    http://sps-int.serv.cdc.fr/clients/1.0?contains=durand&field=LEPUSU&limit=30

Pagination

Principe : recours là encore à des paramètres

    limit | max-results | pageSize : nombre d'éléments retournés (le "pas" de pagination")
    start | start-index | page : indice du début de la recherche (ne numéro de page)*

    http://sps-int.serv.cdc.fr/clients/1.0?limit=10&start=3

Filtrage

On réalise du filtrage pour des raisons :

  • fonctionelles (recherche avancée, données nécessitant un niveau d'habilitation élevé)

  • ou technique à des fins d'optimisation et d'amélioration des performances (réduction du nombre de requêtes et taille du payload)

  • Dans tous les cas, l'API doit permettre au consommateur de préciser unitairement les données qu'il souhaite recueillir ou bien les groupes de données fonctionnellement cohérentes (fragment)

Filtrage par fragment

A la demande du consommateur, le payload de la réponse peut inclure des fragments de données complémentaires

  • Utilisation du mécanisme d'expansion

  • Consiste à fournir 1,n identifiants de fragment via le paramètre expand

      ...?expand=<identifiant fragment>[, <identifiant fragment>]
    
      //Extraction des contrats et des lignes carrière du client
      http://sps-int.serv.cdc.fr/clients/1.0/01AGZ201?expand=contrat,carriere

La liste des fragments peut être connue de façon :

  • statique (via la documentation de l'API)

  • dynamique, via un attribut ("expand") positionné au niveau de l'objet parent renvoyé

      {
          "expand": "contrat, carriere",
          "self": "http://sps-int.serv.cdc.fr/clients/1.0/01AGZ201",
          "contrat": {
              "contrats": [],
              "size": 3
          }
          "carriere": {
              "carriere": {},
          }
      }
  • Il est possible de préciser un sous-fragment d'un fragment via la notation pointée

      http://sps-int.serv.cdc.fr/clients/1.0/01AGZ201?expand=contrat.employeur

Filtrage des données renvoyées

  • La liste des champs à renvoyer est indiquer au niveau de la requête via un paramètre

      ...?fields=<champs1>[,<champ2>]

Codes retour

  • Codes retour HTTP standard (20x, 30x, 4xx, 5xx)
  • cf document "guide de mise en eouvre REST - v0.2.docx"
  • Un code retour peut être éventuellement accompagné d'un payload JSON précisant la nature de l'anomalie
  • Plusieurs payload d'anomalie ont déjà été normalisés (erreur validation champs, erruer contrôles de cohérence, ...)

Code retour HTTP 400 Bad Request

  • Erreur technique : erreur au niveau de la requête transmise par le client
    • Un header http requis n’est pas présent ou invalide
    • Un paramètre de la requête est manquant ou non supporté
  • Anomalie fonctionelle : la validation fonctionnelle (type, taille, pattern, ...etc) des paramètres fournies à échouée

      //structure JSON
      {
          "typeError":"FieldValidationFault",
          "message" : "Echec de la validation des données du formulaire",
          "fieldErrors":[
              {"fieldname":"nom","message":"La taille du champ nom doit être comprise entre 3 et 30 caractères","type":"Size"},
              {"fieldname":"adresse","message":"La taille du champ adresse doit être comprise entre 5 et 50 caractères","type":"Size"}
              ]
      }

Code retour HTTP 401 Unauthorized

  • L'accès au service REST est sécurisé par un jeton. Ce dernier est absent, mal formé, périmé, ...etc

      //structure JSON
      {
          "typeError":"UnauthorizedFault",
          "message" : "unauthorized",
      }

Code retour HTTP 403 Forbidden

  • L'utilisateur ne dispose pas des habilitations suffisantes pour accéder au service

      //structure JSON
      {
          "typeError":"AccessDeniedFault",
          "message" : "access denied",
      }

Code retour HTTP 404 Resource Not Found

  • Erreur technique : L'URI employée est inexistante ou mal formée

  • Anomalie fonctionelle : La recherche d'une ressource n'aboutie pas

      //structure JSON
      {
          "typeError": "ResourceNotFoundFault",
          "message" : "Le librairie recherché est inconnu !", 
          "cause" : "L'identifiant 33 n'existe pas"  //Champs facultatif
      }

Code retour HTTP 500 Internal Server Error

  • Erreur interne grave

      //structure JSON
      {
          "typeError": "GenericFault",
          "message" : "Missing header X-RequestID", 
          "stackTrace" : [
              {"methodName":"...","fileName":"...","lineNumber":33,"className":"...","nativeMethod":false},
              {"methodName":"...","fileName":"...","lineNumber":66,"className":"...","nativeMethod":false},
              ...
          ]
      }

Headers HTTP

  • Headers standards : accept(-*), host, user-agent, authorization, content-type, ...etc
  • Il est possible de compléter la requête en ajoutant ses propres headers
  • Par défaut, le socle AngularJS DEI ajoute le header X-RequestID

Gestion du cache

Deux grands cas d'usage :

  • Economie bande passante

    • minification, aggrégation des sources js, css, ...
    • Header ETAG / code retour 304 (Not Modified)
  • Economie temps de traitement / CPU

    • limite le nombre de connexion HTTP, accès ressources

Header ETAG

TODO

Sécurité

Authentification

  • HTTPS Basic/Digest Authentication
  • OAUTH2 / OpenId Connect / JWT

OAUTH2

Gestion des Habilitations

OWASP : identifiants opaques, XSS, CSRF, rejeu, vol de jetons...

Virtualisation service REST

Socle Publication de Services

Responsabilité

  • Sécurisation : présentation d'un jeton de sécurité (ACCESS TOKEN)

  • SLA : possbilité d'appliquer des quotas, plages horaires, abonnements, ...

  • Traçabilité

  • Gestion des erreurs

  • Transformation technique

Nommage des URI

CORS

Implémentation

Socle Technique retenu

  • Spring Core, Spring MVC - V4.x
  • Spring HATEOAS - V0.12.0.RELEASE
  • Spring Security v3.2.x
  • Jackson (JSON) - V2.3.x
  • HDIV + Esapi - V2.1.5

Points d'entrées service REST

  • Un controller Spring MVC par ressource
  • Utilisation de l'annotation @RestController
  • Le path-uri de la ressource doit être défini au niveau de la classe
    • @RequestMapping("path-uri")
    • permet, par défaut, de retourner une collection (paginée ou non) de ressources
  • Représentation par défaut : JSON Natural (application/json) en UTF-8
  • Le paylaod JSON (content) peut être enrichi de rubriques complémentaires :
    • links : liste des liens associés à la resource (cf §HATEOAS)
    • expand : liste des fragments possibles

Points d'entrées service REST (suite)

  • Autant de méthodes publiques que de verbes à exposer (Uniform Interface)
  • @RequestMapping (value="pattern URI", method="verbe HTTP")
    • headers et params pour compléter éventuellement le mapping
  • @ResponseStatus(code retour HTTP) pour préciser le code retour par défaut
    • sinon pris en charge au niveau du traitement de l'exception
  • @RequestParam et @RequestHeader pour spécificier le mapping de paramètres ou de headers attendus
    • Attention : leve une exception si élément est obligatoire mais non fourni
    • attribut required=false pour s'en prémunir sinon

Plan de nommage des packages

  • racine fr.icdc.dei.code projet aramis.presentation
    • .controller
    • .exception
    • .dto
    • .resource (HATEOAS)
    • .assembler (HATEOAS)

La gestion des exceptions

  • La gestion des exceptions est centralisée au niveau d'un controlleur spécialisé du Socle DEI

    • AdviceController.class
  • Utilisation de l'annonation @ControllerAdvice(annotations=RestController.class)

    • l'annotation @ControllerAdvice permet de mutualisé le code entre plusieurs controllers
    • l'attribut annotations=RestController.class permet de cibler une catégorie de controller

Créer ses propres exceptions

Accès à l'objet Authentication

HATEOAS

Hypertext As The Engine Of Application State

HTML is an hypermedia format, allowing link and form controls to let you flow through the application and thereby change the state of the application. This way of using hypermedia of the representation (such as HTML) to denote and manage the state of the application is called hypermedia http://jeremybarthe.com/slides/humantalks-hateoas/#/

Name Purpose

self Use this type to link to the preferred URI of the resource. alternate Use this type when providing a link to a URI for an alternative version of the same resource. edit Use this type to link to a URI that clients can use to edit the resource. related Use this type to link to a related resource. previous / next Use these types to link to the previous or next resource in an ordered series of resources. first and last Use these types to link to the first and last

Représentation des listes

Conception

  • nécessite un diagramme d'état avec ses transitions

Les objets manipulés pour chaque ressource

  • Plusieurs types d'objet sont manipulés dans le cadre d'un service Rest
    • [INPUT] ObjectForm (from AngularJS / POST)
    • Object couche métier
    • ObjectDTO <-> Object
    • [OUTPUT] ObjectResource (to AngularJS) + ObjectResourceAssembler <-- ObjectDTO

Prise en charge HATEOAS

  • Resource
  • Assembler
  • Utilisation de Pageable / PageableResourceAsssemble maj AbstractResourceSupport
    • @delegate assembler : pour créer les liens utilisation d'un resolver pour transformer les parameter en object avec @Valid

Pageable cf code + conf pour le pageableResolver

date : Yoda time + sérialiser ou simpleDateFormat sur safeJsonObjectMapper + @date sur les DTO

Déclaration d'une ressource Spring HATEOAS

  • Au niveau de Spring HATEOAS, une ressource est representée par un héritage de la classe ResourceSupport
  • Cette dernière facilite l'ajout de lien(s)

  • La création d'une ressource à partir de sa réprésentation métier/DTO s'opère par le biais d'un assembler

  • Spring HATEOAS offre la classe paramétrèe ResourceAssemblerSupport<E, R>
    • ou E désigne l'entité métier ou le DTO
    • et R la ressource Spring HATEOAS

Déclaration d'une ressource avec le Socle DEI

  • La ressource doit simplement hériter de la classe abstraite AbstractResourceSupport<T>
    • surcharge du constructeur
      • paramètre 1 : objet (DTO) associé à la ressource
      • paramètre 2 : liste de fragments (expand) pris en charge par la ressource à un instant t
    • surchage de la méthode abstraite getDefaultExpand()
      • liste des fragments (expand) pris en charge par défaut par la ressource
  • Cet héritage permet :
    • de gérer automatiquement la représenation des fragments associés à la ressource
    • de normaliser les noms des attributs content et expand

Exemple ressource Libraire de DESOTE

    public class LibraireResource extends AbstractResourceSupport<LibraireDTO> {

        //private final LibraireDTO libraire;
        private static final String[] LIBRAIRE_EXPANDS = new String[] {
                "commandes", "ouvrages" };

        public LibraireResource(LibraireDTO libraire, String...expands) {
            super(libraire, expands);
        }


        @Override
        protected Iterable<String> getDefaultExpand() {
            return Arrays.asList(LIBRAIRE_EXPANDS);
        }

    }

Exemple de représentation JSON générée

    {
        "content":{"id":6,"nom":"ATTICA la librairie des langues","adresse":"11 Rue Boussingault","codePostal":"75013","ville":"Paris"},
        "expand":["ouvrages"],
        "links":[
            {"rel":"self","href":"http://localhost:10080/desote-web-springmvc-spi/web/libraireHATEOAS/6"},
            {"rel":"orders","href":"http://localhost:10080/desote-web-springmvc-spi/web/libraireHATEOAS/6/orders"}]
    }

Création de la ressource

  • Comme pour Spring HATEOAS, la création de la ressource est prise en charge par l'assembler
  • L'utilisation d'un constructeur spécialisé necessite de surcharger la méthode instantiateResource
  • L'ajout de liens spécifiques s'opère au niveau de la méthode toResource
0