Laravel url() или route() не возвращают правильное имя домена
Моя настройка:
- Усадьба на Mac OSX с несколькими настроенными сайтами
- У меня есть одна установка сайта с использованием domfit.test в качестве локального домена (автоматически сопоставляется с помощью hostsupdater)
Моя проблема:
Если я vagrant ssh
, а потом share domfit.test
Я получаю случайный сгенерированный URL-адрес ngrok, как и следовало ожидать ( http://whatever.ngrok.io/), однако при доступе к этому URL-адресу все мои ресурсы / маршруты начинаются с префикса http://domfit.test/
( http://domfit.test/login например)
Я пробовал следующее:
- Установка APP_URL в качестве URL-адреса ngrok
php artisan config:clear
php artisan cache:clear
{{ url('login') }}
{{ route('login') }}
Насколько я понимаю, url() должен возвращать фактический URL, который запрашивал браузер (а не использовать APP_URL), но он всегда возвращает domfit.test
Если я переименую свой сайт в Homestead.yaml (например, в newdomfit.test) и повторно предоставлю его, то это домен, который используют url() и route() независимо от моего APP_URL. Таким образом, Homestead.yaml, похоже, форсирует этот домен. Возникает вопрос: как вы на самом деле собираетесь использовать функцию общего доступа?
Я новичок в Laravel, поэтому я не уверен, является ли все это ожидаемым поведением, и я что-то неправильно понимаю?
Я просто хочу, чтобы мои ссылки и ресурсы в шаблонах работали для локального (domfit.test), общего доступа (ngrok) и в конечном итоге для производства с одним и тем же кусочком кода. Я беспокоюсь о том, что мне придется изменить все ссылки на route() или url(), когда я попытаюсь запустить этот веб-сайт
РЕДАКТИРОВАТЬ НИЖЕ
ОК, я только что попробовал еще раз. Изменено APP_URL для ngrok:
Искал всю мою кодовую базу для domfit.test, и только некоторые случайные файлы сеанса, кажется, имеют ссылки:
код / domfit/ хранение / рамки / сессия /
APP_NAME=DomFit
APP_VERSION=0.01
APP_ENV=local
APP_KEY=XXXX
APP_DEBUG=true
APP_URL=http://04b7beec.ngrok.io
Затем в моем контроллере я делаю это для некоторой простой отладки:
echo(url('/login'));
echo(route('login'));
echo($_SERVER['HTTP_HOST']);
echo($_SERVER['HTTP_X_ORIGINAL_HOST']);
Если я использую URL ngrok, то получаю вывод:
http://domfit.test/login
http://domfit.test/login
domfit.test
04b7beec.ngrok.io
Я не понимаю, как $_SERVER['HTTP_HOST'] возвращает неправильный URL?
Мой нгрок все еще живет по адресу - http://04b7beec.ngrok.io/
Похоже, это может быть связано с этим: https://github.com/laravel/valet/issues/342
ДРУГОЕ РЕДАКТИРОВАНИЕ
Похоже, это связано с командой Share Homesteads:
function share() {
if [[ "$1" ]]
then
ngrok http ${@:2} -host-header="$1" 80
else
echo "Error: missing required parameters."
echo "Usage: "
echo " share domain"
echo "Invocation with extra params passed directly to ngrok"
echo " share domain -region=eu -subdomain=test1234"
fi
}
Который передает параметр -host-header в ngrok, который согласно их документации:
Некоторые серверы приложений, такие как WAMP, MAMP и pow, используют заголовок Host для определения того, какой сайт разработки отображать. По этой причине ngrok может переписать ваши запросы с измененным заголовком Host. Используйте ключ -host-header для перезаписи входящих HTTP-запросов.
Если я использую ngrok без него, то отображаемый веб-сайт будет другим (потому что в Homestead настроено несколько сайтов), поэтому я все еще не уверен, как обойти это. В настоящее время я могу отключить другие сайты, так как я не активно занимаюсь их разработкой.
5 ответов
Несмотря на то, что вы переходите на URL-адрес ngrok, заголовок узла в запросе по-прежнему задается как имя вашего сайта. Laravel использует заголовок узла для создания абсолютного URL-адреса для ссылок, ресурсов и т. Д. Ngrok включает в себя URL-адрес ngrok X-Original-Host
заголовок, но Laravel ничего не знает об этом.
Есть два основных решения проблемы:
- обновить запрос с соответствующими значениями сервера и заголовка, или
- использовать
forceRootUrl()
способ игнорировать значения сервера и заголовка.
TrustedProxies и переадресованный хост
Если вы используете TrustedProxies (по умолчанию в Laravel >= 5.5), вы можете установить X-Forwarded-Host
заголовок к X-Original-Host
заголовок. Laravel будет использовать значение в X-Forwarded-Host
заголовок, чтобы построить все абсолютные URL.
Вы можете сделать это на уровне веб-сервера. Например, если вы используете Apache, вы можете добавить это в свой public/.htaccess
файл:
# Handle ngrok X-Original-Host Header
RewriteCond %{HTTP:X-Original-Host} \.ngrok\.io$ [NC]
RewriteRule .* - [E=HTTP_X_FORWARDED_HOST:%{HTTP:X-Original-Host}]
Если вы предпочитаете обрабатывать это в своем приложении, а не на веб-сервере, вам необходимо обновить запрос Laravel. Есть много мест, где вы можете сделать это, но один пример будет в вашем AppServiceProvider::boot()
метод:
public function boot(\Illuminate\Http\Request $request)
{
if ($request->server->has('HTTP_X_ORIGINAL_HOST')) {
$request->server->set('HTTP_X_FORWARDED_HOST', $request->server->get('HTTP_X_ORIGINAL_HOST'));
$request->headers->set('X_FORWARDED_HOST', $request->server->get('HTTP_X_ORIGINAL_HOST'));
}
}
Не использовать TrustedProxies
Если вы не используете TrustedProxies, вы не можете использовать .htaccess
метод. Однако вы все равно можете обновить значения сервера и заголовков в вашем приложении. В этом случае вам нужно перезаписать заголовок Host:
public function boot(\Illuminate\Http\Request $request)
{
if ($request->server->has('HTTP_X_ORIGINAL_HOST')) {
$request->server->set('HTTP_HOST', $request->server->get('HTTP_X_ORIGINAL_HOST'));
$request->headers->set('HOST', $request->server->get('HTTP_X_ORIGINAL_HOST'));
}
}
С помощьюforceRootUrl()
Если вы не хотите изменять какие-либо заголовки или запрос Laravel, вы можете просто указать генератору URL, какой корневой URL использовать. Генератор URL имеет forceRootUrl()
метод, который вы можете использовать, чтобы указать ему использовать конкретное значение вместо просмотра запроса. Опять в вашем AppServiceProvider::boot()
метод:
public function boot(\Illuminate\Http\Request $request)
{
if ($request->server->has('HTTP_X_ORIGINAL_HOST')) {
$this->app['url']->forceRootUrl($request->server->get('HTTP_X_FORWARDED_PROTO').'://'.$request->server->get('HTTP_X_ORIGINAL_HOST'));
}
}
Вы можете принудительно использовать протокол с помощью последнего решения @patricus, используя это:
$this->app['url']->forceScheme('https');
Это то, что я придумала для моего <base>
тег ngrok Issue:
<base href="{{request()->isSecure() ? 'https' : 'http'}}://{{ $_SERVER['HTTP_X_ORIGINAL_HOST'] ?? request()->getHttpHost() }}">
В файле app.config и.env попробуйте изменить его на:
'url' => env ('APP_URL', ' http://localhost/'),
У меня аналогичная проблема, и я решил ее, как показано ниже.
В AppServiceProvider.php добавьте ниже проверку внутри
boot()
if (!empty( env('NGROK_URL') ) && $request->server->has('HTTP_X_ORIGINAL_HOST')) {
$this->app['url']->forceRootUrl(env('NGROK_URL'));
}
Также в вашем
.env
добавить ниже запись
NGROK_URL=xxxx.ngrok.io
Полный документ решения (ссылка)