Removing trailing slashes from URLs

Lately one of our APIs has logs full of 404 Not Found errors due to trailing slash issues, for example, a resource which lives at /products/1 keeps getting requests made to /products/1/ – returning a 404. Ignoring the log errors, customer frustration and responding to support tickets with “wrong address, idiot” isn’t very pragmatic. So let’s explore the issue.

Whether a trailing slash should appear at the end of a URL isn’t always clear-cut. Articles like this from Google examine the correct use of trailing slashes in more detail and this article does well to highlight the issues from the point of REST APIs. Generally, the question is whether the resource has or will someday have sub-resources, does the URL refer to a singular or collection object in relation to the system?

Accepting both sometimes a reasonable usability compromise, typically by sending a HTTP redirect to the correct version. Using the correct HTTP redirect can have various effects, the 301 Moved Permanently code is a good choice but only works with GET requests, POST, PUT & DELETE will have to use the 307 status code as discussed here

Server Level Solutions:

The quickest and arguably neatest approach is to let the web server take care of the redirect using something like Apache’s mod_rewrite, either modifying the virtual host config or adding a .htaccess file to the base directory being served (e.g. /var/www/my_site/). More information on setting up and using mod_rewrite (if not already running) can be found here.

To add trailing slashes:

RewriteCond %{REQUEST_FILENAME} !-f

RewriteRule ^(.*[^/])$ /$1/ [L,R=301]

or to remove them:

RewriteCond %{REQUEST_FILENAME} !-d

RewriteRule ^(.*)/$ /$1 [L,R=301]

The above is an easy and often acceptable solution but it does have a couple of issues:

  • It will only work with GET requests, not POST, PUT & DELETE (the 307 code discussed above can overcome this)
  • It is a server level solution for an application issue (reducing portability, encapsulation etc).

Let’s look at some application level solutions for either accepting both slash / no slash or using HTTP Redirection codes:


Application Level Solutions:

Accept both URL sets (slash or no slash):

  • In Symfony

Update the relevant routing .yml file with the following:

    pattern: /path{trailingSlash}
    defaults: { _controller: AppBundle:Controller, trailingSlash : "/" }
    requirements: { trailingSlash : "[/]{0,1}" }
  • In Zend

Add [/] to the end of your routes, eg:

'route'    => '/[:controller[/[:action]]]',


'route'    => '/[:controller[/[:action[/]]]]',

Use a HTTP 301 redirect

  • In Symfony

First, create a new redirect controller:

Then, place the following route at the bottom of your routes list:

    path: /{url}
    defaults: { _controller: AppBundle:Redirecting:removeTrailingSlash }
        url: .*/$
    methods: [GET]

From the Symfony Cookbook

  • In Laravel

Create a new route to match all requests with a trailing slash:

Route::get('{any}', function($url){
    return Redirect::to(mb_substr($url, 0, -1), 301);
})->where('any', '(.*)\/$');

From wishfoundry


If there are any more frameworks people would like requested or if people have any code snippets for other frameworks or web servers, please leave a comment.

Programming Cheat Sheets

Great collection of programming language cheat sheets listed in this article.

Nice just to browse them all for fun.

As a follow-up question, what opinions do people have on cheat sheets in aid of teaching or learning new skills? I’ve always found them a great tool but many other teachers proclaim that they’re flawed.

Comments & opinions welcome.

Introduction to Angular 2 Components — Quantix

Introduction to Angular 2 Components A component is a main building block of an Angular 2 application, and an application may have any number of components. We can consider a component a particular view of the application with its own logic and data. In AngularJS 1.0, there was the concept of controllers, $Scope, and […]

via Introduction to Angular 2 Components — Quantix

Node-inspector console not working in latest version of Google Chrome

The latest version of Google Chrome doesn’t execute commands when the Enter button is pressed and instead just wraps to a new line. Fortunately, other than downgrading Chrome, a quicker fix is suggested on the node-inspector issue list here.

First edit the node-inspector config file (as below if installed globally, otherwise from within your project):

$ vi /usr/local/lib/node_modules/node-inspector/front-end/platform/DOMExtension.js

Then search for the isEnterKey function (line 779) and comment out the line:
return event.keyCode !== 229 && event.keyIdentifier === "Enter";
Replacing it with:
return (event.keyCode !== 229 && event.keyIdentifier === "Enter") || event.keyCode === 13;

So the function should now look like:

function isEnterKey(event) {
    return (event.keyCode !== 229 && event.keyIdentifier === "Enter") || event.keyCode === 13;

    // Check if in IME.
    // return event.keyCode !== 229 && event.keyIdentifier === "Enter";

Save, restart node-inspector and your node process manager (e.g. nodemon) and then node-inspector will once again execute console commands via the Enter key.

Web programming language survey

Using Auth0 with Symfony

Auth0 provide a 3rd party authentication service, as they point out this can have a lot of benefits (along with a few drawbacks). They have written a great tutorial on integrating Auth0 with the PHP Symfony framework here:

Do many people have experience using Auth0 to handle their authentication? I’ve never used them and am naturally sceptical about tying my platform to a 3rd party supplier I will have to pay. However it’s so frequent seeing a lot of expensive developer time wasted on an inferior inhouse solutions so is this worth a try?