Aller directement à la fin des métadonnées
Aller au début des métadonnées

The home url for REST API is http://yourforumurl/api/

Example : http://forum.doctissimo.fr/api/

 


1 - Les requêtes


 

L'API accepte de recevoir plusieurs type de requêtes, définies par la méthode (REQUEST_METHOD, HTTP_X_HTTP_METHOD_OVERRIDE) utilisée lors de l'appel.

Nous pourrons donc avoir:

  • GET 
    • Si nous détectons un resource_identifier dans le masque de l'URL, alors la fonction get() du service concerné sera appelée et fournira les informations de l'objet demandé*
    • Si l'argument q est fourni dans la query_string (?q=...), alors c'est la fonction search() qui sera utilisée et renverra une liste de liens de l'API pour chaque object retrouvé (la liste peut-être vide en cas de recherche infructueuse).
    • Sinon, c'est la fonction list() qui sera appelée et renverra alors une liste d'objets*

A noter que list() propose un système de pagination et accepte les arguments page et results_per_page dans la query_string.

  • POST
    • Si nous ne détectons pas de resource_identifier dans le masque de l'URL, alors la fonction create() du service concerné sera appelée et fournira les informations de l'objet ainsi créé*

NOTA: tout ce qui est envoyé via la méthode POST doit impérativement contenir le hash_check du user correspondant, sinon, la requête est refusée/ignorée.

  • PUT
    • Si nous détectons un resource_identifier dans le masque de l'URL, alors la fonction update() du service concerné sera appelée et fournira les informations de l'objet ainsi mis à jour*
  • DELETE 
    • Si nous détectons un resource_identifier dans le masque de l'URL, alors la fonction delete() du service concerné sera appelée et fournira les informations de l'objet comme il était avant sa suppression*

 

* Une erreur peut néanmoins également être retournée: cf. 2- Les réponses.

 


 2 - Les réponses


L'API doit toujours renvoyer une réponse en JSON.

L'object encodé sera du type:
DOC_rest_response {
    error: null|bool
    error_code: null|int 
    error_description: null|string
    resource: {} 

}

En cas de succès, errorerror_code et error_description vaudront null, et resource sera un objet contenant les infos retournées par l'API.

En cas d'erreur par contre, c'est le contraire: resource sera null alors que les autres attributs seront renseignés. error vaudra alors true.
Erreurs possibles:

  • "Not found" (code: 404)
  • "Bad Request" (codes: 400*, 403)
  • "Forbidden" (codes: 403*, 401)
  • "Not Implemented" (code: 501)

* => Valeur par défaut. Il faudra voir si les valeurs rajoutées sont vraiment utilisées ou si l'on peut tout standardiser...

 


3 - Authentification


L'authentification envers l'API REST se fait via l'URL http://<url_club>/api/auth.php

Les méthodes acceptées sont GET, POST et PUT.

Les paramètres attendus sont:

  • le pseudo: GET/POST['pseudo']
  • le mot passe encrypté: GET/POST['password']

NOTA: tout ce qui est envoyé via la méthode POST doit impérativement contenir le hash_check du user correspondant, sinon, la requête est refusée/ignorée.

 


4 - Facebook connect


Si le visiteur est déjà connecté à un compte Facebook, l'API REST propose également d'authentifier la personne au travers de son ID FaceBook via l'URL http://<url_club>/api/ext_auth.php

Les méthodes acceptées sont GET et POST

Les paramètres attendus sont:

  • le client: GET['client'] = 'facebook'
  • les infos: POST['content'] (JSON encoded): array('pseudo', 'email', 'uid', 'sex', 'birthday', 'first_name', 'last_name', 'country', 'city', 'postcode', 'force_join', 'facebook_name', 'facebook_token');

NOTA: tout ce qui est envoyé via la méthode POST doit impérativement contenir le hash_check du user correspondant, sinon, la requête est refusée/ignorée.

 


5 - Google connect


Si le visiteur est déjà connecté à un compte Google+, l'API REST propose également d'authentifier la personne au travers de son ID Google via l'URL http://<url_club>/api/ext_auth.php

Les méthodes acceptées sont GET et POST

Les paramètres attendus sont:

  • le client: GET['client'] = 'google'
  • les infos: POST['content'] (JSON encoded): array('pseudo', 'email', 'uid', 'sex', 'birthday', 'first_name', 'last_name', 'country', 'city', 'postcode', 'force_join');

NOTA: tout ce qui est envoyé via la méthode POST doit impérativement contenir le hash_check du user correspondant, sinon, la requête est refusée/ignorée.

 


6 - Versionning


 

Afin de permettre l'évolution de notre API, nous allons également mettre en place le support d'un versionning, via un paramètre _GET v=<int>.
Pour toutes les applications utilisant déjà notre API, rien ne changera. Les URLs ne fournissant pas ce nouveau paramètre seront considérées comme souhaitant accéder à la version d'origine de notre API. C'est comme si elles appelait une url?v=1.

Pour les futures évolutions de notre API, nous fournirons de nouvelles versions à chaque fois qu'un retour sera modifié. L'ajout de nouveaux attributs pourra toujours se faire sur la version d'origine vu que cela n'altérera pas son fonctionnement, par contre, la modification ou suppression des attributs existants se fera exclusivement sur une nouvelle version. 

NOTA: si une version demandée n'existe pas, une erreur "500 - System Error" sera retournée.

 

 


6 - Exemples

La connexion au forum avec l'API REST se fait via un cookie (CFSESSID). Donc si les appels sont fait directement par le client, en ajax par exemple, il n'y a rien de particulier à faire.

Par contre, si on souhaite passer par un proxy afin de faire un traitement supplémentaire par exemple, il y a certaines opérations à faire pour que le comportement soit correct. Voici des exemples de code avec CURL en PHP :

 

Dans cet exemple, nous voyons toutes les étapes pour un processus sans accro afin de faire office de proxy en transférant les données POST et les cookies dans les 2 sens.

Appel avec curl
/**
 * Escape chars recursively in an array.
 *
 * @param  mixed &$myArr
 */
function proxy_recursiveEscapeChar(&$myArr) {
   if (!is_array($myArr)) {
      // case string:
      if (substr($myArr, 0, 1) == '@') {
         // Avoid having a '@' in first pos (interpreted by cUrl as uploaded filepath).
         $myArr = ' '.$myArr;    // => DOC_utils::post(), ::get(), ... automatically trim() value by default.
      }
      if (get_magic_quotes_gpc()) {
         $myArr = stripslashes($myArr);
      }
   } else {
      //case array:
      foreach ($myArr AS $key => $element) {
         if (is_array($element)) {
            proxy_recursiveEscapeChar($element);
            $myArr[$key] = $element;
         } else {
            if (substr($element, 0, 1) == '@') {
               // Avoid having a '@' in first pos (interpreted by cUrl as uploaded filepath).
               $myArr[$key] = ' '.$element;    // => DOC_utils::post(), ::get(), ... automatically trim() value by default.
            }
            if (get_magic_quotes_gpc()) {
               $myArr[$key] = stripslashes($element);
            }
         }
      }
   }
}

/**
 * _POSTed arrays need to be converted into string for proxy-forward.
 * If not done, php is trying to do it, but multi-dimensional arrays are then not
 * well supported.
 *
 * @param  $formdata
 * @return string
 */
function proxy_buildPostQuery($formdata) {
   $serialized = array();
   if (is_array($formdata)) {
      foreach ($formdata as $k => $v) {
         if (is_array($v) || (is_object($v) && !is_a($v, 'CurlFile'))) {
            $formdata[$k] = serialize($v);
            $serialized[] = $k;
         }
      }
   }

   if (count($serialized) > 0) {
      $formdata[SERIALIZED_POST] = implode(',', $serialized);
   }

   return $formdata;
}

// Ici l'URL qu'on souhaite appeler
$url = 'http://club.dev.trunk.devs.mesdiscussions.net/api/auth.php';

$session = curl_init($url);
curl_setopt($session, CURLOPT_HEADER, true);
curl_setopt($session, CURLOPT_RETURNTRANSFER, true);

// Transmettre les informations indiquant qu'on passe par un proxy
// /!\ Indispensable pour pouvoir sauvegarder la bonne IP dans les logs utilisateurs. Sinon, ça sera l'IP du proxy qui sera enregistré comme ayant fait l'action, ce qui pourra poser des problèmes en cas de réquisition judiciaire.
if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
   $x_forwarded_for = $_SERVER['HTTP_X_FORWARDED_FOR'];
} elseif (!empty($_SERVER['HTTP_CLIENT_IP'])) {
   $x_forwarded_for = $_SERVER['HTTP_CLIENT_IP'];
} elseif (!empty($_SERVER['REMOTE_ADDR'])) {
   $x_forwarded_for = $_SERVER['REMOTE_ADDR'];
} else {
   $x_forwarded_for = '';
}
if (isset($_SERVER["SERVER_ADDR"])) {
   curl_setopt($session, CURLOPT_HTTPHEADER, array(
      "Via: ".$_SERVER["SERVER_ADDR"],
      "X-Forwarded-For: ".$x_forwarded_for,
      "X-Forwarded-Referer: ".(isset($_SERVER["HTTP_REFERER"]) ? $_SERVER["HTTP_REFERER"] : ''),
      "X-Forwarded-Host: ".(isset($_SERVER["HTTP_HOST"]) ? $_SERVER["HTTP_HOST"] : ''),
      "X-Forwarded-Server: ".(isset($_SERVER["SERVER_NAME"]) ? $_SERVER["SERVER_NAME"] : '')));
}

// On transfère les cookies de l'utilisateur vers l'API
// /!\ Indispensable pour savoir quel utilisateur est connecté, sinon on sera considéré comme déconnecté lors de l'appel et on ne pourra jamais accéder à des données privée ou en modifier
if (!empty($_COOKIE)) {
   $cookie_array = array();
   foreach ($_COOKIE as $k => $v) {
      $cookie_array[] = $k.'='.$v;
   }
   curl_setopt($session, CURLOPT_COOKIE, implode('; ', $cookie_array));
}

// Envoi des données POST
proxy_recursiveEscapeChar($_POST);
$postvars = $_POST;
if ($postvars) {
   curl_setopt($session, CURLOPT_POST, true);
   curl_setopt($session, CURLOPT_POSTFIELDS, proxy_buildPostQuery($postvars));
}

// Appel à l'API
$response = curl_exec($session);

// Récupération des headers et du contenu du retour
$headers_size = curl_getinfo($session, CURLINFO_HEADER_SIZE);
$headers      = substr($response, 0, $headers_size);
$body         = substr($response, $headers_size);

curl_close($session);

// Renvoyer les cookies créés par l'API au client
// /!\ Nécessaire lorsqu'on tente se connecter l'utilisateur pour qu'il conserve sa session
if (preg_match_all('#Set-Cookie: (.+)=(.*); expires=(.+); path=(.*); domain=([^\\s]*)\\s*#', $headers, $matches, PREG_SET_ORDER)) {
   foreach ($matches as $match) {
      setcookie($match[1], $match[2], strtotime($match[3]), $match[4], $match[5]);
   }
}

// Renvoyer le contenu au client
echo $body;

 

Pour faire un PUT, il suffirait de mettre la ligne suivante :

Appel en PUT
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "PUT");

 

 

 

  • Aucune étiquette