Skip to content
Extraits de code Groupes Projets
Valider 85d0528c rédigé par cerdic's avatar cerdic
Parcourir les fichiers

Report de r21363 : Amelioration de la gestion du Proxy : gestion des echecs,...

Report de r21363 : Amelioration de la gestion du Proxy : gestion des echecs, et gestion du https via CONNECT

Quand la requête necessite un proxy et qu'elle echoue, il ne faut pas essayer de la relancer en direct via fopen() ou via file_get_contents() car cela produit un timeout sur le firewall éventuel

Pour faire une requête https à travers un proxy il faut en général passer par un CONNECT initial (https://en.wikipedia.org/wiki/HTTP_tunnel) ce qui n'était pas géré ici. On implémente donc ce dialogue.
Par soucis de compatibilité il ne sera pris en charge qu'en cas de
```define('_PROXY_HTTPS_VIA_CONNECT',true);```
dans le fichier mes_options.php. A voir si il faut rendre cette fonctionnalité activable par l'interface et/ou si elle doit être celle active par défaut.
parent b564d9ac
Aucune branche associée trouvée
Aucune étiquette associée trouvée
Aucune requête de fusion associée trouvée
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
/** /**
* Ce fichier gère l'obtention de données distantes * Ce fichier gère l'obtention de données distantes
* *
* @package SPIP\Core\Distant * @package SPIP\Core\Distant
**/ **/
if (!defined('_ECRIRE_INC_VERSION')) return; if (!defined('_ECRIRE_INC_VERSION')) return;
...@@ -22,7 +22,7 @@ if (!defined('_INC_DISTANT_CONTENT_ENCODING')) define('_INC_DISTANT_CONTENT_ENCO ...@@ -22,7 +22,7 @@ if (!defined('_INC_DISTANT_CONTENT_ENCODING')) define('_INC_DISTANT_CONTENT_ENCO
if (!defined('_INC_DISTANT_USER_AGENT')) define('_INC_DISTANT_USER_AGENT', 'SPIP-' . $GLOBALS['spip_version_affichee'] . " (" . $GLOBALS['home_server'] . ")"); if (!defined('_INC_DISTANT_USER_AGENT')) define('_INC_DISTANT_USER_AGENT', 'SPIP-' . $GLOBALS['spip_version_affichee'] . " (" . $GLOBALS['home_server'] . ")");
if (!defined('_INC_DISTANT_MAX_SIZE')) define('_INC_DISTANT_MAX_SIZE',2097152); if (!defined('_INC_DISTANT_MAX_SIZE')) define('_INC_DISTANT_MAX_SIZE',2097152);
define('_REGEXP_COPIE_LOCALE', ',' . define('_REGEXP_COPIE_LOCALE', ',' .
preg_replace('@^https?:@', 'https?:', preg_replace('@^https?:@', 'https?:',
(isset($GLOBALS['meta']["adresse_site"]) ? $GLOBALS['meta']["adresse_site"] : '')) (isset($GLOBALS['meta']["adresse_site"]) ? $GLOBALS['meta']["adresse_site"] : ''))
. "/?spip.php[?]action=acceder_document.*file=(.*)$,"); . "/?spip.php[?]action=acceder_document.*file=(.*)$,");
...@@ -295,13 +295,20 @@ function recuperer_url($url, $options = array()){ ...@@ -295,13 +295,20 @@ function recuperer_url($url, $options = array()){
if (!$fopen) { if (!$fopen) {
$res = recuperer_entetes_complets($handle, $options['if_modified_since']); $res = recuperer_entetes_complets($handle, $options['if_modified_since']);
if(!$res) { if(!$res) {
fclose($handle);
$t = @parse_url($url);
$host = $t['host'];
// Chinoisierie inexplicable pour contrer // Chinoisierie inexplicable pour contrer
// les actions liberticides de l'empire du milieu // les actions liberticides de l'empire du milieu
if ($res = @file_get_contents($url)){ if (!need_proxy($host)
$result['status'] = 200; AND $res = @file_get_contents($url)){
$result['page'] = $res; $res = array(
return $result; 'status' => 200,
'page' => $res,
);
} }
else
return false;
} }
elseif ($res['location'] AND $options['follow_location']){ elseif ($res['location'] AND $options['follow_location']){
$options['follow_location']--; $options['follow_location']--;
...@@ -315,9 +322,14 @@ function recuperer_url($url, $options = array()){ ...@@ -315,9 +322,14 @@ function recuperer_url($url, $options = array()){
spip_log("HTTP status ".$res['status']." pour $url"); spip_log("HTTP status ".$res['status']." pour $url");
} }
$result['status'] = $res['status']; $result['status'] = $res['status'];
$result['headers'] = $res['headers']; if (isset($res['headers']))
$result['last_modified'] = $res['last_modified']; $result['headers'] = $res['headers'];
$result['location'] = $res['location']; if (isset($res['last_modified']))
$result['last_modified'] = $res['last_modified'];
if (isset($res['location']))
$result['location'] = $res['location'];
if (isset($res['page']))
$result['page'] = $res['page'];
} }
// on ne veut que les entetes // on ne veut que les entetes
...@@ -332,27 +344,30 @@ function recuperer_url($url, $options = array()){ ...@@ -332,27 +344,30 @@ function recuperer_url($url, $options = array()){
if (preg_match(",\bContent-Encoding: .*gzip,is", $result['headers'])) if (preg_match(",\bContent-Encoding: .*gzip,is", $result['headers']))
$gz = (_DIR_TMP . md5(uniqid(mt_rand())) . '.tmp.gz'); $gz = (_DIR_TMP . md5(uniqid(mt_rand())) . '.tmp.gz');
$res = recuperer_body($handle, $options['taille_max'], $gz ? $gz : $copy); if (!$result['page']){
fclose($handle); $res = recuperer_body($handle, $options['taille_max'], $gz ? $gz : $copy);
if ($copy){ fclose($handle);
$result['length'] = $res; if ($copy){
$result['file'] = $copy; $result['length'] = $res;
} $result['file'] = $copy;
elseif($res) {
$result['page'] = &$res;
$result['length'] = strlen($result['page']);
// Decompresser au besoin
if ($gz){
$result['page'] = implode('', gzfile($gz));
supprimer_fichier($gz);
} }
elseif($res) {
$result['page'] = &$res;
$result['length'] = strlen($result['page']);
}
if (!$result['page'])
return $result;
// Faut-il l'importer dans notre charset local ? // Decompresser au besoin
if ($options['transcoder']){ if ($gz){
include_spip('inc/charsets'); $result['page'] = implode('', gzfile($gz));
$result['page'] = transcoder_page($result['page'], $result['headers']); supprimer_fichier($gz);
} }
// Faut-il l'importer dans notre charset local ?
if ($options['transcoder']){
include_spip('inc/charsets');
$result['page'] = transcoder_page($result['page'], $result['headers']);
} }
return $result; return $result;
...@@ -1010,7 +1025,8 @@ function init_http($method, $url, $refuse_gz = false, $referer = '', $datas = "" ...@@ -1010,7 +1025,8 @@ function init_http($method, $url, $refuse_gz = false, $referer = '', $datas = ""
$f = lance_requete($method, $scheme, $user, $host, $path, $port, $noproxy, $refuse_gz, $referer, $datas, $vers, $date); $f = lance_requete($method, $scheme, $user, $host, $path, $port, $noproxy, $refuse_gz, $referer, $datas, $vers, $date);
if (!$f){ if (!$f){
// fallback : fopen // fallback : fopen
if (!_request('tester_proxy')){ if (!need_proxy($host)
AND !_request('tester_proxy')){
$f = @fopen($url, "rb"); $f = @fopen($url, "rb");
spip_log("connexion vers $url par simple fopen"); spip_log("connexion vers $url par simple fopen");
$fopen = true; $fopen = true;
...@@ -1059,10 +1075,19 @@ function lance_requete($method, $scheme, $user, $host, $path, $port, $noproxy, $ ...@@ -1059,10 +1075,19 @@ function lance_requete($method, $scheme, $user, $host, $path, $port, $noproxy, $
$http_proxy = need_proxy($host); $http_proxy = need_proxy($host);
if ($user) $user = urlencode($user[0]) . ":" . urlencode($user[1]); if ($user) $user = urlencode($user[0]) . ":" . urlencode($user[1]);
$connect = "";
if ($http_proxy){ if ($http_proxy){
$path = (($scheme=='ssl') ? 'https://' : "$scheme://") if (defined('_PROXY_HTTPS_VIA_CONNECT') AND $scheme=="ssl"){
. (!$user ? '' : "$user@") $path_host = (!$user ? '' : "$user@") . $host . (($port!=80) ? ":$port" : "");
. "$host" . (($port!=80) ? ":$port" : "") . $path; $connect = "CONNECT " .$path_host." $vers\r\n"
."Host: $path_host\r\n"
."Proxy-Connection: Keep-Alive\r\n";
}
else {
$path = (($scheme=='ssl') ? 'https://' : "$scheme://")
. (!$user ? '' : "$user@")
. "$host" . (($port!=80) ? ":$port" : "") . $path;
}
$t2 = @parse_url($http_proxy); $t2 = @parse_url($http_proxy);
$first_host = $t2['host']; $first_host = $t2['host'];
if (!($port = $t2['port'])) $port = 80; if (!($port = $t2['port'])) $port = 80;
...@@ -1072,9 +1097,34 @@ function lance_requete($method, $scheme, $user, $host, $path, $port, $noproxy, $ ...@@ -1072,9 +1097,34 @@ function lance_requete($method, $scheme, $user, $host, $path, $port, $noproxy, $
else else
$first_host = $noproxy . $host; $first_host = $noproxy . $host;
$f = @fsockopen($first_host, $port); if ($connect){
spip_log("Recuperer $path sur $first_host:$port par $f"); $streamContext = stream_context_create(array('ssl' => array('verify_peer' => false, 'allow_self_signed' => true)));
if (!$f) return false; $f = @stream_socket_client("tcp://$first_host:$port", $nError, $sError, 10, STREAM_CLIENT_CONNECT, $streamContext);
spip_log("Recuperer $path sur $first_host:$port par $f (via CONNECT)","connect");
if (!$f) return false;
stream_set_timeout($f, 10);
fputs($f, $connect);
fputs($f, "\r\n");
$res = fread($f, 1024);
if (!$res
OR !count($res = explode(' ',$res))
OR $res[1]!=='200'){
spip_log("Echec CONNECT sur $first_host:$port","connect"._LOG_INFO_IMPORTANTE);
fclose($f);
return false;
}
// important, car sinon on lit trop vite et les donnees ne sont pas encore dispo
stream_set_blocking($f, true);
// envoyer le handshake
stream_socket_enable_crypto($f, true, STREAM_CRYPTO_METHOD_SSLv23_CLIENT);
spip_log("OK CONNECT sur $first_host:$port","connect");
}
else {
$f = @fsockopen($first_host, $port);
spip_log("Recuperer $path sur $first_host:$port par $f");
if (!$f) return false;
}
$site = isset($GLOBALS['meta']["adresse_site"]) ? $GLOBALS['meta']["adresse_site"] : ''; $site = isset($GLOBALS['meta']["adresse_site"]) ? $GLOBALS['meta']["adresse_site"] : '';
...@@ -1094,4 +1144,3 @@ function lance_requete($method, $scheme, $user, $host, $path, $port, $noproxy, $ ...@@ -1094,4 +1144,3 @@ function lance_requete($method, $scheme, $user, $host, $path, $port, $noproxy, $
return $f; return $f;
} }
?>
0% Chargement en cours ou .
You are about to add 0 people to the discussion. Proceed with caution.
Terminez d'abord l'édition de ce message.
Veuillez vous inscrire ou vous pour commenter