Strip/add slash to route path using middleware?

6,479 views
Skip to first unread message

richardhenry

unread,
Mar 21, 2011, 8:03:22 PM3/21/11
to Express
Hey there,

If I create the route:

app.get('/about', function(req, res) {
res.send('hello');
});

Is it possible to have requests to '/about/' redirected to '/about' ?

Ideally in turn, if I created the route:

app.get('/users/', function(req, res) {
res.send('list of users');
});

Requests to '/users' would be redirected to '/users/'.

Would this be feasible to do using middleware?

Thanks!

Richard

Laurie Harper

unread,
Mar 21, 2011, 8:50:16 PM3/21/11
to expre...@googlegroups.com
On 2011-03-21, at 8:03 PM, richardhenry wrote:
> If I create the route:
>
> app.get('/about', function(req, res) {
> res.send('hello');
> });
>
> Is it possible to have requests to '/about/' redirected to '/about' ?

app.get('/about/', function(req, res) { res.redirect('/about'); });

However, I'd suggest skipping the redirect and just doing this:

app.get('/about/?', function(req, res) { res.send('hello'); });

The '/?' makes the trailing slash optional and will serve both /about and /about/. Adding a redirect in there just increases traffic and server load while making your site or application feel less responsive as users sit waiting for that invisible extra HTTP round trip.

> Ideally in turn, if I created the route:
>
> app.get('/users/', function(req, res) {
> res.send('list of users');
> });
>
> Requests to '/users' would be redirected to '/users/'.

If you are going to do the redirect thing, pick one convention and stick with it :-) Why would you want some requests to require a trailing slash and others require it not to be there?

> Would this be feasible to do using middleware?

If you are sticking to a single convention the sure: create a middleware that calls res.redirect() if the trailing slash is missing (or present), next() otherwise. If you want to mix conventions you would need to figure out, for each request, which routes match it, which do (or don't) include a trailing slash, and what to do in the case where multiple routes match and they aren't consistent -- does the routes with trailing slash win, or the ones without?

Perhaps you could elaborate on your use-case and why you need to do this?
--
Laurie Harper
http://laurie.holoweb.net/

Johan Steenkamp

unread,
Mar 21, 2011, 9:11:15 PM3/21/11
to expre...@googlegroups.com
Since routes are processed as regex you could try something like: /about/?

However you are probably better off using the request params and then
handling the various paths in a switch/case block:

app.get('/:page?', function(req, res){
switch (req.params.page){
case 'about':
res.send('about');
break;

case 'stuff':
res.send('stuff');
break;

default:
res.send('default')
}
});

> --
> You received this message because you are subscribed to the Google Groups "Express" group.
> To post to this group, send email to expre...@googlegroups.com.
> To unsubscribe from this group, send email to express-js+...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/express-js?hl=en.
>
>

vision media [ Tj Holowaychuk ]

unread,
Mar 22, 2011, 11:22:14 AM3/22/11
to expre...@googlegroups.com
all the regexps generated have a trailing \/?
--
Tj Holowaychuk
Vision Media
President & Creative Lead

Laurie Harper

unread,
Mar 22, 2011, 12:27:53 PM3/22/11
to expre...@googlegroups.com
Oops, I *always* forget that :-] So in fact the original requirements can't be met through routes, and must be done in middleware if you really want the behaviour (which, as mentioned before, I personally wouldn't :-).
-- 
Laurie Harper



richardhenry

unread,
Apr 5, 2011, 8:34:03 PM4/5/11
to Express
A URL ending in a slash is a directory, and a URL without a slash is a
resource. So /users/ would be a list of users, and /users/bob would be
a single user.

It's nice to fully follow the RESTful specification, particularly when
building a HTTP API.

Richard

On Mar 22, 12:27 pm, Laurie Harper <lau...@holoweb.net> wrote:
> Oops, I *always* forget that :-] So in fact the original requirements can't be met through routes, and must be done in middleware if you really want the behaviour (which, as mentioned before, I personally wouldn't :-).
>
> On 2011-03-22, at 11:22 AM, vision media [ Tj Holowaychuk ] wrote:
>
>
>
>
>
> > all the regexps generated have a trailing \/?
>
> > On Mon, Mar 21, 2011 at 6:11 PM, Johan Steenkamp <jo...@orbital.co.nz> wrote:
> > Since routes are processed as regex you could try something like: /about/?
>
> > However you are probably better off using the request params and then
> > handling the various paths in a switch/case block:
>
> > app.get('/:page?', function(req, res){
> >  switch (req.params.page){
> >    case 'about':
> >      res.send('about');
> >    break;
>
> >    case 'stuff':
> >      res.send('stuff');
> >    break;
>
> >    default:
> >      res.send('default')
> >  }
> > });
>
> > On Tue, Mar 22, 2011 at 1:03 PM, richardhenry <richardhe...@me.com> wrote:
> > > Hey there,
>
> > > If I create the route:
>
> > >    app.get('/about', function(req, res) {
> > >      res.send('hello');
> > >    });
>
> > > Is it possible to have requests to '/about/' redirected to '/about' ?
>
> > > Ideally in turn, if I created the route:
>
> > >    app.get('/users/', function(req, res) {
> > >      res.send('list of users');
> > >    });
>
> > > Requests to '/users' would be redirected to '/users/'.
>
> > > Would this be feasible to do using middleware?
>
> > > Thanks!
>
> > > Richard
>
> > > --
> > > You received this message because you are subscribed to the Google Groups "Express" group.
> > > To post to this group, send email to expre...@googlegroups.com.
> > > To unsubscribe from this group, send email to express-js+...@googlegroups.com.
> > > For more options, visit this group athttp://groups.google.com/group/express-js?hl=en.
>
> > --
> > You received this message because you are subscribed to the Google Groups "Express" group.
> > To post to this group, send email to expre...@googlegroups.com.
> > To unsubscribe from this group, send email to express-js+...@googlegroups.com.
> > For more options, visit this group athttp://groups.google.com/group/express-js?hl=en.

TJ Holowaychuk

unread,
Apr 5, 2011, 8:35:59 PM4/5/11
to expre...@googlegroups.com
Yeah, but you can still obviously GET /users and GET /users/bob, only difference is that express (currently) does not consider GET /users and GET /users/ different, nor in most cases would you really want to

-- 
TJ Holowaychuk

Aseem Kishore

unread,
Apr 5, 2011, 8:46:29 PM4/5/11
to expre...@googlegroups.com, TJ Holowaychuk
I agree you want the server to handle both by default, but I'll toss in a +1 that it's more polished when you can 301 redirect one to the other, for clean and canonical URLs, and I agree with Richard that different situations call for the slash vs. not.

==> In an ideal world with Richard's example:

/users -> 301 redirect to /users/
/users/ -> 200
/users/bob -> 200
/users/bob/ -> 301 redirect to /users/bob

This is not a huge deal, and I appreciate that Express handles both cases by default so you don't have to think about it, but I too would love the ability to optionally specify whether the slash "should" be there or not.

Cheers,
Aseem

Laurie Harper

unread,
Apr 5, 2011, 11:45:08 PM4/5/11
to expre...@googlegroups.com
I've never seen that stated as a part of any 'RESTful specification', do you have a reference?

As far as I know, REST is just a set of architectural patterns, not a specification, and is not specifically tied to the web, or even HTTP for that matter, even if it's almost always mentioned in that context.

L.

Laurie Harper

unread,
Apr 5, 2011, 11:52:44 PM4/5/11
to expre...@googlegroups.com
There's a general distinction between 'canonical URI' for a resource, vs. the (set of) URIs through which that resource can be referenced. For example, if host foo.com has IP 10.8.7.6, these are different URIs, but clearly they reference the same resource:

http://10.8.7.6/users/

All are equally valid for accessing that resource. Only one should be considered canonical. And who gets to pick which one is canonical?... you do! :-) 

Redirecting from .../resource to .../resource/ just adds an HTTP round trip. Like I said at the start of the thread, there's rarely a good reason to incur the cost. If you really want to (or have a use case that requires it) you always have that option.

L.

-- 
Laurie Harper



Paul Vencill

unread,
Aug 23, 2012, 8:06:10 AM8/23/12
to expre...@googlegroups.com

I feel like this is already well handled by your web server (mod_rewrite and similar), so why burden the app logic with it at all?

On Aug 22, 2012 3:46 PM, "John Van Horn" <jmva...@gmail.com> wrote:
Richard, did you ever find a solution for this? I'm a bit surprised that this functionality isn't included (in middleware or otherwise). This is basic canonicalization.

To respond with 200 (and same content) to both /users and /users/, is to duplicate content... bad for seo. You need to pick one way as the canoncial representation, and 301 redirect the other. Generally, I would be much more worried about seo than any impact on performance this redirect would have.
To view this discussion on the web visit https://groups.google.com/d/msg/express-js/-/m3LX6ynZ-lIJ.
Reply all
Reply to author
Forward
0 new messages