X-Git-Url: https://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2FHttpFunctions.php;h=1c794853a02d64059ee6ff2e52a75286240cf953;hb=63811f0b1424adec7bd9cf77a4eb2ffb73744b82;hp=7f0d6a216051437e07eb01541b2e17513035c9fd;hpb=d9a3591294d9ce32fa9129ecdd426528676287a7;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/HttpFunctions.php b/includes/HttpFunctions.php index 7f0d6a2160..1c794853a0 100644 --- a/includes/HttpFunctions.php +++ b/includes/HttpFunctions.php @@ -25,6 +25,8 @@ * @defgroup HTTP HTTP */ +use MediaWiki\Logger\LoggerFactory; + /** * Various HTTP related functions * @ingroup HTTP @@ -55,9 +57,10 @@ class Http { * to avoid attacks on intranet services accessible by HTTP. * - userAgent A user agent, if you want to override the default * MediaWiki/$wgVersion + * @param string $caller The method making this request, for profiling * @return string|bool (bool)false on failure or a string on success */ - public static function request( $method, $url, $options = array() ) { + public static function request( $method, $url, $options = array(), $caller = __METHOD__ ) { wfDebug( "HTTP: $method: $url\n" ); $options['method'] = strtoupper( $method ); @@ -69,14 +72,17 @@ class Http { $options['connectTimeout'] = 'default'; } - $req = MWHttpRequest::factory( $url, $options ); + $req = MWHttpRequest::factory( $url, $options, $caller ); $status = $req->execute(); - $content = false; if ( $status->isOK() ) { - $content = $req->getContent(); + return $req->getContent(); + } else { + $errors = $status->getErrorsByType( 'error' ); + $logger = LoggerFactory::getInstance( 'http' ); + $logger->warning( $status->getWikiText(), array( 'caller' => $caller ) ); + return false; } - return $content; } /** @@ -87,18 +93,21 @@ class Http { * * @param string $url * @param array $options + * @param string $caller The method making this request, for profiling * @return string */ - public static function get( $url, $options = array() ) { + public static function get( $url, $options = array(), $caller = __METHOD__ ) { $args = func_get_args(); - if ( is_string( $args[1] ) || is_numeric( $args[1] ) ) { + if ( isset( $args[1] ) && ( is_string( $args[1] ) || is_numeric( $args[1] ) ) ) { // Second was used to be the timeout // And third parameter used to be $options - wfWarn( "Second parameter should not be a timeout." ); - $options = isset( $args[2] ) ? $args[2] : array(); + wfWarn( "Second parameter should not be a timeout.", 2 ); + $options = isset( $args[2] ) && is_array( $args[2] ) ? + $args[2] : array(); $options['timeout'] = $args[1]; + $caller = __METHOD__; } - return Http::request( 'GET', $url, $options ); + return Http::request( 'GET', $url, $options, $caller ); } /** @@ -107,10 +116,11 @@ class Http { * * @param string $url * @param array $options + * @param string $caller The method making this request, for profiling * @return string */ - public static function post( $url, $options = array() ) { - return Http::request( 'POST', $url, $options ); + public static function post( $url, $options = array(), $caller = __METHOD__ ) { + return Http::request( 'POST', $url, $options, $caller ); } /** @@ -224,18 +234,30 @@ class MWHttpRequest { public $status; + /** + * @var Profiler + */ + protected $profiler; + + /** + * @var string + */ + protected $profileName; + /** * @param string $url Url to use. If protocol-relative, will be expanded to an http:// URL * @param array $options (optional) extra params to pass (see Http::request()) + * @param string $caller The method making this request, for profiling + * @param Profiler $profiler An instance of the profiler for profiling, or null */ - protected function __construct( $url, $options = array() ) { + protected function __construct( $url, $options = array(), $caller = __METHOD__, $profiler = null ) { global $wgHTTPTimeout, $wgHTTPConnectTimeout; $this->url = wfExpandUrl( $url, PROTO_HTTP ); $this->parsedUrl = wfParseUrl( $this->url ); if ( !$this->parsedUrl || !Http::isValidURI( $this->url ) ) { - $this->status = Status::newFatal( 'http-invalid-url' ); + $this->status = Status::newFatal( 'http-invalid-url', $url ); } else { $this->status = Status::newGood( 100 ); // continue } @@ -271,6 +293,10 @@ class MWHttpRequest { if ( $this->noProxy ) { $this->proxy = ''; // noProxy takes precedence } + + // Profile based on what's calling us + $this->profiler = $profiler; + $this->profileName = $caller; } /** @@ -286,11 +312,12 @@ class MWHttpRequest { * Generate a new request object * @param string $url Url to use * @param array $options (optional) extra params to pass (see Http::request()) + * @param string $caller The method making this request, for profiling * @throws MWException * @return CurlHttpRequest|PhpHttpRequest * @see MWHttpRequest::__construct */ - public static function factory( $url, $options = null ) { + public static function factory( $url, $options = null, $caller = __METHOD__ ) { if ( !Http::$httpEngine ) { Http::$httpEngine = function_exists( 'curl_init' ) ? 'curl' : 'php'; } elseif ( Http::$httpEngine == 'curl' && !function_exists( 'curl_init' ) ) { @@ -300,7 +327,7 @@ class MWHttpRequest { switch ( Http::$httpEngine ) { case 'curl': - return new CurlHttpRequest( $url, $options ); + return new CurlHttpRequest( $url, $options, $caller, Profiler::instance() ); case 'php': if ( !wfIniGetBool( 'allow_url_fopen' ) ) { throw new MWException( __METHOD__ . ': allow_url_fopen ' . @@ -309,7 +336,7 @@ class MWHttpRequest { 'http://php.net/curl.' ); } - return new PhpHttpRequest( $url, $options ); + return new PhpHttpRequest( $url, $options, $caller, Profiler::instance() ); default: throw new MWException( __METHOD__ . ': The setting of Http::$httpEngine is not valid.' ); } @@ -770,14 +797,20 @@ class CurlHttpRequest extends MWHttpRequest { } if ( $this->followRedirects && $this->canFollowRedirects() ) { - wfSuppressWarnings(); + MediaWiki\suppressWarnings(); if ( !curl_setopt( $curlHandle, CURLOPT_FOLLOWLOCATION, true ) ) { wfDebug( __METHOD__ . ": Couldn't set CURLOPT_FOLLOWLOCATION. " . "Probably safe_mode or open_basedir is set.\n" ); // Continue the processing. If it were in curl_setopt_array, // processing would have halted on its entry } - wfRestoreWarnings(); + MediaWiki\restoreWarnings(); + } + + if ( $this->profiler ) { + $profileSection = $this->profiler->scopedProfileIn( + __METHOD__ . '-' . $this->profileName + ); } $curlRes = curl_exec( $curlHandle ); @@ -791,6 +824,10 @@ class CurlHttpRequest extends MWHttpRequest { curl_close( $curlHandle ); + if ( $this->profiler ) { + $this->profiler->scopedProfileOut( $profileSection ); + } + $this->parseHeader(); $this->setStatus(); @@ -880,7 +917,13 @@ class PhpHttpRequest extends MWHttpRequest { } if ( $this->sslVerifyHost ) { - $options['ssl']['CN_match'] = $this->parsedUrl['host']; + // PHP 5.6.0 deprecates CN_match, in favour of peer_name which + // actually checks SubjectAltName properly. + if ( version_compare( PHP_VERSION, '5.6.0', '>=' ) ) { + $options['ssl']['peer_name'] = $this->parsedUrl['host']; + } else { + $options['ssl']['CN_match'] = $this->parsedUrl['host']; + } } if ( is_dir( $this->caInfo ) ) { @@ -899,13 +942,31 @@ class PhpHttpRequest extends MWHttpRequest { $result = array(); + if ( $this->profiler ) { + $profileSection = $this->profiler->scopedProfileIn( + __METHOD__ . '-' . $this->profileName + ); + } do { $reqCount++; - wfSuppressWarnings(); + MediaWiki\suppressWarnings(); $fh = fopen( $url, "r", false, $context ); - wfRestoreWarnings(); + MediaWiki\restoreWarnings(); if ( !$fh ) { + // HACK for instant commons. + // If we are contacting (commons|upload).wikimedia.org + // try again with CN_match for en.wikipedia.org + // as php does not handle SubjectAltName properly + // prior to "peer_name" option in php 5.6 + if ( isset( $options['ssl']['CN_match'] ) + && ( $options['ssl']['CN_match'] === 'commons.wikimedia.org' + || $options['ssl']['CN_match'] === 'upload.wikimedia.org' ) + ) { + $options['ssl']['CN_match'] = 'en.wikipedia.org'; + $context = stream_context_create( $options ); + continue; + } break; } @@ -929,6 +990,9 @@ class PhpHttpRequest extends MWHttpRequest { break; } } while ( true ); + if ( $this->profiler ) { + $this->profiler->scopedProfileOut( $profileSection ); + } $this->setStatus();