My setup:
This is what I came up for my <base>
tag ngrok issue:
<base href="{{request()->isSecure() ? 'https' : 'http'}}://{{ $_SERVER['HTTP_X_ORIGINAL_HOST'] ?? request()->getHttpHost() }}">
In your app.config and .env file, try changing it to:
'url' => env('APP_URL', 'http://localhost'),
You can force the protocol with the last @patricus solution using this:
$this->app['url']->forceScheme('https');
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:
forceRootUrl()
method to ignore the server and header values.TrustedProxies and Forwarded Host
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.
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}]
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'));
}
}
Not Using TrustedProxies
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'));
}
}
Using forceRootUrl()
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'));
}
}