Bug #948
closedPHP header('Status: 404') doesn't work outside a server.error-handler-404
Description
It's impossible to return a 404 status code from php scripts executed in normal mode (not server.error-handler-404). Other status code works, for example:
<?php header('Status: 301'); print_r($_SERVER); ?>
this page does return the right '''HTTP/1.1 301 Moved Permanently''' header, but
<?php header('Status: 404'); print_r($_SERVER); ?>
does return the '''HTTP/1.1 200 OK''' header.[BR]
Someone argued that I don't need to have PHP scripts return 404 status codes, but this is incorrect. If I remove one record from my database and a search engine spider tries to access the now outdated url pointing to that record, I need to be able to show a 404 error so it won't index that page, and eventually remove it from its index.
-- bobo
Updated by darix almost 18 years ago
$ cat test.php ; curl -v http://localhost/~darix/test.php <?php header("Status: 404"); header("Content-Type: text/plain" ); print("not found\n"); ?> * About to connect() to localhost port 80 * Trying 127.0.0.1... connected * Connected to localhost (127.0.0.1) port 80 > GET /~darix/test.php HTTP/1.1 > User-Agent: curl/7.15.5 (x86_64-unknown-linux) libcurl/7.15.5 OpenSSL/0.9.8a zlib/1.2.3 libidn/0.6.0 > Host: localhost > Accept: */* > < HTTP/1.1 404 Not Found < Transfer-Encoding: chunked < X-Powered-By: PHP/5.2.0 < Content-Type: text/plain < Date: Fri, 29 Dec 2006 07:01:58 GMT < Server: lighttpd (1.4.x.svn.r1387/SuSE) not found * Connection #0 to host localhost left intact * Closing connection #0 $ lighttpd -v lighttpd-1.4.13 (ssl) - a light and fast webserver Build-Date: Dec 2 2006 21:52:11
Updated by Anonymous almost 18 years ago
On PHP 5.2.0 all ok
< HTTP/1.1 404 Not Found
< Transfer-Encoding: chunked
< X-Powered-By: PHP/5.2.0
< Set-Cookie: PHPSESSID=10499b9e4e84616a12406f67e6ca5eaa; path=/
< Expires: Thu, 19 Nov 1981 08:52:00 GMT
< Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
< Pragma: no-cache
< Content-type: text/html; charset=utf-8
< Date: Fri, 29 Dec 2006 09:02:36 GMT
< Server: lighttpd/1.5.0
Please write your version of PHP.
-- boom
Updated by Anonymous almost 18 years ago
Replying to boom@bamex.ru:
Please write your version of PHP.
I'm using PHP 5.2.0 on Mac OS X for my development
PHP 5.2.0 (cgi-fcgi) (built: Dec 16 2006 19:07:00) Copyright (c) 1997-2006 The PHP Group Zend Engine v2.2.0, Copyright (c) 1998-2006 Zend Technologies
and PHP 5.2.0 with Zend Optimizer on Linux for deployment on the server
PHP 5.2.0 (cgi-fcgi) (built: Dec 17 2006 16:01:19) Copyright (c) 1997-2006 The PHP Group Zend Engine v2.2.0, Copyright (c) 1998-2006 Zend Technologies with Zend Extension Manager v1.0.11, Copyright (c) 2003-2006, by Zend Technologies with Zend Optimizer v3.2.0, Copyright (c) 1998-2006, by Zend Technologies
with the code of the report I always get (on server and locally):
bobohome:~ bobo$ curl --head "http://www.pensieriparole.it/prova.php" HTTP/1.1 200 OK X-Powered-By: PHP/5.2.0 Content-type: text/html Date: Fri, 29 Dec 2006 10:17:29 GMT Server: lighttpd/1.4.13
Updated by Anonymous almost 18 years ago
Sorry, the preceding reply was mine.
-- bobo
Updated by Anonymous over 17 years ago
Any news on this report? Will it be fixed? When?
In the meantime I'm using 410 instead of 404, this mitigates the problem since it is correctly returned as the http status code, but the user doesn't see anything, it always returns an empty page. So:
404 => page ok, status wrong
410 => page empty, status ok
I now have php 5.2.1 but the problem persists.
You can try it on your own requesting http://www.pensieriparole.it/prova.php for 404 and http://www.pensieriparole.it/prova410.php for 410.
Please answer, thanks
-- bobo
Updated by darix over 17 years ago
try:
header('Status: 404 Not found')
are you sure this is an lighttpd problem and not a general problem of php?
Updated by Anonymous over 17 years ago
I tried and the response is the same.
It's definitely a lighttpd problem, because my website was running on Apache before lighttpd, and there it was working as I wanted: status 404 returned and special error page.
Thanks
-- bobo
Updated by darix over 17 years ago
$ cat test.php <?php header('Status: 404 Not Found'); header('Content-Type: text/plain'); print("not found here\n"); ?> $ curl -kv https://localhost/test.php > GET /test.php HTTP/1.1 > User-Agent: curl/7.15.5 (x86_64-unknown-linux) libcurl/7.15.5 OpenSSL/0.9.8a zlib/1.2.3 libidn/0.6.0 > Host: localhost > Accept: */* > < HTTP/1.1 404 Not Found < Transfer-Encoding: chunked < X-Powered-By: PHP/5.2.1 < Content-Type: text/plain < Date: Sun, 04 Mar 2007 19:14:10 GMT < Server: lighttpd (1.4.x.svn.r1524/SuSE) not found here
i would say ... works for me ... or do you expect to see the 404 page from lighttpd?
Updated by Anonymous over 17 years ago
I tried your code but I'm out of luck...
No I don't want the 404 page from lighttpd, I expect the correct status code and my personal error page (in the website, here's only a test code).
$ cat prova.php <?php header('Status: 404 Not Found'); header('Content-Type: text/plain'); print("not found here\n"); ?> $ curl -kv http://www.pensieriparole.it/prova.php * About to connect() to www.pensieriparole.it port 80 * Trying 212.35.215.120... connected * Connected to www.pensieriparole.it (212.35.215.120) port 80 > GET /prova.php HTTP/1.1 > User-Agent: curl/7.15.5 (i686-pc-linux-gnu) libcurl/7.15.5 OpenSSL/0.9.8d zlib/1.2.3 libidn/0.6.5 > Host: www.pensieriparole.it > Accept: */* > < HTTP/1.1 200 OK < Transfer-Encoding: chunked < X-Powered-By: PHP/5.2.1 < Content-Type: text/plain < Date: Sun, 04 Mar 2007 19:27:28 GMT < Server: lighttpd/1.4.13 not found here * Connection #0 to host www.pensieriparole.it left intact * Closing connection #0
-- bobo
Updated by Anonymous over 17 years ago
I talked to darix in the irc channel and through some tests found out this: the issue arises only if you use the
server.error-handler-404 = "/error.php"
code in the configuration, which of course I use... I correctly handled the error.php page returning the 404 Not found status header (in fact if choosing a non existent real file the page correctly shows and the status code is 404).
The bug is still there with lighttpd 1.4.15.
Thanks again
-- bobo
Updated by darix over 17 years ago
the longer version:
index.php returns 404. lighty sends it to the 404 handler. and the 404 handler returns 404 again. than lighty converts it into a 200.
Updated by darix over 17 years ago
1427 } else if (con->in_error_handler) { 1428 /* error-handler is a 404 */ 1429 1430 con->http_status = con->error_handler_saved_status; 1431 } 1432 } else if (con->in_error_handler) { 1433 /* error-handler is back and has generated content */ 1434 /* if Status: was set, take it otherwise use 200 */ 1435 }
as we see. the 2nd elseif doesnt restore the old code.
can you try:
Index: connections.c =================================================================== --- connections.c (revision 1820) +++ connections.c (working copy) @@ -1432,6 +1432,7 @@ } else if (con->in_error_handler) { /* error-handler is back and has generated content */ /* if Status: was set, take it otherwise use 200 */ + con->http_status = con->error_handler_saved_status; } if (con->http_status == 0) con->http_status = 200;
Updated by Anonymous over 17 years ago
YES it works! Thank you!
I already patched the lighttpd on my production server, if I ever see something strange happen because of this I will notify to you.
Hope to see the patch applied in the next release of lighttpd.
-- bobo
Updated by darix over 17 years ago
- Status changed from New to Fixed
- Resolution set to fixed
fixed in all active branches.
Updated by glen over 17 years ago
- Status changed from Fixed to Need Feedback
- Resolution deleted (
fixed)
i believe this change broke possibility to return other than 404 status code from {{{server.error-handler-404}}server.error-handler-404
}
at least in 1.4.13 it worked, and NEWS says:
1.3.16 - 2005-07-31 * error-handler-404 defaults to Status: 200 and static files work now
lighttpd conf:
server.error-handler-404 = "/404.php"
404.php:
<? Header('Status: 200'); ?> it's mee
# curl -kv lighttpd/no_such_file * About to connect() to lighttpd port 80 (#0) * Trying 192.168.2.27... connected * Connected to lighttpd (192.168.2.27) port 80 (#0) > GET /no_such_file HTTP/1.1 > User-Agent: curl/7.16.1 (x86_64-pld-linux-gnu) libcurl/7.16.1 OpenSSL/0.9.7l zlib/1.2.3 libidn/0.6.10 libssh2/0.11 > Host: lighttpd > Accept: */* > < HTTP/1.1 404 Not Found < Transfer-Encoding: chunked < Content-type: text/html < Date: Wed, 18 Jul 2007 01:43:24 GMT < Server: lighttpd it's mee * Connection #0 to host lighttpd left intact * Closing connection #0
# curl -kv lighttpd/404.php * About to connect() to lighttpd port 80 (#0) * Trying 192.168.2.27... connected * Connected to lighttpd (192.168.2.27) port 80 (#0) > GET /404.php HTTP/1.1 > User-Agent: curl/7.16.1 (x86_64-pld-linux-gnu) libcurl/7.16.1 OpenSSL/0.9.7l zlib/1.2.3 libidn/0.6.10 libssh2/0.11 > Host: lighttpd > Accept: */* > < HTTP/1.1 200 OK < Transfer-Encoding: chunked < Content-type: text/html < Date: Wed, 18 Jul 2007 01:43:46 GMT < Server: lighttpd it's mee * Connection #0 to host lighttpd left intact * Closing connection #0
Updated by darix over 17 years ago
first of all you quoted 1.3.16 changelog. intended?
furthermore... are you sure you 404 handler got called at all?
Updated by glen over 17 years ago
yes, i quoted NEWS file where at 1.3.16 it noted that it's expected to return 200 code. so it must be a bug :)
and yes it got called. check the responses i pasted in previous note (http://lighttpd/no_such_file is inexistent file)
Updated by darix over 17 years ago
hmm ... indeed that broke the old behavior.
can you send me your error.php again please?
Updated by darix over 17 years ago
can you please test svn r1904 of the 1.4.x branch?
I checked in a fix that now passes the 404-handler testsuite and fixes both #1270 and #948 .
See this link how to get the svn branch.
Updated by glen over 17 years ago
- Status changed from Need Feedback to Fixed
- Resolution set to fixed
seems ok now (i can use 200 status code in 404 handler)
# wget -O /dev/null -S --cache=off http://lighttpd/no_such_file 2>&1|grep HTTP/ HTTP/1.0 200 OK # wget -O /dev/null -S --cache=off http://lighttpd/404.php 2>&1|grep HTTP/ HTTP/1.0 200 OK # cat /www/htdocs/localhost/404.php <? Header('Status: 200'); ?> it's mee
Also available in: Atom