Skip to main content

This site requires you to update your browser. Your browsing experience maybe affected by not having the most up to date version.

We've moved the forum!

Please use forum.silverstripe.org for any new questions (announcement).
The forum archive will stick around, but will be read only.

You can also use our Slack channel or StackOverflow to ask for help.
Check out our community overview for more options to contribute.

General Questions /

General questions about getting started with SilverStripe that don't fit in any of the categories above.

Moderators: martimiz, Sean, Ed, biapar, Willr, Ingo, swaiba

Could someone tell me what the purpose of the first few lines of Controller::redirect method are?


Go to End


6 Posts   3293 Views

Avatar
ImacSS

Community Member, 35 Posts

4 September 2009 at 8:31am

Edited: 04/09/2009 9:24am

Running into a problem where I am encountering the error message produced from the first few lines of the Controller::redirect() method - and wondering if someone could explain the rationale behind this logic?

if($this->response->getHeader('Location')) {
user_error("Already directed to " . $this->response->getHeader('Location') . "; now trying to direct to $url", E_USER_WARNING);
return;
}

Just curious, as I'm finding it difficult to come up with a work around given these lines.

Thanks

UPDATE: Never mnd - this doesn't effect live deployment as it's only a warning, so commenting it from my local development machine...

Avatar
Willr

Forum Moderator, 5523 Posts

5 September 2009 at 7:02pm

Edited: 05/09/2009 7:03pm

FYI Its to prevent having Director::redirect() commands redirecting the user multiple times.

Avatar
anselmdk

Community Member, 18 Posts

7 September 2009 at 2:39am

So how would you approach only redirecting the user to the first appearing Director::redirect?

I'm getting the 'Already redirected' warning, and have no clue of how to get around it (I'm building a 'maintenance offline' settings script):

$bolMaintenanceRedirect = true;
if (Member::currentUser()) {
if(Member::currentUser()->isAdmin()) {
$bolMaintenanceRedirect = false;
}
}
if ($bolMaintenanceRedirect){
if (Director::urlParam("Controller") != 'Security') {
if (Director::urlParam("Action") != 'login') {
Director::redirect('downformaintenance.html');
}
}
}

Avatar
Willr

Forum Moderator, 5523 Posts

7 September 2009 at 9:47am

Is it calling that function twice? If you put a Debug::message("test"); inside that last if does it show twice?. You could be redirecting as well as SilverStripe doing something with the security redirect

Avatar
anselmdk

Community Member, 18 Posts

8 September 2009 at 9:49pm

I was looking for a way to overrule any other redirects that would have been set before. I thought maybe there would be a method for that?
I ended up by fixing this by setting some preferences, and a couple of if statements.

Thanks for the fast reply!

Avatar
adrian

Community Member, 5 Posts

13 July 2012 at 2:15pm

I know this is a very old thread, but judging by the number of views it's still a question that comes up from time to time, so I thought I'd share a method I used to resolve this.

First note that Director::redirect() simply calls the redirect() function of the current controller, which will usually result in a call to the implementation of the function down in the base ContentController class and it is in that implementation that the double redirect warning is generated. I note that some people propose commenting out the offending lines of code, but for the record you can simply override that function in your Page class, and exclude the 3 lines of code. So in your Page_Controller class just have this function:

function redirect($url, $code=302) {
    // Attach site-root to relative links, if they have a slash in them
    if($url == "" || $url[0] == '?' || (substr($url,0,4) != "http" && $url[0] != "/" && strpos($url,'/') !== false)){
        $url = Director::baseURL() . $url;
    }

    $this->response->redirect($url, $code);
}

which is simply the default base implementation sans the few lines of code that generate the warning. No need to touch the core code (as if that's ever the correct answer)

As a side discussion:

I'm not satisfied that there's any need for that warning in the first place. For example, in some sites I have a function that is called from within Page_Controller Init() which checks to see if the current page should be in SSL and redirects the user into the https:// version of the URL if they aren't (it also transitions them out of SSL when I want them out as well). So that results in the first instance of the HTTP header "location" being set... BUT my understanding is that the PHP side of things hasn't finished executing yet, and the user's browser hasn't yet been sent the HTTP headers. Correct? So then later on in my code let's say I have a function that determines the user is trying to access a secure page and I want to redirect them to a login screen (or it could be Silverstripe's own redirector page type, or even Silverstripe's own "canView()" security check etc...), this will result in the second attempt to set the HTTP header "location" to some value, and if things are allowed to continue without the warning then that should be the one and only 302 that ends up getting sent to the user's browser isn't it?

Now I could put all sorts of code in there to have my SSL check and my secure access check act in unison with all other pieces of custom code that might want to do a redirect for some reason, and if they all are aware of the status of each other's redirection desires then I could probably orchestrate a situation where Director::redirect() only gets called once, but if my underlying assumption is correct that the headers only end up getting sent to the browser once anyway, why not just allow multiple calls to the redirect function without a warning?

Finally, as noted in some other threads on this subject, warnings are suppressed in "test" and "live" mode anyway, but it does bug me that my warning log file on disk can tend to fill up with these messages.