Merge pull request #1539 from ArthurHoaro/feature/manual-root-url

This commit is contained in:
ArthurHoaro 2020-09-22 14:08:54 +02:00 committed by GitHub
commit 98e7a59ca2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 189 additions and 61 deletions

View file

@ -122,9 +122,9 @@ public function buildData(string $feedType, ?array $userInput)
$data['language'] = $this->getTypeLanguage($feedType); $data['language'] = $this->getTypeLanguage($feedType);
$data['last_update'] = $this->getLatestDateFormatted($feedType); $data['last_update'] = $this->getLatestDateFormatted($feedType);
$data['show_dates'] = !$this->hideDates || $this->isLoggedIn; $data['show_dates'] = !$this->hideDates || $this->isLoggedIn;
// Remove leading slash from REQUEST_URI. // Remove leading path from REQUEST_URI (already contained in $pageaddr).
$data['self_link'] = escape(server_url($this->serverInfo)) $requestUri = preg_replace('#(.*?/)(feed.*)#', '$2', escape($this->serverInfo['REQUEST_URI']));
. escape($this->serverInfo['REQUEST_URI']); $data['self_link'] = $pageaddr . $requestUri;
$data['index_url'] = $pageaddr; $data['index_url'] = $pageaddr;
$data['usepermalinks'] = $this->usePermalinks === true; $data['usepermalinks'] = $this->usePermalinks === true;
$data['links'] = $linkDisplayed; $data['links'] = $linkDisplayed;

View file

@ -132,7 +132,7 @@ public function rss(Request $request, Response $response): Response
'date' => $dayDatetime, 'date' => $dayDatetime,
'date_rss' => $dayDatetime->format(DateTime::RSS), 'date_rss' => $dayDatetime->format(DateTime::RSS),
'date_human' => format_date($dayDatetime, false, true), 'date_human' => format_date($dayDatetime, false, true),
'absolute_url' => $indexUrl . '/daily?day=' . $day, 'absolute_url' => $indexUrl . 'daily?day=' . $day,
'links' => [], 'links' => [],
]; ];

View file

@ -369,7 +369,11 @@ function server_url($server)
*/ */
function index_url($server) function index_url($server)
{ {
$scriptname = $server['SCRIPT_NAME'] ?? ''; if (defined('SHAARLI_ROOT_URL') && null !== SHAARLI_ROOT_URL) {
return rtrim(SHAARLI_ROOT_URL, '/') . '/';
}
$scriptname = !empty($server['SCRIPT_NAME']) ? $server['SCRIPT_NAME'] : '/';
if (endsWith($scriptname, 'index.php')) { if (endsWith($scriptname, 'index.php')) {
$scriptname = substr($scriptname, 0, -9); $scriptname = substr($scriptname, 0, -9);
} }
@ -392,7 +396,7 @@ function page_url($server)
$scriptname = substr($scriptname, 0, -9); $scriptname = substr($scriptname, 0, -9);
} }
$route = ltrim($server['REQUEST_URI'] ?? '', $scriptname); $route = preg_replace('@^' . $scriptname . '@', '', $server['REQUEST_URI'] ?? '');
if (! empty($server['QUERY_STRING'])) { if (! empty($server['QUERY_STRING'])) {
return index_url($server) . $route . '?' . $server['QUERY_STRING']; return index_url($server) . $route . '?' . $server['QUERY_STRING'];
} }

View file

@ -151,6 +151,7 @@ _These settings should not be edited_
- **enabled_plugins**: List of enabled plugins. - **enabled_plugins**: List of enabled plugins.
- **default_note_title**: Default title of a new note. - **default_note_title**: Default title of a new note.
- **retrieve_description** (boolean): If set to true, for every new Shaare Shaarli will try to retrieve the description and keywords from the HTML meta tags. - **retrieve_description** (boolean): If set to true, for every new Shaare Shaarli will try to retrieve the description and keywords from the HTML meta tags.
- **root_url**: Overrides automatic discovery of Shaarli instance's URL (e.g.) `https://sub.domain.tld/shaarli-folder/`.
### Security ### Security

View file

@ -35,6 +35,9 @@
$conf = new ConfigManager(); $conf = new ConfigManager();
// Manually override root URL for complex server configurations
define('SHAARLI_ROOT_URL', $conf->get('general.root_url', null));
// In dev mode, throw exception on any warning // In dev mode, throw exception on any warning
if ($conf->get('dev.debug', false)) { if ($conf->get('dev.debug', false)) {
// See all errors (for debugging only) // See all errors (for debugging only)

View file

@ -3,6 +3,7 @@
namespace Shaarli\Feed; namespace Shaarli\Feed;
use DateTime; use DateTime;
use PHPUnit\Framework\TestCase;
use ReferenceLinkDB; use ReferenceLinkDB;
use Shaarli\Bookmark\Bookmark; use Shaarli\Bookmark\Bookmark;
use Shaarli\Bookmark\BookmarkFileService; use Shaarli\Bookmark\BookmarkFileService;
@ -16,7 +17,7 @@
* *
* Unit tests for FeedBuilder. * Unit tests for FeedBuilder.
*/ */
class FeedBuilderTest extends \PHPUnit\Framework\TestCase class FeedBuilderTest extends TestCase
{ {
/** /**
* @var string locale Basque (Spain). * @var string locale Basque (Spain).
@ -44,7 +45,7 @@ class FeedBuilderTest extends \PHPUnit\Framework\TestCase
/** /**
* Called before every test method. * Called before every test method.
*/ */
public static function setUpBeforeClass() public static function setUpBeforeClass(): void
{ {
$conf = new ConfigManager('tests/utils/config/configJson'); $conf = new ConfigManager('tests/utils/config/configJson');
$conf->set('resource.datastore', self::$testDatastore); $conf->set('resource.datastore', self::$testDatastore);
@ -60,7 +61,7 @@ public static function setUpBeforeClass()
'SERVER_NAME' => 'host.tld', 'SERVER_NAME' => 'host.tld',
'SERVER_PORT' => '80', 'SERVER_PORT' => '80',
'SCRIPT_NAME' => '/index.php', 'SCRIPT_NAME' => '/index.php',
'REQUEST_URI' => '/index.php?do=feed', 'REQUEST_URI' => '/feed/atom',
); );
} }
@ -81,7 +82,7 @@ public function testRSSBuildData()
$this->assertEquals(self::$RSS_LANGUAGE, $data['language']); $this->assertEquals(self::$RSS_LANGUAGE, $data['language']);
$this->assertRegExp('/Wed, 03 Aug 2016 09:30:33 \+\d{4}/', $data['last_update']); $this->assertRegExp('/Wed, 03 Aug 2016 09:30:33 \+\d{4}/', $data['last_update']);
$this->assertEquals(true, $data['show_dates']); $this->assertEquals(true, $data['show_dates']);
$this->assertEquals('http://host.tld/index.php?do=feed', $data['self_link']); $this->assertEquals('http://host.tld/feed/atom', $data['self_link']);
$this->assertEquals('http://host.tld/', $data['index_url']); $this->assertEquals('http://host.tld/', $data['index_url']);
$this->assertFalse($data['usepermalinks']); $this->assertFalse($data['usepermalinks']);
$this->assertEquals(ReferenceLinkDB::$NB_LINKS_TOTAL, count($data['links'])); $this->assertEquals(ReferenceLinkDB::$NB_LINKS_TOTAL, count($data['links']));
@ -253,7 +254,7 @@ public function testBuildDataServerSubdir()
'SERVER_NAME' => 'host.tld', 'SERVER_NAME' => 'host.tld',
'SERVER_PORT' => '8080', 'SERVER_PORT' => '8080',
'SCRIPT_NAME' => '/~user/shaarli/index.php', 'SCRIPT_NAME' => '/~user/shaarli/index.php',
'REQUEST_URI' => '/~user/shaarli/index.php?do=feed', 'REQUEST_URI' => '/~user/shaarli/feed/atom',
); );
$feedBuilder = new FeedBuilder( $feedBuilder = new FeedBuilder(
self::$bookmarkService, self::$bookmarkService,
@ -265,7 +266,7 @@ public function testBuildDataServerSubdir()
$data = $feedBuilder->buildData(FeedBuilder::$FEED_ATOM, null); $data = $feedBuilder->buildData(FeedBuilder::$FEED_ATOM, null);
$this->assertEquals( $this->assertEquals(
'http://host.tld:8080/~user/shaarli/index.php?do=feed', 'http://host.tld:8080/~user/shaarli/feed/atom',
$data['self_link'] $data['self_link']
); );

View file

@ -84,7 +84,7 @@ function (
static::assertInstanceOf(BookmarkRawFormatter::class, $formatter); static::assertInstanceOf(BookmarkRawFormatter::class, $formatter);
static::assertSame($parameters['selection'], $selection); static::assertSame($parameters['selection'], $selection);
static::assertTrue($prependNoteUrl); static::assertTrue($prependNoteUrl);
static::assertSame('http://shaarli', $indexUrl); static::assertSame('http://shaarli/subfolder/', $indexUrl);
return $bookmarks; return $bookmarks;
} }

View file

@ -8,7 +8,7 @@
use Slim\Http\Request; use Slim\Http\Request;
use Slim\Http\Response; use Slim\Http\Response;
class ToolsControllerTestControllerTest extends TestCase class ToolsControllerTest extends TestCase
{ {
use FrontAdminControllerMockHelper; use FrontAdminControllerMockHelper;
@ -41,7 +41,7 @@ public function testDefaultInvokeWithHttps(): void
static::assertSame(200, $result->getStatusCode()); static::assertSame(200, $result->getStatusCode());
static::assertSame('tools', (string) $result->getBody()); static::assertSame('tools', (string) $result->getBody());
static::assertSame('https://shaarli', $assignedVariables['pageabsaddr']); static::assertSame('https://shaarli/', $assignedVariables['pageabsaddr']);
static::assertTrue($assignedVariables['sslenabled']); static::assertTrue($assignedVariables['sslenabled']);
} }
@ -63,7 +63,7 @@ public function testDefaultInvokeWithoutHttps(): void
static::assertSame(200, $result->getStatusCode()); static::assertSame(200, $result->getStatusCode());
static::assertSame('tools', (string) $result->getBody()); static::assertSame('tools', (string) $result->getBody());
static::assertSame('http://shaarli', $assignedVariables['pageabsaddr']); static::assertSame('http://shaarli/', $assignedVariables['pageabsaddr']);
static::assertFalse($assignedVariables['sslenabled']); static::assertFalse($assignedVariables['sslenabled']);
} }
} }

View file

@ -392,8 +392,8 @@ public function testValidRssControllerInvokeDefault(): void
static::assertStringContainsString('application/rss', $result->getHeader('Content-Type')[0]); static::assertStringContainsString('application/rss', $result->getHeader('Content-Type')[0]);
static::assertSame('dailyrss', (string) $result->getBody()); static::assertSame('dailyrss', (string) $result->getBody());
static::assertSame('Shaarli', $assignedVariables['title']); static::assertSame('Shaarli', $assignedVariables['title']);
static::assertSame('http://shaarli', $assignedVariables['index_url']); static::assertSame('http://shaarli/subfolder/', $assignedVariables['index_url']);
static::assertSame('http://shaarli/daily-rss', $assignedVariables['page_url']); static::assertSame('http://shaarli/subfolder/daily-rss', $assignedVariables['page_url']);
static::assertFalse($assignedVariables['hide_timestamps']); static::assertFalse($assignedVariables['hide_timestamps']);
static::assertCount(2, $assignedVariables['days']); static::assertCount(2, $assignedVariables['days']);
@ -402,7 +402,7 @@ public function testValidRssControllerInvokeDefault(): void
static::assertEquals($dates[0], $day['date']); static::assertEquals($dates[0], $day['date']);
static::assertSame($dates[0]->format(\DateTime::RSS), $day['date_rss']); static::assertSame($dates[0]->format(\DateTime::RSS), $day['date_rss']);
static::assertSame(format_date($dates[0], false), $day['date_human']); static::assertSame(format_date($dates[0], false), $day['date_human']);
static::assertSame('http://shaarli/daily?day='. $dates[0]->format('Ymd'), $day['absolute_url']); static::assertSame('http://shaarli/subfolder/daily?day='. $dates[0]->format('Ymd'), $day['absolute_url']);
static::assertCount(1, $day['links']); static::assertCount(1, $day['links']);
static::assertSame(1, $day['links'][0]['id']); static::assertSame(1, $day['links'][0]['id']);
static::assertSame('http://domain.tld/1', $day['links'][0]['url']); static::assertSame('http://domain.tld/1', $day['links'][0]['url']);
@ -413,7 +413,7 @@ public function testValidRssControllerInvokeDefault(): void
static::assertEquals($dates[1], $day['date']); static::assertEquals($dates[1], $day['date']);
static::assertSame($dates[1]->format(\DateTime::RSS), $day['date_rss']); static::assertSame($dates[1]->format(\DateTime::RSS), $day['date_rss']);
static::assertSame(format_date($dates[1], false), $day['date_human']); static::assertSame(format_date($dates[1], false), $day['date_human']);
static::assertSame('http://shaarli/daily?day='. $dates[1]->format('Ymd'), $day['absolute_url']); static::assertSame('http://shaarli/subfolder/daily?day='. $dates[1]->format('Ymd'), $day['absolute_url']);
static::assertCount(2, $day['links']); static::assertCount(2, $day['links']);
static::assertSame(2, $day['links'][0]['id']); static::assertSame(2, $day['links'][0]['id']);
@ -468,8 +468,8 @@ public function testValidRssControllerInvokeNoBookmark(): void
static::assertStringContainsString('application/rss', $result->getHeader('Content-Type')[0]); static::assertStringContainsString('application/rss', $result->getHeader('Content-Type')[0]);
static::assertSame('dailyrss', (string) $result->getBody()); static::assertSame('dailyrss', (string) $result->getBody());
static::assertSame('Shaarli', $assignedVariables['title']); static::assertSame('Shaarli', $assignedVariables['title']);
static::assertSame('http://shaarli', $assignedVariables['index_url']); static::assertSame('http://shaarli/subfolder/', $assignedVariables['index_url']);
static::assertSame('http://shaarli/daily-rss', $assignedVariables['page_url']); static::assertSame('http://shaarli/subfolder/daily-rss', $assignedVariables['page_url']);
static::assertFalse($assignedVariables['hide_timestamps']); static::assertFalse($assignedVariables['hide_timestamps']);
static::assertCount(0, $assignedVariables['days']); static::assertCount(0, $assignedVariables['days']);
} }

View file

@ -79,8 +79,9 @@ protected function createContainer(): void
$this->container->environment = [ $this->container->environment = [
'SERVER_NAME' => 'shaarli', 'SERVER_NAME' => 'shaarli',
'SERVER_PORT' => '80', 'SERVER_PORT' => '80',
'REQUEST_URI' => '/daily-rss', 'REQUEST_URI' => '/subfolder/daily-rss',
'REMOTE_ADDR' => '1.2.3.4', 'REMOTE_ADDR' => '1.2.3.4',
'SCRIPT_NAME' => '/subfolder/index.php',
]; ];
$this->container->basePath = '/subfolder'; $this->container->basePath = '/subfolder';

View file

@ -257,6 +257,39 @@ public function testSaveInstallDefaultValues(): void
static::assertSame('/subfolder/login', $result->getHeader('location')[0]); static::assertSame('/subfolder/login', $result->getHeader('location')[0]);
static::assertSame('UTC', $confSettings['general.timezone']); static::assertSame('UTC', $confSettings['general.timezone']);
static::assertSame('Shared bookmarks on http://shaarli', $confSettings['general.title']); static::assertSame('Shared bookmarks on http://shaarli/subfolder/', $confSettings['general.title']);
}
/**
* Same test as testSaveInstallDefaultValues() but for an instance install in root directory.
*/
public function testSaveInstallDefaultValuesWithoutSubfolder(): void
{
$confSettings = [];
$this->container->environment = [
'SERVER_NAME' => 'shaarli',
'SERVER_PORT' => '80',
'REQUEST_URI' => '/install',
'REMOTE_ADDR' => '1.2.3.4',
'SCRIPT_NAME' => '/index.php',
];
$this->container->basePath = '';
$request = $this->createMock(Request::class);
$response = new Response();
$this->container->conf->method('set')->willReturnCallback(function (string $key, $value) use (&$confSettings) {
$confSettings[$key] = $value;
});
$result = $this->controller->save($request, $response);
static::assertSame(302, $result->getStatusCode());
static::assertSame('/login', $result->getHeader('location')[0]);
static::assertSame('UTC', $confSettings['general.timezone']);
static::assertSame('Shared bookmarks on http://shaarli/', $confSettings['general.title']);
} }
} }

View file

@ -39,6 +39,6 @@ public function testOpenSearchController(): void
$result->getHeader('Content-Type')[0] $result->getHeader('Content-Type')[0]
); );
static::assertSame('opensearch', (string) $result->getBody()); static::assertSame('opensearch', (string) $result->getBody());
static::assertSame('http://shaarli', $assignedVariables['serverurl']); static::assertSame('http://shaarli/subfolder/', $assignedVariables['serverurl']);
} }
} }

View file

@ -5,12 +5,14 @@
namespace Shaarli\Http; namespace Shaarli\Http;
use PHPUnit\Framework\TestCase;
require_once 'application/http/HttpUtils.php'; require_once 'application/http/HttpUtils.php';
/** /**
* Unitary tests for index_url() * Unitary tests for index_url()
*/ */
class IndexUrlTest extends \PHPUnit\Framework\TestCase class IndexUrlTest extends TestCase
{ {
/** /**
* If on the main page, remove "index.php" from the URL resource * If on the main page, remove "index.php" from the URL resource
@ -103,4 +105,36 @@ public function testPageUrlWithRoute()
) )
); );
} }
/**
* The route is stored in REQUEST_URI and subfolder
*/
public function testPageUrlWithRouteUnderSubfolder()
{
$this->assertEquals(
'http://host.tld/subfolder/picture-wall',
page_url(
array(
'HTTPS' => 'Off',
'SERVER_NAME' => 'host.tld',
'SERVER_PORT' => '80',
'SCRIPT_NAME' => '/subfolder/index.php',
'REQUEST_URI' => '/subfolder/picture-wall',
)
)
);
$this->assertEquals(
'http://host.tld/subfolder/admin/picture-wall',
page_url(
array(
'HTTPS' => 'Off',
'SERVER_NAME' => 'host.tld',
'SERVER_PORT' => '80',
'SCRIPT_NAME' => '/subfolder/admin/index.php',
'REQUEST_URI' => '/subfolder/admin/picture-wall',
)
)
);
}
} }

View file

@ -0,0 +1,51 @@
<?php
declare(strict_types=1);
namespace Shaarli\Http;
use PHPUnit\Framework\TestCase;
/**
* Test index_url with SHAARLI_ROOT_URL defined to override automatic retrieval.
* This should stay in its dedicated class to make sure to not alter other tests of the suite.
*/
class IndexUrlTestWithConstant extends TestCase
{
public static function setUpBeforeClass(): void
{
define('SHAARLI_ROOT_URL', 'http://other-host.tld/subfolder/');
}
/**
* The route is stored in REQUEST_URI and subfolder
*/
public function testIndexUrlWithConstantDefined()
{
$this->assertEquals(
'http://other-host.tld/subfolder/',
index_url(
array(
'HTTPS' => 'Off',
'SERVER_NAME' => 'host.tld',
'SERVER_PORT' => '80',
'SCRIPT_NAME' => '/index.php',
'REQUEST_URI' => '/picture-wall',
)
)
);
$this->assertEquals(
'http://other-host.tld/subfolder/',
index_url(
array(
'HTTPS' => 'Off',
'SERVER_NAME' => 'host.tld',
'SERVER_PORT' => '80',
'SCRIPT_NAME' => '/admin/index.php',
'REQUEST_URI' => '/admin/picture-wall',
)
)
);
}
}