非常简单的问题:这两个PHP(版本5+)标题调用中的哪一个是“最佳”?
header('Not Modified', true, 304);
header('HTTP/1.1 304 Not Modified');
我很确定第一个是最多价的那个,但只是好奇如果在HTTP 1.0下PHP会“修复”第二个......
谢谢!
编辑:其中一个标题在我的网络主机上崩溃了PHP。后续问题: PHP header() call "crashing" script with HTTP 500 error
答案 0 :(得分:8)
我会用这个:
header($_SERVER['SERVER_PROTOCOL'].' 304 Not Modified', true, 304);
$_SERVER['SERVER_PROTOCOL']
包含请求中使用的协议,例如HTTP/1.0
或HTTP/1.1
。
编辑我必须承认我的建议毫无意义。经过几次测试后,我注意到如果第一个参数是有效的HTTP status line,PHP将使用该状态行,而不管第三个参数是否给出了第二个状态代码。第二个参数(文档名称 replace )也没用,因为不能有多个状态行。
因此,此调用中的第二个和第三个参数只是多余的:
header($_SERVER['SERVER_PROTOCOL'].' 304 Not Modified', true, 304);
请改用:
header($_SERVER['SERVER_PROTOCOL'].' 304 Not Modified');
答案 1 :(得分:4)
第一个标题调用的行为有两点值得指出:
答案 2 :(得分:2)
我选择第二个,因为只支持http响应代码参数> = PHP 4.3.0(这可能会影响代码的可移植性)。
我已经多次这样做了,并没有遇到任何不支持HTTP / 1.1的客户端,所以除非你有特殊情况,否则我不应该认为这将是一个问题。
答案 3 :(得分:2)
我通常会使用第二个示例 - 但是,在最近使用apachebench对应用程序进行基准测试时,我们注意到ab经常挂起。
调试后,确定了此样式的标题:
header('HTTP/1.1 304 Not Modified')
是罪魁祸首(是的,我不知道)并且在更改后,
header('Not Modified', true, 304);
信不信由你开始工作。很奇怪,但要考虑一些事情。我可能会使用第二种方法。
答案 4 :(得分:2)
为了将来参考,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标头:
答案 5 :(得分:1)
我认为Gumbo的答案到目前为止是最明智的。不过试试这个:
<?php
header('Gobbledy Gook', true, 304);
?>
如果第一个字符串不是正确的标题,则将其丢弃。如果iy看起来像一个有效的标题,它会被附加到标题中 - 试试这个:
<?php
header('Cache-Control: max-age=10', true, 304);
?>
header()的手册并注意特殊情况 - 总的来说,我认为不建议依赖这种内置的启发式方法。
但是,我猜你真的有兴趣通过代理/浏览器很好地缓存内容。在大多数情况下,延迟远比带宽更成问题。接下来考虑一下当缓存内容过时时浏览器的行为 - 在没有更新的缓存信息的情况下,它会不断向服务器发出重复请求以查看内容是否仍然过时。
即。在大多数情况下,忽略请求的条件部分(或者甚至更好地在Web服务器上剥离它们)实际上提高了性能。