Merge "Allow using a reverse proxy for local HTTP requests"
This commit is contained in:
commit
93821348aa
3 changed files with 57 additions and 4 deletions
|
|
@ -9675,6 +9675,8 @@ $wgHTTPProxy = '';
|
||||||
* Local virtual hosts.
|
* Local virtual hosts.
|
||||||
*
|
*
|
||||||
* This lists domains that are configured as virtual hosts on the same machine.
|
* This lists domains that are configured as virtual hosts on the same machine.
|
||||||
|
* It is expected that each domain can be identified by its hostname alone,
|
||||||
|
* without any ports.
|
||||||
*
|
*
|
||||||
* This affects the following:
|
* This affects the following:
|
||||||
* - MWHttpRequest: If a request is to be made to a domain listed here, or any
|
* - MWHttpRequest: If a request is to be made to a domain listed here, or any
|
||||||
|
|
@ -9687,12 +9689,16 @@ $wgHTTPProxy = '';
|
||||||
$wgLocalVirtualHosts = [];
|
$wgLocalVirtualHosts = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Proxy to use to requests to domains in $wgLocalVirtualHosts
|
* Reverse proxy to use for requests to domains in $wgLocalVirtualHosts
|
||||||
*
|
*
|
||||||
* If set to false, no proxy will be used for local requests
|
* When used, any port in the request URL will be dropped. The behavior of
|
||||||
|
* redirects and cookies is dependent upon the reverse proxy actually in use,
|
||||||
|
* as MediaWiki doesn't implement any special handling for them.
|
||||||
|
*
|
||||||
|
* If set to false, no reverse proxy will be used for local requests.
|
||||||
*
|
*
|
||||||
* @var string|bool
|
* @var string|bool
|
||||||
* @since 1.37
|
* @since 1.38
|
||||||
*/
|
*/
|
||||||
$wgLocalHTTPProxy = false;
|
$wgLocalHTTPProxy = false;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -239,12 +239,47 @@ abstract class MWHttpRequest implements LoggerAwareInterface {
|
||||||
// Otherwise, fallback to $wgLocalHTTPProxy for local URLs
|
// Otherwise, fallback to $wgLocalHTTPProxy for local URLs
|
||||||
// or $wgHTTPProxy for everything else
|
// or $wgHTTPProxy for everything else
|
||||||
if ( self::isLocalURL( $this->url ) ) {
|
if ( self::isLocalURL( $this->url ) ) {
|
||||||
$this->proxy = (string)$wgLocalHTTPProxy;
|
if ( $wgLocalHTTPProxy !== false ) {
|
||||||
|
$this->setReverseProxy( $wgLocalHTTPProxy );
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
$this->proxy = (string)$wgHTTPProxy;
|
$this->proxy = (string)$wgHTTPProxy;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable use of a reverse proxy in which the hostname is
|
||||||
|
* passed as a "Host" header, and the request is sent to the
|
||||||
|
* proxy's host:port instead.
|
||||||
|
*
|
||||||
|
* Note that any custom port in the request URL will be lost
|
||||||
|
* and cookies and redirects may not work properly.
|
||||||
|
*
|
||||||
|
* @param string $proxy URL of proxy
|
||||||
|
*/
|
||||||
|
protected function setReverseProxy( string $proxy ) {
|
||||||
|
$parsedProxy = wfParseUrl( $proxy );
|
||||||
|
if ( $parsedProxy === false ) {
|
||||||
|
throw new Exception( "Invalid reverseProxy configured: $proxy" );
|
||||||
|
}
|
||||||
|
// Set the current host in the Host header
|
||||||
|
$this->setHeader( 'Host', $this->parsedUrl['host'] );
|
||||||
|
// Set current protocol in X-Forwarded-Proto
|
||||||
|
// TODO: consider supporting the standardized "Forwarded" header too
|
||||||
|
$this->setHeader( 'X-Forwarded-Proto', $this->parsedUrl['scheme'] );
|
||||||
|
// Replace scheme, host and port in the request
|
||||||
|
$this->parsedUrl['scheme'] = $parsedProxy['scheme'];
|
||||||
|
$this->parsedUrl['host'] = $parsedProxy['host'];
|
||||||
|
if ( isset( $parsedProxy['port'] ) ) {
|
||||||
|
$this->parsedUrl['port'] = $parsedProxy['port'];
|
||||||
|
} else {
|
||||||
|
unset( $this->parsedUrl['port'] );
|
||||||
|
}
|
||||||
|
$this->url = wfAssembleUrl( $this->parsedUrl );
|
||||||
|
// Mark that we're already using a proxy
|
||||||
|
$this->noProxy = true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the URL can be served by localhost
|
* Check if the URL can be served by localhost
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use Wikimedia\TestingAccessWrapper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @covers MWHttpRequest
|
* @covers MWHttpRequest
|
||||||
*/
|
*/
|
||||||
|
|
@ -85,4 +87,14 @@ class MWHttpRequestTest extends PHPUnit\Framework\TestCase {
|
||||||
$this->assertSame( $expect, MWHttpRequest::isValidURI( $uri ), $message );
|
$this->assertSame( $expect, MWHttpRequest::isValidURI( $uri ), $message );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testSetReverseProxy() {
|
||||||
|
$req = TestingAccessWrapper::newFromObject(
|
||||||
|
MWHttpRequest::factory( 'https://example.org/path?query=string' )
|
||||||
|
);
|
||||||
|
$req->setReverseProxy( 'http://localhost:1234' );
|
||||||
|
$this->assertSame( $req->url, 'http://localhost:1234/path?query=string' );
|
||||||
|
$this->assertSame( $req->reqHeaders['Host'], 'example.org' );
|
||||||
|
$this->assertSame( $req->reqHeaders['X-Forwarded-Proto'], 'https' );
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue