OSB : appel d’un WS REST ne respectant pas les contraintes WADL

Présentation du problème

REST et caractères réservés dans l’URL

L’architecture REST permet d’interroger des WS (WebService) en utilisant simplement des requêtes HTTP.
On peut donc les utiliser directement depuis un navigateur Web en saisissant l’URL.
Par exemple :
exemple d'appel REST depuis un navigateur
Il est possible, en théorie, d’utiliser des caractères réservés (#, ‘, (), …) dans cette URL.
Une liste des caractères en question est donnée dans les références en fin de l’article.
Par exemple on aurait pu écrire cette URL : http://10.7.1.11:5000/test/acme/client?filter[lastName]=doe&filter[firstName]=john

WADL et contraintes sur les caractères

OSB gère les WS REST au moyen de fichiers WADL.
Ces fichiers donnent une structure aux services en définissant précisément les paramètres (nom et type par exemple), un peu comme les WSDL pour les services SOAP.
En particulier, les noms de paramètres passés à la fin d’une URL doivent respecter le format NMTOKEN.
Pour faire simple, seuls les lettres, chiffres et tirets sont autorisés. De ce fait, tout autre caractère spécial est interdit : [], !, …
Les contraintes du format WADL ainsi que les détails du format NMTOKEN sont donnés dans les références en fin de l’article.
Ainsi notre URL précédente « http://10.7.1.11:5000/test/acme/client?filter[lastName]=doe&filter[firstName]=john » n’est plus valide. On aurait par contre pu avoir : http://10.7.1.11:5000/test/acme/client?filter_lastName=doe&filter_firstName=john

Présentation du problème dans OSB (Oracle Service Bus)

Avec des langages permissifs, il est possible de publier des WS REST ne respectant pas les contraintes WADL.
Un exemple en Python est donné dans les références en fin de l’article. Cet exemple se contente de parser toutes les informations de la requête et de les renvoyer en JSON.
Ainsi, un peut passer cet appel depuis un navigateur :
exemple WS REST ne respectant pas les contraintes WADL
Par contre, si on essaye depuis OSB, le connecteur REST, en respect des conventions WADL, nous empêche d’utiliser les [] :
exemple d'erreur dans OSB en utilisant des [] dans le nom d'un paramètre
On peut essayer de contourner en échappant les caractères spéciaux, mais cela ne donne rien.
De toute façon, les caractères d’échappement ne respectant pas le format NMTOKEN, cette piste sera un échec.
exemple de tentative d'échappement de caractère spécial
Il est donc impossible d’appeler ce WS REST depuis OSB en utilisant le connecteur dédié.

Contournement via connecteur HTTP

La solution à adopter consiste alors à utiliser un connecteur HTTP.
L’URL sera construite dynamiquement en concaténant les éléments et en utilisant l’échappement « % » sur les caractères réservés.
Un exemple de projet OSB et la liste des échappements sont donnés dans les références en fin de l’article.
présentation générale du projet d'exemple

Schéma d’entrée

On commence par écrire une XSD qui permettra de passer nos paramètres, quelques soient les caractères. Il y aura une URI et des couples clé/valeurs, tous en chaîne de caractères.
schéma XSD d'entrée
Ainsi, l’URL de test « http://127.0.0.1:5000/test/dummiest?filter[lastName]=doe&filter[firstName]=john » sera représentée en XML :
fichier XML d'exemple

Business

Il s’agit d’un simple connecteur HTTP de type REST avec une URL bidon.
business

Proxy et pipeline

A partir de là, on créé le couple proxy/pipeline (relié au business).
Pour le proxy, un simple connecteur HTTP suffit. Il prend en entrée notre XSD et ressort du texte brut.
proxy
Pour le pipeline , il y a 2 éléments :

  1. « Assign » dans le bloc « Request » : construire dynamiquement l’URL
  2. « Routing Options » : appeler l’URL dynamique

pipeline

Création de l’URL dynamique

Dans l’élément « Assign », on crée la variable URL avec un transformation XQuery.
Cette transformation utilise 2 fonctions natives importantes :

  1. encode-for-uri : échapper les caractères spéciaux
  2. concat : concaténer l’URI puis les couples de paramètres nom/valeur

Ainsi, « http://…?filter[lastName]=doe&filter[firstName]=john » deviendra « http://…?filter%5BlastName%5D=doe&filter%5BfirstName%5D=john ».
transformation XQuery de création d'URL dynamique
L’assignation dans la variable URL se fait alors avec un appel à la transformation.
création de la variable URL via un appel à la transformation

Utilisation de l’URL dynamique

Dans l’élément « Routing Options », on indique l’URL dynamique (créée à l’étape précédente) et le verbe (ici GET, mais n’importe quel autre serait possible).
paramétrage de l'élément

Test

On déploie le projet et depuis la console OSB on teste le proxy.
On remplit notre requête d’exemple :
création du test avec la requête d'exemple
Puis on exécute, ce qui donne le résultat :
résultat
On voit alors que les caractères spéciaux ont bien été passés au service, qui les a correctement décodés et utilisés dans la réponse.

Références

Uniform Resource Identifier (URI): Generic Syntax – Reserved Characters : Spécification du format URI, en particulier les caractères réservés
Web Application Description Language – Parameter Definition : spécification du format WADL, en particulier les paramètres
xsd:NMTOKEN : description du type NMTOKEN
: dummyPythonRESTserverProjet Python implémentant un WS REST sans WADL
SBTestRESTnoWADL : Projet Oracle d’appel de WS REST sans WADL
Percent-encoding : Les table de %-encodage
Test du connecteur REST/JSON : une présentation du connecteur REST sous OSB

Merci à Ayoub Kermani et Julien Leleu pour leur aide et commentaires sur Yammer.