Laravel和ngrok:网址和资产的网址不正确

时间:2018-05-05 23:27:48

标签: laravel laravel-5 homestead ngrok vagrant-share

我的设置:

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

我的问题:

如果我vagrant ssh,然后share domfit.test,我会得到一个随机生成的ngrok网址(http://whatever.ngrok.io),但是当我访问此网址时,我的所有资源/路由以http://domfit.test/为前缀(例如http://domfit.test/login

我尝试过以下方法:

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

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

如果我在Homestead.yaml中重命名我的网站(例如改为newdomfit.test)并重新配置,那么这就是url()route()使用的域名,无论我是谁APP_URL。所以Homestead.yaml似乎在强迫该域名。这引出了一个问题 - 您打算如何实际使用共享功能?

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

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

以下编辑

好的,我刚刚再次尝试过。已更改APP_URL的{​​{1}}:

搜索了ngrok的整个代码库,只有一些随机会话文件似乎有引用:

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

domfit.test

然后在我的控制器中我做了一些简单的调试:

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

我不明白http://domfit.test/login http://domfit.test/login domfit.test 04b7beec.ngrok.io 如何返回错误的网址?

看起来它可能与此相关:https://github.com/laravel/valet/issues/342

另一个编辑

看起来它与Homestead的$_SERVER['HTTP_HOST']命令有关:

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

  

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

如果没有它我会使用ngrok,那么显示的网站是不同的(因为我在Homestead配置了多个网站) - 所以我还是不确定如何解决这个问题。暂时我可以禁用其他网站,因为我没有积极开发这些网站。

5 个答案:

答案 0 :(得分:4)

即使您要转至ngrok URL,请求中的主机标头仍将设置为您的站点名称。 Laravel使用主机头以建立链路,资产等ngrok绝对URL包括在X-Original-Host头中的ngrok网址,但Laravel不知道的事情。

有这个问题的两个基本方案:

  1. 更新与合适的服务器和标头值,或
  2. 请求
  3. 使用forceRootUrl()方法忽略服务器和标头值。

<强> TrustedProxies和转发主机

如果使用的是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'));
    }
}

答案 1 :(得分:1)

您可以使用以下方法强制使用最后一个@patricus解决方案的协议:

$this->app['url']->forceScheme('https');

答案 2 :(得分:0)

这是我为<base>标签ngrok问题准备的:

<base href="{{request()->isSecure() ? 'https' : 'http'}}://{{ $_SERVER['HTTP_X_ORIGINAL_HOST'] ?? request()->getHttpHost() }}">

答案 3 :(得分:-1)

我遇到了类似的问题,解决方法如下

在 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

解决方案的完整文档 (link)

答案 4 :(得分:-2)

在app.config和.env文件中,尝试将其更改为:

&#39; URL&#39; =&GT;环境(&#39; APP_URL&#39;,&#39; http://localhost&#39;),