Fatfree маршрутизация со встроенным веб-сервером PHP - PullRequest
0 голосов
/ 30 августа 2018

Я изучаю маршрут fatfree и обнаружил, что он ведет себя неожиданно.

Вот мой код в index.php:

$f3 = require_once(dirname(dirname(__FILE__)). '/lib/base.php');
$f3 = \Base::instance();

echo 'received uri: '.$_SERVER['REQUEST_URI'].'<br>';

$f3->route('GET /brew/@count',
    function($f3,$params) {
        echo $params['count'].' bottles of beer on the wall.';
    }
);

$f3->run();

и вот URL, к которому я обращаюсь: http://xx.xx.xx.xx:8090/brew/12

Я получаю ошибку 404:

received uri: /brew/12
Not Found

HTTP 404 (GET /12)

странно то, что URI в F3 теперь "/ 12" вместо "/ brew / 12", и я думаю, что это проблема.

Когда я проверяю base.php (3.6.5), $ this-> hive ['BASE'] = "/ brew" и $ this-> hive ['PATH'] = "/ 12". Но если F3 использует только $ this-> hive ['PATH'] для сопоставления с предопределенным маршрутом, он не сможет сопоставить их.

Если я изменю маршрут на:

$f3->route('GET /brew',

и используйте URL: http://xx.xx.xx.xx:8090/brew,, тогда маршрут соответствует без проблем. В этом случае $ this-> hive ['BASE'] = "" и $ this-> hive ['PATH'] = "/ brew". Если F3 сравнивает $ this-> hive ['PATH'] с предопределенным маршрутом, они совпадают друг с другом.

Кстати, я использую встроенный веб-сервер PHP и, поскольку $ _SERVER ['REQUEST_URI'] (который используется base.php) возвращает правильный URI, я не думаю, что с URL-адресом что-то не так переписать в моем .htrouter.php.

Есть идеи? Что я здесь упустил?

добавить содержимое .htrouter.php сюда

<?php

#get the relative URL
$uri = urldecode(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH));

#if request to a real file (such as a html, image, js, css) then leave it as it is
if ($uri !== '/' && file_exists(__DIR__  . $uri)) {
    return false;
}

#if request virtual URL then pass it to the bootstrap file - index.php
$_GET['_url'] = $_SERVER['REQUEST_URI'];
require_once __DIR__ . './public/index.php';

Ответы [ 2 ]

0 голосов
/ 01 сентября 2018

Ваша проблема напрямую связана с тем, как вы используете встроенный веб-сервер PHP.

Как указано в PHP документах , вот как сервер обрабатывает запросы:

URI-запросы поступают из текущего рабочего каталога, где был запущен PHP, если только опция -t не используется для указания явного корня документа. Если в запросе URI не указан файл, возвращаются либо index.php, либо index.html в данном каталоге. Если ни один из файлов не существует, поиск по index.php и index.html будет продолжаться в родительском каталоге и так далее, пока файл не будет найден или корень документа не будет достигнут. Если index.php или index.html найден, он возвращается, и $ _SERVER ['PATH_INFO'] устанавливается на завершающую часть URI. В противном случае возвращается код ответа 404.

Если при запуске веб-сервера в командной строке указан файл PHP, он рассматривается как сценарий «маршрутизатора». Сценарий запускается в начале каждого HTTP-запроса. Если этот скрипт возвращает FALSE, то запрашиваемый ресурс возвращается как есть. В противном случае вывод скрипта возвращается в браузер.

Это означает, что, по умолчанию (без скрипта маршрутизатора), веб-сервер выполняет довольно хорошую работу по маршрутизации несуществующих URI в корневой файл документа index.php.

Другими словами, при условии, что ваша файловая структура имеет вид:

lib/
    base.php
    template.php
    etc.
public/
    index.php

Для запуска сервера и правильной отправки запросов в среду достаточно следующей команды:

php -S 0.0.0.0:8090 -t public/

Или, если вы запускаете команду прямо из общедоступной / папки:

cd public
php -S 0.0.0.0:8090

Помните, что рабочий каталог вашего приложения зависит от папки, из которой вы вызываете команду. Чтобы использовать это значение, я настоятельно рекомендую вам добавить chdir(__DIR__); вверху вашего public/index.php файла. Таким образом, все последующие вызовы require будут относиться к вашей папке public/. Например: $f3 = require('../lib/base.php');

Маршрутизация URI в стиле файла

Встроенный сервер, по умолчанию , не будет передавать несуществующие file URI на ваш index.php, как указано в:

Если в запросе URI не указан файл, возвращаются либо index.php, либо index.html в данном каталоге

Так что, если вы планируете определять некоторые маршруты с точками, например:

$f3->route('GET /brew.json','Brew->json');
$f3->route('GET /brew.html','Brew->html');

Тогда это не сработает, потому что PHP не передаст запрос на index.php.

В этом случае вам необходимо вызвать пользовательский маршрутизатор, например .htrouter.php, который вы пытались использовать. Единственное, что ваш .htrouter.php, очевидно, был разработан для другой платформы (F3 не заботится о $_GET['url'], но заботится о $_SERVER['SCRIPT_NAME'].

Вот пример .htrouter.php, который должен работать с F3:

// public directory definition
$public_dir=__DIR__.'/public';

// serve existing files as-is
if (file_exists($public_dir.$_SERVER['REQUEST_URI']))
    return FALSE;

// patch SCRIPT_NAME and pass the request to index.php
$_SERVER['SCRIPT_NAME']='index.php';
require($public_dir.'/index.php');

Примечание: переменная $public_dir должна быть установлена ​​в соответствии с расположением файла .htrouter.php.

Например, если вы звоните:

php -S 0.0.0.0:8090 -t public/ .htrouter.php

должно быть $public_dir=__DIR__.'/public'.

Но если вы позвоните:

cd public
php -S 0.0.0.0:8090 .htrouter.php

должно быть $public_dir=__DIR__.

0 голосов
/ 01 сентября 2018

ОК, я проверил base.php и выяснил, когда f3 вычисляет базовый URI, он использует $ _SERVER ['SCRIPT_NAME'].

$base='';
if (!$cli)
    $base=rtrim($this->fixslashes(
        dirname($_SERVER['SCRIPT_NAME'])),'/');

если у нас есть веб-сервер, который перенаправляет все запросы на index.php, то _SERVER ['SCRIPT_NAME'] = /index.php, и в этом случае base будет ''.

если мы используем перезапись URL через .htrouter.php для index.php, то _SERVER ['SCRIPT_NAME'] = / brew / 12, и в этом случае base - '/ brew', что вызывает проблему.

Поскольку я собираюсь использовать перезапись URL-адреса, я должен закомментировать оператор if и убедиться, что base = ''.

Спасибо xfra35 за подсказку.

...