Discussion:
RFC: Proposal for URL dispatching / routing in CGI::App
Mark Stosberg
2005-12-04 18:51:41 UTC
Permalink
Hello,

I've posted my thoughts on a proposed design for URL dispatching
in CGI::Application (which is different than my idea last week!).

http://cgiapp.erlbaum.net/?DispatchDesign

I'd appreciate your feedback on it, or feel free to update the document
appropriately directly.

This functionality is in the spirit of what "CGI::Application::Dispatch"
does now, but proposes an expanded scope of functionality.

Not that we don't actually have to all agree on how dispatching should
work, since it's possible to have more than system for this.

Thanks,

Mark
--
http://mark.stosberg.com/


---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/cgiapp-***@public.gmane.org/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: cgiapp-unsubscribe-***@public.gmane.org
For additional commands, e-mail: cgiapp-help-***@public.gmane.org
Mark Stosberg
2005-12-08 01:38:22 UTC
Permalink
Post by Mark Stosberg
Hello,
I've posted my thoughts on a proposed design for URL dispatching
in CGI::Application (which is different than my idea last week!).
http://cgiapp.erlbaum.net/?DispatchDesign
I'd appreciate your feedback on it, or feel free to update the document
appropriately directly.
This functionality is in the spirit of what "CGI::Application::Dispatch"
does now, but proposes an expanded scope of functionality.
Not that we don't actually have to all agree on how dispatching should
work, since it's possible to have more than system for this.
Again, the correct URL is http://www.cgi-app.org/?DispatchDesign

Also, please remember that responding to RFCs give you one extra vote
when voting for a new CGI::App name. Extra votes will not be rewarded if
you respond to you own RFC, live in Tennesse or Utah, or where
otherwise prohibited by law. Thank You.

I've now updated the document with a couple additional bits I think
we'll need:

"args_to_new" -- to provide additional args you may want to pass to
new() in each case, such as a TMPL_PATH.

"global_args_to_new" -- for things you always want to pass to new(),
such as the location of a config file.

Other feedback? Anyone interested in writing the code for this?
(I was hoping to get out of that part of it... )

Mark
--
http://mark.stosberg.com/


---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/cgiapp-***@public.gmane.org/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: cgiapp-unsubscribe-***@public.gmane.org
For additional commands, e-mail: cgiapp-help-***@public.gmane.org
Michael Graham
2005-12-08 08:13:59 UTC
Permalink
Post by Mark Stosberg
Post by Mark Stosberg
Not that we don't actually have to all agree on how dispatching should
work, since it's possible to have more than system for this.
Again, the correct URL is http://www.cgi-app.org/?DispatchDesign
Also, please remember that responding to RFCs give you one extra vote
when voting for a new CGI::App name.
Yay! Four votes for me!

I like your dispatch proposal quite a lot, and I also agree with all of
Shawn's comments on the wiki. This module would certainly clean up the
dispatch code I'm using at work. For fun I tried rewriting my dispatch
table using the syntax you proposed, and its a lot cleaner. But it also
led to all the feature requests I put on the wiki :)
Post by Mark Stosberg
Other feedback? Anyone interested in writing the code for this?
(I was hoping to get out of that part of it... )
I have a feeling this is going to be a tricky module to write, because
when an URL matches multiple targets, the system has to choose the best
match. Static strings should be preferred against variable matches, and
maybe longer matches are considered more precise? (That's how
Config::Context does it anyway.)

For instance, with the URL /admin/users/edit, given the following
dispatch table, the fourth mapping should probably win because it
matches the longest static substring.

1. :app/:rm/:id => { }
2. admin/:app/:extra => { }
3. admin/:rm/:id => { app => AdminSystem }
4. admin/users/:rm => { app => UserAdmin }

(And at the same time, the system has to be smart enough to complain
that mappings 2 and 3 are equivalent.)

And then the same problem exists in reverse, when you try to implement
to_uri(). Given the following call:

$self->to_uri('app' => 'UserAdmin', rm => "edit", id => 23 );

and based on the above mapping table, you could end up with two URLs:

A. /UserAdmin/edit/23 (from map #1)
B. /admin/users/edit?id=23 (from map #4)

Which is the "correct" URL? URL B uses the most precise match (longer
static string), but URL A uses fewer query parameters and makes a
shorter, neater URL.

Of course, maybe the Rails people have already solved the algorithms to
do these things?


Michael


---
Michael Graham <***@the-wire.com>


---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/***@lists.erlbaum.net/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: cgiapp-***@lists.erlbaum.net
For additional commands, e-mail: cgiapp-***@lists.erlbaum.net
David Emery
2005-12-08 08:42:34 UTC
Permalink
Hi,

Wish I had more time to participate in this one, but here's my quick 2
cents, just so I can get a double vote later on the colour of the
shed. (Chapeau, Boshi, Beanie, Yarmulka, Helmet ...)

I think this is basically the old REST thread revived, with the "cool
URLs" idea looking to me like REST thang with a milder flavor of
koolaid. Though I haven't had time to read through it thoroughly.
Post by Michael Graham
I have a feeling this is going to be a tricky module to write, because
when an URL matches multiple targets, the system has to choose the best
match. Static strings should be preferred against variable matches, and
maybe longer matches are considered more precise? (That's how
Config::Context does it anyway.)
I suggest using whichever match comes first in the dispatch list. That
way it's easy to understand and control, no?


Dave
Post by Michael Graham
For instance, with the URL /admin/users/edit, given the following
dispatch table, the fourth mapping should probably win because it
matches the longest static substring.
1. :app/:rm/:id => { }
2. admin/:app/:extra => { }
3. admin/:rm/:id => { app => AdminSystem }
4. admin/users/:rm => { app => UserAdmin }
(And at the same time, the system has to be smart enough to complain
that mappings 2 and 3 are equivalent.)
And then the same problem exists in reverse, when you try to implement
$self->to_uri('app' => 'UserAdmin', rm => "edit", id => 23 );
A. /UserAdmin/edit/23 (from map #1)
B. /admin/users/edit?id=23 (from map #4)
Which is the "correct" URL? URL B uses the most precise match (longer
static string), but URL A uses fewer query parameters and makes a
shorter, neater URL.
Of course, maybe the Rails people have already solved the algorithms to
do these things?
Michael
---
---------------------------------------------------------------------
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/***@lists.erlbaum.net/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: cgiapp-***@lists.erlbaum.net
For additional commands, e-mail: cgiapp-***@lists.erlbaum.net
Webmaster Techcode.NET
2005-12-08 13:58:07 UTC
Permalink
Hello,

----- Original Message -----
Post by David Emery
I suggest using whichever match comes first in the dispatch list. That
way it's easy to understand and control, no?
Dave
I agree with Dave's point.

Things would be easier to code - and easier to understand from "users" point
of view.

But I'm a bit lost on the point on this - the only benefit I see compared to doing this by
just .htaccess/mod_rewrite (which you need to use anyway) - is that you can generate
the links [ such as: url_for( controller => 'Blog', rm => 'recent' ); ]


Anyway in the nature of true (lazy) programmers I'm also interested in a solution that would enable
you to work the magic without specifying the dispatch map. Say similar to AutoRunmode module ...

In a similar way as the Dispatch modules works (first part is module, second is runmode/method).
We could just stuff the rest of the params inside url as matching name value ...

==== Sample ====

www.site.com/Module/Method/param_name/10 or www.site.com/Module/Method/param_name=10

Would dispatch to Module (include some prefix if applicable), call it's Method sub, and set param_name to 10 ...

==== Sample ====

At present I use a combination of .htaccess and Dispatch module/plugin. And I send all url's that end in .perl to the
Dispatcher. I also have a function (in Page.pm called display) that I use to process templates that do not contain
any code behind them - but still need some processing to include header/footer or similar.

== In .htaccess file ==

RewriteEngine On
RewriteBase /
RewriteRule ^(.+)(\.perl)$ /index.pl/$1 [L]
RewriteRule ^(.+)(\.dhtml)$ /index.pl/Page/display/?page=$1.dwt [L]

== In .htaccess file ==

Of course I build my url's
Mark Stosberg
2005-12-08 18:13:45 UTC
Permalink
Post by Webmaster Techcode.NET
But I'm a bit lost on the point on this - the only benefit I see
compared to doing this by just .htaccess/mod_rewrite (which you need
url_for( controller => 'Blog', rm => 'recent' ); ]
You don't need mod_rewrite, it just helps send everything through the
dispatcher. Without out all the URLs could go through a script that
might be

/dp.cgi/app/rm/42

Instead of

/app/rm/42

Also, there is increased portability without a mod_rewrite/Apache dependence.

Finally, we should underestimate the developer usability of writing
dispatching in /Perl/ rather than mod_rewrite voodoo.

For me, working with mod_rewrite is in the same realm as editting
procmail syntax... I only do it when I have to, and usually with a
reference handy.
Post by Webmaster Techcode.NET
Anyway in the nature of true (lazy) programmers I'm also interested in
a solution that would enable you to work the magic without specifying
the dispatch map. Say similar to AutoRunmode module ...
Rails already handles this idea. You simply start with a generic map:

":app/:rm/:id"

And then add exceptions when you need them.
Post by Webmaster Techcode.NET
In a similar way as the Dispatch modules works (first part is module,
second is runmode/method). We could just stuff the rest of the params
inside url as matching name value ...
==== Sample ====
www.site.com/Module/Method/param_name/10 or
www.site.com/Module/Method/param_name=10
Would dispatch to Module (include some prefix if applicable), call
it's Method sub, and set param_name to 10 ...
No, thanks. That's what query strings are for.

The dispatch mapper does allow you to leave out query parameter names
from the URLs, but using that more than one two things can quickly lead
to ugly URLS

/foo/23/45/452

( Putting dates an URLS an exception, as we are trained to see that pattern. )

If you want to put names *and* values in the URL than that's what query
strings are for.


I have now integrated the comments from the wiki into the main design
document. I removed the comments that fully integrated, but I left two
of Shawn's because I'm not sure my responses would fully address the
concerns.

Here's what I said:

=== More notes about "requirements"

Without requirements, the pattern ":year/:month/:day" could just as well match
"posts/show/10". With no requirements you either have to match on a fixed
string, or assume any characteres as a URL bit. requirements are not meant to
fully validate the URL bits. It is simply there to allow to provide
distinctions based on patterns to complete more flexible routing schemes
without having longer URLs.

It's not essential feature to have for v1.0 and may be something we can live
without.


=== More about setting "value => undef"

Given a pattern like this:

':year/:month/:day'

We need to know whether ":month" and ":day" are optional or required. In other
words, should this work?

':year/'

To make the distinction, we either need to make some fields as optional, or
some as required.

Here we follow Rails precedent of defaulting to required, and being explicit
about being optional. Think of it as defaulting to "use strict" for URL
patterns.


Mark


---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/cgiapp-***@public.gmane.org/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: cgiapp-unsubscribe-***@public.gmane.org
For additional commands, e-mail: cgiapp-help-***@public.gmane.org
Michael Graham
2005-12-08 19:34:52 UTC
Permalink
Post by Mark Stosberg
=== More notes about "requirements"
Without requirements, the pattern ":year/:month/:day" could just as well match
"posts/show/10". With no requirements you either have to match on a fixed
string, or assume any characteres as a URL bit. requirements are not meant to
fully validate the URL bits. It is simply there to allow to provide
distinctions based on patterns to complete more flexible routing schemes
without having longer URLs.
It's not essential feature to have for v1.0 and may be something we can live
without.
Yeah, I can see how pattern matching can assist in routing. I guess
that what bothers me about requirements is that (a) it looks like
validation/untainting (which it's not supposed to be), and (b) it puts
additional matching logic on the right hand side (which in my head is
sort of for 'match results').

How about this instead?

:year:(\d{4})/:day:(\d{1,2}/:month:(\d{1,2})

Sure it's ugly, but at least the matching logic is all in one place.
Plus hopefully its ugliness discourages abuse. We can even allow multi-
line commented maps (after a fashion):


':year:(\d{4})', # year, e.g. 9008
'/',
':day:(\d{1,2}', # day, e.g. 99
'/',
':month:(\d{1,2})', # month, e.g. 72

=> { app => 'Blog' rm => 'by_date' },

(Hey, when I formatted it like that, I fixed a bug in my sample code!)

And without comments we can get rid of a little bit of line noise:

':year:(\d{4})
/
:day:(\d{1,2}
/
:month:(\d{1,2})' => { app => 'Blog' rm => 'by_date' },


We could try parsing the comments ourselves, but that way leads to
madness and despair...
Post by Mark Stosberg
=== More about setting "value => undef"
':year/:month/:day'
We need to know whether ":month" and ":day" are optional or required. In other
words, should this work?
':year/'
I'm reading that as: should '/1999' work?

My reading is that it shouldn't match (with or without the requirements),
because it's missing slashes. However '/1999//' would be ambigous, at
least without requirements.

But if the idea is to provide more matching logic to the routing system,
then maybe a different syntax could be used for optional parameters?

':year/?month/?day'


After all, isn't one of Perl's superpowers the ability to solve problems
with punctuation?


Michael


---
Michael Graham <***@the-wire.com>


---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/***@lists.erlbaum.net/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: cgiapp-***@lists.erlbaum.net
For additional commands, e-mail: cgiapp-***@lists.erlbaum.net
Rob Kinyon
2005-12-08 19:46:33 UTC
Permalink
Post by Michael Graham
Yeah, I can see how pattern matching can assist in routing. I guess
that what bothers me about requirements is that (a) it looks like
validation/untainting (which it's not supposed to be), and (b) it puts
additional matching logic on the right hand side (which in my head is
sort of for 'match results').
How about this instead?
:year:(\d{4})/:day:(\d{1,2}/:month:(\d{1,2})
Sure it's ugly, but at least the matching logic is all in one place.
Plus hopefully its ugliness discourages abuse. We can even allow multi-
':year:(\d{4})', # year, e.g. 9008
'/',
':day:(\d{1,2}', # day, e.g. 99
'/',
':month:(\d{1,2})', # month, e.g. 72
=> { app => 'Blog' rm => 'by_date' },
(Hey, when I formatted it like that, I fixed a bug in my sample code!)
':year:(\d{4})
/
:day:(\d{1,2}
/
:month:(\d{1,2})' => { app => 'Blog' rm => 'by_date' },
We could try parsing the comments ourselves, but that way leads to
madness and despair...
Post by Mark Stosberg
=== More about setting "value => undef"
':year/:month/:day'
We need to know whether ":month" and ":day" are optional or required. In other
words, should this work?
':year/'
I'm reading that as: should '/1999' work?
My reading is that it shouldn't match (with or without the requirements),
because it's missing slashes. However '/1999//' would be ambigous, at
least without requirements.
Actually, the question is: Should /1999 be matchable by that routing
directive? I would say that provision should be made to allow that.
However, the restriction should be made that 1999//02 (to match all
the 2nd days of the month in 1999) should be banned. If you want to
specify the third place, you have to specify the second place.
Post by Michael Graham
But if the idea is to provide more matching logic to the routing system,
then maybe a different syntax could be used for optional parameters?
':year/?month/?day'
Maybe ... an alternative would be to specify defaults for them and
anything with a default is optional.

Rob

---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/***@lists.erlbaum.net/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: cgiapp-***@lists.erlbaum.net
For additional commands, e-mail: cgiapp-***@lists.erlbaum.net
Mark Stosberg
2005-12-08 20:55:12 UTC
Permalink
Post by Michael Graham
How about this instead?
:year:(\d{4})/:day:(\d{1,2}/:month:(\d{1,2})
That's OK, that's more like my original proposal (before I made the wiki
page). Django does something more like this. Here's some example of
their syntax:

(r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'news.views.article_detail'),
(r'^articles/(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d+)/$', 'news.views.article_detail'),

The first one, without the names, is just very ugly. Our syntax would at
least be slightly less noisy. I further simplified it by removing the
extra colons:

:year(\d{4})/:day(\d{1,2})/:month(\d{1,2})
Post by Michael Graham
Sure it's ugly, but at least the matching logic is all in one place.
Plus hopefully its ugliness discourages abuse. We can even allow multi-
':year:(\d{4})', # year, e.g. 9008
'/',
':day:(\d{1,2}', # day, e.g. 99
'/',
':month:(\d{1,2})', # month, e.g. 72
=> { app => 'Blog' rm => 'by_date' },
Hmm, maybe in v2.

<thinks more>

We could just make this a "qr" thingie, and get commenting like this for
free.

But that could be slightly confusing if we are using ":" and "?" in
special ways. I don't mind the verbose syntax for declaring something
is optional.
Post by Michael Graham
But if the idea is to provide more matching logic to the routing system,
then maybe a different syntax could be used for optional parameters?
':year/?month/?day'
This would be OK too, although the question mark could begin to be
confused with the beginning of a query string in this case.
Post by Michael Graham
After all, isn't one of Perl's superpowers the ability to solve problems
with punctuation?
Yes. Punctuation is also Perl's kryptonite, so we need to be careful.

Mark


---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/cgiapp-***@public.gmane.org/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: cgiapp-unsubscribe-***@public.gmane.org
For additional commands, e-mail: cgiapp-help-***@public.gmane.org
Rhesa Rozendaal
2005-12-08 21:16:56 UTC
Permalink
Ok, now that you all have had time to play with this, please explain why this
is less difficult and unwieldy than mod_rewrite.

Seriously.

Another question: how is this at all relevant for cgiapp? Why should my apps
care about urls? All they need to know is that input comes through
$self->query->param, and output goes through $outputref in cgiapp_postrun.

Thirdly: Links belong in my templates, not in my app, so I have no business
knowing how to generate them.

Quarto: If the idea behind pretty urls is hiding the implementation details,
then the dispatcher should be decoupled from the app as much as possible too.
It should not need to know whether the app is RoR, Struts, Catalyst, or a
plain shell script. And we already have that in the form of mod_rewrite(*).

Why is every framework reinventing the same wheel over and over again?

Rhesa

(*) Web servers other than Apache better have something comparable...
I know that IIS doesn't, but then again, it doesn't handle path_info either.
Post by Mark Stosberg
Post by Michael Graham
How about this instead?
:year:(\d{4})/:day:(\d{1,2}/:month:(\d{1,2})
That's OK, that's more like my original proposal (before I made the wiki
page). Django does something more like this. Here's some example of
(r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'news.views.article_detail'),
(r'^articles/(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d+)/$', 'news.views.article_detail'),
The first one, without the names, is just very ugly. Our syntax would at
least be slightly less noisy. I further simplified it by removing the
:year(\d{4})/:day(\d{1,2})/:month(\d{1,2})
Post by Michael Graham
Sure it's ugly, but at least the matching logic is all in one place.
Plus hopefully its ugliness discourages abuse. We can even allow multi-
':year:(\d{4})', # year, e.g. 9008
'/',
':day:(\d{1,2}', # day, e.g. 99
'/',
':month:(\d{1,2})', # month, e.g. 72
=> { app => 'Blog' rm => 'by_date' },
Hmm, maybe in v2.
<thinks more>
We could just make this a "qr" thingie, and get commenting like this for
free.
But that could be slightly confusing if we are using ":" and "?" in
special ways. I don't mind the verbose syntax for declaring something
is optional.
Post by Michael Graham
But if the idea is to provide more matching logic to the routing system,
then maybe a different syntax could be used for optional parameters?
':year/?month/?day'
This would be OK too, although the question mark could begin to be
confused with the beginning of a query string in this case.
Post by Michael Graham
After all, isn't one of Perl's superpowers the ability to solve problems
with punctuation?
Yes. Punctuation is also Perl's kryptonite, so we need to be careful.
Mark
---------------------------------------------------------------------
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/***@lists.erlbaum.net/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: cgiapp-***@lists.erlbaum.net
For additional commands, e-mail: cgiapp-***@lists.erlbaum.net
Ron Savage
2005-12-08 21:50:41 UTC
Permalink
On Thu, 08 Dec 2005 22:16:56 +0100, Rhesa Rozendaal wrote:

Hi Rhese
Post by Rhesa Rozendaal
Ok, now that you all have had time to play with this, please
explain why this is less difficult and unwieldy than mod_rewrite.
Yes, it's getting ridiculous.
Post by Rhesa Rozendaal
Another question: how is this at all relevant for cgiapp? Why
It's separate, surely.

[snip great criticism of creeping featureitis]
Post by Rhesa Rozendaal
Post by Michael Graham
:year:(\d{4})/:day:(\d{1,2}/:month:(\d{1,2})
Actually, this is constraining the input, right? Ideas are getting mixed up,
here.
--
Cheers
Ron Savage, ***@savage.net.au on 9/12/2005
http://savage.net.au/index.html
Let the record show: Microsoft is not an Australian company



---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/***@lists.erlbaum.net/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: cgiapp-***@lists.erlbaum.net
For additional commands, e-mail: cgiapp-***@lists.erlbaum.net
Dan Horne
2005-12-08 22:02:35 UTC
Permalink
From: Rhesa Rozendaal
Thirdly: Links belong in my templates, not in my app, so I
have no business knowing how to generate them.
But in my application, the links belong in my apps, and the designers don't
know how to generate them.

For example - in my full text searches, the designers simply put <tmpl_var
prev> <tmpl_var next> at the bottom of the paginated results. They don't
need to know about offsets, results per page, keywords etc. Likwise, all
menu items, links etc are generated automatically. If a file is available
for download, <tmpl_var file> suffices. Now you can argue that this means
the app knows too much about the links, but in my case, the burden of
maintaining these links is removed from the designers (who are not
technical) and this allows them to rapidly knock up new templates and sites
without gettng bamboozled by details that they don't care about...

Personally, I'd like everything to be self-contained in the application
layer. mod_rewrite is a pain, because I don't always have access to another
administrator's Apache conf. And if the URL format needs updating with extra
parameters etc, I don't need to hunt around every Apache conf file on the
sites that have the app installed - I just want to supply the latest version
of the app.

Dan


---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/***@lists.erlbaum.net/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: cgiapp-***@lists.erlbaum.net
For additional commands, e-mail: cgiapp-***@lists.erlbaum.net
Ron Savage
2005-12-08 22:53:19 UTC
Permalink
On Fri, 9 Dec 2005 11:02:35 +1300, Dan Horne wrote:

Hi Dan
Post by Dan Horne
Post by Rhesa Rozendaal
Thirdly: Links belong in my templates, not in my app, so I have
no business knowing how to generate them.
But in my application, the links belong in my apps, and the
designers don't know how to generate them.
Exactly. It's impossible that one way-of-doing-things will fit every situation.
Hence the inevitable complexity...
--
Ron Savage
***@savage.net.au
http://savage.net.au/index.html



---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/***@lists.erlbaum.net/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: cgiapp-***@lists.erlbaum.net
For additional commands, e-mail: cgiapp-***@lists.erlbaum.net
Michael Graham
2005-12-09 20:36:34 UTC
Permalink
Post by Rhesa Rozendaal
Ok, now that you all have had time to play with this, please explain why this
is less difficult and unwieldy than mod_rewrite.
Okay, that's a fair comment. If the original goal was to make the
dispatch routes clear and free of line noise, then adding regexes to
them is probably not helpful.
Post by Rhesa Rozendaal
Thirdly: Links belong in my templates, not in my app, so I have no business
knowing how to generate them.
I agree with Dan Horne's remark later in this thread. Links are
positioned and styled and worded in the templates, but if an URL is
essentially a piece of code, why should it be constructed by the
designer?
Post by Rhesa Rozendaal
Quarto: If the idea behind pretty urls is hiding the implementation details,
then the dispatcher should be decoupled from the app as much as possible too.
It should not need to know whether the app is RoR, Struts, Catalyst, or a
plain shell script. And we already have that in the form of mod_rewrite(*).
I think this is a noble goal. And if we leave aside the link
generation side of things for a moment, maybe it's possible to achieve
this with mod_rewrite alone. I'm not very familiar with mod_rewrite, so
maybe it would meet my needs. Here's a dispatch table, using the
proposed syntax:

'arch/:path' => { app => 'Blog::Archive' },
'admin/tmpl_edit/:path' => { app => 'Blog::Admin::Tmpl_Editor' },

'admin/:controller/:rm' => { prefix => 'Blog::Admin' },
':controller/:rm' => { prefix => 'Blog::' },

This would dispatch the following example URLs as follows:

/arch/foo/bar.html => Blog::Arch (path = /foo/bar.html)
/arch/other.html => Blog::Arch (path = /other.html)
/admin/users/edit => Blog::Admin::Users (rm = edit)
/admin/users/edit_process => Blog::Admin::Users (rm = edit_process)
/comment/add => Blog::Comment (rm = add)
/admin/tmpl_edit/a.html => Blog::Admin::Tmpl_Editor (path = /a.html)


How would this be done with mod_rewrite? Without knowing too much about
rewrite, I can see a few immediate challenges:

* how to dispatch directly to Perl C::A modules without using an
intermediate CGI script for each app

* how to handle capitalization of module names (tmpl_editor vs.
Tmpl_Editor)


Finally, one of the things I do at work is share the same codebase
amongst multiple sites. So 'Blog::Admin::Foo' might actually be
transformed into 'Site1::Blog::Admin::Foo' or 'Site9::Blog::Admin::Foo'.

These classes are generated dynamically at request time if they don't
already exist, using something like this:

@Site1::Blog::Admin::Foo::ISA = ('Common::Blog::Admin::Foo');

This allows me to add site-specific behaviour on a case-by-case basis by
dropping in a subclass for a specific app. But for the most part, the
app directory for most sites is empty.

I have a feeling that if I wanted to use mod_rewrite I would end up
writing a dispatch.cgi anyways, except instead of dispatching based on
the contents of PATH_INFO, it would dispatch based on the contents of
the CGI $query.


Michael


---
Michael Graham <***@the-wire.com>


---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/***@lists.erlbaum.net/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: cgiapp-***@lists.erlbaum.net
For additional commands, e-mail: cgiapp-***@lists.erlbaum.net
Mark Stosberg
2005-12-10 02:47:42 UTC
Permalink
Post by Rhesa Rozendaal
Ok, now that you all have had time to play with this, please explain why this
is less difficult and unwieldy than mod_rewrite.
Seriously.
Another question: how is this at all relevant for cgiapp? Why should my apps
care about urls? All they need to know is that input comes through
$self->query->param, and output goes through $outputref in cgiapp_postrun.
Thirdly: Links belong in my templates, not in my app, so I have no business
knowing how to generate them.
Traditionally, web applications got all their variables in URLS through
query strings.

Jesse was the first person I recall advocating something different:
putting the run mode in PATH_INFO. This made a lot of sense because it
seperated the /state/ of the application from the rest of the form data
being transmitted. Later, processing a run mode this way became a
built-in feature of CGI::Application.

I've seen a lot of CGI::App based websites using this "script.cgi/rm"
style. Although it's rather useful, I hadn't see this much on on
websites outside of CGI::Application.

I think CGI::App users used this because it was *easy*, as well as
providing value.

Now I see that nearly all Rails apps seem to be using the
:controller/:action/:id model.

It seems clean and useful, yet I don't see it much outside of Rails.

mod_rewrite has been around for ages as a known technology, yet I can
no popular standard mod_rewrite solutions that are being used to solve
this problem. Drupal uses a bit of mod_rewrite as part of standard
setups, but only enough to pass everything to Drupal's own dispatcher.

I believe the difference in Rail's success of having clean URLs (versus
mod_rewrite verus The World) is that they made it *easy* and *standard*.

In our own system, I foresee a helper script that would set up standard
bits for a website:

$cape newsite .

Adding Scaffolding...
www/cgi-bin/dispatch.cgi
www/.htaccess
config/dispatch.pl
config/Config.pl
perllib/
t/pod.t

While this is just a sketch, it gives you idea that right off the bat,
you could be starting with a .htaccess file that filters everything to a
dispatch script, and all you have to do is edit a configuration file,
using Perl, a tool you already know well.

Without the Apache requirement, it becomes easier for people to work
offline one laptops-- people like the built-in server in Catalyst for
this reason.
Post by Rhesa Rozendaal
Why is every framework reinventing the same wheel over and over again?
The dispatcher being designer wouldn't have to be tied to CGI::App.
I imagine we can talk to equivalent of new() and run() in Catalyst.
Adapters for some other Perl-based frameworks could be made as well.

Mark
--
http://mark.stosberg.com/


---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/cgiapp-***@public.gmane.org/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: cgiapp-unsubscribe-***@public.gmane.org
For additional commands, e-mail: cgiapp-help-***@public.gmane.org
Mark Stosberg
2005-12-10 14:18:26 UTC
Permalink
Post by Rhesa Rozendaal
Ok, now that you all have had time to play with this, please explain why this
is less difficult and unwieldy than mod_rewrite.
Here's another strong, real world example of what our own dispatching
system could do.

Drupal has cool URLs. They use a standard 4 line .htaccess/mod_rewrite
file, and then send everything through their own dispatcher, creating
URLS like "node/30", which handle most content pages.

Well, that's sort of cool, but not memorable. So here's the kicker--
Anywhere I add or update a node, I can choose a URL alias for it. Not
only will the dispatcher understand this URL but /all internal/ links
will immediately start using the preferred URL, as if the other never
existed.

If you Google for "gimp image slicing", a page I put with Drupal quickly
appeared on the first page of results. I think is in part due to the URL
being "gimp_image_slicing" instead of "node/28".

However, not every link to a page will be generated by the application.
I create my own links when I add new content by typing in a textarea,
outside of app-space. I love that I can link to simple names I can
remember, like "use" "share" and "blog/mark/matt_switches_to_linux"
(instead of "node/32")

It's not just "neat", it allows you to use a Drupal to manage your site
and have decent human friendly URLs with little effort, instead of a
structure that screams "Hey! I'm run by CMS with URLS only a robot could
remember!"

With a decent dispatcher as a foundation, it would be an easier task to
create a sub-class which first looks up aliases in a database table
before making a final dispatch decision.
Post by Rhesa Rozendaal
Seriously.
Seriously. I don't think mod_rewrite could do that for us.

Mark
--
http://mark.stosberg.com/


---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/cgiapp-***@public.gmane.org/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: cgiapp-unsubscribe-***@public.gmane.org
For additional commands, e-mail: cgiapp-help-***@public.gmane.org
Michael Peters
2005-12-10 15:15:31 UTC
Permalink
Post by Michael Graham
Post by Mark Stosberg
=== More notes about "requirements"
Without requirements, the pattern ":year/:month/:day" could just as well match
"posts/show/10". With no requirements you either have to match on a fixed
string, or assume any characteres as a URL bit. requirements are not meant to
fully validate the URL bits. It is simply there to allow to provide
distinctions based on patterns to complete more flexible routing schemes
without having longer URLs.
It's not essential feature to have for v1.0 and may be something we can live
without.
Yeah, I can see how pattern matching can assist in routing. I guess
that what bothers me about requirements is that (a) it looks like
validation/untainting (which it's not supposed to be), and (b) it puts
additional matching logic on the right hand side (which in my head is
sort of for 'match results').
I'm not sure how flexible this needs to be. Thinking about it, I don't think
there will be a full url of "/1999/10/25" in a real site. It would probably look
more like "/article/view/1999/10/25".

So the default rule of "/:module/:rm/:id wouldn't match. The programmer would
probably use a rule of "/:module/:rm/:year/:month/:day", but even that is
probably too generic. It would probably be "/article/view/:year/:month/:day"
since the number of modules and run modes that can take a year/month/day combo
would be limited.
Post by Michael Graham
How about this instead?
:year:(\d{4})/:day:(\d{1,2}/:month:(\d{1,2})
Sure it's ugly
Sure is.
Post by Michael Graham
, but at least the matching logic is all in one place.
Plus hopefully its ugliness discourages abuse. We can even allow multi-
':year:(\d{4})', # year, e.g. 9008
'/',
':day:(\d{1,2}', # day, e.g. 99
'/',
':month:(\d{1,2})', # month, e.g. 72
=> { app => 'Blog' rm => 'by_date' },
Even uglier in my opinion.

[snip]
Post by Michael Graham
We could try parsing the comments ourselves, but that way leads to
madness and despair...
That's crazy talk! But seriously, I think we need to keep it as simple as
possible (I want to avoid having a dispatch parser that implements anything
close to a full grammar). All it needs to do is cover the majority of the cases
at first. As more and more users try it out and discover real-world use-cases
where it's not sufficient and then we can look at doing more.

But in all likelihood, I suspect that most people will be able to find a way to
get what they want with just a couple more rules added in.

Another thing I would like to see is to be able to have this dispatcher be able
to work as either a PerlTransHandler (to dispatch to .cgi scritps) or
PerlContentHandler (to dispatch straight to the module) under mod_perl.

Maybe the rules are specified in a separate module or even in the httpd.conf. So
whatever package implements this dispatch table would include a module or two to
act as the handler.
--
Michael Peters
Developer
Plus Three, LP



---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/***@lists.erlbaum.net/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: cgiapp-***@lists.erlbaum.net
For additional commands, e-mail: cgiapp-***@lists.erlbaum.net
Mark Stosberg
2005-12-10 15:59:59 UTC
Permalink
Post by Michael Peters
That's crazy talk! But seriously, I think we need to keep it as simple as
possible (I want to avoid having a dispatch parser that implements anything
close to a full grammar). All it needs to do is cover the majority of the cases
at first. As more and more users try it out and discover real-world use-cases
where it's not sufficient and then we can look at doing more.
My philosophy exactly. So let's take out all forms of pattern matching
out of the v1.0 design spec. We'll have several ideas to start from if
we want to extend it later.

I've updated the spec on the wiki with the following refinements:

- "requirements" is gone altogether.
- the "field => undef" syntax which as confusing is gone, replaced with
the ":field?/" syntax which was suggested.
- I removed Shawn's comments, since I felt they had been addressed.

I happy with the outcome and have the some sense we are ready to move
from design and implementation.

Final feedback?

Mark
--
http://mark.stosberg.com/


---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/cgiapp-***@public.gmane.org/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: cgiapp-unsubscribe-***@public.gmane.org
For additional commands, e-mail: cgiapp-help-***@public.gmane.org
Michael Peters
2005-12-10 16:46:27 UTC
Permalink
Post by Mark Stosberg
Post by Michael Peters
That's crazy talk! But seriously, I think we need to keep it as simple as
possible (I want to avoid having a dispatch parser that implements anything
close to a full grammar). All it needs to do is cover the majority of the cases
at first. As more and more users try it out and discover real-world use-cases
where it's not sufficient and then we can look at doing more.
My philosophy exactly. So let's take out all forms of pattern matching
out of the v1.0 design spec. We'll have several ideas to start from if
we want to extend it later.
- "requirements" is gone altogether.
- the "field => undef" syntax which as confusing is gone, replaced with
the ":field?/" syntax which was suggested.
How about "?field" instead. So a full pattern would be

articles/list/:year/?month/?day

instead of

articles/list/:year/:month?/:day?

Just 2 characters shorter. I don't know if that would be confusing since we're
used to seeing the '?' after the optional token in regexes.
Post by Mark Stosberg
I happy with the outcome and have the some sense we are ready to move
from design and implementation.
Final feedback?
So do we want this to be in CGI::Application::Dispatch? Maybe there's someway to
make it backwards compatible with what it currently does, since it's pretty
simple. Or we could break backwards compatability and go for a 2.x generation
and keep 1.x around... or have a separate module all together. Although
"CGI::Application::Dispatch" is the perfect name for this new functionality.
--
Michael Peters
Developer
Plus Three, LP


---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/***@lists.erlbaum.net/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: cgiapp-***@lists.erlbaum.net
For additional commands, e-mail: cgiapp-***@lists.erlbaum.net
David Emery
2005-12-10 17:39:31 UTC
Permalink
Post by Michael Peters
Post by Mark Stosberg
Post by Michael Peters
That's crazy talk! But seriously, I think we need to keep it as simple as
possible (I want to avoid having a dispatch parser that implements anything
close to a full grammar). All it needs to do is cover the majority of the cases
at first. As more and more users try it out and discover real-world use-cases
where it's not sufficient and then we can look at doing more.
My philosophy exactly. So let's take out all forms of pattern matching
out of the v1.0 design spec. We'll have several ideas to start from if
we want to extend it later.
- "requirements" is gone altogether.
- the "field => undef" syntax which as confusing is gone, replaced with
the ":field?/" syntax which was suggested.
How about "?field" instead. So a full pattern would be
articles/list/:year/?month/?day
instead of
articles/list/:year/:month?/:day?
Just 2 characters shorter. I don't know if that would be confusing since we're
used to seeing the '?' after the optional token in regexes.
Post by Mark Stosberg
I happy with the outcome and have the some sense we are ready to move
from design and implementation.
Final feedback?
Another quick 2 yen's worth...

It looks to me kind of like you're just reinventing a dumbed down
regex language. Why not just use normal Perl regexs? Besides not
having to remember another syntax, you've got pretty well every
conceivable case covered from the start. In most cases the regexes
will be really simple, but if you want to do something bizarre, you're
not limited to the scenarios envisioned by the developers, (making
simple things easy, difficult things possible, or however that goes)

Dave
Post by Michael Peters
So do we want this to be in CGI::Application::Dispatch? Maybe there's someway to
make it backwards compatible with what it currently does, since it's pretty
simple. Or we could break backwards compatability and go for a 2.x generation
and keep 1.x around... or have a separate module all together. Although
"CGI::Application::Dispatch" is the perfect name for this new functionality.
--
Michael Peters
Developer
Plus Three, LP
---------------------------------------------------------------------
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/***@lists.erlbaum.net/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: cgiapp-***@lists.erlbaum.net
For additional commands, e-mail: cgiapp-***@lists.erlbaum.net
Mark Stosberg
2005-12-10 18:02:47 UTC
Permalink
Post by David Emery
Post by Michael Peters
How about "?field" instead. So a full pattern would be
articles/list/:year/?month/?day
instead of
articles/list/:year/:month?/:day?
Just 2 characters shorter. I don't know if that would be confusing since we're
used to seeing the '?' after the optional token in regexes.
I find this confusing because in Perl REs, the question mark comes
/after/ the thing that is optional. I think removing the colons remove
clarity too, because it's less clear whether wether "month" is a string
or variable.
Post by David Emery
It looks to me kind of like you're just reinventing a dumbed down
regex language. Why not just use normal Perl regexs? Besides not
having to remember another syntax, you've got pretty well every
conceivable case covered from the start. In most cases the regexes
will be really simple, but if you want to do something bizarre, you're
not limited to the scenarios envisioned by the developers, (making
simple things easy, difficult things possible, or however that goes)
We started there. My first proposal looked like:

$self->dispatch([
qr{
/(?#rm) (\w+)
/(?#user) (\w+)
/(?#tags+) ([\w\+]+)
}x;
]);

Perl notably doesn't have named back references, which is what
I hacked around with (?#user). Full REs are uglier and seem
unnecessary, at least for an initial version.
Post by David Emery
Post by Michael Peters
So do we want this to be in CGI::Application::Dispatch?
Yes, if it can fit. I was intentional about not bringing it up in the
conversation, to avoid a sense we were constrained by its current
design.
Post by David Emery
Post by Michael Peters
Maybe there's someway to make it backwards compatible with what it
currently does, since it's pretty simple. Or we could break backwards
compatability and go for a 2.x generation and keep 1.x around... or
have a separate module all together. Although
"CGI::Application::Dispatch" is the perfect name for this new
functionality.
Would you be interested in working out how they might fit together?

It also might be fun to put the code in a public SCM system so others
can contribute easily. I prefer darcs, but using Jason Crome's SVN
server seems like an option that would go over well.

I should really give 'svk' another try now that some time has passed
anyway...

Mark
--
http://mark.stosberg.com/


---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/cgiapp-***@public.gmane.org/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: cgiapp-unsubscribe-***@public.gmane.org
For additional commands, e-mail: cgiapp-help-***@public.gmane.org
Timothy Appnel
2005-12-10 21:16:49 UTC
Permalink
I'm coming in late and trying to catch up on this. After reading this
entire thread I don't get a sense of consensus yet and have to wonder
what the rush is. If there is one thing you take away from this
message it's slow down and think this through ESPECIALLY if this is
going to be added into the core.

I have to agree with Ron about featurities and over-engineering (my
term). I'm big on doing the simplest thing possible that works. After
scanning this thread and the wiki page I get the sense that the scope
is too broad and ambitious which in my experience means it is likely
to fail. Even with all forms of pattern matching removed this still
seems like a bit much.

Let me come at this from a different direction. Is
CGI::Application::Dispatch so deficient that it needs to be scrapped
or receive a major overhaul? I liked it quite a bit (Nice work
Michael. :) because I believe that if you have long complex URLs
schemes to manage then you are doing something wrong. (That's my
RESTful leanings.) It always did right by me. Besides limitations are
fun and good for creativity. (A mantra of the 37 signals team I have
to concur with.)

Where is the discussion of what you can't do with
CGI::Application::Dispatch? Why these missing features are essential
(as opposed to nice to have). This isn't clear to me at all.

Anyway, these are my initial thoughts. I need to think about this a
bit more reading over the wiki page and some of its references. I
wanted to put these thoughts out there now since Mark is talking
about implementation already. Which brings me back to my first point
so I'll stop here.

<tim/>

---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/***@lists.erlbaum.net/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: cgiapp-***@lists.erlbaum.net
For additional commands, e-mail: cgiapp-***@lists.erlbaum.net
Mark Stosberg
2005-12-10 21:56:22 UTC
Permalink
Post by Timothy Appnel
I'm coming in late and trying to catch up on this. After reading this
entire thread I don't get a sense of consensus yet and have to wonder
what the rush is. If there is one thing you take away from this
message it's slow down and think this through ESPECIALLY if this is
going to be added into the core.
There is no need for this to be in the CGI::Application core module.
Which means there is less need to agree, since it will be easy to /not/
use or use an alternate. It's still nice to discuss to come up with the
best possible design.
Post by Timothy Appnel
I have to agree with Ron about featurities and over-engineering (my
term). I'm big on doing the simplest thing possible that works. After
scanning this thread and the wiki page I get the sense that the scope
is too broad and ambitious which in my experience means it is likely
to fail. Even with all forms of pattern matching removed this still
seems like a bit much.
Having removed general pattern matching, this is a more modest
proposal than what Rails, Django and Catalyst implement.
Post by Timothy Appnel
Let me come at this from a different direction. Is
CGI::Application::Dispatch so deficient that it needs to be scrapped
or receive a major overhaul? I liked it quite a bit (Nice work
Michael. :) because I believe that if you have long complex URLs
schemes to manage then you are doing something wrong. (That's my
RESTful leanings.) It always did right by me. Besides limitations are
fun and good for creativity. (A mantra of the 37 signals team I have
to concur with.)
Where is the discussion of what you can't do with
CGI::Application::Dispatch? Why these missing features are essential
(as opposed to nice to have). This isn't clear to me at all.
This is a good point to discuss how CGI::App::Dispatch fits into the
conversation.

- ::Dispatch doesn't handle the URL generation helper methods like
uri_for() and link_to(). (Not that these belong in a dispatching
module, but they are part of the bigger plan.)

- ::Dispatch doesn't handle "args_to_new", which is necessary to
completely replace an instance script.

- ::Dispatch doesn't handle parsing the URL for parameters. In the new
design you can specify ':year/:month/:day' and later easily access
the values from the URL in $self->param('year'), etc. Very handy.

Does ::Dispatch have a fatal flaw? No, that I can see. It seems like a
workable foundation.

Here's an attempt at merging the concepts together:

CGI::Application::Dispatch->dispatch(

# default prefix
PREFIX => 'MyApp',

# default args to new()
ARGS_TO_NEW => {
PARAMS => {
config_files => ['../../../config/Config.pl'],
}
},
TABLE => {
# Support the original Dispatch style
'bar' => 'Some::OtherName',

# plus the new proposal...
'date/:year/:month?/:day?' => {
app => 'Blog',
rm => 'by_date',
args_to_new => { TMPL_PATH = "events/" },
},

},
);

########################

Some nitpicks: I think it would clearer to have the "prefix" and
"args_to_new" wrapped in a defaults hash, as in the new proposal.
Also, I think "NS_PREFIX" is a little clearer than "PREFIX".

Mark


---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/cgiapp-***@public.gmane.org/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: cgiapp-unsubscribe-***@public.gmane.org
For additional commands, e-mail: cgiapp-help-***@public.gmane.org
Timothy Appnel
2005-12-11 16:56:21 UTC
Permalink
Post by Mark Stosberg
- ::Dispatch doesn't handle the URL generation helper methods like
uri_for() and link_to(). (Not that these belong in a dispatching
module, but they are part of the bigger plan.)
Fair enough. I think working out the other issues -- namely what the
dispatcher handles and how will define how these work. So for now...
Post by Mark Stosberg
- ::Dispatch doesn't handle "args_to_new", which is necessary to
completely replace an instance script.
The CGI::Application::Dispatch POD says "Any extra params to
dispatch() will be passed on to the new() method of the
CGI::Application module being called." I think this covers what you
are asking for. Correct?
Post by Mark Stosberg
- ::Dispatch doesn't handle parsing the URL for parameters. In the new
design you can specify ':year/:month/:day' and later easily access
the values from the URL in $self->param('year'), etc. Very handy.
While I agree that it is handy it seems like a lot has to happen to
avoid a little.

First I should say that I don't agree with how Rails is mixing action
(runmode) parameter validation and (presumably) error handling with
their dispatcher. I think your URI scheme should be sufficiently
unambiguous that the dispatcher shouldn't have to perform such
operations just to determine where to route a request.

If we are going to support such a thing then we should just support
regular expression matching and be done with it. My preference is to
tackle these other things first, release and see how things go before
returning to this.

Here is my scenario to how the dispatcher could work. Treat every path
as $app/$rm/@params. The dispatcher loads the $app and is defined
executes the run mode. The dispatcher would stash the remaining
elements (@params) for the run mode to optionally do something with.
The run mode would then assign, validate and handle errors.

To me this is a lot more straight forward and lightweight then
creating an entire syntax to perform these functions IF you need them.

Looking at the wiki page example dispatch table and trying to apply it
to CGI::Application::Dispatch I have a suggestion. Assigning an app
AND runmode to a key like this

'' => { app => 'blog', rm => 'recent'}
'posts' => { app => 'Blog', rm => 'posts' },

...could be handled in CGI:Application::Dispatch by permitting an
ARRAY reference to be assigned to a dispatch table key. Meaning...

'posts' => [ 'Blog', 'posts' ]

So here is an example of a dispatch call incorporating all of these things.

CGI::Application::Dispatch->dispatch(
PREFIX => 'MyApp',
DEFAULT => 'foo',
config_files => ['../../../config/Config.pl'],
TABLE => {
'bar' => 'Some::OtherName',
'foo' => [ 'Some::OtherName', 'run_mode' ],
},
);

Thoughts?

<tim/>
--
Timothy Appnel
http://www.timaoutloud.org/

---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/***@lists.erlbaum.net/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: cgiapp-***@lists.erlbaum.net
For additional commands, e-mail: cgiapp-***@lists.erlbaum.net
Mark Stosberg
2005-12-11 19:28:33 UTC
Permalink
Post by Timothy Appnel
The CGI::Application::Dispatch POD says "Any extra params to
dispatch() will be passed on to the new() method of the
CGI::Application module being called." I think this covers what you
are asking for. Correct?
Thanks. I had missed that. It would be helpful to add an example of that
the synopsis to make the functionality easier to discover.

This does handle the default args_to_new() case. I would still like
to be able to make exceptions for each module. I have started setting
different TMPL_PATH values in different instance scripts.
Post by Timothy Appnel
If we are going to support such a thing then we should just support
regular expression matching and be done with it. My preference is to
tackle these other things first, release and see how things go before
returning to this.
I wouldn't mind incremental updates here, although I am fond of the
proposed dispatch syntax.
Post by Timothy Appnel
Here is my scenario to how the dispatcher could work. Treat every path
executes the run mode. The dispatcher would stash the remaining
The run mode would then assign, validate and handle errors.
That's essentially what we already have now with @params being handled
as the query string.

One of the essential features is to provide a name for part of the URL
in the dispatcher, and than have easy access to that named parameter in
the run mode.

The "optional" versus "required" seems less important but nice.
Post by Timothy Appnel
To me this is a lot more straight forward and lightweight then
creating an entire syntax to perform these functions IF you need them.
You make it sound as if we creating a large and heavy syntax. We are
talking about two special characters:

":foo" indicates a named URL part named foo
"?" means the previous named param is optional.

Here: I went ahead and created a proof concept for parsing this,
including 7 tests:

http://mark.stosberg.com/perl/ca-dispatch.pl
Post by Timothy Appnel
CGI::Application::Dispatch->dispatch(
PREFIX => 'MyApp',
DEFAULT => 'foo',
config_files => ['../../../config/Config.pl'],
TABLE => {
'bar' => 'Some::OtherName',
'foo' => [ 'Some::OtherName', 'store' ],
},
);
This doesn't work for me because it doesn't cover the named the params.
It also removes the names in the hash, which added some clarity. It's
not so clear that the second element is a run mode name. (Especially
after I edited your example above to rename the run mode to something else
besides "run_mode" . :)

Stepping back, I want to say I'm satisfied with how this
design-by-consensus is going.

In designing a shared framework, we have a few options:

1. Bury our heads in the sand and ignore what other frameworks are
doing.

2. Blindly follow what other frameworks are doing because it seems to
work for them.

3. Visit the foreign lands the of other frameworks and critically review
the differences to decide what to keep, discard and change.

We clearly taking the third option.

Having been a part of formal consensus based decision making groups, I
can see that making decisions this way tends to take longer, but is more
likely to lead to results the group is satisfied with. (And yes, given
a large enough group, the model breaks down.)

Differences have been aired, but the tone has been respectful and I
think it's been a valuable process.

Mark
--
http://mark.stosberg.com/


---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/cgiapp-***@public.gmane.org/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: cgiapp-unsubscribe-***@public.gmane.org
For additional commands, e-mail: cgiapp-help-***@public.gmane.org
Timothy Appnel
2005-12-12 03:40:42 UTC
Permalink
Post by Mark Stosberg
as the query string.
I was thinking of something in the path_info that doesn't have a key
Post by Mark Stosberg
One of the essential features is to provide a name for part of the URL
in the dispatcher, and than have easy access to that named parameter in
the run mode.
Understood. How would this scenario handle naming conflicts -- there
is a form element named year and a path_info/dispatch parameter named
that. That wasn't discussed in the Rail documentation. The easy answer
is don't do that, but it should be stated.
Post by Mark Stosberg
You make it sound as if we creating a large and heavy syntax. We are
":foo" indicates a named URL part named foo
"?" means the previous named param is optional.
I get the feeling something is throwing me off that is clear and your
head. I think its mixing the param ordering with the prefix/key. Like
this scenario handle posts/:category and posts/:year/:month?/:day?. Is
it simply he who comes first wins meaning if category comes before
y/m/d that year alone will never work because category will intercept
it?

To say the syntax is heavy isn't accurate and I apologize if I gave
that impression. I'm thinking about all of the potential exceptions
you may need to handle or ways you could shoot yourself in the foot.

Perhaps seperating variable assignment from the prefix will clarify
the matter. The fact I have a problem is clear here:

TABLE => {
'posts' => {
app => "SomeModule',
params => ':year/:month?/:day?',
run_mode => 'date_archive'
},
'posts' => {
app => "SomeModule',
params => ':category',
run_mode => 'category_archive'
}
};

Basic Perl knowledge tells you this won't work because you have two
hash elements with the same key.

Slightly off topic: if a run_mode is not defined in a table mapping
element is the second path_info param automatically picked up as the
run mode or must that be defined in the variable assignment? In other
words given this...

'posts' => {
app => "SomeModule',
params => ':category',
}

Would /posts/view/news load SomeModule and call the view run mode
while assigning the value "news" to param('category')?
Post by Mark Stosberg
Post by Mark Stosberg
CGI::Application::Dispatch->dispatch(
PREFIX => 'MyApp',
DEFAULT => 'foo',
config_files => ['../../../config/Config.pl'],
TABLE => {
'bar' => 'Some::OtherName',
'foo' => [ 'Some::OtherName', 'store' ],
},
);
This doesn't work for me because it doesn't cover the named the params.
It also removes the names in the hash, which added some clarity. It's
not so clear that the second element is a run mode name. (Especially
after I edited your example above to rename the run mode to something else
besides "run_mode" . :)
I was trying to keep it as close to the existing
CGI::Application::Dispatch. Since I was only envision a second
optional param being added it seemed unnecessary to introduce a hash.
(I've been working with a few modules like XML::Writer lately that
follow such a convention.)
Post by Mark Stosberg
Differences have been aired, but the tone has been respectful and I
think it's been a valuable process.
Agreed.

<tim/>
--
Timothy Appnel
http://www.timaoutloud.org/

---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/***@lists.erlbaum.net/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: cgiapp-***@lists.erlbaum.net
For additional commands, e-mail: cgiapp-***@lists.erlbaum.net
Mark Stosberg
2005-12-12 04:37:50 UTC
Permalink
Post by Timothy Appnel
Post by Mark Stosberg
as the query string.
I was thinking of something in the path_info that doesn't have a key
For reference, Catalyst is a little more like this, although they put
the logic in run mode attributes, like this:

sub day : Regex('^(\d{4})/(\d\d?)$') {
my ( $self, $c, $year, $day ) = @_;

I like the centeralization, clarity and simplicity of where we are
headed as an alternative.
Post by Timothy Appnel
Post by Mark Stosberg
One of the essential features is to provide a name for part of the URL
in the dispatcher, and than have easy access to that named parameter in
the run mode.
Understood. How would this scenario handle naming conflicts -- there
is a form element named year and a path_info/dispatch parameter named
that. That wasn't discussed in the Rail documentation. The easy answer
is don't do that, but it should be stated.
Query params would be in $self->query->param();
Path info params would be in $self->param();
(I'd really like to /not/ add yet another param() system).
Post by Timothy Appnel
Post by Mark Stosberg
You make it sound as if we creating a large and heavy syntax. We are
":foo" indicates a named URL part named foo
"?" means the previous named param is optional.
I get the feeling something is throwing me off that is clear and your
head. I think its mixing the param ordering with the prefix/key. Like
this scenario handle posts/:category and posts/:year/:month?/:day?.
No, our simplified system wouldn't handle that. Rails handled it by
restricting that ":year" must be a 4 digit number number. The most
recent proposal on the wiki removed that feature. The workaround would
be be

posts/:category
posts/by_date/:year...

That works for me. I think if URLs are just a little bit more magical,
I'll be happy.
Post by Timothy Appnel
it simply he who comes first wins meaning if category comes before
y/m/d that year alone will never work because category will intercept
it?
It will be an array where "first match wins".
Post by Timothy Appnel
To say the syntax is heavy isn't accurate and I apologize if I gave
that impression. I'm thinking about all of the potential exceptions
you may need to handle or ways you could shoot yourself in the foot.
Perhaps seperating variable assignment from the prefix will clarify
TABLE => {
'posts' => {
app => "SomeModule',
params => ':year/:month?/:day?',
run_mode => 'date_archive'
},
'posts' => {
app => "SomeModule',
params => ':category',
run_mode => 'category_archive'
}
};
I think it's important that the url patterns by the key, because
logically we are mapping URLs to something else.
Post by Timothy Appnel
Basic Perl knowledge tells you this won't work because you have two
hash elements with the same key.
Slightly off topic: if a run_mode is not defined in a table mapping
element is the second path_info param automatically picked up as the
run mode or must that be defined in the variable assignment? In other
words given this...
'posts' => {
app => "SomeModule',
params => ':category',
}
Would /posts/view/news load SomeModule and call the view run mode
while assigning the value "news" to param('category')?
I think the "start_mode" would be used, unless there is other
"mode_param" processing going, which could possibly get the run mode
from PATH_INFO (a current feature).
Post by Timothy Appnel
I was trying to keep it as close to the existing
CGI::Application::Dispatch. Since I was only envision a second
optional param being added it seemed unnecessary to introduce a hash.
(I've been working with a few modules like XML::Writer lately that
follow such a convention.)
I can envision other cases where that would work, just like subroutines
that have only two parameters don't name them.

Mark
--
http://mark.stosberg.com/


---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/cgiapp-***@public.gmane.org/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: cgiapp-unsubscribe-***@public.gmane.org
For additional commands, e-mail: cgiapp-help-***@public.gmane.org
David Emery
2005-12-12 05:29:38 UTC
Permalink
Post by Mark Stosberg
Post by Timothy Appnel
Post by Mark Stosberg
as the query string.
I was thinking of something in the path_info that doesn't have a key
For reference, Catalyst is a little more like this, although they put
sub day : Regex('^(\d{4})/(\d\d?)$') {
I like the centeralization, clarity and simplicity of where we are
headed as an alternative.
REST::Application might be another reference worth checking out

http://search.cpan.org/~moconnor/REST-Application-0.01/Application.pm


My own homegrown, not-ready-for-general-consumption set-up uses some
code pillaged from REST::Application and looks like this to parse path
info and set run_mode and named params:

$self->param('runmode_map', {
qr!^/view/(\d+)! => ["rm_view", "item_id"],
qr!^/edit/(\d+)! =>{
GET => ["rm_edit", "item_id"],
POST => ["rm_edit_in", "item_id"],
},
qr!^/add/?! =>{
GET => ["rm_show_form"],
POST => ["rm_add_in"],
},
qr!^/search/?! =>{
GET => ["rm_search_form"],
POST => ["rm_search_in"],
},
qr!^/delete/(\d+)! => ["rm_delete", "item_id"],
qr!^/list/csv/?! => "rm_list_csv",
qr!^/list/?$! => "rm_list",
}
);


$self->mode_param( \&set_rm );

Excuse the lack of explanation (no time right now or for the next week
or so), but I think it's more or less self-explanatory. This is in my
app set-up rather than in dispatch, but I think the basic idea
applies.

Does this trigger any synapses for anyone?

Dave
Post by Mark Stosberg
Post by Timothy Appnel
Post by Mark Stosberg
One of the essential features is to provide a name for part of the URL
in the dispatcher, and than have easy access to that named parameter in
the run mode.
Understood. How would this scenario handle naming conflicts -- there
is a form element named year and a path_info/dispatch parameter named
that. That wasn't discussed in the Rail documentation. The easy answer
is don't do that, but it should be stated.
Query params would be in $self->query->param();
Path info params would be in $self->param();
(I'd really like to /not/ add yet another param() system).
Post by Timothy Appnel
Post by Mark Stosberg
You make it sound as if we creating a large and heavy syntax. We are
":foo" indicates a named URL part named foo
"?" means the previous named param is optional.
I get the feeling something is throwing me off that is clear and your
head. I think its mixing the param ordering with the prefix/key. Like
this scenario handle posts/:category and posts/:year/:month?/:day?.
No, our simplified system wouldn't handle that. Rails handled it by
restricting that ":year" must be a 4 digit number number. The most
recent proposal on the wiki removed that feature. The workaround would
be be
posts/:category
posts/by_date/:year...
That works for me. I think if URLs are just a little bit more magical,
I'll be happy.
Post by Timothy Appnel
it simply he who comes first wins meaning if category comes before
y/m/d that year alone will never work because category will intercept
it?
It will be an array where "first match wins".
Post by Timothy Appnel
To say the syntax is heavy isn't accurate and I apologize if I gave
that impression. I'm thinking about all of the potential exceptions
you may need to handle or ways you could shoot yourself in the foot.
Perhaps seperating variable assignment from the prefix will clarify
TABLE => {
'posts' => {
app => "SomeModule',
params => ':year/:month?/:day?',
run_mode => 'date_archive'
},
'posts' => {
app => "SomeModule',
params => ':category',
run_mode => 'category_archive'
}
};
I think it's important that the url patterns by the key, because
logically we are mapping URLs to something else.
Post by Timothy Appnel
Basic Perl knowledge tells you this won't work because you have two
hash elements with the same key.
Slightly off topic: if a run_mode is not defined in a table mapping
element is the second path_info param automatically picked up as the
run mode or must that be defined in the variable assignment? In other
words given this...
'posts' => {
app => "SomeModule',
params => ':category',
}
Would /posts/view/news load SomeModule and call the view run mode
while assigning the value "news" to param('category')?
I think the "start_mode" would be used, unless there is other
"mode_param" processing going, which could possibly get the run mode
from PATH_INFO (a current feature).
Post by Timothy Appnel
I was trying to keep it as close to the existing
CGI::Application::Dispatch. Since I was only envision a second
optional param being added it seemed unnecessary to introduce a hash.
(I've been working with a few modules like XML::Writer lately that
follow such a convention.)
I can envision other cases where that would work, just like subroutines
that have only two parameters don't name them.
Mark
--
http://mark.stosberg.com/
---------------------------------------------------------------------
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/***@lists.erlbaum.net/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: cgiapp-***@lists.erlbaum.net
For additional commands, e-mail: cgiapp-***@lists.erlbaum.net
Mark Stosberg
2005-12-13 00:31:57 UTC
Permalink
Post by David Emery
REST::Application might be another reference worth checking out
http://search.cpan.org/~moconnor/REST-Application-0.01/Application.pm
Definitely. Thanks for the reference. I added it the wiki page.

REST::Application uses a RE and arg passing syntax like Catalyst, but
uses a central dispatcher instead of subroutine attributes.

Mark
--
http://mark.stosberg.com/


---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/cgiapp-***@public.gmane.org/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: cgiapp-unsubscribe-***@public.gmane.org
For additional commands, e-mail: cgiapp-help-***@public.gmane.org
Michael Graham
2005-12-12 05:10:15 UTC
Permalink
Post by Timothy Appnel
Understood. How would this scenario handle naming conflicts -- there
is a form element named year and a path_info/dispatch parameter named
that. That wasn't discussed in the Rail documentation. The easy answer
is don't do that, but it should be stated.
Actually I don't think there will be a conflict, because the parameters
are accessed in different ways:

$self->param('year'); # from dispatch
$self->query->param('year'); # from POST
$self->query->url_param('year'); # from QUERY_STRING

...
Post by Timothy Appnel
Like this scenario handle posts/:category and posts/:year/:month?/:day?.
Is it simply he who comes first wins meaning if category comes before
y/m/d that year alone will never work because category will intercept
it?
Earlier on in this thread, I was speculating about how to disambiguate
between multiple matches, and I was quickly talked out of proposing any
kind of intelligent matching system (based on best match, longest match,
etc.). It's much, much simpler to make the first match win, and let the
programmer select an order that makes sense.

And you're right that if you have this mapping:

posts/:category
posts/:year/:month?/:day?

then the second one will never match. I suspect the system can be
designed to warn about mappings that can't be reached.
Post by Timothy Appnel
Perhaps seperating variable assignment from the prefix will clarify
TABLE => {
'posts' => {
app => "SomeModule',
params => ':year/:month?/:day?',
run_mode => 'date_archive'
},
'posts' => {
app => "SomeModule',
params => ':category',
run_mode => 'category_archive'
}
};
Basic Perl knowledge tells you this won't work because you have two
hash elements with the same key.
Ah! Thanks for this example! Something was bugging me about using
C::A's existing TABLE structure and I coudn't put my finger on it.

The TABLE structure won't work because it's a hashref. This is not so
much a problem because you can't have duplicates, but because you lose
the order of the entries. When that happens, you can no longer let the
first match win.

We need an array ref instead, something like:

DISPATCH => [
'posts/:category' => { app => 'Blog', rm => 'posts' },
':app/:rm/:id' => { app => 'Blog' },
],
Post by Timothy Appnel
Slightly off topic: if a run_mode is not defined in a table mapping
element is the second path_info param automatically picked up as the
run mode or must that be defined in the variable assignment? In other
words given this...
'posts' => {
app => "SomeModule',
params => ':category',
}
Would /posts/view/news load SomeModule and call the view run mode
while assigning the value "news" to param('category')?
I think the run mode should only be taken from path_info when explicitly
requested by the rule (e.g. /foo/:app/:rm ).

For most apps I want the run mode set, but every so often I have an
exception, e.g:

/get/path/to/file.html
/get/other/path/to/other/file.html

For an app like this, I don't want the run mode being set to 'path' or
'other'. And I also don't want to be forced to make my URLs
artificially longer by including a dummy run mode:

/get/view/path/to/file.html
/get/view/other_path/to/other_file.html


Michael


---
Michael Graham <***@the-wire.com>


---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/***@lists.erlbaum.net/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: cgiapp-***@lists.erlbaum.net
For additional commands, e-mail: cgiapp-***@lists.erlbaum.net
Timothy Appnel
2005-12-12 14:41:14 UTC
Permalink
Post by Michael Graham
I think the run mode should only be taken from path_info when explicitly
requested by the rule (e.g. /foo/:app/:rm ).
I guess my concern is how do you automate the selection of run mode in
the dispatcher if it can be anywhere (or not at all). is :rm a special
variable declaration or is each app module required to know something
about the dispatch table in order to select the right run mode? This
is an interesting question.
Post by Michael Graham
For most apps I want the run mode set, but every so often I have an
/get/path/to/file.html
/get/other/path/to/other/file.html
For an app like this, I don't want the run mode being set to 'path' or
'other'. And I also don't want to be forced to make my URLs
/get/view/path/to/file.html
/get/view/other_path/to/other_file.html
Sorry I'm not following what you mean here.

<tim/>

--
Timothy Appnel
http://www.timaoutloud.org/

---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/***@lists.erlbaum.net/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: cgiapp-***@lists.erlbaum.net
For additional commands, e-mail: cgiapp-***@lists.erlbaum.net
Michael Graham
2005-12-12 18:12:43 UTC
Permalink
Post by Timothy Appnel
Post by Michael Graham
I think the run mode should only be taken from path_info when explicitly
requested by the rule (e.g. /foo/:app/:rm ).
I guess my concern is how do you automate the selection of run mode in
the dispatcher if it can be anywhere (or not at all). is :rm a special
variable declaration or is each app module required to know something
about the dispatch table in order to select the right run mode? This
is an interesting question.
Yes, we've been assuming that :rm is a special placeholder name that
sets current_run_mode, not $self->param('rm').
Post by Timothy Appnel
Post by Michael Graham
For most apps I want the run mode set, but every so often I have an
/get/path/to/file.html
/get/other/path/to/other/file.html
For an app like this, I don't want the run mode being set to 'path' or
'other'. And I also don't want to be forced to make my URLs
/get/view/path/to/file.html
/get/view/other_path/to/other_file.html
Sorry I'm not following what you mean here.
You were asking whether run_modes should automatically be parsed from
URLs if they are left out of the dispatch parameters and I was
illustrating why that would be a Bad Idea (tm).

Obviously the URL /get/some/file/somewhere.htm wants $rm to be left
unset and $path to be set to '/some/file/somewhere.html'. It doesn't
want $rm set to 'some' and @params set to ('file', 'somewhere.html').

There are other reasons why it's a bad idea to *always* parse the run
mode from the URL (Rob pointed some out), but this is the reason that
hits home for me, since I actually have apps that work like this.


Michael



---
Michael Graham <***@the-wire.com>


---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/***@lists.erlbaum.net/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: cgiapp-***@lists.erlbaum.net
For additional commands, e-mail: cgiapp-***@lists.erlbaum.net
Rob Kinyon
2005-12-12 05:09:17 UTC
Permalink
Post by Timothy Appnel
First I should say that I don't agree with how Rails is mixing action
(runmode) parameter validation and (presumably) error handling with
their dispatcher. I think your URI scheme should be sufficiently
unambiguous that the dispatcher shouldn't have to perform such
operations just to determine where to route a request.
Rails doesn't do runmode parameter validation or error handling in the
parser. It does URL parsing to determine how to dispatch. If no
dispatch can be found, there's an optional error-handler you can
define.
Post by Timothy Appnel
If we are going to support such a thing then we should just support
regular expression matching and be done with it. My preference is to
tackle these other things first, release and see how things go before
returning to this.
I'm cool with that.
Post by Timothy Appnel
Here is my scenario to how the dispatcher could work. Treat every path
executes the run mode. The dispatcher would stash the remaining
The run mode would then assign, validate and handle errors.
To me this is a lot more straight forward and lightweight then
creating an entire syntax to perform these functions IF you need them.
A few things you don't seem to be considering:
* I don't want my runmode name in my URL.
- I want to leave refactoring as a possibility in the future
- I want to hide information from potential attackers
* I want to provide human-generatable URLs that map back to my
runmodes. For example, /report/<format>/<report_name>?a=1&b=2 would
map to My::App::Report::run() and the format doesn't get used until
the print() function which is defined in My::App::Base. How does your
system handle this?
* I want to provide /reports?/<format> which maps to My::App::Report::display()
Post by Timothy Appnel
CGI::Application::Dispatch->dispatch(
PREFIX => 'MyApp',
DEFAULT => 'foo',
config_files => ['../../../config/Config.pl'],
TABLE => {
'bar' => 'Some::OtherName',
'foo' => [ 'Some::OtherName', 'run_mode' ],
},
);
Thoughts?
Yeah - TABLE needs to be an array, not a hash.

Another thing - the reason for the pattern matches in Rails is so that
you can do something like:

/blog/:year => { :year => /\d+/ }
/blog/:user

Obviously, if you did :user first, you'd never match on :year. But,
that's your own damn fault for being stupid. No program can ever
account for the possible stupidity of its users without reducing the
actual capabilities that it provides.

Now, you can have an analyzer that will tell you "Cannot ever reach
such-and-such", kinda like the AST analyzers you have for compilers.
But, that should only be written when there's a sufficient need for
it.

Rob

---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/***@lists.erlbaum.net/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: cgiapp-***@lists.erlbaum.net
For additional commands, e-mail: cgiapp-***@lists.erlbaum.net
Timothy Appnel
2005-12-12 14:25:29 UTC
Permalink
Post by Rob Kinyon
Post by Timothy Appnel
Here is my scenario to how the dispatcher could work. Treat every path
executes the run mode. The dispatcher would stash the remaining
The run mode would then assign, validate and handle errors.
To me this is a lot more straight forward and lightweight then
creating an entire syntax to perform these functions IF you need them.
* I don't want my runmode name in my URL.
- I want to leave refactoring as a possibility in the future
- I want to hide information from potential attackers
* I want to provide human-generatable URLs that map back to my
runmodes. For example, /report/<format>/<report_name>?a=1&b=2 would
map to My::App::Report::run() and the format doesn't get used until
the print() function which is defined in My::App::Base. How does your
system handle this?
* I want to provide /reports?/<format> which maps to My::App::Report::display()
The addon to what you are commenting on is if a run mode was defined
in the dispatch table the run mode is NOT extracted from the URL. I
think we moved passed this suggestion though.
Post by Rob Kinyon
Yeah - TABLE needs to be an array, not a hash.
That was something that was carried over from how
CGI::Application::Dispatch currently operates. I agree that it will
have to change to an array reference to work as we are discussing.

<tim/>

--
Timothy Appnel
http://www.timaoutloud.org/

---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/***@lists.erlbaum.net/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: cgiapp-***@lists.erlbaum.net
For additional commands, e-mail: cgiapp-***@lists.erlbaum.net
Rob Kinyon
2005-12-12 14:41:08 UTC
Permalink
Post by Timothy Appnel
The addon to what you are commenting on is if a run mode was defined
in the dispatch table the run mode is NOT extracted from the URL. I
think we moved passed this suggestion though.
It's not a suggestion - it's the entire point. If you have the runmode
be part of the URL, then it's nothing more than a stupid way to do the
current dispatching process. The point is that you divorce the URL
from the runmode.

Rob

---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/***@lists.erlbaum.net/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: cgiapp-***@lists.erlbaum.net
For additional commands, e-mail: cgiapp-***@lists.erlbaum.net
Michael Graham
2005-12-10 23:04:59 UTC
Permalink
Post by Timothy Appnel
I'm coming in late and trying to catch up on this.
Welcome to the party!
Post by Timothy Appnel
Let me come at this from a different direction. Is
CGI::Application::Dispatch so deficient that it needs to be scrapped or
receive a major overhaul?
I use CGI::Application::Dispatch. I think it's great for what it does
and I don't want to criticize it. I especially think that Michael did a
good job in pushing the idea of using dispatching with CGI::Application
instead of always using one instance script per app.

I think when I've encountered limitations with CA::Dispatch, it is
because I've tried to get it to do things it wasn't designed for.

CA::Dispatch remains simple and easy to use, but my own subclass of it
is way too complex and arcane. It has evolved to the point that it is
several times the size of CA::Dispatch, and it now does all the URL
parsing itself. It is has essentially become a dispatcher on its
own.

A limitation I encountered with CA::Dispath is that it wants you to have
a single mapping policy for all the URLs on your site. Maybe this works
for some people? It didn't work well with what I was trying to achieve.

I wanted this fairly simple map:

/app/some_module/foo => MySite::Some::Module
(rm = foo)

/app/some_module => MySite::Some::Module
(rm = )

/app/admin/some_module/foo => MySite::Admin::Some::Module
(rm = foo)

/app/admin/some_module => MySite::Admin::Some::Module
(rm = )

It's that last one that's a problem. A dispatch system with a
single mapping policy will translate that into:

module = MySite::Admin, rm = some_module

This can be solved very easily if you allow multiple URL maps based on
static string prefixes:

/app => MySite::
/app/admin => MySite::Admin


CA::Dispatch does allows table-based matching but it isn't flexible
enough to handle this.

My::Dispatch->dispatch(
RM => 1,
TABLE => {
'app' => 'MySite',
'app/admin' => 'MySite::Admin', # won't work
}
);


The first limitation is that URLs in the table can't have slashes in
them. The second limitation is that each URL in the table must be an
exact match. In other words you can't expect /app/some_module to match
against 'app'.

So I subclassed CA::Dispatch and wrote my own table handling. Which was
fine. But now, as I say, my subclass has become a full table-based
dispatcher in its own right that really should be replaced with
something more well-thought out and robust and general purpose.

Ultimately, all I want from a "Next Generation" dispatcher is some kind
of flexible /string/:app/:rm matching. I don't personally need any of
that parameter parsing stuff.


Michael



---
Michael Graham <***@the-wire.com>


---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/***@lists.erlbaum.net/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: cgiapp-***@lists.erlbaum.net
For additional commands, e-mail: cgiapp-***@lists.erlbaum.net
Rob Kinyon
2005-12-12 04:21:24 UTC
Permalink
Post by Mark Stosberg
Post by David Emery
It looks to me kind of like you're just reinventing a dumbed down
regex language. Why not just use normal Perl regexs? Besides not
having to remember another syntax, you've got pretty well every
conceivable case covered from the start. In most cases the regexes
will be really simple, but if you want to do something bizarre, you're
not limited to the scenarios envisioned by the developers, (making
simple things easy, difficult things possible, or however that goes)
$self->dispatch([
qr{
/(?#rm) (\w+)
/(?#user) (\w+)
/(?#tags+) ([\w\+]+)
}x;
]);
Perl notably doesn't have named back references, which is what
I hacked around with (?#user). Full REs are uglier and seem
unnecessary, at least for an initial version.
Better would be simple strings that have a very strict syntax. Either
it parses exactly or an error is thrown. That way, we're not bound to
syntactic correctness for the URL format, but we still have Perl
around it.

No matter what, this needs to be part of some plugin and not part of
the main code. The current dispatch methodology also needs to be
pulled out of the main code and made into a plugin that is shipped
with the main code and enabled by default if no other dispatcher is
enabled. (And, I think, the installer for the main code needs to be
made more intelligent, but that's another topic.)

Rob

---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/***@lists.erlbaum.net/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: cgiapp-***@lists.erlbaum.net
For additional commands, e-mail: cgiapp-***@lists.erlbaum.net
Mark Stosberg
2005-12-12 04:39:49 UTC
Permalink
Post by Rob Kinyon
No matter what, this needs to be part of some plugin and not part of
the main code. The current dispatch methodology also needs to be
pulled out of the main code and made into a plugin that is shipped
with the main code and enabled by default if no other dispatcher is
enabled. (And, I think, the installer for the main code needs to be
made more intelligent, but that's another topic.)
When you say the "main code", are you referring to
"CGI::Application::Dispatch" here? It's not clear to me.

Mark
--
http://mark.stosberg.com/


---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/cgiapp-***@public.gmane.org/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: cgiapp-unsubscribe-***@public.gmane.org
For additional commands, e-mail: cgiapp-help-***@public.gmane.org
Timothy Appnel
2005-12-12 14:45:28 UTC
Permalink
Post by Mark Stosberg
When you say the "main code", are you referring to
"CGI::Application::Dispatch" here? It's not clear to me.
Me neither.

I'm realizing that I may have jumped to the conclusion that we are
working with CGI::Application::Dispatch as opposed to starting over.
Does anyone disagree with building on what CGI::Application::Dispatch
has established?

<tim/>

--
Timothy Appnel
http://www.timaoutloud.org/

---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/***@lists.erlbaum.net/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: cgiapp-***@lists.erlbaum.net
For additional commands, e-mail: cgiapp-***@lists.erlbaum.net
Rob Kinyon
2005-12-12 15:16:09 UTC
Permalink
Post by Mark Stosberg
When you say the "main code", are you referring to
"CGI::Application::Dispatch" here? It's not clear to me.
main-code == CGI/Application.pm

There is the current dispatching model within C::A::run() that, imho,
needs to be pulled out into a plugin. That would become the default
dispatcher. (Well, actually, the default "default dispatcher", but
that's another thread.)

Rob

---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/***@lists.erlbaum.net/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: cgiapp-***@lists.erlbaum.net
For additional commands, e-mail: cgiapp-***@lists.erlbaum.net
Michael Graham
2005-12-12 18:13:47 UTC
Permalink
Post by Timothy Appnel
I'm realizing that I may have jumped to the conclusion that we are
working with CGI::Application::Dispatch as opposed to starting over.
Does anyone disagree with building on what CGI::Application::Dispatch
has established?
CGI::Application::Dispatch has a very central namespace, and it would be
good if the community-endorsed "next generation" dispatcher could use
it.

However, what we are suggesting is quite different from what
CGI::Application::Dispatch currently does. It's similar in spirit, but
in implementation, there are lots of little details that differ.

I'm worried that the documentation becomes very confusing because the
old terminology and new terminolgy are similar, even though the
implentation is different. E.g.:

%TABLE is used to map specific URLs to specific modules.
@DISPATCH is a new system for mapping URL-rules to specific modules.

A user familiar with the old system will understand this. A new user
will be totally confused.

And you can't leave the old behaviour undocumented, because people are
still using it and they'll want to look up stuff in the docs.

So some options are:

* Use a different namespace for the new system (e.g. CA::URLMaps,
CA::Routes, CA::Launcher, CA::StartMeUp etc.)

* Put all the old docs in CA::Dispatch::COMPAT.pod, but leave all the
old features turned on for backwards compatiblity.

* Do something as Rob suggests with a pluggable dispatch architecture.
In this case CA::Dispatch would probably become
CA::Plugin::Dispatch, anyway.


Michael


---
Michael Graham <***@the-wire.com>


---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/***@lists.erlbaum.net/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: cgiapp-***@lists.erlbaum.net
For additional commands, e-mail: cgiapp-***@lists.erlbaum.net
Michael Peters
2005-12-12 18:45:25 UTC
Permalink
Post by Michael Graham
Post by Timothy Appnel
I'm realizing that I may have jumped to the conclusion that we are
working with CGI::Application::Dispatch as opposed to starting over.
Does anyone disagree with building on what CGI::Application::Dispatch
has established?
CGI::Application::Dispatch has a very central namespace, and it would be
good if the community-endorsed "next generation" dispatcher could use
it.
I agree.
Post by Michael Graham
However, what we are suggesting is quite different from what
CGI::Application::Dispatch currently does. It's similar in spirit, but
in implementation, there are lots of little details that differ.
I'm worried that the documentation becomes very confusing because the
old terminology and new terminolgy are similar, even though the
%TABLE is used to map specific URLs to specific modules.
@DISPATCH is a new system for mapping URL-rules to specific modules.
A user familiar with the old system will understand this. A new user
will be totally confused.
And you can't leave the old behaviour undocumented, because people are
still using it and they'll want to look up stuff in the docs.
I'm not so sure this would be a problem. I think we can document both approaches
and note that the old one is deprecated (like D::FV does). Put the newer
approach in all examples, but leave the older stuff there, maybe in a different
section.
Post by Michael Graham
* Use a different namespace for the new system (e.g. CA::URLMaps,
CA::Routes, CA::Launcher, CA::StartMeUp etc.)
Dispatch is a much better name though :)
Post by Michael Graham
* Put all the old docs in CA::Dispatch::COMPAT.pod, but leave all the
old features turned on for backwards compatiblity.
Right now I'm inclined to do something like this, even if I don't split it out
into it's own separate pod file.
Post by Michael Graham
* Do something as Rob suggests with a pluggable dispatch architecture.
In this case CA::Dispatch would probably become
CA::Plugin::Dispatch, anyway.
But C::A::D can't really be plugin since it sit's outside of C::A. Especially in
mod_perl where it becomes you PerlHandler. It doesn't add anything to C::A, it
just handles the mapping of URL to module/rm.

That said, the new approach would be a mixture of both. C::A::D would still need
to sit outside of C::A, but there would need to be another module (or maybe just
a different usage of C::A::D) that acts as a plugin to add the uri_for() and
link_to() methods to C::A

My preference would be to keep all the old features of C::A::D but point people
to ways of accomplishing the same thing with the "new-way". Maybe even make the
"old-way" work behind the scenes by using the "new-way". I'm kinda busy right
now, but I have something in my head. If I get some time today or tomorrow, I'll
write it up the API and see what others think.
--
Michael Peters
Developer
Plus Three, LP


---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/***@lists.erlbaum.net/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: cgiapp-***@lists.erlbaum.net
For additional commands, e-mail: cgiapp-***@lists.erlbaum.net
Michael Graham
2005-12-12 20:29:27 UTC
Permalink
Post by Michael Peters
Post by Michael Graham
* Do something as Rob suggests with a pluggable dispatch architecture.
In this case CA::Dispatch would probably become
CA::Plugin::Dispatch, anyway.
But C::A::D can't really be plugin since it sit's outside of C::A. Especially in
mod_perl where it becomes you PerlHandler. It doesn't add anything to C::A, it
just handles the mapping of URL to module/rm.
Yeah, I know - but I gather Rob's got some ideas for making C::A's
dispatch system pluggable, though. I'm not sold on it, but it seems
like it will be an interesting discussion. I do like the idea of being
able to use CA::Dispatch as a PerlTransHandler thought.

...
Post by Michael Peters
My preference would be to keep all the old features of C::A::D but point people
to ways of accomplishing the same thing with the "new-way". Maybe even make the
"old-way" work behind the scenes by using the "new-way". I'm kinda busy right
now, but I have something in my head. If I get some time today or tomorrow, I'll
write it up the API and see what others think.
Coolness!


Michael


---
Michael Graham <***@the-wire.com>


---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/***@lists.erlbaum.net/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: cgiapp-***@lists.erlbaum.net
For additional commands, e-mail: cgiapp-***@lists.erlbaum.net
Timothy Appnel
2005-12-12 19:03:39 UTC
Permalink
Post by Michael Graham
However, what we are suggesting is quite different from what
CGI::Application::Dispatch currently does. It's similar in spirit, but
in implementation, there are lots of little details that differ.
Let me ask the same question I put out earlier. Why not? Mark put out
his and I addressed how his issues could be addressed in that
framework. I don't see what you mean or why such a path is so
necessary.
Post by Michael Graham
I'm worried that the documentation becomes very confusing because the
old terminology and new terminolgy are similar, even though the
%TABLE is used to map specific URLs to specific modules.
@DISPATCH is a new system for mapping URL-rules to specific modules.
A user familiar with the old system will understand this. A new user
will be totally confused.
I don't agree with adding @DISPATH and a new system for mapping
though. That is an artificial distinction IMHO. TABLE contains a
reference to a hash in the current implementation. It would be trivial
to check what type of reference is in there and act accordingly. This
way backwards compatibility is maintained and users used to the old
way can keep using it.
Post by Michael Graham
And you can't leave the old behaviour undocumented, because people are
still using it and they'll want to look up stuff in the docs.
Of course not. As I've illustrated you can support both with little
disruption or modification to the code. Granted its not ideally how it
would be done if we were building from the ground up, but I think
reinventing the wheel is a worse thing(tm).
Post by Michael Graham
* Use a different namespace for the new system (e.g. CA::URLMaps,
CA::Routes, CA::Launcher, CA::StartMeUp etc.)
If the community is serious about taking some cues from Rails then
adding more similar, but different options is not advisable.
Post by Michael Graham
* Put all the old docs in CA::Dispatch::COMPAT.pod, but leave all the
old features turned on for backwards compatiblity.
Once again, I don't see why this would be necessary. Adding a note in
the documentation stating the array reference is the preference and
were the hash reference came from should be sufficient.
Post by Michael Graham
* Do something as Rob suggests with a pluggable dispatch architecture.
In this case CA::Dispatch would probably become
CA::Plugin::Dispatch, anyway.
This doesn't work for me for a number of reasons. Not every
application will have multiple instance scripts/app modules for one.
This adds a complexity with little value also. As David Heinemeier
Hansson has been known to say "flexibility is overrated." I have agree
based on my experience -- I'd gladly take one simple way of doing
things then being able to do it however I want.

Rather then just look at the documentation and APIs to Rails I started
reading some of the philosophy and "zen" behind Rails and found an
interesting passage from DHH
that I wanted to put out into this conversation. When asked why is
Rails so popular he replied...

"Rails is opinionated software. It eschews placing the old ideals of
software in a primary position. One of those ideals is flexibility—the
notion that we should try to accommodate as many approaches as
possible, that we shouldn't pass judgement on one form of development
over another. Well, Rails does, and I believe that's why it works."

"With Rails, you trade flexibility at the infrastructure level to gain
flexibility at the application level. If you are happy to work along
the golden path that I've embedded in Rails, you gain an immense
reward in terms of productivity that allows you to do more, sooner,
and better at the application level."

The entire interview is here if you are interested in reading it all:
http://www.oreillynet.com/pub/a/network/2005/08/30/ruby-rails-david-heinemeier-hansson.html)

This is the biggest point I think Cataylst misses that I'm rather
disappointed in it. (Hence I'm here having this conversation and not
somewhere else using Catayst.) If we learn anything from the mistakes
of others my hope is that it is this.

<tim/>

--
Timothy Appnel
http://www.timaoutlou
Michael Graham
2005-12-12 20:29:11 UTC
Permalink
Post by Timothy Appnel
Post by Michael Graham
However, what we are suggesting is quite different from what
CGI::Application::Dispatch currently does. It's similar in spirit, but
in implementation, there are lots of little details that differ.
Let me ask the same question I put out earlier. Why not? Mark put out
his and I addressed how his issues could be addressed in that
framework. I don't see what you mean or why such a path is so
necessary.
Sorry, I may be stating the obvious, but all I'm saying is that the
following are two very different systems, but similar enough in spirit
that they may confuse new users:

# old style
TABLE => {
'blog' => 'MySite::Blog',
'admin_users' => 'MySite::Admin::Users',
}

# new style
TABLE => [
'blog/:rm' => { app => Blog },
'admin/:app/:rm' => { prefix => 'MySite::Admin' },
]

But maybe I'm not understanding your question. Are you asking me why I
think these systems are different? Or are you asking me to justify why
I want the second one?
Post by Timothy Appnel
though. That is an artificial distinction IMHO. TABLE contains a
reference to a hash in the current implementation. It would be trivial
to check what type of reference is in there and act accordingly. This
way backwards compatibility is maintained and users used to the old
way can keep using it.
Good point - there's no reason why it can't still be called TABLE. That
has the nice side effect that the system doesn't have to figure out what
to do if the user provides both a new-style and an old-style mapping at
the same time.
Post by Timothy Appnel
Post by Michael Graham
* Use a different namespace for the new system (e.g. CA::URLMaps,
CA::Routes, CA::Launcher, CA::StartMeUp etc.)
If the community is serious about taking some cues from Rails then
adding more similar, but different options is not advisable.
I tend to favour standardization over competition myself. All I'm
saying is this has to be balanced with legacy code and backwards
compatibility issues. Sometimes it's cleaner to start fresh.
Post by Timothy Appnel
Post by Michael Graham
* Put all the old docs in CA::Dispatch::COMPAT.pod, but leave all the
old features turned on for backwards compatiblity.
Once again, I don't see why this would be necessary. Adding a note in
the documentation stating the array reference is the preference and
were the hash reference came from should be sufficient.
I'm certainly willing to go this route. I'm just saying we should be
careful, is all. I've seen modules with layers of legacy documentation
that were really confusing to me when I approached them as a new user.

The Rails quotes on flexibility were interesting. I tend to agree with
whoever said "absense of constraints are the enemy of art".

In terms of this discussion, I hope it doesn't look like I'm arguing for
flexibility for its own sake. I'm trying very hard not to request
features that I *might* need in the future. Sure I've done some
speculation, but when I've requested features, I've tried to restrict
myself to real URLs that I already use in my own homegrown mapping
system.

From my perspective, with my variety of real-world mapping requirements,
allowing '/string/:app/:rm' => { prefix => 'Foo' } is a *minimalist*
solution. Believe it or not. :)


Michael


---
Michael Graham <***@the-wire.com>


---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/***@lists.erlbaum.net/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: cgiapp-***@lists.erlbaum.net
For additional commands, e-mail: cgiapp-***@lists.erlbaum.net
Timothy Appnel
2005-12-12 21:12:02 UTC
Permalink
Post by Michael Graham
But maybe I'm not understanding your question. Are you asking me why I
think these systems are different? Or are you asking me to justify why
I want the second one?
I was just curious why you are suggesting a new module and why
CGI::Application::Dispatch couldn't be adapted to provide the features
being discussed.
Post by Michael Graham
From my perspective, with my variety of real-world mapping requirements,
allowing '/string/:app/:rm' => { prefix => 'Foo' } is a *minimalist*
solution. Believe it or not. :)
I think you mean app and not prefix in that hash. PREFIX is an
existing option in CGI::Application::Dispatch.

Did anyone have any thoughts on moving the variable assignment into
the hash instead of tacking them onto the TABLE key? I.E.

'string' => { app=> 'Foo', params=>':app/:rm' }


Does this add clarity so that conflicting dispatch rules are created?
It did for me though I'm still not clear to how a missing required
parameter is handled. (Who handles the error? The run mode or the
dispatcher?)

<tim/>
--
Timothy Appnel
http://www.timaoutloud.org/

---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/***@lists.erlbaum.net/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: cgiapp-***@lists.erlbaum.net
For additional commands, e-mail: cgiapp-***@lists.erlbaum.net
Michael Graham
2005-12-12 22:08:34 UTC
Permalink
Post by Timothy Appnel
Post by Michael Graham
From my perspective, with my variety of real-world mapping requirements,
allowing '/string/:app/:rm' => { prefix => 'Foo' } is a *minimalist*
solution. Believe it or not. :)
I think you mean app and not prefix in that hash. PREFIX is an
existing option in CGI::Application::Dispatch.
No, I do actually mean prefix. I'm suggesting that each rule be able to
override the default PREFIX. The :app is already determined from the
rule. Here is a slightly less contrived example table followed by some
example URLs and their results:

PREFIX => 'MySite',
TABLE => [
'blog/:rm' => { app => 'Blog' },
'admin/:app/:rm' => { prefix => 'MySite::Admin' }
'get/:path' => { app => 'GetDoc' }
':app/:rm' => { }
],


URL Module Run Mode
--- ------ --------
/blog/show MySite::Blog show
/blog/list MySite::Blog list
/blog MySite::Blog

/admin/users/edit MySite::Admin::Users edit
/admin/users/add MySite::Admin::Users add
/admin/users MySite::Admin::Users

/foo/bar MySite::Foo bar

/get/some/doc.pdf MySite::GetDocument
(params: path=/some/doc.pdf)

/get/other/doc.pdf MySite::GetDocument
(params: path=/other/doc.pdf)


So the default PREFIX is always prepended, unless overridden by a rule.
Post by Timothy Appnel
Did anyone have any thoughts on moving the variable assignment into
the hash instead of tacking them onto the TABLE key? I.E.
'string' => { app=> 'Foo', params=>':app/:rm' }
Does this add clarity so that conflicting dispatch rules are created?
I dunno. I still prefer matches to the left, results to the right.
Post by Timothy Appnel
It did for me though I'm still not clear to how a missing required
parameter is handled. (Who handles the error? The run mode or the
dispatcher?)
Well, that's an argument against, right there. We're not doing input
validation, but rather URI matching. So we don't have "required"
parameters in the validation sense. It's simply that non-matching URIs
don't match.

So while these are duplicates:

'blog/:year/:month?/:day?' => { app => 'Blog' }
'blog/:page' => { app => 'Blog' }

these aren't:

'blog/:year/:month/:day?' => { app => 'Blog' }
'blog/:page' => { app => 'Blog' }

In the second case, /blog/2002/12 matches the first rule, but /blog/2002
matches the second.


Michael


---
Michael Graham <***@the-wire.com>


---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/***@lists.erlbaum.net/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: cgiapp-***@lists.erlbaum.net
For additional commands, e-mail: cgiapp-***@lists.erlbaum.net
Timothy Appnel
2005-12-12 22:39:34 UTC
Permalink
Post by Michael Graham
PREFIX => 'MySite',
TABLE => [
'blog/:rm' => { app => 'Blog' },
'admin/:app/:rm' => { prefix => 'MySite::Admin' }
'get/:path' => { app => 'GetDoc' }
':app/:rm' => { }
],
PREFIX is optional in Dispatch. What is the harm in this?

TABLE => [
'blog/:rm' => { app => 'MySite::Blog' },
'admin/:app/:rm' => { app => 'MySite::Admin' }
'get/:path' => { app => 'MySite::GetDoc' }
':app/:rm' => { }
]
Post by Michael Graham
Post by Timothy Appnel
It did for me though I'm still not clear to how a missing required
parameter is handled. (Who handles the error? The run mode or the
dispatcher?)
Well, that's an argument against, right there. We're not doing input
validation, but rather URI matching. So we don't have "required"
parameters in the validation sense. It's simply that non-matching URIs
don't match.
'blog/:year/:month?/:day?' => { app => 'Blog' }
'blog/:page' => { app => 'Blog' }
'blog/:year/:month/:day?' => { app => 'Blog' }
'blog/:page' => { app => 'Blog' }
In the second case, /blog/2002/12 matches the first rule, but /blog/2002
matches the second.
I had to read your example three times before I understood why which
is what I'm getting at. This still seems too confusing. It seems to me
there has to be a better way or perhaps, in order to support what you
propose, some form of simple regex pattern matching is required to
disambiguate URL patterns like in your first example. This way :year
can be defined as 4 digits (\d{4}) and will let single parameters fall
to another rule. Rails has such a feature in their routes. That left
side could get really gruesome looking if your patterns are complex
enough.

<tim/>
--
Timothy Appnel
http://www.timaoutloud.org/

---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/***@lists.erlbaum.net/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: cgiapp-***@lists.erlbaum.net
For additional commands, e-mail: cgiapp-***@lists.erlbaum.net
Michael Graham
2005-12-12 22:58:08 UTC
Permalink
Post by Timothy Appnel
Post by Michael Graham
PREFIX => 'MySite',
TABLE => [
'blog/:rm' => { app => 'Blog' },
'admin/:app/:rm' => { prefix => 'MySite::Admin' }
'get/:path' => { app => 'GetDoc' }
':app/:rm' => { }
],
PREFIX is optional in Dispatch. What is the harm in this?
TABLE => [
'blog/:rm' => { app => 'MySite::Blog' },
'admin/:app/:rm' => { app => 'MySite::Admin' }
'get/:path' => { app => 'MySite::GetDoc' }
':app/:rm' => { }
]
Well, in 'admin/:app/:rm', what does ':app' do, since 'app' is already
specified in the results? In particular, are you suggesting that the
following would still match?

URL Module Run Mode
--- ------ --------
/admin/users/edit MySite::Admin::Users edit
/admin/users/add MySite::Admin::Users add
/admin/users MySite::Admin::Users

If so, then you seem to be suggesting that whatever ':app' matches in
the URL should be combined in some intelligent way with the value of
'app' in the results. That seems too magical to me. For instance, how
is it obvious that you want 'MySite::Admin::Users' and not
'Users::MySite::Admin'? Prefix is much clearer.

IMO, 'app' should only be allowed in the results if ':app' does not appear in
the rule. Similarly for 'rm' and ':rm'.
Post by Timothy Appnel
Post by Michael Graham
So we don't have "required"
parameters in the validation sense. It's simply that non-matching URIs
don't match.
'blog/:year/:month?/:day?' => { app => 'Blog' }
'blog/:page' => { app => 'Blog' }
'blog/:year/:month/:day?' => { app => 'Blog' }
'blog/:page' => { app => 'Blog' }
In the second case, /blog/2002/12 matches the first rule, but /blog/2002
matches the second.
I had to read your example three times before I understood why which
is what I'm getting at. This still seems too confusing.
Yes, but these examples are deliberately contrived to illustrate the
mechanics of the mapping system, and the various edge cases. They are
not meant to be real world examples. If you used a mapping like the
above in real life, you get what you deserve, IMO.

Besides, the system can be designed to warn about inaccessible rules.


Michael



---
Michael Graham <***@the-wire.com>


---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/***@lists.erlbaum.net/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: cgiapp-***@lists.erlbaum.net
For additional commands, e-mail: cgiapp-***@lists.erlbaum.net
Timothy Appnel
2005-12-13 01:18:54 UTC
Permalink
Post by Michael Graham
Well, in 'admin/:app/:rm', what does ':app' do, since 'app' is already
specified in the results?
Good point. A hasty cut and paste is to blame.
Post by Michael Graham
In particular, are you suggesting that the
following would still match?
URL Module Run Mode
--- ------ --------
/admin/users/edit MySite::Admin::Users edit
/admin/users/add MySite::Admin::Users add
/admin/users MySite::Admin::Users
If so, then you seem to be suggesting that whatever ':app' matches in
the URL should be combined in some intelligent way with the value of
'app' in the results. That seems too magical to me. For instance, how
is it obvious that you want 'MySite::Admin::Users' and not
'Users::MySite::Admin'? Prefix is much clearer.
I made a mistake in my example. Prefix is a nice short hand when all
modules share the similar names, but it complicates matters when you
are dealing with modules from completely different namespaces.

This feels like a fringe case to me.
Post by Michael Graham
IMO, 'app' should only be allowed in the results if ':app' does not appear in
the rule. Similarly for 'rm' and ':rm'.
Agreed.
Post by Michael Graham
Yes, but these examples are deliberately contrived to illustrate the
mechanics of the mapping system, and the various edge cases. They are
not meant to be real world examples. If you used a mapping like the
above in real life, you get what you deserve, IMO.
I don't see these are being edge cases since your scenario it
precisely how Movable Type constructs its URLs by default. Not to say
that we're going to build MT here, but that your example URL scheme is
not that exotic or outlandish.

I'm either for really simple or going all the way (i guess that would
essentially be a port of what Ruby's Routes does) with really simple
being my overwhelming preference. What you are advocating is between
the two and seems more incomplete then a compromise.
Post by Michael Graham
Besides, the system can be designed to warn about inaccessible rules.
Code to save a developer from themselves never wins me over. The table
format should be clear enough that an inaccessible rule is fairly
obvious.
Post by Michael Graham
But what if I have a non-year value which is 4 digits?
I know. This is why the current proposal (or is it the scope that's
the problem?) with or without regex pattern matching that doesn't seem
quite right to me.

<tim/>
--
Timothy Appnel
http://www.timaoutloud.org/

---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/***@lists.erlbaum.net/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: cgiapp-***@lists.erlbaum.net
For additional commands, e-mail: cgiapp-***@lists.erlbaum.net
Michael Graham
2005-12-13 07:08:29 UTC
Permalink
...
Post by Timothy Appnel
Prefix is a nice short hand when all
modules share the similar names, but it complicates matters when you
are dealing with modules from completely different namespaces.
Which is why you don't use 'prefix' when you really mean 'app'. That's
why I gave examples of both:

'admin/:app/:rm' => { prefix => 'MySite::Admin' }
'get/:path' => { app => 'GetDoc' }

In some cases (when you have a bunch of modules under a namespace), you
want to use a prefix. In other cases you don't even want to derive the
module name from the URL.

The reason I want to allow 'prefix' in the results section is because
sometimes a dispatcher sits in front of more than one namespace.
Post by Timothy Appnel
This feels like a fringe case to me.
Well, it may seem esoteric to you, but the examples I gave are pretty
close to what I use every day.
Post by Timothy Appnel
Post by Michael Graham
Yes, but these examples are deliberately contrived to illustrate the
mechanics of the mapping system, and the various edge cases. They are
not meant to be real world examples. If you used a mapping like the
above in real life, you get what you deserve, IMO.
I don't see these are being edge cases since your scenario it
precisely how Movable Type constructs its URLs by default. Not to say
that we're going to build MT here, but that your example URL scheme is
not that exotic or outlandish.
I don't have an MT system handy to test with, but I do want to point out
that that we're only talking about *optional* parameters. There is no
ambiguity here:

'blog/:year/:month' => { app => 'Blog' }
'blog/:id' => { app => 'Blog' }
Post by Timothy Appnel
I'm either for really simple or going all the way (i guess that would
essentially be a port of what Ruby's Routes does) with really simple
being my overwhelming preference. What you are advocating is between
the two and seems more incomplete then a compromise.
Well that seems a bit like all-or-nothing thinking to me. The syntax
I've been promoting is good enough to handle all of the mapping
scenarios that I've had to deal with, so I can't say it seems
incomplete to me.

You seem to have latched on to a very small aspect of the system, namely
the it's possible that programmers will shoot themselves in their feet
by accidentally entering duplicate rules. I suspect that this is going
to be a trap with *any* system that involves matching.

For instance, using your proposed syntax:

'blog' => { app => 'Blog', params => ':rm' }
'blog/admin' => { app => 'Admin', params => ':rm' }

What does 'blog/admin' match? By your reckoning it should be *obvious*
that it matches the first rule, but it isn't obvious to me.


Michael


---
Michael Graham <***@the-wire.com>


---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/***@lists.erlbaum.net/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: cgiapp-***@lists.erlbaum.net
For additional commands, e-mail: cgiapp-***@lists.erlbaum.net

Michael Peters
2005-12-12 22:57:03 UTC
Permalink
Post by Timothy Appnel
Post by Michael Graham
PREFIX => 'MySite',
TABLE => [
'blog/:rm' => { app => 'Blog' },
'admin/:app/:rm' => { prefix => 'MySite::Admin' }
'get/:path' => { app => 'GetDoc' }
':app/:rm' => { }
],
PREFIX is optional in Dispatch. What is the harm in this?
TABLE => [
'blog/:rm' => { app => 'MySite::Blog' },
'admin/:app/:rm' => { app => 'MySite::Admin' }
'get/:path' => { app => 'MySite::GetDoc' }
':app/:rm' => { }
]
This won't work as intended because the 'admin/:app/:rm' rule can't work with
multiple apps under the 'MySite::Admin' prefix. In order to make this work with
a non-overridable PREFIX, he'd need to make an entry for each app class under
the 'MySite::Admin' namespace, which could get kinda tedious.

I personally think that being able to override things like PREFIX, on a
case-by-case basis would be a good thing.

This also brings up another question. If a rule has ':app' in it, should a
warning/error be thrown if the right-hand side has "app => 'Foo'" in it? If not,
what should happen?
Post by Timothy Appnel
Post by Michael Graham
'blog/:year/:month?/:day?' => { app => 'Blog' }
'blog/:page' => { app => 'Blog' }
'blog/:year/:month/:day?' => { app => 'Blog' }
'blog/:page' => { app => 'Blog' }
In the second case, /blog/2002/12 matches the first rule, but /blog/2002
matches the second.
I had to read your example three times before I understood why which
is what I'm getting at. This still seems too confusing. It seems to me
there has to be a better way or perhaps, in order to support what you
propose, some form of simple regex pattern matching is required to
disambiguate URL patterns like in your first example. This way :year
can be defined as 4 digits (\d{4}) and will let single parameters fall
to another rule. Rails has such a feature in their routes. That left
side could get really gruesome looking if your patterns are complex
enough.
We've already talked about using regexes on the left hand side in previous
emails and here are the main reasons against that:

+ regexes don't allow for named captures. You couldn't have it automatically
know which part of the match was the :app or :rm if any. This would require
inventing a new synax for that and then created our own regex parser to deal with it
+ regexes are uglier. Not an important reason, but a reason non-the-less.
Regexes are their own mini-language, and no one will deny that they can be
pretty complex and sometimes confusing. We feel that all cases could be handled
by the syntax that's been proposed.
--
Michael Peters
Developer
Plus Three, LP


---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/***@lists.erlbaum.net/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: cgiapp-***@lists.erlbaum.net
For additional commands, e-mail: cgiapp-***@lists.erlbaum.net
Ron Savage
2005-12-13 00:16:26 UTC
Permalink
On Mon, 12 Dec 2005 17:39:34 -0500, Timothy Appnel wrote:

Hi Tim
first example. This way :year can be defined as 4 digits (\d{4})
and will let single parameters fall to another rule. Rails has such
But what if I have a non-year value which is 4 digits?

--
Ron Savage
***@savage.net.au
http://savage.net.au/index.html



---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/***@lists.erlbaum.net/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: cgiapp-***@lists.erlbaum.net
For additional commands, e-mail: cgiapp-***@lists.erlbaum.net
Mark Stosberg
2005-12-13 00:51:31 UTC
Permalink
Post by Ron Savage
Hi Tim
first example. This way :year can be defined as 4 digits (\d{4})
and will let single parameters fall to another rule. Rails has such
But what if I have a non-year value which is 4 digits?
Then you've designed an un-intuitive URL scheme.

/blog/2004
/blog/2003

One number is a year and the other isn't?

You probably need to clarify one of the URLs:

/blog/by_date/2004

# perhaps a blog entry ID
/blog/2003


Mark
--
http://mark.stosberg.com/


---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/cgiapp-***@public.gmane.org/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: cgiapp-unsubscribe-***@public.gmane.org
For additional commands, e-mail: cgiapp-help-***@public.gmane.org
Rob Kinyon
2005-12-08 15:58:00 UTC
Permalink
Post by David Emery
I suggest using whichever match comes first in the dispatch list. That
way it's easy to understand and control, no?
Yes. That's what Rails does, and it's easiest to work with.
Post by David Emery
Post by Michael Graham
Which is the "correct" URL? URL B uses the most precise match (longer
static string), but URL A uses fewer query parameters and makes a
shorter, neater URL.
Of course, maybe the Rails people have already solved the algorithms to
do these things?
First match wins. :-)

Rob

---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/***@lists.erlbaum.net/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: cgiapp-***@lists.erlbaum.net
For additional commands, e-mail: cgiapp-***@lists.erlbaum.net
Mark Stosberg
2005-12-08 18:02:54 UTC
Permalink
Post by Rob Kinyon
Post by David Emery
I suggest using whichever match comes first in the dispatch list. That
way it's easy to understand and control, no?
Yes. That's what Rails does, and it's easiest to work with.
Post by David Emery
Post by Michael Graham
Which is the "correct" URL? URL B uses the most precise match (longer
static string), but URL A uses fewer query parameters and makes a
shorter, neater URL.
Of course, maybe the Rails people have already solved the algorithms to
do these things?
First match wins. :-)
That's what I had in mind as well.

Mark


---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/cgiapp-***@public.gmane.org/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: cgiapp-unsubscribe-***@public.gmane.org
For additional commands, e-mail: cgiapp-help-***@public.gmane.org
Michael Graham
2005-12-08 19:12:22 UTC
Permalink
Post by David Emery
I suggest using whichever match comes first in the dispatch list. That
way it's easy to understand and control, no?
Yeah, that is definitely the sensible thing to do. I think I was
blinded by the idea that the table would be a hash not a list.


Michael


---
Michael Graham <***@the-wire.com>


---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/***@lists.erlbaum.net/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: cgiapp-***@lists.erlbaum.net
For additional commands, e-mail: cgiapp-***@lists.erlbaum.net
Loading...