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

前端 未结 9 969
一整个雨季
一整个雨季 2020-12-25 11:30

How can i trigger 500 Internal Server Error or 404 Page Not Found Apache errors in PHP?

For 500 Internal Server Error i have tried

相关标签:
9条回答
  • 2020-12-25 12:07
    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.

    0 讨论(0)
  • 2020-12-25 12:07

    I know this is an old thread, but when I searched on Google, it jumps out as the first answer. I was trying to figure out how to do it these days, so I think I should post my workaround from 2018.

    As you all have known, no, you cannot simply trigger Apache’s error pages from PHP. 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.

    Here is my conf of 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. 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.

    Here are some lines of 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. It then passes the category to ErrorPage::GenerateErrorPage() which actually generates contents of the error page.

    In ErrorPage::GenerateErrorPage(), I do something like this:

    <?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”. This function will generate a fully functional error page with correct (or what we expected, at least) HTTP status code. 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.

    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).

    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.

    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() 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().

    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.

    0 讨论(0)
  • 2020-12-25 12:14

    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).
    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.

    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.

    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.

    0 讨论(0)
提交回复
热议问题