2
104

sendhttp

sendhttp
SYNOPSIS

sendhttp($method, $url, $args, $files=false, $base64=false, $options=false, $header=false)

DESCRIPTION

sendhttp génère le document d'une requête HTTP GET, POST, PUT, DELETE ou HEAD, le transmet à un serveur HTTP ou HTTPS et retourne le code HTTP, l'en-tête et le corps du document renvoyés par le serveur ou false en cas d'erreur.

$method vaut 'GET', 'POST', 'PUT', 'DELETE' ou 'HEAD' selon le type de requête attendu par le serveur.

$url adresse le code PHP du serveur qui va analyser le document, effectuer un traitement et retourner un document au format HTTP. $url a le format [proto://]host[:portnum]/path. Mettez proto à 'https' pour transmettre le document en mode sécurisé. host donne le nom ou l'adresse IP du serveur. Si nécessaire, ajoutez portnum pour spécifier un numéro de port différent de 80 ou 443 pour des connexions en HTTP ou HTTPS avec un serveur à l'écoute sur des ports particuliers. path donne le chemin d'accès au code en PHP sur le serveur.

$args contient la liste des paramètres du service appelé sous la forme d'un tableau associatif { 'param1' => val1, ... }. $args permet de passer un ou plusieurs champs directement dans une URL pour une requête HTTP GET, DELETE ou HEAD, les champs extraits d'un formulaire HTML ou des champs encodés en JSON pour une requête HTTP POST ou PUT.

$files contient la liste des fichiers ajoutés en pièces jointes sous la forme d'un tableau associatif { 'docname' => {'name' => 'filename', 'type' => 'mimetype', 'tmp_name' => 'pathname'}, ... }. Ce paramètre est optionnel. Typiquement, il permet de passer un fichier transmis par une balise <input type="file" name="docname"... /> d'un formulaire HTML. Alternativement, le champ tmp_name peut être remplacé par un champ data suivi des données en binaires. Pour passer un contenu vide, mettre le champ files à true ou un champ data à '' (CHAÎNE VIDE). Si $base64 est à true, les contenus des fichiers sont encodés en base64.

sendhttp renvoie un tableau contenant le code de retour HTTP, l'en-tête MIME de la réponse ventilée ligne par ligne dans un tableau associatif et le corps brut de la réponse. Si un argument est invalide ou si la connexion a échoué, sendhttp retourne false.

EXEMPLE
php> $r = sendhttp('GET', 'http://www.google.com/search', array('q' => 'izend'));

Equivaut à taper http:://www.google.com/search?q=izend dans la barre d'adresse d'un navigateur.

php> print_r($r[0]);
200

Affiche le code de retour HTTP.

php> print_r($r[1]);
Array
(
    [Date] => ...
    [Expires] => -1
    [Cache-Control] => private, max-age=0
    [Content-Type] => text/html; charset=ISO-8859-1
    ...
)

Affiche l'en-tête MIME du document.

php> echo $r[1]['Content-Type'];
text/html; charset=ISO-8859-1

Affiche le type de contenu du document.

php> print_r($r[2]);
<!doctype html><head><title>izend - Google Search</title> ...

Affiche le document.

CODE
  1. function sendhttp($method, $url, $args, $files=false, $base64=false, $options=false, $header=false) {

sendhttp accepte 7 arguments : un type de requête, une URL, une liste de paramètres et en option une liste de fichiers dont le contenu peut être transmis encodé en base64, des paramètres passés dans le contexte de la connexion avec le service distant, des champs additionnels placés dans l'entête du document HTTP.

  1.     $r = http_parse_url($url);
  2.  
  3.     if (!$r) {
  4.         return false;
  5.     }
  6.  
  7.     list($proto, $scheme, $host, $portnum, $path, $query)=$r;
  8.  
  9.     if ($query) {
  10.         $path .= '?' . $query;
  11.     }

Décompose l'URL avec http_parse_url. Initialise les variables $proto, $scheme, $host, $portnum et $path. Retourne false si $url est invalide.

  1.     $hostaddr=($scheme == 'http' && $portnum == 80) ? $host : $host . ':' . $portnum;
  2.  
  3.     $user_agent='iZend';
  4.  
  5.     $content_string=$content_type=false;
  6.  
  7.     $crlf="\r\n";

Initialise la valeur des champs Host: et User-Agent: de la requête. Prépare l'en-tête et le corps du document HTTP. Définit $crlf à la valeur de la fin d'une ligne d'un document MIME. Teste le type de requête.

  1.     switch ($method) {
  2.         case 'POST':
  3.         case 'PUT':
  4.             if ($files) {
  5.                 $boundary = md5(microtime());
  6.                 $content_type = 'multipart/form-data; boundary='.$boundary;
  7.  
  8.                 $content_string = '';
  9.  
  10.                 if ($args && is_array($args)) {
  11.                     foreach ($args as $k => $v) {
  12.                         $content_string .= '--' . $boundary . $crlf;
  13.                         $content_string .= 'Content-Disposition: form-data; name="' . $k . '"' . $crlf . $crlf . $v . $crlf;
  14.                     }
  15.                 }
  16.                 if (is_array($files)) {
  17.                     foreach ($files as $k => $v ) {
  18.                         $data=false;
  19.                         if (isset($v['tmp_name'])) {
  20.                             $data = file_get_contents($v['tmp_name']);
  21.                         }
  22.                         else if (isset($v['data'])) {
  23.                             $data = $v['data'];
  24.                         }
  25.                         if (!$data) {
  26.                             break;
  27.                         }
  28.                         $content_string .= '--' . $boundary . $crlf;
  29.                         $content_string .= 'Content-Disposition: form-data; name="' . $k . '"; filename="' . $v['name'] . '"' . $crlf;
  30.                         $content_string .= 'Content-Type: ' . $v['type'] . $crlf;
  31.                         if ($base64) {
  32.                             $content_string .= 'Content-Transfer-Encoding: base64' . $crlf . $crlf;
  33.                             $content_string .= chunk_split(base64_encode($data)) . $crlf;
  34.                         }
  35.                         else {
  36.                             $content_string .= 'Content-Transfer-Encoding: binary' . $crlf . $crlf;
  37.                             $content_string .= $data . $crlf;
  38.                         }
  39.                     }
  40.                 }
  41.                 $content_string .= '--' . $boundary . '--' . $crlf;
  42.             }
  43.             else {
  44.                 if ($args) {
  45.                     if (is_array($args)) {
  46.                         $content_type = 'application/x-www-form-urlencoded';
  47.                         $content_string = http_build_args($args);
  48.                     }
  49.                     else {
  50.                         $content_string = $args;
  51.                     }
  52.                 }
  53.             }
  54.  
  55.             $header_string="$method $path HTTP/1.1${crlf}Host: $hostaddr${crlf}User-Agent: $user_agent${crlf}";
  56.  
  57.             if ($content_string) {
  58.                 $content_length = strlen($content_string);
  59.                 $header_string .= "Content-Length: $content_length${crlf}";
  60.                 if ($content_type) {
  61.                     $header_string .= "Content-Type: $content_type${crlf}";
  62.                 }
  63.             }
  64.             break;

Si la requête est un POST ou un PUT, si le document à un ou plusieurs fichiers joints, écrit un document de type multipart/form-data, sinon écrit un document de type application/x-www-form-urlencoded. Dans le premier cas, fabrique un corps de document avec une première partie qui définit un séparateur unique puis une séries de parties annexes contenant chacune un des fichiers joints dont le contenu est encodé en base64 si $base64 est à true. Dans le second cas, fabrique un corps de document HTTP contenant les paramètres éventuels de la requêtes proprement formatés avec http_build_args.

  1.         case 'GET':
  2.         case 'HEAD':
  3.         case 'DELETE':
  4.             if ($args && is_array($args)) {
  5.                 $path .= ($query ? '&' : '?') . http_build_args($args);
  6.             }
  7.             $header_string="$method $path HTTP/1.1${crlf}Host: $hostaddr${crlf}User-Agent: $user_agent${crlf}";
  8.             break;

Si la requête est un GET, un DELETE ou un HEAD, ajoute les paramètres éventuels proprement formatés avec http_build_args après le chemin d'accès, puis fabrique l'en-tête du document HTTP. Le corps du document est vide.

  1.         default:
  2.             return false;
  3.     }

Retourne false si $method n'est pas 'POST', 'PUT''GET', 'HEAD' ou 'DELETE'.

  1.     if ($header && is_array($header)) {
  2.         foreach ($header as $name => $value) {
  3.             if (is_array($value)) {
  4.                 $value = implode('; ', $value);
  5.             }
  6.             $header_string .= "${name}: ${value}${crlf}";
  7.         }
  8.     }

Ajoute dans $header_string les lignes définies par le tableau $header passé en argument.

  1.     $header_string .= "Connection: close${crlf}${crlf}";

Termine l'entête du document.

  1.     return sendhttpraw($proto, $host, $portnum, $header_string, $content_string, $options);
  2. }

Envoie $header_string et $content_string à $host avec sendhttpraw et retourne un tableau avec le code HTTP renvoyé par le service, l'en-tête MIME du document sous la forme d'un tableau associatif et le contenu brut du corps de la réponse.

sendhttpraw
SYNOPSIS

sendhttpraw($proto, $host, $portnum, $header_string, $content_string=false, $options=false)

DESCRIPTION
CODE
  1. function sendhttpraw($proto, $host, $portnum, $header_string, $content_string=false, $options=false) {

sendhttpraw accepte 6 arguments : un type de connexion - tcp ou ssl, un nom d'hôte ou une adresse IP, un numéro de port, l'entête et le corps d'un document HTTP, une série d'options passées dans le contexte de l'ouverture de la connexion.

  1.     $url=$proto . '://' . $host . ':' . $portnum;
  2.  
  3.     $socket = $options ? @stream_socket_client($url, $errstr, $errno, 60, STREAM_CLIENT_CONNECT, stream_context_create($options)) : @stream_socket_client($url);
  4.  
  5.     if ($socket === false) {
  6.         return false;
  7.     }

Ouvre la connexion avec le serveur. Retourne false en cas d'erreur.

  1.     if (fwrite($socket, $header_string) === false) {
  2.         return false;
  3.     }
  4.  
  5.     if ($content_string) {
  6.         $content_len = strlen($content_string);
  7.         for ($written = 0; $written < $content_len; $written += $w) {
  8.             $w = fwrite($socket, $written == 0 ? $content_string : substr($content_string, $written));
  9.             if ($w === false) {
  10.                 return false;
  11.             }
  12.         }
  13.     }

Écrit l'en-tête du document puis le corps du document en plusieurs paquets si nécessaire.

  1.     $response = '';
  2.     while (!feof($socket)) {
  3.         $response .= fread($socket, 8192);
  4.     }

Lit la réponse du serveur.

  1.     fclose($socket);

Ferme la connexion avec le serveur.

  1.     if (!$response) {
  2.         return false;
  3.     }

Retourne false si la réponse est vide.

  1.     $crlf="\r\n";

Définit $crlf à la valeur de la fin d'une ligne d'un document MIME.

  1.     list($response_headers, $response_body) = explode($crlf . $crlf, $response, 2);

Divise l'en-tête et le corps de la réponse. Sépare l'en-tête ligne par ligne. Extrait la première ligne de l'en-tête pour en retirer le code de retour.

  1.     $response_header_lines = explode($crlf, $response_headers);
  2.     $http_response_line = array_shift($response_header_lines);
  3.  
  4.     if (preg_match('@^HTTP/[0-9]\.[0-9] ([0-9]{3})@', $http_response_line, $r)) {
  5.         $response_code = $r[1];
  6.     }
  7.     else {
  8.         $response_code = 0;
  9.     }
  10.  
  11.     $response_header_array = array();
  12.     foreach ($response_header_lines as $header_line) {
  13.         list($header, $value) = explode(': ', $header_line, 2);
  14.         $response_header_array[ucwords($header, '-')] = $value;
  15.     }

Sauve l'en-tête de la réponse dans un tableau associatif.

  1.     if (isset($response_header_array['Transfer-Encoding'])) {
  2.         switch ($response_header_array['Transfer-Encoding']) {
  3.             case 'chunked':
  4.                 $chunks = explode($crlf, $response_body);
  5.                 foreach ($chunks as $i => $s) {
  6.                     if ($i % 2 == 0) {
  7.                         unset($chunks[$i]);
  8.                     }
  9.                 }
  10.                 $response_body = implode('', $chunks);
  11.                 break;
  12.             default:
  13.                 break;
  14.         }
  15.     }
  16.  
  17.     return array($response_code, $response_header_array, $response_body);
  18. }

Retourne un tableau avec le code HTTP renvoyé par le service, l'en-tête MIME du document sous la forme d'un tableau associatif et le contenu brut du corps de la réponse.

sendget
SYNOPSIS

sendget($url, $args, $options=false, $header=false)

DESCRIPTION

sendget retourne le document renvoyé par l'appel du service HTTP à l'adresse $url en GET avec les arguments $args.

En cas d'erreur, sendget retourne false.

CODE
  1. function sendget($url, $args=false, $options=false, $header=false) {
  2.     return sendhttp('GET', $url, $args, false, false, $options, $header);
  3. }

sendget retourne le résultat de l'appel de sendhttp avec $method à 'GET' et les arguments $url, $args, options et headers.

sendpost
SYNOPSIS

sendpost($url, $args, $files=false, $base64=false, $options=false, $header=false)

DESCRIPTION

sendpost retourne le document renvoyé par l'appel du service HTTP à l'adresse $url en POST avec les arguments $args et les pièces jointes $files encodées en base64 si $base64 vaut true.

En cas d'erreur, sendpost retourne false.

CODE
  1. function sendpost($url, $args=false, $files=false, $base64=false, $options=false, $header=false) {
  2.     return sendhttp('POST', $url, $args, $files, $base64, $options, $header);
  3. }

sendpost retourne le résultat de l'appel de sendhttp avec $method à 'POST' et les arguments $url, $args, $files, $base64, options et headers.

sendput
SYNOPSIS

sendput($url, $args, $files=false, $base64=false, $options=false, $header=false)

DESCRIPTION

sendput retourne le document renvoyé par l'appel du service HTTP à l'adresse $url en PUT avec les arguments $args et les pièces jointes $files encodées en base64 si $base64 vaut true.

En cas d'erreur, sendput retourne false.

CODE
  1. function sendput($url, $args=false, $files=false, $base64=false, $options=false, $header=false) {
  2.     return sendhttp('PUT', $url, $args, $files, $base64, $options, $header);
  3. }

sendput retourne le résultat de l'appel de sendhttp avec $method à 'PUT' et les arguments $url, $args, $files, $base64, options et headers.

senddelete
SYNOPSIS

senddelete($url, $args, $options=false, $header=false)

DESCRIPTION

senddelete retourne le document renvoyé par l'appel du service HTTP à l'adresse $url en DELETE avec les arguments $args.

En cas d'erreur, senddelete retourne false.

CODE
  1. function senddelete($url, $args=false, $options=false, $header=false) {
  2.     return sendhttp('DELETE', $url, $args, false, false, $options, $header);
  3. }

senddelete retourne le résultat de l'appel de sendhttp avec $method à 'DELETE' et les arguments $url, $args, options et headers.

sendhead
SYNOPSIS

sendhead($url, $args, $options=false, $header=false)

DESCRIPTION

sendhead retourne le document renvoyé par l'appel du service HTTP à l'adresse $url en HEAD avec les arguments $args.

En cas d'erreur, sendhead retourne false.

CODE
  1. function sendhead($url, $args=false, $options=false, $header=false) {
  2.     return sendhttp('HEAD', $url, $args, false, false, $options, $header);
  3. }

sendhead retourne le résultat de l'appel de sendhttp avec $method à 'HEAD' et les arguments $url, $args, options et headers.

http_build_args
SYNOPSIS

http_build_args($args)

DESCRIPTION

http_build_args retourne le tableau associatif $args sous la forme d'une chaine de paramètres d'une URL proprement encodée.

CODE
  1. function http_build_args($args) {
  2.     $args_string = '';
  3.  
  4.     foreach ($args as $name => $value) {
  5.         $args_string .= ($args_string ? '&' : '') . urlencode($name) . '=' . urlencode($value);
  6.     }
  7.  
  8.     return $args_string;
  9. }
http_parse_url
SYNOPSIS

http_parse_url($url)

DESCRIPTION

http_parse_url retourne un tableau contenant le protocole - tcp ou ssl, le schéma - http ou https, le nom d'hôte ou l'adresse IP, le numéro de port et le chemin décrit par $url.

CODE
  1. function http_parse_url($url) {
  2.     $purl = @parse_url($url);
  3.     if ($purl === false) {
  4.         return false;
  5.     }
  6.  
  7.     $scheme = isset($purl['scheme']) ? $purl['scheme'] : 'http';
  8.     switch($scheme) {
  9.         case 'https':
  10.             $proto = 'ssl';
  11.             break;
  12.         case 'http':
  13.             $proto = 'tcp';
  14.             break;
  15.         default:
  16.             return false;
  17.     }
  18.     $host = isset($purl['host']) ? $purl['host'] : 'localhost';
  19.     $portnum = isset($purl['port']) ? $purl['port'] : ($scheme == 'https' ? 443 : 80);
  20.     $path = isset($purl['path']) ? $purl['path'] : '/';
  21.     $query = isset($purl['query']) ? $purl['query'] : false;
  22.  
  23.     return array($proto, $scheme, $host, $portnum, $path, $query);
  24. }
Application
Encoder un code QR

Google publie une API pour dessiner des graphiques et d'autres types d'images - Google Charts API - qui permet d'obtenir une image PNG d'un code QR. Passez simplement les paramètres requis dans une <img> :

<img src="http://chart.googleapis.com/chart?cht=qr&chf=&bg,s,ffffff&chs=63x63&chld=M|0&chl=www.izend.org" />

qrencode

Décoder un code QR

Décoder l'image d'un code QR est plus délicat. Supposez que vous n'ayez pas trouvé une véritable API HTTP mais juste un formulaire qui vous laisse télécharger une image et retourne le texte décodé : ZXing Decoder Online. Essayez-le. Ce formulaire retourne le texte décodé ou un autre document HTML en cas d'erreur.

Extrayez le code source du formulaire :

<form enctype="multipart/form-data" method="post" action="decode">
<input name="f" type="file"/>
<input type="submit"/>
</form>

Écrivez une fonction qui passe ces paramètres dans une requête HTTP du type POST :

  1. require_once 'sendhttp.php';
  2. require_once 'filemimetype.php';
  3.  
  4. function qrdecode($file) {
  5.     $url = 'https://zxing.org/w/decode';
  6.     $files=array('f' => array('name' => basename($file), 'tmp_name' => $file, 'type' => file_mime_type($file)));
  7.  
  8.     $response=sendpost($url, false, $files, false); // DON'T encode data in base64
  9.  
  10.     if (!$response or $response[0] != 200) {
  11.         return false;
  12.     }
  13.  
  14.     if (!preg_match('#<tr><td>Parsed Result</td><td><pre.*>(.*)</pre></td></tr>#', $response[2], $r)) { // extract data - adapt when response format changes
  15.         return false;
  16.     }
  17.  
  18.     return strip_tags($r[1]);
  19. }

qrdecode envoie une requête POST à l'adresse https://zxing.org/w/decode avec un fichier en pièce l'image d'un code QR et retourne le texte qu'il contient. Si le service retourne une erreur, qrdecode retourne false.

IMPORTANT: Soyez très prudent lorsque vous insérez des données retournées par un autre service. Si possible, retirez toutes les balises avec strip_tags et ajoutez votre propre formatage.

Testez la fonction qrdecode avec le QR d'un site web :

$ php -a
php > define('ROOT_DIR', dirname(__FILE__));
php > set_include_path(ROOT_DIR . DIRECTORY_SEPARATOR . 'library' . PATH_SEPARATOR . get_include_path());
php > require_once 'qrdecode.php';
php > echo qrdecode('logos/siteqr.png') . PHP_EOL;
http://www.izend.org
VOIR AUSSI

qrencode, qrdecode

Commentaires

Votre commentaire :
[p] [b] [i] [u] [s] [quote] [pre] [br] [code] [url] [email] strip aide 2000

Entrez un maximum de 2000 caractères.
Améliorez la présentation de votre texte avec les balises de formatage suivantes :
[p]paragraphe[/p], [b]gras[/b], [i]italique[/i], [u]souligné[/u], [s]barré[/s], [quote]citation[/quote], [pre]tel quel[/pre], [br]à la ligne,
[url]http://www.izend.org[/url], [url=http://www.izend.org]site[/url], [email]izend@izend.org[/email], [email=izend@izend.org]izend[/email],
[code]commande[/code], [code=langage]code source en c, java, php, html, javascript, xml, css, sql, bash, dos, make, etc.[/code].