📄 apache.py
字号:
# vim: set sw=4 expandtab : # # Copyright 2004 Apache Software Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you # may not use this file except in compliance with the License. You # may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or # implied. See the License for the specific language governing # permissions and limitations under the License. # # Originally developed by Gregory Trubetskoy. # # $Id: apache.py 468216 2006-10-27 00:54:12Z grahamd $import sysimport tracebackimport timeimport osimport pdbimport statimport impimport typesimport cgiimport _apachetry: import threadingexcept: import dummy_threading as threading# Cache for values of PythonPath that have been seen already._path_cache = {}_path_cache_lock = threading.Lock()_result_warning = """Handler has returned result or raised SERVER_RETURNexception with argument having non integer type. Type of value returnedwas %s, whereas expected """ + str(types.IntType) + "."class CallBack: """ A generic callback object. """ class HStack: """ The actual stack string lives in the request object so it can be manipulated by both apache.py and mod_python.c """ def __init__(self, req): self.req = req def pop(self): handlers = self.req.hstack.split() if not handlers: return None else: self.req.hstack = " ".join(handlers[1:]) return handlers[0] def ConnectionDispatch(self, conn): # config config = conn.base_server.get_config() debug = int(config.get("PythonDebug", 0)) try: handler = conn.hlist.handler # split module::handler l = handler.split('::', 1) module_name = l[0] if len(l) == 1: # no oject, provide default object_str = "connectionhandler" else: object_str = l[1] # evaluate pythonpath and set sys.path to # resulting value if not already done if config.has_key("PythonPath"): _path_cache_lock.acquire() try: pathstring = config["PythonPath"] if not _path_cache.has_key(pathstring): newpath = eval(pathstring) _path_cache[pathstring] = None sys.path[:] = newpath finally: _path_cache_lock.release() # import module module = import_module(module_name, autoreload=int(config.get("PythonAutoReload", 1)), log=debug) # find the object object = resolve_object(module, object_str, arg=conn, silent=0) # Only permit debugging using pdb if Apache has # actually been started in single process mode. pdb_debug = int(config.get("PythonEnablePdb", "0")) one_process = exists_config_define("ONE_PROCESS") if pdb_debug and one_process: # Don't use pdb.runcall() as it results in # a bogus 'None' response when pdb session # is quit. With this code the exception # marking that the session has been quit is # propogated back up and it is obvious in # the error message what actually occurred. debugger = pdb.Pdb() debugger.reset() sys.settrace(debugger.trace_dispatch) try: result = object(conn) finally: debugger.quitting = 1 sys.settrace(None) else: result = object(conn) assert (type(result) == type(int())), \ "ConnectionHandler '%s' returned invalid return code." % handler except PROG_TRACEBACK, traceblock: # Program run-time error try: (etype, value, traceback) = traceblock result = self.ReportError(etype, value, traceback, srv=conn.base_server, phase="ConnectionHandler", hname=handler, debug=debug) finally: traceback = None except: # Any other rerror (usually parsing) try: exc_type, exc_value, exc_traceback = sys.exc_info() result = self.ReportError(exc_type, exc_value, exc_traceback, srv=conn.base_server, phase="ConnectionHandler", hname=handler, debug=debug) finally: exc_traceback = None return result def FilterDispatch(self, filter): req = filter.req # config config = req.get_config() debug = int(config.get("PythonDebug", 0)) try: # add the directory to pythonpath if # not there yet, or evaluate pythonpath # and set sys.path to resulting value # if not already done if config.has_key("PythonPath"): _path_cache_lock.acquire() try: pathstring = config["PythonPath"] if not _path_cache.has_key(pathstring): newpath = eval(pathstring) _path_cache[pathstring] = None sys.path[:] = newpath finally: _path_cache_lock.release() else: if filter.dir and (filter.dir not in sys.path): sys.path[:0] = [filter.dir] if not callable(filter.handler): # split module::handler l = filter.handler.split('::', 1) module_name = l[0] if len(l) == 1: # no oject, provide default if filter.is_input: object_str = "inputfilter" else: object_str = "outputfilter" else: object_str = l[1] # import module module = import_module(module_name, autoreload=int(config.get("PythonAutoReload", 1)), log=debug) # find the object object = resolve_object(module, object_str, arg=filter, silent=0) else: object = filter.handler # Only permit debugging using pdb if Apache has # actually been started in single process mode. pdb_debug = int(config.get("PythonEnablePdb", "0")) one_process = exists_config_define("ONE_PROCESS") if pdb_debug and one_process: # Don't use pdb.runcall() as it results in # a bogus 'None' response when pdb session # is quit. With this code the exception # marking that the session has been quit is # propogated back up and it is obvious in # the error message what actually occurred. debugger = pdb.Pdb() debugger.reset() sys.settrace(debugger.trace_dispatch) try: result = object(filter) finally: debugger.quitting = 1 sys.settrace(None) else: result = object(filter) # always flush the filter. without a FLUSH or EOS bucket, # the content is never written to the network. # XXX an alternative is to tell the user to flush() always if not filter.closed: filter.flush() except SERVER_RETURN, value: # SERVER_RETURN indicates a non-local abort from below # with value as (result, status) or (result, None) or result try: if len(value.args) == 2: (result, status) = value.args if status: req.status = status else: result = value.args[0] if type(result) != type(7): s = "Value raised with SERVER_RETURN is invalid. It is a " s = s + "%s, but it must be a tuple or an int." % type(result) _apache.log_error(s, APLOG_NOERRNO|APLOG_ERR, req.server) return except: pass except PROG_TRACEBACK, traceblock: # Program run-time error try: (etype, value, traceback) = traceblock filter.disable() result = self.ReportError(etype, value, traceback, req=req, filter=filter, phase="Filter: " + filter.name, hname=filter.handler, debug=debug) finally: traceback = None except: # Any other rerror (usually parsing) try: exc_type, exc_value, exc_traceback = sys.exc_info() filter.disable() result = self.ReportError(exc_type, exc_value, exc_traceback, req=req, filter=filter, phase=filter.name, hname=filter.handler, debug=debug) finally: exc_traceback = None return OK def HandlerDispatch(self, req): """ This is the handler dispatcher. """ # be cautious result = HTTP_INTERNAL_SERVER_ERROR # config config = req.get_config() debug = int(config.get("PythonDebug", 0)) default_object_str = req.phase[len("python"):].lower() # Lookup expected status values that allow us to # continue when multiple handlers exist. expected = _status_values[default_object_str] try: hlist = req.hlist while hlist.handler is not None: # add the directory to pythonpath if # not there yet, or evaluate pythonpath # and set sys.path to resulting value # if not already done if config.has_key("PythonPath"): _path_cache_lock.acquire() try: pathstring = config["PythonPath"] if not _path_cache.has_key(pathstring): newpath = eval(pathstring) _path_cache[pathstring] = None sys.path[:] = newpath finally: _path_cache_lock.release() else: dir = hlist.directory if dir and (dir not in sys.path): sys.path[:0] = [dir] if not callable(hlist.handler): # split module::handler l = hlist.handler.split('::', 1) module_name = l[0] if len(l) == 1: # no object, provide default object_str = default_object_str else: object_str = l[1] # import module module = import_module(module_name, autoreload=int(config.get("PythonAutoReload", 1)), log=debug) # find the object object = resolve_object(module, object_str, arg=req, silent=hlist.silent) else: object = hlist.handler if not hlist.silent or object is not None: try: # Only permit debugging using pdb if Apache has # actually been started in single process mode. pdb_debug = int(config.get("PythonEnablePdb", "0")) one_process = exists_config_define("ONE_PROCESS") if pdb_debug and one_process: # Don't use pdb.runcall() as it results in # a bogus 'None' response when pdb session # is quit. With this code the exception # marking that the session has been quit is # propogated back up and it is obvious in # the error message what actually occurred. debugger = pdb.Pdb() debugger.reset() sys.settrace(debugger.trace_dispatch) try: result = object(req) finally: debugger.quitting = 1 sys.settrace(None) else: result = object(req) except SERVER_RETURN, value: # The SERVER_RETURN exception type when raised # otherwise indicates an abort from below with # value as (result, status) or (result, None) or
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -