Cách gửi lỗi 500 Lỗi Máy chủ Nội bộ từ tập lệnh PHP


80

Tôi cần gửi "Lỗi máy chủ nội bộ 500" từ tập lệnh PHP trong các điều kiện nhất định. Tập lệnh được cho là do ứng dụng của bên thứ ba gọi. Tập lệnh chứa một vài die("this happend")câu lệnh mà tôi cần gửi 500 Internal Server Errormã phản hồi thay vì thông thường 200 OK. Tập lệnh của bên thứ ba sẽ gửi lại yêu cầu trong một số điều kiện nhất định, bao gồm cả việc không nhận được 200 OKmã phản hồi.

Phần thứ hai của câu hỏi: Tôi cần thiết lập tập lệnh của mình như sau:

<?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" );
?>

Tôi chỉ cần gửi 200tiêu đề sau khi dòng cuối cùng đã được thực thi.

Biên tập

Một câu hỏi phụ: tôi có thể gửi 500 tiêu đề lạ như sau:

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

Các lỗi như vậy có được ghi lại bởi máy chủ web không?


không phải là doable khi u gửi header và loại bỏ tiêu đề sau
ajreal

1
Câu hỏi phụ: Điều đó hoàn toàn hợp pháp. Các Cụm từ Lý do không dùng để tiêu thụ máy móc và chúng có thể là bất cứ thứ gì. Chỉ có Mã trạng thái gồm ba chữ số mới quan trọng. (RFC2616 6.1.1: "Các cụm từ lý do được liệt kê ở đây chỉ là khuyến nghị - chúng CÓ THỂ được thay thế bằng các cụm từ tương đương cục bộ mà không ảnh hưởng đến giao thức.")
Piskvor rời khỏi tòa nhà vào

Câu trả lời:


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

FYI, giải pháp này gửi tiêu đề X-Pad: tránh lỗi trình duyệt trong một số phiên bản của Apache. stackoverflow.com/questions/8711584/… . http_response_code()bỏ qua tiêu đề này.
Anthony Rutledge

3
Điều đó thậm chí hoạt động nếu tiêu đề không ở đầu, (chẳng hạn như bằng chứng làm việc), công việc tốt.
tôi là tôi

Tuyệt, nếu bạn muốn xuất ra một json thay vì lỗi 500 Internal server?
tblancog

44

PHP 5.4 có một chức năng được gọi là http_response_code , vì vậy nếu bạn đang sử dụng PHP 5.4, bạn chỉ cần thực hiện:

http_response_code(500);

Tôi đã viết một polyfill cho hàm này (Gist) nếu bạn đang chạy phiên bản PHP dưới 5.4.


Để trả lời câu hỏi tiếp theo của bạn, HTTP 1.1 RFC cho biết:

Các cụm từ lý do được liệt kê ở đây chỉ là các khuyến nghị - chúng CÓ THỂ được thay thế bằng các cụm từ tương đương cục bộ mà không ảnh hưởng đến giao thức.

Điều đó có nghĩa là bạn có thể sử dụng bất kỳ văn bản nào bạn muốn (không bao gồm ký tự xuống dòng hoặc nguồn cấp dữ liệu dòng) sau chính mã và nó sẽ hoạt động. Tuy nhiên, nói chung, thường có một mã phản hồi tốt hơn để sử dụng. Ví dụ: thay vì sử dụng 500 mà không tìm thấy bản ghi, bạn có thể gửi 404 (không tìm thấy) và đối với một cái gì đó như "điều kiện không thành công" (tôi đoán là lỗi xác thực), bạn có thể gửi một cái gì đó như 422 (không thể xử lý thực thể).


Điều quan trọng cần ghi nhớ là chức năng này cũng không hoạt động nữa khi đầu ra đã bắt đầu!
rob74

@ rob74 True - khi PHP bắt đầu gửi đầu ra, tất cả các hàm liên quan đến tiêu đề sẽ không còn hoạt động. Nếu bạn không chắc mình có phải thay đổi mã phản hồi trước khi bắt đầu gửi đầu ra hay không, thì bộ đệm đầu ra là một giải pháp tốt.
inxilpro

33

Bạn có thể sử dụng chức năng sau để gửi thay đổi trạng thái:

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);
    }
}

Bạn có thể sử dụng nó như sau:

<?php
header_status(500);

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

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

update_database();

header_status(200);

21
Tiết kiệm một vài byte bộ nhớ hiếm khi là lý do chính đáng để viết mã ứng dụng web theo cách này hay cách khác.
Dan Grossman

1
bạn không thiếu một ;sau die()?
henrywright

2
Danh sách của bạn là mất tích 418 => "Tôi là một ấm trà" nhìn thấy: en.wikipedia.org/wiki/Hyper_Text_Coffee_Pot_Control_Protocol
Louis Loudog Trottier

16

Bạn chỉ có thể đặt:

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

bên trong các điều kiện của bạn như:

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

Đối với truy vấn cơ sở dữ liệu, bạn có thể thực hiện như sau:

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

Bạn nên nhớ rằng bạn phải đặt mã này trước bất kỳ thẻ html nào (hoặc đầu ra).


11
Đảm bảo rằng bạn thoát / die / return / something sau khi gọi header (). PHP sẽ tiếp tục thực thi mã - điều này có lẽ không mong muốn.
David Goodwin

8

Bạn có thể đơn giản hóa nó như thế này:

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

Nó sẽ trả về tiêu đề sau:

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

Đã thêm: Nếu bạn cần biết chính xác điều gì đã xảy ra, hãy làm như sau:

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');
}

5
Bây giờ những gì được 'x'cho là?
Core Xii

1
+1 Lưu ý rằng tham số đầu tiên trong headerphải là một chuỗi không trống. Điều đó 'x'không thực sự quan trọng.
theazureshadow

1
@Core Xii, tham số đầu tiên không được rỗng như @theazureshadow đã chỉ ra. Nói tóm lại, bằng cách gọi tiêu đề ('something', true, 500), tiêu đề đúng "HTTP / 1.0 500 Internal Server Error" sẽ được trả về. Bạn có thể gọi tôi là lười biếng, nhưng việc vượt qua mã lỗi sẽ dễ dàng hơn là xử lý chuỗi tiêu đề thực tế :) Hãy xem php.net/manual/en/ Chức năng.header.php để biết thêm chi tiết.
David Kuridža

Sách hướng dẫn không rõ ràng lắm về điều này. Vì vậy, bạn đang nói rằng nếu bạn buộc mã trạng thái, PHP sẽ tự động ghi đè đối số chuỗi thành giá trị chính xác của nó? Vậy tại sao hướng dẫn sử dụng lại nói rằng nó chỉ có hiệu lực nếu chuỗi không trống?
Core Xii

1
Lưu ý rằng trong một số cấu hình PHP (cấu hình mà nhà cung cấp dịch vụ lưu trữ của tôi sử dụng cho exapmle, nhưng không phải thiết lập cục bộ của tôi) thủ thuật này sẽ không hoạt động! Apache không nhận ra "x" là một chuỗi tiêu đề chính xác và sẽ không thành công với lỗi "Tiêu đề không đúng định dạng".
mjsarfatti

2

Mã của bạn sẽ giống như sau:

<?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');
?>

Tôi giả sử bạn ngừng thực hiện nếu có điều gì đó không ổn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.