如何发送500内部服务器错误从一个 PHP 脚本

我需要发送“500内部服务器错误”从一个 PHP 脚本在某些条件下。该脚本应该由第三方应用程序调用。该脚本包含两个 die("this happend")语句,我需要为其发送 500 Internal Server Error响应代码,而不是通常的 200 OK。第三方脚本将在某些条件下重新发送请求,其中包括不接收 200 OK响应代码。

问题的第二部分: 我需要这样设置我的脚本:

<?php
custom_header( "500 Internal Server Error" );


if ( that_happened ) {
die( "that happened" )
}


if ( something_else_happened ) {
die( "something else happened" )
}


update_database( );


// the script can also fail on the above line
// e.g. a mysql error occurred


remove_header( "500" );
?>

我需要发送 200头只有在最后一行已经执行。

剪辑

附带一个问题: 我能发送500个这样奇怪的标题吗:

HTTP/1.1 500 No Record Found
HTTP/1.1 500 Script Generated Error (E_RECORD_NOT_FOUND)
HTTP/1.1 500 Conditions Failed on Line 23

这些错误会被网络服务器记录下来吗?

153271 次浏览

You can simplify it like this:

if ( that_happened || something_else_happened )
{
header('X-Error-Message: Incorrect username or password', true, 500);
die;
}

It will return following header:

HTTP/1.1 500 Internal Server Error
...
X-Error-Message: Incorrect username or password
...

Added: If you need to know exactly what went wrong, do something like this:

if ( that_happened )
{
header('X-Error-Message: Incorrect username', true, 500);
die('Incorrect username');
}


if ( something_else_happened )
{
header('X-Error-Message: Incorrect password', true, 500);
die('Incorrect password');
}

You may use the following function to send a status change:

function header_status($statusCode) {
static $status_codes = null;


if ($status_codes === null) {
$status_codes = array (
100 => 'Continue',
101 => 'Switching Protocols',
102 => 'Processing',
200 => 'OK',
201 => 'Created',
202 => 'Accepted',
203 => 'Non-Authoritative Information',
204 => 'No Content',
205 => 'Reset Content',
206 => 'Partial Content',
207 => 'Multi-Status',
300 => 'Multiple Choices',
301 => 'Moved Permanently',
302 => 'Found',
303 => 'See Other',
304 => 'Not Modified',
305 => 'Use Proxy',
307 => 'Temporary Redirect',
400 => 'Bad Request',
401 => 'Unauthorized',
402 => 'Payment Required',
403 => 'Forbidden',
404 => 'Not Found',
405 => 'Method Not Allowed',
406 => 'Not Acceptable',
407 => 'Proxy Authentication Required',
408 => 'Request Timeout',
409 => 'Conflict',
410 => 'Gone',
411 => 'Length Required',
412 => 'Precondition Failed',
413 => 'Request Entity Too Large',
414 => 'Request-URI Too Long',
415 => 'Unsupported Media Type',
416 => 'Requested Range Not Satisfiable',
417 => 'Expectation Failed',
422 => 'Unprocessable Entity',
423 => 'Locked',
424 => 'Failed Dependency',
426 => 'Upgrade Required',
500 => 'Internal Server Error',
501 => 'Not Implemented',
502 => 'Bad Gateway',
503 => 'Service Unavailable',
504 => 'Gateway Timeout',
505 => 'HTTP Version Not Supported',
506 => 'Variant Also Negotiates',
507 => 'Insufficient Storage',
509 => 'Bandwidth Limit Exceeded',
510 => 'Not Extended'
);
}


if ($status_codes[$statusCode] !== null) {
$status_string = $statusCode . ' ' . $status_codes[$statusCode];
header($_SERVER['SERVER_PROTOCOL'] . ' ' . $status_string, true, $statusCode);
}
}

You may use it as such:

<?php
header_status(500);


if (that_happened) {
die("that happened")
}


if (something_else_happened) {
die("something else happened")
}


update_database();


header_status(200);
header($_SERVER['SERVER_PROTOCOL'] . ' 500 Internal Server Error', true, 500);

Your code should look like:

<?php
if ( that_happened ) {
header("HTTP/1.0 500 Internal Server Error");
die();
}


if ( something_else_happened ) {
header("HTTP/1.0 500 Internal Server Error");
die();
}


// Your function should return FALSE if something goes wrong
if ( !update_database() ) {
header("HTTP/1.0 500 Internal Server Error");
die();
}


// the script can also fail on the above line
// e.g. a mysql error occurred




header('HTTP/1.1 200 OK');
?>

I assume you stop execution if something goes wrong.

You can just put:

header("HTTP/1.0 500 Internal Server Error");

inside your conditions like:

if (that happened) {
header("HTTP/1.0 500 Internal Server Error");
}

As for the database query, you can just do that like this:

$result = mysql_query("..query string..") or header("HTTP/1.0 500 Internal Server Error");

You should remember that you have to put this code before any html tag (or output).

PHP 5.4 has a function called http_response_code, so if you're using PHP 5.4 you can just do:

http_response_code(500);

I've written a polyfill for this function (Gist) if you're running a version of PHP under 5.4.


To answer your follow-up question, the HTTP 1.1 RFC says:

The reason phrases listed here are only recommendations -- they MAY be replaced by local equivalents without affecting the protocol.

That means you can use whatever text you want (excluding carriage returns or line feeds) after the code itself, and it'll work. Generally, though, there's usually a better response code to use. For example, instead of using a 500 for no record found, you could send a 404 (not found), and for something like "conditions failed" (I'm guessing a validation error), you could send something like a 422 (unprocessable entity).