Strelka::App::

Errors

module
Included Modules
Strelka::Constants
Extended With
Strelka::Plugin

Custom error-handling plugin for Strelka::App.

plugin :errors

# Handle only status 400 errors
on_status HTTP::BAD_REQUEST do |res, status_info|
    # Do something on 400 errors
end

# Handle any other error in the 4xx range
on_status 400..499 do |res, status_info|
    # Do something on 4xx errors
end

If you have the :templating plugin loaded, you can substitute a Symbol that corresponds with one of the declared templates instead:

class MyApp < Strelka::App
    plugins :errors, :templating

    layout 'layout.tmpl'
    templates :missing => 'errors/missing.tmpl'

    # Load the 'missing' template, wrap it up in the layout
    # template and render that as the body of the 404
    # response
    on_status HTTP::NOT_FOUND, :missing

end # class MyApp

The template can access the status info hash via the :status_info note on the request or response object:

<!-- error.tmpl -->
Sorry, there was a <?call request.notes[:status_info][:status] ?> error:
<?escape request.notes[:status_info][:message] ?>.

If you want to do something application-specific for an error, but still use the default error-handling, just call finish_with again with the status info from your status handler:

class MyApp < Strelka::App
    plugins :errors

    # Send an email when an app is going to return a 500 error
    on_status HTTP::SERVER_ERROR do |res, info|
        require 'mail'
        Mail.deliver do
            from    'app@example.com'
            to      'team@example.com'
            subject "SERVER_ERROR: %p [%s]" %
                    [ self.class, self.class.version_string ]
            body    "Server error while running %p [%s]: %s" %
                    [ self.class, self.conn, status.message ]
        end

        # Finish the transaction
        finish_with( info )
    end

    def handle( req )
        finish_with( HTTP::SERVER_ERROR, "Ack! Something bad happened." )
    end

end # class MyApp

See the documentation for Strelka::App::Errors::ClassMethods#on_status for more details on the status-handler block.

Constants

DEFAULT_HANDLER_STATUS_RANGE

The range of status codes to delegate to an on_status handler that doesn't specify one

Public Instance Methods

anchor
handle_request( request )

Check for a status response that is hooked, and run the hook if one is found.

# File lib/strelka/app/errors.rb, line 143
def handle_request( request )
        self.log.debug "[:errors] Wrapping request in custom error-handling."
        response = nil

        # Catch a finish_with; the status_response will only be non-nil
        status_response = catch( :finish ) do

                # Provide our own exception-handling and translate them into server errors
                begin
                        response = super
                rescue => err
                        self.log.error "%s: %s %s" % [ err.class.name, err.message, err.backtrace.first ]
                        err.backtrace[ 1..-1 ].each {|frame| self.log.debug('  ' + frame) }

                        finish_with(
                                status:    HTTP::SERVER_ERROR,
                                message:   err.message,
                                headers:   {},
                                backtrace: err.backtrace,
                                exception: err
                        )
                end
                nil
        end

        # If the app or any plugins threw a finish, look for a handler for the status code
        # and call it if one is found.
        response = self.handle_status_response( request, status_response ) if status_response

        return response
end
anchor
handle_status_response( request, status_info )

Return a response built out of the status_info for the specified request if there is a custom handler. If there isn't one, rethrows to the main :finish handler.

# File lib/strelka/app/errors.rb, line 178
def handle_status_response( request, status_info )
        status = status_info[:status]

        # If we can't find a custom handler for this status, re-throw
        # to the default handler instead
        handler = self.status_handler_for( status ) or
                throw( :finish, status_info )
        self.log.debug "Custom %d handler: %p" % [ status, handler ]

        # Set up the request's response with the right status code
        request.notes[:status_info] = status_info
        response = request.response
        response.status = status

        # The handler is an UnboundMethod, so bind it to the app instance
        # and call it
        return handler.bind( self ).call( response, status_info )
end
anchor
status_handler_for( status_code )

Find a status handler for the given status_code and return it as an UnboundMethod.

# File lib/strelka/app/errors.rb, line 199
def status_handler_for( status_code )
        self.log.debug "[:errors] Looking for a status handler for %d responses" % [ status_code ]
        handlers = self.class.status_handlers
        ranges = handlers.keys

        ranges.each do |range|
                return handlers[ range ] if range.include?( status_code )
        end

        return nil
end