/usr/share/pyshared/cherrypy/_cperror.py is in python-cherrypy 2.3.0-3.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 | """Error classes for CherryPy."""
import urllib
import urlparse
class Error(Exception):
pass
class NotReady(Error):
"""A request was made before the app server has been started."""
pass
class WrongConfigValue(Error):
""" Happens when a config value can't be parsed, or is otherwise illegal. """
pass
class RequestHandled(Exception):
"""Exception raised when no further request handling should occur."""
pass
class InternalRedirect(Exception):
"""Exception raised when processing should be handled by a different path.
If you supply 'params', it will be used to re-populate params.
If 'params' is a dict, it will be used directly.
If 'params' is a string, it will be converted to a dict using cgi.parse_qs.
If you omit 'params', the params from the original request will
remain in effect, including any POST parameters.
"""
def __init__(self, path, params=None):
import cherrypy
import cgi
request = cherrypy.request
# Note that urljoin will "do the right thing" whether url is:
# 1. a URL relative to root (e.g. "/dummy")
# 2. a URL relative to the current path
# Note that any querystring will be discarded.
path = urlparse.urljoin(cherrypy.request.path, path)
# Set a 'path' member attribute so that code which traps this
# error can have access to it.
self.path = path
if params is not None:
if isinstance(params, basestring):
request.query_string = params
request.queryString = request.query_string # Backward compatibility
pm = cgi.parse_qs(params, keep_blank_values=True)
for key, val in pm.items():
if len(val) == 1:
pm[key] = val[0]
request.params = pm
else:
request.query_string = urllib.urlencode(params)
request.queryString = request.query_string
request.params = params.copy()
Exception.__init__(self, path, params)
class HTTPRedirect(Exception):
"""Exception raised when the request should be redirected.
The new URL must be passed as the first argument to the Exception, e.g.,
cperror.HTTPRedirect(newUrl). Multiple URLs are allowed. If a URL
is absolute, it will be used as-is. If it is relative, it is assumed
to be relative to the current cherrypy.request.path.
"""
def __init__(self, urls, status=None):
import cherrypy
if isinstance(urls, basestring):
urls = [urls]
abs_urls = []
for url in urls:
# Note that urljoin will "do the right thing" whether url is:
# 1. a complete URL with host (e.g. "http://www.dummy.biz/test")
# 2. a URL relative to root (e.g. "/dummy")
# 3. a URL relative to the current path
# Note that any querystring in browser_url will be discarded.
url = urlparse.urljoin(cherrypy.request.browser_url, url)
abs_urls.append(url)
self.urls = abs_urls
# RFC 2616 indicates a 301 response code fits our goal; however,
# browser support for 301 is quite messy. Do 302 instead. See
# http://ppewww.ph.gla.ac.uk/~flavell/www/post-redirect.html
if status is None:
if cherrypy.response.version >= "1.1":
status = 303
else:
status = 302
else:
status = int(status)
if status < 300 or status > 399:
raise ValueError("status must be between 300 and 399.")
self.status = status
Exception.__init__(self, abs_urls, status)
def set_response(self):
import cherrypy
response = cherrypy.response
response.status = status = self.status
if status in (300, 301, 302, 303, 307):
response.headers['Content-Type'] = "text/html"
# "The ... URI SHOULD be given by the Location field
# in the response."
response.headers['Location'] = self.urls[0]
# "Unless the request method was HEAD, the entity of the response
# SHOULD contain a short hypertext note with a hyperlink to the
# new URI(s)."
msg = {300: "This resource can be found at <a href='%s'>%s</a>.",
301: "This resource has permanently moved to <a href='%s'>%s</a>.",
302: "This resource resides temporarily at <a href='%s'>%s</a>.",
303: "This resource can be found at <a href='%s'>%s</a>.",
307: "This resource has moved temporarily to <a href='%s'>%s</a>.",
}[status]
response.body = "<br />\n".join([msg % (u, u) for u in self.urls])
elif status == 304:
# Not Modified.
# "The response MUST include the following header fields:
# Date, unless its omission is required by section 14.18.1"
# The "Date" header should have been set in Request.__init__
# "...the response SHOULD NOT include other entity-headers.
for key in ('Allow', 'Content-Encoding', 'Content-Language',
'Content-Length', 'Content-Location', 'Content-MD5',
'Content-Range', 'Content-Type', 'Expires',
'Last-Modified'):
if key in response.headers:
del response.headers[key]
# "The 304 response MUST NOT contain a message-body."
response.body = None
elif status == 305:
# Use Proxy.
# self.urls[0] should be the URI of the proxy.
response.headers['Location'] = self.urls[0]
response.body = None
else:
raise ValueError("The %s status code is unknown." % status)
class HTTPError(Error):
""" Exception used to return an HTTP error code to the client.
This exception will automatically set the response status and body.
A custom message (a long description to display in the browser)
can be provided in place of the default.
"""
def __init__(self, status=500, message=None):
self.status = status = int(status)
if status < 400 or status > 599:
raise ValueError("status must be between 400 and 599.")
self.message = message
Error.__init__(self, status, message)
def set_response(self):
import cherrypy
handler = cherrypy._cputil.get_special_attribute("_cp_on_http_error", "_cpOnHTTPError")
handler(self.status, self.message)
class NotFound(HTTPError):
""" Happens when a URL couldn't be mapped to any class.method """
def __init__(self, path=None):
if path is None:
import cherrypy
path = cherrypy.request.path
self.args = (path,)
HTTPError.__init__(self, 404, "The path %s was not found." % repr(path))
class InternalError(HTTPError):
""" Error that should never happen """
def __init__(self, message=None):
HTTPError.__init__(self, 500, message)
|