terom@7: terom@7: """ terom@7: WSGI application implementation terom@7: """ terom@7: terom@7: # for error reporting terom@7: import sys, traceback terom@7: terom@7: # for Request/Response terom@7: import http terom@7: terom@31: class Application (object) : terom@7: """ terom@31: Our WSGI application, implements the wsgi __call__ interface terom@7: """ terom@7: terom@31: def __init__ (self, handler) : terom@31: """ terom@31: Initialize to use the given handler for requests terom@31: """ terom@30: terom@31: self.handler = handler terom@7: terom@31: def handle_request (self, env, start_response) : terom@31: """ terom@31: The actual request handling code terom@31: """ terom@7: terom@31: # build Request object terom@31: request = http.Request(env) terom@7: terom@31: try : terom@31: # request -> response using our handler terom@31: response = self.handler.handle_request(request) terom@7: terom@31: except http.ResponseError, err : terom@31: # just use the generated response terom@31: response = err.get_response() terom@7: terom@31: # send response terom@31: assert response, "No response" terom@31: terom@31: # send response status/headers terom@31: start_response(response.get_status(), response.get_headers()) terom@7: terom@31: # send respones data terom@31: yield response.get_data() terom@31: terom@72: def handle_error (self, exc_info, env, start_response) : terom@72: """ terom@72: Handle errors thrown by handle_request. This should call start_response with the exc_info and return the terom@72: error message (i.e. str), otherwise the error will be thrown up yet another level. terom@72: terom@72: Note that e.g. unicode is a failure... terom@72: """ terom@72: terom@72: # try and send 500 ISE to browser, if no headers yet... terom@72: start_response("500 Internal Server Error", [('Content-type', "text/plain; charset=UTF-8")], exc_info) terom@72: terom@72: # format traceback terom@72: data = ''.join(traceback.format_exception(*exc_info)) terom@72: terom@72: # no unicode, kplzthx terom@72: return data.encode('utf-8') terom@72: terom@31: def __call__ (self, env, start_response) : terom@31: """ terom@31: Wraps handle_request to trap errors terom@31: """ terom@31: terom@31: try : terom@31: # passthrough request_handler terom@31: for chunk in self.handle_request(env, start_response) : terom@31: yield chunk terom@31: terom@31: except : terom@31: # execption info terom@31: info = sys.exc_info() terom@31: terom@72: # handle terom@72: yield self.handle_error(info, env, start_response) terom@31: