Acces à des ressources externes depuis EZPUBLISH : Proxy vs Acces direct
Par Alex SEBBANE le vendredi, février 17 2012, 22:25 - EzPublish
Parfois, une extension doit acceder a des ressources externes. il s'agit souvent de récupérer de l'information avec des systemes differents. il peut alors s'agir :
- d'un appel à des fichiers XML distant (cas 1)
- d'utilisation d'une API tiers avec passage d'information en GET (cas 2)
- d'utilisation d'une API tiers avec passage d'information en POST (cas 3)
- d'utilisation d'une API tiers avec envoi de fichier (cas 4)
Nous étudierons ces quatre cas.
Appel a un acces direct (cas 1)
imaginons qu'une application doivent recuperer des informations dans un ficheir XML : http://www.lesitetiers.com/fichier.xml en PHP on ferai appel à la fonction file_get_content qui renvoie le contenu du ficheir appelé dnas une chaine.
<?php
$homepage = file_get_contents('http://www.lesitetiers.com/fichier.xml');
echo $homepage;
?>
cela fonctionne dans la plupart des cas. malheureusement, dans un environnement de production assez strict et contrôlé, les accès vers l'externe sont interdits et il faut alors passé par un proxy. il existe une classe qui permet de faire cela dans eZPublish : la classe eZHTTPTool. le code ci-dessous devient alors :
<?php
$homepage = eZHTTPTool::getDataByURL('http://www.lesitetiers.com/fichier.xml');
echo $homepage;
?>
Attention : il faudra alors avoir installé la bibliothèque Curl de PHP et avoir configuré le proxy dans une surcharge du fichier de configuration site.ini la methode getDataByURL est prevu pour utiliser les configurations ci dessus.
[ProxySettings] # If an user wants to use proxy in linkcheck.php/rssimport.php or downloading site packages in "setup wizard". # If empty proxy will not be used. # Example: http://<host>:<port> ProxyServer= User= Password=
utilisation d'une API tiers avec passage d'information en GET (cas 2)
imaginons que nous devions utiliser l'API slideshare pour en recuperer des informations (voir ici )
nous nous retrouvons ici avec le cas precedent si nous recontruisons l'url a appeller avant ex :http://www.slideshare.net/api/oembed/2?url=http://www.slideshare.net/haraldf/business-quotes-for-2011&format=xml
<?php
$xmlslideshare = eZHTTPTool::getDataByURL('http://www.slideshare.net/api/oembed/2?url=http://www.slideshare.net/alexsebbane/bpce-ezpublish&format=xml');
echo $xmlslideshare ;
?>
utilisation d'une API tiers avec passage d'information en POST (cas 3)
Normalement en PHP, il faut utiliser un code qui ressemble a cela :
<?php
$url = "http://www.lesitetiers.com/form.php";
$port = 80;
//create array of data to be posted
$param['firstName'] = 'Alexandre';
$param['action'] = 'Register';
$param['lastName'] = 'SEBBANE';
$dataArr = array();
foreach (array_keys($params) as $key) {
array_push($dataArr,urlencode($key) ."=".
urlencode($params[$key]));
}
$data = implode("&",$dataArr);
$fp = fsockopen( $url, $port, $errno, $errstr, 30);
$out = "POST ".$path." HTTP/1.0\r\n";
$out .= "Host: ".$url."\r\n";
$out .= "User-Agent: ".$_SERVER['HTTP_USER_AGENT']."\r\n";
$out .= "Content-type: application/x-www-form-urlencoded; charset=UTF-8\r\n";
$out .= "Content-Length: ".strlen($data)."\r\n\r\n";
fwrite($fp, $out);
fwrite($fp, $data);
$contentLength = 0;
$finished = false;
$result = Array();
$header = Array();
$safe=0;
while(!feof($fp) && $safe<1000 && !$finished) {
// receive the results of the request
$line = fgets($fp, 128);
$header[] = $line;
if (trim($line) == '')
{
$finished = true;
}
if (strpos(strtolower($line), strtolower('Content-Length')) !== false)
{
$arrParts = explode(':', $line);
$contentLength = trim($arrParts[1]);
}
$safe++;
}
$content = fgets($fp, $contentLength+10);
$content .= fgets($fp, $contentLength+10);
fclose($fp);
echo $content;
?>
encore une fois, ce code fonctionne mais pas dans un environnement avec un proxy. il faudra alors utiliser une nouvelle fois la librairie CURL. le code ci dessus devient alors :
<?php
//create array of data to be posted
$url = "http://www.lesitetiers.com/form.php";
//create array of data to be posted
$param['firstName'] = 'Alexandre';
$param['action'] = 'Register';
$param['lastName'] = 'SEBBANE';
//traverse array and prepare data for posting (key1=value1)
foreach ( $param as $key => $value) {
$post_items[] = $key . '=' . $value;
}
//create the final string to be posted using implode()
$post_string = implode ('&', $post_items);
//create cURL connection
$curl_connection = curl_init($url);
$ini = eZINI::instance();
$proxy = $ini->hasVariable( 'ProxySettings', 'ProxyServer' ) ? $ini->variable( 'ProxySettings', 'ProxyServer' ) : false;
// If we should use proxy
if ( $proxy )
{
curl_setopt ( $curl_connection, CURLOPT_PROXY , $proxy );
$userName = $ini->hasVariable( 'ProxySettings', 'User' ) ? $ini->variable( 'ProxySettings', 'User' ) : false;
$password = $ini->hasVariable( 'ProxySettings', 'Password' ) ? $ini->variable( 'ProxySettings', 'Password' ) : false;
if ( $userName )
{
curl_setopt ( $curl_connection, CURLOPT_PROXYUSERPWD, "$userName:$password" );
}
}
//set options
curl_setopt($curl_connection, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($curl_connection, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)");
curl_setopt($curl_connection, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl_connection, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl_connection, CURLOPT_FOLLOWLOCATION, 1);
//set data to be posted
curl_setopt($curl_connection, CURLOPT_POSTFIELDS, $post_string);
//perform our request
$content = curl_exec($curl_connection);
//close the connection
curl_close($curl_connection);
echo $content;
?>
ce code n'existe pas dans le kernel Ez, mais il est possible d'en creer une methode qui prendrai 2 parametres : url, tableau de parametre à envoyer.
Utilisation d'une API tiers avec envoi de fichier (cas 4)
en PHP, la methode utilisé pour envoyer un fichier est assez complexe :
<?php
$filename = 'var/dump/fichier.zip';
$host = 'https://www.lesitetiers.com';
$path = '/form.php';
$port = 443;
$postdata = array();
$handle = fopen($filename, "r");
if ($handle == false){
$script->shutdown( 1, 'Reading zip failed.' );
}
$contents = fread($handle, filesize($filename));
fclose($handle);
$filedata = array('inputname', basename($filename), $contents);
unlink($newfile);
$cli->output( "Uploading log-file..." );
$boundary = "---------------------".substr(md5(rand(0,32000)),0,10);
$fp = fsockopen($host, $port, $errno, $errstr, 30);
fputs($fp, "POST $path HTTP/1.0\r\n");
fputs($fp, "Host: $host\r\n");
fputs($fp, "Content-Transfer-Encoding: binary\r\n");
fputs($fp, "User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1) Gecko/20061010 Firefox/2.0\r\n");
fputs($fp, "Content-type: multipart/form-data; boundary=".$boundary."\r\n");
$data = "--$boundary\r\nContent-Disposition: form-data; name=\"uploadfile\"; filename=\"$filedata[1]\"\r\n\r\n$filedata[2]\r\n";
$data .= "--$boundary--\r\n";
fputs($fp, "Content-length: ".strlen($data)."\r\n\r\n");
fputs($fp, $data);
while(!feof($fp)) {
$result .= fread($fp, 1024);
}
fclose($fp);
echo $result ;
?>
en utilisant la librairie CURL, le code ser reduit a cela :
<?php
$filename = 'var/dump/fichier.zip';
$host = 'https://www.lesitetiers.com';
$path = '/form.php';
$port = 443;
$ch = curl_init();
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_VERBOSE, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible;)");
curl_setopt($ch, CURLOPT_URL, $host.$path );
curl_setopt($ch, CURLOPT_POST, true);
$ini = eZINI::instance();
$proxy = $ini->hasVariable( 'ProxySettings', 'ProxyServer' ) ? $ini->variable( 'ProxySettings', 'ProxyServer' ) : false;
// If we should use proxy
if ( $proxy )
{
curl_setopt ( $ch, CURLOPT_PROXY , $proxy );
$userName = $ini->hasVariable( 'ProxySettings', 'User' ) ? $ini->variable( 'ProxySettings', 'User' ) : false;
$password = $ini->hasVariable( 'ProxySettings', 'Password' ) ? $ini->variable( 'ProxySettings', 'Password' ) : false;
if ( $userName )
{
curl_setopt ( $ch, CURLOPT_PROXYUSERPWD, "$userName:$password" );
}
}
$post = array(
"file_box"=> $filename,
);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
$result = curl_exec($ch);
echo $result;
?>
Donc, voici donc un aperçu de toutes les combines pour respecter une norme posé par ezpublish : si la configuration de Ez mets en place un proxy ou non, votre code ne sera pas a modifier ou a adapter.
Des coquilles peuvent s’être glisser dans les codes ci dessous. je veux juste mettre en avant cette problematique que j'ai eu pendaznt 4 ans dnas mon environnement professionnel.
merci d'avance de respecter cela pour tout ceux qui comme moi ne peuvent acceder a internet que via des PROXYS.

Commentaires
C'est bien, mais via la l'extension ggwebservices on peut faire facilement la meme chose que le cas 1 à 3 ci dessus, en 2 lignes de code (et de config).
Les avantages:
- ca marche avec et sans curl a bord
- ca marche avec ou sans proxy
- support complet pour https, authentification basic/digest/ntlm, des requetes et reponses compressees entre autres
je ne connais aps bien ton extension : je voulais juste rappeller a la communaute la problematique des extensions vs proxy ... car quand elle m'intgeressent il me faut les modifier...
il y a aussi un message caché pour ez_network et ezodoscope....
Alexandre