NovaBryan/EVE_Dump
Log | Files | 📦 下载最新源码 (.zip) | Refs | README

_cperror.py (8696B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\carbon\common\lib\cherrypy\_cperror.py
      2 from cgi import escape as _escape
      3 from sys import exc_info as _exc_info
      4 from traceback import format_exception as _format_exception
      5 from cherrypy._cpcompat import basestring, iteritems, urljoin as _urljoin
      6 from cherrypy.lib import httputil as _httputil
      7 
      8 class CherryPyException(Exception):
      9     pass
     10 
     11 
     12 class TimeoutError(CherryPyException):
     13     pass
     14 
     15 
     16 class InternalRedirect(CherryPyException):
     17 
     18     def __init__(self, path, query_string = ''):
     19         import cherrypy
     20         self.request = cherrypy.serving.request
     21         self.query_string = query_string
     22         if '?' in path:
     23             path, self.query_string = path.split('?', 1)
     24         path = _urljoin(self.request.path_info, path)
     25         self.path = path
     26         CherryPyException.__init__(self, path, self.query_string)
     27 
     28 
     29 class HTTPRedirect(CherryPyException):
     30     status = None
     31     urls = None
     32     encoding = 'utf-8'
     33 
     34     def __init__(self, urls, status = None, encoding = None):
     35         import cherrypy
     36         request = cherrypy.serving.request
     37         if isinstance(urls, basestring):
     38             urls = [urls]
     39         abs_urls = []
     40         for url in urls:
     41             if isinstance(url, unicode):
     42                 url = url.encode(encoding or self.encoding)
     43             url = _urljoin(cherrypy.url(), url)
     44             abs_urls.append(url)
     45 
     46         self.urls = abs_urls
     47         if status is None:
     48             if request.protocol >= (1, 1):
     49                 status = 303
     50             else:
     51                 status = 302
     52         else:
     53             status = int(status)
     54             if status < 300 or status > 399:
     55                 raise ValueError('status must be between 300 and 399.')
     56         self.status = status
     57         CherryPyException.__init__(self, abs_urls, status)
     58 
     59     def set_response(self):
     60         import cherrypy
     61         response = cherrypy.serving.response
     62         response.status = status = self.status
     63         if status in (300, 301, 302, 303, 307):
     64             response.headers['Content-Type'] = 'text/html;charset=utf-8'
     65             response.headers['Location'] = self.urls[0]
     66             msg = {300: "This resource can be found at <a href='%s'>%s</a>.",
     67              301: "This resource has permanently moved to <a href='%s'>%s</a>.",
     68              302: "This resource resides temporarily at <a href='%s'>%s</a>.",
     69              303: "This resource can be found at <a href='%s'>%s</a>.",
     70              307: "This resource has moved temporarily to <a href='%s'>%s</a>."}[status]
     71             msgs = [ msg % (u, u) for u in self.urls ]
     72             response.body = '<br />\n'.join(msgs)
     73             response.headers.pop('Content-Length', None)
     74         elif status == 304:
     75             for key in ('Allow', 'Content-Encoding', 'Content-Language', 'Content-Length', 'Content-Location', 'Content-MD5', 'Content-Range', 'Content-Type', 'Expires', 'Last-Modified'):
     76                 if key in response.headers:
     77                     del response.headers[key]
     78 
     79             response.body = None
     80             response.headers.pop('Content-Length', None)
     81         elif status == 305:
     82             response.headers['Location'] = self.urls[0]
     83             response.body = None
     84             response.headers.pop('Content-Length', None)
     85         else:
     86             raise ValueError('The %s status code is unknown.' % status)
     87 
     88     def __call__(self):
     89         raise self
     90 
     91 
     92 def clean_headers(status):
     93     import cherrypy
     94     response = cherrypy.serving.response
     95     respheaders = response.headers
     96     for key in ['Accept-Ranges',
     97      'Age',
     98      'ETag',
     99      'Location',
    100      'Retry-After',
    101      'Vary',
    102      'Content-Encoding',
    103      'Content-Length',
    104      'Expires',
    105      'Content-Location',
    106      'Content-MD5',
    107      'Last-Modified']:
    108         if key in respheaders:
    109             del respheaders[key]
    110 
    111     if status != 416:
    112         if 'Content-Range' in respheaders:
    113             del respheaders['Content-Range']
    114 
    115 
    116 class HTTPError(CherryPyException):
    117     status = None
    118     code = None
    119     reason = None
    120 
    121     def __init__(self, status = 500, message = None):
    122         self.status = status
    123         try:
    124             self.code, self.reason, defaultmsg = _httputil.valid_status(status)
    125         except ValueError as x:
    126             raise self.__class__(500, x.args[0])
    127 
    128         if self.code < 400 or self.code > 599:
    129             raise ValueError('status must be between 400 and 599.')
    130         self._message = message or defaultmsg
    131         CherryPyException.__init__(self, status, message)
    132 
    133     def set_response(self):
    134         import cherrypy
    135         response = cherrypy.serving.response
    136         clean_headers(self.code)
    137         response.status = self.status
    138         tb = None
    139         if cherrypy.serving.request.show_tracebacks:
    140             tb = format_exc()
    141         response.headers['Content-Type'] = 'text/html;charset=utf-8'
    142         response.headers.pop('Content-Length', None)
    143         content = self.get_error_page(self.status, traceback=tb, message=self._message)
    144         response.body = content
    145         _be_ie_unfriendly(self.code)
    146 
    147     def get_error_page(self, *args, **kwargs):
    148         return get_error_page(*args, **kwargs)
    149 
    150     def __call__(self):
    151         raise self
    152 
    153 
    154 class NotFound(HTTPError):
    155 
    156     def __init__(self, path = None):
    157         if path is None:
    158             import cherrypy
    159             request = cherrypy.serving.request
    160             path = request.script_name + request.path_info
    161         self.args = (path,)
    162         HTTPError.__init__(self, 404, "The path '%s' was not found." % path)
    163 
    164 
    165 _HTTPErrorTemplate = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"\n"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\n<html>\n<head>\n    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>\n    <title>%(status)s</title>\n    <style type="text/css">\n    #powered_by {\n        margin-top: 20px;\n        border-top: 2px solid black;\n        font-style: italic;\n    }\n\n    #traceback {\n        color: red;\n    }\n    </style>\n</head>\n    <body>\n        <h2>%(status)s</h2>\n        <p>%(message)s</p>\n        <pre id="traceback">%(traceback)s</pre>\n    <div id="powered_by">\n    <span>Powered by <a href="http://www.cherrypy.org">CherryPy %(version)s</a></span>\n    </div>\n    </body>\n</html>\n'
    166 
    167 def get_error_page(status, **kwargs):
    168     import cherrypy
    169     try:
    170         code, reason, message = _httputil.valid_status(status)
    171     except ValueError as x:
    172         raise cherrypy.HTTPError(500, x.args[0])
    173 
    174     if kwargs.get('status') is None:
    175         kwargs['status'] = '%s %s' % (code, reason)
    176     if kwargs.get('message') is None:
    177         kwargs['message'] = message
    178     if kwargs.get('traceback') is None:
    179         kwargs['traceback'] = ''
    180     if kwargs.get('version') is None:
    181         kwargs['version'] = cherrypy.__version__
    182     for k, v in iteritems(kwargs):
    183         if v is None:
    184             kwargs[k] = ''
    185         else:
    186             kwargs[k] = _escape(kwargs[k])
    187 
    188     pages = cherrypy.serving.request.error_page
    189     error_page = pages.get(code) or pages.get('default')
    190     if error_page:
    191         try:
    192             if hasattr(error_page, '__call__'):
    193                 return error_page(**kwargs)
    194             return open(error_page, 'rb').read() % kwargs
    195         except:
    196             e = _format_exception(*_exc_info())[-1]
    197             m = kwargs['message']
    198             if m:
    199                 m += '<br />'
    200             m += 'In addition, the custom error page failed:\n<br />%s' % e
    201             kwargs['message'] = m
    202 
    203     return _HTTPErrorTemplate % kwargs
    204 
    205 
    206 _ie_friendly_error_sizes = {400: 512,
    207  403: 256,
    208  404: 512,
    209  405: 256,
    210  406: 512,
    211  408: 512,
    212  409: 512,
    213  410: 256,
    214  500: 512,
    215  501: 512,
    216  505: 512}
    217 
    218 def _be_ie_unfriendly(status):
    219     import cherrypy
    220     response = cherrypy.serving.response
    221     s = _ie_friendly_error_sizes.get(status, 0)
    222     if s:
    223         s += 1
    224         content = response.collapse_body()
    225         l = len(content)
    226         if l and l < s:
    227             content = content + ' ' * (s - l)
    228         response.body = content
    229         response.headers['Content-Length'] = str(len(content))
    230 
    231 
    232 def format_exc(exc = None):
    233     if exc is None:
    234         exc = _exc_info()
    235     if exc == (None, None, None):
    236         return ''
    237     import traceback
    238     return ''.join(traceback.format_exception(*exc))
    239 
    240 
    241 def bare_error(extrabody = None):
    242     body = 'Unrecoverable error in the server.'
    243     if extrabody is not None:
    244         if not isinstance(extrabody, str):
    245             extrabody = extrabody.encode('utf-8')
    246         body += '\n' + extrabody
    247     return ('500 Internal Server Error', [('Content-Type', 'text/plain'), ('Content-Length', str(len(body)))], [body])