[mod_python] Passing information through req.internal_redirect().

Graham Dumpleton grahamd at dscpl.com.au
Sat Apr 23 03:41:13 EDT 2005


There has been a few times on the list where questions have been asked 
about
how to pass information through a "req.internal_redirect()" call. The 
problem
is that any data which is stashed in the "req" object isn't available 
to the
target of the internal redirect because Apache/mod_python constructs a 
new
"req" object for the subsequent handler invocation.

Turns out there is actually a way of passing at least some information. 
This
is done by adding new key/values to the "req.subprocess_env" table. 
This table
is held within Apache data structures associated with the request and 
contents
of it are propagated through to the target of the internal redirect. 
The only
trick is that the key names get modified when the redirect occurs. You 
also
can only store string values.

Take for example a handler which contains:

   from mod_python import apache
   import os

   def handler(req):
     req.subprocess_env.add("XXX","YYY")
     req.internal_redirect(os.path.split(req.uri)[0]+'/page')
     return apache.OK

and is accessed as:

   /~grahamd/redirect/redirect

And a second handler which is triggered as the target of the redirect 
which
contains:

   from mod_python import apache

   def handler(req):
     req.content_type = "text/plain"
     for key in req.subprocess_env.keys():
       print >> req, key, "=", req.subprocess_env[key]
     return apache.OK

That is, URL for this is:

   /~grahamd/redirect/page

The result of making a request against the first URL is that 
redirection to
the second occurs, with the output being:

   REDIRECT_GATEWAY_INTERFACE = CGI/1.1
   REDIRECT_SERVER_PROTOCOL = HTTP/1.1
   REDIRECT_REQUEST_METHOD = GET
   REDIRECT_QUERY_STRING =
   REDIRECT_REQUEST_URI = /~grahamd/redirect/redirect
   REDIRECT_SCRIPT_NAME = /~grahamd/redirect/redirect
   REDIRECT_XXX = YYY
   REDIRECT_STATUS = 200
   GATEWAY_INTERFACE = CGI/1.1
   SERVER_PROTOCOL = HTTP/1.1
   REQUEST_METHOD = GET
   QUERY_STRING =
   REQUEST_URI = /~grahamd/redirect/redirect
   SCRIPT_NAME = /~grahamd/redirect/page

As can be seen, the key/value pair of "XXX" and "YYY" have persisted, 
although
the key name is now "REDIRECT_XXX". One can also see that other 
preexisting
variables set by Apache for the original request are also propagated as 
well,
with similar key name change.

That one can pass a newly created value would be useful where for 
example a
initial handler had created a new session object as it could store the 
session
ID in this table such that it is accessible to the second handler. In 
the past
people have noticed how in redirects both handlers end up creating 
separate
new session IDs if the first handler had to create one, because the new 
session
ID is lost and not usable by the second handler.

The information propagated about the initial request is useful as well 
for the
fact that the original URI is present. This could be used by the second 
handler
in some way.

As an example, when using the ErrorDocument directive, Apache uses an 
internal
redirect to redirect to the page when it is a local URI. As documented 
in:

   http://httpd.apache.org/docs-2.0/custom-error.html

the req.subprocess_env would contain the "REDIRECT_*" values shown 
above. In
this case the internal redirect is being done in Apache itself, but 
there is
no reason that you couldn't implement your own version of the 
ErrorDocument
functionality in your own custom handler code.

Anyway, thought I would put together this ramble about this stuff when 
I found
that this could be done since it may have been a solution to problems a 
few
people had faced before, but that it could be done doesn't seem to have 
ever
been mentioned on the mailing list before. At least now anyone 
searching the
archives may find this. :-)

Enjoy.

Graham



More information about the Mod_python mailing list