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

Graham Dumpleton grahamd at dscpl.com.au
Sun Apr 24 03:57:50 EDT 2005


Confirmed state of play. Using "req.prev" does not give access to any
Python specific stuff stashed in "req" by handler which did redirect.
One can as suspected though, use "req.prev.notes" to access data saved
in the "req.notes" of the previous request object, giving a third
place one can save data away.

Obviously if using the "notes" table objects, the subsequent handler
needs to be something that has access to them, whereas  
"req.subprocess_env"
table data can be probably easily be accessed by a handler written in
a totally different language and not in mod_python at all. :-)

Graham

On 24/04/2005, at 5:36 PM, Graham Dumpleton wrote:

> I'll check in a while, but suspect that that still isn't going to give
> access to any Python specific stuff that has been stashed in the "req"
> object. I remember that one of the past mailing list messages was about
> someone having tried this and found it wasn't possible. I would imagine
> though that "req.prev.notes" would give you access to the table object
> of previous request object, since the table object is stored in Apache.
>
> Graham
>
> On 24/04/2005, at 5:29 PM, Nicolas Lehuen wrote:
>
>> I didn't test it, but it seems the 'prev' member field could help you
>> get the initial request object after an internal redirect. Quoting
>> from the documentation :
>>
>> http://www.modpython.org/live/current/doc-html/pyapi-mprequest- 
>> mem.html
>>
>> next
>>     If this is an internal redirect, the request object we redirect
>> to. (Read-Only)
>>
>> prev
>>     If this is an internal redirect, the request object we redirect
>> from. (Read-Only)
>>
>> Regards,
>> Nicolas
>>
>> On 4/24/05, Graham Dumpleton <grahamd at dscpl.com.au> wrote:
>>>> 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
>>>>>
>>>
>>> _______________________________________________
>>> Mod_python mailing list
>>> Mod_python at modpython.org
>>> http://mailman.modpython.org/mailman/listinfo/mod_python
>>>
>
> _______________________________________________
> 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