Contact: fumanchu@aminus.org

Log in as guest/misc to create tickets

Changeset 39

Show
Ignore:
Timestamp:
02/09/06 03:37:48
Author:
fumanchu
Message:

Removed dependency on wsgiref. Also fixed a multiple-header bug with headers_out.add().

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • modpython_gateway.py

    r37 r39  
    77<Location /mcontrol> 
    88    SetHandler python-program 
    9     PythonHandler wsgiref.modpy_wrapper::handler 
    10     PythonOption application cherrypy.wsgiapp::wsgiApp 
     9    PythonHandler modpython_gateway::handler 
     10    PythonOption application cherrypy._cpwsgi::wsgiApp 
    1111    PythonOption import mcontrol.cherry::startup 
    1212</Location> 
     
    1515always be equal to "the root URL of the app"; Apache probably won't act as 
    1616you expect in that case. You can add another PythonOption directive to tell 
    17 the modpython_gateway to force that behavior: 
     17modpython_gateway to force that behavior: 
    1818 
    1919    PythonOption SCRIPT_NAME /mcontrol 
     
    2121""" 
    2222 
    23 import sys 
     23import traceback 
     24 
    2425from mod_python import apache 
    25 from wsgiref.handlers import BaseCGIHandler 
    2626 
    2727 
     
    7070             "when running a version of mod_python < 3.1") 
    7171 
    72 class Handler(BaseCGIHandler): 
     72 
     73class Handler: 
    7374     
    7475    def __init__(self, req): 
     76        self.started = False 
     77         
    7578        options = req.get_options() 
    7679         
     
    7881        try: 
    7982            q = apache.mpm_query 
     83            threaded = q(apache.AP_MPMQ_IS_THREADED) 
     84            forked = q(apache.AP_MPMQ_IS_FORKED) 
    8085        except AttributeError: 
    8186            threaded = options.get('multithread', '').lower() 
     
    9499            else: 
    95100                raise ValueError(bad_value % "multiprocess") 
    96         else: 
    97             threaded = q(apache.AP_MPMQ_IS_THREADED) 
    98             forked = q(apache.AP_MPMQ_IS_FORKED) 
    99          
    100         env = dict(apache.build_cgi_env(req)) 
     101         
     102        env = self.environ = dict(apache.build_cgi_env(req)) 
    101103         
    102104        if 'SCRIPT_NAME' in options: 
     105            # Override SCRIPT_NAME and PATH_INFO if requested. 
    103106            env['SCRIPT_NAME'] = options['SCRIPT_NAME'] 
    104107            env['PATH_INFO'] = req.uri[len(options['SCRIPT_NAME']):] 
    105108         
    106         BaseCGIHandler.__init__(self, 
    107                                 stdin=InputWrapper(req), 
    108                                 stdout=None, 
    109                                 stderr=ErrorWrapper(req), 
    110                                 environ=env, 
    111                                 multiprocess=forked, 
    112                                 multithread=threaded 
    113                                 ) 
     109        env['wsgi.input'] = InputWrapper(req) 
     110        env['wsgi.errors'] = ErrorWrapper(req) 
     111        env['wsgi.version'] = (1,0) 
     112        env['wsgi.run_once'] = False 
     113        if env.get("HTTPS") in ('yes', 'on', '1'): 
     114            env['wsgi.url_scheme'] = 'https' 
     115        else: 
     116            env['wsgi.url_scheme'] = 'http' 
     117        env['wsgi.multithread']  = threaded 
     118        env['wsgi.multiprocess'] = forked 
     119         
    114120        self.request = req 
    115         self._write = req.write 
    116      
    117     def _flush(self): 
    118         pass 
    119      
    120     def send_headers(self): 
    121         self.cleanup_headers() 
    122         self.headers_sent = True 
    123         # Can't just return 200 or the page will hang until timeout 
    124         self.request.status = int(self.status[:3]) 
    125         # the headers.Headers class doesn't have an iteritems method... 
    126         for key, val in self.headers.items(): 
     121     
     122    def run(self, application): 
     123        try: 
     124            result = application(self.environ, self.start_response) 
     125            for data in result: 
     126                self.write(data) 
     127            if not self.started: 
     128                self.request.set_content_length(0) 
     129            if hasattr(result, 'close'): 
     130                result.close() 
     131        except: 
     132            traceback.print_exc(None, self.environ['wsgi.errors']) 
     133            if not self.started: 
     134                self.request.status = 500 
     135                self.request.content_type = 'text/plain' 
     136                data = "A server error occurred. Please contact the administrator." 
     137                self.request.set_content_length(len(data)) 
     138                self.request.write(data) 
     139     
     140    def start_response(self, status, headers, exc_info=None): 
     141        if exc_info: 
     142            try: 
     143                if self.started: 
     144                    raise exc_info[0], exc_info[1], exc_info[2] 
     145            finally: 
     146                exc_info = None 
     147         
     148        self.request.status = int(status[:3]) 
     149         
     150        for key, val in headers: 
    127151            if key.lower() == 'content-length': 
    128                 if val is not None: 
    129                     self.request.set_content_length(int(val)) 
     152                self.request.set_content_length(int(val)) 
    130153            elif key.lower() == 'content-type': 
    131154                self.request.content_type = val 
    132155            else: 
    133                 self.request.headers_out[key] = val 
     156                self.request.headers_out.add(key, val) 
     157         
     158        return self.write 
     159     
     160    def write(self, data): 
     161        if not self.started: 
     162            self.started = True 
     163        self.request.write(data) 
    134164 
    135165 
     
    137167 
    138168def profile(req): 
    139     # Call this function instead of handler 
     169    # Call this function instead of "handler" 
    140170    # to get profiling data for each call. 
    141171    import hotshot, os.path 
    142     ppath = os.path.dirname(__file__) 
    143     if not os.path.exists(ppath): 
    144         os.makedirs(ppath) 
    145172    global _counter 
    146173    _counter += 1 
    147     ppath = os.path.join(ppath, "cp_%s.prof" % _counter) 
     174    ppath = os.path.join(os.path.dirname(__file__), "cp_%s.prof" % _counter) 
    148175    prof = hotshot.Profile(ppath) 
    149     result = prof.runcall(handler, req) 
     176    prof.runcall(handler, req) 
    150177    prof.close() 
    151     return result 
     178    return apache.OK 
    152179 
    153180def handler(req): 
     181    # If you use a PythonImport directive as recommended, its interpreter_name 
     182    # value must EXACTLY match the value of req.interpreter (case-sensitive). 
     183    # You can un-comment the next line to get the value of req.interpreter. 
     184##  raise StandardError(repr(req.interpreter)) 
     185     
    154186    config = req.get_config() 
    155187    debug = int(config.get("PythonDebug", 0)) 
     
    177209    module = __import__(modname, globals(), locals(), ['']) 
    178210    app = getattr(module, objname) 
    179      
    180 ##    modname, objname = options['application'].split('::') 
    181 ##    module = apache.import_module(modname, autoreload=False, log=debug) 
    182 ##    app = apache.resolve_object(module, objname, arg=None, silent=False) 
    183      
    184     # You can un-comment the next line to get the value of req.interpreter. 
    185     # If you use a PythonImport directive as recommended, its interpreter_name 
    186     # value must EXACTLY match the value of req.interpreter (case-sensitive). 
    187 ##  raise StandardError(repr(req.interpreter)) 
    188      
    189     h = Handler(req) 
    190 ##    from paste import lint 
    191 ##    app = lint.middleware(app) 
    192     h.run(app) 
    193      
    194     # status was set in Handler.send_headers(); always return apache.OK 
     211    Handler(req).run(app) 
     212     
     213    # status was set in Handler; always return apache.OK 
    195214    return apache.OK 
    196215