From: Sebastian Spaeth Date: Sun, 23 Dec 2012 10:57:45 +0000 (+0100) Subject: Provide tools.response.render_http_exception and use that X-Git-Url: https://vcs.fsf.org/?a=commitdiff_plain;h=785b287fcb42ac9130b222006097e3f68cec3543;p=mediagoblin.git Provide tools.response.render_http_exception and use that After the webob->werkzeug transition, controller functions can raise werkzeug.HttpExceptions. We need to catch these in app.py when calling the controller and handle them, rendering the corresponding error Response() object. For consistency, we also want to allow meddleware functions to raise HttpExceptions (e.g. the csrf meddleware needs to complain about lack of cookies), so wrap the request and response parts of the meddleware too. Finally, the urlmap.match() can also raise HttpExceptions, so we give it the same treatment (render_http_exception). I am not sure, if we do not need to handle the Redirect exception there in any different way though... The new function render_http_exception makes use of the render_error infrastructure to return a nicely templated error page. It also checks if the stock error messages was used in cases where we have localizations (403, 404) and use those. It is now possible to do things like "raise Forbidden(_('You suckr'))" or raise NotFound(_('where is my left show again')) if you want to return customized error messages to the user. Signed-off-by: Sebastian Spaeth --- diff --git a/mediagoblin/app.py b/mediagoblin/app.py index 1a398bcd..d1f4cab7 100644 --- a/mediagoblin/app.py +++ b/mediagoblin/app.py @@ -24,7 +24,7 @@ from werkzeug.exceptions import HTTPException, NotFound from mediagoblin import meddleware, __version__ from mediagoblin.tools import common, translate, template -from mediagoblin.tools.response import render_404 +from mediagoblin.tools.response import render_http_exception from mediagoblin.tools.theme import register_themes from mediagoblin.tools import request as mg_request from mediagoblin.mg_globals import setup_globals @@ -188,12 +188,11 @@ class MediaGoblinApp(object): try: endpoint, url_values = map_adapter.match() request.matchdict = url_values - except NotFound as exc: - return render_404(request)(environ, start_response) except HTTPException as exc: - # exceptions that match() is documented to return: - # MethodNotAllowed, RequestRedirect TODO: need to handle ??? - return exc(environ, start_response) + # Stop and render exception + return render_http_exception( + request, exc, + exc.get_description(environ))(environ, start_response) view_func = view_functions[endpoint] @@ -209,19 +208,32 @@ class MediaGoblinApp(object): controller = view_func # pass the request through our meddleware classes - for m in self.meddleware: - response = m.process_request(request, controller) - if response is not None: - return response(environ, start_response) + try: + for m in self.meddleware: + response = m.process_request(request, controller) + if response is not None: + return response(environ, start_response) + except HTTPException as e: + return render_http_exception( + request, e, + e.get_description(environ))(environ, start_response) request.start_response = start_response - # get the response from the controller - response = controller(request) + # get the Http response from the controller + try: + response = controller(request) + except HTTPException as e: + response = render_http_exception( + request, e, e.get_description(environ)) - # pass the response through the meddleware - for m in self.meddleware[::-1]: - m.process_response(request, response) + # pass the response through the meddlewares + try: + for m in self.meddleware[::-1]: + m.process_response(request, response) + except HTTPException as e: + response = render_http_exeption( + request, e, e.get_description(environ)) return response(environ, start_response) diff --git a/mediagoblin/tools/response.py b/mediagoblin/tools/response.py index b02dd6b5..80df1f5a 100644 --- a/mediagoblin/tools/response.py +++ b/mediagoblin/tools/response.py @@ -63,6 +63,25 @@ def render_404(request): return render_error(request, 404, err_msg=err_msg) +def render_http_exception(request, exc, description): + """Return Response() given a werkzeug.HTTPException + + :param exc: werkzeug.HTTPException or subclass thereof + :description: message describing the error.""" + # If we were passed the HTTPException stock description on + # exceptions where we have localized ones, use those: + stock_desc = (description == exc.__class__.description) + + if stock_desc and exc.code == 403: + return render_403(request) + elif stock_desc and exc.code == 404: + return render_404(request) + + return render_error(request, title=exc.args[0], + err_msg=description, + status=exc.code) + + def redirect(request, *args, **kwargs): """Redirects to an URL, using urlgen params or location string