Laravel和Ngrok:URL域对于路由和资产不正确 [英] Laravel and ngrok: url domain is not correct for routes and assets

查看:86
本文介绍了Laravel和Ngrok:URL域对于路由和资产不正确的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的设置:

  • 在Mac OSX上配置了多个站点的Homestead
  • 我有一个使用domfit.test作为本地域的站点设置(使用hostsupdater自动映射)

我的问题:

如果我vagrant ssh,然后又是share domfit.test,则会得到一个随机生成的ngrok url,如您所愿( http: //whatever.ngrok.io ),但是当我访问该URL时,我所有的资源/路由都以http://domfit.test/为前缀(

If I vagrant ssh, and then share domfit.test I get a random generated ngrok url as you'd expect (http://whatever.ngrok.io), however when I access this URL all my resources / routes are being prefixed with http://domfit.test/ (http://domfit.test/login for instance)

我尝试了以下操作:

  • 将APP_URL设置为ngrok URL
  • php artisan config:clear
  • php artisan cache:clear
  • {{ url('login') }}
  • {{ route('login') }}
  • Setting APP_URL as the ngrok URL
  • php artisan config:clear
  • php artisan cache:clear
  • {{ url('login') }}
  • {{ route('login') }}

我的理解是url()应该返回浏览器请求的实际URL(而不是使用APP_URL),但它总是返回domfit.test.

My understanding is that url() should return the actual URL that the browser requested (rather than using APP_URL) but it always returns domfit.test.

如果我在Homestead.yaml中重命名我的站点(例如重命名为newdomfit.test)并重新配置,则这是url()route()使用的域,而与我的APP_URL无关.因此,Homestead.yaml似乎正在强制该域.哪个提出了问题-您实际上打算如何使用共享功能?

If I rename my site in Homestead.yaml (for example to newdomfit.test) and re-provision then this is the domain that url() and route() uses, regardless of my APP_URL. So the Homestead.yaml seems to be forcing that domain. Which begs the question - how are you meant to actually use the share functionality?

我是Laravel的新手,所以我不确定是否所有这些都是预期的行为,并且我误会了什么?

I'm new to Laravel so I am not sure if all of this is expected behavior and I am misunderstanding something?

我只希望模板中的链接和资源可用于本地(domfit.test),共享(ngrok)并最终使用相同的代码进行生产.我担心的是,当我尝试打开此网站时,必须更改所有route()url()引用.

I just want my links and resources in templates to work for local (domfit.test), shared (ngrok) and eventually production with the same piece of code. My worry is I will have to change all of my route() or url() references when I attempt to put this website live.

下方编辑

好的,我再次尝试过.将APP_URL更改为ngrok:

OK I've just tried again. Changed APP_URL for ngrok:

在我的整个代码库中搜索了domfit.test,并且似乎只有一些随机会话文件具有引用:

Searched my entire codebase for domfit.test, and only some random session files seem to have references:

代码/domfit/存储/框架/会话/

code/domfit/storage/framework/sessions/

APP_NAME=DomFit
APP_VERSION=0.01
APP_ENV=local
APP_KEY=XXXX
APP_DEBUG=true
APP_URL=http://04b7beec.ngrok.io

然后在我的控制器中让它进行一些简单的调试:

Then in my Controller I have it doing this for some simple debugging:

echo(url('/login'));
echo(route('login'));
echo($_SERVER['HTTP_HOST']);
echo($_SERVER['HTTP_X_ORIGINAL_HOST']);

如果我使用ngrok URL,则得到的输出是:

If I use the ngrok URL the output I get is:

http://domfit.test/login
http://domfit.test/login
domfit.test
04b7beec.ngrok.io

我不明白$_SERVER['HTTP_HOST']如何返回错误的网址?

I don't understand how $_SERVER['HTTP_HOST'] is returning the wrong url?

它可能与此有关: https://github.com/laravel/代客/问题/342

另一项编辑

似乎与Homestead的share命令有关:

It looks like it has to do with Homestead's share command:

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,根据他们的文档:

Which passes the option -host-header to ngrok which according to their documentation:

某些应用程序服务器,例如WAMP,MAMP和pow,使用Host标头确定要显示的开发站点.因此,ngrok可以使用修改后的Host标头重写您的请求.使用-host-header开关重写传入的HTTP请求.

Some application servers like WAMP, MAMP and pow use the Host header for determining which development site to display. For this reason, ngrok can rewrite your requests with a modified Host header. Use the -host-header switch to rewrite incoming HTTP requests.

如果我不使用ngrok,则显示的网站是一个不同的网站(因为我在Homestead中配置了多个网站)-所以我仍然不确定如何解决这个问题.目前,由于我没有积极开发其他网站,因此我可以将其禁用.

If I use ngrok without it, then the website that gets displayed is a different one (because I have multiple sites configured in Homestead) - so I'm still not sure how to get around this. For the time being I could disable the other sites as I'm not actively developing those.

推荐答案

即使您要使用ngrok网址,请求中的主机标头仍设置为您的站点名称. Laravel使用主机头来构建链接,资产等的绝对URL.ngrok在X-Original-Host头中包含ngrok url,但是Laravel对此一无所知.

Even though you're going to the ngrok url, the host header in the request is still set as the name of your site. Laravel uses the host header to build the absolute url for links, assets, etc. ngrok includes the ngrok url in the X-Original-Host header, but Laravel doesn't know anything about that.

此问题有两种基本解决方案:

There are two basic solutions to the issue:

  1. 使用正确的服务器和标头值更新请求,或者
  2. 使用forceRootUrl()方法忽略服务器和标头值.
  1. update the request with the proper server and header values, or
  2. use the forceRootUrl() method to ignore the server and header values.


受信任的代理和转发的主机

如果使用的是TrustedProxies(Laravel> = 5.5中的默认值),并且已将其配置为信任所有代理(protected $proxies = '*';),则可以将X-Forwarded-Host标头设置为X-Original-Host标头.然后Laravel将使用X-Forwarded-Host标头中的值来构建所有绝对URL.

If you're using TrustedProxies (default in Laravel >= 5.5), and you have it configured to trust all proxies (protected $proxies = '*';), you can set the X-Forwarded-Host header to the X-Original-Host header. Laravel will then use the value in the X-Forwarded-Host header to build all absolute urls.

您可以在Web服务器级别执行此操作.例如,如果您使用的是apache,则可以将其添加到您的public/.htaccess文件中:

You can do this at the web server level. For example, if you're using apache, you can add this to your public/.htaccess file:

# 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()方法中将是一个示例:

If you prefer to handle this in your application instead of the web server, you will need to update the Laravel request. There are plenty of places you could choose to do this, but one example would be in your AppServiceProvider::boot() method:

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标头:

If you're not using TrustedProxies, you can't use the .htaccess method. However, you can still update the server and headers values in your application. In this case, you'd need to overwrite the Host header:

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()


Using forceRootUrl()

如果您不想修改任何标头或Laravel请求,则只需告诉URL生成器要使用的根URL. URL生成器具有forceRootUrl()方法,您可以使用该方法告诉它使用特定的值,而不用查看请求.同样,在您的AppServiceProvider::boot()方法中:

If you don't want to modify any headers or the Laravel request, you can simply tell the URL generator what root url to use. The URL generator has a forceRootUrl() method that you can use to tell it to use a specific value instead of looking at the request. Again, in your AppServiceProvider::boot() method:

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'));
    }
}

这篇关于Laravel和Ngrok:URL域对于路由和资产不正确的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆