def handler(apachereq): """Handles an HTTP request. Intended to be called by mod_python, as a handler. @param apachereq: An Apache request object. """ # Make the request object into an IVLE request which can be given to views req = Request(apachereq, config) req.publisher = generate_publisher( config.plugin_index[ViewPlugin], ApplicationRoot(req), publicmode=req.publicmode) try: obj, viewcls, subpath = req.publisher.resolve(req.uri.decode('utf-8')) try: # We 404 if we have a subpath but the view forbids it. if not viewcls.subpath_allowed and subpath: raise NotFound() # Instantiate the view, which should be a BaseView class view = viewcls(req, obj, subpath) # Check that the request (mainly the user) is permitted to access # the view. if not view.authorize(req): # Indicate the forbidden object if this is an admin. if req.user and req.user.admin: raise Unauthorized('Unauthorized: %s' % view) else: raise Unauthorized() # Non-GET requests from other sites leave us vulnerable to # CSRFs. Block them. referer = req.headers_in.get('Referer') if (referer is None or urlparse.urlparse(req.headers_in.get('Referer')).netloc != req.hostname): if req.method != 'GET' and not view.offsite_posts_allowed: raise BadRequest( "Non-GET requests from external sites are forbidden " "for security reasons.") # Render the output view.render(req) except HTTPError, e: # A view explicitly raised an HTTP error. Respect it. req.status = e.code # Try to find a custom error view. if hasattr(viewcls, 'get_error_view'): errviewcls = viewcls.get_error_view(e) else: errviewcls = XHTMLView.get_error_view(e) if errviewcls: errview = errviewcls(req, e, obj) errview.render(req) return req.OK elif e.message: req.write(e.message) return req.OK else: return e.code except mod_python.apache.SERVER_RETURN: # A mod_python-specific Apache error. # XXX: We need to raise these because req.throw_error() uses them. # Remove this after Google Code issue 117 is fixed. raise except Exception, e: # A non-HTTPError appeared. We have an unknown exception. Panic. handle_unknown_exception(req, *sys.exc_info()) return req.OK
# A mod_python-specific Apache error. # XXX: We need to raise these because req.throw_error() uses them. # Remove this after Google Code issue 117 is fixed. raise except Exception, e: # A non-HTTPError appeared. We have an unknown exception. Panic. handle_unknown_exception(req, *sys.exc_info()) return req.OK else: # Commit the transaction if we have a store open. req.commit() return req.OK except Unauthorized, e: # Resolution failed due to a permission check. Display a pretty # error, or maybe a login page. XHTMLView.get_error_view(e)(req, e, req.publisher.root).render(req) return req.OK except PublishingError, e: req.status = 404 if req.user and req.user.admin: XHTMLErrorView(req, NotFound('Not found: ' + str(e.args)), e[0]).render(req) else: XHTMLErrorView(req, NotFound(), e[0]).render(req) return req.OK finally: # Make sure we close the store. req.cleanup()