Overview

Packages

  • Framework
  • None
  • PHP
  • Utilitaire

Classes

  • Bdd
  • Cache
  • CacheSimple
  • Chronometre
  • Cli
  • Config
  • Controleur
  • Debug
  • Framework
  • GestionnaireException
  • I18n
  • Log
  • Registre
  • RestClient
  • RestServeur
  • RestService
  • Script
  • SquelettePhp
  • Url
  • Overview
  • Package
  • Class
  • Tree
  • Deprecated
  • Todo
  1: <?php
  2: // declare(encoding='UTF-8');
  3: /**
  4: * Classe client permettant d'interroger des services web REST.
  5: *
  6: * @category php 5.2
  7: * @package  Framework
  8: * @author       Jean-Pascal MILCENT <jpm@tela-botanica.org>
  9: * @copyright    Copyright (c) 2010, Tela Botanica (accueil@tela-botanica.org)
 10: * @license      http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
 11: * @license      http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
 12: * @version      $Id: RestClient.php 439 2013-10-14 15:48:41Z raphael $
 13: */
 14: class RestClient {
 15:     const HTTP_URL_REQUETE_SEPARATEUR = '&';
 16:     const HTTP_URL_REQUETE_CLE_VALEUR_SEPARATEUR = '=';
 17:     private $http_methodes = array('GET', 'POST', 'PUT', 'DELETE', 'HEAD', 'OPTIONS', 'CONNECT', 'TRACE');
 18:     protected $parametres = null;
 19:     private $url = null;
 20:     private $reponse_entetes = null;
 21:     
 22:     //+----------------------------------------------------------------------------------------------------------------+
 23:     // ACCESSEURS
 24:     
 25:     public function getReponseEntetes() {
 26:         return $this->reponse_entetes;
 27:     }
 28:     
 29:     public function getParametre($cle) {
 30:         $valeur = (isset($this->parametres[$cle])) ? $this->parametres[$cle] : null;
 31:         return $valeur;
 32:     }
 33:     
 34:     public function ajouterParametre($cle, $valeur) {
 35:         $this->parametres[$cle] = $valeur;
 36:     }
 37:     
 38:     public function supprimerParametre($cle) {
 39:         unset($this->parametres[$cle]);
 40:     }
 41:     
 42:     public function nettoyerParametres() {
 43:         $this->parametres = null;
 44:     }
 45:     
 46:     //+----------------------------------------------------------------------------------------------------------------+
 47:     // MÉTHODES
 48:     
 49:     public function consulter($url) {
 50:         $retour = $this->envoyerRequete($url, 'GET');
 51:         return $retour;
 52:     }
 53:     
 54:     public function ajouter($url, Array $donnees) {
 55:         $retour = $this->envoyerRequete($url, 'PUT', $donnees);
 56:         return $retour;
 57:     }
 58:     
 59:     public function modifier($url, Array $donnees) {
 60:         $retour = $this->envoyerRequete($url, 'POST', $donnees);
 61:         return $retour;
 62:     }
 63:     
 64:     public function supprimer($url) {
 65:         $retour = $this->envoyerRequete($url, 'DELETE');
 66:         return $retour;
 67:     }
 68:     
 69:     public function envoyerCurlRequete($url, $mode, Array $donnees = array()) {
 70:         $this->url = $url;
 71:         $contenu = false;
 72:         if (! in_array($mode, $this->http_methodes)) {
 73:             $e = "Le mode de requête '$mode' n'est pas accepté!";
 74:             trigger_error($e, E_USER_WARNING);
 75:         } else {
 76:             if ($mode == 'GET') {
 77:                 $this->traiterUrlParametres();
 78:             }
 79: 
 80:             $ch = curl_init($this->url);
 81:             curl_setopt($ch, CURLOPT_HEADER, TRUE);
 82:             curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
 83:             curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
 84: 
 85:             if($mode == 'POST') curl_setopt($ch, CURLOPT_POST, TRUE);
 86:             elseif($mode == 'PUT') curl_setopt($ch, CURLOPT_PUT, TRUE);
 87:             elseif($mode == 'DELETE') curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "DELETE");
 88: 
 89:             if($donnees) curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($donnees, null, self::HTTP_URL_REQUETE_SEPARATEUR));
 90: 
 91:             /* if(isset($_COOKIES["XDEBUG_PROFILE"])) curl_setopt($ch, CURLOPT_COOKIE, "XDEBUG_PROFILE");
 92:             $caller = self::getCaller(debug_backtrace());
 93:             @curl_setopt($ch, CURLOPT_REFERER, sprintf("%s[%s:%d:%s]", $_SERVER['REQUEST_URI'], $caller['file'], $caller['line'], $caller['function'])); // $_SERVER['QUERY_STRING']; // debug */
 94:             $flux = curl_exec($ch);
 95:             curl_close($ch);
 96: 
 97:             if (!$flux) {
 98:                 $this->reponse_entetes = $http_response_header;
 99:                 trigger_error(sprintf("fail: %s \"%s\" (%s)", strtoupper($mode), $this->url, http_build_query($donnees, null, self::HTTP_URL_REQUETE_SEPARATEUR)),
100:                               E_USER_WARNING);
101:             } else {
102:                 // attention, CURLOPT_FOLLOWLOCATION amène le stream à contenir plusieurs section d'header HTTP successives
103:                 $t = explode("\r\n\r\n", $flux);
104:                 $contenu = array_splice($t, -1);
105:                 $dernier_entete = array_splice($t, -1);
106:                 $contenu = $contenu[0];
107:                 $dernier_entete = $dernier_entete[0];
108: 
109:                 // XXX: mimic stream_get_meta_data() (ce qui n'est pas très propre, le code appelant ferait mieux de se mettre à jour)
110:                 $this->reponse_entetes = array('wrapper_data' => explode("\r\n", $dernier_entete));
111:             }
112:             $this->traiterEntete();
113:         }
114:         $this->reinitialiser();
115:         return $contenu;
116:     }
117: 
118:     static function getCaller($trace) {
119:         foreach($trace as $v) if(strpos($v['file'], '/modules/') !== false) return $v;
120:         return NULL;
121:     }
122: 
123:     public function envoyerRequete($url, $mode, Array $donnees = array()) {
124:         // error_log("framework/envoyerRequete: $mode $url");
125: 
126:         // nous n'activons le wrapper que pour GET pour l'instant
127:         // car l'utilisation de curl pour les autres modes pourrait
128:         // vraisemblablement induire des comportements différents. (test-suite needed)
129:         if(FALSE && function_exists('curl_init') && $mode == 'GET') {
130:             return $this->envoyerCurlRequete($url, $mode, $donnees);
131:         }
132: 
133:         $this->url = $url;
134:         $contenu = false;
135:         if (! in_array($mode, $this->http_methodes)) {
136:             $e = "Le mode de requête '$mode' n'est pas accepté!";
137:             trigger_error($e, E_USER_WARNING);
138:         } else {
139:             if ($mode == 'GET') {
140:                 $this->traiterUrlParametres();
141:             }
142:             $contexte = stream_context_create(array(
143:                 'http' => array(
144:                     'method' => $mode,
145:                     'header' => "Content-type: application/x-www-form-urlencoded\r\n",
146:                     'content' => http_build_query($donnees, null, self::HTTP_URL_REQUETE_SEPARATEUR))));
147:             $flux = @fopen($this->url, 'r', false, $contexte);
148:             if (!$flux) {
149:                 $this->reponse_entetes = $http_response_header;
150:                 trigger_error(sprintf("fail: %s \"%s\" (%s)", strtoupper($mode), $this->url, http_build_query($donnees, null, self::HTTP_URL_REQUETE_SEPARATEUR)),
151:                               E_USER_WARNING);
152: 
153:             } else {
154:                 // Informations sur les en-têtes et métadonnées du flux
155:                 $this->reponse_entetes = stream_get_meta_data($flux);
156:                 
157:                 // Contenu actuel de $url
158:                 $contenu = stream_get_contents($flux);
159:                 
160:                 fclose($flux);
161:             }
162:             $this->traiterEntete();
163:         }
164:         $this->reinitialiser();
165:         return $contenu;
166:     }
167:     
168:     private function traiterUrlParametres() {
169:         $parametres = array();
170:         if (count($this->parametres) > 0) {
171:             foreach ($this->parametres as $cle => $valeur) {
172:                 $cle = rawurlencode($cle);
173:                 $valeur = rawurlencode($valeur);
174:                 $parametres[] = $cle.self::HTTP_URL_REQUETE_CLE_VALEUR_SEPARATEUR.$valeur;
175:             }
176:             $url_parametres = implode(self::HTTP_URL_REQUETE_SEPARATEUR, $parametres);
177:             $this->url = $this->url.'?'.$url_parametres;
178:         }
179:     }
180:     
181:     private function traiterEntete() {
182:         $infos = $this->analyserEntete();
183:         $this->traiterEnteteDebogage($infos);
184:     }
185:     
186:     private function analyserEntete() {
187:         $entetes = $this->reponse_entetes; 
188:         $infos = array('date' => null, 'uri' => $this->url, 'debogages' => null);
189:         
190:         if (isset($entetes['wrapper_data'])) {
191:             $entetes = $entetes['wrapper_data'];
192:         }
193:         foreach ($entetes as $entete) {
194:             if (preg_match('/^X_REST_DEBOGAGE_MESSAGES: (.+)$/', $entete, $match)) {
195:                 $infos['debogages'] = json_decode($match[1]);
196:             }
197:             if (preg_match('/^Date: .+ ([012][0-9]:[012345][0-9]:[012345][0-9]) .*$/', $entete, $match)) {
198:                 $infos['date'] = $match[1];
199:             }
200:         }
201:         return $infos;
202:     }
203:     
204:     private function traiterEnteteDebogage($entetes_analyses) {
205:         if (isset($entetes['debogages'])) {
206:             $date = $entetes['date'];
207:             $uri = $entetes['uri'];
208:             $debogages = $entetes['debogages'];
209:             foreach ($debogages as $debogage) {
210:                 $e = "DEBOGAGE : $date - $uri :\n$debogage";
211:                 trigger_error($e, E_USER_NOTICE);
212:             }
213:         }
214:     }
215:     
216:     private function reinitialiser() {
217:         $this->nettoyerParametres();
218:     }
219: }
API documentation generated by ApiGen 2.8.0