PageRenderTime 52ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/r2/r2/controllers/error.py

https://github.com/wangmxf/lesswrong
Python | 170 lines | 136 code | 3 blank | 31 comment | 4 complexity | e6095457d6bec547f0292f539cc2314f MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, LGPL-2.1
  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. ################################################################################
  22. import os.path
  23. import paste.fileapp
  24. from pylons.middleware import error_document_template, media_path
  25. from pylons import c, request, g
  26. from pylons.i18n import _
  27. import random as rand
  28. try:
  29. # place all r2 specific imports in here. If there is a code error, it'll get caught and
  30. # the stack trace won't be presented to the user in production
  31. from reddit_base import RedditController
  32. from r2.models.subreddit import Default, Subreddit
  33. from r2.lib import pages
  34. from r2.lib.strings import rand_strings
  35. except Exception, e:
  36. if g.debug:
  37. # if debug mode, let the error filter up to pylons to be handled
  38. raise e
  39. else:
  40. # production environment: protect the code integrity!
  41. print "HuffmanEncodingError: make sure your python compiles before deploying, stupid!"
  42. # kill this app
  43. import os
  44. os._exit(1)
  45. redditbroke = \
  46. '''<html>
  47. <head>
  48. <title>LessWrong broke!</title>
  49. </head>
  50. <body>
  51. <div style="margin: auto; text-align: center">
  52. <p>
  53. <a href="/">
  54. <img border="0" src="/static/youbrokeit.png" alt="Error encountered" />
  55. </a>
  56. </p>
  57. %s
  58. </body>
  59. </html>
  60. '''
  61. toofast = \
  62. '''<html>
  63. <head><title>service temporarily unavailable</title></head>
  64. <body>
  65. the service you request is temporarily unavailable. please try again later.
  66. </body>
  67. </html>
  68. '''
  69. class ErrorController(RedditController):
  70. """Generates error documents as and when they are required.
  71. The ErrorDocuments middleware forwards to ErrorController when error
  72. related status codes are returned from the application.
  73. This behaviour can be altered by changing the parameters to the
  74. ErrorDocuments middleware in your config/middleware.py file.
  75. """
  76. allowed_render_styles = ('html', 'xml', 'js', 'embed', '')
  77. def __before__(self):
  78. try:
  79. c.error_page = True
  80. RedditController.__before__(self)
  81. except:
  82. handle_awful_failure("Error occurred in ErrorController.__before__")
  83. def __after__(self):
  84. try:
  85. RedditController.__after__(self)
  86. except:
  87. handle_awful_failure("Error occurred in ErrorController.__after__")
  88. def __call__(self, environ, start_response):
  89. try:
  90. return RedditController.__call__(self, environ, start_response)
  91. except:
  92. return handle_awful_failure("something really awful just happened.")
  93. def send403(self):
  94. c.response.status_code = 403
  95. c.site = Default
  96. title = _("Forbidden (%(domain)s)") % dict(domain=g.domain)
  97. return pages.BoringPage(title, loginbox=False,
  98. show_sidebar = False,
  99. content=pages.ErrorPage()).render()
  100. def send404(self):
  101. c.response.status_code = 404
  102. if c.site._spam and not c.user_is_admin:
  103. msg = _("This category has been banned.")
  104. res = pages.BoringPage(msg, loginbox = False,
  105. show_sidebar = False,
  106. content = pages.ErrorPage(message = msg))
  107. return res.render()
  108. else:
  109. ch=rand.choice(['a','b','c','d','e'])
  110. res = pages.BoringPage(_("Page not found"),
  111. loginbox=False,
  112. show_sidebar = False,
  113. content=pages.UnfoundPage(choice=ch))
  114. return res.render()
  115. def GET_document(self):
  116. try:
  117. code = request.GET.get('code', '')
  118. srname = request.GET.get('srname', '')
  119. if srname:
  120. c.site = Subreddit._by_name(srname)
  121. if c.render_style not in self.allowed_render_styles:
  122. return str(code)
  123. elif code == '403':
  124. return self.send403()
  125. elif code == '500':
  126. return redditbroke % rand_strings.sadmessages
  127. elif code == '503':
  128. c.response.status_code = 503
  129. c.response.headers['Retry-After'] = 1
  130. c.response.content = toofast
  131. return c.response
  132. elif c.site:
  133. return self.send404()
  134. else:
  135. return "page not found"
  136. except:
  137. return handle_awful_failure("something really bad just happened.")
  138. def handle_awful_failure(fail_text):
  139. """
  140. Makes sure that no errors generated in the error handler percolate
  141. up to the user unless debug is enabled.
  142. """
  143. if g.debug:
  144. import sys
  145. s = sys.exc_info()
  146. # reraise the original error with the original stack trace
  147. raise s[1], None, s[2]
  148. try:
  149. # log the traceback, and flag the "path" as the error location
  150. import traceback
  151. g.log.error("FULLPATH: %s" % fail_text)
  152. g.log.error(traceback.format_exc())
  153. return redditbroke % fail_text
  154. except:
  155. # we are doomed. Admit defeat
  156. return "This is an error that should never occur. You win."