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

Graham Dumpleton grahamd at dscpl.com.au
Sun Apr 24 01:49:23 EDT 2005


> How about req.notes - does that work? That may be a more appropriate 
> table to use than subprocess_env.
>
> Grisha

Nothing I put in "req.notes" survives the redirect.

There is some stuff in there:

   python_init_ran = 1
   mod_userdir_user = grahamd

The "python_init_ran" is put there by either of:

   PythonHeaderParserHandler
   PythonPostReadRequestHandler

code in mod_python.c and seems to be a bookkeeping flag to ensure that:

   PythonInitHandler

is only run once.

The "moduserdir_user" setting seems to be inherited from Apache.

Thus, "req.notes" appears to be created for each invocation of request
handler phases.

However, if one instead uses "req.connection.notes", ie., notes object 
which
exists in the connection object, then they are preserved.

So therefore have two ways of passing information, either in the table 
object
"req.subprocess_env" or in table object "req.connection.notes". In the 
latter,
the key names are preserved as they were whereas in 
"req.subprocess_env" they
get "REDIRECT_" prefixed.

Because it is a table object in both cases, value can still only be a 
string.

Information in "req.subprocess_env" is still useful in its own right if 
the
original URI was required.

Anyway, useful stuff to know even though I am not sure I have a use for 
it
at the moment.

Graham

On 24/04/2005, at 12:47 PM, Gregory (Grisha) Trubetskoy wrote:

> On Sat, 23 Apr 2005, Graham Dumpleton wrote:
>
>> 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
>>
>> _______________________________________________
>> Mod_python mailing list
>> Mod_python at modpython.org
>> http://mailman.modpython.org/mailman/listinfo/mod_python
>>



More information about the Mod_python mailing list