PageRenderTime 66ms CodeModel.GetById 53ms app.highlight 9ms RepoModel.GetById 0ms app.codeStats 1ms

/r2/r2/controllers/error.py

https://github.com/wangmxf/lesswrong
Python | 170 lines | 136 code | 3 blank | 31 comment | 5 complexity | e6095457d6bec547f0292f539cc2314f MD5 | raw file
  1# The contents of this file are subject to the Common Public Attribution
  2# License Version 1.0. (the "License"); you may not use this file except in
  3# compliance with the License. You may obtain a copy of the License at
  4# http://code.reddit.com/LICENSE. The License is based on the Mozilla Public
  5# License Version 1.1, but Sections 14 and 15 have been added to cover use of
  6# software over a computer network and provide for limited attribution for the
  7# Original Developer. In addition, Exhibit A has been modified to be consistent
  8# with Exhibit B.
  9# 
 10# Software distributed under the License is distributed on an "AS IS" basis,
 11# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
 12# the specific language governing rights and limitations under the License.
 13# 
 14# The Original Code is Reddit.
 15# 
 16# The Original Developer is the Initial Developer.  The Initial Developer of the
 17# Original Code is CondeNet, Inc.
 18# 
 19# All portions of the code written by CondeNet are Copyright (c) 2006-2008
 20# CondeNet, Inc. All Rights Reserved.
 21################################################################################
 22import os.path
 23
 24import paste.fileapp
 25from pylons.middleware import error_document_template, media_path
 26from pylons import c, request, g
 27from pylons.i18n import _
 28import random as rand
 29
 30try:
 31    # place all r2 specific imports in here.  If there is a code error, it'll get caught and
 32    # the stack trace won't be presented to the user in production
 33    from reddit_base import RedditController
 34    from r2.models.subreddit import Default, Subreddit
 35    from r2.lib import pages
 36    from r2.lib.strings import rand_strings
 37except Exception, e:
 38    if g.debug:
 39        # if debug mode, let the error filter up to pylons to be handled
 40        raise e
 41    else:
 42        # production environment: protect the code integrity!
 43        print "HuffmanEncodingError: make sure your python compiles before deploying, stupid!"
 44        # kill this app
 45        import os
 46        os._exit(1)
 47    
 48redditbroke =  \
 49'''<html>
 50  <head>
 51    <title>LessWrong broke!</title>
 52  </head>
 53  <body>
 54    <div style="margin: auto; text-align: center">
 55      <p>
 56        <a href="/">
 57          <img border="0" src="/static/youbrokeit.png" alt="Error encountered" />
 58        </a>
 59      </p>
 60        %s
 61  </body>
 62</html>
 63'''            
 64
 65toofast =  \
 66'''<html>
 67  <head><title>service temporarily unavailable</title></head>
 68  <body>
 69    the service you request is temporarily unavailable. please try again later.
 70  </body>
 71</html>
 72'''            
 73
 74class ErrorController(RedditController):
 75    """Generates error documents as and when they are required.
 76
 77    The ErrorDocuments middleware forwards to ErrorController when error
 78    related status codes are returned from the application.
 79
 80    This behaviour can be altered by changing the parameters to the
 81    ErrorDocuments middleware in your config/middleware.py file.
 82    """
 83    allowed_render_styles = ('html', 'xml', 'js', 'embed', '')
 84    def __before__(self):
 85        try:
 86            c.error_page = True
 87            RedditController.__before__(self)
 88        except:
 89            handle_awful_failure("Error occurred in ErrorController.__before__")
 90
 91    def __after__(self): 
 92        try:
 93            RedditController.__after__(self)
 94        except:
 95            handle_awful_failure("Error occurred in ErrorController.__after__")
 96
 97    def __call__(self, environ, start_response):
 98        try:
 99            return RedditController.__call__(self, environ, start_response)
100        except:
101            return handle_awful_failure("something really awful just happened.")
102
103
104    def send403(self):
105        c.response.status_code = 403
106        c.site = Default
107        title = _("Forbidden (%(domain)s)") % dict(domain=g.domain)
108        return pages.BoringPage(title,  loginbox=False,
109                                show_sidebar = False, 
110                                content=pages.ErrorPage()).render()
111
112    def send404(self):
113        c.response.status_code = 404
114        if c.site._spam and not c.user_is_admin:
115            msg = _("This category has been banned.")
116            res =  pages.BoringPage(msg, loginbox = False,
117                                    show_sidebar = False, 
118                                    content = pages.ErrorPage(message = msg))
119            return res.render()
120        else:
121            ch=rand.choice(['a','b','c','d','e'])
122            res = pages.BoringPage(_("Page not found"),
123                                   loginbox=False,
124                                   show_sidebar = False, 
125                                   content=pages.UnfoundPage(choice=ch))
126            return res.render()
127
128    def GET_document(self):
129        try:
130            code =  request.GET.get('code', '')
131            srname = request.GET.get('srname', '')
132            if srname:
133                c.site = Subreddit._by_name(srname)
134            if c.render_style not in self.allowed_render_styles:
135                return str(code)
136            elif code == '403':
137                return self.send403()
138            elif code == '500':
139                return redditbroke % rand_strings.sadmessages
140            elif code == '503':
141                c.response.status_code = 503
142                c.response.headers['Retry-After'] = 1
143                c.response.content = toofast
144                return c.response
145            elif c.site:
146                return self.send404()
147            else:
148                return "page not found"
149        except:
150            return handle_awful_failure("something really bad just happened.")
151
152def handle_awful_failure(fail_text):
153    """
154    Makes sure that no errors generated in the error handler percolate
155    up to the user unless debug is enabled.
156    """
157    if g.debug:
158        import sys
159        s = sys.exc_info()
160        # reraise the original error with the original stack trace
161        raise s[1], None, s[2]
162    try:
163        # log the traceback, and flag the "path" as the error location
164        import traceback
165        g.log.error("FULLPATH: %s" % fail_text)
166        g.log.error(traceback.format_exc())
167        return redditbroke % fail_text
168    except:
169        # we are doomed.  Admit defeat
170        return "This is an error that should never occur.  You win."