[Catalyst] stripping path parts and then redispatch?

Larry Leszczynski larryl at emailplus.org
Tue Feb 24 01:44:31 GMT 2009


Just wanted to pass along some solutions...

To recap briefly:

URLs are prefixed with the page language, e.g "/en/foo/bar".  The
language needs to be stripped off and stashed, and the remainder of the
request processed as if the language part had not been there, e.g.
"/foo/bar".

I was trying to use $c->go("/foo/bar"), which works if there is a
Foo::bar() action, but which breaks if the action is supposed to be
Foo::default() with the argument "bar" (or Foo::Bar::default() with no
arguments).


1) Bill Moseley suggested a different approach which is seeming to work
pretty well so far (thanks Bill), it involves subclassing
MyApp->prepare_path() to tweak the path at beginning of processing,
something like this:

  sub prepare_path
  {
      my $c = shift;

      $c->SUPER::prepare_path(@_);

      my @path_chunks = split m[/], $c->request->path, -1;

      return unless (   @path_chunks
                     && $valid_languages{$path_chunks[0]});

      # Pull off first path chunk:
      my $language = shift @path_chunks;
      $c->stash->{language} = $language;

      # Create a request path from the remaining chunks:
      my $path = join('/', @path_chunks) || '/';

      # Stuff modified request path back into request:
      $c->request->path($path);

      # Update request base to include whatever
      # was stripped from the request path:
      my $base = $c->request->base;
      $base->path($base->path . $language . '/');
  }

A nice side effect is that tweaking $c->request->base to include the
language means the language is automatically included when you call
$c->uri_for().


2) In the process of trying to get $c->go() to work for an arbitrary
path, I found a way that seems to make it work consistently even if the
path is supposed to hit a default action:

    # Create your request path to wherever:
    my $path = "/foo/bar/baz";

    # Stuff modified request path back into request:
    $c->request->path($path);

    # Create a new $c->action using $c->request->path.
    # Updates $c->action and $c->request->args.
    $c->dispatcher->prepare_action($c);

    $c->go($c->action, $c->request->args);

This should work for any of $c->forward(), $c->detach(), $c->visit(),
$c->go().


Thanks for all the suggestions,
Larry



More information about the Catalyst mailing list