Skip to content

Instantly share code, notes, and snippets.

@coreywelch
Last active April 28, 2023 19:19
Show Gist options
  • Save coreywelch/2de40f93a252da3b2eddc013a98b3d37 to your computer and use it in GitHub Desktop.
Save coreywelch/2de40f93a252da3b2eddc013a98b3d37 to your computer and use it in GitHub Desktop.
Here is a middleware class for laravel 5 that takes incoming routes and forces them to lowercase.
<?php
namespace App\Http\Middleware;
use Closure;
use \Illuminate\Support\Facades\Redirect;
class LowercaseRoutes
{
/**
* Run the request filter.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
if(!ctype_lower(preg_replace('/[^A-Za-z]/', '', $request->path()))){
$new_route = str_replace($request->path(), strtolower($request->path()), $request->fullUrl());
return Redirect::to($new_route, 301);
}
return $next($request);
}
}
@iceblade112
Copy link

This creates a redirect loop when accessing /. Any ideas? 😕

@mattbucci
Copy link

changed line 19 to if ( ! ctype_lower(preg_replace('/[^A-Za-z]/', '', $request->path())) && $request->path() !== "/") {

to solve iceblade's issue

@samthomson
Copy link

nice 👍

@pridit
Copy link

pridit commented May 26, 2018

What is the license on this please?

@coreywelch
Copy link
Author

coreywelch commented Oct 24, 2018

What is the license on this please?

Never really thought about that, just sharing what I made. But, If I had to throw a license on it it would be MIT. That's what Laravel is licensed under.

@jgusta
Copy link

jgusta commented Dec 17, 2019

Thank you for this middleware.

A caveat with this is that you can't add it as a middleware group because the route has to match before the middleware is run on it. For example you can't use it like this:

Route::middleware(['lowercase'])->group(function () {
    Route::get('/tos', function () {
        return View::make('tos');
    });
});

... because the middleware won't run unless it matches the lowercased route in the first place!

So for those who don't want to have this on your global middleware stack, you can add a catch all route at the very end of your route file. Using the wildcard where() will ensure that the route matches and thus the middleware runs. This will only run the middleware if no other route matched so far just try a lowercased version of the route before hitting 404.

Edit: WARNING! This has the possibility to break any packages that install their own routes, such as Nova. This is because they run AFTER your web.php and thus a catch-all in your web.php will STOP all routes that happen after it from working!

// Catch all route for unmatched routes.
// This will attempt a lowercase version of the route (if there were capitals) and then
// re-sent through the router, landing in the function below if nothing is matched
// If it was all lowercase already then it is sent directly to the 404 below.
Route::middleware(['lowercase'])->group(function () {
    Route::get('{rest}', function($rest) {
        // if no match after lowercasing, then this is called
        abort(404);
    })->where('rest', '.*');
});

Edit: note that I have registered the middleware as 'lowercase' in the $routeMiddleware array in my Kernel.php.

@Vitsen15
Copy link

Vitsen15 commented Jan 4, 2021

Thank you for this gist!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment