def __init__(self, stdin, environ): self.stdin = stdin self.environ = environ self.form = {} self.session = None self.charset = self.DEFAULT_CHARSET or quixote.DEFAULT_CHARSET self.response = HTTPResponse() # The strange treatment of SERVER_PORT_SECURE is because IIS # sets this environment variable to "0" for non-SSL requests # (most web servers -- well, Apache at least -- simply don't set # it in that case). if (environ.get('HTTPS', 'off').lower() in ('on', 'yes', '1') or environ.get('SERVER_PORT_SECURE', '0') != '0'): self.scheme = "https" else: self.scheme = "http" k = self.environ.get('HTTP_COOKIE', '') if k: self.cookies = parse_cookies(k) else: self.cookies = {} # IIS breaks PATH_INFO because it leaves in the path to # the script, so SCRIPT_NAME is "/cgi-bin/q.py" and PATH_INFO # is "/cgi-bin/q.py/foo/bar". The following code fixes # PATH_INFO to the expected value "/foo/bar". web_server = environ.get('SERVER_SOFTWARE', 'unknown') if web_server.find('Microsoft-IIS') != -1: script = environ['SCRIPT_NAME'] path = environ['PATH_INFO'] if path.startswith(script): path = path[len(script):] self.environ['PATH_INFO'] = path
def finish_interrupted_request(self, exc): """ Called at the end of an interrupted request. Requests are interrupted by raising a PublishError exception. This method should return a string object which will be used as the result of the request. """ if not self.config.display_exceptions and exc.private_msg: exc.private_msg = None # hide it request = get_request() request.response = HTTPResponse(status=exc.status_code) output = self.format_publish_error(exc) self.session_manager.finish_successful_request() return output
def finish_interrupted_request(self, request, exc): """ Called at the end of an interrupted request. Requests are interrupted by raising a PublishError exception. This method should return a string object which will be used as the result of the request. This method searches for the nearest namespace with a _q_exception_handler attribute. That attribute is expected to be a function and is called with the request and exception instance as arguments and should return the error page (e.g. a string). If the handler doesn't want to handle a particular error it can re-raise it and the next nearest handler will be found. If no _q_exception_handler is found, the default Quixote handler is used. """ # Throw away the existing response object and start a new one # for the error document we're going to create here. request.response = HTTPResponse() # set response status code so every custom doesn't have to do it request.response.set_status(exc.status_code) if self.config.secure_errors and exc.private_msg: exc.private_msg = None # hide it # walk up stack and find handler for the exception stack = self.namespace_stack[:] while 1: handler = None while stack: object = stack.pop() if hasattr(object, "_q_exception_handler"): handler = object._q_exception_handler break if handler is None: handler = errors.default_exception_handler try: return handler(request, exc) except errors.PublishError: assert handler is not errors.default_exception_handler continue # exception was re-raised or another exception occured
def finish_failed_request(self): """ Called at the end of an failed request. Any exception (other than PublishError) causes a request to fail. This method should return a string object which will be used as the result of the request. """ # build new response to be safe request = get_request() original_response = request.response request.response = HTTPResponse() #self.log("caught an error (%s), reporting it." % # sys.exc_info()[1]) (exc_type, exc_value, tb) = sys.exc_info() error_summary = traceback.format_exception_only(exc_type, exc_value) error_summary = error_summary[0][0:-1] # de-listify and strip newline plain_error_msg = self._generate_plaintext_error(request, original_response, exc_type, exc_value, tb) if not self.config.display_exceptions: # DISPLAY_EXCEPTIONS is false, so return the most # secure (and cryptic) page. request.response.set_header("Content-Type", "text/html") user_error_msg = self._generate_internal_error(request) elif self.config.display_exceptions == 'html': # Generate a spiffy HTML display using cgitb request.response.set_header("Content-Type", "text/html") user_error_msg = self._generate_cgitb_error(request, original_response, exc_type, exc_value, tb) else: # Generate a plaintext page containing the traceback request.response.set_header("Content-Type", "text/plain") user_error_msg = plain_error_msg self.logger.log_internal_error(error_summary, plain_error_msg) request.response.set_status(500) self.session_manager.finish_failed_request() return user_error_msg