If you have a Laravel project, you might be surprised to find your routes are probably available on a number of different URLs.
Imagine the following example from your routes file:
<?php
Route::view('/feature/uptime-monitoring', 'front/feature/uptime-monitoring');
This creates a route at yourdomain.tld/feature/uptime-monitoring
, which you’d expect.
But in most webserver configs, this means the following URLs are all valid and will all return an HTTP/1.1 200 OK
with the same page:
https://ohdear.app/feature/uptime-monitoring
https://ohdear.app/index.php/feature/uptime-monitoring
What’s that index.php
doing in there? It’s needed for some hosting environments that don’t support pretty-printed URLs.
But you might not need/want it, so let’s get rid of it!
Removing index.php from within your Laravel code
One way to get rid of it, is to check the route in Laravel and issue a redirect there if needed.
Here’s one way to do this in app/Providers/RouteServiceProvider.php
.
<?php
use Illuminate\Support\Str;
class RouteServiceProvider extends ServiceProvider
{
public function map(Router $router)
{
$this->removeIndexPhpFromUrl();
}
protected function removeIndexPhpFromUrl()
{
if (Str::contains(request()->getRequestUri(), '/index.php/')) {
$url = str_replace('index.php/', '', request()->getRequestUri());
if (strlen($url) > 0) {
header("Location: $url", true, 301);
exit;
}
}
}
}
This will redirect any URL with index.php in it.
$ curl -I "http://ohdear.app.test/index.php/pricing"
HTTP/1.1 301 Moved Permanently
Location: /pricing
$ curl -i "http://ohdear.app.test/index.php/feature/uptime-monitoring"
HTTP/1.1 301 Moved Permanently
Location: /feature/uptime-monitoring
There are some alternative ways to get the same result, by redirecting on the webserver itself.
Redirecting index.php in Nginx
You can redirect if index.php is in the URL like this.
if ($request_uri ~* "^/index\.php(/?)(.*)") {
return 301 $2;
}
You might have to repeat this if you have different location {}
blocks in your Nginx config.
Redirecting index.php in Apache
You can add an additional line in your .htaccess
.
$ cat .htaccess
<IfModule mod_rewrite.c>
RewriteEngine On
# Redirect if index.php is in the URL
RewriteRule ^index.php/(.+) /$1 [R=301,L]
</IfModule>
At least that’s an easy regex/fix. :-)
Redirecting index.php in Caddy
It’s a bit cumbersome, but this seems to work in Caddy.
$ cat Caddyfile
https:// {
tls {
ask https://ohdear.app/caddy/allowed-domain
}
rewrite {
regexp ^/index.php/(.*)
to /{1}
}
redir {
if {uri} not {rewrite_uri}
/ {rewrite_uri}
}
}
It requires an internal rewrite
to match the index.php and then a redir
to redirect the actual request.