You are viewing a plain text version of this content. The canonical link for it is here.
Posted to mod_python-commits@quetz.apache.org by gr...@apache.org on 2006/05/06 08:30:28 UTC

svn commit: r400247 - in /httpd/mod_python/trunk: Doc/appendixc.tex Doc/modpython5.tex lib/python/mod_python/__init__.py lib/python/mod_python/apache.py src/include/mpversion.h test/htdocs/tests.py test/test.py

Author: grahamd
Date: Fri May  5 23:30:26 2006
New Revision: 400247

URL: http://svn.apache.org/viewcvs?rev=400247&view=rev
Log:
When specifying multiple handlers for phases other than the content phase
as defined by PythonHandler, the status returned by each handler is now
treated the same as how Apache would treat the status if the handler was
registered using the low level C API. What this means is that whereas
previously stacked handlers of any phase would in turn be executed as long
as they returned apache.OK, this is no longer the case and now only occurs
for PythonHandler. What happens for other phases is dependent on the phase,
but in all cases, a handler returning apache.DECLINED no longer causes the
execution of subsequent handlers for the phase to be skipped. Instead, it
will move to the next of the stacked handlers. In the case of
PythonTransHandler, PythonAuthenHandler, PythonAuthzHandler and
PythonTypeHandler, as soon as apache.OK is returned, subsequent handlers
for the phase will be skipped, as the result indicates that any processing
pertinent to that phase has been completed. For other phases, stacked
handlers will continue to be executed if apache.OK is returned as well as
when apache.DECLINED is returned. (MODPYTHON-129)


Modified:
    httpd/mod_python/trunk/Doc/appendixc.tex
    httpd/mod_python/trunk/Doc/modpython5.tex
    httpd/mod_python/trunk/lib/python/mod_python/__init__.py
    httpd/mod_python/trunk/lib/python/mod_python/apache.py
    httpd/mod_python/trunk/src/include/mpversion.h
    httpd/mod_python/trunk/test/htdocs/tests.py
    httpd/mod_python/trunk/test/test.py

Modified: httpd/mod_python/trunk/Doc/appendixc.tex
URL: http://svn.apache.org/viewcvs/httpd/mod_python/trunk/Doc/appendixc.tex?rev=400247&r1=400246&r2=400247&view=diff
==============================================================================
--- httpd/mod_python/trunk/Doc/appendixc.tex (original)
+++ httpd/mod_python/trunk/Doc/appendixc.tex Fri May  5 23:30:26 2006
@@ -170,6 +170,26 @@
       rather than creating a new distinct Python request object. This means
       that any data added explicitly to a request object can be passed
       between such requests.
+    \item
+      (\citetitle[http://issues.apache.org/jira/browse/MODPYTHON-129]{MODPYTHON-129})
+      When specifying multiple handlers for phases other than the content
+      phase as defined by \code{PythonHandler}, the status returned by each
+      handler is now treated the same as how Apache would treat the status
+      if the handler was registered using the low level C API. What this
+      means is that whereas previously stacked handlers of any phase would
+      in turn be executed as long as they returned \code{apache.OK}, this
+      is no longer the case and now only occurs for \code{PythonHandler}.
+      What happens for other phases is dependent on the phase, but in all
+      cases, a handler returning \code{apache.DECLINED} no longer causes
+      the execution of subsequent handlers for the phase to be skipped.
+      Instead, it will move to the next of the stacked handlers. In the
+      case of \code{PythonTransHandler}, \code{PythonAuthenHandler},
+      \code{PythonAuthzHandler} and \code{PythonTypeHandler}, as soon
+      as \code{apache.OK} is returned, subsequent handlers for the phase
+      will be skipped, as the result indicates that any processing pertinent
+      to that phase has been completed. For other phases, stacked handlers
+      will continue to be executed if \code{apache.OK} is returned as well
+      as when \code{apache.DECLINED} is returned.
   \end{itemize}
 
   Bug Fixes

Modified: httpd/mod_python/trunk/Doc/modpython5.tex
URL: http://svn.apache.org/viewcvs/httpd/mod_python/trunk/Doc/modpython5.tex?rev=400247&r1=400246&r2=400247&view=diff
==============================================================================
--- httpd/mod_python/trunk/Doc/modpython5.tex (original)
+++ httpd/mod_python/trunk/Doc/modpython5.tex Fri May  5 23:30:26 2006
@@ -16,8 +16,19 @@
 they will be called sequentially, from left to right. Same handler
 directives can be specified multiple times as well, with the same
 result - all handlers listed will be executed sequentially, from first
-to last. If any handler in the sequence returns a value other than
-\code{apache.OK}, then execution of all subsequent handlers is aborted.
+to last.
+
+If any handler in the sequence returns a value other than \code{apache.OK}
+or \code{apache.DECLINED}, then execution of all subsequent handlers for
+that phase are aborted. What happens when either \code{apache.OK} or
+\code{apache.DECLINED} is returned is dependent on which phase is
+executing.
+
+Note that prior to mod_python 3.3, if any handler in the sequence, no
+matter which phase was executing, returned a value other than
+\code{apache.OK}, then execution of all subsequent handlers for that phase
+was aborted. This is now the case only for the \code{PythonHandler}
+directive.
 
 The list of handlers can optionally be followed by a \code{|} followed
 by one or more file extensions. This would restrict the execution of
@@ -75,6 +86,10 @@
 other phases have been processed. This is useful to make decisions
 based upon the input header fields.
 
+Where multiple handlers are specified, if any handler in the sequence
+returns a value other than \code{apache.OK} or \code{apache.DECLINED}, then
+execution of all subsequent handlers for this phase are aborted.
+
 \begin{notice}
 When this phase of the request is processed, the URI has not yet
 been translated into a path name, therefore this directive could never
@@ -109,6 +124,10 @@
 an actual filename, before the server's default rules (Alias
 directives and the like) are followed.
 
+Where multiple handlers are specified, if any handler in the sequence
+returns a value other than \code{apache.DECLINED}, then execution of all
+subsequent handlers for this phase are aborted.
+
 \begin{notice}
   At the time when this phase of the request is being processed, the
   URI has not been translated into a path name, therefore this
@@ -135,6 +154,10 @@
 request headers and take any appropriate specific actions early in the
 processing sequence.
 
+Where multiple handlers are specified, if any handler in the sequence
+returns a value other than \code{apache.OK} or \code{apache.DECLINED}, then
+execution of all subsequent handlers for this phase are aborted.
+
 \subsection{PythonInitHandler\label{dir-handlers-pih}}
 \index{PythonInitHandler}
 
@@ -151,6 +174,10 @@
 phases that is allowed both inside and outside \file{.htaccess} and
 directory.
 
+Where multiple handlers are specified, if any handler in the sequence
+returns a value other than \code{apache.OK} or \code{apache.DECLINED}, then
+execution of all subsequent handlers for this phase are aborted.
+
 This handler is actually an alias to two different handlers. When
 specified in the main config file outside any directory tags, it is an
 alias to \code{PostReadRequestHandler}. When specified inside directory
@@ -174,6 +201,10 @@
 This routine is called to check for any module-specific restrictions
 placed upon the requested resource.
 
+Where multiple handlers are specified, if any handler in the sequence
+returns a value other than \code{apache.OK} or \code{apache.DECLINED}, then
+execution of all subsequent handlers for this phase are aborted.
+
 For example, this can be used to restrict access by IP number. To do
 so, you would return \code{HTTP_FORBIDDEN} or some such to indicate
 that access is not allowed.
@@ -195,6 +226,10 @@
 verifying that the [encrypted] password sent matches the one in the
 database).
 
+Where multiple handlers are specified, if any handler in the sequence
+returns a value other than \code{apache.DECLINED}, then execution of all
+subsequent handlers for this phase are aborted.
+
 To obtain the username, use \code{req.user}. To obtain the password
 entered by the user, use the \code{req.get_basic_auth_pw()} function.
 
@@ -241,6 +276,10 @@
 whether a user is allowed to access a particular resource. But more
 often than not it is done right in the AuthenHandler.
 
+Where multiple handlers are specified, if any handler in the sequence
+returns a value other than \code{apache.DECLINED}, then execution of all
+subsequent handlers for this phase are aborted.
+
 \subsection{PythonTypeHandler\label{dir-handlers-tph}}
 \index{PythonTypeHandler}
 
@@ -257,6 +296,10 @@
 type information bits, like Content-type (via \code{r->content_type}),
 language, et cetera.
 
+Where multiple handlers are specified, if any handler in the sequence
+returns a value other than \code{apache.DECLINED}, then execution of all
+subsequent handlers for this phase are aborted.
+
 \subsection{PythonFixupHandler\label{dir-handlers-fuh}}
 \index{PythonFixupHandler}
 
@@ -272,6 +315,10 @@
 This routine is called to perform any module-specific fixing of header
 fields, et cetera. It is invoked just before any content-handler.
 
+Where multiple handlers are specified, if any handler in the sequence
+returns a value other than \code{apache.OK} or \code{apache.DECLINED}, then
+execution of all subsequent handlers for this phase are aborted.
+
 \subsection{PythonHandler\label{dir-handlers-ph}}
 \index{PythonHandler}
 
@@ -287,6 +334,10 @@
 This is the main request handler. Many applications will only provide
 this one handler.
 
+Where multiple handlers are specified, if any handler in the sequence
+returns a value other than \code{apache.OK}, then execution of all
+subsequent handlers for this phase are aborted.
+
 \subsection{PythonLogHandler\label{dir-handlers-plh}}
 \index{PythonLogHandler}
 
@@ -300,7 +351,11 @@
 mod_python.c
 
 This routine is called to perform any module-specific logging
-activities. 
+activities.
+
+Where multiple handlers are specified, if any handler in the sequence
+returns a value other than \code{apache.OK} or \code{apache.DECLINED}, then
+execution of all subsequent handlers for this phase are aborted.
 
 \subsection{PythonCleanupHandler\label{dir-handlers-pch}}
 \index{PythonCleanupHandler}

Modified: httpd/mod_python/trunk/lib/python/mod_python/__init__.py
URL: http://svn.apache.org/viewcvs/httpd/mod_python/trunk/lib/python/mod_python/__init__.py?rev=400247&r1=400246&r2=400247&view=diff
==============================================================================
--- httpd/mod_python/trunk/lib/python/mod_python/__init__.py (original)
+++ httpd/mod_python/trunk/lib/python/mod_python/__init__.py Fri May  5 23:30:26 2006
@@ -20,5 +20,5 @@
 __all__ = ["apache", "cgihandler", "psp",
            "publisher", "util", "python22"]
 
-version = "3.3.0-dev-20060503"
+version = "3.3.0-dev-20060506"
 

Modified: httpd/mod_python/trunk/lib/python/mod_python/apache.py
URL: http://svn.apache.org/viewcvs/httpd/mod_python/trunk/lib/python/mod_python/apache.py?rev=400247&r1=400246&r2=400247&view=diff
==============================================================================
--- httpd/mod_python/trunk/lib/python/mod_python/apache.py (original)
+++ httpd/mod_python/trunk/lib/python/mod_python/apache.py Fri May  5 23:30:26 2006
@@ -301,6 +301,13 @@
         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
 
@@ -311,8 +318,8 @@
 
                 module_name = l[0]
                 if len(l) == 1:
-                    # no oject, provide default
-                    object_str = req.phase[len("python"):].lower()
+                    # no object, provide default
+                    object_str = default_object_str
                 else:
                     object_str = l[1]
 
@@ -395,13 +402,15 @@
                             _result_warning % type(result)
 
                     # stop cycling through handlers
-                    if result != OK:
+                    if result not in expected:
                         break
 
                 elif hlist.silent:
-                    # A faulty handler marked as silent will only 
-                    # propagate DECLINED if it is the first and only handler.
-                    if result != OK:
+		    # A missing handler when in silent mode will
+		    # only propagate DECLINED if it is the first
+		    # and only handler.
+
+                    if result == HTTP_INTERNAL_SERVER_ERROR:
                         result = DECLINED
 
                 hlist.next()
@@ -1005,6 +1014,21 @@
 OK = REQ_PROCEED = 0
 DONE = -2
 DECLINED = REQ_NOACTION = -1
+
+_status_values = {
+    "postreadrequesthandler":   [ DECLINED, OK ],
+    "transhandler":             [ DECLINED ],
+    "maptostoragehandler":      [ DECLINED ],
+    "inithandler":              [ DECLINED, OK ],
+    "headerparserhandler":      [ DECLINED, OK ],
+    "accesshandler":            [ DECLINED, OK ],
+    "authenhandler":            [ DECLINED ],
+    "authzhandler":             [ DECLINED ],
+    "typehandler":              [ DECLINED ],
+    "fixuphandler":             [ DECLINED, OK ],
+    "loghandler":               [ DECLINED, OK ],
+    "handler":                  [ OK ],
+}
 
 # constants for get_remote_host
 REMOTE_HOST = 0

Modified: httpd/mod_python/trunk/src/include/mpversion.h
URL: http://svn.apache.org/viewcvs/httpd/mod_python/trunk/src/include/mpversion.h?rev=400247&r1=400246&r2=400247&view=diff
==============================================================================
--- httpd/mod_python/trunk/src/include/mpversion.h (original)
+++ httpd/mod_python/trunk/src/include/mpversion.h Fri May  5 23:30:26 2006
@@ -1,5 +1,5 @@
 #define MPV_MAJOR 3
 #define MPV_MINOR 3
 #define MPV_PATCH 0
-#define MPV_BUILD 20060503
-#define MPV_STRING "3.3.0-dev-20060503"
+#define MPV_BUILD 20060506
+#define MPV_STRING "3.3.0-dev-20060506"

Modified: httpd/mod_python/trunk/test/htdocs/tests.py
URL: http://svn.apache.org/viewcvs/httpd/mod_python/trunk/test/htdocs/tests.py?rev=400247&r1=400246&r2=400247&view=diff
==============================================================================
--- httpd/mod_python/trunk/test/htdocs/tests.py (original)
+++ httpd/mod_python/trunk/test/htdocs/tests.py Fri May  5 23:30:26 2006
@@ -1095,6 +1095,46 @@
     req.write("test ok")
     return apache.OK
 
+def phase_status_1(req):
+    apache.log_error("phase_status_1")
+    req.phases = [1]
+    return apache.DECLINED
+
+def phase_status_2(req):
+    apache.log_error("phase_status_2")
+    req.phases.append(2)
+    req.user = "bogus"
+    req.ap_auth_type = "bogus"
+    return apache.OK
+
+def phase_status_3(req):
+    apache.log_error("phase_status_3")
+    req.phases.append(3)
+    return apache.OK
+
+def phase_status_4(req):
+    apache.log_error("phase_status_4")
+    req.phases.append(4)
+    return apache.DECLINED
+
+def phase_status_5(req):
+    apache.log_error("phase_status_5")
+    req.phases.append(5)
+    return apache.OK
+
+def phase_status_6(req):
+    apache.log_error("phase_status_6")
+    req.phases.append(6)
+    return apache.OK
+
+def phase_status_7(req):
+    apache.log_error("phase_status_7")
+    if req.phases != [1, 2, 4, 5, 6]:
+        req.write("test failed")
+    else:
+        req.write("test ok")
+    return apache.OK
+
 def test_sys_argv(req):
     import sys
     req.write(repr(sys.argv))

Modified: httpd/mod_python/trunk/test/test.py
URL: http://svn.apache.org/viewcvs/httpd/mod_python/trunk/test/test.py?rev=400247&r1=400246&r2=400247&view=diff
==============================================================================
--- httpd/mod_python/trunk/test/test.py (original)
+++ httpd/mod_python/trunk/test/test.py Fri May  5 23:30:26 2006
@@ -2077,6 +2077,33 @@
         if (rsp != "test ok"):
             self.fail(`rsp`)
 
+    def test_phase_status_conf(self):
+        c = VirtualHost("*",
+                        ServerName("test_phase_status"),
+                        DocumentRoot(DOCUMENT_ROOT),
+                        Directory(DOCUMENT_ROOT,
+                                  SetHandler("mod_python"),
+                                  AuthType("bogus"),
+                                  AuthName("bogus"),
+                                  Require("valid-user"),
+                                  PythonAuthenHandler("tests::phase_status_1"),
+                                  PythonAuthenHandler("tests::phase_status_2"),
+                                  PythonAuthenHandler("tests::phase_status_3"),
+                                  PythonFixupHandler("tests::phase_status_4"),
+                                  PythonFixupHandler("tests::phase_status_5"),
+                                  PythonFixupHandler("tests::phase_status_6"),
+                                  PythonHandler("tests::phase_status_7"),
+                                  PythonDebug("On")))
+        return str(c)
+
+    def test_phase_status(self):
+
+        print "\n  * Testing phase status"
+        rsp = self.vhost_get("test_phase_status")
+
+        if (rsp != "test ok"):
+            self.fail(`rsp`)
+
     def test_publisher_conf(self):
         c = VirtualHost("*",
                         ServerName("test_publisher"),
@@ -2568,6 +2595,7 @@
         perRequestSuite.addTest(PerRequestTestCase("test_files_directive"))
         perRequestSuite.addTest(PerRequestTestCase("test_none_handler"))
         perRequestSuite.addTest(PerRequestTestCase("test_server_return"))
+        perRequestSuite.addTest(PerRequestTestCase("test_phase_status"))
         perRequestSuite.addTest(PerRequestTestCase("test_publisher"))
         perRequestSuite.addTest(PerRequestTestCase("test_publisher_auth_nested"))
         perRequestSuite.addTest(PerRequestTestCase("test_publisher_auth_method_nested"))