13

我的设置:

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

我的问题:

如果我vagrant ssh,然后share domfit.test我得到一个随机生成的 ngrok url,正如你所期望的(http://whatever.ngrok.io),但是当我访问这个 URL 时,我所有的资源/路由都带有前缀http://domfit.test/http://domfit .test/login例如)

我尝试了以下方法:

  • 将 APP_URL 设置为 ngrok URL
  • 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_URLngrok

在我的整个代码库中搜索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']);

如果我使用ngrokURL,我得到的输出是:

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 中配置了多个网站) - 所以我仍然不确定如何解决这个问题。暂时我可以禁用其他网站,因为我没有积极开发这些网站。

4

5 回答 5

24

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

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

  1. 使用正确的服务器和标头值更新请求,或者
  2. 使用该forceRootUrl()方法忽略服务器和标头值。

TrustedProxies 和转发主机

如果您使用的是 TrustedProxies(Laravel 中的默认值 >= 5.5),并且您已将其配置为信任所有代理 ( protected $proxies = '*';),则可以将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'));
    }
}

不使用 TrustedProxy

如果您没有使用 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'));
    }
}
于 2019-02-02T00:53:37.330 回答
1

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

$this->app['url']->forceScheme('https');
于 2020-08-19T07:03:12.867 回答
0

这就是我为我的<base>标签 ngrok 问题提出的:

<base href="{{request()->isSecure() ? 'https' : 'http'}}://{{ $_SERVER['HTTP_X_ORIGINAL_HOST'] ?? request()->getHttpHost() }}">
于 2019-04-01T15:56:14.390 回答
-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

解决方案的完整文档(链接

于 2021-03-27T13:50:47.310 回答
-3

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

'url' => env('APP_URL', ' http://localhost '),

于 2018-05-06T23:02:17.807 回答