This post originated from an RSS feed registered with Python Buzz
by Ben Last.
Original Post: Sublunary Paths
Feed Title: The Law Of Unintended Consequences
Feed URL: http://benlast.livejournal.com/data/rss
Feed Description: The Law Of Unintended Consequences
Before you ask, sublunary paths comes from a poem by Philip Larkin (it's Many famous feet have trod, partway down that page). It has nothing much to do with web programming, nor Zope, but every time I see the identifier subpath it reminds me. Besides, I'm sure you appreciate the break from IT once in a while?
A subpath in Zope terms is that part of a URL that comes after the script, method or whatever that's actually executed. Bear in mind that Zope is all about inheritance and object-orientedness, so if we have a script available at:
...and you can consider that the "part3" URL "inherits" myScript. Those extra parts (in bold) don't need to refer to actual directories[1]; they can be pretty much aribtrary. They're made available in the subpath element of the REQUEST object, and here's where that comes in handy.
If you point a browser at a URL that results in the contents of a file being returned, then the question arises of what the file name should be. HTTP allows the server to be specific about the type of the data that's sent, but there's facility to supply a suitable name. This makes sense; naming conventions are extremely varied across platforms, so there's no guarantee that a given name will be appropriate. Instead, what usually happens is that the browser deduces a name from the URL. And here problems may occur.
...which downloads a GIF file. There are browsers in existence[0] that will propose the filename downloadFile?customer=144876ab6&transaction=76yghj576xz7.gif, which is less than useful. The worst part is that the parameters to the request get added to the filename. The request could be made as a POST rather than a GET to avoid this, but there's still no way to specify the filename, meaning that all the files downloaded from this URL may end up with the same name. Not good, especially if they're being paid for and later ones overwrite previous ones.
The subpath trick, however, can be used in a couple of ways to work around this.
First, since the subpath is ignored by Zope, it can be used to suggest a filename when a POST request is made:
In Python terms, we need to look along the subpath and extract those parameters. Here's a suitable method to do it:
#Regular expression to spot parameters of the form = , where
#value may be empty.
paramRe = re.compile(r"(\w+)\s*=\s*(.*)")
def getParametersFromRequest(self):
"""Extract parameters from the subpath and return them in a dict."""
params = {}
#The subpath is a list of path elements; in other words, it's
#been split by '/' characters for us already.
for p in self.REQUEST.subpath:
#Check if it's a parameter.
m = paramRe.match(p)
if m:
#It is a match. group(1) is the identifier,
#group(2) is the value, which we strip.
params[m.group(1)] = m.group(2).strip()
return params
You can call this from any ExternalMethod or Script (Python), passing either self or the container respectively, and it'll return a dict of parameters.
[0] This is an issue that crops up a lot on mobile phone browsers, but wget shows it too. [1] This depends on what it is that you append the subpath to; it works for ExternalMethods, but other types of Zope object require the subdirectories to exist. Which is a pain.