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
|