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

_cpwsgi.py (8124B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\carbon\common\lib\cherrypy\_cpwsgi.py
      2 import sys as _sys
      3 import cherrypy as _cherrypy
      4 from cherrypy._cpcompat import BytesIO
      5 from cherrypy import _cperror
      6 from cherrypy.lib import httputil
      7 
      8 def downgrade_wsgi_ux_to_1x(environ):
      9     env1x = {}
     10     url_encoding = environ[u'wsgi.url_encoding']
     11     for k, v in environ.items():
     12         if k in (u'PATH_INFO', u'SCRIPT_NAME', u'QUERY_STRING'):
     13             v = v.encode(url_encoding)
     14         elif isinstance(v, unicode):
     15             v = v.encode('ISO-8859-1')
     16         env1x[k.encode('ISO-8859-1')] = v
     17 
     18     return env1x
     19 
     20 
     21 class VirtualHost(object):
     22     default = None
     23     use_x_forwarded_host = True
     24     domains = {}
     25 
     26     def __init__(self, default, domains = None, use_x_forwarded_host = True):
     27         self.default = default
     28         self.domains = domains or {}
     29         self.use_x_forwarded_host = use_x_forwarded_host
     30 
     31     def __call__(self, environ, start_response):
     32         domain = environ.get('HTTP_HOST', '')
     33         if self.use_x_forwarded_host:
     34             domain = environ.get('HTTP_X_FORWARDED_HOST', domain)
     35         nextapp = self.domains.get(domain)
     36         if nextapp is None:
     37             nextapp = self.default
     38         return nextapp(environ, start_response)
     39 
     40 
     41 class InternalRedirector(object):
     42 
     43     def __init__(self, nextapp, recursive = False):
     44         self.nextapp = nextapp
     45         self.recursive = recursive
     46 
     47     def __call__(self, environ, start_response):
     48         redirections = []
     49         while True:
     50             environ = environ.copy()
     51             try:
     52                 return self.nextapp(environ, start_response)
     53             except _cherrypy.InternalRedirect as ir:
     54                 sn = environ.get('SCRIPT_NAME', '')
     55                 path = environ.get('PATH_INFO', '')
     56                 qs = environ.get('QUERY_STRING', '')
     57                 old_uri = sn + path
     58                 if qs:
     59                     old_uri += '?' + qs
     60                 redirections.append(old_uri)
     61                 if not self.recursive:
     62                     new_uri = sn + ir.path
     63                     if ir.query_string:
     64                         new_uri += '?' + ir.query_string
     65                     if new_uri in redirections:
     66                         ir.request.close()
     67                         raise RuntimeError('InternalRedirector visited the same URL twice: %r' % new_uri)
     68                 environ['REQUEST_METHOD'] = 'GET'
     69                 environ['PATH_INFO'] = ir.path
     70                 environ['QUERY_STRING'] = ir.query_string
     71                 environ['wsgi.input'] = BytesIO()
     72                 environ['CONTENT_LENGTH'] = '0'
     73                 environ['cherrypy.previous_request'] = ir.request
     74 
     75 
     76 class ExceptionTrapper(object):
     77 
     78     def __init__(self, nextapp, throws = (KeyboardInterrupt, SystemExit)):
     79         self.nextapp = nextapp
     80         self.throws = throws
     81 
     82     def __call__(self, environ, start_response):
     83         return _TrappedResponse(self.nextapp, environ, start_response, self.throws)
     84 
     85 
     86 class _TrappedResponse(object):
     87     response = iter([])
     88 
     89     def __init__(self, nextapp, environ, start_response, throws):
     90         self.nextapp = nextapp
     91         self.environ = environ
     92         self.start_response = start_response
     93         self.throws = throws
     94         self.started_response = False
     95         self.response = self.trap(self.nextapp, self.environ, self.start_response)
     96         self.iter_response = iter(self.response)
     97 
     98     def __iter__(self):
     99         self.started_response = True
    100         return self
    101 
    102     def next(self):
    103         return self.trap(self.iter_response.next)
    104 
    105     def close(self):
    106         if hasattr(self.response, 'close'):
    107             self.response.close()
    108 
    109     def trap(self, func, *args, **kwargs):
    110         try:
    111             return func(*args, **kwargs)
    112         except self.throws:
    113             raise
    114         except StopIteration:
    115             raise
    116         except:
    117             tb = _cperror.format_exc()
    118             _cherrypy.log(tb, severity=40)
    119             if not _cherrypy.request.show_tracebacks:
    120                 tb = ''
    121             s, h, b = _cperror.bare_error(tb)
    122             if self.started_response:
    123                 self.iter_response = iter([])
    124             else:
    125                 self.iter_response = iter(b)
    126             try:
    127                 self.start_response(s, h, _sys.exc_info())
    128             except:
    129                 _cherrypy.log(traceback=True, severity=40)
    130                 raise
    131 
    132             if self.started_response:
    133                 return ''.join(b)
    134             else:
    135                 return b
    136 
    137 
    138 class AppResponse(object):
    139 
    140     def __init__(self, environ, start_response, cpapp):
    141         if environ.get(u'wsgi.version') == (u'u', 0):
    142             environ = downgrade_wsgi_ux_to_1x(environ)
    143         self.environ = environ
    144         self.cpapp = cpapp
    145         try:
    146             self.run()
    147         except:
    148             self.close()
    149             raise
    150 
    151         r = _cherrypy.serving.response
    152         self.iter_response = iter(r.body)
    153         self.write = start_response(r.output_status, r.header_list)
    154 
    155     def __iter__(self):
    156         return self
    157 
    158     def next(self):
    159         return self.iter_response.next()
    160 
    161     def close(self):
    162         self.cpapp.release_serving()
    163 
    164     def run(self):
    165         env = self.environ.get
    166         local = httputil.Host('', int(env('SERVER_PORT', 80)), env('SERVER_NAME', ''))
    167         remote = httputil.Host(env('REMOTE_ADDR', ''), int(env('REMOTE_PORT', -1) or -1), env('REMOTE_HOST', ''))
    168         scheme = env('wsgi.url_scheme')
    169         sproto = env('ACTUAL_SERVER_PROTOCOL', 'HTTP/1.1')
    170         request, resp = self.cpapp.get_serving(local, remote, scheme, sproto)
    171         request.login = env('LOGON_USER') or env('REMOTE_USER') or None
    172         request.multithread = self.environ['wsgi.multithread']
    173         request.multiprocess = self.environ['wsgi.multiprocess']
    174         request.wsgi_environ = self.environ
    175         request.prev = env('cherrypy.previous_request', None)
    176         meth = self.environ['REQUEST_METHOD']
    177         path = httputil.urljoin(self.environ.get('SCRIPT_NAME', ''), self.environ.get('PATH_INFO', ''))
    178         qs = self.environ.get('QUERY_STRING', '')
    179         rproto = self.environ.get('SERVER_PROTOCOL')
    180         headers = self.translate_headers(self.environ)
    181         rfile = self.environ['wsgi.input']
    182         request.run(meth, path, qs, rproto, headers, rfile)
    183 
    184     headerNames = {'HTTP_CGI_AUTHORIZATION': 'Authorization',
    185      'CONTENT_LENGTH': 'Content-Length',
    186      'CONTENT_TYPE': 'Content-Type',
    187      'REMOTE_HOST': 'Remote-Host',
    188      'REMOTE_ADDR': 'Remote-Addr'}
    189 
    190     def translate_headers(self, environ):
    191         for cgiName in environ:
    192             if cgiName in self.headerNames:
    193                 yield (self.headerNames[cgiName], environ[cgiName])
    194             elif cgiName[:5] == 'HTTP_':
    195                 translatedHeader = cgiName[5:].replace('_', '-')
    196                 yield (translatedHeader, environ[cgiName])
    197 
    198 
    199 class CPWSGIApp(object):
    200     pipeline = [('ExceptionTrapper', ExceptionTrapper), ('InternalRedirector', InternalRedirector)]
    201     head = None
    202     config = {}
    203     response_class = AppResponse
    204 
    205     def __init__(self, cpapp, pipeline = None):
    206         self.cpapp = cpapp
    207         self.pipeline = self.pipeline[:]
    208         if pipeline:
    209             self.pipeline.extend(pipeline)
    210         self.config = self.config.copy()
    211 
    212     def tail(self, environ, start_response):
    213         return self.response_class(environ, start_response, self.cpapp)
    214 
    215     def __call__(self, environ, start_response):
    216         head = self.head
    217         if head is None:
    218             head = self.tail
    219             for name, callable in self.pipeline[::-1]:
    220                 conf = self.config.get(name, {})
    221                 head = callable(head, **conf)
    222 
    223             self.head = head
    224         return head(environ, start_response)
    225 
    226     def namespace_handler(self, k, v):
    227         if k == 'pipeline':
    228             self.pipeline.extend(v)
    229         elif k == 'response_class':
    230             self.response_class = v
    231         else:
    232             name, arg = k.split('.', 1)
    233             bucket = self.config.setdefault(name, {})
    234             bucket[arg] = v