在 .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,直接提供删除。