Idea -- allow URLs to be specified hierarchically

14 views
Skip to first unread message

Adam Atlas

unread,
Jul 2, 2007, 1:38:14 PM7/2/07
to we...@googlegroups.com
As your URLs tuple (for web.request.handle) gets longer, it seems to
me that it would be useful to be able to specify things
hierarchically instead of completely as flat regexes. My proposal is
that we allow the second part of each regex/handler pair to be a list
(as distinguished from a string or tuple) of the same format of the
top-level tuple; this gets "flattened" into the parent by prepending
each regex with the first part of the pair in the parent. For
instance, I'm currently writing a little wiki to be a demo of various
web.py things. Here's what some of the URLs look like:

urls = (
'/', 'h_main_redirect',
'/wiki:register', 'h_register',
'/wiki:account', 'h_account',
'/wiki:login', 'h_login',
'/wiki:logout', 'h_logout',
'/wiki:recent-changes', 'h_recent_changes',
'/wiki:login', 'h_login',
'/wiki:logout', 'h_logout',
'/([^/]+)', 'h_page',
'/([^/]+)/history', 'h_history',
)

To make it less likely that there'll be mistakes, inconsistencies,
etc. and to save a little bit of typing, we could use this feature to
change it to something like this:

urls = (
'/', 'h_main_redirect',
'/wiki:', [
'register', 'h_register',
'account', 'h_account',
'login', 'h_login',
'logout', 'h_logout',
'recent-changes', 'h_recent_changes',
'login', 'h_login',
'logout', 'h_logout',
],
'/([^/]+)', [
'', 'h_page',
'/history', 'h_history',
],
)

This would be flattened into a tuple identical to the one given above.
Of course, it could be any number of levels deep.

PA

unread,
Jul 2, 2007, 2:38:39 PM7/2/07
to we...@googlegroups.com

On Jul 02, 2007, at 19:38, Adam Atlas wrote:

> As your URLs tuple (for web.request.handle) gets longer, it seems to
> me that it would be useful to be able to specify things
> hierarchically instead of completely as flat regexes.

Right on... one thing I would find useful would be to express an object
method call as a URL...

For example, one could construct a URL along these lines:

/[object]/[instance]/[method].[argument]/

E.g.:

/date/1999/12/31/editor/configuration.1

'/date' being the object
'/1999/12/31' the instance
'/editor' a method
'/configuration.1' another method with one argument

For illustration purpose, here is an implementation in Lua with does
this [1][2]:

-- first. one construct a so-called service
-- the first parameter is the object prefix, the root of a path
hierarchy
-- the second parameter is an object class, e.g. 'Date'
-- the third and fourth parameters are functions to translate an object
to a URL and vis-versa
local aService = HTTPService( '/date/', Date, toURL, toObject )

-- then, one registers the service with the HTTP engine
-- note that you only need to register the root of the path hierarchy
HTTP[ aService.pattern ] = aService()

Upon invocation, the service calls toObject to translate a URL to an
object instance (e.g. '/1999/12/31' -> aDate). Then it translates the
remaining of the path into a method invocation chain (e.g. GET
'/editor' -> getEditor() or POST '/editor' -> postEditor() ). Each
method invocation can have some optional, dot separated, arguments
(e.g. PUT '/configuration.1' -> putConfiguration( 1 ) ).

Anyway, just a thought :)

Cheers,

PA.

[1] http://dev.alt.textdrive.com/browser/HTTP/HTTP.lua#L435
[2] http://dev.alt.textdrive.com/browser/HTTP/HTTPExtra.lua#L432

Tommi

unread,
Jul 2, 2007, 2:47:52 PM7/2/07
to web.py
Doesn't

(
'wiki:(.*)', 'handler.\1'
)

go pretty far along?

bubblboy

unread,
Jul 2, 2007, 3:11:20 PM7/2/07
to we...@googlegroups.com

Well, not if you only want to match a few words and not every possible
resource starting with "wiki:". In that case you would have to use something
like "wiki:((?:foo)|(?:bar))$", assuming your handlers even have the same
names in the first place (not possible when you want to use non-alphanumerical
characters and the like).

Anyway, in reply to Adam: I am not sure if this will actually make it look
cleaner. Also, I doubt adding nested lists automatically makes it "less error
prone". I am not sure if this is worth it—I like how webpy is small and only
has the absolutely necessary features. Then again, maybe that is just me.
Maybe you could provide (and maintain) a patch for people who are interested?

I am undecided.

b^4

Message has been deleted

Tzury

unread,
Jul 2, 2007, 10:36:44 PM7/2/07
to web.py
This is what I am doing in my apps:
in code.py I specify only the top level mapping such as:

urls = (
'/admin.*', 'admin.controller.parse',
'/ajax.*' , 'ajax.controller.parse',
)

Now, within each 'controller.parse' I parse the path again and act
accordingly.
With this approach I gain a clean, small-sliced and readable code ---
as I love.

This is an example for ajax.controller.parse (which has a switch-like
technique as well):


class parse:

def GET(self):

json_res = ""
self.url = web.ctx.path
params = web.input()

switch = {
".*/ajax/sync": self.sync,
".*/ajax/helloworld" : self.helloworld,
".*/ajax/vext/add" : self.users_add_vext,
".*/ajax/vext/delete" : self.users_delete_vext,
".*/ajax/ddi/add" : self.users_add_ddi,
".*/ajax/ddi/delete" : self.users_delete_ddi,
".*/ajax/groups/add/": self.groups_add,
".*/ajax/groups/del/": self.groups_del
}

for knownurl in switch:
if re.match(knownurl, self.url):
json_res = switch[knownurl](params)
break

web.header("Content-Type","X-JSON")
print json_res

Aaron Swartz

unread,
Jul 5, 2007, 1:02:28 PM7/5/07
to we...@googlegroups.com
I'm OK with this. Feel free to file a bug.
Reply all
Reply to author
Forward
0 new messages