简体   繁体   English

在 PHP 中触发 500 Internal Server Error 并显示 Apache 错误页面

[英]Trigger 500 Internal Server Error in PHP and display Apache error page

How can i trigger 500 Internal Server Error or 404 Page Not Found Apache errors in PHP?如何在 PHP 中触发500 Internal Server Error404 Page Not Found Apache 错误?

For 500 Internal Server Error i have tried following code :对于 500 内部服务器错误,我尝试了以下代码:

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

But it shows me a blank page.但它向我显示了一个空白页。 How can i show the error in Apache's default format?如何以 Apache 的默认格式显示错误?

Please guide..请指导..

You could just copy the Apache error documents into your web root (or symlink them in) and use header() to set the error codes and with those documents as output.您可以将 Apache 错误文档复制到您的 Web 根目录(或符号链接它们)并使用header()设置错误代码并将这些文档作为输出。 That's probably best unless you have a compelling reason not to.除非您有令人信服的理由不这样做,否则这可能是最好的。 But in case that won't work for you, there are some alternatives (albeit, hacky alternatives).但是,如果这对您不起作用,则有一些替代方案(尽管是 hacky 替代方案)。

For 500, just put a bug in your code.对于 500,只需在您的代码中添加一个错误。

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

The PHP script will raise an exception, resulting in a regular Apache 500 error page. PHP 脚本将引发异常,导致常规 Apache 500 错误页面。 (But be aware of the caveat that this will only result in an Apache error if the PHP init setting display_errors is set to 0 . In most development configurations, this is not the case. In most production configurations, this is the case. If you don't know your production server's setting, you'll have to just test this to see if it works.) (但请注意,如果 PHP init 设置display_errors设置为0 ,这只会导致 Apache 错误。在大多数开发配置中,情况并非如此。在大多数生产配置中,情况确实如此。如果您不知道您的生产服务器的设置,您必须测试它以查看它是否有效。)

For 404, I think the best you can do is redirect to a non-existent page.对于 404,我认为你能做的最好的事情就是重定向到一个不存在的页面。 It's not exactly the same thing, but might do for your purposes.这不是完全相同的事情,但可能会为您的目的做。

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

In most browsers, the users won'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.在大多数浏览器中,用户实际上不会看到重定向,他们只会默默地快速重定向到一个不存在的页面,从而导致常规的 Apache 404 错误。 Of course, the url will have changed and some users might notice that.当然,网址会发生变化,一些用户可能会注意到这一点。 If that's not acceptable, you can perhaps achieve similar results using Apache mod_rewrite to rewrite the url backend to a non-existent location.如果这是不可接受的,您也许可以使用 Apache mod_rewrite将 url 后端重写到不存在的位置来获得类似的结果。

To respond to several comments: Setting the response code via header() (or some other way) will not result in the standard Apache error document.回应几个评论:通过header() (或其他方式)设置响应代码不会导致标准的 Apache 错误文档。 It will simply return that response code with your own output.它只会用您自己的输出返回该响应代码。 This is intentional behavior, designed so that you can have custom error documents, or otherwise set response codes as the HTTP spec dictates on any request.这是有意的行为,旨在让您可以拥有自定义错误文档,或者按照 HTTP 规范对任何请求的规定设置响应代码。 If you want the Apache error documents, you have to either forge them (as per my initial suggestion of simply copying the error documents to your web root), or you'll have to trick Apache into returning them (as per my backup suggestion).如果您想要Apache错误文档,则必须伪造它们(根据我最初的建议,即简单地将错误文档复制到您的 Web 根目录),或者您必须诱使 Apache 返回它们(根据我的备份建议) .

After such a knowledge-full discussion, i think there is no php code can display the by default 500 Internal Server Error.经过如此全面的讨论,我认为没有php代码可以显示默认的500内部服务器错误。 The solution is :解决办法是:
1. Create a folder named http500 next to the php file. 1.在php文件旁边创建一个名为http500的文件夹。
2. Create a .htaccess file in it and add following code : 2. 在其中创建一个 .htaccess 文件并添加以下代码:

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

header('location : http500/'); header('位置:http500/');

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?
}

However, you will need output buffering ON to be able to use php header() function after you use any output function like echo .但是,在使用echo等任何输出函数后,您将需要输出缓冲 ON 才能使用 php header()函数。

I know this is an old thread however...我知道这是一个旧线程但是...

You could render an iframe element into your view, and then set its height and width to 100% in the event of the error you are preparing to handle.您可以将 iframe 元素渲染到您的视图中,然后在您准备处理错误时将其高度和宽度设置为 100%。

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

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

THAT SAID那说

I truly think that the best modern solution for this would be something like:我真的认为最好的现代解决方案是这样的:

<?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>

This would result in a proper error code for all users, and also a stack trace for dev if you set the $env variable to 'dev' on your dev stack.如果您在开发堆栈上将 $env 变量设置为“dev”,这将为所有用户生成正确的错误代码,并且还会为 dev 生成堆栈跟踪。 用户看到的情况,默认使用 CENTOS7 使用安装了 yum 的 PHP 5.4

No redirect, no hackery, secure unless you need to expose an error it won't.没有重定向,没有黑客,安全,除非您需要公开错误,否则它不会。 :) :)

I'm probably quite late, but this solution should work我可能已经很晚了,但是这个解决方案应该有效

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

This will trigger a 500 ISE response, and show the default 500 error page, then stop the script.这将触发 500 ISE 响应,并显示默认的 500 错误页面,然后停止脚本。 Obviously you will need to to modify the location of the included file显然你需要修改包含文件的位置

I know this is an old thread, but when I searched on Google, it jumps out as the first answer.我知道这是一个旧线程,但是当我在 Google 上搜索时,它跳出作为第一个答案。 I was trying to figure out how to do it these days, so I think I should post my workaround from 2018.这些天我试图弄清楚如何去做,所以我想我应该发布我从 2018 年开始的解决方法。

As you all have known, no, you cannot simply trigger Apache's error pages from PHP .众所周知,不,您不能简单地从 PHP 触发 Apache 的错误页面 There's no way doing it.没有办法做到。 So the best workaround I could find, after some research, is to use a PHP function to display the custom error pages , which is called from both what you specified in Apache, and the page that you want to trigger 500 Internal Server Error.因此,经过一番研究,我能找到的最佳解决方法是使用 PHP 函数来显示自定义错误页面,该页面从您在 Apache 中指定的内容以及您想要触发 500 Internal Server Error 的页面中调用。

Here is my conf of Apache:这里是我conf的Apache:

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

As you could see, all 4xx and 500 errors are redirected to a same php file.如您所见,所有 4xx 和 500 错误都被重定向到同一个 php 文件。 Why I'm not using separate files for each code is another question, which has nothing to do with your question here, so let's forget it and focus on error.php for now.为什么我不为每个代码使用单独的文件是另一个问题,这与您在这里的问题无关,所以让我们暂时忘记它,现在专注于error.php

Here are some lines of 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);
?>

In short, it receives HTTP status code from Apache via http_response_code() , and simply categorize the status code into two categories: Internal Server Error and Non-Internal Server Error.简而言之,它通过http_response_code()从 Apache 接收 HTTP 状态码,并将状态码简单地分为两类:内部服务器错误和非内部服务器错误。 It then passes the category to ErrorPage::GenerateErrorPage() which actually generates contents of the error page.然后它将类别传递给ErrorPage::GenerateErrorPage() ,后者实际生成错误页面的内容。

In ErrorPage::GenerateErrorPage() , I do something like this:ErrorPage::GenerateErrorPage() ,我做这样的事情:

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

at the beginning of the function, so that there won't be any annoying “headers already sent”.在函数的开头,这样就不会有任何烦人的“headers already sent”。 This function will generate a fully functional error page with correct (or what we expected, at least) HTTP status code.此函数将生成一个功能齐全的错误页面,其中包含正确的(或至少是我们预期的)HTTP 状态代码。 After setting the HTTP status code, as you may guess, one of two prepared contents will be generated by following php codes, one for 500, another for 404.设置完HTTP状态码后,你可能已经猜到了,下面的php代码会生成两个准备好的内容之一,一个是500,另一个是404。

Now let's go back to your question.现在让我们回到你的问题。

You want to trigger exactly the same error page as Apache does, and now you can simply call the ErrorPage::GenerateErrorPage() from wherever you want, as long as you give it correct parameters ( TRUE for 500, FALSE for 404 in my case).您想触发与 Apache 完全相同的错误页面,现在您可以简单地从任何地方调用ErrorPage::GenerateErrorPage() ,只要您给它正确的参数(在我的情况下为TRUE为 500, FALSE为 404) )。

Obviously, because that the Apache error pages are generated by the same function ErrorPage::GenerateErrorPage() , we can guarantee that what you trigger wherever is exactly what you would expect from Apache error pages.显然,因为 Apache 错误页面是由相同的函数ErrorPage::GenerateErrorPage() ,所以我们可以保证您在任何地方触发的内容正是您对 Apache 错误页面所期望的。

Here is my example of a trigger page:这是我的触发器页面示例:

<?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();
?>

The reason I use ob_start() and ob_clean() is that, in this way, I can clear anything output before the exception occurs, and send a pure 500 Internal Server Error page that looks exactly the same as Apache gives , without any content on the trigger page ( phpInfo() in this case).我使用ob_start()ob_clean()是,通过这种方式,我可以在异常发生之前清除任何输出,并发送一个纯 500 Internal Server Error 页面,该页面看起来与 Apache 给出的完全相同,没有任何内容触发页面(本例中为phpInfo() )。 ob_start() and ob_clean() also make sure that there won't be “headers already sent” , because nothing will ever be sent unless you call ob_end_flush() . ob_start()ob_clean()确保不会有“headers already sent” ,因为除非您调用ob_end_flush()否则不会发送任何内容。

The solution above is concluded from what I researched these days.上面的解决方案是根据我这些天的研究得出的。 It is so far so good for me, but I'm not sure if it is the correct way to do it.到目前为止,它对我来说很好,但我不确定这是否是正确的方法。 Any comments, questions, thoughts, suggestions and improvements are welcomed.欢迎任何意见、问题、想法、建议和改进。

you simply cannot trigger apache error pages from php code without hackery redirection as proposed by ben lee because error document redirection is handled by another layer of your application's stack (specifically, apache's mod_core ).您根本无法从 php 代码触发 apache 错误页面,而没有 ben lee 提出的黑客重定向,因为错误文档重定向是由应用程序堆栈的另一层(特别是 apache 的mod_core )处理的。
when your script runs, it's too late.当您的脚本运行时,为时已晚。

the trickery of getting an error page by throwing an exception heavily depends on your php.ini's settings about error handling and verbosity .通过抛出异常获取错误页面的技巧在很大程度上取决于您的 php.ini 的错误处理和详细设置。

http_response_code() currently only exists in php's svn thus it's not available in most production environments which are supposed to run an official release version. http_response_code()目前只存在于 php 的 svn 中,因此它在大多数应该运行官方发布版本的生产环境中不可用。

my advice is to properly implement a custom error and exception handler via set_error_handler() and set_exception_handler() , respectively, use header() to send the client proper http status information and (if needed) generate error pages.我的建议是分别通过set_error_handler()set_exception_handler()正确实现自定义错误和异常处理程序,使用header()向客户端发送正确的 http 状态信息并(如果需要)生成错误页面。

On PHP 5.5 => "header("tester.php",true,500);"在 PHP 5.5 => "header("tester.php",true,500);" where tester.php does not exist.其中 tester.php 不存在。 It works and takes me to my 500 page :)它有效并带我到我的 500 页 :)

Unfortunately none of the other methods listed here worked for me for one reason or the other.不幸的是,出于某种原因,此处列出的其他方法均不适合我。

内部服务器错误 500 的原因。我打开 httpd.conf 文本文件并编辑它修复了我的错误,只需更改我的 serverName localhost 81 而不是 80。

Apparently there is a function called http_response_code that will let you set the response code appropriately.显然有一个名为http_response_code的函数可以让您适当地设置响应代码。 If that doesn't work (there's a note in the documentation about it possibly being only in SVN) then the header function can take an optional response code argument:如果这不起作用(文档中有关于它可能仅在 SVN 中的注释),则header函数可以采用可选的响应代码参数:

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

This should signal Apache correctly.这应该正确地向 Apache 发出信号。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM