Welcome Guest, Not a member yet? Register   Sign In
redirect() not affected by $this->output->set_header()
#1

[eluser]aaronadams[/eluser]
If I set a header with $this->output->set_header(), and then I do an HTTP redirect with the redirect() helper, my header doesn't make it into the redirect.

Scenario:

Facebook iframe apps require a P3P header in order for Internet Explorer to allow cookies to be set by the iframed page.

Facebook will send user data to the iframe via POST; best practice is to process the POST data, create a session, and 302 redirect to a GET request of the same resource.

If I set the P3P header with $this->output->set_header(), start a session, and then redirect(), Internet Explorer ignores the session data, breaking the app.

I'm now forced to set my header with PHP's builtin header() as opposed to using CI's Output class. In conjunction with gzip, setting a header this way, without the assistance of the Output class, makes me extremely nervous.

It seems to be that the solution would be to re-implement redirect() as a method of the Output class, with the helper calling the method. This way, the class could output its headers before setting the Location header and exiting.
#2

[eluser]skunkbad[/eluser]
Why not just use redirect() from the URL helper? Also, make sure not to try to access helper functions using $this->, because they are not class methods.
#3

[eluser]aaronadams[/eluser]
I'm guessing you misread. I am using redirect() from the URL helper. The issue is that it doesn't respect headers set via $this->output->set_header().
#4

[eluser]skunkbad[/eluser]
Maybe you should set the second param of set_header to TRUE? There's nothing special going on here. The URL helper and the Output class both just wrap PHP's header() function. Unless you are trying to modify the content-length header, there's no difference between using output->set_header() and PHP's header();
#5

[eluser]aaronadams[/eluser]
The second parameter of CI_Output:Confusedet_header() maps to the second parameter of PHP header(), which already defaults to true.

That has nothing to do with this issue, though.

The issue boils down to this: if I set headers via CodeIgniter's Output class, and then redirect via CodeIgniter's URL helper, the headers I asked CodeIgniter to send aren't sent.

This is incredibly confusing. I can't think of any reason somebody would want to redirect and have their headers ignored.

Suggesting that I should use PHP header() instead of going through the Output class is like suggesting that I should just echo to the browser instead of going through the Output class. It completely defeats the purpose of using a framework. If I set headers via CodeIgniter's Output class, I expect them to be present in my output; that seems reasonable!
#6

[eluser]aaronadams[/eluser]
A code sample might help:

Code:
// Send P3P header to enable third-party cookies in Internet Explorer
$this->output->set_header('P3P: CP="This Facebook app does not have a P3P policy."');

// If there's a signed request from Facebook...
if ( $this->input->post('signed_request') )
{
// Make sure the Facebook SDK fully processes the user immediately
$this->facebook->getAccessToken();
$this->facebook->getUser();

// Redirect to self
log_message('debug', 'Controller: Redirecting to ' . current_url());
redirect(current_url());
}

The header isn't output when redirect() is called, which means the cookie doesn't make it through the redirect, which means the application fails.
#7

[eluser]skunkbad[/eluser]
[quote author="aaronadams" date="1334882025"]
Suggesting that I should use PHP header() instead of going through the Output class is like suggesting that I should just echo to the browser instead of going through the Output class.[/quote]

I know. I should have never recommended using real PHP. That could have totally self destructed your application. Maybe could have crashed Apache or fried your server. Try this:

Code:
$this->output->set_header('P3P: CP="This Facebook app does not have a P3P policy."');
$this->output->set_header('Location: ' . current_url());

It worked for me, meaning I saw the headers in Firebug. I don't know why using redirect() doesn't work, but it didn't work for me either. It should be noted that using PHP's header function worked just the same, but I know it may be risky.
#8

[eluser]aaronadams[/eluser]
[quote author="skunkbad" date="1334891961"]I know. I should have never recommended using real PHP. That could have totally self destructed your application. Maybe could have crashed Apache or fried your server.[/quote]

No need for snark, we're just a couple of developers solving a problem here.

There are plenty of reasons a direct call to header() is a bad idea; for instance, header() takes effect immediately, therefore it would affect error output, which is probably undesirable. And since header() is immediate while Output:Confusedet_header() is deferred, calls to the latter will always supercede calls to the former, regardless of the order in which they're called.

[quote author="skunkbad" date="1334891961"]Try this:

Code:
$this->output->set_header('P3P: CP="This Facebook app does not have a P3P policy."');
$this->output->set_header('Location: ' . current_url());

It worked for me, meaning I saw the headers in Firebug.[/quote]

Indeed, that's another way to deal with it – of course you'd also then need to output the headers and exit. I'm not sure if the Output class has a public methods to output the headers; I'd have to take a look.

[quote author="skunkbad" date="1334891961"]I don't know why using redirect() doesn't work, but it didn't work for me either. It should be noted that using PHP's header function worked just the same, but I know it may be risky.[/quote]

redirect() doesn't work because it's a standalone helper, unrelated to the Output class; and only the Output class is able to output its own headers (not technically true, granted, but directly accessing the $headers property of the Output class from the redirect() helper would be poor practice, and would be prone to break in the future).

The remedy would be for CI to add a redirect() method to the Output class, with the helper remaining a shortcut version; the method would work identically, plus it would output any already-set headers.

To maintain backwards compatibility, Output::redirect() could accept an additional $include_headers parameter, defaulting to TRUE; and the redirect() helper could add the parameter as well, defaulting to FALSE instead. This way we don't break existing apps which rely on this quirk.

Thanks for confirming for me. Much appreciated. Always good to know I'm not going crazy.
#9

[eluser]CroNiX[/eluser]
redirect() executes immediately, so it will never have a chance to parse any additional headers set by CI::output();
#10

[eluser]glassyflower[/eluser]
[quote author="aaronadams" date="1334956411"][quote author="skunkbad" date="1334891961"]I know. I should have never recommended using real PHP. That could have totally self destructed your application. Maybe could have crashed Apache or fried your server.[/quote]

No need for snark, we're just a couple of developers solving a problem here.

There are plenty of reasons a direct call to header() is a bad idea; for instance, header() takes effect immediately, therefore it would affect error output, which is probably undesirable. And since header() is immediate while Output:Confusedet_header() is deferred, calls to the latter will always supercede calls to the former, regardless of the order in which they're called.

[quote author="skunkbad" date="1334891961"]Try this:

Code:
$this->output->set_header('P3P: CP="This Facebook app does not have a P3P policy."');
$this->output->set_header('Location: ' . current_url());

It worked for me, meaning I saw the headers in Firebug.[/quote]

Indeed, that's another way to deal with it – of course you'd also then need to output the headers and exit. I'm not sure if the Output class has a public methods to output the headers; I'd have to take a look.

[quote author="skunkbad" date="1334891961"]I don't know why using redirect() doesn't work, but it didn't work for me either. It should be noted that using PHP's header function worked just the same, but I know it may be risky.[/quote]

redirect() doesn't work because it's a standalone helper, unrelated to the Output class; and only the Output class is able to output its own headers (not technically true, granted, but directly accessing the $headers property of the Output class from the redirect() helper would be poor practice, and would be prone to break in the future).

The remedy would be for CI to add a redirect() method to the Output class, with the helper remaining a shortcut version; the method would work identically, plus it would output any already-set headers.

To maintain backwards compatibility, Output::redirect() could accept an additional $include_headers parameter, defaulting to TRUE; and the redirect() helper could add the parameter as well, defaulting to FALSE instead. This way we don't break existing apps which rely on this quirk.

Thanks for confirming for me. Much appreciated. Always good to know I'm not going crazy.[/quote]
i think so.thank for share




Theme © iAndrew 2016 - Forum software by © MyBB