Aller au contenu principal

Enrichissement d’une ressource

Permet au fournisseur d’API de modifier et de compléter le comportement attendu sur une ressource en particulier.

Déclaration d’un endpoint de production et/ou de sandbox

Principe de fonctionnement

L’API déclare dans sa configuration un endpoint et/ou un sandboxEndpoint pour une ressource. Dès la déclaration réalisée, la Gateway applique les redirections.

Exemple illustré avec l’API Digiposte v3, qui a :

En déclarant un endpoint et un sandboxEndpoint sur cette route, le propriétaire de l’API modifie les API requêtées :

API requêtée initialement (sans déclaration d’un endpoint et d’un sandboxEndpoint sur la route)API requêtée après déclaration d’un endpoint et d’un sandboxEndpoint sur la route
Endpointhttps://api.digiposte.fr/api/v3/partner/:partner_id/memberships/:partner_user_id/documents/certifiedhttps://api.digiposte.fr/api/v4/partner/:partner_id/memberships/:partner_user_id/documents/certified
SandboxEndpointhttps://api.interop.digiposte.io/api/v3/partner/:partner_id/memberships/:partner_user_id/documents/certifiedhttps://api.interop.digiposte.io/api/v4/partner/:partner_id/memberships/:partner_user_id/documents/certified

Principe de mise en œuvre

- type: api
value:
name: My Api
urlContext: myapi
version: '1'
...
- type: resource
value:
name: My Resource
method: post
route: /official/route/dispayed
endpoint: /real/endpoint/joigned
sandboxEndpoint: https://other.api.fr/real/sandboxendpoint/joigned
api:
urlContext: myapi
version: "1"

Ajout d’un Plugin

Permet au fournisseur d’API d’ajouter un traitement à une requête avant de l’envoyer vers l’API cible ou avant de faire suivre la réponse reçue de l’API cible vers le client.

Principe de fonctionnement des plugins

Il y a deux types de plugins :

  • Les plugins lié à l'API : Ils permettent d'effectuer des traitements avant l'envoi ou après envoi sur toutes les requêtes de l'API. Ils sont déclarés dans la configuration de l'API via le champ extra.
  • Les plugins lié aux ressources: Ils permettent d'effectuer des traitements avant l'envoi ou après envoi sur une ressource de l'API. Ils sont déclarés dans la configuration de la ressource via le champ extra.

Le flow de chaque requête-réponse entre Okapi et l'API distante est le suivant :

Request Flow

Il est à noter que

Pour chaque requête / réponse d'une ressource, Okapi exécute la liste des plugins de l'api avant d'exécuter la liste des plugins de la ressource ciblée.

L'ensemble des plugins sera appliqué dès l'import du fichier de configuration Yaml ou après l'intervention du support Okapi.

La configuration finale prendra cette forme :

- type: api
value:
name: My Api
urlContext: myapi
version: '1'
...
extra :
plugins :
- before : |
my plugin code
- after : |
my plugin code
- type: resource
value:
name: My Resource
method: get
route: /route
extra :
plugins :
- before : |
my plugin javascript code
- after : |
my plugin javascript code
api:
urlContext: myapi
version: "1"

Principe de mise en œuvre des plugins

Un plugin est un code Javascript, qui peut être soit de type before, soit de type after.

  • Dans le cas du before, nous pouvons modifier la variable
    • req qui correspond aux infos de la requête HTTP.
  • Dans le cas du after, nous avons accès a deux variables :
    • req qui correspond aux infos de la requête HTTP.
    • res qui correspond aux infos de la réponse de l'API.
Il est à noter que

l'ensemble des variables sont présentes dans le context api.

  plugins:
# On déclare un plugin de type before
- before: |
api.req.headers['x-my-header'] = 'my value'
# On déclare un plugin de type after
- after: |
if (api.req.headers['x-my-header'] === 'my value') {
api.res.headers['x-my-header'] = 'my value'
}
Attention

Le code Javascript n'est pas une fonction, il est exécuté directement.

Le plugin peut aussi utiliser la bibliothèque Lodash via la variable _.

Attention

Pour une mise en œuvre avancée du code Javascript, il est vivement recommandé de demander l'assistance de l'équipe Support Okapi.

Exemples de mise en œuvre des plugins

Quelques exemples de mise en œuvre pour vous mettre dans le bon chemin:

  1. Un plugin before

    // Nous bénéficions de la bibliothèque Lodash pour ajouter des headers personnalisés à la liste
    // des headers déjà envoyée avec la requête initiale
    _.extend(api.req.headers, {
    'x-example-header': 'example header value'
    })

    // Aussi, on peut ajouter des 'query string' personnalisés
    _.extend(api.req.qs, {
    example: 'example query string'
    })
  2. Un plugin after

    // Un simple traitement qui fait un test sur le statut
    // retourné par la ressource
    const okValue = api.res.statusCode === 200

    // On peut modifier ou ajouter un header personnalisé
    api.res.headers['x-ok'] = okValue;

    // On peut aussi faire retourner le résultat immédiatement
    // avec un body modifié
    res.json({
    ...api.body,
    ok: okValue
    })

La configuration finale avec les deux plugins sera comme suit :

...
- type: resource
value:
name: My Resource
method: get
route: /route
extra :
plugins :
- before: |
_.extend(api.req.headers, {
'x-example-header': 'example header value'
})
_.extend(api.req.qs, {
example: 'example query string'
})
- after: |
const okValue = api.res.statusCode === 200
api.res.headers['x-ok'] = okValue;
res.json({
...api.body,
ok: okValue
})
api:
urlContext: myapi
version: "1"

Cas d'usages

Filtrage IP
extra:
plugins:
- before: |
const allowedIps = ['127.0.0.1'] # Liste d'IPs
const emails = ['consommateur@email.com'] # Compte consommateur sur lequel appliquer le filtrage
const isSandbox = res.locals.appKey.sandbox # Pour savoir si c'est une requête sandbox
const email = res.locals.user.email # Récupération de l'email consommateur

if (!isSandbox && (emails.includes(email) && !allowedIps.includes(req.ip)))
return res.status(403).send('Forbidden')
Ajout d'un header suivant l'environnement
extra:
plugins:
- before: >
const isSandbox = res.locals.appKey.sandbox;
if (isSandbox) {
api.req.headers['authorization'] = 'Bearer [SANDBOX_ACCESS_TOKEN]';
} else {
api.req.headers['authorization'] = 'Bearer [PROD_ACCESS_TOKEN]';
}

Restriction d’accès par IP ou plage d’IP

Pour limiter l’accès à l’API à partir d’une ou plusieurs adresses IP spécifiques, ou d’une plage d’IP, vous pouvez implémenter le code suivant :

extra:
plugins:
- before: |
const blackListIps = ['127.0.*.*']; // A remplacer par vos valeurs

if (blackListIps.some(pattern => new RegExp('^' + pattern.replace(/\*/g, '\\d{1,3}') + '$').test(req.ip)))
return res.status(403).send('Forbidden');