durusmail: quixote-users: Quixote and mod_python bugs
Quixote and mod_python bugs
2004-04-09
Shahms King (2 parts)
Quixote and mod_python bugs
Shahms King
2004-04-09
After getting about 1/3 - 2/3 finished writing my own web framework
using mod_python I stumbled across Quixote and marveled at how similar
it was to what I was writing, scrapped my project and started learning
Quixote. (Thanks for saving me a lot of work, btw ;-P)

Anyway, in the process of learning the framework I discovered a couple
of bugs that weren't already mentioned in the mailing list or
documentation:

1) ModPython/Apache sets the 'PATH_INFO' and 'SCRIPT_NAME' variables
differently depending on how it's referenced from the apache config.
 directives set everything up correctly, but 
directives essentially prepend one level from 'PATH_INFO' onto
'SCRIPT_NAME' leading to some strange behavior.

i.e. PATH_INFO='/simple',SCRIPT_NAME='/qdemo' becomes
PATH_INFO='',SCRIPT_NAME='/qdemo/simple'

this leads to strange looking paths like "/qdemo/simple/12/factorial",
etc. and infinite redirects when referencing the root directory.

This is a relatively minor bug, unless you want to write your own
publisher and have it reside with the rest of the application.  I'm not
sure what the best way to fix this is, but there are a number of
options.

2) Logging.  This is a known issue, at least from the mailing list
history, and it is really easy to fix. In fact, attached is a patch that
preserves current behavior when 'ERROR_LOG' is specified in the config
file, otherwise it uses Apache's logging facilities.

Those are really the only problems I found, but I do have some other
questions:

The 'stderr' argument to Publisher.publish() is ignored; should it be?
What's the purpose of 'Publisher.debug_log'? It isn't currently used
anywhere.

--
Shahms King 
--- mod_python_handler.py       2003-12-03 15:30:30.000000000 -0800
+++ /var/www/qtest/quixote_handler.py   2004-04-09 15:59:24.000000000 -0700
@@ -9,22 +9,54 @@
 __revision__ = "$Id: mod_python_handler.py 22960 2003-11-03 18:14:22Z dbinger
$"

 # adapted from Erno Kuusela's quixote_handler.py, 2001/09/19 GPW
+# error logging added 2004/04/09 Shahms E. King

 import sys
 from mod_python import apache
 from quixote import Publisher, enable_ptl
+from quixote.config import Config
+
+class ErrorLog:
+    def __init__(self, publisher):
+        self.publisher = publisher
+
+    def write(self, msg):
+        self.publisher.log(msg)
+
+    def close(self):
+        pass

 class ModPythonPublisher(Publisher):
+    def __init__(self, package, config=None):
+        Publisher.__init__(self, package, config)
+        self.error_log = self.__error_log = ErrorLog(self) # may be overwritten
+        self.setup_logs()
+        self.__apache_request = None
+
+    def log(self, msg):
+        if self.error_log is self.__error_log:
+            if self.__apache_request:
+                self.__apache_request.log_error(msg)
+            else:
+                apache.log_error(msg)
+        else:
+            Publisher.log(self, msg)
+
     def publish_modpython(self, req):
         """publish_modpython() -> None

         Entry point from mod_python.
         """
-        self.publish(apache.CGIStdin(req),
-                     apache.CGIStdout(req),
-                     sys.stderr,
-                     apache.build_cgi_env(req))
-        return apache.OK
+        self.__apache_request = req
+        try:
+            self.publish(apache.CGIStdin(req),
+                         apache.CGIStdout(req),
+                         sys.stderr,
+                         apache.build_cgi_env(req))
+
+            return apache.OK
+        finally:
+            self.__apache_request = None

 enable_ptl()

@@ -37,12 +69,18 @@
     except KeyError:
         package = None

+    try:
+        configfile = opts['quixote-config-file']
+        config = Config()
+        config.read_file(self, configfile)
+    except KeyError:
+        config = None
+
     if not package:
         return apache.HTTP_INTERNAL_SERVER_ERROR
-    else:
-        pub = name2publisher.get(package)
-        if pub is None:
-            pub = ModPythonPublisher(package)
-            pub.setup_logs()
-            name2publisher[package] = pub
-        return pub.publish_modpython(req)
+
+    pub = name2publisher.get(package)
+    if pub is None:
+        pub = ModPythonPublisher(package, config)
+        name2publisher[package] = pub
+    return pub.publish_modpython(req)
reply