Merge pull request #17684 from mlatief/support-no-proxy
Add support for GuzzleHTTP 'no' proxy
This commit is contained in:
commit
6675f9b403
|
@ -524,6 +524,12 @@ $CONFIG = array(
|
||||||
/**
|
/**
|
||||||
* The URL of your proxy server, for example ``proxy.example.com:8081``.
|
* The URL of your proxy server, for example ``proxy.example.com:8081``.
|
||||||
*
|
*
|
||||||
|
* Note: Guzzle (the http library used by Nextcloud) is reading the environment
|
||||||
|
* variables HTTP_PROXY (only for cli request), HTTPS_PROXY, and NO_PROXY by default.
|
||||||
|
*
|
||||||
|
* If you configure proxy with Nextcloud any default configuration by Guzzle
|
||||||
|
* is overwritten. Make sure to set ``proxyexclude`` accordingly if necessary.
|
||||||
|
*
|
||||||
* Defaults to ``''`` (empty string)
|
* Defaults to ``''`` (empty string)
|
||||||
*/
|
*/
|
||||||
'proxy' => '',
|
'proxy' => '',
|
||||||
|
@ -536,6 +542,16 @@ $CONFIG = array(
|
||||||
*/
|
*/
|
||||||
'proxyuserpwd' => '',
|
'proxyuserpwd' => '',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of host names that should not be proxied to.
|
||||||
|
* For example: ``['.mit.edu', 'foo.com']``.
|
||||||
|
*
|
||||||
|
* Hint: Use something like ``explode(',', getenv('NO_PROXY'))`` to sync this
|
||||||
|
* value with the global NO_PROXY option.
|
||||||
|
*
|
||||||
|
* Defaults to empty array.
|
||||||
|
*/
|
||||||
|
'proxyexclude' => [],
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deleted Items (trash bin)
|
* Deleted Items (trash bin)
|
||||||
|
|
|
@ -65,12 +65,20 @@ class Client implements IClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
private function buildRequestOptions(array $options): array {
|
private function buildRequestOptions(array $options): array {
|
||||||
|
$proxy = $this->getProxyUri();
|
||||||
|
|
||||||
$defaults = [
|
$defaults = [
|
||||||
RequestOptions::PROXY => $this->getProxyUri(),
|
|
||||||
RequestOptions::VERIFY => $this->getCertBundle(),
|
RequestOptions::VERIFY => $this->getCertBundle(),
|
||||||
RequestOptions::TIMEOUT => 30,
|
RequestOptions::TIMEOUT => 30,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// Only add RequestOptions::PROXY if Nextcloud is explicitly
|
||||||
|
// configured to use a proxy. This is needed in order not to override
|
||||||
|
// Guzzle default values.
|
||||||
|
if($proxy !== null) {
|
||||||
|
$defaults[RequestOptions::PROXY] = $proxy;
|
||||||
|
}
|
||||||
|
|
||||||
$options = array_merge($defaults, $options);
|
$options = array_merge($defaults, $options);
|
||||||
|
|
||||||
if (!isset($options[RequestOptions::HEADERS]['User-Agent'])) {
|
if (!isset($options[RequestOptions::HEADERS]['User-Agent'])) {
|
||||||
|
@ -96,11 +104,21 @@ class Client implements IClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the proxy URI
|
* Returns a null or an associative array specifiying the proxy URI for
|
||||||
|
* 'http' and 'https' schemes, in addition to a 'no' key value pair
|
||||||
|
* providing a list of host names that should not be proxied to.
|
||||||
|
*
|
||||||
|
* @return array|null
|
||||||
|
*
|
||||||
|
* The return array looks like:
|
||||||
|
* [
|
||||||
|
* 'http' => 'username:password@proxy.example.com',
|
||||||
|
* 'https' => 'username:password@proxy.example.com',
|
||||||
|
* 'no' => ['foo.com', 'bar.com']
|
||||||
|
* ]
|
||||||
*
|
*
|
||||||
* @return string|null
|
|
||||||
*/
|
*/
|
||||||
private function getProxyUri(): ?string {
|
private function getProxyUri(): ?array {
|
||||||
$proxyHost = $this->config->getSystemValue('proxy', '');
|
$proxyHost = $this->config->getSystemValue('proxy', '');
|
||||||
|
|
||||||
if ($proxyHost === '' || $proxyHost === null) {
|
if ($proxyHost === '' || $proxyHost === null) {
|
||||||
|
@ -108,12 +126,21 @@ class Client implements IClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
$proxyUserPwd = $this->config->getSystemValue('proxyuserpwd', '');
|
$proxyUserPwd = $this->config->getSystemValue('proxyuserpwd', '');
|
||||||
|
if ($proxyUserPwd !== '' && $proxyUserPwd !== null) {
|
||||||
if ($proxyUserPwd === '' || $proxyUserPwd === null) {
|
$proxyHost = $proxyUserPwd . '@' . $proxyHost;
|
||||||
return $proxyHost;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $proxyUserPwd . '@' . $proxyHost;
|
$proxy = [
|
||||||
|
'http' => $proxyHost,
|
||||||
|
'https' => $proxyHost,
|
||||||
|
];
|
||||||
|
|
||||||
|
$proxyExclude = $this->config->getSystemValue('proxyexclude', []);
|
||||||
|
if ($proxyExclude !== [] && $proxyExclude !== null) {
|
||||||
|
$proxy['no'] = $proxyExclude;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $proxy;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -63,7 +63,15 @@ class ClientTest extends \Test\TestCase {
|
||||||
->method('getSystemValue')
|
->method('getSystemValue')
|
||||||
->with('proxyuserpwd', null)
|
->with('proxyuserpwd', null)
|
||||||
->willReturn(null);
|
->willReturn(null);
|
||||||
$this->assertSame('foo', self::invokePrivate($this->client, 'getProxyUri'));
|
$this->config
|
||||||
|
->expects($this->at(2))
|
||||||
|
->method('getSystemValue')
|
||||||
|
->with('proxyexclude', [])
|
||||||
|
->willReturn([]);
|
||||||
|
$this->assertEquals([
|
||||||
|
'http' => 'foo',
|
||||||
|
'https' => 'foo'
|
||||||
|
], self::invokePrivate($this->client, 'getProxyUri'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGetProxyUriProxyHostWithPassword(): void {
|
public function testGetProxyUriProxyHostWithPassword(): void {
|
||||||
|
@ -87,7 +95,58 @@ class ClientTest extends \Test\TestCase {
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
->willReturn('username:password');
|
->willReturn('username:password');
|
||||||
$this->assertSame('username:password@foo', self::invokePrivate($this->client, 'getProxyUri'));
|
$this->config
|
||||||
|
->expects($this->at(2))
|
||||||
|
->method('getSystemValue')
|
||||||
|
->with(
|
||||||
|
$this->equalTo('proxyexclude'),
|
||||||
|
$this->callback(function ($input) {
|
||||||
|
return $input === [];
|
||||||
|
})
|
||||||
|
)
|
||||||
|
->willReturn([]);
|
||||||
|
$this->assertEquals([
|
||||||
|
'http' => 'username:password@foo',
|
||||||
|
'https' => 'username:password@foo'
|
||||||
|
], self::invokePrivate($this->client, 'getProxyUri'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetProxyUriProxyHostWithPasswordAndExclude(): void {
|
||||||
|
$this->config
|
||||||
|
->expects($this->at(0))
|
||||||
|
->method('getSystemValue')
|
||||||
|
->with(
|
||||||
|
$this->equalTo('proxy'),
|
||||||
|
$this->callback(function ($input) {
|
||||||
|
return $input === '';
|
||||||
|
})
|
||||||
|
)
|
||||||
|
->willReturn('foo');
|
||||||
|
$this->config
|
||||||
|
->expects($this->at(1))
|
||||||
|
->method('getSystemValue')
|
||||||
|
->with(
|
||||||
|
$this->equalTo('proxyuserpwd'),
|
||||||
|
$this->callback(function ($input) {
|
||||||
|
return $input === '';
|
||||||
|
})
|
||||||
|
)
|
||||||
|
->willReturn('username:password');
|
||||||
|
$this->config
|
||||||
|
->expects($this->at(2))
|
||||||
|
->method('getSystemValue')
|
||||||
|
->with(
|
||||||
|
$this->equalTo('proxyexclude'),
|
||||||
|
$this->callback(function ($input) {
|
||||||
|
return $input === [];
|
||||||
|
})
|
||||||
|
)
|
||||||
|
->willReturn(['bar']);
|
||||||
|
$this->assertEquals([
|
||||||
|
'http' => 'username:password@foo',
|
||||||
|
'https' => 'username:password@foo',
|
||||||
|
'no' => ['bar']
|
||||||
|
], self::invokePrivate($this->client, 'getProxyUri'));
|
||||||
}
|
}
|
||||||
|
|
||||||
private function setUpDefaultRequestOptions(): void {
|
private function setUpDefaultRequestOptions(): void {
|
||||||
|
@ -101,6 +160,11 @@ class ClientTest extends \Test\TestCase {
|
||||||
->method('getSystemValue')
|
->method('getSystemValue')
|
||||||
->with('proxyuserpwd', null)
|
->with('proxyuserpwd', null)
|
||||||
->willReturn(null);
|
->willReturn(null);
|
||||||
|
$this->config
|
||||||
|
->expects($this->at(2))
|
||||||
|
->method('getSystemValue')
|
||||||
|
->with('proxyexclude', [])
|
||||||
|
->willReturn([]);
|
||||||
$this->certificateManager
|
$this->certificateManager
|
||||||
->expects($this->once())
|
->expects($this->once())
|
||||||
->method('getAbsoluteBundlePath')
|
->method('getAbsoluteBundlePath')
|
||||||
|
@ -109,7 +173,10 @@ class ClientTest extends \Test\TestCase {
|
||||||
|
|
||||||
$this->defaultRequestOptions = [
|
$this->defaultRequestOptions = [
|
||||||
'verify' => '/my/path.crt',
|
'verify' => '/my/path.crt',
|
||||||
'proxy' => 'foo',
|
'proxy' => [
|
||||||
|
'http' => 'foo',
|
||||||
|
'https' => 'foo'
|
||||||
|
],
|
||||||
'headers' => [
|
'headers' => [
|
||||||
'User-Agent' => 'Nextcloud Server Crawler',
|
'User-Agent' => 'Nextcloud Server Crawler',
|
||||||
],
|
],
|
||||||
|
@ -131,7 +198,10 @@ class ClientTest extends \Test\TestCase {
|
||||||
|
|
||||||
$options = array_merge($this->defaultRequestOptions, [
|
$options = array_merge($this->defaultRequestOptions, [
|
||||||
'verify' => false,
|
'verify' => false,
|
||||||
'proxy' => 'bar',
|
'proxy' => [
|
||||||
|
'http' => 'bar',
|
||||||
|
'https' => 'bar'
|
||||||
|
],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->guzzleClient->method('request')
|
$this->guzzleClient->method('request')
|
||||||
|
@ -154,7 +224,10 @@ class ClientTest extends \Test\TestCase {
|
||||||
|
|
||||||
$options = array_merge($this->defaultRequestOptions, [
|
$options = array_merge($this->defaultRequestOptions, [
|
||||||
'verify' => false,
|
'verify' => false,
|
||||||
'proxy' => 'bar',
|
'proxy' => [
|
||||||
|
'http' => 'bar',
|
||||||
|
'https' => 'bar'
|
||||||
|
],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->guzzleClient->method('request')
|
$this->guzzleClient->method('request')
|
||||||
|
@ -177,7 +250,10 @@ class ClientTest extends \Test\TestCase {
|
||||||
|
|
||||||
$options = array_merge($this->defaultRequestOptions, [
|
$options = array_merge($this->defaultRequestOptions, [
|
||||||
'verify' => false,
|
'verify' => false,
|
||||||
'proxy' => 'bar',
|
'proxy' => [
|
||||||
|
'http' => 'bar',
|
||||||
|
'https' => 'bar'
|
||||||
|
],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->guzzleClient->method('request')
|
$this->guzzleClient->method('request')
|
||||||
|
@ -200,7 +276,10 @@ class ClientTest extends \Test\TestCase {
|
||||||
|
|
||||||
$options = array_merge($this->defaultRequestOptions, [
|
$options = array_merge($this->defaultRequestOptions, [
|
||||||
'verify' => false,
|
'verify' => false,
|
||||||
'proxy' => 'bar',
|
'proxy' => [
|
||||||
|
'http' => 'bar',
|
||||||
|
'https' => 'bar'
|
||||||
|
],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->guzzleClient->method('request')
|
$this->guzzleClient->method('request')
|
||||||
|
@ -223,7 +302,10 @@ class ClientTest extends \Test\TestCase {
|
||||||
|
|
||||||
$options = array_merge($this->defaultRequestOptions, [
|
$options = array_merge($this->defaultRequestOptions, [
|
||||||
'verify' => false,
|
'verify' => false,
|
||||||
'proxy' => 'bar',
|
'proxy' => [
|
||||||
|
'http' => 'bar',
|
||||||
|
'https' => 'bar'
|
||||||
|
],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->guzzleClient->method('request')
|
$this->guzzleClient->method('request')
|
||||||
|
@ -246,7 +328,10 @@ class ClientTest extends \Test\TestCase {
|
||||||
|
|
||||||
$options = array_merge($this->defaultRequestOptions, [
|
$options = array_merge($this->defaultRequestOptions, [
|
||||||
'verify' => false,
|
'verify' => false,
|
||||||
'proxy' => 'bar',
|
'proxy' => [
|
||||||
|
'http' => 'bar',
|
||||||
|
'https' => 'bar'
|
||||||
|
],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->guzzleClient->method('request')
|
$this->guzzleClient->method('request')
|
||||||
|
@ -268,7 +353,6 @@ class ClientTest extends \Test\TestCase {
|
||||||
|
|
||||||
$this->assertEquals([
|
$this->assertEquals([
|
||||||
'verify' => \OC::$SERVERROOT . '/resources/config/ca-bundle.crt',
|
'verify' => \OC::$SERVERROOT . '/resources/config/ca-bundle.crt',
|
||||||
'proxy' => null,
|
|
||||||
'headers' => [
|
'headers' => [
|
||||||
'User-Agent' => 'Nextcloud Server Crawler'
|
'User-Agent' => 'Nextcloud Server Crawler'
|
||||||
],
|
],
|
||||||
|
@ -287,6 +371,11 @@ class ClientTest extends \Test\TestCase {
|
||||||
->method('getSystemValue')
|
->method('getSystemValue')
|
||||||
->with('proxyuserpwd', null)
|
->with('proxyuserpwd', null)
|
||||||
->willReturn(null);
|
->willReturn(null);
|
||||||
|
$this->config
|
||||||
|
->expects($this->at(2))
|
||||||
|
->method('getSystemValue')
|
||||||
|
->with('proxyexclude', [])
|
||||||
|
->willReturn([]);
|
||||||
$this->certificateManager
|
$this->certificateManager
|
||||||
->expects($this->once())
|
->expects($this->once())
|
||||||
->method('getAbsoluteBundlePath')
|
->method('getAbsoluteBundlePath')
|
||||||
|
@ -295,7 +384,46 @@ class ClientTest extends \Test\TestCase {
|
||||||
|
|
||||||
$this->assertEquals([
|
$this->assertEquals([
|
||||||
'verify' => '/my/path.crt',
|
'verify' => '/my/path.crt',
|
||||||
'proxy' => 'foo',
|
'proxy' => [
|
||||||
|
'http' => 'foo',
|
||||||
|
'https' => 'foo'
|
||||||
|
],
|
||||||
|
'headers' => [
|
||||||
|
'User-Agent' => 'Nextcloud Server Crawler'
|
||||||
|
],
|
||||||
|
'timeout' => 30,
|
||||||
|
], self::invokePrivate($this->client, 'buildRequestOptions', [[]]));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSetDefaultOptionsWithProxyAndExclude(): void {
|
||||||
|
$this->config
|
||||||
|
->expects($this->at(0))
|
||||||
|
->method('getSystemValue')
|
||||||
|
->with('proxy', null)
|
||||||
|
->willReturn('foo');
|
||||||
|
$this->config
|
||||||
|
->expects($this->at(1))
|
||||||
|
->method('getSystemValue')
|
||||||
|
->with('proxyuserpwd', null)
|
||||||
|
->willReturn(null);
|
||||||
|
$this->config
|
||||||
|
->expects($this->at(2))
|
||||||
|
->method('getSystemValue')
|
||||||
|
->with('proxyexclude', [])
|
||||||
|
->willReturn(['bar']);
|
||||||
|
$this->certificateManager
|
||||||
|
->expects($this->once())
|
||||||
|
->method('getAbsoluteBundlePath')
|
||||||
|
->with(null)
|
||||||
|
->willReturn('/my/path.crt');
|
||||||
|
|
||||||
|
$this->assertEquals([
|
||||||
|
'verify' => '/my/path.crt',
|
||||||
|
'proxy' => [
|
||||||
|
'http' => 'foo',
|
||||||
|
'https' => 'foo',
|
||||||
|
'no' => ['bar']
|
||||||
|
],
|
||||||
'headers' => [
|
'headers' => [
|
||||||
'User-Agent' => 'Nextcloud Server Crawler'
|
'User-Agent' => 'Nextcloud Server Crawler'
|
||||||
],
|
],
|
||||||
|
|
Loading…
Reference in New Issue