Permalink
Browse files

Replace abort() to pass exception info to error pages.

  • Loading branch information...
1 parent f6a994e commit 633a7104913ef35a284349996481e67e0e9b092e @chromakode chromakode committed with Logan Hanks Mar 14, 2012
@@ -69,6 +69,11 @@ def error_mapper(code, message, environ, global_conf=None, **kw):
if code in codes:
# StatusBasedForward expects a relative URL (no SCRIPT_NAME)
d = dict(code = code, message = message)
+
+ exception = environ.get('r2.controller.exception')
+ if exception:
+ d['explanation'] = exception.explanation
+
if environ.get('REDDIT_CNAME'):
d['cnameframe'] = 1
if environ.get('REDDIT_NAME'):
@@ -116,7 +116,8 @@ def send403(self):
else:
res = pages.RedditError(
title=_("forbidden (%(domain)s)") % dict(domain=g.domain),
- message=_("you are not allowed to do that"))
+ message=_("you are not allowed to do that"),
+ explanation=request.GET.get('explanation'))
return res.render()
def send404(self):
@@ -20,12 +20,14 @@
# Inc. All Rights Reserved.
###############################################################################
+from paste.httpexceptions import HTTPForbidden
from r2.lib.utils import Storage, tup
from pylons.i18n import _
from copy import copy
error_list = dict((
('USER_REQUIRED', _("please login to do that")),
+ ('HTTPS_REQUIRED', _("this page must be accessed using https")),
('VERIFIED_USER_REQUIRED', _("you need to set a valid email address to do that.")),
('NO_URL', _('a url is required')),
('BAD_URL', _('you should check that url')),
@@ -161,6 +163,11 @@ def remove(self, pair):
if self.errors.has_key(pair):
del self.errors[pair]
+class ForbiddenError(HTTPForbidden):
+ def __init__(self, error):
+ HTTPForbidden.__init__(self)
+ self.explanation = error_list[error]
+
class UserRequiredException(Exception): pass
class VerifiedUserRequiredException(Exception): pass
class GoldRequiredException(Exception): pass
@@ -22,22 +22,23 @@
from mako.filters import url_escape
from pylons import c, g, request
-from pylons.controllers.util import abort, redirect_to
+from pylons.controllers.util import redirect_to
from pylons.i18n import _
from pylons.i18n.translation import LanguageError
-from r2.lib.base import BaseController, proxyurl
from r2.lib import pages, utils, filters, amqp, stats
from r2.lib.utils import http_utils, is_subdomain, UniqueIterator, is_throttled
from r2.lib.cache import LocalCache, make_key, MemcachedError
import random as rand
from r2.models.account import valid_cookie, FakeAccount, valid_feed, valid_admin_cookie
from r2.models.subreddit import Subreddit, Frontpage
from r2.models import *
-from errors import ErrorSet
+from errors import ErrorSet, ForbiddenError, errors
from validator import *
from r2.lib.template_helpers import add_sr
from r2.config.extensions import is_api
from r2.lib.translation import set_lang
+from r2.lib.contrib import ipaddress
+from r2.lib.base import BaseController, proxyurl, abort
from Cookie import CookieError
from copy import copy
@@ -544,7 +545,7 @@ def cross_domain_handler(self, *args, **kwargs):
def require_https():
if not c.secure:
- abort(403)
+ abort(ForbiddenError(errors.HTTPS_REQUIRED))
def prevent_framing_and_css(allow_cname_frame=False):
def wrap(f):
View
@@ -26,8 +26,8 @@
from pylons import Response, c, g, request, session, config
from pylons.controllers import WSGIController, Controller
-from pylons.controllers.util import abort
from pylons.i18n import N_, _, ungettext, get_lang
+from paste import httpexceptions
from r2.lib.utils import to_js
from r2.lib.filters import spaceCompress, _force_unicode
from r2.lib.template_helpers import get_domain
@@ -63,6 +63,22 @@ def is_local_address(ip):
# TODO: support the /20 and /24 private networks? make this configurable?
return ip.startswith('10.')
+def abort(code_or_exception=None, detail="", headers=None, comment=None):
+ """Raise an HTTPException and save it in environ for use by error pages."""
+ # Pylons 0.9.6 makes it really hard to get your raised HTTPException,
+ # so this helper implements it manually using a familiar syntax.
+ # FIXME: when we upgrade Pylons, we can replace this with raise
+ # and access environ['pylons.controller.exception']
+ if isinstance(code_or_exception, httpexceptions.HTTPException):
+ exc = code_or_exception
+ else:
+ if type(code_or_exception) is type and issubclass(code_or_exception, httpexceptions.HTTPException):
+ exc_cls = code_or_exception
+ else:
+ exc_cls = httpexceptions.get_exception(code_or_exception)
+ exc = exc_cls(detail, headers, comment)
+ request.environ['r2.controller.exception'] = exc
+ raise exc
class BaseController(WSGIController):
def try_pagecache(self):
@@ -1380,26 +1380,32 @@ def __init__(self, client, *args, **kwargs):
class RedditError(BoringPage):
site_tracking = False
- def __init__(self, title, message, image=None, sr_description=None):
+ def __init__(self, title, message, image=None, sr_description=None,
+ explanation=None):
BoringPage.__init__(self, title, loginbox=False,
- show_sidebar = False,
+ show_sidebar = False,
content=ErrorPage(title=title,
message=message,
image=image,
- sr_description=sr_description))
+ sr_description=sr_description,
+ explanation=explanation))
class ErrorPage(Templated):
"""Wrapper for an error message"""
- def __init__(self, title, message, image=None, **kwargs):
+ def __init__(self, title, message, image=None, explanation=None, **kwargs):
if not image:
letter = random.choice(['a', 'b', 'c', 'd', 'e'])
image = 'reddit404' + letter + '.png'
+ # Normalize explanation strings.
+ if explanation:
+ explanation = explanation.lower().rstrip('.') + '.'
Templated.__init__(self,
title=title,
message=message,
image_url=image,
+ explanation=explanation,
**kwargs)
-
+
class Over18(Templated):
"""The creepy 'over 18' check page for nsfw content."""
@@ -31,6 +31,9 @@
<h1>${thing.title}</h1>
<div class="errorpage-message">
${unsafe(safemarkdown(thing.message, wrap=False))}
+ %if thing.explanation:
+ &mdash; ${thing.explanation}
+ %endif
</div>
% if thing.sr_description:

0 comments on commit 633a710

Please sign in to comment.