Merge pull request #57376 from nextcloud/add-server-url-to-http-client-user-agent

feat(http-client): add option to add instance URL to HTTP client user-agent
This commit is contained in:
Thomas Citharel 2026-02-19 18:28:10 +01:00 committed by GitHub
commit 80fd6fa194
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 91 additions and 8 deletions

View file

@ -827,6 +827,17 @@ $CONFIG = [
*/
'allow_local_remote_servers' => true,
/**
* Add the URL of the Nextcloud server in User-Agent headers HTTP calls.
*
* This helps service providers identifying calls from your server,
* which can be helpful for them, but can be a privacy issue on small
* Nextcloud servers.
*
* Defaults to ``false``
*/
'http_client_add_user_agent_url' => false,
/**
* Deleted Items (trash bin)
*

View file

@ -75,6 +75,10 @@ class Client implements IClient {
if (!isset($options[RequestOptions::HEADERS]['User-Agent'])) {
$userAgent = 'Nextcloud-Server-Crawler/' . $this->serverVersion->getVersionString();
$overwriteCliUrl = $this->config->getSystemValueString('overwrite.cli.url');
if ($this->config->getSystemValueBool('http_client_add_user_agent_url') && !empty($overwriteCliUrl)) {
$userAgent .= '; +' . rtrim($overwriteCliUrl, '/');
}
$options[RequestOptions::HEADERS]['User-Agent'] = $userAgent;
}

View file

@ -18,6 +18,7 @@ use OCP\ICertificateManager;
use OCP\IConfig;
use OCP\Security\IRemoteHostValidator;
use OCP\ServerVersion;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;
use function parse_url;
@ -267,12 +268,14 @@ class ClientTest extends \Test\TestCase {
->willReturnMap([
['proxy', '', 'foo'],
['proxyuserpwd', '', ''],
['overwrite.cli.url', '', '']
]);
$this->config
->method('getSystemValueBool')
->willReturnMap([
['installed', false, true],
['allow_local_remote_servers', false, true],
['http_client_add_user_agent_url', false, false]
]);
$this->certificateManager
@ -466,17 +469,20 @@ class ClientTest extends \Test\TestCase {
public function testSetDefaultOptionsWithNotInstalled(): void {
$this->config
->expects($this->exactly(2))
->expects($this->exactly(3))
->method('getSystemValueBool')
->willReturnMap([
['installed', false, false],
['allow_local_remote_servers', false, false],
['http_client_add_user_agent_url', false, false],
]);
$this->config
->expects($this->once())
->expects($this->exactly(2))
->method('getSystemValueString')
->with('proxy', '')
->willReturn('');
->willReturnMap([
['proxy', '', ''],
['overwrite.cli.url', '', ''],
]);
$this->certificateManager
->expects($this->never())
->method('listCertificates');
@ -517,11 +523,12 @@ class ClientTest extends \Test\TestCase {
public function testSetDefaultOptionsWithProxy(): void {
$this->config
->expects($this->exactly(2))
->expects($this->exactly(3))
->method('getSystemValueBool')
->willReturnMap([
['installed', false, true],
['allow_local_remote_servers', false, false],
['http_client_add_user_agent_url', false, false],
]);
$this->config
->expects($this->once())
@ -529,11 +536,12 @@ class ClientTest extends \Test\TestCase {
->with('proxyexclude', [])
->willReturn([]);
$this->config
->expects($this->exactly(2))
->expects($this->exactly(3))
->method('getSystemValueString')
->willReturnMap([
['proxy', '', 'foo'],
['proxyuserpwd', '', ''],
['overwrite.cli.url', '', ''],
]);
$this->certificateManager
->expects($this->once())
@ -577,11 +585,12 @@ class ClientTest extends \Test\TestCase {
public function testSetDefaultOptionsWithProxyAndExclude(): void {
$this->config
->expects($this->exactly(2))
->expects($this->exactly(3))
->method('getSystemValueBool')
->willReturnMap([
['installed', false, true],
['allow_local_remote_servers', false, false],
['http_client_add_user_agent_url', false, false],
]);
$this->config
->expects($this->once())
@ -589,11 +598,12 @@ class ClientTest extends \Test\TestCase {
->with('proxyexclude', [])
->willReturn(['bar']);
$this->config
->expects($this->exactly(2))
->expects($this->exactly(3))
->method('getSystemValueString')
->willReturnMap([
['proxy', '', 'foo'],
['proxyuserpwd', '', ''],
['overwrite.cli.url', '', ''],
]);
$this->certificateManager
->expects($this->once())
@ -635,4 +645,62 @@ class ClientTest extends \Test\TestCase {
],
], self::invokePrivate($this->client, 'buildRequestOptions', [[]]));
}
public static function dataForTestSetServerUrlInUserAgent(): array {
return [
['https://example.com/', 'Nextcloud-Server-Crawler/123.45.6; +https://example.com'],
['', 'Nextcloud-Server-Crawler/123.45.6'],
];
}
#[DataProvider('dataForTestSetServerUrlInUserAgent')]
public function testSetServerUrlInUserAgent(string $url, string $userAgent): void {
$this->config
->expects($this->exactly(3))
->method('getSystemValueBool')
->willReturnMap([
['installed', false, true],
['allow_local_remote_servers', false, false],
['http_client_add_user_agent_url', false, true],
]);
$this->config
->expects($this->exactly(2))
->method('getSystemValueString')
->willReturnMap([
['proxy', '', ''],
['overwrite.cli.url', '', $url],
]);
$this->certificateManager
->expects($this->once())
->method('getAbsoluteBundlePath')
->with()
->willReturn('/my/path.crt');
$this->serverVersion->method('getVersionString')
->willReturn('123.45.6');
$this->assertEquals([
'verify' => '/my/path.crt',
'headers' => [
'User-Agent' => $userAgent,
'Accept-Encoding' => 'gzip',
],
'timeout' => 30,
'nextcloud' => [
'allow_local_address' => false,
],
'allow_redirects' => [
'on_redirect' => function (
\Psr\Http\Message\RequestInterface $request,
\Psr\Http\Message\ResponseInterface $response,
\Psr\Http\Message\UriInterface $uri,
): void {
},
],
'version' => '2.0',
'curl' => [
\CURLOPT_HTTP_VERSION => \CURL_HTTP_VERSION_2TLS,
],
], self::invokePrivate($this->client, 'buildRequestOptions', [[]]));
}
}