我的设置:
我的问题:
如果我vagrant ssh
,然后share domfit.test
我得到一个随机生成的ngrok url,你可以期待(http://whatever.ngrok.io),但是当我访问这个URL时,我的所有资源/路由都以http://domfit.test/
为前缀(例如http://domfit.test/login)
我尝试过以下方法:
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']);
如果我使用ngrok
URL,我得到的输出是:
http://domfit.test/login
http://domfit.test/login
domfit.test
04b7beec.ngrok.io
我不明白$_SERVER['HTTP_HOST']
如何返回错误的网址?
看起来它可能与此有关:https://github.com/laravel/valet/issues/342
另一个编辑
看起来它与Homestead的share
命令有关:
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配置了多个网站) - 所以我仍然不确定如何解决这个问题。暂时我可以禁用其他网站,因为我没有积极开发这些网站。
即使您要访问ngrok网址,请求中的主机标头仍会设置为您网站的名称。 Laravel使用主机头来为链接,资产等构建绝对URL .ngrok包含X-Original-Host
头中的ngrok url,但Laravel对此一无所知。
该问题有两个基本解决方案:
forceRootUrl()
方法忽略服务器和标头值。TrustedProxies和Forwarded Host
如果您正在使用TrustedProxies(Laravel> = 5.5中的默认值),则可以将X-Forwarded-Host
标头设置为X-Original-Host
标头。然后,Laravel将使用X-Forwarded-Host
标头中的值来构建所有绝对URL。
您可以在Web服务器级别执行此操作。例如,如果您使用的是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}]
如果您希望在应用程序而不是Web服务器中处理此问题,则需要更新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'));
}
}
这就是我提出的<base>
标签ngrok问题:
<base href="{{request()->isSecure() ? 'https' : 'http'}}://{{ $_SERVER['HTTP_X_ORIGINAL_HOST'] ?? request()->getHttpHost() }}">
在app.config和.env文件中,尝试将其更改为:
'url'=> env('APP_URL','http://localhost'),