35

Yes, this question has been asked before, however, the answers have been inconsistent. Take Why I have to call 'exit' after redirection through header('Location..') in PHP? for instance. Every answer (including the accepted answer) states yes, except the last answer which received zero votes which says "maybe". I am starting to think the correct answer is "maybe". To make it a simple "yes" or "no" question, will doThis() be executed given the following script? Thanks

header('Location: http://somewhereElse.com');
//die();
sleep(1000);
doThis();

EDIT Thanks, all. With my PHP/Linux/Apache configuration, the second syslog() executes, so the answer is "yes, all script down stream of the header will be executed." I will assume (and hope I am correct) it is the same with all PHP/Linux/Apache configurations!

<?php
  header('Location: http://google.com');
  syslog(LOG_INFO,'first');  
  sleep(5);
  syslog(LOG_INFO,'Second');  
?>
Community
  • 1
  • 1
user1032531
  • 24,767
  • 68
  • 217
  • 387
  • 3
    Have you tried it? The sleep time in your example will exceed the `max_execution_time`. Otherwise, yes. – mario Feb 13 '13 at 05:33
  • 1
    Yes, though you don't need the `sleep()` call. `header()` does not halt execution, only sets response headers – Phil Feb 13 '13 at 05:34
  • No, haven't tried it. Shame on me! Reading the last post on my original referenced SO thread as well as responses to http://stackoverflow.com/questions/7246649/will-all-code-after-redirect-header-in-php-always-get-executed, it appears that Apache will close the connection, and the PHP script will cease to execute. – user1032531 Feb 13 '13 at 05:37
  • 1
    yes yes yes, header is like any other part of the php script, it will be sent after the script execution completed, however, the trick is: if we want to redirect to new URL: then why continue executing scripts after header("location: url"); ?> –  Feb 13 '13 at 05:43
  • My test results were added to my original post under the EDIT section. – user1032531 Feb 13 '13 at 05:57

10 Answers10

32

Yes, the script continues to process after the call to header('Location: http://google.com') if you don't explicitly terminate it! I just tried this locally. I added test.php to a site in apache with these contents:

<?php

header('Location: http://google.com');
error_log("WE MADE IT HERE SOMEHOW");

?>

And checked my /var/log/apache2/error_log for this entry:

[Tue Feb 12 23:39:23 2013] [error] [client 127.0.0.1] WE MADE IT HERE SOMEHOW

Possibly surprising, but yes, it continues to execute if you don't halt execution.

Cody A. Ray
  • 5,869
  • 1
  • 37
  • 31
  • 1
    I feel lame for not testing! Great for you Cody! Go Scientific Method! I will also test and post my findings. – user1032531 Feb 13 '13 at 05:42
  • Thanks Cody. I tested and agree with your results. Reason I asked before testing is that I wasn't sure if it was configuration determinate. I will in the future assume that it will always be executed regardless of OS or web server. – user1032531 Feb 13 '13 at 05:57
  • `header('Location: http://google.com');` redirects **after** `error_log("WE MADE IT HERE SOMEHOW");` has been executed so this cannot be the correct answer. You have to add `fastcgi_finish_request();` after the header function. – Viktor Joras Aug 05 '19 at 11:18
  • @ViktorJoras This answers the question, which asked whether the script continues executing. When (and whether) the client honors the Location header and redirect is irrelevant. All the server does when you `fastcgi_finish_request()` is to flush buffered output (including headers) to the client and close the connection. The script continues to execute. See for example: https://stackoverflow.com/a/4236290/337735 – Cody A. Ray Aug 10 '19 at 02:23
13

People seem to get this really confused, and as to why the script is executed. When you send the redirect header the browser immediately redirects the user to the new page but your server will continue to process the code even though there is no one to receive it at the end, this doesn't mean the script is terminated. Unless you configure Apache to stop the script when it realizes there is no one on the other end.

When a PHP script is running normally the NORMAL state, is active. If the remote client disconnects the ABORTED state flag is turned on. A remote client disconnect is usually caused by the user hitting his STOP button.

You can decide whether or not you want a client disconnect to cause your script to be aborted. Sometimes it is handy to always have your scripts run to completion even if there is no remote browser receiving the output. The default behaviour is however for your script to be aborted when the remote client disconnects. This behavior can be set via the ignore_user_abort php.ini directive as well as through the corresponding php_value ignore_user_abort Apache httpd.conf directive or with the ignore_user_abort() function.

The correct way of redirecting a user without further actions is:

header("Location: blah.php");
exit();
Neo
  • 11,078
  • 2
  • 68
  • 79
  • Why exit and not die? – NaughtySquid Jan 24 '21 at 13:02
  • @NaughtySquid `exit` and `die` are literally just different names for the same function (or "language construct", since it's not really a function). Which you use is entirely a matter of taste. – IMSoP Jul 14 '22 at 11:10
5

Let me explain more. let's have an example using session.

$_SESSION["username"] = 'some username';
header("Location: another-file.php");
$_SESSION["username"] = 'replace username';

Result of $_SESSION["username"] will be replace username

You can output a lot more headers than just Location headers with header, most of which you don't want to stop your code execution. If you want to stop code execution, you need to call exit explicitly.

The header command doesn't interrupt the flow of your code. Even if that is encountered, your page is still downloaded by the browser, even if it isn't show. Consider 404 pages, which (despite being errors) are still processed by the browser (though they are rendered while redirects are not).

Dipesh Parmar
  • 27,090
  • 8
  • 61
  • 90
3

Running the code:

//http://www.php.net/manual/en/function.header.php
header('Location: http://google.com');
flush();
sleep(3);

$a=fopen('test.txt', 'w');
fwrite($a,headers_sent());
fclose($a);

The server paused and wrote the file before the client redirected me. This is because, even after flush()ing the buffer, the the redirect is not processed until the script ceases execution (ie, the script terminated). The file test.txt had '1' in every case, meaning that the headers were sent, just not processed by the browser until the connection was terminated.

  • in every case, meaning on a win32 development machine, linux development machine, and a linux production environment.
Jon
  • 4,746
  • 2
  • 24
  • 37
2

This first example shows that some code is executed after the header location redirect, but that not all code is necessarily executed. Once the browser starts responding to the redirect header, it'll terminate the connection on the current page, which will causes PHP to terminate executing its code. This shows how NOT to do things.

session_start();
$_SESSION["some_value"] = 'original value';
header("Location: /index.php/test2");

$start_time = microtime(true);

for($i = 0; $i <= 100000; $i ++)
{
    password_hash($i);  // slow it down
    $_SESSION["some_value"] = $i;   
    $_SESSION['time'] = microtime(true) - $start_time;
}

$_SESSION['some_value'] = 'finished!';

// Result:
// some_value = 174

In this example I added ignore_user_abort() to show how to execute all the code:

ignore_user_abort(TRUE);
session_start();
$_SESSION["some_value"] = 'original value';
header("Location: /index.php/test2");

$start_time = microtime(true);

for($i = 0; $i <= 100000; $i ++)
{
    password_hash($i);  // slow it down
    $_SESSION["some_value"] = $i;   
    $_SESSION['time'] = microtime(true) - $start_time;
}

$_SESSION['some_value'] = 'finished!';

// Result:
// some_value = finished!

And this is how you would typically execute a redirect, by killing the script immediately after the redirect:

session_start();
$_SESSION["some_value"] = 'original value';
header("Location: /index.php/test2");
die();

$start_time = microtime(true);

for($i = 0; $i <= 100000; $i ++)
{
    password_hash($i);  // slow it down
    $_SESSION["some_value"] = $i;   
    $_SESSION['time'] = microtime(true) - $start_time;
}

$_SESSION['some_value'] = 'finished!';

// Result:
// some_value = original value

In short, either use die(), exit(), or ignore_user_abort(TRUE);

2

The script will still run after the redirection is done. Although it may be useful sometimes, people who use header function have to be aware, that it can be dangerous. Look at this piece of very unsafe code:

<?php
if($_GET['some_secret'] != '123') {
    setcookie("status", "not logged in");
    header("Location: /");
}
setcookie("status", "logged in");

echo("Some secret info!")
?>

No matter what some_secret you enter, you will always have a cookie with value logged in. The only difference here is that the user will be redirected if wrong parameter value is given.

Solution: Use die() or exit() method to end the script immediately after redirection

This small correction will make our script working as we wanted to.

<?php
if($_GET['some_secret'] != '123') {
    setcookie("status", "not logged in");
    header("Location: /");
    die();
}
setcookie("status", "logged in");

echo("Some secret info!")
?>

(I won't show another simple solution with else statement, as this is not really the way it should be done.)


You may think, that a user at least won't see the secret information you print on the screen. WRONG! Browser just makes a redirection, but it's up to us if we follow it.

In this example, I used a vulnerable code without die:

$ telnet 192.168.1.39 80
Trying 192.168.1.39...
Connected to 192.168.1.39.
Escape character is '^]'.
GET /test.php?some_secret=wrong
Some secret info!
Connection closed by foreign host.

As you can see, secret information leaked.

So, be aware, that header can be very unsafe!
...and remember to normally not store such data like passwords in plaintext or information like logged in in cookies

linoskoczek
  • 135
  • 5
1

Yes, it will be executed for short amount of time.

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.

Read more

Community
  • 1
  • 1
Techie
  • 44,706
  • 42
  • 157
  • 243
  • So, the answer is no, given the 1000 second (or whatever) delay? – user1032531 Feb 13 '13 at 05:43
  • it depends on your internet connection. – Techie Feb 13 '13 at 05:44
  • I think it depends on the client as well. Say, for example, some client requests the page and does not respect the header. – AKS Feb 13 '13 at 05:44
  • This answer is nothing for me, because it haven't any reference for support, PHP documentation not mentioned any thing like this! –  Feb 13 '13 at 05:46
  • 2
    Just because the client closes the connection, doesn't mean the server stops processing your script. There is no magical time limit after which processing halts – Phil Feb 13 '13 at 05:46
  • My testing given the my configuration agrees that the server doesn't stop. +1 for Phil – user1032531 Feb 13 '13 at 05:54
0

yes yes yes, header is like any other part of the php script, it will be sent after the script execution completed, however, the trick is: if we want to redirect to new URL: then why continue executing scripts after header("location: url"); ?>

<?php
header('Location: test.php');
header('Location: test.php');
header('Location: test.php');
header('Location: test.php');
header('Location: test.php');
header('Location: test.php');
header('Location: test.php');

$var = 'google.com';
header("Location: http://$var");

?> 
0
header("Location: http://example.com/newURL.php");
die;

Yes the script continues after the header redirect, so make sure to call die; or exit; any time you you redirect to stop execution. Don't need to put the script to sleep :).

How to make a redirect in PHP?

Community
  • 1
  • 1
Andrew
  • 18,680
  • 13
  • 103
  • 118
-1

USECASE SCENARIO: Redirect users to captive portal then start a countdown timer to write them off the block list after x minutes.

Dudus
  • 25
  • 8