[Zope-dev] __before_publishing_traverse__ calls RESPONSE.redirect(): is there another way to change the browser URL?

Craeg K Strong cstrong@arielpartners.com
Fri, 27 Sep 2002 12:49:01 -0400


Thanks for the response!

I have made a bit more progress on the issue.  To recap: our application
consists of a number of HTML forms.  When the submit button on a form is
pressed, the application must do some processing in order to determine
which URL should next be displayed.

We are trying to follow ReST principles, so in order to view an invoice
within a task order for a contract, you might view the following url

http://acme.com/myapp/contracts/TRW-001/taskorders/TO-01/invoices/DSDC-001-9301

We have defined a __before_publishing_traverse__ hook that determines the proper
URL and then does the following:

raise 'Redirect', newURL

We found that by doing the redirect this way, rather than:

response.redirect(newURL)

__bobo_traverse__ does *not* get called.  By raising an exception, the
current call is aborted, and a new request is generated for the new URL.
This is a good thing.

However, I would like to distinguish between two cases:

a) Direct Navigation:   e.g.I am a user and I just typed in

http://acme.com/myapp/contracts/TRW-001/taskorders/TO-01/invoices/DSDC-001-9301

into my browser

b) Application-Controlled:   e.g. I am the application, I did some processing
based on a button the user pressed in some form somewhere and determined
that the next URL should be

http://acme.com/myapp/contracts/TRW-001/taskorders/TO-01/invoices/DSDC-001-9301

====Now here is the issue====

In both cases above, the REQUEST object looks identical.   Is there any way
that I can distinguish a GET that is the result of a REDIRECT from one that
is not?

I would think this would be of interest to others.  For example, if I move my
web page and put a redirect from the old address, I could track how many
people came to my web page directly versus those that are still using the
old address and are getting redirected.

Any advice?

Thanks again!

--Craeg

Casey Duncan wrote:
> ----- Original Message -----
> From: "Craeg K Strong" <cstrong@arielpartners.com>
> To: <zope-dev@zope.org>
> Sent: Monday, September 23, 2002 10:59 PM
> Subject: [Zope-dev] __before_publishing_traverse__ calls
> RESPONSE.redirect(): is there another way to change the browser URL?
>  
>>Hello:
>>
>>I have defined a __before_publishing__traverse__() method in my Zope
> 
> product.
> 
>>Its job is to redirect the URL displayed in the browser to a nice looking
>>URL, something like
>>
>>"../myapp/invoices/123"
>>
>>instead of
>>
>>"../myapp/execute"
> 
> 
> __before_publishing__traverse__() doesn't affect the way the url looks to
> the browser. Although it can change the path being traversed inside Zope if
> you wish. It effectively lets any traversed object affect the rest of the
> traversal in some arbitrary way, or do some work before it is itself
> traversed.
> 
> 
>>That way all my ZPT forms can call the same method: execute(),
>>and I don't hardcode any URLs in my ZPTs.  The objective is to
>>encapsulate my resource-to-URL mapping so that it can be changed
>>independently from the ZPT code.
>>
>>I don't want to use setVirtualRoot, because I want to change the entire
>>URL, not just "all but the leaf"
> 
> 
> I'm not following this.
> 
> 
>>The problem is that __before_publishing_traverse__ is getting called
> 
> *twice*
> 
>>for each button press.
>>
>>*First* it gets called with the "../myapp/execute" URL.  This is when I
>>call RESPONSE.redirect()
>>
>>*Second* it gets called with the "../myapp/invoices/123" URL
>>
>>I am trying to understand how Zope works with the HTTP REDIRECT machinery.
> 
> 
> __before_publishing_traverse__ is called once for any object that defines it
> each time that object is traversed during a web request. A redirect
> generates a whole new web request, so this causes another whole set of
> object traversals.
> 
> 
>>Is there a way to make the URL that is actually displayed in the browser
>>*different* from the Zope method name you are calling, aside from using
>>RESPONSE.redirect()?
> 
> 
> Redirect would not do this. Redirect changes the URL and makes the browser
> go to that URL. Whether that URL is a complete traversal to a method depends
> on your application. For example, a humble Python script has a traversal
> hook of the aforementioned variety that eats the rest of the URL path
> elements and binds them to the script's namespace, by default under the name
> "traverse_subpath". For example, given a Python script "pyscript" in your
> Zope root directory, then the following URL would call it:
> 
> http://zopeserver/pyscript/more/path/elements
> 
> When called, the script would have the traverse_subpath set to the value
> ['more','path','elements']. So the URL does not point to a method in this
> case. This is the easiest way to gather data from URL path elements.
> 
> To do the same in external Python code, take a gander at the traversal hook
> in {Zope}/lib/python/Shared/DC/Scripts/Bindings.py which is the code that
> Python scripts use.
> 
> hth,
> 
> -Casey