PHP: Bagaimana cara mengirim kode respons HTTP?

254

Saya memiliki skrip PHP yang perlu membuat respons dengan kode respons HTTP (kode status), seperti HTTP 200 OK, atau kode 4XX atau 5XX.

Bagaimana saya bisa melakukan ini di PHP?

Paulo Coghi - Pasang kembali Monica
sumber

Jawaban:

461

Saya baru saja menemukan pertanyaan ini dan merasa perlu jawaban yang lebih komprehensif:

Pada PHP 5.4 ada tiga metode untuk mencapai ini:

Merakit kode respons sendiri-sendiri (PHP> = 4.0)

The header()fungsi memiliki penggunaan-kasus khusus yang mendeteksi garis respon HTTP dan memungkinkan Anda mengganti dengan satu kustom

header("HTTP/1.1 200 OK");

Namun, ini memerlukan perlakuan khusus untuk (Cepat) CGI PHP:

$sapi_type = php_sapi_name();
if (substr($sapi_type, 0, 3) == 'cgi')
    header("Status: 404 Not Found");
else
    header("HTTP/1.1 404 Not Found");

Catatan: Menurut HTTP RFC , frasa alasannya bisa berupa string khusus apa pun (yang sesuai dengan standar), tetapi demi kompatibilitas klien saya tidak merekomendasikan menempatkan string acak di sana.

Catatan: php_sapi_name() membutuhkan PHP 4.0.1

Argumen ke-3 untuk fungsi header (PHP> = 4.3)

Jelas ada beberapa masalah saat menggunakan varian pertama itu. Yang terbesar menurut saya adalah sebagian diuraikan oleh PHP atau server web dan kurang didokumentasikan.

Sejak 4.3, headerfungsi memiliki argumen ke-3 yang memungkinkan Anda mengatur kode respons dengan nyaman, tetapi menggunakannya membutuhkan argumen pertama menjadi string yang tidak kosong. Berikut ini dua opsi:

header(':', true, 404);
header('X-PHP-Response-Code: 404', true, 404);

Saya merekomendasikan yang kedua . Yang pertama tidak bekerja pada semua browser saya telah diuji, tetapi beberapa browser kecil atau web crawler mungkin memiliki masalah dengan garis header yang hanya berisi tanda titik dua. Nama bidang header di ke-2. Varian ini tentu saja tidak standar dengan cara apa pun dan dapat dimodifikasi, saya hanya memilih nama yang mudah-mudahan deskriptif.

Fungsi http_response_code (PHP> = 5.4)

The http_response_code()Fungsi diperkenalkan di PHP 5.4, dan itu membuat hal-hal yang jauh lebih mudah.

http_response_code(404);

Itu saja.

Kesesuaian

Berikut adalah fungsi yang saya buat ketika saya membutuhkan kompatibilitas di bawah 5.4 tetapi menginginkan fungsi dari fungsi "baru" http_response_code. Saya percaya PHP 4.3 lebih dari cukup kompatibilitas ke belakang, tetapi Anda tidak pernah tahu ...

// For 4.3.0 <= PHP <= 5.4.0
if (!function_exists('http_response_code'))
{
    function http_response_code($newcode = NULL)
    {
        static $code = 200;
        if($newcode !== NULL)
        {
            header('X-PHP-Response-Code: '.$newcode, true, $newcode);
            if(!headers_sent())
                $code = $newcode;
        }       
        return $code;
    }
}
ganda
sumber
10
Saya dapat mengkonfirmasi bahwa header('X-PHP-Response-Code: 404', true, 404);itu berfungsi dengan baik di bawah PHP-FPM (FastCGI)
Josh
@dualed (1) tidak akan headers_sent()selalu benar setelah menelepon header()? (2) pernah menemukan sesuatu seperti http_response_text () di dunia 5.4? Setidaknya tajuk lama () dapat memengaruhi teks setelah kode status.
Bob Stein
@ BobStein-VisiBone (1) headers_sent() benar jika Anda tidak dapat menambahkan header lagi karena konten sudah dikirim, bukan jika Anda telah menambahkan header. (2) Maaf, tidak. Bahasa lain memiliki dukungan yang lebih baik
digandakan
1
@ Jerry alasan mengapa saya tidak menyarankan melakukan ini adalah sama mengapa saya tidak menyarankan hanya usus besar. PHP dapat menangani hal ini secara berbeda di seluruh versi, karena tidak ditentukan apa yang terjadi dengan "tajuk" seperti itu, mungkin gagal sepenuhnya - tidak mengatur tajuk atau status, atau mungkin menambahkan tajuk yang tidak valid (standar protokol http 1.1 memerlukan titik dua )
digandakan
8
Saya menghabiskan berjam-jam menyadari bahwa http_response_code(dan mungkin lebih umum memodifikasi header) tidak berfungsi lagi setelah Anda echosesuatu. Semoga ini bisa membantu.
Neptilo
40

Sayangnya saya menemukan solusi yang disajikan oleh @dualed memiliki berbagai kekurangan.

  1. Menggunakan substr($sapi_type, 0, 3) == 'cgi'bukan enogh untuk mendeteksi CGI cepat. Saat menggunakan PHP-FPM FastCGI Process Manager, php_sapi_name()mengembalikan fpm bukan cgi

  2. Fasctcgi dan php-fpm mengekspos bug lain yang disebutkan oleh @Josh - menggunakan header('X-PHP-Response-Code: 404', true, 404);tidak berfungsi dengan baik di bawah PHP-FPM (FastCGI)

  3. header("HTTP/1.1 404 Not Found");mungkin gagal ketika protokol bukan HTTP / 1.1 (yaitu 'HTTP / 1.0'). Protokol saat ini harus dideteksi menggunakan $_SERVER['SERVER_PROTOCOL'](tersedia sejak PHP 4.1.0

  4. Setidaknya ada 2 kasus saat panggilan http_response_code()menghasilkan perilaku yang tidak terduga:

    • Ketika PHP menemukan kode respons HTTP yang tidak dimengerti, PHP akan mengganti kode dengan kode yang diketahui dari grup yang sama. Misalnya "Server Web 521 sedang down" diganti dengan "500 Server Internal Kesalahan". Banyak kode respons tidak umum lainnya dari grup lain 2xx, 3xx, 4xx ditangani dengan cara ini.
    • Di server dengan fungsi php-fpm dan nginx http_response_code () DAPAT mengubah kode seperti yang diharapkan tetapi tidak pesan. Sebagai contoh, ini dapat menghasilkan tajuk "404 OK" yang aneh. Masalah ini juga disebutkan di situs web PHP oleh komentar pengguna http://www.php.net/manual/en/function.http-response-code.php#112423

Untuk referensi Anda di sini ada daftar lengkap kode status respons HTTP (daftar ini mencakup kode dari standar internet IETF serta RET IETF lainnya. Banyak di antaranya TIDAK saat ini didukung oleh fungsi PHP http_response_code): http: //en.wikipedia .org / wiki / List_of_HTTP_status_codes

Anda dapat dengan mudah menguji bug ini dengan menelepon:

http_response_code(521);

Server akan mengirim "500 Internal Server Error" kode respons HTTP yang menghasilkan kesalahan tak terduga jika misalnya Anda memiliki aplikasi klien kustom yang memanggil server Anda dan mengharapkan beberapa kode HTTP tambahan.


Solusi saya (untuk semua versi PHP sejak 4.1.0):

$httpStatusCode = 521;
$httpStatusMsg  = 'Web server is down';
$phpSapiName    = substr(php_sapi_name(), 0, 3);
if ($phpSapiName == 'cgi' || $phpSapiName == 'fpm') {
    header('Status: '.$httpStatusCode.' '.$httpStatusMsg);
} else {
    $protocol = isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0';
    header($protocol.' '.$httpStatusCode.' '.$httpStatusMsg);
}

Kesimpulan

Implementasi http_response_code () tidak mendukung semua kode respons HTTP dan dapat menimpa kode respons HTTP yang ditentukan dengan kode lain dari grup yang sama.

Fungsi http_response_code () baru tidak menyelesaikan semua masalah yang ada tetapi membuat hal-hal terburuk memperkenalkan bug baru.

Solusi "kompatibilitas" yang ditawarkan oleh @dualed tidak berfungsi seperti yang diharapkan, setidaknya di bawah PHP-FPM.

Solusi lain yang ditawarkan oleh @dualed juga memiliki berbagai bug. Deteksi CGI cepat tidak menangani PHP-FPM. Protokol saat ini harus dideteksi.

Setiap tes dan komentar sangat dihargai.

Grigore Madalin
sumber
21

karena PHP 5.4 dapat Anda gunakan http_response_code()untuk mendapatkan dan mengatur kode status tajuk.

berikut sebuah contoh:

<?php

// Get the current response code and set a new one
var_dump(http_response_code(404));

// Get the new response code
var_dump(http_response_code());
?>

di sini adalah dokumen dari fungsi ini di php.net:

http_response_code

Sayyed Ali Roshan
sumber
Dalam pengalaman saya, ini adalah jawaban terbaik.
berantakan
Mengapa menggunakan var_dump ()?
Tomas Gonzalez
Tapi mengapa var_dump () bukannya gema? Bisakah hasilnya tidak cocok untuk gema sederhana? Atau bahkan print_r (). var_dump () tampaknya tidak cukup untuk kode produksi ...
Tomas Gonzalez
@TomasGonzalez itu bukan masalah besar, saya hanya ingin menunjukkan kepada Anda apa yang ada di dalamnya dengan mencetak semuanya dengan var_dump () dan Anda benar mereka tidak penting
Seyed Ali Roshan
Ok aku paham. Yang menarik perhatian saya adalah bahwa dalam dokumen resmi, contohnya menggunakan var_dump () juga. Jadi saya ingin tahu tentang alasan melakukannya. Mungkin ada sesuatu yang saya lewatkan. php.net/manual/en/function.http-response-code.php
Tomas Gonzalez
10

Tambahkan baris ini sebelum output tubuh apa pun, jika Anda tidak menggunakan buffering output.

header("HTTP/1.1 200 OK");

Ganti bagian pesan ('OK') dengan pesan yang sesuai, dan kode status dengan kode Anda yang sesuai (404, 501, dll)

sparkey0
sumber
2
Apakah pesan yang kita masukkan (untuk remplace OK) bisa berupa apa saja?
FMaz008
Ini berhasil untuk saya. Saya sedang mengerjakan formulir kontak di situs web dengan PHP 5.3. Dan solusi ini berhasil untuk saya. Ini akan memberikan teks respons dan kode HTTP ini untuk permintaan AJAX yang dilakukan fungsi gagal. Itu yang saya inginkan.
Surjith SM
7

Jika Anda di sini karena Wordpress memberikan 404 saat memuat lingkungan, ini akan memperbaiki masalah:

define('WP_USE_THEMES', false);
require('../wp-blog-header.php');
status_header( 200 );
//$wp_query->is_404=false; // if necessary

Masalahnya adalah karena ia mengirim Status: 404 Tidak Ditemukan header. Anda harus menimpanya. Ini juga akan berfungsi:

define('WP_USE_THEMES', false);
require('../wp-blog-header.php');
header("HTTP/1.1 200 OK");
header("Status: 200 All rosy");
jaggedsoft
sumber
header ("HTTP / 1.1 200 OK"); http_response_code (201); header ("Status: 200 All rosy"); // kerja
alpc
6

Dengan fungsi header . Ada contoh di bagian parameter pertama yang diperlukan.

Quentin
sumber
2

Jika versi PHP Anda tidak termasuk fungsi ini:

<?php

function http_response_code($code = NULL) {
        if ($code !== NULL) {
            switch ($code) {
                case 100: $text = 'Continue';
                    break;
                case 101: $text = 'Switching Protocols';
                    break;
                case 200: $text = 'OK';
                    break;
                case 201: $text = 'Created';
                    break;
                case 202: $text = 'Accepted';
                    break;
                case 203: $text = 'Non-Authoritative Information';
                    break;
                case 204: $text = 'No Content';
                    break;
                case 205: $text = 'Reset Content';
                    break;
                case 206: $text = 'Partial Content';
                    break;
                case 300: $text = 'Multiple Choices';
                    break;
                case 301: $text = 'Moved Permanently';
                    break;
                case 302: $text = 'Moved Temporarily';
                    break;
                case 303: $text = 'See Other';
                    break;
                case 304: $text = 'Not Modified';
                    break;
                case 305: $text = 'Use Proxy';
                    break;
                case 400: $text = 'Bad Request';
                    break;
                case 401: $text = 'Unauthorized';
                    break;
                case 402: $text = 'Payment Required';
                    break;
                case 403: $text = 'Forbidden';
                    break;
                case 404: $text = 'Not Found';
                    break;
                case 405: $text = 'Method Not Allowed';
                    break;
                case 406: $text = 'Not Acceptable';
                    break;
                case 407: $text = 'Proxy Authentication Required';
                    break;
                case 408: $text = 'Request Time-out';
                    break;
                case 409: $text = 'Conflict';
                    break;
                case 410: $text = 'Gone';
                    break;
                case 411: $text = 'Length Required';
                    break;
                case 412: $text = 'Precondition Failed';
                    break;
                case 413: $text = 'Request Entity Too Large';
                    break;
                case 414: $text = 'Request-URI Too Large';
                    break;
                case 415: $text = 'Unsupported Media Type';
                    break;
                case 500: $text = 'Internal Server Error';
                    break;
                case 501: $text = 'Not Implemented';
                    break;
                case 502: $text = 'Bad Gateway';
                    break;
                case 503: $text = 'Service Unavailable';
                    break;
                case 504: $text = 'Gateway Time-out';
                    break;
                case 505: $text = 'HTTP Version not supported';
                    break;
                default:
                    exit('Unknown http status code "' . htmlentities($code) . '"');
                    break;
            }
            $protocol = (isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0');
            header($protocol . ' ' . $code . ' ' . $text);
            $GLOBALS['http_response_code'] = $code;
        } else {
            $code = (isset($GLOBALS['http_response_code']) ? $GLOBALS['http_response_code'] : 200);
        }
        return $code;
    }
Tuan Rumah
sumber
1

Kita bisa mendapatkan nilai balik yang berbeda dari http_response_code melalui dua lingkungan yang berbeda:

  1. Lingkungan Server Web
  2. Lingkungan CLI

Di lingkungan server web, kembalikan kode respons sebelumnya jika Anda memberikan kode respons atau ketika Anda tidak memberikan kode respons apa pun maka itu akan mencetak nilai saat ini. Nilai standarnya adalah 200 (OK).

Di CLI Environment, true akan kembali jika Anda memberikan kode respons dan false jika Anda tidak memberikan response_code.

Contoh Lingkungan Web Server dari nilai pengembalian Response_code:

var_dump(http_respone_code(500)); // int(200)
var_dump(http_response_code()); // int(500)

Contoh nilai pengembalian Lingkungan CLI dari Response_code:

var_dump(http_response_code()); // bool(false)
var_dump(http_response_code(501)); // bool(true)
var_dump(http_response_code()); // int(501)
GaziAnis
sumber