2

So I know the general rule of thumb is after doing a header redirect in PHP, you should call exit() to avoid having extra code running, but I want to know if you put code after the redirect header, if it will always run?

I was doing some research on various ways of tracking referrals in Google Analytics and came across this post: Google Analytics Tips & Tricks – Tracking 301 Redirects in Google Analytics

It recommends doing something like this:

<?
Header( “HTTP/1.1 301 Moved Permanently” );
Header( “Location: http://www.new-url.com” );
?>

<script type=”text/javascript”>
var gaJsHost = ((“https:” == document.location.protocol) ? “https://ssl.” : “http://www.”);
document.write(unescape(“%3Cscript src=’” + gaJsHost + “google-analytics.com/ga.js’ type=’text/javascript’%3E%3C/script%3E”));
</script>
<script type=”text/javascript”>
try {
var pageTracker = _gat._getTracker(“UA-YOURPROFILE-ID”);
pageTracker._trackPageview();
} catch(err) {}</script>

From the way I've always understood the header() function, it's up to the browser and it can run the redirect whenever it wants to. So there's no guarantee the JavaScript would actually begin or finish executing prior to the redirect occurring.

PHP's documentation for the header() function indicates the reason for exiting after a redirect is to "make sure that code below does not get executed when we redirect." That doesn't sound like they guarantee all following code will run, just that it could happen.

Regardless, I found a different way to actually manage the tracking, but I wanted to see if I could find out how exactly header() worked in this situation..

Thanks for your help.

David Stinemetze
  • 8,830
  • 3
  • 21
  • 34
  • I'm researching on the same problem of tracking a redirect page; Can you share your 'other way' of doing it? Thanks. – L__ Jun 26 '13 at 12:55
  • It's been a couple years since I set this up and really can't remember what I did, or what project this was even for. That said, I'd image the solution involved event tracking. https://developers.google.com/analytics/devguides/collection/gajs/eventTrackerGuide If you redirect to http://www.new-url.com/?from301 Then you can trigger the appropriate event when you see the appropriate URL parameter. Like I said, I don't have the specific details, but I imagine that was the way I went with it. – David Stinemetze Jul 08 '13 at 21:02

5 Answers5

3

It's a race condition. Once the redirect header is sent to the browser, the browser will close the current connection and open a new one for the redirect URL. Until that original connection is closed and Apache shuts down the script, your code will continue to execute as before.

In theory, if there was a sufficiently fast connection between the client/server, and there was no buffering anywhere in the pipeline, issuing the header would cause the script to be terminated immediately. In reality, it can be anywhere between "now" and "never" for the shutdown to be initiated.

Marc B
  • 356,200
  • 43
  • 426
  • 500
  • That is incorrect. Sending a header does NOT close the connection. Infact sending a response body with the redirect is the *norm* rather than the exception. – Anupam Jain Aug 30 '11 at 16:50
  • I didn't say it does. I said the browser will close the connection upon receipt of the header - it's supposed to go over ---> there, so there's no point in loading more of the document which is just going to get thrown away. – Marc B Aug 30 '11 at 16:51
  • That too is incorrect. The browser will not close the connection without downloading the full response body as well. – Anupam Jain Aug 30 '11 at 16:53
  • 1
    The question isn't about downloading the response. it's about executing it. Again that'd be a race condition - the browser is going to be opening the new location, which COULD happen before it ever gets around to loading/executing any JS in the response body. – Marc B Aug 30 '11 at 16:57
  • I was just using the JavaScript example above because it was what prompted me to think about it. What if it's using PHP code instead? – David Stinemetze Aug 30 '11 at 17:00
  • 2
    We could argue about it all day which doesn't sound fun. So to make it as clear as possible - The question asks if the PHP code is always executed even after the header("Location..."). The answer is **YES**. Any other answer is wrong. – Anupam Jain Aug 30 '11 at 17:01
  • Please see http://stackoverflow.com/questions/14847010/will-php-script-be-executed-after-header-redirect for other opinions – user1032531 Feb 13 '13 at 06:01
  • +1 - I had a bug in a project I'd been working on where on the development server, code after the header('Location') call was being executed, whereas on my trunk it wasn't. This explains that behaviour – billyonecan Jul 04 '13 at 15:24
  • @AnupamJain the answer is not always yes. – billyonecan Jul 04 '13 at 15:25
3

Using the header function in PHP only adds to the headers of the response returned by the server. It does not immediately send any data and does not immediately terminate the connection. Any code after the header call will be executed.

In particular, it's a good idea to add a response body even after doing a 301 redirect so that clients that do not support the redirect also get some descriptive response. Infact according to the HTTP 1.1 specification Section 10.3.2 -

Unless the request method was HEAD, the entity of the response SHOULD contain a short hypertext note with a hyperlink to the new URI(s). If the 301 status code is received in response to a request other than GET or HEAD, the user agent MUST NOT automatically redirect the request unless it can be confirmed by the user, since this might change the conditions under which the request was issued.

Anupam Jain
  • 7,851
  • 2
  • 39
  • 74
  • Do you have any documentation to support this? – David Stinemetze Aug 30 '11 at 17:28
  • 1
    Sure, Look at the [HTTP 1.1 spec Section 10.3.2](http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html) - "Unless the request method was HEAD, the entity of the response SHOULD contain a short hypertext note with a hyperlink to the new URI(s). If the 301 status code is received in response to a request other than GET or HEAD, the user agent MUST NOT automatically redirect the request unless it can be confirmed by the user, since this might change the conditions under which the request was issued." – Anupam Jain Aug 30 '11 at 17:41
0

I have noticed that the code does still execute and multiple headers based on if statements can cause a "redirect loop error". i made it a habit to now add in die("Redirecting..."); after every header redirect and have not see the problem persist.

0

The HTML after your Location line doesn't run inside PHP; it would run in the browser. It's up to the browser whether or not to execute the Javascript that you've included on that page; PHP has nothing to do with it.

To me, the PHP docs imply that any PHP below the header() when you send a redirect will continue to run. But it 'runs' in the PHP interpreter, dumping JS to the browser. There's no relation between what it says in the PHP docs and whether or not the JS gets run by the browser.

Jonathan
  • 7,536
  • 4
  • 30
  • 44
0

EDIT:

Well, as Anupam Jain pointed out, looks like that browsers do not terminate connection without getting the response body and it sounds sensible. So i rethinked my answer

That doesn't sound like they guarantee all following code will run

Exactly More likely it's a warning in case there is some sensible code that shouldn't be executed. A private page contents for example. So, beside sending header you have to also make sure that no sensitive content were sent and exit looks like quite robust solution. So, I'd phrase it as "make sure that sensible code below does not get executed when we redirect."

So there's no guarantee the JavaScript would actually begin or finish executing prior to the redirect occurring.

Exactly It seems it has nothing to do with script execution but rather with browser's will to execute anything after getting 3xx response. I think I'm gonna test it, but you can test it as well too.

Your Common Sense
  • 156,878
  • 40
  • 214
  • 345
  • Your assumptions are incorrect. Browsers do not terminate connection without getting the response body. And browsers have legitimate reasons to not redirect automatically. Look at this [Firefox addon](https://addons.mozilla.org/en-US/firefox/addon/noredirect/) for an example. – Anupam Jain Aug 30 '11 at 17:09