การใช้ส่วนหัวใน PHP

คำถามง่ายๆ: หนึ่งในสองการเรียกส่วนหัว PHP (เวอร์ชัน 5+) นี้ใดที่ "ดีที่สุด"

header('Not Modified', true, 304);
header('HTTP/1.1 304 Not Modified');

ฉันค่อนข้างแน่ใจว่าอันแรกนั้นเป็นอันที่มีความหลากหลายมากที่สุด แต่แค่อยากรู้ว่า PHP จะ "แก้ไข" อันที่สองถ้าอยู่ภายใต้ HTTP 1.0...

ขอบคุณ!

แก้ไข: หนึ่งในส่วนหัวเหล่านี้ทำให้ PHP บนเว็บโฮสต์ของฉันขัดข้อง คำถามติดตามผลที่: PHP header() เรียกใช้สคริปต์ขัดข้องด้วย ข้อผิดพลาด HTTP 500


person AlexV    schedule 04.01.2010    source แหล่งที่มา


คำตอบ (6)


ฉันจะใช้อันนี้:

header($_SERVER['SERVER_PROTOCOL'].' 304 Not Modified', true, 304);

$_SERVER['SERVER_PROTOCOL'] มีโปรโตคอลที่ใช้ในคำขอ เช่น HTTP/1.0 หรือ HTTP/1.1


แก้ไข    ฉันต้องยอมรับว่าข้อเสนอแนะของฉันไร้เหตุผล หลังจากการทดสอบไม่กี่ครั้ง ฉันสังเกตเห็นว่าหากพารามิเตอร์แรกเป็น HTTP ที่ถูกต้อง บรรทัดสถานะ PHP จะใช้บรรทัดสถานะนั้นโดยไม่คำนึงว่าจะได้รับรหัสสถานะที่สองพร้อมกับพารามิเตอร์ที่สามหรือไม่ และพารามิเตอร์ตัวที่สอง (ชื่อเอกสารที่ แทนที่) ก็ไม่มีประโยชน์เช่นกัน เนื่องจากไม่สามารถมีบรรทัดสถานะได้หลายบรรทัด

ดังนั้นพารามิเตอร์ตัวที่สองและสามในการเรียกนี้จึงซ้ำซ้อน:

header($_SERVER['SERVER_PROTOCOL'].' 304 Not Modified', true, 304);

ใช้สิ่งนี้แทน:

header($_SERVER['SERVER_PROTOCOL'].' 304 Not Modified');
person Gumbo    schedule 04.01.2010

มีสองสิ่งเกี่ยวกับพฤติกรรมของการเรียกส่วนหัวครั้งแรกที่ควรค่าแก่การชี้ให้เห็น:

  • หากคุณระบุอาร์กิวเมนต์ที่ 3 PHP จะเพิกเฉยต่ออาร์กิวเมนต์สตริงแรก และส่งการตอบกลับที่ถูกต้องสำหรับหมายเลขที่กำหนด นี่อาจทำให้วิธีแรกเสี่ยงต่อข้อผิดพลาดของโปรแกรมเมอร์น้อยลง
  • ดูเหมือนว่า PHP จะตอบสนองด้วยการตอบสนอง HTTP/1.1 แม้ว่าคำขอจะถูกสร้างขึ้นด้วย HTTP/1.0 ก็ตาม
person Ben James    schedule 04.01.2010
comment
ดูเหมือนว่าจุดแรกไม่เป็นความจริง (อย่างน้อยสำหรับเว็บโฮสต์ของฉัน) เนื่องจากฉันได้รับแบ็กเอนด์: ส่วนหัวที่มีรูปแบบไม่ถูกต้องจากสคริปต์ ส่วนหัวไม่ถูกต้อง=ไม่ได้แก้ไข: index.php... - person AlexV; 21.01.2010

ฉันจะเลือกอันที่สองเนื่องจากอาร์กิวเมนต์รหัสตอบกลับ http รองรับเท่านั้น >= PHP 4.3.0 (ซึ่งอาจส่งผลต่อความสามารถในการเคลื่อนย้ายโค้ด)

ฉันเคยทำสิ่งนี้มาหลายครั้งแล้วและไม่พบไคลเอนต์ใด ๆ ที่ไม่รองรับ HTTP/1.1 ดังนั้น เว้นแต่คุณจะมีกรณีพิเศษ ฉันไม่ควรคิดว่านั่นจะเป็นปัญหา

person Adam Hopkinson    schedule 04.01.2010
comment
ทำไมคุณถึงสนใจความเข้ากันได้ของ php4? คุณไม่ได้ใช้วัตถุ (หรือใช้มันในวิธีที่จำกัดมาก)? - person Valentin Golev; 04.01.2010
comment
อันที่จริงฉันคิดว่า PHP 4 cold dead ฉันไม่รองรับ PHP ‹ 5 ในสคริปต์ใด ๆ ของฉันอีกต่อไป - person AlexV; 04.01.2010
comment
ค่อนข้างมาก แต่ยังคงมีเซิร์ฟเวอร์ PHP 4 จำนวนมาก ดังนั้นหากจำเป็นต้องให้โค้ดสามารถพกพาได้ ก็เป็นเรื่องที่ต้องพิจารณา ทำไมคุณถึงยังสนใจ HTTP/1.0? - person Adam Hopkinson; 04.01.2010
comment
ใช่ ฉันรู้ว่ามีเซิร์ฟเวอร์ PHP 4 อยู่จำนวนหนึ่ง แต่ฉันไม่ได้ใช้/สนับสนุนเซิร์ฟเวอร์เหล่านั้น ฉันไม่ต้องการให้ PHP 4 เป็น IE 6 อื่น... ฉันไม่สนใจ HTTP 1.0 จริงๆ แต่เนื่องจากฉันสามารถควบคุมเวอร์ชัน PHP ที่ฉันรันได้ ไม่ใช่เวอร์ชัน HTTP ที่ใช้ในการสืบค้น ฉันจึงชอบคำตอบใน ภาษาเดียวกับการสืบค้น - person AlexV; 04.01.2010

โดยปกติฉันจะใช้ตัวอย่างที่สอง - อย่างไรก็ตาม เมื่อเร็วๆ นี้เปรียบเทียบแอปพลิเคชันโดยใช้ apachebench เราสังเกตเห็นว่า ab หยุดทำงานบ่อยครั้ง

หลังจากการดีบัก พบว่าส่วนหัวในลักษณะนี้:

header('HTTP/1.1 304 Not Modified')

เป็นผู้กระทำผิด (ใช่ ไม่รู้เลย) แล้วพอเปลี่ยนเป็น

header('Not Modified', true, 304);

เชื่อหรือไม่ว่า AB เริ่มทำงานแล้ว แปลกมากแต่ก็มีเรื่องให้คิด ฉันอาจจะใช้วิธีที่สองต่อไป

person mr-sk    schedule 04.01.2010
comment
แปลก... โฮสต์ของฉันขัดข้องด้วยข้อผิดพลาด 500 เมื่อใช้ส่วนหัว ('ไม่แก้ไข', จริง, 304); (ฉันได้รับข้อผิดพลาดแบ็กเอนด์: ส่วนหัวที่มีรูปแบบไม่ถูกต้องจากสคริปต์ Bad header=Not Modified: index.php ) - person AlexV; 21.01.2010

สำหรับการอ้างอิงในอนาคต ฟังก์ชัน http_response_code() จะมาใน 5.4:

http://www.php.net/manual/en/function.http-response-code.php

ทางเลือกอื่นคือ:

if (!function_exists('http_response_code')) {
    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;

    }
}

ในตัวอย่างนี้ ฉันกำลังใช้ $GLOBALS แต่คุณสามารถใช้กลไกการจัดเก็บอะไรก็ได้ที่คุณต้องการ... ฉันไม่คิดว่าจะมีวิธีส่งคืนรหัสสถานะปัจจุบัน:

https://bugs.php.net/bug.php?id=52555

สำหรับการอ้างอิงรหัสข้อผิดพลาดที่ฉันได้รับจากซอร์สโค้ดของ PHP:

http://lxr.php.net/opengrok/xref/PHP_5_4/sapi/cgi/cgi_main.c#354

และวิธีที่ส่วนหัว http ปัจจุบันถูกส่งไปพร้อมกับตัวแปรที่ใช้:

http://lxr.php.net/opengrok/xref/PHP_5_4/main/SAPI.c#856

person Craig Francis    schedule 25.01.2012

ฉันคิดว่าคำตอบของ Gumbo นั้นสมเหตุสมผลที่สุด อย่างไรก็ตาม ลองสิ่งนี้:

<?php
header('Gobbledy Gook', true, 304);
?>

หากสตริงแรกไม่ใช่ส่วนหัวที่ถูกต้อง จะถูกละทิ้ง หากฉันดูเหมือนส่วนหัวที่ถูกต้อง ก็จะถูกผนวกเข้ากับส่วนหัว - ลองสิ่งนี้:

<?php
header('Cache-Control: max-age=10', true, 304);
?>

คู่มือสำหรับ header() และหมายเหตุกรณีพิเศษ - โดยทั่วไปฉันคิดว่ามันไม่แนะนำให้พึ่งพาการวิเคราะห์พฤติกรรมในตัวดังกล่าว

อย่างไรก็ตาม ฉันเดาว่าคุณสนใจที่จะให้เนื้อหาแคชอย่างดีโดยพร็อกซี/เบราว์เซอร์ ในกรณีส่วนใหญ่ เวลาแฝงเป็นปัญหาของปัญหามากกว่าแบนด์วิธ ต่อไป ให้พิจารณาว่าเบราว์เซอร์ทำงานอย่างไรเมื่อเนื้อหาที่แคชเก่า หากไม่มีข้อมูลแคชที่อัปเดต เบราว์เซอร์จะส่งคำขอซ้ำไปยังเซิร์ฟเวอร์เพื่อดูว่าเนื้อหายังคงเก่าอยู่หรือไม่

เช่น. ในกรณีส่วนใหญ่ การเพิกเฉยต่อส่วนที่เป็นเงื่อนไขของคำขอ (หรือดีกว่าการแยกคำขอบนเว็บเซิร์ฟเวอร์) จะช่วยปรับปรุงประสิทธิภาพได้จริง

person symcbean    schedule 04.01.2010
comment
หากสตริงแรกไม่ใช่ส่วนหัวที่ถูกต้อง จะถูกละทิ้ง ถ้าฉันดูเหมือนส่วนหัวที่ถูกต้อง มันจะถูกผนวกเข้ากับส่วนหัว คุณแน่ใจหรือไม่? เมื่อฉันใช้ header('Not Modified', true, 304); ฉันได้รับข้อผิดพลาดแบ็กเอนด์: ส่วนหัวที่มีรูปแบบไม่ถูกต้องจากสคริปต์ Bad header=Not Modified: index.php เป็นเพราะเหตุนั้นหรือเปล่า? - person AlexV; 21.01.2010