3 * @copyright Copyright (C) 2010-2023, the Friendica project
5 * @license GNU AGPL version 3 or any later version
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Affero General Public License as
9 * published by the Free Software Foundation, either version 3 of the
10 * License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Affero General Public License for more details.
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
22 namespace Friendica\Test\src\Util;
24 use Friendica\App\BaseURL;
25 use Friendica\Core\Config\Capability\IManageConfigValues;
26 use Friendica\Core\Config\Capability\ISetConfigValuesTransactionally;
27 use Friendica\Core\Config\Model\Config;
28 use Friendica\Core\Config\Model\ConfigTransaction;
29 use Friendica\Core\Config\Util\ConfigFileManager;
30 use Friendica\Core\Config\ValueObject\Cache;
31 use Friendica\Test\MockedTest;
32 use Friendica\Test\Util\VFSTrait;
34 class BaseURLTest extends MockedTest
38 protected function setUp(): void
45 public function dataDefault()
59 'sslPolicy' => BaseURL::DEFAULT_SSL_SCHEME,
64 'WithSubDirectory' => [
66 'SERVER_NAME' => 'friendica.local',
67 'REDIRECT_URI' => 'test/module/more',
68 'QUERY_STRING' => 'module/more',
77 'hostname' => 'friendica.local',
79 'sslPolicy' => BaseURL::DEFAULT_SSL_SCHEME,
80 'url' => 'http://friendica.local/test',
87 'hostname' => 'friendica.local',
89 'sslPolicy' => BaseURL::SSL_POLICY_FULL,
90 'url' => 'http://friendica.local/test',
93 'hostname' => 'friendica.local',
95 'sslPolicy' => BaseURL::SSL_POLICY_FULL,
96 'url' => 'http://friendica.local/test',
100 'WithHttpsScheme' => [
102 'SERVER_NAME' => 'friendica.local',
103 'REDIRECT_URI' => 'test/module/more',
104 'QUERY_STRING' => 'module/more',
114 'hostname' => 'friendica.local',
116 'sslPolicy' => BaseURL::SSL_POLICY_FULL,
117 'url' => 'https://friendica.local/test',
121 'WithoutQueryString' => [
123 'SERVER_NAME' => 'friendica.local',
124 'REDIRECT_URI' => 'test/more',
134 'hostname' => 'friendica.local',
135 'urlPath' => 'test/more',
136 'sslPolicy' => BaseURL::SSL_POLICY_FULL,
137 'url' => 'https://friendica.local/test/more',
143 'SERVER_NAME' => 'friendica.local',
144 'SERVER_PORT' => '1234',
145 'REDIRECT_URI' => 'test/more',
155 'hostname' => 'friendica.local:1234',
156 'urlPath' => 'test/more',
157 'sslPolicy' => BaseURL::SSL_POLICY_FULL,
158 'url' => 'https://friendica.local:1234/test/more',
164 'SERVER_NAME' => 'friendica.local',
165 'SERVER_PORT' => '443',
166 'REDIRECT_URI' => 'test/more',
175 'hostname' => 'friendica.local',
176 'urlPath' => 'test/more',
177 'sslPolicy' => BaseURL::SSL_POLICY_FULL,
178 'url' => 'https://friendica.local/test/more',
184 'SERVER_NAME' => 'friendica.local',
185 'SERVER_PORT' => '80',
186 'REDIRECT_URI' => 'test/more',
195 'hostname' => 'friendica.local',
196 'urlPath' => 'test/more',
197 'sslPolicy' => BaseURL::DEFAULT_SSL_SCHEME,
198 'url' => 'http://friendica.local/test/more',
206 * Test the default config determination
207 * @dataProvider dataDefault
209 public function testCheck($server, $input, $assert)
211 $configMock = \Mockery::mock(IManageConfigValues::class);
212 $configMock->shouldReceive('get')->with('config', 'hostname')->andReturn($input['hostname']);
213 $configMock->shouldReceive('get')->with('system', 'urlpath')->andReturn($input['urlPath']);
214 $configMock->shouldReceive('get')->with('system', 'ssl_policy')->andReturn($input['sslPolicy']);
215 $configMock->shouldReceive('get')->with('system', 'url')->andReturn($input['url']);
217 // If we don't have an urlPath as an input, we assert it, we will save it to the DB for the next time
218 if (!isset($input['urlPath']) && isset($assert['urlPath'])) {
219 $configMock->shouldReceive('set')->with('system', 'urlpath', $assert['urlPath'])->once();
222 // If we don't have the ssl_policy as an input, we assert it, we will save it to the DB for the next time
223 if (!isset($input['sslPolicy']) && isset($assert['sslPolicy'])) {
224 $configMock->shouldReceive('set')->with('system', 'ssl_policy', $assert['sslPolicy'])->once();
227 // If we don't have the hostname as an input, we assert it, we will save it to the DB for the next time
228 if (empty($input['hostname']) && !empty($assert['hostname'])) {
229 $configMock->shouldReceive('set')->with('config', 'hostname', $assert['hostname'])->once();
232 // If we don't have an URL at first, but we assert it, we will save it to the DB for the next time
233 if (empty($input['url']) && !empty($assert['url'])) {
234 $configMock->shouldReceive('set')->with('system', 'url', $assert['url'])->once();
237 $baseUrl = new BaseURL($configMock, $server);
239 self::assertEquals($assert['hostname'], $baseUrl->getHostname());
240 self::assertEquals($assert['urlPath'], $baseUrl->getUrlPath());
241 self::assertEquals($assert['sslPolicy'], $baseUrl->getSSLPolicy());
242 self::assertEquals($assert['scheme'], $baseUrl->getScheme());
243 self::assertEquals($assert['url'], $baseUrl->get());
246 public function dataSave()
251 'hostname' => 'friendica.local',
253 'sslPolicy' => BaseURL::SSL_POLICY_FULL,
254 'url' => 'https://friendica.local/path',
258 'hostname' => 'friendica.local',
260 'sslPolicy' => BaseURL::SSL_POLICY_FULL,
262 'url' => 'https://friendica.local/path',
266 'hostname' => 'friendica.old',
267 'urlPath' => 'is/old/path',
268 'sslPolicy' => BaseURL::DEFAULT_SSL_SCHEME,
269 'url' => 'http://friendica.old/is/old/path',
273 'hostname' => 'friendica.local',
274 'urlPath' => 'new/path',
275 'sslPolicy' => BaseURL::SSL_POLICY_FULL,
277 'url' => 'https://friendica.local/new/path',
281 'hostname' => 'friendica.old',
282 'urlPath' => 'is/old/path',
283 'sslPolicy' => BaseURL::DEFAULT_SSL_SCHEME,
284 'url' => 'http://friendica.old/is/old/path',
292 'url' => 'http://friendica.old/is/old/path',
294 'changeHostname' => [
296 'hostname' => 'friendica.old',
297 'urlPath' => 'is/old/path',
298 'sslPolicy' => BaseURL::DEFAULT_SSL_SCHEME,
299 'url' => 'http://friendica.old/is/old/path',
303 'hostname' => 'friendica.local',
307 'url' => 'http://friendica.local/is/old/path',
311 'hostname' => 'friendica.old',
312 'urlPath' => 'is/old/path',
313 'sslPolicy' => BaseURL::DEFAULT_SSL_SCHEME,
314 'url' => 'http://friendica.old/is/old/path',
319 'urlPath' => 'new/path',
322 'url' => 'http://friendica.old/new/path',
324 'changeSSLPolicy' => [
326 'hostname' => 'friendica.old',
327 'urlPath' => 'is/old/path',
328 'sslPolicy' => BaseURL::DEFAULT_SSL_SCHEME,
329 'url' => 'http://friendica.old/is/old/path',
335 'sslPolicy' => BaseURL::SSL_POLICY_FULL,
337 'url' => 'https://friendica.old/is/old/path',
343 * Test the save() method
344 * @dataProvider dataSave
346 public function testSave($input, $save, $url)
348 $configFileManager = new ConfigFileManager($this->root->url(), $this->root->url() . '/config/', $this->root->url() . '/static/');
349 $config = new Config($configFileManager, new Cache([
351 'hostname' => $input['hostname'] ?? null,
354 'urlpath' => $input['urlPath'] ?? null,
355 'ssl_policy' => $input['sslPolicy'] ?? null,
356 'url' => $input['url'] ?? null,
357 'force_ssl' => $input['force_ssl'] ?? null,
361 $baseUrl = new BaseURL($config, []);
363 $baseUrl->save($save['hostname'], $save['sslPolicy'], $save['urlPath']);
365 self::assertEquals($url, $baseUrl->get());
369 * Test the saveByUrl() method
370 * @dataProvider dataSave
376 public function testSaveByUrl($input, $save, $url)
378 $configFileManager = new ConfigFileManager($this->root->url(), $this->root->url() . '/config/', $this->root->url() . '/static/');
379 $config = new Config($configFileManager, new Cache([
381 'hostname' => $input['hostname'] ?? null,
384 'urlpath' => $input['urlPath'] ?? null,
385 'ssl_policy' => $input['sslPolicy'] ?? null,
386 'url' => $input['url'] ?? null,
387 'force_ssl' => $input['force_ssl'] ?? null,
391 $baseUrl = new BaseURL($config, []);
393 $baseUrl->saveByURL($url);
395 self::assertEquals($url, $baseUrl->get());
398 public function dataGetBaseUrl()
402 'sslPolicy' => BaseURL::DEFAULT_SSL_SCHEME,
404 'url' => 'http://friendica.local/new/test',
405 'assert' => 'http://friendica.local/new/test',
407 'DefaultWithSSL' => [
408 'sslPolicy' => BaseURL::DEFAULT_SSL_SCHEME,
410 'url' => 'http://friendica.local/new/test',
411 'assert' => 'https://friendica.local/new/test',
413 'SSLFullWithSSL' => [
414 'sslPolicy' => BaseURL::SSL_POLICY_FULL,
416 'url' => 'http://friendica.local/new/test',
417 'assert' => 'http://friendica.local/new/test',
419 'SSLFullWithoutSSL' => [
420 'sslPolicy' => BaseURL::SSL_POLICY_FULL,
422 'url' => 'https://friendica.local/new/test',
423 'assert' => 'https://friendica.local/new/test',
426 'sslPolicy' => BaseURL::SSL_POLICY_NONE,
428 'url' => 'http://friendica.local/new/test',
429 'assert' => 'http://friendica.local/new/test',
431 'NoSSLWithoutSSL' => [
432 'sslPolicy' => BaseURL::SSL_POLICY_NONE,
434 'url' => 'http://friendica.local/new/test',
435 'assert' => 'http://friendica.local/new/test',
441 * Test the get() method
442 * @dataProvider dataGetBaseUrl
444 public function testGetURL($sslPolicy, $ssl, $url, $assert)
446 $configMock = \Mockery::mock(IManageConfigValues::class);
447 $configMock->shouldReceive('get')->with('config', 'hostname')->andReturn('friendica.local');
448 $configMock->shouldReceive('get')->with('system', 'urlpath')->andReturn('new/test');
449 $configMock->shouldReceive('get')->with('system', 'ssl_policy')->andReturn($sslPolicy);
450 $configMock->shouldReceive('get')->with('system', 'url')->andReturn($url);
452 $baseUrl = new BaseURL($configMock, []);
454 self::assertEquals($assert, $baseUrl->get($ssl));
457 public function dataCheckRedirectHTTPS()
462 'REQUEST_METHOD' => 'GET',
466 'sslPolicy' => BaseURL::DEFAULT_SSL_SCHEME,
467 'url' => 'https://friendica.local',
472 'REQUEST_METHOD' => 'GET',
475 'sslPolicy' => BaseURL::DEFAULT_SSL_SCHEME,
476 'url' => 'https://friendica.local',
479 'forceSSLWithSSLPolicy' => [
482 'sslPolicy' => BaseURL::SSL_POLICY_FULL,
483 'url' => 'https://friendica.local',
486 'forceSSLWithSSLPolicyAndGet' => [
488 'REQUEST_METHOD' => 'GET',
491 'sslPolicy' => BaseURL::SSL_POLICY_FULL,
492 'url' => 'https://friendica.local',
499 * Test the checkRedirectHTTPS() method
500 * @dataProvider dataCheckRedirectHTTPS
502 public function testCheckRedirectHTTPS($server, $forceSSL, $sslPolicy, $url, $redirect)
504 $configMock = \Mockery::mock(IManageConfigValues::class);
505 $configMock->shouldReceive('get')->with('config', 'hostname')->andReturn('friendica.local');
506 $configMock->shouldReceive('get')->with('system', 'urlpath')->andReturn('new/test');
507 $configMock->shouldReceive('get')->with('system', 'ssl_policy')->andReturn($sslPolicy);
508 $configMock->shouldReceive('get')->with('system', 'url')->andReturn($url);
509 $configMock->shouldReceive('get')->with('system', 'force_ssl')->andReturn($forceSSL);
511 $baseUrl = new BaseURL($configMock, $server);
513 self::assertEquals($redirect, $baseUrl->checkRedirectHttps());