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

_cprequest.py (15107B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\carbon\common\lib\cherrypy\_cprequest.py
      2 import os
      3 import sys
      4 import time
      5 import warnings
      6 import cherrypy
      7 from cherrypy._cpcompat import basestring, copykeys, ntob, unicodestr
      8 from cherrypy._cpcompat import SimpleCookie, CookieError
      9 from cherrypy import _cpreqbody, _cpconfig
     10 from cherrypy._cperror import format_exc, bare_error
     11 from cherrypy.lib import httputil, file_generator
     12 
     13 class Hook(object):
     14     callback = None
     15     failsafe = False
     16     priority = 50
     17     kwargs = {}
     18 
     19     def __init__(self, callback, failsafe = None, priority = None, **kwargs):
     20         self.callback = callback
     21         if failsafe is None:
     22             failsafe = getattr(callback, 'failsafe', False)
     23         self.failsafe = failsafe
     24         if priority is None:
     25             priority = getattr(callback, 'priority', 50)
     26         self.priority = priority
     27         self.kwargs = kwargs
     28 
     29     def __cmp__(self, other):
     30         return cmp(self.priority, other.priority)
     31 
     32     def __call__(self):
     33         return self.callback(**self.kwargs)
     34 
     35     def __repr__(self):
     36         cls = self.__class__
     37         return '%s.%s(callback=%r, failsafe=%r, priority=%r, %s)' % (cls.__module__,
     38          cls.__name__,
     39          self.callback,
     40          self.failsafe,
     41          self.priority,
     42          ', '.join([ '%s=%r' % (k, v) for k, v in self.kwargs.items() ]))
     43 
     44 
     45 class HookMap(dict):
     46 
     47     def __new__(cls, points = None):
     48         d = dict.__new__(cls)
     49         for p in points or []:
     50             d[p] = []
     51 
     52         return d
     53 
     54     def __init__(self, *a, **kw):
     55         pass
     56 
     57     def attach(self, point, callback, failsafe = None, priority = None, **kwargs):
     58         self[point].append(Hook(callback, failsafe, priority, **kwargs))
     59 
     60     def run(self, point):
     61         exc = None
     62         hooks = self[point]
     63         hooks.sort()
     64         for hook in hooks:
     65             if exc is None or hook.failsafe:
     66                 try:
     67                     hook()
     68                 except (KeyboardInterrupt, SystemExit):
     69                     raise
     70                 except (cherrypy.HTTPError, cherrypy.HTTPRedirect, cherrypy.InternalRedirect):
     71                     exc = sys.exc_info()[1]
     72                 except:
     73                     exc = sys.exc_info()[1]
     74                     cherrypy.log(traceback=True, severity=40)
     75 
     76         if exc:
     77             raise
     78 
     79     def __copy__(self):
     80         newmap = self.__class__()
     81         for k, v in self.items():
     82             newmap[k] = v[:]
     83 
     84         return newmap
     85 
     86     copy = __copy__
     87 
     88     def __repr__(self):
     89         cls = self.__class__
     90         return '%s.%s(points=%r)' % (cls.__module__, cls.__name__, copykeys(self))
     91 
     92 
     93 def hooks_namespace(k, v):
     94     hookpoint = k.split('.', 1)[0]
     95     if isinstance(v, basestring):
     96         v = cherrypy.lib.attributes(v)
     97     if not isinstance(v, Hook):
     98         v = Hook(v)
     99     cherrypy.serving.request.hooks[hookpoint].append(v)
    100 
    101 
    102 def request_namespace(k, v):
    103     if k[:5] == 'body.':
    104         setattr(cherrypy.serving.request.body, k[5:], v)
    105     else:
    106         setattr(cherrypy.serving.request, k, v)
    107 
    108 
    109 def response_namespace(k, v):
    110     if k[:8] == 'headers.':
    111         cherrypy.serving.response.headers[k.split('.', 1)[1]] = v
    112     else:
    113         setattr(cherrypy.serving.response, k, v)
    114 
    115 
    116 def error_page_namespace(k, v):
    117     if k != 'default':
    118         k = int(k)
    119     cherrypy.serving.request.error_page[k] = v
    120 
    121 
    122 hookpoints = ['on_start_resource',
    123  'before_request_body',
    124  'before_handler',
    125  'before_finalize',
    126  'on_end_resource',
    127  'on_end_request',
    128  'before_error_response',
    129  'after_error_response']
    130 
    131 class Request(object):
    132     prev = None
    133     local = httputil.Host('127.0.0.1', 80)
    134     remote = httputil.Host('127.0.0.1', 1111)
    135     scheme = 'http'
    136     server_protocol = 'HTTP/1.1'
    137     base = ''
    138     request_line = ''
    139     method = 'GET'
    140     query_string = ''
    141     query_string_encoding = 'utf8'
    142     protocol = (1, 1)
    143     params = {}
    144     header_list = []
    145     headers = httputil.HeaderMap()
    146     cookie = SimpleCookie()
    147     rfile = None
    148     process_request_body = True
    149     methods_with_bodies = ('POST', 'PUT')
    150     body = None
    151     dispatch = cherrypy.dispatch.Dispatcher()
    152     script_name = ''
    153     path_info = '/'
    154     login = None
    155     app = None
    156     handler = None
    157     toolmaps = {}
    158     config = None
    159     is_index = None
    160     hooks = HookMap(hookpoints)
    161     error_response = cherrypy.HTTPError(500).set_response
    162     error_page = {}
    163     show_tracebacks = True
    164     show_mismatched_params = True
    165     throws = (KeyboardInterrupt, SystemExit, cherrypy.InternalRedirect)
    166     throw_errors = False
    167     closed = False
    168     stage = None
    169     namespaces = _cpconfig.NamespaceSet(**{'hooks': hooks_namespace,
    170      'request': request_namespace,
    171      'response': response_namespace,
    172      'error_page': error_page_namespace,
    173      'tools': cherrypy.tools})
    174 
    175     def __init__(self, local_host, remote_host, scheme = 'http', server_protocol = 'HTTP/1.1'):
    176         self.local = local_host
    177         self.remote = remote_host
    178         self.scheme = scheme
    179         self.server_protocol = server_protocol
    180         self.closed = False
    181         self.error_page = self.error_page.copy()
    182         self.namespaces = self.namespaces.copy()
    183         self.stage = None
    184 
    185     def close(self):
    186         if not self.closed:
    187             self.closed = True
    188             self.stage = 'on_end_request'
    189             self.hooks.run('on_end_request')
    190             self.stage = 'close'
    191 
    192     def run(self, method, path, query_string, req_protocol, headers, rfile):
    193         response = cherrypy.serving.response
    194         self.stage = 'run'
    195         try:
    196             self.error_response = cherrypy.HTTPError(500).set_response
    197             self.method = method
    198             path = path or '/'
    199             self.query_string = query_string or ''
    200             self.params = {}
    201             rp = (int(req_protocol[5]), int(req_protocol[7]))
    202             sp = (int(self.server_protocol[5]), int(self.server_protocol[7]))
    203             self.protocol = min(rp, sp)
    204             response.headers.protocol = self.protocol
    205             url = path
    206             if query_string:
    207                 url += '?' + query_string
    208             self.request_line = '%s %s %s' % (method, url, req_protocol)
    209             self.header_list = list(headers)
    210             self.headers = httputil.HeaderMap()
    211             self.rfile = rfile
    212             self.body = None
    213             self.cookie = SimpleCookie()
    214             self.handler = None
    215             self.script_name = self.app.script_name
    216             self.path_info = pi = path[len(self.script_name):]
    217             self.stage = 'respond'
    218             self.respond(pi)
    219         except self.throws:
    220             raise
    221         except:
    222             if self.throw_errors:
    223                 raise
    224             else:
    225                 cherrypy.log(traceback=True, severity=40)
    226                 if self.show_tracebacks:
    227                     body = format_exc()
    228                 else:
    229                     body = ''
    230                 r = bare_error(body)
    231                 response.output_status, response.header_list, response.body = r
    232 
    233         if self.method == 'HEAD':
    234             response.body = []
    235         try:
    236             cherrypy.log.access()
    237         except:
    238             cherrypy.log.error(traceback=True)
    239 
    240         if response.timed_out:
    241             raise cherrypy.TimeoutError()
    242         return response
    243 
    244     def respond(self, path_info):
    245         response = cherrypy.serving.response
    246         try:
    247             try:
    248                 if self.app is None:
    249                     raise cherrypy.NotFound()
    250                 self.stage = 'process_headers'
    251                 self.process_headers()
    252                 self.hooks = self.__class__.hooks.copy()
    253                 self.toolmaps = {}
    254                 self.stage = 'get_resource'
    255                 self.get_resource(path_info)
    256                 self.body = _cpreqbody.RequestBody(self.rfile, self.headers, request_params=self.params)
    257                 self.namespaces(self.config)
    258                 self.stage = 'on_start_resource'
    259                 self.hooks.run('on_start_resource')
    260                 self.stage = 'process_query_string'
    261                 self.process_query_string()
    262                 if self.process_request_body:
    263                     if self.method not in self.methods_with_bodies:
    264                         self.process_request_body = False
    265                 self.stage = 'before_request_body'
    266                 self.hooks.run('before_request_body')
    267                 if self.process_request_body:
    268                     self.body.process()
    269                 self.stage = 'before_handler'
    270                 self.hooks.run('before_handler')
    271                 if self.handler:
    272                     self.stage = 'handler'
    273                     response.body = self.handler()
    274                 self.stage = 'before_finalize'
    275                 self.hooks.run('before_finalize')
    276                 response.finalize()
    277             except (cherrypy.HTTPRedirect, cherrypy.HTTPError):
    278                 inst = sys.exc_info()[1]
    279                 inst.set_response()
    280                 self.stage = 'before_finalize (HTTPError)'
    281                 self.hooks.run('before_finalize')
    282                 response.finalize()
    283             finally:
    284                 self.stage = 'on_end_resource'
    285                 self.hooks.run('on_end_resource')
    286 
    287         except self.throws:
    288             raise
    289         except:
    290             if self.throw_errors:
    291                 raise
    292             self.handle_error()
    293 
    294     def process_query_string(self):
    295         try:
    296             p = httputil.parse_query_string(self.query_string, encoding=self.query_string_encoding)
    297         except UnicodeDecodeError:
    298             raise cherrypy.HTTPError(404, 'The given query string could not be processed. Query strings for this resource must be encoded with %r.' % self.query_string_encoding)
    299 
    300         for key, value in p.items():
    301             if isinstance(key, unicode):
    302                 del p[key]
    303                 p[key.encode(self.query_string_encoding)] = value
    304 
    305         self.params.update(p)
    306 
    307     def process_headers(self):
    308         headers = self.headers
    309         for name, value in self.header_list:
    310             name = name.title()
    311             value = value.strip()
    312             if '=?' in value:
    313                 dict.__setitem__(headers, name, httputil.decode_TEXT(value))
    314             else:
    315                 dict.__setitem__(headers, name, value)
    316             if name == 'Cookie':
    317                 try:
    318                     self.cookie.load(value)
    319                 except CookieError:
    320                     msg = 'Illegal cookie name %s' % value.split('=')[0]
    321                     raise cherrypy.HTTPError(400, msg)
    322 
    323         if not dict.__contains__(headers, 'Host'):
    324             if self.protocol >= (1, 1):
    325                 msg = "HTTP/1.1 requires a 'Host' request header."
    326                 raise cherrypy.HTTPError(400, msg)
    327         host = dict.get(headers, 'Host')
    328         if not host:
    329             host = self.local.name or self.local.ip
    330         self.base = '%s://%s' % (self.scheme, host)
    331 
    332     def get_resource(self, path):
    333         dispatch = self.app.find_config(path, 'request.dispatch', self.dispatch)
    334         dispatch(path)
    335 
    336     def handle_error(self):
    337         try:
    338             self.hooks.run('before_error_response')
    339             if self.error_response:
    340                 self.error_response()
    341             self.hooks.run('after_error_response')
    342             cherrypy.serving.response.finalize()
    343         except cherrypy.HTTPRedirect:
    344             inst = sys.exc_info()[1]
    345             inst.set_response()
    346             cherrypy.serving.response.finalize()
    347 
    348     def _get_body_params(self):
    349         warnings.warn('body_params is deprecated in CherryPy 3.2, will be removed in CherryPy 3.3.', DeprecationWarning)
    350         return self.body.params
    351 
    352     body_params = property(_get_body_params, doc='\n    If the request Content-Type is \'application/x-www-form-urlencoded\' or\n    multipart, this will be a dict of the params pulled from the entity\n    body; that is, it will be the portion of request.params that come\n    from the message body (sometimes called "POST params", although they\n    can be sent with various HTTP method verbs). This value is set between\n    the \'before_request_body\' and \'before_handler\' hooks (assuming that\n    process_request_body is True).\n    \n    Deprecated in 3.2, will be removed for 3.3 in favor of\n    :attr:`request.body.params<cherrypy._cprequest.RequestBody.params>`.')
    353 
    354 
    355 class ResponseBody(object):
    356 
    357     def __get__(self, obj, objclass = None):
    358         if obj is None:
    359             return self
    360         else:
    361             return obj._body
    362 
    363     def __set__(self, obj, value):
    364         if isinstance(value, basestring):
    365             if value:
    366                 value = [value]
    367             else:
    368                 value = []
    369         elif hasattr(value, 'read'):
    370             value = file_generator(value)
    371         elif value is None:
    372             value = []
    373         obj._body = value
    374 
    375 
    376 class Response(object):
    377     status = ''
    378     header_list = []
    379     headers = httputil.HeaderMap()
    380     cookie = SimpleCookie()
    381     body = ResponseBody()
    382     time = None
    383     timeout = 300
    384     timed_out = False
    385     stream = False
    386 
    387     def __init__(self):
    388         self.status = None
    389         self.header_list = None
    390         self._body = []
    391         self.time = time.time()
    392         self.headers = httputil.HeaderMap()
    393         dict.update(self.headers, {'Content-Type': 'text/html',
    394          'Server': 'CherryPy/' + cherrypy.__version__,
    395          'Date': httputil.HTTPDate(self.time)})
    396         self.cookie = SimpleCookie()
    397 
    398     def collapse_body(self):
    399         if isinstance(self.body, basestring):
    400             return self.body
    401         newbody = ''.join([ chunk for chunk in self.body ])
    402         self.body = newbody
    403         return newbody
    404 
    405     def finalize(self):
    406         try:
    407             code, reason, _ = httputil.valid_status(self.status)
    408         except ValueError:
    409             raise cherrypy.HTTPError(500, sys.exc_info()[1].args[0])
    410 
    411         headers = self.headers
    412         self.output_status = ntob(str(code), 'ascii') + ntob(' ') + headers.encode(reason)
    413         if self.stream:
    414             if dict.get(headers, 'Content-Length') is None:
    415                 dict.pop(headers, 'Content-Length', None)
    416         elif code < 200 or code in (204, 205, 304):
    417             dict.pop(headers, 'Content-Length', None)
    418             self.body = ntob('')
    419         elif dict.get(headers, 'Content-Length') is None:
    420             content = self.collapse_body()
    421             dict.__setitem__(headers, 'Content-Length', len(content))
    422         self.header_list = h = headers.output()
    423         cookie = self.cookie.output()
    424         if cookie:
    425             for line in cookie.split('\n'):
    426                 if line.endswith('\r'):
    427                     line = line[:-1]
    428                 name, value = line.split(': ', 1)
    429                 if isinstance(name, unicodestr):
    430                     name = name.encode('ISO-8859-1')
    431                 if isinstance(value, unicodestr):
    432                     value = headers.encode(value)
    433                 h.append((name, value))
    434 
    435     def check_timeout(self):
    436         if time.time() > self.time + self.timeout:
    437             self.timed_out = True