4

I have a Catalyst application and would like to redirect based on a conditional statement. I am having trouble with this and I'm wondering if anyone might have insight into why this seemingly easy task is proving difficult.

In my Root.pm module I have a sub begin and can redirect to another website, e.g. www.perl.org, but I am unable to redirect to a page within my application. Any thoughts on how to do a conditional redirect?

sub begin : Private {
    my ( $self, $c ) = @_;
    $c->stash->{client_id} = somenumber; # I'm setting this manually for testing

    $c->res->redirect('http://www.perl.org/') unless $c->stash->{client_id};
    $c->res->redirect('http://www.mysite.com/success') if $c->stash->{client_id}; #does not
}
daxim
  • 39,270
  • 4
  • 65
  • 132
CodeWriter
  • 337
  • 2
  • 7
  • Are you aware of the difference between `if` and `unless`? Also, do you know when a value evaluates to true or false? – Htbaa Apr 04 '11 at 18:27
  • Yes, I know the difference between if and unless. In my example above I'm saying got to www.perl.org unless a number (false). Redirect into my website if a number (true). The $C-detach does not work for me either. I think it might have something to do with begin being called again and again and again. So I'm wondering how to get to another page within my site based on a conditional statement. – CodeWriter Apr 04 '11 at 18:34
  • First, what is the value of `somenumber`? – Htbaa Apr 04 '11 at 18:43
  • somenumber can be anything you want. 0 to go to www.perl.org and 1 to redirect into my website (which does not work as I mentioned.) Thanks for your help. – CodeWriter Apr 04 '11 at 18:45
  • 1
    I just tested it with value 1 and 0 and it behaves as expected. Also with your example. What version of Catalyst are you using? I tested with 5.80025. – Htbaa Apr 04 '11 at 18:53
  • I'm using the latest version of Catalyst. Are you redirecting to a page within an actual 'local' catalyst application? That is where my problem is. – CodeWriter Apr 04 '11 at 19:00
  • I used the **exact** same code as yours, in `Root.pm`. Do you even want to redirect to an external site? Or should these be internal redirections in your website? – Htbaa Apr 04 '11 at 19:05
  • I have no intention to redirect to an external site. The code above was to illustrate a point and to prove that it does indeed work in some cases. My goal is actually quite simple. Based on a simple db query, I will redirect (or $c->detach, whichever I can get to work) to one page or another. Essentially a login success/failure page, but I hesitate to bring that up because people will mention other plugins. In the simplest sense, once again... if a condition is True go to /true.html and if false go to /false.html I have yet to make this work, because I think Catalyst infinite loops. – CodeWriter Apr 04 '11 at 19:14
  • 1
    Well I think you need to ask yourself if you should do this in `auto`, especially since you don't want to redirect to some external site. This is because auto is run automatically for every action that's being executed. So you redirect in your `auto` sub, which makes the application perform a new request, which runs `auto` and so the loop continues. Also, I believe you need to always `$c->detach` after you redirect, otherwise it executes the rest of the subroutine. – Htbaa Apr 04 '11 at 19:33
  • Okay. Thank you for your help. I will continue to explore this. You have been very helpful. – CodeWriter Apr 04 '11 at 19:38
  • Also: Since this is a begin action, make sure it is actually called. Only those begin/end actions will be called that are closest to the controller of the action that was dispatched to. If you want to stack actions, the Chained dispatch type should be of help. – phaylon Apr 06 '11 at 15:37

1 Answers1

1

Maybe you're getting stuck in an infinite loop, in which your begin sub redirects the user to another page in your Catalyst application; once "the controller that will run has been identified, but before any URL-matching actions are called" (from the Catalyst::Manual::Intro man page), begin will be called again, causing another redirect and so on.

Try moving this code out of begin entirely; perhaps, as Htbaa suggested, auto might be what you're looking for. The standard $c->detach case (in controller controller) is:

sub check_login :Local {
  # do something
  $c->detach('controller/login_successful') if($success);
  # display error message
}

sub login_successful :Local {
  # do something with the logged in user.
}

In this case, doing a $c->res->redirect('http://example.com/login_successful') should work perfectly as well. Hope that helps!

Gaurav
  • 1,888
  • 1
  • 18
  • 23