首页 文章

在PHP中触发500内部服务器错误并显示Apache错误页面

提问于
浏览
35

如何在PHP中触发 500 Internal Server Error404 Page Not Found Apache错误?

对于500内部服务器错误,我尝试了以下代码:

header("HTTP/1.0 500 Internal Server Error");

但它显示了一个空白页面 . 如何以Apache的默认格式显示错误?

请指导..

9 回答

  • 0

    您可以将Apache错误文档复制到Web根目录中(或将它们符号链接)并使用header()设置错误代码并将这些文档作为输出 . 那对你有用,有一些替代品(虽然是hacky替代品) .

    对于500,只需在代码中添加一个错误 .

    <?php throw new Exception('Nooooooooooooooo!'); ?>
    

    PHP脚本将引发异常,从而产生常规的Apache 500错误页面 . (但请注意,如果PHP初始化设置 display_errors 设置为 0 ,这只会导致Apache错误 . 在大多数开发配置中,情况并非如此 . 在大多数 生产环境 配置中,情况就是这样 . 如果你不要设置,你只需要测试它,看看它是否有效 . )

    对于404,我认为您可以做的最好的事情是重定向到不存在的页面 . 它不是完全相同的东西,但可能适用于您的目的 .

    <?php header("Location: /i-dont-think-therefore-i-am-not"); ?>
    

    在大多数浏览器中,用户赢得了't actually see the redirect, they will just get silently and quickly redirected to a non-existent page, resulting in a regular Apache 404 error. Of course, the url will have changed and some users might notice that. If that'不可接受,您可以使用Apache mod_rewrite将URL后端重写为不存在的位置,从而获得类似的结果 .

    要回复几条注释:通过 header() (或其他方式)设置响应代码不会产生标准的Apache错误文档 . 它只会使用您自己的输出返回响应代码 . 这是故意行为,旨在使您可以拥有自定义错误文档,或者按照HTTP规范对任何请求的指示设置响应代码 . 如果你想要Apache错误文档,你必须要么伪造它们(根据我最初建议的只是将错误文档复制到你的web根目录),或者你必须欺骗Apache返回它们(根据我的备份建议) .

  • 6

    经过这样的知识全面讨论,我认为没有php代码可以默认显示500内部服务器错误 . 解决方案是:
    1.在php文件旁边创建一个名为 http500 的文件夹 .
    2.在其中创建.htaccess文件并添加以下代码:

    <IfModule mod_rewrite.c>
        RewriteEngine On
        RewriteCond %{REQUEST_FILENAME} -d
        RewriteRule ^])(.(*/
        RewriteRule ^])((a-zA
    </IfModule>
    
    • PHP重定向代码:

    header('location:http500 /');

  • 3
    function ISE()
    {
      header('HTTP/1.1 500 Internal Server Error', true, 500);
      trigger_error('ISE function called.', E_USER_ERROR);//if you are logging errors?
    }
    

    但是,在使用任何输出函数(如 echo )之后,您将需要输出缓冲ON才能使用php header() 函数 .

  • 0

    我可能已经很晚了,但这个解决方案应该可行

    header("HTTP/1.0 500 Internal Server Error");
    include("/path-to-public-html/errors/500.php");
    die();
    

    这将触发500 ISE响应,并显示默认的500错误页面,然后停止脚本 . 显然,您需要修改包含文件的位置

  • 11

    你根本无法触发来自php代码的apache错误页面而没有像ben lee所提议的hackery重定向,因为错误文档重定向是由应用程序的另一层处理的's stack (specifically, apache' s mod_core) .
    当你的脚本运行时,为时已晚 .

    通过抛出异常来获取错误页面的诡计很大程度上取决于你的php.ini关于error handling and verbosity的设置 .

    http_response_code() 目前仅存在于php 's svn thus it'中,在大多数应该运行正式发布版本的 生产环境 环境中不可用 .

    我的建议是分别通过 set_error_handler()set_exception_handler() 正确实现自定义错误和异常处理程序,使用 header() 发送客户端正确的http状态信息和(如果需要)生成错误页面 .

  • 0

    显然有一个名为http_response_code的函数可以让你适当地设置响应代码 . 如果没有't work (there'在文档中关于它的说明可能仅在SVN中)那么 header 函数可以采用可选的响应代码参数:

    header("HTTP/1.0 ...", true, 404);
    

    这应该正确地告诉Apache .

  • 7

    在PHP 5.5 =>“header(”tester.php“,true,500);”其中tester.php不存在 . 它工作,带我到我的500页:)

    不幸的是,由于某种原因,这里列出的其他方法都不适用于我 .

  • 0

    我知道这是一个老线程但是......

    您可以在视图中渲染iframe元素,然后在您准备处理的错误中将其高度和宽度设置为100% .

    <?php header("HTTP/1.0 500 Internal Server Error"); http_response_code(500); ?>

    <iframe src="page_displaying_apache_screenshot_fullscreen.html"></iframe>

    这说的

    我真的认为最好的现代解决方案是这样的:

    <?php
    header("HTTP/1.0 500 Internal Server Error");
    http_response_code(500);
    ?>
    <div class="panel-body">
        <h1>Error!</h1>
         <p>
             <?php
    
             // Then, in the view if your in dev env, print exception and stack trace
             if ($env === 'dev') 
             {
                 throw new Exception('Uh oh! Something broke while adding a new user the db.');
             }
             else 
             {
                 echo "Hold your butts, an error has occured.";
                 die();
             }
             ?>
         </p>
       </div>
    

    如果在开发堆栈上将$ env变量设置为'dev',这将导致所有用户的正确错误代码,以及dev的堆栈跟踪 .
    What the user sees with this, using PHP 5.4 installed with yum using CENTOS7 by default

    没有重定向,没有hackery,安全,除非你需要暴露它不会发生的错误 . :)

  • 2

    我知道这是一个老话题,但是当我在Google上搜索时,它会跳出来作为第一个答案 . 这几天我试图弄清楚如何做到这一点,所以我想我应该从2018年开始我的解决方法 .

    众所周知,不, you cannot simply trigger Apache’s error pages from PHP . 没办法做到这一点 . 因此,在经过一些研究之后,我能找到的最好的解决方法是 to use a PHP function to display the custom error pages ,这是从你的两个方面调用的在Apache中指定,以及要触发500内部服务器错误的页面 .

    这是我的 conf 的Apache:

    ErrorDocument 400 /error.php
    ErrorDocument 401 /error.php
    ErrorDocument 403 /error.php
    ErrorDocument 404 /error.php
    ErrorDocument 500 /error.php
    

    如您所见,所有4xx和500错误都被重定向到同一个php文件 . 为什么我没有为每个代码使用单独的文件是另一个问题,这与你的问题无关,所以让我们忘记它并立即关注 error.php .

    以下是 error.php 的一些行:

    <?php
    require_once("error_page.php");
    
    $relative_path = "";
    $internal_server_error = FALSE;
    
    if (isset($_SERVER['REDIRECT_URL']) && $_SERVER['REDIRECT_URL'] != "")
    {
        $relative_path = $_SERVER['REDIRECT_URL'];
        $internal_server_error = (http_response_code() >= 500);
    }
    else if (isset($_SERVER['REQUEST_URI']))
    {
        $relative_path = $_SERVER['REQUEST_URI'];
    }
    
    ErrorPage::GenerateErrorPage($internal_server_error, $relative_path);
    ?>
    

    简而言之,它通过 http_response_code() 从Apache接收HTTP状态代码,并简单地将状态代码分为两类:内部服务器错误和非内部服务器错误 . 然后它将类别传递给 ErrorPage::GenerateErrorPage() ,它实际上生成了错误页面的内容 .

    ErrorPage::GenerateErrorPage() 中,我做了这样的事情:

    <?php
    http_response_code($internal_server_error ? 500 : 404);
    ?>
    

    在函数的开头,这样就不会有任何恼人的“已经发送的头” . 此函数将生成一个功能完整的错误页面,其中包含正确的(或至少我们期望的)HTTP状态代码 . 在设置HTTP状态代码之后,正如您可能猜到的,将通过以下php代码生成两个准备好的内容之一,一个用于500,另一个用于404 .

    现在让我们回到你的问题 .

    你想要触发与Apache完全相同的错误页面,现在只要你给它正确的参数( TRUE 为500, FALSE 为404,在我的情

    显然,因为Apache错误页面是由同一个函数 ErrorPage::GenerateErrorPage() 生成的,所以我们可以保证您触发的内容与Apache错误页面完全相同 .

    这是我的触发页面示例:

    <?php
    ob_start();
    
    require_once("error_page.php");
    
    try
    {
        // Actual contents go here
        phpInfo();
        throw new Exception('test exception');
    }
    catch (Exception $e)
    {
        ob_clean();
        ErrorPage::GenerateErrorPage(TRUE);
        ob_end_flush();
        exit();
    }
    
    ob_end_flush();
    ?>
    

    我使用 ob_start()ob_clean() 的原因是,通过这种方式,我可以在异常发生之前清除任何输出,并且 send a pure 500 Internal Server Error page that looks exactly the same as Apache gives ,在触发页面上没有任何内容(在这种情况下为 phpInfo() ) . ob_start()ob_clean() 也是 make sure that there won’t be “headers already sent” ,因为除非你打电话给 ob_end_flush() ,否则什么都不会发送 .

    上面的解决方案是我最近研究的结论 . 这对我来说是如此的好,但我不确定这是否是正确的方法 . 欢迎提出任何意见,问题,想法,建议和改进 .

相关问题