wsgi.py
author Tero Marttila <terom@fixme.fi>
Mon, 16 Feb 2009 19:02:59 +0200
changeset 77 bef7196f7682
parent 72 5160b9e0edf1
permissions -rw-r--r--
add tree_parse test and fix treeparse to handle other than filesystem paths

"""
    WSGI application implementation
"""

# for error reporting
import sys, traceback

# for Request/Response
import http

class Application (object) :
    """
        Our WSGI application, implements the wsgi __call__ interface
    """

    def __init__ (self, handler) :
        """
            Initialize to use the given handler for requests
        """

        self.handler = handler
    
    def handle_request (self, env, start_response) :
        """
            The actual request handling code
        """

        # build Request object
        request = http.Request(env)

        try :
            # request -> response using our handler
            response = self.handler.handle_request(request)

        except http.ResponseError, err :
            # just use the generated response
            response = err.get_response()

        # send response
        assert response, "No response"
        
        # send response status/headers
        start_response(response.get_status(), response.get_headers())

        # send respones data
        yield response.get_data()

    def handle_error (self, exc_info, env, start_response) :
        """
            Handle errors thrown by handle_request. This should call start_response with the exc_info and return the
            error message (i.e. str), otherwise the error will be thrown up yet another level.

            Note that e.g. unicode is a failure...
        """

        # try and send 500 ISE to browser, if no headers yet...
        start_response("500 Internal Server Error", [('Content-type', "text/plain; charset=UTF-8")], exc_info)

        # format traceback
        data = ''.join(traceback.format_exception(*exc_info))
        
        # no unicode, kplzthx
        return data.encode('utf-8')
    
    def __call__ (self, env, start_response) :
        """
            Wraps handle_request to trap errors
        """

        try :
            # passthrough request_handler
            for chunk in self.handle_request(env, start_response) :
                yield chunk

        except :
            # execption info
            info = sys.exc_info()

            # handle
            yield self.handle_error(info, env, start_response)