Fixing bad base url

This commit is contained in:
SergiX44 2019-11-18 11:42:42 +01:00
parent 7e5a156939
commit 399901c7a8
8 changed files with 56 additions and 55 deletions

View file

@ -47,11 +47,11 @@ XBackBone require PHP >= `7.1`, with installed the required extensions:
cp config.example.php config.php && nano config.php
```
By default, XBackBone will use Sqlite3 as DB engine, and a `storage` dir in the main directory. You can leave these settings unchanged for a simple personal installation.
You must set the `base_path`, or remove it for get dynamically the url from request (not recommended).
You must set the `base_url`, or remove it for get dynamically the url from request (not recommended).
```php
return [
'base_path' => '/',
'base_url' => 'https://example.com', // no trailing slash
'storage' => [
'driver' => 'local',
'path' => 'storage',

View file

@ -187,8 +187,8 @@ if (!function_exists('urlFor')) {
*/
function urlFor(string $path = '', string $append = ''): string
{
global $app;
return $app->getBasePath().$path.$append;
$baseUrl = resolve('config')['base_url'];
return $baseUrl.$path.$append;
}
}
@ -377,3 +377,16 @@ if (!function_exists('glob_recursive')) {
return $files;
}
}
if (!function_exists('dsnFromConfig')) {
/**
* Return the database DSN from config.
* @param array $config
* @return string
*/
function dsnFromConfig(array $config): string
{
$dsn = $config['db']['connection'] === 'sqlite' ? BASE_DIR.$config['db']['dsn'] : $config['db']['dsn'];
return $config['db']['connection'].':'.$dsn;
}
}

View file

@ -12,9 +12,6 @@ use Aws\S3\S3Client;
use DI\Bridge\Slim\Bridge;
use DI\ContainerBuilder;
use Google\Cloud\Storage\StorageClient;
use GuzzleHttp\Psr7\Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;
use League\Flysystem\Adapter\Ftp as FtpAdapter;
use League\Flysystem\Adapter\Local;
use League\Flysystem\AwsS3v3\AwsS3Adapter;
@ -23,6 +20,8 @@ use Monolog\Formatter\LineFormatter;
use Monolog\Handler\RotatingFileHandler;
use Monolog\Logger;
use Psr\Container\ContainerInterface as Container;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;
use Spatie\Dropbox\Client as DropboxClient;
use Spatie\FlysystemDropbox\DropboxAdapter;
use Superbalist\Flysystem\GoogleStorage\GoogleStorageAdapter;
@ -41,7 +40,7 @@ if (!file_exists('config.php') && is_dir('install/')) {
// Load the config
$config = array_replace_recursive([
'app_name' => 'XBackBone',
'base_path' => $_SERVER['REQUEST_URI'],
'base_url' => isset($_SERVER['HTTPS']) ? 'https://'.$_SERVER['HTTP_HOST'] : 'http://'.$_SERVER['HTTP_HOST'],
'debug' => false,
'maintenance' => false,
'db' => [
@ -65,7 +64,7 @@ if (!$config['debug']) {
$builder->addDefinitions([
'config' => value($config),
'logger' => factory(function (Container $container) {
'logger' => factory(function () {
$logger = new Logger('app');
$streamHandler = new RotatingFileHandler(BASE_DIR.'logs/log.txt', 10, Logger::DEBUG);
@ -80,14 +79,13 @@ $builder->addDefinitions([
return $logger;
}),
'session' => factory(function (Container $container) {
'session' => factory(function () {
return new Session('xbackbone_session', BASE_DIR.'resources/sessions');
}),
'database' => factory(function (Container $container) {
$config = $container->get('config');
$dsn = $config['db']['connection'] === 'sqlite' ? BASE_DIR.$config['db']['dsn'] : $config['db']['dsn'];
return new DB($config['db']['connection'].':'.$dsn, $config['db']['username'], $config['db']['password']);
return new DB(dsnFromConfig($config), $config['db']['username'], $config['db']['password']);
}),
'storage' => factory(function (Container $container) {
@ -145,7 +143,7 @@ $builder->addDefinitions([
]);
$app = Bridge::create($builder->build());
$app->setBasePath(substr($config['base_path'], 0, -1));
$app->setBasePath(parse_url($config['base_url'], PHP_URL_PATH));
if (!$config['debug']) {
$app->getRouteCollector()->setCacheFile(BASE_DIR.'resources/cache/routes.cache.php');
@ -155,18 +153,18 @@ $app->add(InjectMiddleware::class);
$app->add(RememberMiddleware::class);
// Permanently redirect paths with a trailing slash to their non-trailing counterpart
$app->add(function (Request $request, RequestHandler $handler) use (&$config) {
$app->add(function (Request $request, RequestHandler $handler) use (&$app, &$config) {
$uri = $request->getUri();
$path = $uri->getPath();
if ($path !== $config['base_path'] && substr($path, -1) === '/') {
if ($path !== $app->getBasePath().'/' && substr($path, -1) === '/') {
// permanently redirect paths with a trailing slash
// to their non-trailing counterpart
$uri = $uri->withPath(substr($path, 0, -1));
if ($request->getMethod() == 'GET') {
$response = new Response();
return $response->withStatus(301)
if ($request->getMethod() === 'GET') {
return $app->getResponseFactory()
->createResponse(301)
->withHeader('Location', (string)$uri);
} else {
$request = $request->withUri($uri);

View file

@ -1,6 +1,6 @@
<?php
return [
'base_path' => '/',
'base_url' => 'https://localhost', // no trailing slash
'db' => [
'connection' => 'sqlite',
'dsn' => 'resources/database/xbackbone.db',

View file

@ -11,17 +11,17 @@ use Aws\S3\S3Client;
use DI\Bridge\Slim\Bridge;
use DI\ContainerBuilder;
use Google\Cloud\Storage\StorageClient;
use League\Flysystem\Adapter\Ftp as FtpAdapter;
use League\Flysystem\Adapter\Local;
use League\Flysystem\AwsS3v3\AwsS3Adapter;
use League\Flysystem\Adapter\Ftp as FtpAdapter;
use League\Flysystem\FileExistsException;
use Spatie\Dropbox\Client as DropboxClient;
use League\Flysystem\Filesystem;
use Psr\Container\ContainerInterface as Container;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Spatie\Dropbox\Client as DropboxClient;
use Spatie\FlysystemDropbox\DropboxAdapter;
use Superbalist\Flysystem\GoogleStorage\GoogleStorageAdapter;
use Psr\Container\ContainerInterface as Container;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Message\ResponseInterface as Response;
use function DI\factory;
use function DI\get;
use function DI\value;
@ -31,7 +31,7 @@ define('BASE_DIR', realpath(__DIR__.'/../').DIRECTORY_SEPARATOR);
// default config
$config = [
'base_path' => $_SERVER['REQUEST_URI'],
'base_url' => str_replace('/install/', '', (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http')."://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]"),
'debug' => true,
'db' => [
'connection' => 'sqlite',
@ -106,10 +106,10 @@ $builder->addDefinitions([
]);
$app = Bridge::create($builder->build());
$app->setBasePath($_SERVER['REQUEST_URI']);
$app->setBasePath(parse_url($config['base_url'].'/install', PHP_URL_PATH));
$app->addRoutingMiddleware();
$app->get('', function (Response $response, View $view, Session $session) use (&$config) {
$app->get('/', function (Response $response, View $view, Session $session) use (&$config) {
if (!extension_loaded('gd')) {
$session->alert('The required "gd" extension is not loaded.', 'danger');
@ -142,12 +142,11 @@ $app->get('', function (Response $response, View $view, Session $session) use (&
$installed = file_exists(__DIR__.'/../config.php');
return $view->render($response, 'install.twig', [
'installed' => $installed,
'app_path' => str_replace('install/', '', $config['base_path']),
'installed' => $installed
]);
})->setName('install');
$app->post('', function (Request $request, Response $response, Filesystem $storage, Session $session) use (&$config) {
$app->post('/', function (Request $request, Response $response, Filesystem $storage, Session $session) use (&$config) {
// Check if there is a previous installation, if not, setup the config file
$installed = true;
@ -155,7 +154,7 @@ $app->post('', function (Request $request, Response $response, Filesystem $stora
$installed = false;
// config file setup
$config['base_path'] = param($request, 'base_path');
$config['base_url'] = param($request, 'base_url');
$config['storage']['driver'] = param($request, 'storage_driver');
unset($config['debug']);
$config['db']['connection'] = param($request, 'connection');
@ -179,7 +178,7 @@ $app->post('', function (Request $request, Response $response, Filesystem $stora
case 'ftp':
if (!extension_loaded('ftp')) {
$session->alert('The "ftp" extension is not loaded.', 'danger');
return redirect($response, urlFor());
return redirect($response, urlFor('/'));
}
$config['storage']['host'] = param($request, 'storage_host');
$config['storage']['username'] = param($request, 'storage_username');
@ -216,7 +215,7 @@ $app->post('', function (Request $request, Response $response, Filesystem $stora
$storage->readAndDelete($storageTestFile);
} catch (Exception $e) {
$session->alert("Storage setup error: {$e->getMessage()} [{$e->getCode()}]", 'danger');
return redirect($response, urlFor());
return redirect($response, urlFor('/install'));
}
// if from older installations with no support of other than local driver
@ -227,31 +226,21 @@ $app->post('', function (Request $request, Response $response, Filesystem $stora
unset($config['storage_dir']);
}
// if from 2.x versions
// update the config
if ($installed && isset($config['base_url'])) {
$path = parse_url($config['base_url'], PHP_URL_PATH);
$config['base_path'] = $path.'/';
unset($config['base_url']);
}
// Build the dns string and run the migrations
try {
$firstMigrate = false;
if ($config['db']['connection'] === 'sqlite' && !file_exists(__DIR__.'/../'.$config['db']['dsn'])) {
touch(__DIR__.'/../'.$config['db']['dsn']);
$firstMigrate = true;
}
$dsn = $config['db']['connection'] === 'sqlite' ? __DIR__.'/../'.$config['db']['dsn'] : $config['db']['dsn'];
$db = new DB($config['db']['connection'].':'.$dsn, $config['db']['username'], $config['db']['password']);
$db = new DB(dsnFromConfig($config), $config['db']['username'], $config['db']['password']);
$migrator = new Migrator($db, __DIR__.'/../resources/schemas', $firstMigrate);
$migrator->migrate();
} catch (PDOException $e) {
$session->alert("Cannot connect to the database: {$e->getMessage()} [{$e->getCode()}]", 'danger');
return redirect($response, urlFor());
return redirect($response, urlFor('/install'));
}
// if not installed, create the default admin account
@ -279,7 +268,7 @@ $app->post('', function (Request $request, Response $response, Filesystem $stora
// Installed successfully, destroy the installer session
$session->destroy();
return redirect($response, "{$config['base_path']}?afterInstall=true");
return redirect($response, urlFor('/?afterInstall=true'));
});
$app->run();

View file

@ -27,9 +27,10 @@
<form method="post" action="">
{% if not installed %}
<div class="form-group row">
<label for="base_path" class="col-sm-3 col-form-label">Base Path</label>
<label for="base_url" class="col-sm-3 col-form-label">Base URL</label>
<div class="col-sm-9">
<input type="text" class="form-control" id="base_path" name="base_path" value="{{ app_path }}" autocomplete="off" required>
<input type="text" class="form-control" id="base_url" name="base_url" value="{{ config.base_url }}" autocomplete="off" required>
<small>No trailing slash.</small>
</div>
</div>
<hr>

View file

@ -21,7 +21,7 @@
<link href="{{ asset('/static/app/app.css') }}" rel="stylesheet">
<script>
window.AppConfig = {
'base_path': '{{ urlFor() }}',
'base_url': '{{ urlFor() }}',
'max_upload_size': {{ maxUploadSize }},
'lang': {'publish': '{{ lang('publish') }}', 'hide': '{{ lang('hide') }}', 'dropzone': '{{ lang('drop_to_upload') }}'}
}

View file

@ -51,7 +51,7 @@ var app = {
var isOutline = false;
if ($(this).data('published')) {
isOutline = $callerButton.hasClass('btn-outline-warning');
$.post(window.AppConfig.base_path + '/upload/' + id + '/unpublish', function () {
$.post(window.AppConfig.base_url + '/upload/' + id + '/unpublish', function () {
$callerButton
.data('published', false)
.tooltip('dispose')
@ -64,7 +64,7 @@ var app = {
});
} else {
isOutline = $callerButton.hasClass('btn-outline-info');
$.post(window.AppConfig.base_path + '/upload/' + id + '/publish', function () {
$.post(window.AppConfig.base_url + '/upload/' + id + '/publish', function () {
$callerButton
.data('published', true)
.tooltip('dispose')
@ -80,7 +80,7 @@ var app = {
mediaDelete: function () {
var id = $(this).data('id');
var $callerButton = $(this);
$.post(window.AppConfig.base_path + '/upload/' + id + '/delete', function () {
$.post(window.AppConfig.base_url + '/upload/' + id + '/delete', function () {
$callerButton.tooltip('dispose');
$('#media_' + id).fadeOut(200, function () {
$(this).remove();
@ -89,14 +89,14 @@ var app = {
},
refreshToken: function () {
var id = $(this).data('id');
$.post(window.AppConfig.base_path + '/user/' + id + '/refreshToken', function (data) {
$.post(window.AppConfig.base_url + '/user/' + id + '/refreshToken', function (data) {
$('#token').val(data);
});
},
loadThemes: function (e) {
e.preventDefault();
var $themes = $('#themes');
$.get(window.AppConfig.base_path + '/system/themes', function (data) {
$.get(window.AppConfig.base_url + '/system/themes', function (data) {
$themes.empty();
$.each(data, function (key, value) {
var opt = document.createElement('option');
@ -114,7 +114,7 @@ var app = {
checkForUpdates: function () {
$('#checkForUpdatesMessage').empty().text('...');
$('#doUpgradeButton').prop('disabled', true);
$.get(window.AppConfig.base_path + '/system/checkForUpdates?prerelease=' + $(this).data('prerelease'), function (data) {
$.get(window.AppConfig.base_url + '/system/checkForUpdates?prerelease=' + $(this).data('prerelease'), function (data) {
$('#checkForUpdatesMessage').empty().text(data.message);
if (data.upgrade) {
$('#doUpgradeButton').prop('disabled', false);