Question

I'm developing a Catalyst application and having trouble with the way Catalyst interprets urls.

Let's say that in our Catalyst application we have a controller Account. If this is the case, Catalyst will interpret

http://mydomain.com/account and http://mydomain.com/account/

as the same url for the index action.

However, for SEO and linking purposes (and just to be consistent overall) I would like to force Catalyst to only recognize one format and stick to it.

I've found one module that seems to be built for this: Catalyst::Plugin::SanitizeUrl, it's documentation says you should just put

use Catalyst 'SanitizeUrl';

in myapp.pm and this will handle everything for you.

However, whenever I use it I just get this error:

Bad request

On every page load. Does anyone know of a simple way to have Catalyst only use one format?

Was it helpful?

Solution 3

I ended up combining what edem said with some stuff that I did and this is my end result:

sub begin :Private {
    my ($self, $c) = @_;

    #don't allow trailing slashes!
    my @path = split "/", $c->req->path, -1;
    if(@path and (pop @path eq '')) {
        my $p = join '/', @path;
        #set as moved permanently
        $c->res->redirect("/$p", 301);
        return;
    }
}

If there is a trailing slash at the end of the request, it will always redirect to the same url but without the slash.

OTHER TIPS

The simple way to force Catalyst use only one format without trailing slash is add this method to MyApp.pm:

sub begin :Private {
    my ($self, $c) = @_;
    my @path = split "/", $c->req->path, -1;
    $c->detach('default') if @path and (pop @path eq '');
}

It will redirect on 'default' method a.k.a Page 404 if uri ends with slash on any request.

I guess you can forward url to different action method depending on whether trailing / is present or not. So,

sub index :Path :Args(0) { 
    my ($self,$c) = @_;
    my $path = $c->request->path;
    my $matched = $path =~ s/(\/)$//;
    if ($matched) {
          $c->forward('withslash');
    }
    else {
          $c->forward('withoutslash');
    }
}

Again this is an untried solution, you might need to check it.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top