SitePoint Sponsor

User Tag List

Results 1 to 12 of 12
  1. #1
    SitePoint Addict
    Join Date
    May 2006
    Location
    Amsterdam
    Posts
    206
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Issue HTTP/1.1 500 Internal Server Error on E_ERROR | E_PARSE

    Does anyone know of a way to issue an HTTP/1.1 500 Internal Server Error when an E_ERROR or E_PARSE error occurs?

    I've read and experienced the fact that the set_error_handler() cannot handle those errors, nor an Exception. I've seen one example of parsing the output buffer in order to determine if Fatal or Parse error appears and then handle as desired, but I'd rather not do that. I was hoping there might be some ERROR_STATE flag that I could use to test in a register_shutdown_function() for any type of error, but I couldn't find one ...

    Any thoughts or ideas?

  2. #2
    SitePoint Addict Mal Curtis's Avatar
    Join Date
    Jul 2009
    Location
    New Zealand
    Posts
    327
    Mentioned
    13 Post(s)
    Tagged
    0 Thread(s)
    http://www.phpdevblog.net/2008/11/ca...d-notices.html

    Try that method there. You'll notice the switch on $errNo. You can simply send the headers, and exit the script if it matches E_NOTICE.

  3. #3
    ¬.¬ shoooo... silver trophy logic_earth's Avatar
    Join Date
    Oct 2005
    Location
    CA
    Posts
    9,013
    Mentioned
    8 Post(s)
    Tagged
    0 Thread(s)
    E_PARSE, is a compile time error it cannt be caught by the application...cause it is not running. E_ERROR, is a fatel error which is not rocoverable becaue it stops ALL execution. What you are after is not possible. Forthermore, you should not have these errors on a production system.
    Logic without the fatal effects.
    All code snippets are licensed under WTFPL.


  4. #4
    SitePoint Addict
    Join Date
    May 2006
    Location
    Amsterdam
    Posts
    206
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    @Mal Curtis,
    Thanks for the link. It’s a good Class concept for handling errors such as E_WARNING as demonstrated, but as the article states, it doesn’t handle Fatal Errors, such as E_ERROR and E_PARSE.


    @logic_earth,
    “E_PARSE, is a compile time error it cannt be caught by the application...cause it is not running. E_ERROR, is a fatel error which is not rocoverable becaue it stops ALL execution.”
    This is exactly why I want the server to issue 500 Internal Server Error when this occurs; instead it issues 200 OK (the problem is, it’s not okay).

    “What you are after is not possible.”
    So far this is unfortunately what I'm observing as well ...

    “Forthermore, you should not have these errors on a production system.”
    This is an ideal that I agree with, but reality is different ...

  5. #5
    SitePoint Addict Mal Curtis's Avatar
    Join Date
    Jul 2009
    Location
    New Zealand
    Posts
    327
    Mentioned
    13 Post(s)
    Tagged
    0 Thread(s)
    Sorry, for some reason I read E_PARSE but my brain said E_NOTICE.

    E_PARSE should never be on a production server, not just in theory, but in reality. E_ERROR should just be handled with the correct try {} catch {} constructs in your code.

  6. #6
    SitePoint Addict
    Join Date
    May 2006
    Location
    Amsterdam
    Posts
    206
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks Mal Curtis,

    “E_PARSE should never be on a production server, not just in theory, but in reality.”
    Still, I’ve seen it happen, so I want to make sure we have something that covers it.

    “E_ERROR should just be handled with the correct try {} catch {} constructs in your code.”
    I was hoping this would work, but I haven't been able to get the try {} catch {} to catch an E_ERROR when PHP throws it ... maybe we’re not writing the try {} catch {} properly. Here are two examples using try{} catch{}:

    This one is catchable because our code throws the E_ERROR (“should” really be E_USER_ERROR, but using the E_ERROR for the example).
    PHP Code:
    <?php

    try {
        
        throw new 
    Exception'Testing'E_ERROR );
        
    } catch ( 
    Exception $e ) {
        
        switch ( 
    $e->getCode() ) {
            
            case 
    E_ERROR:
                
    header('HTTP/1.1 500 Internal Server Error');
                echo 
    '<h1>Internal Server Error</h1>';
                exit(
    1);
                break;
                
            
    // handle other error types with other cases
            
        
    }
    }
    And here's an example that causes PHP to throw an E_ERROR which is not catchable. The result is that the script halts processing wherever the error occurs and the header is set to 200 OK:
    PHP Code:
    <?php
    try {
        
        require_once 
    'does-not-exist.php';
        
    } catch ( 
    Exception $e ) {
        
        switch ( 
    $e->getCode() ) {
            
            case 
    E_ERROR:
                
    header('HTTP/1.1 500 Internal Server Error');
                echo 
    '<h1>Internal Server Error</h1>';
                exit(
    1);
                break;
                
            
    // handle other error types with other cases
            
        
    }
    }

  7. #7
    ¬.¬ shoooo... silver trophy logic_earth's Avatar
    Join Date
    Oct 2005
    Location
    CA
    Posts
    9,013
    Mentioned
    8 Post(s)
    Tagged
    0 Thread(s)
    The only way to catch E_PARSE and E_ERROR that I can think of is by having a proxy script. This proxy script would call the real one using the shell, it would then parse the output for those errors. A better option is to test your application, any E_PARSE or E_ERROR errors should be delt with before uploading.
    Logic without the fatal effects.
    All code snippets are licensed under WTFPL.


  8. #8
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    You could set the header to 500 initially, and then at the end of your script set it to 200. That way, if the script crashes midways, it'll have the 500 header. It's a hack, and I wouldn't really recommend it.

  9. #9
    SitePoint Addict
    Join Date
    May 2006
    Location
    Amsterdam
    Posts
    206
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    @ logic_earth,
    “A better option is to test your application, any E_PARSE or E_ERROR errors should be delt with before uploading.”
    I definitely agree; the best option would be an E_PARSE and E_ERROR free app. The issue is that sometimes, for whatever reason, we are human after all , one or two can slip by when working in a team with a fast paced production schedule. I like to play it safe and have some type of notification in place for the public and the programming team and without the ability of calling some type of “closing script” or pointing to a 500 page with the notification built-in, these type of errors could go unnoticed.


    @kyberfabrikken,
    “You could set the header to 500 initially, and then at the end of your script set it to 200”
    I found a Class at eZ Components that does something along the lines you mention. It relies on a boolean check in a registered shutdown function that will issue the Internal Server Error message, or whatever you’d like, if the boolean hasn’t been set to true before the shutdown. I tried it out and while it does achieve the effect I’m looking for, I find it annoying because we need to make sure to set the boolean to true in one or several places depending on how a script may exit. Maybe this will work for our calls to services so that they issue something besides 200 on a E_ERROR or E_PARSE halt ... I do wish PHP would do this on its own though ... I guess this boils down to a feature request.

  10. #10
    SitePoint Addict
    Join Date
    May 2006
    Location
    Amsterdam
    Posts
    206
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I did a bit more research on this topic and thought you might want to read about what I found ...

    I discovered that when display_errors is set to Off and an E_PARSE or E_ERROR error occurs, PHP will send a 500 Internal Server Error header response.

    This is great news, we were testing in a Development environment with display_errors set to On so we were getting the 200 OK header response - I imagine that represents the fact that the error messages were displayed OK. In any case, this means that any app that calls our services on the production servers will receive the 500 Internal Server Error if an E_ERROR or E_PARSE error occurs.

    That leaves two issues we were hoping to resolve:

    1. A blank page for a person browsing the page.
    2. Notification to the development team.

    Even when PHP issues the 500 Internal Server Error, the ErrorDocument specified in .htaccess or httpd.conf never appears. This is because Apache has not gone into an error state so there’s no reason for it to issue its 500 Internal Server Error page. And since PHP halts all script activity there’s no “standard” method I can find at the moment for running a last ditch message or notification script.

    So, at least we’re one step further for now ....

    Thanks again for all of your thoughts and suggestions,
    Dan

  11. #11
    SitePoint Wizard bronze trophy
    Join Date
    Jul 2008
    Posts
    5,757
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Am I missing something?
    PHP Code:
    register_shutdown_function(function(){
        
    $e error_get_last();
        
        if (
    in_array($e['type'], array(E_PARSEE_ERROR))) {
            
    ob_end_clean();
            
    header('HTTP/1.1 500 Internal Server Error');
            echo 
    '<h1>Internal Server Error</h1>';
            
    print_r($e);
            exit(
    1);
        }
    });



    ob_start();
    include 
    'app.php'
    Seems to catch E_ERROR and E_PARSE just fine on 5.3

  12. #12
    SitePoint Addict
    Join Date
    May 2006
    Location
    Amsterdam
    Posts
    206
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    @crmalibu
    Am I missing something?
    I don’t think so ... nice input, thanks!

    For a moment I thought I was reading a Javascript function
    For anyone interested in reading more about Anonymous Functions in PHP ...

    At the moment I only see two dependencies:

    1. output buffering
      • as long as the script output isn't too heavy this should be ok
      • a memory increase, i guess, could be justified if a query needs it
      • any other things you know of to watch out for?

    2. no errors in the file where the shutdown function lives and is registered
      • ... this is possible


    I added a few other error levels and tested it in 5.2.10; don't have 5.3.0 installed yet. Need to test further inside a more complex app to be sure ...

    [index.php]
    PHP Code:
    <?php

    register_shutdown_function
    'shutdownHandle' );

    function 
    shutdownHandle() {
        
       
    $e error_get_last();

        if (
            
    in_array(
                
    $e['type'],
                array(
                    
    E_PARSE,
                    
    E_ERROR,
                    
    E_COMPILE_ERROR,
                    
    E_COMPILE_WARNING,
                    
    E_USER_ERROR
                
    )
            )
        ) {
            
           
    ob_clean();
           
    header'HTTP/1.1 500 Internal Server Error' );
           echo 
    '<h1>Internal Server Error</h1>';
           
    // whatever type of output you want including mail(), public message, etc.
           // in this case debug info
           
    print_r($e);
           exit(
    1);
           
       }

    }

    ob_start();
    include 
    'closure-test.php';
    [closure-test.php]
    PHP Code:
    <?php

    echo '<h1>Closure Test</h1>';

    // Closure / Anonymous Function Test
    $helloworld = function() {
        return 
    "each hello world is different... " date"His" );
    };

    echo 
    $helloworld();

    // If you're running PHP 5.3.0 or higher
    require 'does-not-exist.php';


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •