Deprecate the Http class
All methods got moved to HttpRequestFactory or MWHttpRequest or dropped. I made the return value of the new HttpRequestFactory::request/get/post methods null on error instead of false, so that when we drop PHP 7 support, we can use a "?string" return value. This could theoretically change behavior of code that was switched from the old Http methods, but probably won't. I kept the old behavior for the deprecated methods. I changed the default value of $wgHTTPProxy from false to ''. This way it should be usable directly without a trivial wrapper method. For the benefit of anyone who might have set it to false in LocalSettings.php, I also recommend casting to string just in case. Http::$httpEngine is deprecated. Eventually it will be removed along with the curl and PHP engines, leaving only the Guzlle engine. I also added deprecation of MWHttpRequest::factory, which occurred in 1.31, to the release notes for 1.34. Now hopefully we can hard-deprecate it in another couple of versions. Bug: T214390 Change-Id: I2a316a758d793857f248bd251b90f5e9a6440e3a
This commit is contained in:
parent
427fbee734
commit
9018579681
23 changed files with 256 additions and 122 deletions
|
|
@ -116,7 +116,7 @@ because of Phabricator reports.
|
|||
* …
|
||||
|
||||
=== Deprecations in 1.34 ===
|
||||
* The MWNamespace class is deprecated. Use MediaWikiServices::getNamespaceInfo.
|
||||
* The MWNamespace class is deprecated. Use NamespaceInfo.
|
||||
* ExtensionRegistry->load() is deprecated, as it breaks dependency checking.
|
||||
Instead, use ->queue().
|
||||
* User::isBlocked() is deprecated since it does not tell you if the user is
|
||||
|
|
@ -135,6 +135,13 @@ because of Phabricator reports.
|
|||
RevisionLookup::getPreviousRevision and RevisionLookup::getNextRevision.
|
||||
* The Title parameter to RevisionLookup::getPreviousRevision and
|
||||
RevisionLookup::getNextRevision is deprecated and should be omitted.
|
||||
* MWHttpRequest::factory is deprecated. Use HttpRequestFactory.
|
||||
* The Http class is deprecated. For the request, get, and post methods, use
|
||||
HttpRequestFactory. For isValidURI, use MWHttpRequest::isValidURI. For
|
||||
getProxy, use (string)$wgHTTPProxy. For createMultiClient, construct a
|
||||
MultiHttpClient directly.
|
||||
* Http::$httpEngine is deprecated and has no replacement. The default 'guzzle'
|
||||
engine will eventually be made the only engine for HTTP requests.
|
||||
|
||||
=== Other changes in 1.34 ===
|
||||
* …
|
||||
|
|
|
|||
|
|
@ -8399,7 +8399,7 @@ $wgAsyncHTTPTimeout = 25;
|
|||
/**
|
||||
* Proxy to use for CURL requests.
|
||||
*/
|
||||
$wgHTTPProxy = false;
|
||||
$wgHTTPProxy = '';
|
||||
|
||||
/**
|
||||
* Local virtual hosts.
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use MediaWiki\Logger\LoggerFactory;
|
||||
use MediaWiki\MediaWikiServices;
|
||||
|
||||
/**
|
||||
* Send information about this MediaWiki instance to MediaWiki.org.
|
||||
|
|
@ -229,7 +230,7 @@ class Pingback {
|
|||
$json = FormatJson::encode( $data );
|
||||
$queryString = rawurlencode( str_replace( ' ', '\u0020', $json ) ) . ';';
|
||||
$url = 'https://www.mediawiki.org/beacon/event?' . $queryString;
|
||||
return Http::post( $url ) !== false;
|
||||
return MediaWikiServices::getInstance()->getHttpRequestFactory()->post( $url ) !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@
|
|||
* @file
|
||||
*/
|
||||
|
||||
use MediaWiki\MediaWikiServices;
|
||||
|
||||
/**
|
||||
* Example class for HTTP accessible external objects.
|
||||
* Only supports reading, not storing.
|
||||
|
|
@ -28,7 +30,8 @@
|
|||
*/
|
||||
class ExternalStoreHttp extends ExternalStoreMedium {
|
||||
public function fetchFromURL( $url ) {
|
||||
return Http::get( $url, [], __METHOD__ );
|
||||
return MediaWikiServices::getInstance()->getHttpRequestFactory()->
|
||||
get( $url, [], __METHOD__ );
|
||||
}
|
||||
|
||||
public function store( $location, $data ) {
|
||||
|
|
|
|||
|
|
@ -502,8 +502,9 @@ class ForeignAPIRepo extends FileRepo {
|
|||
}
|
||||
|
||||
/**
|
||||
* Like a Http:get request, but with custom User-Agent.
|
||||
* @see Http::get
|
||||
* Like a HttpRequestFactory::get request, but with custom User-Agent.
|
||||
* @see HttpRequestFactory::get
|
||||
* @todo Can this use HttpRequestFactory::get() but just pass the 'userAgent' option?
|
||||
* @param string $url
|
||||
* @param string $timeout
|
||||
* @param array $options
|
||||
|
|
|
|||
|
|
@ -2070,7 +2070,8 @@ abstract class File implements IDBAccessObject {
|
|||
$this->repo->descriptionCacheExpiry ?: $cache::TTL_UNCACHEABLE,
|
||||
function ( $oldValue, &$ttl, array &$setOpts ) use ( $renderUrl, $fname ) {
|
||||
wfDebug( "Fetching shared description from $renderUrl\n" );
|
||||
$res = Http::get( $renderUrl, [], $fname );
|
||||
$res = MediaWikiServices::getInstance()->getHttpRequestFactory()->
|
||||
get( $renderUrl, [], $fname );
|
||||
if ( !$res ) {
|
||||
$ttl = WANObjectCache::TTL_UNCACHEABLE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -165,7 +165,8 @@ class ForeignDBFile extends LocalFile {
|
|||
$this->repo->descriptionCacheExpiry ?: $cache::TTL_UNCACHEABLE,
|
||||
function ( $oldValue, &$ttl, array &$setOpts ) use ( $renderUrl, $fname ) {
|
||||
wfDebug( "Fetching shared description from $renderUrl\n" );
|
||||
$res = Http::get( $renderUrl, [], $fname );
|
||||
$res = MediaWikiServices::getInstance()->getHttpRequestFactory()->
|
||||
get( $renderUrl, [], $fname );
|
||||
if ( !$res ) {
|
||||
$ttl = WANObjectCache::TTL_UNCACHEABLE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,18 @@ class CurlHttpRequest extends MWHttpRequest {
|
|||
protected $curlOptions = [];
|
||||
protected $headerText = "";
|
||||
|
||||
/**
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function __construct() {
|
||||
if ( !function_exists( 'curl_init' ) ) {
|
||||
throw new RuntimeException(
|
||||
__METHOD__ . ': curl (https://www.php.net/curl) is not installed' );
|
||||
}
|
||||
|
||||
parent::__construct( ...func_get_args() );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param resource $fh
|
||||
* @param string $content
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ class GuzzleHttpRequest extends MWHttpRequest {
|
|||
|
||||
/**
|
||||
* @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 array $options (optional) extra params to pass (see HttpRequestFactory::create())
|
||||
* @param string $caller The method making this request, for profiling
|
||||
* @param Profiler|null $profiler An instance of the profiler for profiling, or null
|
||||
* @throws Exception
|
||||
|
|
|
|||
|
|
@ -19,74 +19,40 @@
|
|||
*/
|
||||
|
||||
use MediaWiki\Logger\LoggerFactory;
|
||||
use MediaWiki\MediaWikiServices;
|
||||
|
||||
/**
|
||||
* Various HTTP related functions
|
||||
* @deprecated since 1.34
|
||||
* @ingroup HTTP
|
||||
*/
|
||||
class Http {
|
||||
public static $httpEngine = false;
|
||||
/** @deprecated since 1.34, just use the default engine */
|
||||
public static $httpEngine = null;
|
||||
|
||||
/**
|
||||
* Perform an HTTP request
|
||||
*
|
||||
* @deprecated since 1.34, use HttpRequestFactory::request()
|
||||
*
|
||||
* @param string $method HTTP method. Usually GET/POST
|
||||
* @param string $url Full URL to act on. If protocol-relative, will be expanded to an http:// URL
|
||||
* @param array $options Options to pass to MWHttpRequest object.
|
||||
* Possible keys for the array:
|
||||
* - timeout Timeout length in seconds
|
||||
* - connectTimeout Timeout for connection, in seconds (curl only)
|
||||
* - postData An array of key-value pairs or a url-encoded form data
|
||||
* - proxy The proxy to use.
|
||||
* Otherwise it will use $wgHTTPProxy (if set)
|
||||
* Otherwise it will use the environment variable "http_proxy" (if set)
|
||||
* - noProxy Don't use any proxy at all. Takes precedence over proxy value(s).
|
||||
* - sslVerifyHost Verify hostname against certificate
|
||||
* - sslVerifyCert Verify SSL certificate
|
||||
* - caInfo Provide CA information
|
||||
* - maxRedirects Maximum number of redirects to follow (defaults to 5)
|
||||
* - followRedirects Whether to follow redirects (defaults to false).
|
||||
* Note: this should only be used when the target URL is trusted,
|
||||
* to avoid attacks on intranet services accessible by HTTP.
|
||||
* - userAgent A user agent, if you want to override the default
|
||||
* MediaWiki/$wgVersion
|
||||
* - logger A \Psr\Logger\LoggerInterface instance for debug logging
|
||||
* - username Username for HTTP Basic Authentication
|
||||
* - password Password for HTTP Basic Authentication
|
||||
* - originalRequest Information about the original request (as a WebRequest object or
|
||||
* an associative array with 'ip' and 'userAgent').
|
||||
* @param array $options Options to pass to MWHttpRequest object. See HttpRequestFactory::create
|
||||
* docs
|
||||
* @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, array $options = [], $caller = __METHOD__ ) {
|
||||
$logger = LoggerFactory::getInstance( 'http' );
|
||||
$logger->debug( "$method: $url" );
|
||||
|
||||
$options['method'] = strtoupper( $method );
|
||||
|
||||
if ( !isset( $options['timeout'] ) ) {
|
||||
$options['timeout'] = 'default';
|
||||
}
|
||||
if ( !isset( $options['connectTimeout'] ) ) {
|
||||
$options['connectTimeout'] = 'default';
|
||||
}
|
||||
|
||||
$req = MWHttpRequest::factory( $url, $options, $caller );
|
||||
$status = $req->execute();
|
||||
|
||||
if ( $status->isOK() ) {
|
||||
return $req->getContent();
|
||||
} else {
|
||||
$errors = $status->getErrorsByType( 'error' );
|
||||
$logger->warning( Status::wrap( $status )->getWikiText( false, false, 'en' ),
|
||||
[ 'error' => $errors, 'caller' => $caller, 'content' => $req->getContent() ] );
|
||||
return false;
|
||||
}
|
||||
$ret = MediaWikiServices::getInstance()->getHttpRequestFactory()->request(
|
||||
$method, $url, $options, $caller );
|
||||
return is_string( $ret ) ? $ret : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple wrapper for Http::request( 'GET' )
|
||||
* @see Http::request()
|
||||
*
|
||||
* @deprecated since 1.34, use HttpRequestFactory::get()
|
||||
*
|
||||
* @since 1.25 Second parameter $timeout removed. Second parameter
|
||||
* is now $options which can be given a 'timeout'
|
||||
*
|
||||
|
|
@ -111,7 +77,8 @@ class Http {
|
|||
|
||||
/**
|
||||
* Simple wrapper for Http::request( 'POST' )
|
||||
* @see Http::request()
|
||||
*
|
||||
* @deprecated since 1.34, use HttpRequestFactory::post()
|
||||
*
|
||||
* @param string $url
|
||||
* @param array $options
|
||||
|
|
@ -124,11 +91,12 @@ class Http {
|
|||
|
||||
/**
|
||||
* A standard user-agent we can use for external requests.
|
||||
*
|
||||
* @deprecated since 1.34, use HttpRequestFactory::getUserAgent()
|
||||
* @return string
|
||||
*/
|
||||
public static function userAgent() {
|
||||
global $wgVersion;
|
||||
return "MediaWiki/$wgVersion";
|
||||
return MediaWikiServices::getInstance()->getHttpRequestFactory()->getUserAgent();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -143,37 +111,37 @@ class Http {
|
|||
*
|
||||
* @todo FIXME this is wildly inaccurate and fails to actually check most stuff
|
||||
*
|
||||
* @deprecated since 1.34, use MWHttpRequest::isValidURI
|
||||
* @param string $uri URI to check for validity
|
||||
* @return bool
|
||||
*/
|
||||
public static function isValidURI( $uri ) {
|
||||
return (bool)preg_match(
|
||||
'/^https?:\/\/[^\/\s]\S*$/D',
|
||||
$uri
|
||||
);
|
||||
return MWHttpRequest::isValidURI( $uri );
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the relevant proxy from $wgHTTPProxy
|
||||
*
|
||||
* @return mixed The proxy address or an empty string if not set.
|
||||
* @deprecated since 1.34, use $wgHTTPProxy directly
|
||||
* @return string The proxy address or an empty string if not set.
|
||||
*/
|
||||
public static function getProxy() {
|
||||
wfDeprecated( __METHOD__, '1.34' );
|
||||
|
||||
global $wgHTTPProxy;
|
||||
|
||||
if ( $wgHTTPProxy ) {
|
||||
return $wgHTTPProxy;
|
||||
}
|
||||
|
||||
return "";
|
||||
return (string)$wgHTTPProxy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a configured MultiHttpClient
|
||||
*
|
||||
* @deprecated since 1.34, construct it directly
|
||||
* @param array $options
|
||||
* @return MultiHttpClient
|
||||
*/
|
||||
public static function createMultiClient( array $options = [] ) {
|
||||
wfDeprecated( __METHOD__, '1.34' );
|
||||
|
||||
global $wgHTTPConnectTimeout, $wgHTTPTimeout, $wgHTTPProxy;
|
||||
|
||||
return new MultiHttpClient( $options + [
|
||||
|
|
|
|||
|
|
@ -20,34 +20,52 @@
|
|||
namespace MediaWiki\Http;
|
||||
|
||||
use CurlHttpRequest;
|
||||
use DomainException;
|
||||
use GuzzleHttpRequest;
|
||||
use Http;
|
||||
use MediaWiki\Logger\LoggerFactory;
|
||||
use MWHttpRequest;
|
||||
use PhpHttpRequest;
|
||||
use Profiler;
|
||||
use GuzzleHttpRequest;
|
||||
use RuntimeException;
|
||||
use Status;
|
||||
|
||||
/**
|
||||
* Factory creating MWHttpRequest objects.
|
||||
*/
|
||||
class HttpRequestFactory {
|
||||
|
||||
/**
|
||||
* Generate a new MWHttpRequest object
|
||||
* @param string $url Url to use
|
||||
* @param array $options (optional) extra params to pass (see Http::request())
|
||||
* @param array $options Possible keys for the array:
|
||||
* - timeout Timeout length in seconds
|
||||
* - connectTimeout Timeout for connection, in seconds (curl only)
|
||||
* - postData An array of key-value pairs or a url-encoded form data
|
||||
* - proxy The proxy to use.
|
||||
* Otherwise it will use $wgHTTPProxy (if set)
|
||||
* Otherwise it will use the environment variable "http_proxy" (if set)
|
||||
* - noProxy Don't use any proxy at all. Takes precedence over proxy value(s).
|
||||
* - sslVerifyHost Verify hostname against certificate
|
||||
* - sslVerifyCert Verify SSL certificate
|
||||
* - caInfo Provide CA information
|
||||
* - maxRedirects Maximum number of redirects to follow (defaults to 5)
|
||||
* - followRedirects Whether to follow redirects (defaults to false).
|
||||
* Note: this should only be used when the target URL is trusted,
|
||||
* to avoid attacks on intranet services accessible by HTTP.
|
||||
* - userAgent A user agent, if you want to override the default
|
||||
* MediaWiki/$wgVersion
|
||||
* - logger A \Psr\Logger\LoggerInterface instance for debug logging
|
||||
* - username Username for HTTP Basic Authentication
|
||||
* - password Password for HTTP Basic Authentication
|
||||
* - originalRequest Information about the original request (as a WebRequest object or
|
||||
* an associative array with 'ip' and 'userAgent').
|
||||
* @param string $caller The method making this request, for profiling
|
||||
* @throws DomainException
|
||||
* @throws RuntimeException
|
||||
* @return MWHttpRequest
|
||||
* @see MWHttpRequest::__construct
|
||||
*/
|
||||
public function create( $url, array $options = [], $caller = __METHOD__ ) {
|
||||
if ( !Http::$httpEngine ) {
|
||||
Http::$httpEngine = 'guzzle';
|
||||
} elseif ( Http::$httpEngine == 'curl' && !function_exists( 'curl_init' ) ) {
|
||||
throw new DomainException( __METHOD__ . ': curl (https://www.php.net/curl) is not ' .
|
||||
'installed, but Http::$httpEngine is set to "curl"' );
|
||||
}
|
||||
|
||||
if ( !isset( $options['logger'] ) ) {
|
||||
|
|
@ -60,16 +78,9 @@ class HttpRequestFactory {
|
|||
case 'curl':
|
||||
return new CurlHttpRequest( $url, $options, $caller, Profiler::instance() );
|
||||
case 'php':
|
||||
if ( !wfIniGetBool( 'allow_url_fopen' ) ) {
|
||||
throw new DomainException( __METHOD__ . ': allow_url_fopen ' .
|
||||
'needs to be enabled for pure PHP http requests to ' .
|
||||
'work. If possible, curl should be used instead. See ' .
|
||||
'https://www.php.net/curl.'
|
||||
);
|
||||
}
|
||||
return new PhpHttpRequest( $url, $options, $caller, Profiler::instance() );
|
||||
default:
|
||||
throw new DomainException( __METHOD__ . ': The setting of Http::$httpEngine is not valid.' );
|
||||
throw new RuntimeException( __METHOD__ . ': The requested engine is not valid.' );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -82,4 +93,75 @@ class HttpRequestFactory {
|
|||
return function_exists( 'curl_init' ) || wfIniGetBool( 'allow_url_fopen' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform an HTTP request
|
||||
*
|
||||
* @since 1.34
|
||||
* @param string $method HTTP method. Usually GET/POST
|
||||
* @param string $url Full URL to act on. If protocol-relative, will be expanded to an http://
|
||||
* URL
|
||||
* @param array $options See HttpRequestFactory::create
|
||||
* @param string $caller The method making this request, for profiling
|
||||
* @return string|null null on failure or a string on success
|
||||
*/
|
||||
public function request( $method, $url, array $options = [], $caller = __METHOD__ ) {
|
||||
$logger = LoggerFactory::getInstance( 'http' );
|
||||
$logger->debug( "$method: $url" );
|
||||
|
||||
$options['method'] = strtoupper( $method );
|
||||
|
||||
if ( !isset( $options['timeout'] ) ) {
|
||||
$options['timeout'] = 'default';
|
||||
}
|
||||
if ( !isset( $options['connectTimeout'] ) ) {
|
||||
$options['connectTimeout'] = 'default';
|
||||
}
|
||||
|
||||
$req = $this->create( $url, $options, $caller );
|
||||
$status = $req->execute();
|
||||
|
||||
if ( $status->isOK() ) {
|
||||
return $req->getContent();
|
||||
} else {
|
||||
$errors = $status->getErrorsByType( 'error' );
|
||||
$logger->warning( Status::wrap( $status )->getWikiText( false, false, 'en' ),
|
||||
[ 'error' => $errors, 'caller' => $caller, 'content' => $req->getContent() ] );
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple wrapper for request( 'GET' ), parameters have same meaning as for request()
|
||||
*
|
||||
* @since 1.34
|
||||
* @param string $url
|
||||
* @param array $options
|
||||
* @param string $caller
|
||||
* @return string|null
|
||||
*/
|
||||
public function get( $url, array $options = [], $caller = __METHOD__ ) {
|
||||
$this->request( 'GET', $url, $options, $caller );
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple wrapper for request( 'POST' ), parameters have same meaning as for request()
|
||||
*
|
||||
* @since 1.34
|
||||
* @param string $url
|
||||
* @param array $options
|
||||
* @param string $caller
|
||||
* @return string|null
|
||||
*/
|
||||
public function post( $url, array $options = [], $caller = __METHOD__ ) {
|
||||
$this->request( 'POST', $url, $options, $caller );
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getUserAgent() {
|
||||
global $wgVersion;
|
||||
|
||||
return "MediaWiki/$wgVersion";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ abstract class MWHttpRequest implements LoggerAwareInterface {
|
|||
|
||||
/**
|
||||
* @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 array $options (optional) extra params to pass (see HttpRequestFactory::create())
|
||||
* @param string $caller The method making this request, for profiling
|
||||
* @param Profiler|null $profiler An instance of the profiler for profiling, or null
|
||||
* @throws Exception
|
||||
|
|
@ -172,9 +172,9 @@ abstract class MWHttpRequest implements LoggerAwareInterface {
|
|||
|
||||
/**
|
||||
* Generate a new request object
|
||||
* Deprecated: @see HttpRequestFactory::create
|
||||
* @deprecated since 1.34, use HttpRequestFactory instead
|
||||
* @param string $url Url to use
|
||||
* @param array|null $options (optional) extra params to pass (see Http::request())
|
||||
* @param array|null $options (optional) extra params to pass (see HttpRequestFactory::create())
|
||||
* @param string $caller The method making this request, for profiling
|
||||
* @throws DomainException
|
||||
* @return MWHttpRequest
|
||||
|
|
@ -224,7 +224,8 @@ abstract class MWHttpRequest implements LoggerAwareInterface {
|
|||
if ( self::isLocalURL( $this->url ) || $this->noProxy ) {
|
||||
$this->proxy = '';
|
||||
} else {
|
||||
$this->proxy = Http::getProxy();
|
||||
global $wgHTTPProxy;
|
||||
$this->proxy = (string)$wgHTTPProxy;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -662,4 +663,27 @@ abstract class MWHttpRequest implements LoggerAwareInterface {
|
|||
$this->reqHeaders['X-Forwarded-For'] = $originalRequest['ip'];
|
||||
$this->reqHeaders['X-Original-User-Agent'] = $originalRequest['userAgent'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the given URI is a valid one.
|
||||
*
|
||||
* This hardcodes a small set of protocols only, because we want to
|
||||
* deterministically reject protocols not supported by all HTTP-transport
|
||||
* methods.
|
||||
*
|
||||
* "file://" specifically must not be allowed, for security reasons
|
||||
* (see <https://www.mediawiki.org/wiki/Special:Code/MediaWiki/r67684>).
|
||||
*
|
||||
* @todo FIXME this is wildly inaccurate and fails to actually check most stuff
|
||||
*
|
||||
* @since 1.34
|
||||
* @param string $uri URI to check for validity
|
||||
* @return bool
|
||||
*/
|
||||
public static function isValidURI( $uri ) {
|
||||
return (bool)preg_match(
|
||||
'/^https?:\/\/[^\/\s]\S*$/D',
|
||||
$uri
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,17 @@ class PhpHttpRequest extends MWHttpRequest {
|
|||
|
||||
private $fopenErrors = [];
|
||||
|
||||
public function __construct() {
|
||||
if ( !wfIniGetBool( 'allow_url_fopen' ) ) {
|
||||
throw new RuntimeException( __METHOD__ . ': allow_url_fopen needs to be enabled for ' .
|
||||
'pure PHP http requests to work. If possible, curl should be used instead. See ' .
|
||||
'https://www.php.net/curl.'
|
||||
);
|
||||
}
|
||||
|
||||
parent::__construct( ...func_get_args() );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $url
|
||||
* @return string
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ class ImportStreamSource implements ImportSource {
|
|||
# quicker and sorts out user-agent problems which might
|
||||
# otherwise prevent importing from large sites, such
|
||||
# as the Wikimedia cluster, etc.
|
||||
$data = Http::request(
|
||||
$data = MediaWikiServices::getInstance()->getHttpRequestFactory()->request(
|
||||
$method,
|
||||
$url,
|
||||
[
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
<?php
|
||||
|
||||
use MediaWiki\MediaWikiServices;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
/**
|
||||
|
|
@ -159,7 +160,8 @@ class ImportableUploadRevisionImporter implements UploadRevisionImporter {
|
|||
|
||||
// @todo FIXME!
|
||||
$src = $wikiRevision->getSrc();
|
||||
$data = Http::get( $src, [], __METHOD__ );
|
||||
$data = MediaWikiServices::getInstance()->getHttpRequestFactory()->
|
||||
get( $src, [], __METHOD__ );
|
||||
if ( !$data ) {
|
||||
$this->logger->debug( "IMPORT: couldn't fetch source $src\n" );
|
||||
fclose( $f );
|
||||
|
|
|
|||
|
|
@ -1203,9 +1203,11 @@ abstract class Installer {
|
|||
}
|
||||
|
||||
try {
|
||||
$text = Http::get( $url . $file, [ 'timeout' => 3 ], __METHOD__ );
|
||||
$text = MediaWikiServices::getInstance()->getHttpRequestFactory()->
|
||||
get( $url . $file, [ 'timeout' => 3 ], __METHOD__ );
|
||||
} catch ( Exception $e ) {
|
||||
// Http::get throws with allow_url_fopen = false and no curl extension.
|
||||
// HttpRequestFactory::get can throw with allow_url_fopen = false and no curl
|
||||
// extension.
|
||||
$text = null;
|
||||
}
|
||||
unlink( $dir . $file );
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@
|
|||
* @author Platonides
|
||||
*/
|
||||
|
||||
use MediaWiki\MediaWikiServices;
|
||||
|
||||
require_once __DIR__ . '/Benchmarker.php';
|
||||
|
||||
/**
|
||||
|
|
@ -45,7 +47,8 @@ class BenchHttpHttps extends Benchmarker {
|
|||
}
|
||||
|
||||
private function doRequest( $proto ) {
|
||||
Http::get( "$proto://localhost/", [], __METHOD__ );
|
||||
MediaWikiServices::getInstance()->getHttpRequestFactory()->
|
||||
get( "$proto://localhost/", [], __METHOD__ );
|
||||
}
|
||||
|
||||
// bench function 1
|
||||
|
|
|
|||
|
|
@ -34,6 +34,8 @@
|
|||
* @author Antoine Musso <hashar at free dot fr>
|
||||
*/
|
||||
|
||||
use MediaWiki\MediaWikiServices;
|
||||
|
||||
require_once __DIR__ . '/Maintenance.php';
|
||||
|
||||
/**
|
||||
|
|
@ -216,7 +218,7 @@ class FindHooks extends Maintenance {
|
|||
|
||||
$retval = [];
|
||||
while ( true ) {
|
||||
$json = Http::get(
|
||||
$json = MediaWikiServices::getInstance()->getHttpRequestFactory()->get(
|
||||
wfAppendQuery( 'https://www.mediawiki.org/w/api.php', $params ),
|
||||
[],
|
||||
__METHOD__
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@
|
|||
* @ingroup Maintenance
|
||||
*/
|
||||
|
||||
use MediaWiki\MediaWikiServices;
|
||||
|
||||
require_once __DIR__ . '/Maintenance.php';
|
||||
|
||||
/**
|
||||
|
|
@ -64,7 +66,8 @@ class ImportSiteScripts extends Maintenance {
|
|||
$url = wfAppendQuery( $baseUrl, [
|
||||
'action' => 'raw',
|
||||
'title' => "MediaWiki:{$page}" ] );
|
||||
$text = Http::get( $url, [], __METHOD__ );
|
||||
$text = MediaWikiServices::getInstance()->getHttpRequestFactory()->
|
||||
get( $url, [], __METHOD__ );
|
||||
|
||||
$wikiPage = WikiPage::factory( $title );
|
||||
$content = ContentHandler::makeContent( $text, $wikiPage->getTitle() );
|
||||
|
|
@ -86,7 +89,8 @@ class ImportSiteScripts extends Maintenance {
|
|||
|
||||
while ( true ) {
|
||||
$url = wfAppendQuery( $baseUrl, $data );
|
||||
$strResult = Http::get( $url, [], __METHOD__ );
|
||||
$strResult = MediaWikiServices::getInstance()->getHttpRequestFactory()->
|
||||
get( $url, [], __METHOD__ );
|
||||
$result = FormatJson::decode( $strResult, true );
|
||||
|
||||
$page = null;
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ TEXT
|
|||
$url = rtrim( $this->source, '?' ) . '?' . $url;
|
||||
}
|
||||
|
||||
$json = Http::get( $url );
|
||||
$json = MediaWikiServices::getInstance()->getHttpRequestFactory()->get( $url );
|
||||
$data = json_decode( $json, true );
|
||||
|
||||
if ( is_array( $data ) ) {
|
||||
|
|
|
|||
|
|
@ -1,19 +1,25 @@
|
|||
<?php
|
||||
|
||||
use MediaWiki\MediaWikiServices;
|
||||
use Wikimedia\TestingAccessWrapper;
|
||||
|
||||
abstract class MWHttpRequestTestCase extends PHPUnit\Framework\TestCase {
|
||||
protected static $httpEngine;
|
||||
protected $oldHttpEngine;
|
||||
|
||||
/** @var HttpRequestFactory */
|
||||
private $factory;
|
||||
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
$this->oldHttpEngine = Http::$httpEngine;
|
||||
Http::$httpEngine = static::$httpEngine;
|
||||
|
||||
$this->factory = MediaWikiServices::getInstance()->getHttpRequestFactory();
|
||||
|
||||
try {
|
||||
$request = MWHttpRequest::factory( 'null:' );
|
||||
} catch ( DomainException $e ) {
|
||||
$request = $factory->create( 'null:' );
|
||||
} catch ( RuntimeException $e ) {
|
||||
$this->markTestSkipped( static::$httpEngine . ' engine not supported' );
|
||||
}
|
||||
|
||||
|
|
@ -32,19 +38,19 @@ abstract class MWHttpRequestTestCase extends PHPUnit\Framework\TestCase {
|
|||
// --------------------
|
||||
|
||||
public function testIsRedirect() {
|
||||
$request = MWHttpRequest::factory( 'http://httpbin.org/get' );
|
||||
$request = $this->factory->create( 'http://httpbin.org/get' );
|
||||
$status = $request->execute();
|
||||
$this->assertTrue( $status->isGood() );
|
||||
$this->assertFalse( $request->isRedirect() );
|
||||
|
||||
$request = MWHttpRequest::factory( 'http://httpbin.org/redirect/1' );
|
||||
$request = $this->factory->create( 'http://httpbin.org/redirect/1' );
|
||||
$status = $request->execute();
|
||||
$this->assertTrue( $status->isGood() );
|
||||
$this->assertTrue( $request->isRedirect() );
|
||||
}
|
||||
|
||||
public function testgetFinalUrl() {
|
||||
$request = MWHttpRequest::factory( 'http://httpbin.org/redirect/3' );
|
||||
$request = $this->factory->create( 'http://httpbin.org/redirect/3' );
|
||||
if ( !$request->canFollowRedirects() ) {
|
||||
$this->markTestSkipped( 'cannot follow redirects' );
|
||||
}
|
||||
|
|
@ -52,14 +58,14 @@ abstract class MWHttpRequestTestCase extends PHPUnit\Framework\TestCase {
|
|||
$this->assertTrue( $status->isGood() );
|
||||
$this->assertNotSame( 'http://httpbin.org/get', $request->getFinalUrl() );
|
||||
|
||||
$request = MWHttpRequest::factory( 'http://httpbin.org/redirect/3', [ 'followRedirects'
|
||||
$request = $this->factory->create( 'http://httpbin.org/redirect/3', [ 'followRedirects'
|
||||
=> true ] );
|
||||
$status = $request->execute();
|
||||
$this->assertTrue( $status->isGood() );
|
||||
$this->assertSame( 'http://httpbin.org/get', $request->getFinalUrl() );
|
||||
$this->assertResponseFieldValue( 'url', 'http://httpbin.org/get', $request );
|
||||
|
||||
$request = MWHttpRequest::factory( 'http://httpbin.org/redirect/3', [ 'followRedirects'
|
||||
$request = $this->factory->create( 'http://httpbin.org/redirect/3', [ 'followRedirects'
|
||||
=> true ] );
|
||||
$status = $request->execute();
|
||||
$this->assertTrue( $status->isGood() );
|
||||
|
|
@ -71,7 +77,7 @@ abstract class MWHttpRequestTestCase extends PHPUnit\Framework\TestCase {
|
|||
return;
|
||||
}
|
||||
|
||||
$request = MWHttpRequest::factory( 'http://httpbin.org/redirect/3', [ 'followRedirects'
|
||||
$request = $this->factory->create( 'http://httpbin.org/redirect/3', [ 'followRedirects'
|
||||
=> true, 'maxRedirects' => 1 ] );
|
||||
$status = $request->execute();
|
||||
$this->assertTrue( $status->isGood() );
|
||||
|
|
@ -79,7 +85,7 @@ abstract class MWHttpRequestTestCase extends PHPUnit\Framework\TestCase {
|
|||
}
|
||||
|
||||
public function testSetCookie() {
|
||||
$request = MWHttpRequest::factory( 'http://httpbin.org/cookies' );
|
||||
$request = $this->factory->create( 'http://httpbin.org/cookies' );
|
||||
$request->setCookie( 'foo', 'bar' );
|
||||
$request->setCookie( 'foo2', 'bar2', [ 'domain' => 'example.com' ] );
|
||||
$status = $request->execute();
|
||||
|
|
@ -88,7 +94,7 @@ abstract class MWHttpRequestTestCase extends PHPUnit\Framework\TestCase {
|
|||
}
|
||||
|
||||
public function testSetCookieJar() {
|
||||
$request = MWHttpRequest::factory( 'http://httpbin.org/cookies' );
|
||||
$request = $this->factory->create( 'http://httpbin.org/cookies' );
|
||||
$cookieJar = new CookieJar();
|
||||
$cookieJar->setCookie( 'foo', 'bar', [ 'domain' => 'httpbin.org' ] );
|
||||
$cookieJar->setCookie( 'foo2', 'bar2', [ 'domain' => 'example.com' ] );
|
||||
|
|
@ -97,7 +103,7 @@ abstract class MWHttpRequestTestCase extends PHPUnit\Framework\TestCase {
|
|||
$this->assertTrue( $status->isGood() );
|
||||
$this->assertResponseFieldValue( 'cookies', [ 'foo' => 'bar' ], $request );
|
||||
|
||||
$request = MWHttpRequest::factory( 'http://httpbin.org/cookies/set?foo=bar' );
|
||||
$request = $this->factory->create( 'http://httpbin.org/cookies/set?foo=bar' );
|
||||
$cookieJar = new CookieJar();
|
||||
$request->setCookieJar( $cookieJar );
|
||||
$status = $request->execute();
|
||||
|
|
@ -106,7 +112,7 @@ abstract class MWHttpRequestTestCase extends PHPUnit\Framework\TestCase {
|
|||
|
||||
$this->markTestIncomplete( 'CookieJar does not handle deletion' );
|
||||
|
||||
// $request = MWHttpRequest::factory( 'http://httpbin.org/cookies/delete?foo' );
|
||||
// $request = $this->factory->create( 'http://httpbin.org/cookies/delete?foo' );
|
||||
// $cookieJar = new CookieJar();
|
||||
// $cookieJar->setCookie( 'foo', 'bar', [ 'domain' => 'httpbin.org' ] );
|
||||
// $cookieJar->setCookie( 'foo2', 'bar2', [ 'domain' => 'httpbin.org' ] );
|
||||
|
|
@ -118,7 +124,7 @@ abstract class MWHttpRequestTestCase extends PHPUnit\Framework\TestCase {
|
|||
}
|
||||
|
||||
public function testGetResponseHeaders() {
|
||||
$request = MWHttpRequest::factory( 'http://httpbin.org/response-headers?Foo=bar' );
|
||||
$request = $this->factory->create( 'http://httpbin.org/response-headers?Foo=bar' );
|
||||
$status = $request->execute();
|
||||
$this->assertTrue( $status->isGood() );
|
||||
$headers = array_change_key_case( $request->getResponseHeaders(), CASE_LOWER );
|
||||
|
|
@ -127,7 +133,7 @@ abstract class MWHttpRequestTestCase extends PHPUnit\Framework\TestCase {
|
|||
}
|
||||
|
||||
public function testSetHeader() {
|
||||
$request = MWHttpRequest::factory( 'http://httpbin.org/headers' );
|
||||
$request = $this->factory->create( 'http://httpbin.org/headers' );
|
||||
$request->setHeader( 'Foo', 'bar' );
|
||||
$status = $request->execute();
|
||||
$this->assertTrue( $status->isGood() );
|
||||
|
|
@ -135,14 +141,14 @@ abstract class MWHttpRequestTestCase extends PHPUnit\Framework\TestCase {
|
|||
}
|
||||
|
||||
public function testGetStatus() {
|
||||
$request = MWHttpRequest::factory( 'http://httpbin.org/status/418' );
|
||||
$request = $this->factory->create( 'http://httpbin.org/status/418' );
|
||||
$status = $request->execute();
|
||||
$this->assertFalse( $status->isOK() );
|
||||
$this->assertSame( $request->getStatus(), 418 );
|
||||
}
|
||||
|
||||
public function testSetUserAgent() {
|
||||
$request = MWHttpRequest::factory( 'http://httpbin.org/user-agent' );
|
||||
$request = $this->factory->create( 'http://httpbin.org/user-agent' );
|
||||
$request->setUserAgent( 'foo' );
|
||||
$status = $request->execute();
|
||||
$this->assertTrue( $status->isGood() );
|
||||
|
|
@ -150,7 +156,7 @@ abstract class MWHttpRequestTestCase extends PHPUnit\Framework\TestCase {
|
|||
}
|
||||
|
||||
public function testSetData() {
|
||||
$request = MWHttpRequest::factory( 'http://httpbin.org/post', [ 'method' => 'POST' ] );
|
||||
$request = $this->factory->create( 'http://httpbin.org/post', [ 'method' => 'POST' ] );
|
||||
$request->setData( [ 'foo' => 'bar', 'foo2' => 'bar2' ] );
|
||||
$status = $request->execute();
|
||||
$this->assertTrue( $status->isGood() );
|
||||
|
|
@ -163,7 +169,7 @@ abstract class MWHttpRequestTestCase extends PHPUnit\Framework\TestCase {
|
|||
return;
|
||||
}
|
||||
|
||||
$request = MWHttpRequest::factory( 'http://httpbin.org/ip' );
|
||||
$request = $this->factory->create( 'http://httpbin.org/ip' );
|
||||
$data = '';
|
||||
$request->setCallback( function ( $fh, $content ) use ( &$data ) {
|
||||
$data .= $content;
|
||||
|
|
@ -177,7 +183,7 @@ abstract class MWHttpRequestTestCase extends PHPUnit\Framework\TestCase {
|
|||
}
|
||||
|
||||
public function testBasicAuthentication() {
|
||||
$request = MWHttpRequest::factory( 'http://httpbin.org/basic-auth/user/pass', [
|
||||
$request = $this->factory->create( 'http://httpbin.org/basic-auth/user/pass', [
|
||||
'username' => 'user',
|
||||
'password' => 'pass',
|
||||
] );
|
||||
|
|
@ -185,7 +191,7 @@ abstract class MWHttpRequestTestCase extends PHPUnit\Framework\TestCase {
|
|||
$this->assertTrue( $status->isGood() );
|
||||
$this->assertResponseFieldValue( 'authenticated', true, $request );
|
||||
|
||||
$request = MWHttpRequest::factory( 'http://httpbin.org/basic-auth/user/pass', [
|
||||
$request = $this->factory->create( 'http://httpbin.org/basic-auth/user/pass', [
|
||||
'username' => 'user',
|
||||
'password' => 'wrongpass',
|
||||
] );
|
||||
|
|
@ -195,7 +201,7 @@ abstract class MWHttpRequestTestCase extends PHPUnit\Framework\TestCase {
|
|||
}
|
||||
|
||||
public function testFactoryDefaults() {
|
||||
$request = MWHttpRequest::factory( 'http://acme.test' );
|
||||
$request = $this->factory->create( 'http://acme.test' );
|
||||
$this->assertInstanceOf( MWHttpRequest::class, $request );
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
<?php
|
||||
|
||||
use MediaWiki\MediaWikiServices;
|
||||
use Wikimedia\TestingAccessWrapper;
|
||||
|
||||
/**
|
||||
|
|
@ -1538,7 +1539,8 @@ class FileBackendTest extends MediaWikiTestCase {
|
|||
$url = $this->backend->getFileHttpUrl( [ 'src' => $source ] );
|
||||
|
||||
if ( $url !== null ) { // supported
|
||||
$data = Http::request( "GET", $url, [], __METHOD__ );
|
||||
$data = MediaWikiServices::getInstance()->getHttpRequestFactory()->
|
||||
get( $url, [], __METHOD__ );
|
||||
$this->assertEquals( $content, $data,
|
||||
"HTTP GET of URL has right contents ($backendName)." );
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,6 +67,8 @@ class HttpTest extends MediaWikiTestCase {
|
|||
* @covers Http::getProxy
|
||||
*/
|
||||
public function testGetProxy() {
|
||||
$this->hideDeprecated( 'Http::getProxy' );
|
||||
|
||||
$this->setMwGlobals( 'wgHTTPProxy', false );
|
||||
$this->assertEquals(
|
||||
'',
|
||||
|
|
|
|||
Loading…
Reference in a new issue