在 .htaccess 重定向后通过 PHP 发送 404 header
Send 404 header via PHP after .htaccess redirect
我想创建一个自定义 404 页面,但它不会发送 404 Header,它仍然发送 200 OK。
.htaccess
我的 .htaccess 将每个请求重定向到 index.php。
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ /index.php [NC,L]
index.php
index.php 处理包含 .php 文件的 url。实际上 controller.php 解析 URL 最后 pasteContent.php 包含请求的 .php content-file.
//Handle URL
require 'inc/controller.php';
//Paste <head>
require 'inc/site_header.php';
//Paste <body>
require 'inc/pasteContent.php';
//Paste footer
require 'inc/site_footer.php';
进一步了解 controller.php:
如您所见,在没有任何输出之前,我已经尝试发送 404-Header。
//Parse the URL
function parse_path() {
[...]
return $path;
}
$path_info = parse_path();
$controller = $path_info['call_parts'][0];
//Does this page exist?
function contentFound($c){
$found = true;
switch ($c) {
[...]
default:
$found = false;
} return $found;
}
//If content does not exist -> 404
if(!contentFound($controller)) {
header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found");
require 'inc/site_header.php';
require 'inc/pasteContent.php';
require 'inc/site_footer.php';
die();
}
实际上我也尝试将 header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found");?
放在我的 index.php 之上,我们被重定向到那里,但它仍然发送 200 OK。
我做错了什么?
确保 headers 和内容(如果空格在 <?php
之前则开始发送)尚未由 PHP 发送。
if (headers_sent($filename, $linenum)) {
echo "Headers sent in $filename on line $linenum\n";
exit;
}
如果您知道哪个文件在哪一行开始输出,也许您会看到,出了什么问题。
作为解决方法,您可以使用 output buffering:
在 index.php 的顶部插入 ob_start();
和 PHP 将等到脚本终止后再发送任何内容。
你可以直接这样定义协议<?php
header("HTTP/1.0 404 Not Found");
?>
,也可以尝试使用http_response_code(404);
重置状态码
正如 KIMB-technologies 在他之前对这个问题的 answer 中指出的那样,空格导致了这个问题。如果您在任何 PHP 文件的开头都找不到任何可见的空格,那么它们上面可能存在不可见的空格。
有时 UTF-8 BOM(字节顺序标记)出现在某些文件中。它对文本编辑器是不可见的,但会弄乱 PHP headers.
Google 了解适合您 OS 的方法,使用 Bash、Powershell 或其他工具删除它。一些 IDE,例如 PhpStorm,直接提供删除。
我想创建一个自定义 404 页面,但它不会发送 404 Header,它仍然发送 200 OK。
.htaccess
我的 .htaccess 将每个请求重定向到 index.php。
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ /index.php [NC,L]
index.php
index.php 处理包含 .php 文件的 url。实际上 controller.php 解析 URL 最后 pasteContent.php 包含请求的 .php content-file.
//Handle URL
require 'inc/controller.php';
//Paste <head>
require 'inc/site_header.php';
//Paste <body>
require 'inc/pasteContent.php';
//Paste footer
require 'inc/site_footer.php';
进一步了解 controller.php:
如您所见,在没有任何输出之前,我已经尝试发送 404-Header。
//Parse the URL
function parse_path() {
[...]
return $path;
}
$path_info = parse_path();
$controller = $path_info['call_parts'][0];
//Does this page exist?
function contentFound($c){
$found = true;
switch ($c) {
[...]
default:
$found = false;
} return $found;
}
//If content does not exist -> 404
if(!contentFound($controller)) {
header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found");
require 'inc/site_header.php';
require 'inc/pasteContent.php';
require 'inc/site_footer.php';
die();
}
实际上我也尝试将 header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found");?
放在我的 index.php 之上,我们被重定向到那里,但它仍然发送 200 OK。
我做错了什么?
确保 headers 和内容(如果空格在 <?php
之前则开始发送)尚未由 PHP 发送。
if (headers_sent($filename, $linenum)) {
echo "Headers sent in $filename on line $linenum\n";
exit;
}
如果您知道哪个文件在哪一行开始输出,也许您会看到,出了什么问题。
作为解决方法,您可以使用 output buffering:
在 index.php 的顶部插入 ob_start();
和 PHP 将等到脚本终止后再发送任何内容。
你可以直接这样定义协议<?php
header("HTTP/1.0 404 Not Found");
?>
,也可以尝试使用http_response_code(404);
正如 KIMB-technologies 在他之前对这个问题的 answer 中指出的那样,空格导致了这个问题。如果您在任何 PHP 文件的开头都找不到任何可见的空格,那么它们上面可能存在不可见的空格。
有时 UTF-8 BOM(字节顺序标记)出现在某些文件中。它对文本编辑器是不可见的,但会弄乱 PHP headers.
Google 了解适合您 OS 的方法,使用 Bash、Powershell 或其他工具删除它。一些 IDE,例如 PhpStorm,直接提供删除。