<?php
// Fonction permettant d'invoquer un service distant.
function sendRequest($url, $auth, $serviceName, $arguments = array())
{
   // On accepte des URL en http ou https
   assert('preg_match(\'`^https?://`i\', $url)');
   // La clef d'authentification doit être une chaîne
   assert('is_string($auth)');
   // Le nom du service ne doit pas contenir autre chose que des lettres,
   // chiffres, ":" et "_"
   assert('preg_match("`^[\w:]+$`", $serviceName)');
   // Les arguments doivent être placés dans un tableau.
   assert('is_array($arguments)');
   
   // La donnée linéarisée est encodée
   $data = 'args=' . urlencode(serialize($arguments));

   // On crée un tableau contenant les entêtes et données à envoyer au serveur
   // distant.
   $opts = array (
      // C'est pour de la communication via HTTP
      'http'=>array (
         // La méthode sera "POST"
         'method' => 'POST',
         // L'entête HTTP contient :
         'header' =>
                     // La clef d'authentification
                     "x-auth: $auth\r\n" .
                     // Le nom de la fonction à appeler
                     "x-service-name: $serviceName\r\n" .
                     // Les données sont urlencodées
                     "Content-type: application/x-www-form-urlencoded\r\n" .
                     // Ne pas oublier de préciser la taille des données
                     "Content-Length: " . strlen($data) . "\r\n",
         // Les données à envoyer
         'content' => $data
       )
   );

   // On crée un context pour le passer en paramètre de file_get_contents
   $context = stream_context_create($opts);

   // On appelle la page distante en masquant les erreurs de chargement
   $content = @file_get_contents($url, false, $context);

   if (false === $content) {
      // Si le contenu retourné contient "false" cela indique un problème de
      // connexion au serveur
      throw new Exception('Problème d\'accès au serveur distant');
   } else {
      // On délinéarise le contenu retourné
      $result = unserialize($content);
      if (false === $result) {
         // Problème de délinéarisation du résultat (ou résultat contenant
         // "false"). Cela arrive quand le script distant affiche une erreur.
         throw new Exception('Problème de délinéarisation du résultat');
      } elseif (! is_array($result) or
            !(
               array_key_exists('exception', $result) or
               array_key_exists('return', $result)
               )) {
         // Si le contenu n'est pas un tableau, ou qu'il n'y a ni exception ni
         // résultat, cela indique que le résultat linéarisé n'est pas
         // conforme aux attentes (tableau contenant "exception" et "return")
         throw new Exception('Résultat retourné non conforme');
      }
   }

   if (! empty($result['exception'])) {
      // Il y a une exception, alors on la lève
      throw new Exception($result['exception']);
   } else {
      // On retourne le résultat s'il n'y a pas d'exception.
      return $result['return'];
   }
}

?>