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

Chris Jackson christopher.jackson at gmail.com
Mon Apr 25 08:58:58 EDT 2005


This is all very intersting...and useful information.  I just wish
there was a more standard built-in way of doing this, but I guess
req.subprocess_env will suffice for now.

One could call add_common_vars() to add "extra" data to subprocess_env
as well.  It's also intresting that you mention the req.subprocess_env
table is handled by Apache and can be access in a cross-lingual
fashion; Perhaps even across different processes and separate
"applications."

Thanks for pointing this info out to us.

~= Chris =~

On 4/24/05, Graham Dumpleton <grahamd at dscpl.com.au> wrote:
> 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
> 
> _______________________________________________
> 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