Discussion:
Announce: CGI::Snapp::Dispatch V 1.00 etc, with PSGI support
(too old to reply)
Ron Savage
2012-04-12 03:29:37 UTC
Permalink
Hi Folks

I've uploaded to CPAN:

o CGI::Snapp::Dispatch V 1.00.

This distro includes CGI::Snapp::Dispatch::Regexp.

Both modules support usage in a PSGI environment.

This module is a partner for CGI::Snapp, and together they are almost
drop-in replacements for CGI::Application, CGI::Application::Dispatch,
CGI::Application::Dispatch::Regexp and CGI::Application::Dispatch::PSGI.

The default for logging is to not create a logger, as per CGI::Snapp V
1.01 below.

There are 63 tests.

PSGI is supported without needing a module called
CGI::Snapp::Dispatch::PSGI.

o CGI::Snapp V 1.01.

This has a new mutator _psgi() for use by CGI::Snapp::Dispatch.

Also, the default for logging is now to not create a logger.

PSGI is supported without needing a module called CGI::Snapp::PSGI.

o CGI::Snapp::Plugin::Forward V 1.01.

The tests explicitly create a logger since CGI::Snapp V 1.01 now does not.

o CGI::Snapp::Plugin::Redirect V 1.01.

The tests explicitly create a logger since CGI::Snapp V 1.01 now does not.
--
Ron Savage
http://savage.net.au/
Ph: 0421 920 622

##### CGI::Application community mailing list ################
## ##
## To unsubscribe, or change your message delivery options, ##
## visit: http://www.erlbaum.net/mailman/listinfo/cgiapp ##
## ##
## Web archive: http://www.erlbaum.net/pipermail/cgiapp/ ##
## Wiki: http://cgiapp.erlbaum.net/ ##
## ##
################################################################
B. Estrade
2012-04-12 15:34:42 UTC
Permalink
Post by Ron Savage
Hi Folks
o CGI::Snapp::Dispatch V 1.00.
This distro includes CGI::Snapp::Dispatch::Regexp.
Both modules support usage in a PSGI environment.
This module is a partner for CGI::Snapp, and together they are almost
drop-in replacements for CGI::Application, CGI::Application::Dispatch,
CGI::Application::Dispatch::Regexp and CGI::Application::Dispatch::PSGI.
The default for logging is to not create a logger, as per CGI::Snapp V
1.01 below.
There are 63 tests.
PSGI is supported without needing a module called
CGI::Snapp::Dispatch::PSGI.
o CGI::Snapp V 1.01.
This has a new mutator _psgi() for use by CGI::Snapp::Dispatch.
Also, the default for logging is now to not create a logger.
PSGI is supported without needing a module called CGI::Snapp::PSGI.
o CGI::Snapp::Plugin::Forward V 1.01.
The tests explicitly create a logger since CGI::Snapp V 1.01 now does not.
o CGI::Snapp::Plugin::Redirect V 1.01.
The tests explicitly create a logger since CGI::Snapp V 1.01 now does not.
Ron,

Congratulations and nice work. I am sorry to be dense, but as long as
I've been following Snapp and as many of the docs that I seem to have
read, I am still trying to figure out exactly what Snapp gives us over
CAP.

I ask because I am at the start of a major project that is making
critical use of CAP and CAP::Dispatch. If I am going to switch, now's
the time, but I need to justify it to myself.

Thank you,
Brett
Post by Ron Savage
--
Ron Savage
http://savage.net.au/
Ph: 0421 920 622
##### CGI::Application community mailing list ################
## ##
## To unsubscribe, or change your message delivery options, ##
## visit: http://www.erlbaum.net/mailman/listinfo/cgiapp ##
## ##
## Web archive: http://www.erlbaum.net/pipermail/cgiapp/ ##
## Wiki: http://cgiapp.erlbaum.net/ ##
## ##
################################################################
##### CGI::Application community mailing list ################
## ##
## To unsubscribe, or change your message delivery options, ##
## visit: http://www.erlbaum.net/mailman/listinfo/cgiapp ##
## ##
## Web archive: http://www.erlbaum.net/pipermail/cgiapp/ ##
## Wiki: http://cgiapp.erlbaum.net/ ##
## ##
################################################################
Ron Savage
2012-04-12 23:30:09 UTC
Permalink
Hi Brett
Post by B. Estrade
Congratulations and nice work. I am sorry to be dense, but as long as
I've been following Snapp and as many of the docs that I seem to have
read, I am still trying to figure out exactly what Snapp gives us over
CAP.
I ask because I am at the start of a major project that is making
critical use of CAP and CAP::Dispatch. If I am going to switch, now's
the time, but I need to justify it to myself.
A perfectly reasonable request.

As I've hinted, with great restraint, in:

https://metacpan.org/module/CGI::Snapp#Why-did-you-fork-CGI::Application-

I been struggling with Mark Stosberg for years about timely releases of
patches (mostly to CGI::Session). I have written a great deal of code
and docs, some of which he withheld from release for more than a year.

I eventually decided for re-write this code so as to free myself from
that constraint. In other words, I wished to guarantee current and
future support - by doing it myself - for my current and future projects.

That does not mean I have to use CGI::Snapp for everything. In fact, I'm
very tempted to start learning Mojo, but I wanted a safe and reliable
alternative to be in place before I adopted something new, since the
latter course would necessarily involve a learning curve.

The other factor you - and everyone - should take into account is that
CGI::App etc appear to be longer supported, in that bug fixing has stopped.

CGI::Snapp etc bugs (if any!) will be of great concern to me and will be
fixed ASAP.

For such software technology, it's actually nice to have a choice.

Choose wisely!
--
Ron Savage
http://savage.net.au/
Ph: 0421 920 622

##### CGI::Application community mailing list ################
## ##
## To unsubscribe, or change your message delivery options, ##
## visit: http://www.erlbaum.net/mailman/listinfo/cgiapp ##
## ##
## Web archive: http://www.erlbaum.net/pipermail/cgiapp/ ##
## Wiki: http://cgiapp.erlbaum.net/ ##
## ##
################################################################
David Groskind
2012-04-13 02:39:12 UTC
Permalink
Reading the email exchange below, it looks like CGI::Application has
stalled and one of the developers has forked the code.

There are enough differences with the forked version that I would stick
with CGI::App.
Post by Ron Savage
Hi Brett
Post by B. Estrade
Congratulations and nice work. I am sorry to be dense, but as long as
I've been following Snapp and as many of the docs that I seem to have
read, I am still trying to figure out exactly what Snapp gives us over
CAP.
I ask because I am at the start of a major project that is making
critical use of CAP and CAP::Dispatch. If I am going to switch, now's
the time, but I need to justify it to myself.
A perfectly reasonable request.
https://metacpan.org/module/CGI::Snapp#Why-did-you-fork-CGI::Application-
I been struggling with Mark Stosberg for years about timely releases of
patches (mostly to CGI::Session). I have written a great deal of code
and docs, some of which he withheld from release for more than a year.
I eventually decided for re-write this code so as to free myself from
that constraint. In other words, I wished to guarantee current and
future support - by doing it myself - for my current and future projects.
That does not mean I have to use CGI::Snapp for everything. In fact, I'm
very tempted to start learning Mojo, but I wanted a safe and reliable
alternative to be in place before I adopted something new, since the
latter course would necessarily involve a learning curve.
The other factor you - and everyone - should take into account is that
CGI::App etc appear to be longer supported, in that bug fixing has stopped.
CGI::Snapp etc bugs (if any!) will be of great concern to me and will be
fixed ASAP.
For such software technology, it's actually nice to have a choice.
Choose wisely!
--
Ron Savage
http://savage.net.au/
Ph: 0421 920 622
##### CGI::Application community mailing list ################
## ##
## To unsubscribe, or change your message delivery options, ##
## visit: http://www.erlbaum.net/mailman/listinfo/cgiapp ##
## ##
## Web archive: http://www.erlbaum.net/pipermail/cgiapp/ ##
## Wiki: http://cgiapp.erlbaum.net/ ##
## ##
################################################################
##### CGI::Application community mailing list ################
## ##
## To unsubscribe, or change your message delivery options, ##
## visit: http://www.erlbaum.net/mailman/listinfo/cgiapp ##
## ##
## Web archive: http://www.erlbaum.net/pipermail/cgiapp/ ##
## Wiki: http://cgiapp.erlbaum.net/ ##
## ##
################################################################
Ron Savage
2012-04-13 03:08:32 UTC
Permalink
Hi David
Post by David Groskind
Reading the email exchange below, it looks like CGI::Application has
stalled and one of the developers has forked the code.
There are enough differences with the forked version that I would stick
with CGI::App.
There have to be some differences, otherwise there's not much point in a
fork...

Also, I've written or re-written all the documentation for my modules,
and hopefully made them vastly easier to read.
--
Ron Savage
http://savage.net.au/
Ph: 0421 920 622

##### CGI::Application community mailing list ################
## ##
## To unsubscribe, or change your message delivery options, ##
## visit: http://www.erlbaum.net/mailman/listinfo/cgiapp ##
## ##
## Web archive: http://www.erlbaum.net/pipermail/cgiapp/ ##
## Wiki: http://cgiapp.erlbaum.net/ ##
## ##
################################################################
Nic Zero
2012-04-13 10:48:34 UTC
Permalink
I too have recently rewritten CGI::App and most of its core plugins.
That was not my original plan.  You may remember recently I was
recommending people make use of class-level initialisation and
only do object-level initialisation (ie per cgiapp instance) for those
things that can't be shared.  However, when I looked into it more
deeply (as part of a separate task) I found that support for this
within plugins is quite sketchy and unreliable.  CGI::App itself
doesn't really support the idea in any clear way.  I also thought
that rearranging the code inside CGI::App would help me and
others understand the flow better.  So I started to refactor.  But
then I encountered code that is convoluted, for example a six-
line subroutine that was much clearer in one line.  So I started
to rewrite.  And then I decided the whole thing would be easier to
code against as well as easier to read if I made my Stash plugin
be used within CGI::App itself (much like Catalyst & Mojolicious).
So then I realised I was departing from being CGI::App
compatible.

That's where that story ends.  As soon as you've broken
compatibility you've distanced yourself from the CGI::App
community and your one-man project is dead.  My time wasn't
wasted cos I then refactored again so that the good bits are
separate extensions that can be used with CGI::App or
Mojolicious.  [They're close to being published; tests need to
be improved and documentation needs to catch up.]

I thought that my micro-framework would still fill a niche: those
cases where you want the functionality of Catalyst but with a
1 MB du footprint.  Unfortunately those smart people over at
Mojolicious had a fabulous 2011 and can do much more than
my framework and still sit inside 1 MB.

So if you're still reading, my strong recommendations are:
* Respect CGI::App for what it is.  If you need more, go see
Mojolicious::Lite and Mojolicious itself.
* Ignore people like Ron & me who are tempted to do rewrites
that will never have the community that CGI::App grew.  Two
years from now both of our frameworks will still contain more
bugs and fewer working examples than CGI::App.
* Ron, if you do continue with Snapp, try borrowing some of
the smart ideas from Mojolicious::Lite, but
* like me, I suspect you'll fall in love with Mojolicious and
Snapp will just be an amusing memory.

Happy coding,
Nic

##### CGI::Application community mailing list ################
## ##
## To unsubscribe, or change your message delivery options, ##
## visit: http://www.erlbaum.net/mailman/listinfo/cgiapp ##
## ##
## Web archive: http://www.erlbaum.net/pipermail/cgiapp/ ##
## Wiki: http://cgiapp.erlbaum.net/ ##
## ##
##############
B. Estrade
2012-04-13 14:59:20 UTC
Permalink
Post by Nic Zero
I too have recently rewritten CGI::App and most of its core plugins.
That was not my original plan.?? You may remember recently I was
recommending people make use of class-level initialisation and
only do object-level initialisation (ie per cgiapp instance) for those
things that can't be shared.?? However, when I looked into it more
deeply (as part of a separate task) I found that support for this
within plugins is quite sketchy and unreliable.?? CGI::App itself
doesn't really support the idea in any clear way.?? I also thought
that rearranging the code inside CGI::App would help me and
others understand the flow better.?? So I started to refactor.?? But
then I encountered code that is convoluted, for example a six-
line subroutine that was much clearer in one line.?? So I started
to rewrite.?? And then I decided the whole thing would be easier to
code against as well as easier to read if I made my Stash plugin
be used within CGI::App itself (much like Catalyst & Mojolicious).
So then I realised I was departing from being CGI::App
compatible.
That's where that story ends.?? As soon as you've broken
compatibility you've distanced yourself from the CGI::App
community and your one-man project is dead.?? My time wasn't
wasted cos I then refactored again so that the good bits are
separate extensions that can be used with CGI::App or
Mojolicious.?? [They're close to being published; tests need to
be improved and documentation needs to catch up.]
..ah, yes..the community - that's the compelling part about CAP for
me. I like this list a lot, for example.
Post by Nic Zero
I thought that my micro-framework would still fill a niche: those
cases where you want the functionality of Catalyst but with a
1 MB du footprint.?? Unfortunately those smart people over at
Mojolicious had a fabulous 2011 and can do much more than
my framework and still sit inside 1 MB.
* Respect CGI::App for what it is.?? If you need more, go see
Mojolicious::Lite and Mojolicious itself.
* Ignore people like Ron & me who are tempted to do rewrites
that will never have the community that CGI::App grew.?? Two
years from now both of our frameworks will still contain more
bugs and fewer working examples than CGI::App.
I am less inclined to use something other than CAP proper, but
Mojolicious looks interesting. Something about how much it hides is a
little unerving to me, though.

I have routes set up fine using CAP::Dispatch (which also supports the
HTTP methods for the clean URIs. Beyond setting up the routes, I am
not sure what Mojo gives me since I still have to implement my backend
to push and pull data. It is a lot cleaner looking, but one thing that
stands out to me are those templates in Mojo - out of the box, they
seem way to powerful (I am a fan of super dumb templates).
Post by Nic Zero
* Ron, if you do continue with Snapp, try borrowing some of
the smart ideas from Mojolicious::Lite, but
* like me, I suspect you'll fall in love with Mojolicious and
Snapp will just be an amusing memory.
Thanks, everyone. And thanks, Ron, for your efforts - I don't think
any effort to improve things or to learn is time wasted. Most OSS
projects out there are "one man" or "one off". I have a few myself =).

Brett
Post by Nic Zero
Happy coding,
Nic
##### CGI::Application community mailing list ################
## ##
## To unsubscribe, or change your message delivery options, ##
## visit: http://www.erlbaum.net/mailman/listinfo/cgiapp ##
## ##
## Web archive: http://www.erlbaum.net/pipermail/cgiapp/ ##
## Wiki: http://cgiapp.erlbaum.net/ ##
## ##
################################################################
##### CGI::Application community mailing list ################
## ##
## To unsubscribe, or change your message delivery options, ##
## visit: http://www.erlbaum.net/mailman/listinfo/cgiapp ##
## ##
## Web archive: http://www.erlbaum.net/pipermail/cgiapp/ ##
## Wiki: http://cgiapp.erlbaum.net/ ##
## ##
################################################################
Ron Savage
2012-04-14 00:41:06 UTC
Permalink
Hi Brett
Post by B. Estrade
..ah, yes..the community - that's the compelling part about CAP for
me. I like this list a lot, for example.
Agreed. I released Snapp publicly just so the community can use it.
Post by B. Estrade
I am less inclined to use something other than CAP proper, but
Mojolicious looks interesting. Something about how much it hides is a
little unerving to me, though.
It's always a bit of a risk to change direction away from a
well-recognized module to an alternative, since you are - at first -
entering the unknown. But you did that by adopting CAP originally.

I have precisely the same reaction as you to Mojolicious'
automated-hamburger-with-the-lot approach.
Post by B. Estrade
I have routes set up fine using CAP::Dispatch (which also supports the
HTTP methods for the clean URIs. Beyond setting up the routes, I am
not sure what Mojo gives me since I still have to implement my backend
to push and pull data. It is a lot cleaner looking, but one thing that
stands out to me are those templates in Mojo - out of the box, they
seem way to powerful (I am a fan of super dumb templates).
Yes - it's writing the real guts of the app which is always the
challenge, and I do love to see how others have done it, since I'm very
visual like that. If too much is automated, what's to see?

My choice of templater is Text::Xslate.
Post by B. Estrade
Post by Nic Zero
* Ron, if you do continue with Snapp, try borrowing some of
the smart ideas from Mojolicious::Lite, but
* like me, I suspect you'll fall in love with Mojolicious and
Snapp will just be an amusing memory.
Thanks, everyone. And thanks, Ron, for your efforts - I don't think
any effort to improve things or to learn is time wasted. Most OSS
projects out there are "one man" or "one off". I have a few myself =).
Thanx for the positive feedback. I'm delighted to say I don't think any
of my time was wasted.

As some of you might know, I take care of my mother who has Alzheimer's,
so I'm at home all day with plenty of time available.
--
Ron Savage
http://savage.net.au/
Ph: 0421 920 622

##### CGI::Application community mailing list ################
## ##
## To unsubscribe, or change your message delivery options, ##
## visit: http://www.erlbaum.net/mailman/listinfo/cgiapp ##
## ##
## Web archive: http://www.erlbaum.net/pipermail/cgiapp/ ##
## Wiki: http://cgiapp.erlbaum.net/ ##
## ##
################################################################
Ron Savage
2012-04-14 00:28:37 UTC
Permalink
Hi Nic
* Ignore people like Ron& me who are tempted to do rewrites
that will never have the community that CGI::App grew. Two
years from now both of our frameworks will still contain more
bugs and fewer working examples than CGI::App.
My plan is that Snapp will always contain less bugs :-).
* Ron, if you do continue with Snapp, try borrowing some of
the smart ideas from Mojolicious::Lite, but
* like me, I suspect you'll fall in love with Mojolicious and
Snapp will just be an amusing memory.
Quite possibly, but the code will not suffer bit rot. It definitely will
be maintained.
--
Ron Savage
http://savage.net.au/
Ph: 0421 920 622

##### CGI::Application community mailing list ################
## ##
## To unsubscribe, or change your message delivery options, ##
## visit: http://www.erlbaum.net/mailman/listinfo/cgiapp ##
## ##
## Web archive: http://www.erlbaum.net/pipermail/cgiapp/ ##
## Wiki: http://cgiapp.erlbaum.net/ ##
## ##
################################################################
Mark Stosberg
2012-08-29 03:27:04 UTC
Permalink
Hello Everyone.

I'll start with a apology about not being as present as I intended.
Messages from this list were not coming directly to my Inbox for some
time, and it took me longer than I wanted to get that addressed.
Starting today, messages should be going back in my Inbox again, and I
will attempt be more responsive here.

I'm still alive and well, and use and support CGI::Application every day
at work. I'm also now the primary maintainer of CGI.pm. While it's only
a part of the CGI::Application framework, it has substantially more
lines of code, as well as more bugs and bug traffic. More of my
maintenance time has been spent maintaining that lately.

I appreciate the fork that Ron Savage recently published, because it's
good to explore options, and it's easiest to evaluate options if they
are complete. I also agree with the spirit of it. It's time for the next
generation of the framework, one that breaks compatibility in some
places to move the whole forward.

I started writing my own fork over a year ago in hopes of having
something to share around the time for YAPC 2011. While I needed to put
that on hold for a while, It's now on the verge of the initial release.
It was interesting to find Ron's fork which had been developed
independently and in parallel, to see where we agreed and where we
differed.

Here are the key points I have mind for the update I'll be publishing
soon:

- A new name space, to avoid confusion and problems with API changes.

- A "::Compat" addition that allows people to keep using a maximal
amount of the old API if they need to. (Including a certain amount of
plugins)

- PSGI-native. I'm excited that Perl web frameworks are converging here.
We'll be able to take advantage of PSGI "Middleware" that was designed
with other frameworks in mind. Many things that were CGI::App plugins
before are now better done done as PSGI "Middleware". As a plugin
author, you get the benefit of having more users who may be using
other frameworks. The difference with CGI::App will be that PSGI will
the *only* code path supported.

- Uses Any::Moose / Mouse. I endorse the Moose API and Mouse brings
much of that API to lower resource environments, like the CGI
environment where CGI::Application has always performed well.

It's already possible to write a CGI::App subclass based on Moose or
Mouse, but like with PSGI, I think it's in our best interest to
upgrade to first class support.

Just as "PSGI Middleware" presents a new opportunity for code re-use,
Moose/Mouse "roles" present another alternative to "plugins" that can
be shared between frameworks. For example, methods for logging,
database access and "config" data are all good candidates to be
implemented as roles.

- Templating APIs removed from core, for now. We'll get a new templating
API, although the details are still TBD.

- Plans to replace CGI.pm with request and response objects. As the
CGI.pm maintainer, I could devote another full post to reasons why I
don't to be using it in another 5 or 10 years. Details here are still
to be determined as well.

Immediately we would see the "query()" method replaced with a "req"
method to represent a "request" object. HTTP has "requests" and
"responses". The idea of a "query object" is a CGI.pm'ism to leave
behind.

About every other Perl framework I've looked at models the response
and request this way, and it's time we implemented this sensible
design as well.


- The popular and small "::Forward()" and "::Redirect()" plugins will
be merged into the core.

As part of considering the future of CGI::Application, I did consider
just dropping it. I maintain it, but lack the emotional attachment of
being the original author. I stepped back and took a look at it from the
distance and compared it to alternatives. Outside of the few "details"
I'd like to change, I find the core of it still offers a unique
combination of design properties that I think are worth taking forward:

- I think the flow of the execution stages works very well. I'm talking
about "init", "setup", "prerun", "run", "postrun", "teardown", as
they are implemented in "new()" and "run()".

- Lightweight / fast start up time.

- Simple. Less code to learn, less chance for bugs.

- Global dispatching. That is, a single central table, rather than
storing dispatch details "locally", with each run mode.

- Ability to scale up. I find CGI::App suitable for large projects as
well as small.

There's also a great community of people and plugins around CGI::App as
well.

I look forward to being conversation with you all more about this. I'll
set a goal to release the first code-as-draft for my proposal within a
week, and look forward to your feedback to sculpt it into a releasable
form.

Thanks,

Mark


##### CGI::Application community mailing list ################
## ##
## To unsubscribe, or change your message delivery options, ##
## visit: http://www.erlbaum.net/mailman/listinfo/cgiapp ##
## ##
## Web archive: http://www.erlbaum.net/pipermail/cgiapp/ ##
## Wiki: http://cgiapp.erlbaum.net/ ##
## ##
################################################################
Gabor Szabo
2012-08-29 06:26:57 UTC
Permalink
Post by Mark Stosberg
I'll start with a apology about not being as present as I intended.
No need for that.
Post by Mark Stosberg
I started writing my own fork over a year ago in hopes of having
something to share around the time for YAPC 2011. While I needed to put
that on hold for a while, It's now on the verge of the initial release.
Here are the key points I have mind for the update I'll be publishing
- A new name space, to avoid confusion and problems with API changes.
My bike-shed request is to avoid the word CGI :)

Otherwise I applaud your work and plans! Thank you!

regards
Gabor

##### CGI::Application community mailing list ################
## ##
## To unsubscribe, or change your message delivery options, ##
## visit: http://www.erlbaum.net/mailman/listinfo/cgiapp ##
## ##
## Web archive: http://www.erlbaum.net/pipermail/cgiapp/ ##
## Wiki: http://cgiapp.erlbaum.net/ ##
## ##
################################################################
Jiří Pavlovský
2012-08-29 08:35:30 UTC
Permalink
Post by Mark Stosberg
I started writing my own fork over a year ago in hopes of having
something to share around the time for YAPC 2011. While I needed to put
that on hold for a while, It's now on the verge of the initial release.
Post by Mark Stosberg
Here are the key points I have mind for the update I'll be publishing
- A new name space, to avoid confusion and problems with API changes.
My bike-shed request is to avoid the word CGI :)
I agree that well chosen name is crucial for taking over the world ;)
--
Jiří Pavlovský


##### CGI::Application community mailing list ################
## ##
## To unsubscribe, or change your message delivery options, ##
## visit: http://www.erlbaum.net/mailman/listinfo/cgiapp ##
## ##
## Web archive: http://www.erlbaum.net/pipermail/cgiapp/ ##
## Wiki: http://cgiapp.erlbaum.net/ ##
## ##
##########################################################
Mark Stosberg
2012-08-29 13:07:13 UTC
Permalink
Post by Gabor Szabo
Post by Mark Stosberg
I started writing my own fork over a year ago in hopes of having
something to share around the time for YAPC 2011. While I needed to put
that on hold for a while, It's now on the verge of the initial release.
Here are the key points I have mind for the update I'll be publishing
- A new name space, to avoid confusion and problems with API changes.
My bike-shed request is to avoid the word CGI :)
Gabor,

Thanks for the feedback. Your request will be granted.

Mark



##### CGI::Application community mailing list ################
## ##
## To unsubscribe, or change your message delivery options, ##
## visit: http://www.erlbaum.net/mailman/listinfo/cgiapp ##
## ##
## Web archive: http://www.erlbaum.net/pipermail/cgiapp/ ##
## Wiki: http://cgiapp.erlbaum.net/ ##
## ##
################################################################
Michael Peters
2012-08-29 15:50:34 UTC
Permalink
Post by Mark Stosberg
I look forward to being conversation with you all more about this. I'll
set a goal to release the first code-as-draft for my proposal within a
week, and look forward to your feedback to sculpt it into a releasable
form.
I agree with just about everything you've mentioned here Mark. I've been
thinking myself that C::A needed to be "reinvented" as something more
modern but that still had the same flavor.

My only advice is that since you'll really only have this one time to
make a break like this from the past, don't feel bad about breaking
backward compatibility. From your email it doesn't seem like you do,
just wanted to make sure that you knew we'd support something like that.

And like Gabor said, avoid the word "CGI" :) I know we've been down the
naming rabbit hole before and it makes all the bikeshedders come out, a
good unique, google-able name would be nice. And naming writes go to the
man who does the work, so enjoy :)
--
Michael Peters
Plus Three, LP


##### CGI::Application community mailing list ################
## ##
## To unsubscribe, or change your message delivery options, ##
## visit: http://www.erlbaum.net/mailman/listinfo/cgiapp ##
## ##
## Web archive: http://www.erlbaum.net/pipermail/cgiapp/ ##
## Wiki: http://cgiapp.erlbaum.net/ ##
## ##
################################################################
Richard Jones
2012-09-01 07:46:48 UTC
Permalink
Hi Mark,

I also use C::A everyday - my main application that I wrote and maintain
is a C::A. You are of course right that C::A uses some out-of-date
procedures like the query method. But since C::A first appeared we now
have newer frameworks like Catalyst, Mojo, and the more recent Dancer
(also in the process of being rewritten to embrace the Moose API). Given
that Ron has already forked C::A I wonder if there is any point
embarking on another?

Accepting that Catalyst is not to everyones taste, and Dancer may not
yet have the recognition and presence that Catalyst and Mojo/Mojolicious
have as web frameworks, I'm wondering what advantage a revamped C::A
under a new name will provide.

One essential item for any web framework is a competent dispatcher,
something I think compromises Dancer v1 (hopefully addressed in v2),
essential for an application with a large number of run-modes (or
equivalents). C::A::Dispatch or a core equivalent is a must IMO. I'm not
sure if that is what you had in mind with "global dispatching".

Still, best wishes for C::A mark II if you decide to go through with it,
and looking forward to seeing the draft code later this week :)
Post by Mark Stosberg
Hello Everyone.
I'll start with a apology about not being as present as I intended.
Messages from this list were not coming directly to my Inbox for some
time, and it took me longer than I wanted to get that addressed.
Starting today, messages should be going back in my Inbox again, and I
will attempt be more responsive here.
I'm still alive and well, and use and support CGI::Application every day
at work. I'm also now the primary maintainer of CGI.pm. While it's only
a part of the CGI::Application framework, it has substantially more
lines of code, as well as more bugs and bug traffic. More of my
maintenance time has been spent maintaining that lately.
I appreciate the fork that Ron Savage recently published, because it's
good to explore options, and it's easiest to evaluate options if they
are complete. I also agree with the spirit of it. It's time for the next
generation of the framework, one that breaks compatibility in some
places to move the whole forward.
I started writing my own fork over a year ago in hopes of having
something to share around the time for YAPC 2011. While I needed to put
that on hold for a while, It's now on the verge of the initial release.
It was interesting to find Ron's fork which had been developed
independently and in parallel, to see where we agreed and where we
differed.
Here are the key points I have mind for the update I'll be publishing
- A new name space, to avoid confusion and problems with API changes.
- A "::Compat" addition that allows people to keep using a maximal
amount of the old API if they need to. (Including a certain amount of
plugins)
- PSGI-native. I'm excited that Perl web frameworks are converging here.
We'll be able to take advantage of PSGI "Middleware" that was designed
with other frameworks in mind. Many things that were CGI::App plugins
before are now better done done as PSGI "Middleware". As a plugin
author, you get the benefit of having more users who may be using
other frameworks. The difference with CGI::App will be that PSGI will
the *only* code path supported.
- Uses Any::Moose / Mouse. I endorse the Moose API and Mouse brings
much of that API to lower resource environments, like the CGI
environment where CGI::Application has always performed well.
It's already possible to write a CGI::App subclass based on Moose or
Mouse, but like with PSGI, I think it's in our best interest to
upgrade to first class support.
Just as "PSGI Middleware" presents a new opportunity for code re-use,
Moose/Mouse "roles" present another alternative to "plugins" that can
be shared between frameworks. For example, methods for logging,
database access and "config" data are all good candidates to be
implemented as roles.
- Templating APIs removed from core, for now. We'll get a new templating
API, although the details are still TBD.
- Plans to replace CGI.pm with request and response objects. As the
CGI.pm maintainer, I could devote another full post to reasons why I
don't to be using it in another 5 or 10 years. Details here are still
to be determined as well.
Immediately we would see the "query()" method replaced with a "req"
method to represent a "request" object. HTTP has "requests" and
"responses". The idea of a "query object" is a CGI.pm'ism to leave
behind.
About every other Perl framework I've looked at models the response
and request this way, and it's time we implemented this sensible
design as well.
- The popular and small "::Forward()" and "::Redirect()" plugins will
be merged into the core.
As part of considering the future of CGI::Application, I did consider
just dropping it. I maintain it, but lack the emotional attachment of
being the original author. I stepped back and took a look at it from the
distance and compared it to alternatives. Outside of the few "details"
I'd like to change, I find the core of it still offers a unique
- I think the flow of the execution stages works very well. I'm talking
about "init", "setup", "prerun", "run", "postrun", "teardown", as
they are implemented in "new()" and "run()".
- Lightweight / fast start up time.
- Simple. Less code to learn, less chance for bugs.
- Global dispatching. That is, a single central table, rather than
storing dispatch details "locally", with each run mode.
- Ability to scale up. I find CGI::App suitable for large projects as
well as small.
There's also a great community of people and plugins around CGI::App as
well.
I look forward to being conversation with you all more about this. I'll
set a goal to release the first code-as-draft for my proposal within a
week, and look forward to your feedback to sculpt it into a releasable
form.
Thanks,
Mark
##### CGI::Application community mailing list ################
## ##
## To unsubscribe, or change your message delivery options, ##
## visit: http://www.erlbaum.net/mailman/listinfo/cgiapp ##
## ##
## Web archive: http://www.erlbaum.net/pipermail/cgiapp/ ##
## Wiki: http://cgiapp.erlbaum.net/ ##
## ##
################################################################
--
Richard Jones

##### CGI::Application community mailing list ################
## ##
## To unsubscribe, or change your message delivery options, ##
## visit: http://www.erlbaum.net/mailman/listinfo/cgiapp ##
## ##
## Web archive: http://www.erlbaum.net/pipermail/cgiapp/ ##
## Wiki: http://cgiapp.erlbaum.net/ ##
## ##
################################################################
Mark Stosberg
2012-09-08 03:36:32 UTC
Permalink
Richard,

Thanks for the feedback.
But since C::A first appeared we now have newer frameworks like
Catalyst, Mojo, and the more recent Dancer (also in the process of
being rewritten to embrace the Moose API). Given that Ron has already
forked C::A I wonder if there is any point embarking on another?
Accepting that Catalyst is not to everyones taste, and Dancer may not
yet have the recognition and presence that Catalyst and Mojo/Mojolicious
have as web frameworks, I'm wondering what advantage a revamped C::A
under a new name will provide.
I think each has it's own strengths. I looked at Mojo particularly
closely, contributing doc and test patches along the way as I studied
it. ( I was surprised to find that my contribution is still third
highest by number of commits, although I haven't contributed since 2009:
https://github.com/kraih/mojo/graphs/contributors ).

In some ways their is convergance towards PSGI and Moose. I think that's
a good thing, because there is now more re-use between frameworks.
There's also more competition now among "lightweight" frameworks.
Besides the one you mentioned, there is Web::Simple and Amon2, among
many more less well known frameworks.

I think CGI::App's basic design with stages and callbacks is worth
carrying forward. I think a lightweight impementation of the Moose API
is also worth supporting in the core, which is absent in Ron's fork.

Finally, I think quite a number of people deployed CGI::Application and
some of it's many plugins, and some of them like me would like a way
forward to modernize their systems without a complete rewrite.
One essential item for any web framework is a competent dispatcher,
something I think compromises Dancer v1 (hopefully addressed in v2),
essential for an application with a large number of run-modes (or
equivalents). C::A::Dispatch or a core equivalent is a must IMO. I'm not
sure if that is what you had in mind with "global dispatching".
I agree that dispatching has been central to web frameworks.

By "global dispatching" I mean centralized dispatching-- having one
place in your app to see all the URLs and what they app to. I call the
default Cataylst style "local" dispatching-- placing the URIs that
encompass the system next to the methods they map to.

I like the design of CGI::Application::Dispatch::PSGI and don't
currently have specific intents to change it.

I've come across one other routing solution that appealed to me.
Router::Simple has a nice OO syntax that's similar to what we use:
https://metacpan.org/module/Router::Simple

Amon2 then provides a nice DSL wrapper around it, so the resulting
dispatch entries look like this:

package MyApp::Web::Dispatcher;
use Amon2::Web::Dispatcher::RouterSimple;
connect '/' => 'Root#index';
connect '/my/' => 'My#index';
connect '/my/:action' => 'My';

https://metacpan.org/module/Amon2::Web::Dispatcher::RouterSimple
Still, best wishes for C::A mark II if you decide to go through with it,
Thanks!

Mark

##### CGI::Application community mailing list ################
## ##
## To unsubscribe, or change your message delivery options, ##
## visit: http://www.erlbaum.net/mailman/listinfo/cgiapp ##
## ##
## Web archive: http://www.erlbaum.net/pipermail/cgiapp/ ##
## Wiki: http://cgiapp.erlbaum.net/ ##
## ##
################################################################
B. Estrade
2012-09-05 17:57:22 UTC
Permalink
Thank you, Mark. Responses are inlined.
Post by Mark Stosberg
Hello Everyone.
I'll start with a apology about not being as present as I intended.
Messages from this list were not coming directly to my Inbox for some
time, and it took me longer than I wanted to get that addressed.
Starting today, messages should be going back in my Inbox again, and I
will attempt be more responsive here.
I'm still alive and well, and use and support CGI::Application every day
at work. I'm also now the primary maintainer of CGI.pm. While it's only
a part of the CGI::Application framework, it has substantially more
lines of code, as well as more bugs and bug traffic. More of my
maintenance time has been spent maintaining that lately.
I appreciate the fork that Ron Savage recently published, because it's
good to explore options, and it's easiest to evaluate options if they
are complete. I also agree with the spirit of it. It's time for the next
generation of the framework, one that breaks compatibility in some
places to move the whole forward.
I started writing my own fork over a year ago in hopes of having
something to share around the time for YAPC 2011. While I needed to put
that on hold for a while, It's now on the verge of the initial release.
It was interesting to find Ron's fork which had been developed
independently and in parallel, to see where we agreed and where we
differed.
It strikes me that CAP is more of a "way" or standard than any
particular implementation, even though I think it could certainly be
standardized or have that one true reference implementation.
Post by Mark Stosberg
Here are the key points I have mind for the update I'll be publishing
- A new name space, to avoid confusion and problems with API changes.
- A "::Compat" addition that allows people to keep using a maximal
amount of the old API if they need to. (Including a certain amount of
plugins)
Or maybe just do something like how perl5 turns on new version based
features (e.g., use CGI::Application q/1.2.3/;).
Post by Mark Stosberg
- PSGI-native. I'm excited that Perl web frameworks are converging here.
We'll be able to take advantage of PSGI "Middleware" that was designed
with other frameworks in mind. Many things that were CGI::App plugins
before are now better done done as PSGI "Middleware". As a plugin
author, you get the benefit of having more users who may be using
other frameworks. The difference with CGI::App will be that PSGI will
the *only* code path supported.
Nice.

I would like to warn that traditional persistent environments will
continue to remain relevant, and I think it's a mistake to discount
this.

Additionally, from what I have seen from the other frameworks, nothing
solves anything in principle beyond what CAP does. Some make it easier
to define runmodes or to set up dispatching, but you still need to
properly create a proper MVC separation and set of supporting modules.
It's the same amount of work no matter what you use.
Post by Mark Stosberg
- Uses Any::Moose / Mouse. I endorse the Moose API and Mouse brings
much of that API to lower resource environments, like the CGI
environment where CGI::Application has always performed well.
It's already possible to write a CGI::App subclass based on Moose or
Mouse, but like with PSGI, I think it's in our best interest to
upgrade to first class support.
I am not sure what this buys anyone, to be frank. I know that using
these object layering might incite some sort of religious war.
Ultimately, this decision is clearly in the hands of those who do the
work. I have my reservations about moving away from Perlish idioms
and towards the oop flavors of the week. Any core might be well served
by avoiding any sort of meta object sugar over the long haul.

I think my overall point is that CAP and what it provides is timeless.
The pendulum swings both ways, and it would be nice to see CAP focus
on improving its strengths and not trying to do what the other kids
might be doing.
Post by Mark Stosberg
Just as "PSGI Middleware" presents a new opportunity for code re-use,
Moose/Mouse "roles" present another alternative to "plugins" that can
be shared between frameworks. For example, methods for logging,
database access and "config" data are all good candidates to be
implemented as roles.
- Templating APIs removed from core, for now. We'll get a new templating
API, although the details are still TBD.
- Plans to replace CGI.pm with request and response objects. As the
CGI.pm maintainer, I could devote another full post to reasons why I
don't to be using it in another 5 or 10 years. Details here are still
to be determined as well.
Immediately we would see the "query()" method replaced with a "req"
method to represent a "request" object. HTTP has "requests" and
"responses". The idea of a "query object" is a CGI.pm'ism to leave
behind.
About every other Perl framework I've looked at models the response
and request this way, and it's time we implemented this sensible
design as well.
I think I am not really clear on what change in perspective means. Is
it truly a semantic change or is it just a different name? I am
somewhat familiar with some of the other new fangled frameworks, but
not well enough to know what the difference is between this
request/response versus query objects.
Post by Mark Stosberg
- The popular and small "::Forward()" and "::Redirect()" plugins will
be merged into the core.
It would be really nice to merge in some bare bones Authentication and
Authorization support - maybe ever by more fully developing CAP's lifecycle.
Post by Mark Stosberg
As part of considering the future of CGI::Application, I did consider
just dropping it. I maintain it, but lack the emotional attachment of
being the original author. I stepped back and took a look at it from the
distance and compared it to alternatives. Outside of the few "details"
I'd like to change, I find the core of it still offers a unique
- I think the flow of the execution stages works very well. I'm talking
about "init", "setup", "prerun", "run", "postrun", "teardown", as
they are implemented in "new()" and "run()".
- Lightweight / fast start up time.
- Simple. Less code to learn, less chance for bugs.
- Global dispatching. That is, a single central table, rather than
storing dispatch details "locally", with each run mode.
- Ability to scale up. I find CGI::App suitable for large projects as
well as small.
There's also a great community of people and plugins around CGI::App as
well.
I am a recent addition to this community, and prefer CAP well over the
other alternatives.
Post by Mark Stosberg
I look forward to being conversation with you all more about this. I'll
set a goal to release the first code-as-draft for my proposal within a
week, and look forward to your feedback to sculpt it into a releasable
form.
Here are some items I would like to see addressed.

1. scalability - it is unnecessarily awkward to have more than 2
levels of subclassing currently.

Direct subclass of CAP uses cgi_init; child of subclass uses setup;
anything else must call SUPER::setup.

2. a more fully developed lifecycle model - similar to the one that
Apache itself uses. In particular, it would be really helpful to have
explicit phases for state (e.g., Session munging), authentication,
and authorization. I imagine those 3 in particular to be extremely
helpful for building things like role based access control or single
sign-on into your application.

3. a more fully developed plugin/event system; I think this goes along
with #2 (i.e., a few more hooks), but in addition to this I have
always thought it would be useful to have some sort of mechanism
through which plugins might be able to query one another. A good
example (and actually the main motivation for #2 and #3) are the CAP
Authorization and Authentication plugins. The short list of troubles
I have had with using these two are:

* when used together, Authorization is called before Authentication,
making it awkward to handle authorization errors of unauthenticated
guests (or maybe Authz assumes an authenticated session);

* default behavior of Authz is to query directly the Authorization
plugin instance for a username; this works fine in that situation,
but there is no clear way for plugin A to make information available
to plugin B;

That's just an example. I think that these improvements would go a
long way to encouraging the timeless benefits that you've outlined
about CAP above.

4. more flexibility with the query object...err response object; I've
run into some hoops to jump through when I wanted to use CGI::Simple
and be able to upload capabilities on or off in a sub class.

5. persistence - I would like to say that I'd like to learn more about CAP and
the ecosystem in persistent environments. It's my impression that
there are some corner cases or funny issues with it. I do not claim
this is true, but I think that we can all agree that while persistent
environments such as mod_perl are considered old fashioned, I think
that they will prove remain relevant amist the tide of alternatives and
"middleware" laden configurations. For me, the ultimate goal would be
to use CAP to create a responsive and consistent daemon type
application as served by Apache, defined strictly through things like runmodes,
plugins, etc. Is PSGI the path to this? Maybe, maybe not.

6*. the last mile - in application frameworks, I am unsure of any that
take the finite state machine model to its logical max. This thought
may be way out there, but defining things like runmodes only takes you
so far. Going a step further, perhaps done through more feature dispatching
or routing, it'd be really nice to be able to define the application
runmodes in terms of a transition function (e.g., current runmode,
input, resulting runmode). In otherwords, support defining an
application to the fullest extent possible though some sort of runmode
dispatch table annotations.

*(forgive me this one is "out there", and I still have not sat down to
figure out what such a capability would look like or value it would
actually add)

Brett
Post by Mark Stosberg
Thanks,
Mark
##### CGI::Application community mailing list ################
## ##
## To unsubscribe, or change your message delivery options, ##
## visit: http://www.erlbaum.net/mailman/listinfo/cgiapp ##
## ##
## Web archive: http://www.erlbaum.net/pipermail/cgiapp/ ##
## Wiki: http://cgiapp.erlbaum.net/ ##
## ##
################################################################
--
Register Now for cPanel Conference
Oct 8-10, 2012, Houston, Texas
http://conference.cpanel.net/

##### CGI::Application community mailing list ################
## ##
## To unsubscribe, or change your message delivery options, ##
## visit: http://www.erlbaum.net/mailman/listinfo/cgiapp ##
## ##
## Web archive: http://www.erlbaum.net/pipermail/cgiapp/ ##
## Wiki: http://cgiapp.erlbaum.net/ ##
## ##
################################################################
Ron Savage
2012-09-05 23:12:40 UTC
Permalink
Hi Brett

I'm snipping this email because I expect to pen several replies.
Post by B. Estrade
Thank you, Mark. Responses are inlined.
Post by Mark Stosberg
- A "::Compat" addition that allows people to keep using a maximal
amount of the old API if they need to. (Including a certain amount of
plugins)
Changing the API and keeping a back-compat API means not changing the
API in the (new) back-compat part of the code.

This is always a difficult decision.

My basic feeling is if people stick with the (new) back-compat API they
might as well have stuck with the old (back-compat!) API.

So the question is, why not switch to the new API. Perhaps because some
people want to switch in small steps.

My policy is that if the switch is on, commit to the whole of the new API.
Post by B. Estrade
Or maybe just do something like how perl5 turns on new version based
features (e.g., use CGI::Application q/1.2.3/;).
Post by Mark Stosberg
- PSGI-native. I'm excited that Perl web frameworks are converging here.
We'll be able to take advantage of PSGI "Middleware" that was designed
with other frameworks in mind. Many things that were CGI::App plugins
before are now better done done as PSGI "Middleware". As a plugin
author, you get the benefit of having more users who may be using
other frameworks. The difference with CGI::App will be that PSGI will
the *only* code path supported.
Nice.
I already use Plack::Middleware::(ContentLength, Session and Static), in
various situations, when using CGI::Snapp.

You do realize that's possible, right?
Post by B. Estrade
I would like to warn that traditional persistent environments will
continue to remain relevant, and I think it's a mistake to discount
this.
Absolutely.

My policy is to make available tools for all programmers, not just those
who adopt the latest mechanism.

After all, there is always going to be a pool of programmers whose work
environment and/or personality is too conservative to let them be
amongst the first to switch. They may in fact make that switch years
after the leaders to. Or, any of us may be employed to support old code.
Post by B. Estrade
Additionally, from what I have seen from the other frameworks, nothing
solves anything in principle beyond what CAP does. Some make it easier
to define runmodes or to set up dispatching, but you still need to
properly create a proper MVC separation and set of supporting modules.
It's the same amount of work no matter what you use.
This is a marvellous point.

I've looked a Mojo a number of times, but despite its great cleverness,
it's major use seems to be smart switching of requests. Likewise, there
are now quite a new routing-oriented packages available. They all attack
the same problem, but it's a small part of a whole app. And the classic
CGI::Application::Dispatch (copied to CGI::Snapp::Dispatch) is a
beautifully simply way to do that.
Post by B. Estrade
Post by Mark Stosberg
- Uses Any::Moose / Mouse. I endorse the Moose API and Mouse brings
much of that API to lower resource environments, like the CGI
environment where CGI::Application has always performed well.
This is tricky. Why is the env low-resourced? And if it is, what's wrong
with targeting it with a low-overhead env such as non-Moose?
Post by B. Estrade
Post by Mark Stosberg
It's already possible to write a CGI::App subclass based on Moose or
Mouse, but like with PSGI, I think it's in our best interest to
upgrade to first class support.
I am not sure what this buys anyone, to be frank. I know that using
Me neither. For control freaks it obviously gives greater, er, control,
over parameters and attributes, but that alone does not guarantee great
apps.
Post by B. Estrade
these object layering might incite some sort of religious war.
Ultimately, this decision is clearly in the hands of those who do the
work. I have my reservations about moving away from Perlish idioms
and towards the oop flavors of the week. Any core might be well served
by avoiding any sort of meta object sugar over the long haul.
I think my overall point is that CAP and what it provides is timeless.
The pendulum swings both ways, and it would be nice to see CAP focus
on improving its strengths and not trying to do what the other kids
might be doing.
Post by Mark Stosberg
Just as "PSGI Middleware" presents a new opportunity for code re-use,
Moose/Mouse "roles" present another alternative to "plugins" that can
be shared between frameworks. For example, methods for logging,
database access and "config" data are all good candidates to be
implemented as roles.
This is important.

See:

- Class::Method::Delegate (no dependencies [actually Carp], no bugs)
- Role::Tiny (ditto [actually Exporter], 1 bug)
- Role::Basic (Storable, 3 bugs)
- Moo::Role (various, 2 bugs)
- Moose::Role (ditto, 52 bugs)

But see what Role::Tiny has to say about Role::Basic.

So Moose/Mouse are not actually needed, if smallness is a virtue.
Post by B. Estrade
Post by Mark Stosberg
- Templating APIs removed from core, for now. We'll get a new templating
API, although the details are still TBD.
Yep.
Post by B. Estrade
Post by Mark Stosberg
- Plans to replace CGI.pm with request and response objects. As the
CGI.pm maintainer, I could devote another full post to reasons why I
don't to be using it in another 5 or 10 years. Details here are still
to be determined as well.
This is important, and probably why moving to PSGI should be considered
if not done sooner rather than later.
Post by B. Estrade
I think I am not really clear on what change in perspective means. Is
it truly a semantic change or is it just a different name? I am
somewhat familiar with some of the other new fangled frameworks, but
not well enough to know what the difference is between this
request/response versus query objects.
In brief, the CGI way has been re-thought and replaced. The end result
is just request/response of course (what else could it be?), but done
again with the knowledge of years of experience with CGI.
Post by B. Estrade
Post by Mark Stosberg
- The popular and small "::Forward()" and "::Redirect()" plugins will
be merged into the core.
Good idea.
Post by B. Estrade
It would be really nice to merge in some bare bones Authentication and
Authorization support - maybe ever by more fully developing CAP's lifecycle.
Likewise. It's a pity a standard(!) way of doing this with CAP doesn't
seem to have evolved /with the approval of all/.
Post by B. Estrade
Here are some items I would like to see addressed.
1. scalability - it is unnecessarily awkward to have more than 2
levels of subclassing currently.
This statement worries me. Could you please expand.

Also, did you look at CGI::Snapp::Demo::Four::Wrapper, which easily
wraps CGI::Snapp::Demo::Four. It's specifically a (simple) demo of
sub-classing.
Post by B. Estrade
Direct subclass of CAP uses cgi_init; child of subclass uses setup;
anything else must call SUPER::setup.
How does this differ from any other class which uses sub-classing? The
parent method is either completely overridden or called /and/ partially
overridden. Or am I missing something?
Post by B. Estrade
3. a more fully developed plugin/event system; I think this goes along
with #2 (i.e., a few more hooks), but in addition to this I have
always thought it would be useful to have some sort of mechanism
through which plugins might be able to query one another. A good
example (and actually the main motivation for #2 and #3) are the CAP
Authorization and Authentication plugins. The short list of troubles
* when used together, Authorization is called before Authentication,
making it awkward to handle authorization errors of unauthenticated
guests (or maybe Authz assumes an authenticated session);
* default behavior of Authz is to query directly the Authorization
plugin instance for a username; this works fine in that situation,
but there is no clear way for plugin A to make information available
to plugin B;
There's no doubt they are awkward. I'd argue the underlying CAP
structure is sound, and just this part need a bug re-think.
Post by B. Estrade
4. more flexibility with the query object...err response object; I've
run into some hoops to jump through when I wanted to use CGI::Simple
and be able to upload capabilities on or off in a sub class.
It'd help if you could expand on this issue.
Post by B. Estrade
5. persistence - I would like to say that I'd like to learn more about CAP and
the ecosystem in persistent environments. It's my impression that
there are some corner cases or funny issues with it. I do not claim
this is true, but I think that we can all agree that while persistent
environments such as mod_perl are considered old fashioned, I think
that they will prove remain relevant amist the tide of alternatives and
"middleware" laden configurations. For me, the ultimate goal would be
to use CAP to create a responsive and consistent daemon type
application as served by Apache, defined strictly through things like runmodes,
plugins, etc. Is PSGI the path to this? Maybe, maybe not.
I only use plack (dev) and starman (prod), but I used to use
Apache(2)::Registry, with CAP. Is that what you're referring to.

Is there something specific which needs to be added?
Post by B. Estrade
6*. the last mile - in application frameworks, I am unsure of any that
take the finite state machine model to its logical max. This thought
may be way out there, but defining things like runmodes only takes you
so far. Going a step further, perhaps done through more feature dispatching
or routing, it'd be really nice to be able to define the application
runmodes in terms of a transition function (e.g., current runmode,
input, resulting runmode). In otherwords, support defining an
application to the fullest extent possible though some sort of runmode
dispatch table annotations.
Perhaps you need Mojo after all :-)).
Post by B. Estrade
*(forgive me this one is "out there", and I still have not sat down to
figure out what such a capability would look like or value it would
actually add)
On the contrary - many thanx.

We need all ideas to be put out there.......
--
Ron Savage
http://savage.net.au/
Ph: 0421 920 622

##### CGI::Application community mailing list ################
## ##
## To unsubscribe, or change your message delivery options, ##
## visit: http://www.erlbaum.net/mailman/listinfo/cgiapp ##
## ##
## Web archive: http://www.erlbaum.net/pipermail/cgiapp/ ##
## Wiki: http://cgiapp.erlbaum.net/ ##
## ##
################################################################
B. Estrade
2012-09-06 14:48:00 UTC
Permalink
Snipped
Post by Ron Savage
Hi Brett
Post by B. Estrade
It would be really nice to merge in some bare bones Authentication and
Authorization support - maybe ever by more fully developing CAP's lifecycle.
Likewise. It's a pity a standard(!) way of doing this with CAP doesn't
seem to have evolved /with the approval of all/.
Post by B. Estrade
Here are some items I would like to see addressed.
1. scalability - it is unnecessarily awkward to have more than 2
levels of subclassing currently.
This statement worries me. Could you please expand.
Also, did you look at CGI::Snapp::Demo::Four::Wrapper, which easily
wraps CGI::Snapp::Demo::Four. It's specifically a (simple) demo of
sub-classing.
Post by B. Estrade
Direct subclass of CAP uses cgi_init; child of subclass uses setup;
anything else must call SUPER::setup.
How does this differ from any other class which uses sub-classing? The
parent method is either completely overridden or called /and/ partially
overridden. Or am I missing something?
What I mean is that there are 2 methods that basically do the same
thing. If you have MyApp (ISA CGI::Application), you would initialize
runmodes and whatnot via cgiapp_init. Say you subclass MyApp to get
MyApp::Foo, but want to keep what is going on in MyApp::cgiapp_init;
but you have your own specific MyApp::Foo runmodes. You'd most cleanly
do this by defining MyApp::Foo::setup. Now, what if you want to
subclass MyApp::Foo into MyApp::Foo::Derp, but you have some Derp
specific runmodes. You end up having to redefine cgiapp_init or
setup; in either case, you're going to have to make an explicit call
to SUPER::cgiapp_init or SUPER::setup.

You're limited to 2 generations below CAP if you want to subclass
without explicitly calling on SUPER because you have 2 explicit
methods -cgiapp_init and setup. I am suggesting a way to provide any
number of generations without having to call on SUPER.

Here is my real world use case. I split my applications into 2 parts;
one amounts to the UI payload delivery, basically HTML that makes all
calls asynchronously. The other is strictly non-UI and handles only
asynchronous requests (i.e., the "REST" API). And I typically have
this hierarchy:

1. WebCommon.pm (ISA CGI::Application; implements Authentication and common run modes)
2. WebApp.pm (ISA WebCommon; base class for the UI delivery or initial "view")
3. WebAPI.pm (ISA WebCommon; base class for the "REST" API)
Post by Ron Savage
From there, I may have another or even another 2 levels of WebApps or
WebAPIs. In WebCommon.pm, I define cgiapp_init; in WebApps.pm and
WebAPI.pm, I define a setup. Beyond that, I redefine setup with a call
to $self->SUPER::setup - not something I really like doing.
Post by Ron Savage
Post by B. Estrade
3. a more fully developed plugin/event system; I think this goes along
with #2 (i.e., a few more hooks), but in addition to this I have
always thought it would be useful to have some sort of mechanism
through which plugins might be able to query one another. A good
example (and actually the main motivation for #2 and #3) are the CAP
Authorization and Authentication plugins. The short list of troubles
* when used together, Authorization is called before Authentication,
making it awkward to handle authorization errors of unauthenticated
guests (or maybe Authz assumes an authenticated session);
* default behavior of Authz is to query directly the Authorization
plugin instance for a username; this works fine in that situation,
but there is no clear way for plugin A to make information available
to plugin B;
There's no doubt they are awkward. I'd argue the underlying CAP
structure is sound, and just this part need a bug re-think.
Post by B. Estrade
4. more flexibility with the query object...err response object; I've
run into some hoops to jump through when I wanted to use CGI::Simple
and be able to upload capabilities on or off in a sub class.
It'd help if you could expand on this issue.
I want to use CGI::Simple, but do not want to enable uploads app-wide.
I have a subclass (WebAPI::UploadApp, say) where I do want to enable
uploads.

In WebCommon.pm, I have to do this:

our $cgi; #= CGI::Simple->new;
sub cgiapp_get_query {
use CGI::Simple ();
$cgi = CGI::Simple->new();
return $cgi;
}

Then in order to override that CGI::Simple to enable uploads, in
WebAPI::UploadApp, I have to do this:

sub cgiapp_get_query {
my $self = shift;
use CGI::Simple ();
$CGI::Simple::DISABLE_UPLOADS = 0;
$self::SUPER::cgi = CGI::Simple->new();
return $self::SUPER::cgi;
}

Granted, there is probably a more correct, cleaner, or better way to do
this; if so, I am all ears.
Post by Ron Savage
Post by B. Estrade
5. persistence - I would like to say that I'd like to learn more about CAP and
the ecosystem in persistent environments. It's my impression that
there are some corner cases or funny issues with it. I do not claim
this is true, but I think that we can all agree that while persistent
environments such as mod_perl are considered old fashioned, I think
that they will prove remain relevant amist the tide of alternatives and
"middleware" laden configurations. For me, the ultimate goal would be
to use CAP to create a responsive and consistent daemon type
application as served by Apache, defined strictly through things like runmodes,
plugins, etc. Is PSGI the path to this? Maybe, maybe not.
I only use plack (dev) and starman (prod), but I used to use
Apache(2)::Registry, with CAP. Is that what you're referring to.
Yes.
Post by Ron Savage
Is there something specific which needs to be added?
I don't know :)...I plan on investigating persistent environments more
in the near future.
Post by Ron Savage
Post by B. Estrade
6*. the last mile - in application frameworks, I am unsure of any that
take the finite state machine model to its logical max. This thought
may be way out there, but defining things like runmodes only takes you
so far. Going a step further, perhaps done through more feature dispatching
or routing, it'd be really nice to be able to define the application
runmodes in terms of a transition function (e.g., current runmode,
input, resulting runmode). In otherwords, support defining an
application to the fullest extent possible though some sort of runmode
dispatch table annotations.
Perhaps you need Mojo after all :-)).
Maybe so.
Post by Ron Savage
Post by B. Estrade
*(forgive me this one is "out there", and I still have not sat down to
figure out what such a capability would look like or value it would
actually add)
On the contrary - many thanx.
We need all ideas to be put out there.......
Thanks :)

Brett
Post by Ron Savage
--
Ron Savage
http://savage.net.au/
Ph: 0421 920 622
##### CGI::Application community mailing list ################
## ##
## To unsubscribe, or change your message delivery options, ##
## visit: http://www.erlbaum.net/mailman/listinfo/cgiapp ##
## ##
## Web archive: http://www.erlbaum.net/pipermail/cgiapp/ ##
## Wiki: http://cgiapp.erlbaum.net/ ##
## ##
################################################################
--
Register Now for cPanel Conference
Oct 8-10, 2012, Houston, Texas
http://conference.cpanel.net/

##### CGI::Application community mailing list ################
## ##
## To unsubscribe, or change your message delivery options, ##
## visit: http://www.erlbaum.net/mailman/listinfo/cgiapp ##
## ##
## Web archive: http://www.erlbaum.net/pipermail/cgiapp/ ##
## Wiki: http://cgiapp.erlbaum.net/ ##
## ##
################################################################
Rhesa Rozendaal
2012-09-06 17:04:24 UTC
Permalink
Post by B. Estrade
You're limited to 2 generations below CAP if you want to subclass
without explicitly calling on SUPER because you have 2 explicit
methods -cgiapp_init and setup. I am suggesting a way to provide any
number of generations without having to call on SUPER.
You're not limited to 2 levels of inheritance. The grandchild's SUPER
calls the child's method, and the child's SUPER calls the parent's
method. It'll work the same even when you add a grandchild. (At some
point I'd start asking myself if inheritance is really the way I'd want
to structure my application).
Post by B. Estrade
Here is my real world use case. I split my applications into 2 parts;
one amounts to the UI payload delivery, basically HTML that makes all
calls asynchronously. The other is strictly non-UI and handles only
asynchronous requests (i.e., the "REST" API). And I typically have
1. WebCommon.pm (ISA CGI::Application; implements Authentication and common run modes)
2. WebApp.pm (ISA WebCommon; base class for the UI delivery or initial "view")
3. WebAPI.pm (ISA WebCommon; base class for the "REST" API)
Post by Ron Savage
From there, I may have another or even another 2 levels of WebApps or
WebAPIs. In WebCommon.pm, I define cgiapp_init; in WebApps.pm and
WebAPI.pm, I define a setup. Beyond that, I redefine setup with a call
to $self->SUPER::setup - not something I really like doing.
You'd be better off setting up your runmodes in an init hook. That's the
way I do it in CA::Plugin::RunmodeDeclare.

package WebCommon;
use base 'CGI::Application';

__PACKAGE__->add_callback( init => sub {
$_[0]->run_modes([ ... ]);
});

package WebAPI;
use base 'WebCommon';

__PACKAGE__->add_callback( init => sub {
$_[0]->run_modes([ ... ]);
});

package WebAPI::Stuff;
use base 'WebAPI';

__PACKAGE__->add_callback( init => sub {
$_[0]->run_modes([ ... ]);
});



Then WebAPI has all the run modes of WebCommon, as well as its own run
modes. And WebAPI::Stuff has those of WebAPI and its own.

However, I'd ask myself if I really want to have all those parent run
modes in the child app.
Post by B. Estrade
I want to use CGI::Simple, but do not want to enable uploads app-wide.
I have a subclass (WebAPI::UploadApp, say) where I do want to enable
uploads.
our $cgi; #= CGI::Simple->new;
Don't do this. You need a query object that's an attribute of the
current CA object. A package variable is going to have too wide a scope.
Post by B. Estrade
sub cgiapp_get_query {
use CGI::Simple ();
$cgi = CGI::Simple->new();
return $cgi;
}
This is better written as:

sub cgiapp_get_query {
use CGI::Simple;
return CGI::Simple->new;
}
Post by B. Estrade
Then in order to override that CGI::Simple to enable uploads, in
sub cgiapp_get_query {
my $self = shift;
use CGI::Simple ();
$CGI::Simple::DISABLE_UPLOADS = 0;
$self::SUPER::cgi = CGI::Simple->new();
return $self::SUPER::cgi;
}
That code makes little sense. cgiapp_get_query is supposed to return a
CGI compatible object. It's not supposed to change variables in another
package.

This is what you should do instead:

sub cgiapp_get_query {
local $CGI::Simple::DISABLE_UPLOADS = 0;
return $_[0]->SUPER::cgiapp_get_query;
}
Post by B. Estrade
Granted, there is probably a more correct, cleaner, or better way to do
this; if so, I am all ears.
The only ugly thing about that is that package variable to influence
upload behavior. It'd be prettier if CGI::Simple had an accessor for
that, or a constructor argument. That's what you get for trying to be
compatible with CGI.pm I guess ;)

rhesa

##### CGI::Application community mailing list ################
## ##
## To unsubscribe, or change your message delivery options, ##
## visit: http://www.erlbaum.net/mailman/listinfo/cgiapp ##
## ##
## Web archive: http://www.erlbaum.net/pipermail/cgiapp/ ##
## Wiki: http://cgiapp.erlbaum.net/ ##
## ##
################################################################
B. Estrade
2012-09-07 14:20:39 UTC
Permalink
Thank you, Rhesa. This is helpful.

My last common on cgiapp_init and setup will be this. It's not simply
how deeply inheritance can be, it's the fact that there are 2 explicit
API methods for initializing an instance beyond what is provided for
in the ancestor. For me, it'd make more sense to do a way with setup
altogether and use a method similar to the init hook you mentioned
below. I am sure MMWV, but I will take your advice below. Thanks for
the help.

Brett
Post by Rhesa Rozendaal
Post by B. Estrade
You're limited to 2 generations below CAP if you want to subclass
without explicitly calling on SUPER because you have 2 explicit
methods -cgiapp_init and setup. I am suggesting a way to provide any
number of generations without having to call on SUPER.
You're not limited to 2 levels of inheritance. The grandchild's SUPER
calls the child's method, and the child's SUPER calls the parent's
method. It'll work the same even when you add a grandchild. (At some
point I'd start asking myself if inheritance is really the way I'd want
to structure my application).
Post by B. Estrade
Here is my real world use case. I split my applications into 2 parts;
one amounts to the UI payload delivery, basically HTML that makes all
calls asynchronously. The other is strictly non-UI and handles only
asynchronous requests (i.e., the "REST" API). And I typically have
1. WebCommon.pm (ISA CGI::Application; implements Authentication and common run modes)
2. WebApp.pm (ISA WebCommon; base class for the UI delivery or initial "view")
3. WebAPI.pm (ISA WebCommon; base class for the "REST" API)
Post by Ron Savage
From there, I may have another or even another 2 levels of WebApps or
WebAPIs. In WebCommon.pm, I define cgiapp_init; in WebApps.pm and
WebAPI.pm, I define a setup. Beyond that, I redefine setup with a call
to $self->SUPER::setup - not something I really like doing.
You'd be better off setting up your runmodes in an init hook. That's the
way I do it in CA::Plugin::RunmodeDeclare.
package WebCommon;
use base 'CGI::Application';
__PACKAGE__->add_callback( init => sub {
$_[0]->run_modes([ ... ]);
});
package WebAPI;
use base 'WebCommon';
__PACKAGE__->add_callback( init => sub {
$_[0]->run_modes([ ... ]);
});
package WebAPI::Stuff;
use base 'WebAPI';
__PACKAGE__->add_callback( init => sub {
$_[0]->run_modes([ ... ]);
});
Then WebAPI has all the run modes of WebCommon, as well as its own run
modes. And WebAPI::Stuff has those of WebAPI and its own.
However, I'd ask myself if I really want to have all those parent run
modes in the child app.
Post by B. Estrade
I want to use CGI::Simple, but do not want to enable uploads app-wide.
I have a subclass (WebAPI::UploadApp, say) where I do want to enable
uploads.
our $cgi; #= CGI::Simple->new;
Don't do this. You need a query object that's an attribute of the
current CA object. A package variable is going to have too wide a scope.
Post by B. Estrade
sub cgiapp_get_query {
use CGI::Simple ();
$cgi = CGI::Simple->new();
return $cgi;
}
sub cgiapp_get_query {
use CGI::Simple;
return CGI::Simple->new;
}
Post by B. Estrade
Then in order to override that CGI::Simple to enable uploads, in
sub cgiapp_get_query {
my $self = shift;
use CGI::Simple ();
$CGI::Simple::DISABLE_UPLOADS = 0;
$self::SUPER::cgi = CGI::Simple->new();
return $self::SUPER::cgi;
}
That code makes little sense. cgiapp_get_query is supposed to return a
CGI compatible object. It's not supposed to change variables in another
package.
sub cgiapp_get_query {
local $CGI::Simple::DISABLE_UPLOADS = 0;
return $_[0]->SUPER::cgiapp_get_query;
}
Post by B. Estrade
Granted, there is probably a more correct, cleaner, or better way to do
this; if so, I am all ears.
The only ugly thing about that is that package variable to influence
upload behavior. It'd be prettier if CGI::Simple had an accessor for
that, or a constructor argument. That's what you get for trying to be
compatible with CGI.pm I guess ;)
rhesa
##### CGI::Application community mailing list ################
## ##
## To unsubscribe, or change your message delivery options, ##
## visit: http://www.erlbaum.net/mailman/listinfo/cgiapp ##
## ##
## Web archive: http://www.erlbaum.net/pipermail/cgiapp/ ##
## Wiki: http://cgiapp.erlbaum.net/ ##
## ##
################################################################
##### CGI::Application community mailing list ################
## ##
## To unsubscribe, or change your message delivery options, ##
## visit: http://www.erlbaum.net/mailman/listinfo/cgiapp ##
## ##
## Web archive: http://www.erlbaum.net/pipermail/cgiapp/ ##
## Wiki: http://cgiapp.erlbaum.net/ ##
## ##
################################################################
Ron Savage
2012-09-06 23:52:46 UTC
Permalink
Hi Brett
Post by B. Estrade
What I mean is that there are 2 methods that basically do the same
thing. If you have MyApp (ISA CGI::Application), you would initialize
runmodes and whatnot via cgiapp_init. Say you subclass MyApp to get
MyApp::Foo, but want to keep what is going on in MyApp::cgiapp_init;
but you have your own specific MyApp::Foo runmodes. You'd most cleanly
do this by defining MyApp::Foo::setup. Now, what if you want to
subclass MyApp::Foo into MyApp::Foo::Derp, but you have some Derp
specific runmodes. You end up having to redefine cgiapp_init or
setup; in either case, you're going to have to make an explicit call
to SUPER::cgiapp_init or SUPER::setup.
You're limited to 2 generations below CAP if you want to subclass
without explicitly calling on SUPER because you have 2 explicit
methods -cgiapp_init and setup. I am suggesting a way to provide any
number of generations without having to call on SUPER.
Rhesa has replied with one (slightly more complex) way of doing things.
Here is another:

package WebCommon;
use base 'CGI::Application';

sub cgi_init # or setup
{
$self -> web_common_init;
}

package WebAPI;
use base 'WebCommon';

sub cgi_init # or setup
{
$self -> web_api_init;
}

package WebAPI::Stuff;
use base 'WebAPI';

sub cgi_init # or setup
{
$self -> web_api_stuff_init;
}

The 3 new subs can be stand-alone or call each other or call common
code. They can do whatever you think best.

The point is that the sub-class cgi_inits are overridden by the /normal/
operation of CAP, and hence are called at the appropriate time
/automatically/.

Obviously you can call SUPER::cgi_init or SUPER::anything if you wish.

(Sometimes of course calling a super class's method is mandatory. For
instance, with CGI::Snapp, a sub-class must call SUPER::_init($arg), as
in the demo. But that's to initialize object-level variables, having
nothing to do with what we're talking about.)

The problem is that SUPER::* is a way of sharing /all/ the code in the
super class's cgi_init.

If you don't wish to do that, then do as I've indicated above, and just
share none or some of the code via web_common_init etc. You really do
have a variety of ways to work.

Lastly, there is no limit on the depth of nesting possible.
--
Ron Savage
http://savage.net.au/
Ph: 0421 920 622

##### CGI::Application community mailing list ################
## ##
## To unsubscribe, or change your message delivery options, ##
## visit: http://www.erlbaum.net/mailman/listinfo/cgiapp ##
## ##
## Web archive: http://www.erlbaum.net/pipermail/cgiapp/ ##
## Wiki: http://cgiapp.erlbaum.net/ ##
## ##
################################################################
Mark Stosberg
2012-09-09 00:28:29 UTC
Permalink
Post by Ron Savage
Post by B. Estrade
Post by Mark Stosberg
- Uses Any::Moose / Mouse. I endorse the Moose API and Mouse brings
much of that API to lower resource environments, like the CGI
environment where CGI::Application has always performed well.
This is tricky. Why is the env low-resourced? And if it is, what's wrong
with targeting it with a low-overhead env such as non-Moose?
I'm thinking primarily of these environments:

- CGI, used in shared hosting accounts where there is persistent option
- Automated tests, which like CGI, need to load modules each time.

These environments also see non-persistent CGI::App use sometimes:

- Cron scripts (I use CGI::App for cron scripts for convenience)
- Interactive command-line scripts (I also use CGI::App for some of
these which are part of a large website).

I'm not thinking so much in terms hardware. A few years ago I
benchmarked the start-up times of various Perl-based web building tools,
which would apply to the environments above:


http://mark.stosberg.com/blog/2008/11/startup-benchmarks-for-mojo-catalyst-titanium-httpengine-and-cgiapplication.html

Since then, hardware has gotten faster, and SSDs are becoming more
common. Today I benchmark "Mouse" taking .05 seconds to load on my
laptop. That's price I think is completely reasonable to pay. Without
using a timing tool, the difference in indistinquishable from "instant".

time -p perl -MMouse -e 1
Post by Ron Savage
Post by B. Estrade
these object layering might incite some sort of religious war.
Ultimately, this decision is clearly in the hands of those who do the
work. I have my reservations about moving away from Perlish idioms
and towards the oop flavors of the week. Any core might be well served
by avoiding any sort of meta object sugar over the long haul.
I think my overall point is that CAP and what it provides is timeless.
The pendulum swings both ways, and it would be nice to see CAP focus
on improving its strengths and not trying to do what the other kids
might be doing.
Post by Mark Stosberg
Just as "PSGI Middleware" presents a new opportunity for code re-use,
Moose/Mouse "roles" present another alternative to "plugins" that can
be shared between frameworks. For example, methods for logging,
database access and "config" data are all good candidates to be
implemented as roles.
This is important.
- Class::Method::Delegate (no dependencies [actually Carp], no bugs)
- Role::Tiny (ditto [actually Exporter], 1 bug)
- Role::Basic (Storable, 3 bugs)
- Moo::Role (various, 2 bugs)
- Moose::Role (ditto, 52 bugs)
But see what Role::Tiny has to say about Role::Basic.
So Moose/Mouse are not actually needed, if smallness is a virtue.
I also see that CGI.pm has over 80 open bugs, while
Plack::Request/Plack::Response appear to have 2 open bugs in the Plack
bug queue that apply to them, with both them appearing to be enhancement
requests.

The number of bug reports a project has seems to often be driven by
popularity. There's also a certain accumulation that comes with age.
The comparison above is misleading in any case, as as the "small" role
solutions have just one module or so in the distribution, so those bugs
are exactly about roles. The Moose bug queue is for the whole Moose
project. Only about 5 or 6 that I see have "role" in the title of the
bug reports.

Also consider that CGI.pm has one person committing fixes for the 80+
bugs (for lack of interest from others, it seems), while the Moose
project appears to have about 8 maintainers.

On it's own, I don't think the general presence of bugs in a bug queue
presents a great concern about the quality of project, although specific
bugs certainly could. Are there specific bugs with Moose or Mouse roles
that you find troubling?

Mark

##### CGI::Application community mailing list ################
## ##
## To unsubscribe, or change your message delivery options, ##
## visit: http://www.erlbaum.net/mailman/listinfo/cgiapp ##
## ##
## Web archive: http://www.erlbaum.net/pipermail/cgiapp/ ##
## Wiki: http://cgiapp.erlbaum.net/ ##
## ##
################################################################
Ron Savage
2012-09-09 00:44:03 UTC
Permalink
Hi Mark
Post by Mark Stosberg
Post by Ron Savage
Post by B. Estrade
Post by Mark Stosberg
- Uses Any::Moose / Mouse. I endorse the Moose API and Mouse brings
much of that API to lower resource environments, like the CGI
environment where CGI::Application has always performed well.
This is tricky. Why is the env low-resourced? And if it is, what's wrong
with targeting it with a low-overhead env such as non-Moose?
- CGI, used in shared hosting accounts where there is persistent option
- Automated tests, which like CGI, need to load modules each time.
- Cron scripts (I use CGI::App for cron scripts for convenience)
- Interactive command-line scripts (I also use CGI::App for some of
these which are part of a large website).
OK. Good points.
Post by Mark Stosberg
I'm not thinking so much in terms hardware. A few years ago I
benchmarked the start-up times of various Perl-based web building tools,
http://mark.stosberg.com/blog/2008/11/startup-benchmarks-for-mojo-catalyst-titanium-httpengine-and-cgiapplication.html
Since then, hardware has gotten faster, and SSDs are becoming more
common. Today I benchmark "Mouse" taking .05 seconds to load on my
laptop. That's price I think is completely reasonable to pay. Without
using a timing tool, the difference in indistinquishable from "instant".
Agreed: .05 sec is nothing.
Post by Mark Stosberg
time -p perl -MMouse -e 1
Post by Ron Savage
Post by B. Estrade
these object layering might incite some sort of religious war.
Ultimately, this decision is clearly in the hands of those who do the
work. I have my reservations about moving away from Perlish idioms
and towards the oop flavors of the week. Any core might be well served
by avoiding any sort of meta object sugar over the long haul.
I think my overall point is that CAP and what it provides is timeless.
The pendulum swings both ways, and it would be nice to see CAP focus
on improving its strengths and not trying to do what the other kids
might be doing.
Post by Mark Stosberg
Just as "PSGI Middleware" presents a new opportunity for code re-use,
Moose/Mouse "roles" present another alternative to "plugins" that can
be shared between frameworks. For example, methods for logging,
database access and "config" data are all good candidates to be
implemented as roles.
This is important.
- Class::Method::Delegate (no dependencies [actually Carp], no bugs)
- Role::Tiny (ditto [actually Exporter], 1 bug)
- Role::Basic (Storable, 3 bugs)
- Moo::Role (various, 2 bugs)
- Moose::Role (ditto, 52 bugs)
But see what Role::Tiny has to say about Role::Basic.
So Moose/Mouse are not actually needed, if smallness is a virtue.
I also see that CGI.pm has over 80 open bugs, while
Plack::Request/Plack::Response appear to have 2 open bugs in the Plack
bug queue that apply to them, with both them appearing to be enhancement
requests.
The number of bug reports a project has seems to often be driven by
popularity. There's also a certain accumulation that comes with age.
The comparison above is misleading in any case, as as the "small" role
solutions have just one module or so in the distribution, so those bugs
are exactly about roles. The Moose bug queue is for the whole Moose
project. Only about 5 or 6 that I see have "role" in the title of the
bug reports.
Also consider that CGI.pm has one person committing fixes for the 80+
bugs (for lack of interest from others, it seems), while the Moose
project appears to have about 8 maintainers.
On it's own, I don't think the general presence of bugs in a bug queue
presents a great concern about the quality of project, although specific
bugs certainly could. Are there specific bugs with Moose or Mouse roles
that you find troubling?
Nope. I did not intend the # of bugs to say anything about the relative
merits of the modules. It was all about (potential) user education.

IMHO Role::Tiny looks like the best choice.
--
Ron Savage
http://savage.net.au/
Ph: 0421 920 622

##### CGI::Application community mailing list ################
## ##
## To unsubscribe, or change your message delivery options, ##
## visit: http://www.erlbaum.net/mailman/listinfo/cgiapp ##
## ##
## Web archive: http://www.erlbaum.net/pipermail/cgiapp/ ##
## Wiki: http://cgiapp.erlbaum.net/ ##
## ##
################################################################
Mark Stosberg
2012-09-08 22:10:55 UTC
Permalink
Brett,

Thanks for the feedback.
Post by B. Estrade
Post by Mark Stosberg
- A "::Compat" addition that allows people to keep using a maximal
amount of the old API if they need to. (Including a certain amount of
plugins)
Or maybe just do something like how perl5 turns on new version based
features (e.g., use CGI::Application q/1.2.3/;).
My goal there is to really start fresh, and have a minimal amount of
extra stuff in the core. No one is being forced to upgrade, and changing
a single line of code seems reasonable for those who want to upgrade the
module without updating any of their other project code.
Post by B. Estrade
Post by Mark Stosberg
- PSGI-native. I'm excited that Perl web frameworks are converging here.
We'll be able to take advantage of PSGI "Middleware" that was designed
with other frameworks in mind. Many things that were CGI::App plugins
before are now better done done as PSGI "Middleware". As a plugin
author, you get the benefit of having more users who may be using
other frameworks. The difference with CGI::App will be that PSGI will
the *only* code path supported.
Nice.
I would like to warn that traditional persistent environments will
continue to remain relevant, and I think it's a mistake to discount
this.
I assume you mean mod_perl and FastCGI? PSGI helps code to run in those
environments in a clean way. In those cases, it's definitely preferable
to the old way of having framework code that includes conditionals for
each environment. The guts of CGI.pm are an example of that ugliness.
Post by B. Estrade
Additionally, from what I have seen from the other frameworks, nothing
solves anything in principle beyond what CAP does. Some make it easier
to define runmodes or to set up dispatching, but you still need to
properly create a proper MVC separation and set of supporting modules.
It's the same amount of work no matter what you use.
I disagree that it's the same amount of work no matter what choices you
make. Some are easier to install, some are easier to learn, and some
have more formality that provide ready-made discipline to help organize
more complex projects.
Post by B. Estrade
Post by Mark Stosberg
- Uses Any::Moose / Mouse. I endorse the Moose API and Mouse brings
much of that API to lower resource environments, like the CGI
environment where CGI::Application has always performed well.
It's already possible to write a CGI::App subclass based on Moose or
Mouse, but like with PSGI, I think it's in our best interest to
upgrade to first class support.
I am not sure what this buys anyone, to be frank.
I appreciate the frankness. :)
Post by B. Estrade
I know that using these object layering might incite some sort of
religious war. Ultimately, this decision is clearly in the hands of
those who do the work. I have my reservations about moving away from
Perlish idioms and towards the oop flavors of the week. Any core might
be well served by avoiding any sort of meta object sugar over the long
haul.
Moose was first released over six years ago, so I don't think it's fair
to call it's popularity weekly. With Any::Mouse, performance is good in
CGI environments via Mouse, and also good in persistent environments
with Moose. We've now reached a "Moose tipping point" where a project of
any significant size is likely to be loading Moose or Mouse or Moo
anyway, so whether to load them or not has become last of an issue.

For example, if you want to access Amazon APIs via Perl, you'd likely
choose Net::Amazon::S3, which loads Moose. If you use the modern
Text::XSlate templating system, you'll be loading Mouse. If you want to
conveniently access cookies in Test::WWW::Mechanize than you might use
HTTP::CookieMonster, which loads Moo.

Importantly, there's no requirement to use these in your own modules, or
even switch from CGI::Application to the new project.
Post by B. Estrade
I think my overall point is that CAP and what it provides is timeless.
The pendulum swings both ways, and it would be nice to see CAP focus
on improving its strengths and not trying to do what the other kids
might be doing.
I agree that there are timeless basic principles in there. I appreciate
PSGI and the Moose APIs because there are helping bring the Perl web
development community together by providing good options for re-using
code between frameworks, with PSGI Middleware and Moose roles.
Post by B. Estrade
Post by Mark Stosberg
- Plans to replace CGI.pm with request and response objects. As the
CGI.pm maintainer, I could devote another full post to reasons why I
don't to be using it in another 5 or 10 years. Details here are still
to be determined as well.
Immediately we would see the "query()" method replaced with a "req"
method to represent a "request" object. HTTP has "requests" and
"responses". The idea of a "query object" is a CGI.pm'ism to leave
behind.
About every other Perl framework I've looked at models the response
and request this way, and it's time we implemented this sensible
design as well.
I think I am not really clear on what change in perspective means. Is
it truly a semantic change or is it just a different name? I am
somewhat familiar with some of the other new fangled frameworks, but
not well enough to know what the difference is between this
request/response versus query objects.
A "Query object" seems to be defined as "whatever functionality CGI.pm"
provides. I could perhaps understand "query" as a synonym for "HTTP
request", but what does it have to do with the header() method used for
generating HTTP responses?

Consider:

CGI.pm:
Set a response header: $q->header('Foo' => 1);
Get a response header: XXX Can't do it!
Get a request header : $q->http('Foo');

Plack::Request/Response:
Set a response header: $res->header('Foo' => 1 );
Get a response header: $res->header('Foo');
Get a request header : $req->header('Foo');

With, CGI.pm, looking at a request header can be confusing and
asymettric. (Perhaps you've been sent a header to tell you whether to
return JSON or HTML). header() for responses, and "http()" for
requests??

A design like that of Plack::Request/Response better models reality,
with a symettric API that handles incoming and outgoing requests in a
uniform way.

Another advantage would be the compability with other frameworks use the
use "res" and "req" response and requests. That would enable some kinds
of simple plugins to be shared.
Post by B. Estrade
Post by Mark Stosberg
- The popular and small "::Forward()" and "::Redirect()" plugins will
be merged into the core.
It would be really nice to merge in some bare bones Authentication and
Authorization support - maybe ever by more fully developing CAP's lifecycle.
More detailed suggestions would be welcome here, but I'm hestitent. Are
there examples of other frames that do something here in a way that's
appealing?

I would generally plan to keep the core small, but would welcome more
full-featured stacks to be shipped that were based on it, as Titanium
did for CGI::Application.

One project that strikes me as interesting here is "Abilities".
It addresses the problem space by using a "role". It is framework
independent, but is intended to be used as part of web applications.

https://metacpan.org/module/Abilities

This is an example of the kind of code I would like to make more easily
available to CGI::App based projects.
Post by B. Estrade
I am a recent addition to this community, and prefer CAP well over the
other alternatives.
That's good to hear, and welcome. Could you say more about why you
prefer it and how you use it?
Post by B. Estrade
1. scalability - it is unnecessarily awkward to have more than 2
levels of subclassing currently.
Direct subclass of CAP uses cgi_init; child of subclass uses setup;
anything else must call SUPER::setup.
Another option I use sometimes is to use the callback system:

# Register an action to happen at the init stage.
__PACKAGE__->add_callback('init', sub {

});

Note that the Moose API also helps here as well, as it allows you to say
this:

# Add some additional functionality after 'setup' runs in the parent
after 'setup' => sub {
my $self = shift;
};


https://metacpan.org/module/Moose::Manual::MethodModifiers#BEFORE-and-AFTER-modifiers

The Moose API also provides "BUILD", which like our callback system is
called for every class in the inheritance hierarchy. So another way to
add some "initialization" functionality would be to put this in your
Moose/Mouse based child class:

# Another way to add extra functionality when setting up classes.
sub BUILD {
my $self = shift;
}
Post by B. Estrade
2. a more fully developed lifecycle model - similar to the one that
Apache itself uses. In particular, it would be really helpful to have
explicit phases for state (e.g., Session munging), authentication,
and authorization. I imagine those 3 in particular to be extremely
helpful for building things like role based access control or single
sign-on into your application.
I agree that session, authentication and authorization are all useful,
but it's not clear to me what significant gains formal phase definitions
here would bring us. Do you have examples where this design has been put
to great use? Currently, our plugins in these areas use the calback
system to hook in at the phases that are useful for them, and that seems
to work well enough.
Post by B. Estrade
3. a more fully developed plugin/event system; I think this goes along
with #2 (i.e., a few more hooks), but in addition to this I have
always thought it would be useful to have some sort of mechanism
through which plugins might be able to query one another. A good
example (and actually the main motivation for #2 and #3) are the CAP
Authorization and Authentication plugins. The short list of troubles
* when used together, Authorization is called before Authentication,
making it awkward to handle authorization errors of unauthenticated
guests (or maybe Authz assumes an authenticated session);
* default behavior of Authz is to query directly the Authorization
plugin instance for a username; this works fine in that situation,
but there is no clear way for plugin A to make information available
to plugin B;
That's just an example. I think that these improvements would go a
long way to encouraging the timeless benefits that you've outlined
about CAP above.
Regarding "more hooks", we already have an API to add custom hooks who
folks who want more than the standard ones. Some plugins use this
functionality to provide hooks that come part of their own published
API.

Regarding "plugins querying each other", the Moose "Meta Object Protocol"
provides functionality in this area that we could take advantage of.
We can check to see if an object "does" a role, or check to
see if the "original_package_name" matches the plugin we can expect.

https://metacpan.org/module/Moose::Manual::Roles
https://metacpan.org/module/Class::MOP::Method
Post by B. Estrade
4. more flexibility with the query object...err response object; I've
run into some hoops to jump through when I wanted to use CGI::Simple
and be able to upload capabilities on or off in a sub class.
You'll have be more specific here. The framework already allows you to
use alternate query objects, and requires very few methods of it.

Splitting the query object into response and request objects would
immediately provide flexibility, as you could replace the objects
independently. :)

Regarding turning uploads on and off independently, Plack::Request
includes flexibility here, as upload handling is split off into it's own
module, as Plack::Request::Upload. You could easily make an alternate
class for uploads that behaved differently.

Perhaps want you want to do in your case is to reject "POST" requests as
soon as possible. In that case, using a Plack "Middleware" may be best
solution, as it can take action even before the content is prepared for
processing by your application.
Post by B. Estrade
5. persistence - I would like to say that I'd like to learn more about
CAP and the ecosystem in persistent environments. It's my impression
that there are some corner cases or funny issues with it. I do not
claim this is true, but I think that we can all agree that while
persistent environments such as mod_perl are considered old fashioned,
I think that they will prove remain relevant amist the tide of
alternatives and "middleware" laden configurations. For me, the
ultimate goal would be to use CAP to create a responsive and
consistent daemon type application as served by Apache, defined
strictly through things like runmodes, plugins, etc. Is PSGI the path
to this? Maybe, maybe not.
I use CGI::Application almost exclusively under mod_perl 2 now, and am
not aware of significant "gotchas" there. When I switch my large
application over to PSGI (from vanilla mod_perl 2), it will still be
running under mod_perl 2, only with a PSGI adapter.

I don't see Apache/mod_perl2 and "Middleware" as being at odds with each
other. Sometimes they provide different solutions. Sometimes an Apache
solution may perform better, sometimes a Middleware solution may be
preferred for being hackable pure Perl.

I'm personal curious to evaluate replacing Apache with Starman as an app
server, with Nginx in front of it serving static content and acting as a
reverse-proxy. (I already use Nginx this way, but only with Apache on
the backend).
Post by B. Estrade
6*. the last mile - in application frameworks, I am unsure of any that
take the finite state machine model to its logical max. This thought
may be way out there, but defining things like runmodes only takes you
so far. Going a step further, perhaps done through more feature dispatching
or routing, it'd be really nice to be able to define the application
runmodes in terms of a transition function (e.g., current runmode,
input, resulting runmode). In otherwords, support defining an
application to the fullest extent possible though some sort of runmode
dispatch table annotations.
I'll have to wait for the more specific proposal on this point. :)

Mark

##### CGI::Application community mailing list ################
## ##
## To unsubscribe, or change your message delivery options, ##
## visit: http://www.erlbaum.net/mailman/listinfo/cgiapp ##
## ##
## Web archive: http://www.erlbaum.net/pipermail/cgiapp/ ##
## Wiki: http://cgiapp.erlbaum.net/ ##
## ##
################################################################
B. Estrade
2012-09-10 14:05:11 UTC
Permalink
Thank you, Mark.

I accept what you so at face value and will seek to educate myself
more. Below I address the questions you asked me.

On Sat, Sep 08, 2012 at 06:10:55PM -0400, Mark Stosberg wrote:
snip..
Post by Mark Stosberg
Post by B. Estrade
It would be really nice to merge in some bare bones Authentication and
Authorization support - maybe ever by more fully developing CAP's lifecycle.
More detailed suggestions would be welcome here, but I'm hestitent. Are
there examples of other frames that do something here in a way that's
appealing?
Not that I know of; I must admit I am a one trick pony wrt frameworks.
CAP is all I use and know.
Post by Mark Stosberg
I would generally plan to keep the core small, but would welcome more
full-featured stacks to be shipped that were based on it, as Titanium
did for CGI::Application.
My motivation for this is based on our needs. We use CAP to write not
just authenticated applications, but those with role based
authorization. I have had moderate success using Authen and Authz,
but in order to do what was necessary to Authen before Authz or to
properly scale out the RBAC restrictions, I had to ditch both and
implement my own callbacks during the prerun stage. I suppose both
plugins got be over the learning curve, and after I was able to
implement authentication and authorization without the plugins.

Anyway, my main reason for recommending these 2 in particular as
bona fide life cycle events is that the mirror Apache's life cycle. I
think this reflects the value of these two stages. The first
(authentication) is simply for verifying to some degree that the actor
on the system is who they claim to be; the authorization is to ensure
that this authentication actor has authorized to execute the targeted
run mode. Both are prerun type of stages, but first classing them
would be nice.

I am not sure I can persuade you to formalize these two stages in
particular, but I hope that you consider this. I believe that
authentication and RBAC style authorization is only going to become
more important, and if nothing these stages would provide a clue to
application programmers that CAP is very much suitable for industrial
strenght web applications.
Post by Mark Stosberg
One project that strikes me as interesting here is "Abilities".
It addresses the problem space by using a "role". It is framework
independent, but is intended to be used as part of web applications.
https://metacpan.org/module/Abilities
Thank you.
Post by Mark Stosberg
This is an example of the kind of code I would like to make more easily
available to CGI::App based projects.
Post by B. Estrade
I am a recent addition to this community, and prefer CAP well over the
other alternatives.
That's good to hear, and welcome. Could you say more about why you
prefer it and how you use it?
I prefer it because it provided me with a significant epiphany after
doing CGI the hard way for too long. It's also more or less what we
standardize on internally at cPanel.

We use it to write internal applications and external facing APIs that
require both authentication and authorization. One of our primary
requirements is also raw speed, so even .05 seconds matters to us.
This is the basis for my distaste for any sort of MOP layer. However,
I concede that in a persistent environment, start up times are
amortized over the long term and in this way any cost eventually goes
to 0.
Post by Mark Stosberg
Post by B. Estrade
1. scalability - it is unnecessarily awkward to have more than 2
levels of subclassing currently.
Direct subclass of CAP uses cgi_init; child of subclass uses setup;
anything else must call SUPER::setup.
# Register an action to happen at the init stage.
__PACKAGE__->add_callback('init', sub {
});
Nice.
Post by Mark Stosberg
Note that the Moose API also helps here as well, as it allows you to say
# Add some additional functionality after 'setup' runs in the parent
after 'setup' => sub {
my $self = shift;
};
Thank you. Yeah, that syntax makes me cring actually :).

However, this out of the box seems to provide the basis for a very
well structured plugin system.
Post by Mark Stosberg
https://metacpan.org/module/Moose::Manual::MethodModifiers#BEFORE-and-AFTER-modifiers
The Moose API also provides "BUILD", which like our callback system is
called for every class in the inheritance hierarchy. So another way to
add some "initialization" functionality would be to put this in your
# Another way to add extra functionality when setting up classes.
sub BUILD {
my $self = shift;
}
Post by B. Estrade
2. a more fully developed lifecycle model - similar to the one that
Apache itself uses. In particular, it would be really helpful to have
explicit phases for state (e.g., Session munging), authentication,
and authorization. I imagine those 3 in particular to be extremely
helpful for building things like role based access control or single
sign-on into your application.
I agree that session, authentication and authorization are all useful,
but it's not clear to me what significant gains formal phase definitions
here would bring us. Do you have examples where this design has been put
to great use? Currently, our plugins in these areas use the calback
system to hook in at the phases that are useful for them, and that seems
to work well enough.
The one trouble I had with Authen and Authz is that while Authz will
call the Authen::username method if this plugin is being used, my
experiences lead me to believe that Authz will get called no matter if
there is an authenticated username or not - leading to having to
handle the case of username == undef. In otherwords, failure to
authenticate is not triggered before Authz is attempted (thus, this
has to be handled outside of Authen by Authz)...does this make sense?

I tried to order the plugins so that Authen failed before Authz was
attempted, but I couldn't figure out how to do this cleanly. I feel
like this is a serious problem.
Post by Mark Stosberg
Post by B. Estrade
3. a more fully developed plugin/event system; I think this goes along
with #2 (i.e., a few more hooks), but in addition to this I have
always thought it would be useful to have some sort of mechanism
through which plugins might be able to query one another. A good
example (and actually the main motivation for #2 and #3) are the CAP
Authorization and Authentication plugins. The short list of troubles
* when used together, Authorization is called before Authentication,
making it awkward to handle authorization errors of unauthenticated
guests (or maybe Authz assumes an authenticated session);
* default behavior of Authz is to query directly the Authorization
plugin instance for a username; this works fine in that situation,
but there is no clear way for plugin A to make information available
to plugin B;
That's just an example. I think that these improvements would go a
long way to encouraging the timeless benefits that you've outlined
about CAP above.
Regarding "more hooks", we already have an API to add custom hooks who
folks who want more than the standard ones. Some plugins use this
functionality to provide hooks that come part of their own published
API.
Regarding "plugins querying each other", the Moose "Meta Object Protocol"
provides functionality in this area that we could take advantage of.
We can check to see if an object "does" a role, or check to
see if the "original_package_name" matches the plugin we can expect.
https://metacpan.org/module/Moose::Manual::Roles
https://metacpan.org/module/Class::MOP::Method
I think what I was thinking of for a "more developed" plugin system is
to provide a way to better manage when plugins are fired wrt hooks.

For example, have an "after" or "before" type of modifier when
registering a callback would be nice. Even better would be a way to
easily manage the handler queue associated with each hook. It's not
entirely clear to me how to ensure that handlerA will fire before
handlerB; I also know from reading the documentation that a class
level handler will fire before instance level handlers. This might be
by design or just a consequence of the implementation; however being
able to control the handler execution order would be useful I believe.
Post by Mark Stosberg
Post by B. Estrade
4. more flexibility with the query object...err response object; I've
run into some hoops to jump through when I wanted to use CGI::Simple
and be able to upload capabilities on or off in a sub class.
You'll have be more specific here. The framework already allows you to
use alternate query objects, and requires very few methods of it.
I think this has been addressed by others, so no real need to rehash
it.
Post by Mark Stosberg
Splitting the query object into response and request objects would
immediately provide flexibility, as you could replace the objects
independently. :)
Regarding turning uploads on and off independently, Plack::Request
includes flexibility here, as upload handling is split off into it's own
module, as Plack::Request::Upload. You could easily make an alternate
class for uploads that behaved differently.
Perhaps want you want to do in your case is to reject "POST" requests as
soon as possible. In that case, using a Plack "Middleware" may be best
solution, as it can take action even before the content is prepared for
processing by your application.
Thank you.
Post by Mark Stosberg
Post by B. Estrade
5. persistence - I would like to say that I'd like to learn more about
CAP and the ecosystem in persistent environments. It's my impression
that there are some corner cases or funny issues with it. I do not
claim this is true, but I think that we can all agree that while
persistent environments such as mod_perl are considered old fashioned,
I think that they will prove remain relevant amist the tide of
alternatives and "middleware" laden configurations. For me, the
ultimate goal would be to use CAP to create a responsive and
consistent daemon type application as served by Apache, defined
strictly through things like runmodes, plugins, etc. Is PSGI the path
to this? Maybe, maybe not.
I use CGI::Application almost exclusively under mod_perl 2 now, and am
not aware of significant "gotchas" there. When I switch my large
application over to PSGI (from vanilla mod_perl 2), it will still be
running under mod_perl 2, only with a PSGI adapter.
I don't see Apache/mod_perl2 and "Middleware" as being at odds with each
other. Sometimes they provide different solutions. Sometimes an Apache
solution may perform better, sometimes a Middleware solution may be
preferred for being hackable pure Perl.
I'm personal curious to evaluate replacing Apache with Starman as an app
server, with Nginx in front of it serving static content and acting as a
reverse-proxy. (I already use Nginx this way, but only with Apache on
the backend).
Thank you.
Post by Mark Stosberg
Post by B. Estrade
6*. the last mile - in application frameworks, I am unsure of any that
take the finite state machine model to its logical max. This thought
may be way out there, but defining things like runmodes only takes you
so far. Going a step further, perhaps done through more feature dispatching
or routing, it'd be really nice to be able to define the application
runmodes in terms of a transition function (e.g., current runmode,
input, resulting runmode). In otherwords, support defining an
application to the fullest extent possible though some sort of runmode
dispatch table annotations.
I'll have to wait for the more specific proposal on this point. :)
Well, I think a proposal of this magnitude would be a pretty large
undertaking and be subverted by any use of a MOP (or maybe not); the
idea here is to do the opposite of Moose and have a step that takes an
application definition and generates some some fairly efficient/low
level Perl that is maximally explicit rather than maximally implicit
(as Moose provides); this would minize a lot of overhead. Custom code
would be provided through module hooks so that what you're generating
is the framework code and not the custom app code. IDK, stay with me
because it's stull mulling around in my head.

Thanks, again,
Brett
Post by Mark Stosberg
Mark
##### CGI::Application community mailing list ################
## ##
## To unsubscribe, or change your message delivery options, ##
## visit: http://www.erlbaum.net/mailman/listinfo/cgiapp ##
## ##
## Web archive: http://www.erlbaum.net/pipermail/cgiapp/ ##
## Wiki: http://cgiapp.erlbaum.net/ ##
## ##
################################################################
--
Register Now for cPanel Conference
Oct 8-10, 2012, Houston, Texas
http://conference.cpanel.net/

##### CGI::Application community mailing list ################
## ##
## To unsubscribe, or change your message delivery options, ##
## visit: http://www.erlbaum.net/mailman/listinfo/cgiapp ##
## ##
## Web archive: http://www.erlbaum.net/pipermail/cgiapp/ ##
## Wiki: http://cgiapp.erlbaum.net/ ##
## ##
################################################################
Ron Savage
2012-09-10 22:11:45 UTC
Permalink
Hi Brett
Post by B. Estrade
I think what I was thinking of for a "more developed" plugin system is
to provide a way to better manage when plugins are fired wrt hooks.
For example, have an "after" or "before" type of modifier when
registering a callback would be nice. Even better would be a way to
easily manage the handler queue associated with each hook. It's not
entirely clear to me how to ensure that handlerA will fire before
handlerB; I also know from reading the documentation that a class
level handler will fire before instance level handlers. This might be
by design or just a consequence of the implementation; however being
able to control the handler execution order would be useful I believe.
I don't mind if you choose to continue with CGI::Application rather than
switch to CGI::Snapp, but you should be aware that in the latter's
documentation, I went to great lengths to spell out this matter.
See/Read for yourself my explanation:

https://metacpan.org/module/CGI::Snapp#The-Flow-of-Control

HTH.
--
Ron Savage
http://savage.net.au/
Ph: 0421 920 622

##### CGI::Application community mailing list ################
## ##
## To unsubscribe, or change your message delivery options, ##
## visit: http://www.erlbaum.net/mailman/listinfo/cgiapp ##
## ##
## Web archive: http://www.erlbaum.net/pipermail/cgiapp/ ##
## Wiki: http://cgiapp.erlbaum.net/ ##
## ##
################################################################
Mark Stosberg
2012-09-15 01:22:58 UTC
Permalink
Post by B. Estrade
Post by Mark Stosberg
I would generally plan to keep the core small, but would welcome more
full-featured stacks to be shipped that were based on it, as Titanium
did for CGI::Application.
My motivation for this is based on our needs. We use CAP to write not
just authenticated applications, but those with role based
authorization. I have had moderate success using Authen and Authz,
but in order to do what was necessary to Authen before Authz or to
properly scale out the RBAC restrictions, I had to ditch both and
implement my own callbacks during the prerun stage. I suppose both
plugins got be over the learning curve, and after I was able to
implement authentication and authorization without the plugins.
The one trouble I had with Authen and Authz is that while Authz will
call the Authen::username method if this plugin is being used, my
experiences lead me to believe that Authz will get called no matter if
there is an authenticated username or not - leading to having to
handle the case of username == undef. In otherwords, failure to
authenticate is not triggered before Authz is attempted (thus, this
has to be handled outside of Authen by Authz)...does this make sense?
I tried to order the plugins so that Authen failed before Authz was
attempted, but I couldn't figure out how to do this cleanly. I feel
like this is a serious problem.
My major project also uses Authentication and Authorization. I use and
enjoy CGI::App's Authorization plugin, but found the Authentication
plugin too cumbersone vs rolling my own, so I took the ideas from it,
and implemented my own check at the prerun stage to see if the user is
authenticated. It looks something like this (pseudo-code):

Maybe the key part is that I configure the 'Authz' plugin, so that if
authorization fails, they are redirected to authenticate.

$self->authz('shelter_state')->config(
GET_USERNAME => ...,
FORBIDDEN_RUNMODE => 'redirect_to_login',
DRIVER => ...,
);

My "redirect_to_login" run mode looks like this:

sub redirect_to_login {
my $self = shift;

my $q = $self->query;

my $return_url = $q->self_url;
$return_url = $q->escape($return_url);

my $url = $self->cfg('ROOT_URL').'/account/login';

$self->redirect($url."?return_url=$return_url");
}

When the login process is done, we redirect the user back to where they
came from, and Authorization can be attempted again.

The Authenication and Authorization plugins were originally written the
same author, Cees Hek. I would be suprised to find the two plugins can't
be made to play nicely together.

Did you try re-ordering your "use" lines of the plugins to see if that
addressed your problem? Both the plugins register a callback at the
'prerun' stage when their 'import' method is called during 'use'.
Reversing the order of the 'use' lines will reverse the order they are
triggered in.
Post by B. Estrade
Anyway, my main reason for recommending these 2 in particular as
bona fide life cycle events is that the mirror Apache's life cycle.
And why is Apache's life cycle what we should be mirroring?
Post by B. Estrade
I prefer it because it provided me with a significant epiphany after
doing CGI the hard way for too long. It's also more or less what we
standardize on internally at cPanel.
We use it to write internal applications and external facing APIs that
require both authentication and authorization. One of our primary
requirements is also raw speed, so even .05 seconds matters to us.
This is the basis for my distaste for any sort of MOP layer. However,
I concede that in a persistent environment, start up times are
amortized over the long term and in this way any cost eventually goes
to 0.
It's interesting to hear that CGI::Application is a standard at cPanel!

Regarding performance, I recently benchmarked accessor generation time
for Moo vs Mouse vs Moose vs manual accessors (what CGI::App uses) and
raw hashes.

In a persistent environment like you are using Moose was generating
162,999 accessers *per second* on my laptop. I suspect that wouldn't be
your botteneck. :) This was only marginally slower than the "manual
accessors" benchmark, which would be close to CGI::Application,
delivering 187,617 accessors per second.

https://raw.github.com/gist/3431863/bf6ecdbe23ea8f97a316b2f4ac1fa211cf48ce86/gistfile1.pl

Since your application is performance-sensitive, I would be interested
to know where your profiling shows your performance bottlenecks to be.
Database access? Templating? I suspect the answer won't be in whether
your web framework is using Any::Moose or not.
Post by B. Estrade
Post by Mark Stosberg
Note that the Moose API also helps here as well, as it allows you to say
# Add some additional functionality after 'setup' runs in the parent
after 'setup' => sub {
my $self = shift;
};
Thank you. Yeah, that syntax makes me cring actually :).
However, this out of the box seems to provide the basis for a very
well structured plugin system.
I noticed recently that their docs for this have disclaimers about who
it slows down the method calls some, and the more you stack before/after
hooks on a method call, the more it slows it down. I presume this is
because it's not just calling a list of method calls, but in fact is
progressively nesting method calls inside each other.

In other words, I expect our existing callback system to provide better
performance, although I like the idea of having the "after/before"
syntax available, as the performance difference won't matter in many
cases.
Post by B. Estrade
I think what I was thinking of for a "more developed" plugin system is
to provide a way to better manage when plugins are fired wrt hooks.
For example, have an "after" or "before" type of modifier when
registering a callback would be nice. Even better would be a way to
easily manage the handler queue associated with each hook. It's not
entirely clear to me how to ensure that handlerA will fire before
handlerB; I also know from reading the documentation that a class
level handler will fire before instance level handlers. This might be
by design or just a consequence of the implementation; however being
able to control the handler execution order would be useful I believe.
I think we provide enough control, in that the developer can "use"
modules in the order they choose, or they could explicitly call
add_callback() in order they choose. (IE: use but don't import anything
from the Authz and Authen plugins and then explicitly register the
callbacks yourself, in the order you choose):

use CGI::Application::Plugin::Authentication ();
use CGI::Application::Plugin::Authorization ();

__PACKAGE__->add_callback('prerun',
\&CGI::Application::Plugin::Authentication::prerun_callback() );
__PACKAGE__->add_callback('prerun',
\&CGI::Application::Plugin::Authorization::prerun_callback() );

(Although, in this case, I think just putting the 'use' lines in the
desired order is sufficient.)
Post by B. Estrade
Post by Mark Stosberg
Post by B. Estrade
6*. the last mile - in application frameworks, I am unsure of any that
take the finite state machine model to its logical max. This thought
may be way out there, but defining things like runmodes only takes you
so far. Going a step further, perhaps done through more feature dispatching
or routing, it'd be really nice to be able to define the application
runmodes in terms of a transition function (e.g., current runmode,
input, resulting runmode). In otherwords, support defining an
application to the fullest extent possible though some sort of runmode
dispatch table annotations.
I'll have to wait for the more specific proposal on this point. :)
Well, I think a proposal of this magnitude would be a pretty large
undertaking and be subverted by any use of a MOP (or maybe not); the
idea here is to do the opposite of Moose and have a step that takes an
application definition and generates some some fairly efficient/low
level Perl that is maximally explicit rather than maximally implicit
(as Moose provides); this would minize a lot of overhead. Custom code
would be provided through module hooks so that what you're generating
is the framework code and not the custom app code. IDK, stay with me
because it's stull mulling around in my head.
It turns out Stevan Little has implemented a web framework as a finite
state machine, if that's what you have in mind:

https://metacpan.org/release/Web-Machine

My first impression was that it was suprisingly complex, as there are
dozens of state possibilities to account for. It didn't initially seem
appealing to me.

Thanks again for the continued feedback!

Mark

##### CGI::Application community mailing list ################
## ##
## To unsubscribe, or change your message delivery options, ##
## visit: http://www.erlbaum.net/mailman/listinfo/cgiapp ##
## ##
## Web archive: http://www.erlbaum.net/pipermail/cgiapp/ ##
## Wiki: http://cgiapp.erlbaum.net/ ##
## ##
################################################################
Jiří Pavlovský
2012-09-15 21:00:17 UTC
Permalink
Post by Mark Stosberg
Regarding performance, I recently benchmarked accessor generation time
for Moo vs Mouse vs Moose vs manual accessors (what CGI::App uses) and
raw hashes. In a persistent environment like you are using Moose was
generating 162,999 accessers *per second* on my laptop. I suspect that
wouldn't be your botteneck. :) This was only marginally slower than
the "manual accessors" benchmark, which would be close to
CGI::Application, delivering 187,617 accessors per second.
https://raw.github.com/gist/3431863/bf6ecdbe23ea8f97a316b2f4ac1fa211cf48ce86/gistfile1.pl
Thanks for the benchmark. Help me understand the results. Is it really
so that Moose is on par with the "manual accessors" while Mouse is an
order of magnitude faster?
And Moo order of magnitude slower?
I'm using Moose a lot, but now I'll have a look at Mouse for sure.
--
Jiří Pavlovský


##### CGI::Application community mailing list ################
## ##
## To unsubscribe, or change your message delivery options, ##
## visit: http://www.erlbaum.net/mailman/listinfo/cgiapp ##
## ##
## Web archive: http://www.erlbaum.net/pipermail/cgiapp/ ##
## Wiki: http://cgiapp.erlbaum.net/ ##
## ##
###########################################
Mark Stosberg
2012-09-17 13:17:31 UTC
Permalink
Post by Jiří Pavlovský
Post by Mark Stosberg
Regarding performance, I recently benchmarked accessor generation time
for Moo vs Mouse vs Moose vs manual accessors (what CGI::App uses) and
raw hashes. In a persistent environment like you are using Moose was
generating 162,999 accessers *per second* on my laptop. I suspect that
wouldn't be your botteneck. :) This was only marginally slower than
the "manual accessors" benchmark, which would be close to
CGI::Application, delivering 187,617 accessors per second.
https://raw.github.com/gist/3431863/bf6ecdbe23ea8f97a316b2f4ac1fa211cf48ce86/gistfile1.pl
Thanks for the benchmark. Help me understand the results. Is it really
so that Moose is on par with the "manual accessors" while Mouse is an
order of magnitude faster?
And Moo order of magnitude slower?
I'm using Moose a lot, but now I'll have a look at Mouse for sure.
That's my reading of it. The source code is is there if you want to
check the details of what's going on.

Of course, the benchmark doesn't simulate a full application. Within a
complete real-world application, it's not clear to me how much accessor
speed would matter compared to other factors.

Mark


##### CGI::Application community mailing list ################
## ##
## To unsubscribe, or change your message delivery options, ##
## visit: http://www.erlbaum.net/mailman/listinfo/cgiapp ##
## ##
## Web archive: http://www.erlbaum.net/pipermail/cgiapp/ ##
## Wiki: http://cgiapp.erlbaum.net/ ##
## ##
################################
Mark Stosberg
2012-09-09 19:26:53 UTC
Permalink
Bill,

Thanks for feedback. Responses are below.
Post by Richard Jones
Hi Mark,
Nice to hear you're going to move forward with the CAP project.
After reading your comments about CGI.pm, and comments from others
here, I'm left wondering about a few things. If you're ditching
CGI.pm altogether I know that I'll have to as well.
That's not going to be easy for me. I love the simplicity of these
$cgi = new CGI;
print $cgi->param('contact_name');
$cgi->save($FILE);
$cgi = new CGI($FILE);
What will happen to them?
The simple name=value data format used by the save routine is the same
as the client side data storage in HTML5 (sessionStorage), and I like
that it's easy to understand and read this format, and that I can use
it on both ends (client/server) of my apps.
There not yet specific plans for how CGI.pm will be replaced. How do you
use the save/restore feature? I can say that the PSGI environment does
seem a good deal cleaner for dealing with "input". In CGI, the input by
default comes from STDIN (but large content like post requests), and
several environment variables. This makes the process a bit mysterious,
as well as being action-at-distance a source for confusion. For example,
if something has read and consumed STDIN, it may not there again for
something else to read.

With PSGI, the input is explicitly provided through a Perl hashref, and
the body content comes through a standard file handle.

While I haven't seen a implementation save/restore for PSGI request
objects, it strikes me that it would be pleasant to build.
Post by Richard Jones
What will happen to CGI::Session?
These are all simple, and easy, and familiar. Will the new project
have these, or something similar?
Like CGI.pm, it will continue to exist, but over time I expect I will
quit using it myself and move on to something else.

Plack::Middleware::Session is an obvious choice to consider for this.
I expect I will personally want to use the "Pure SQL" approach to
session storage, so I will need to first write my own storage driver for
it.

I will appreciate moving away from something based on CGI.pm, towards
using another tool that is shared with other frameworks.

http://search.cpan.org/~miyagawa/Plack-Middleware-Session-0.15/lib/Plack/Middleware/Session.pm
https://metacpan.org/module/CGI::Session::Driver::pure_sql

Those who wish to remain with CGI::App / CGI.pm / CGI::Session are
welcome to do so, but will become responsible for more or all of the
maintenance of them.
Post by Richard Jones
As far as I know, Catalyst, Dancer, and Mojolicious do not have the
"save" and "new from file" routines, they use SQL and a third party
database engine only. I know this is probably not something that most
developers would miss, but I think it's pretty handy. I also think
that it's a good place for beginners to start learning to use a
framework. One can go a long way creating apps before they need an SQL
database, and becoming proficient with SQL is expensive. For the apps
I build it's like swatting a fly with a bulldozer.
I'm personally a big fan of SQL and think the related investment is well
worth it. I find the basics rather comprehenable:

"INSERT INTO table VALUES", \%values;
"UPDATE table SET",\%values;
"DELETE FROM table WHERE id = ",\$id;
"SELECT * FROM table WHERE id = ",\$id;

( The above syntax works with DBIx::Simple + SQL::Interp, my preferred
access method. )

However, Plack::Middleware::Session does support a file-storage backend:

https://metacpan.org/module/Plack::Session::Store::File
Post by Richard Jones
Anyway, I also want to thank you for all you've done with CGI.pm and
other modules I use everyday. I, like so many others, have been
standing on your shoulders for years, and I want you to know that I
really do appreciate what you've done for me. If you ever get down to
the Ozarks all the beer and Skittles are on me!
Kindest Regards,
Bill Stephenson
Thanks!

Mark

##### CGI::Application community mailing list ################
## ##
## To unsubscribe, or change your message delivery options, ##
## visit: http://www.erlbaum.net/mailman/listinfo/cgiapp ##
## ##
## Web archive: http://www.erlbaum.net/pipermail/cgiapp/ ##
## Wiki: http://cgiapp.erlbaum.net/ ##
## ##
################################################################
Bill Stephenson
2012-09-12 18:16:31 UTC
Permalink
Post by Mark Stosberg
There not yet specific plans for how CGI.pm will be replaced. How do you
use the save/restore feature?
Thank you, Mark. I appreciate your taking my concerns under consideration.

I've sort of taken my own path to create web apps, and while it works for me, I've gotten some blowback for it a few times over the years, but I really don't mind that, so I'll explain it.

I have a small demo "Note Pad" app at www.raspberryperl.com:

app -> http://raspberryperl.com/cgi-bin/NoteApp/notes.cgi
code -> http://raspberryperl.com/NoteAppCode/

When a user creates a note I save the data in a file:

open(my $NOTE, "> $note_path/$notepad_number")
or &Note_home("Error 3: That didn't work");
$cgi->save($NOTE);
close $NOTE;

When they want to view or edit a note I load the data into a CGI object:

$NOTE = new CGI($FILE); # Throw out the old $NOTE, replace it with a new one
close $FILE;
return ($NOTE);

And use HTML:Template to display it:

$template->param(note_subject => $cgi->param('note_subject'));

I generally use the epoch time of creation to name the file. This gives me an easy way to search by date for documents.

1344045036.txt

Or perhaps assign a document number:

0001.txt

In that case, if you know the document number, finding and loading the data is incredibly fast because you're using the system's b-tree to locate it. The trick (if it can be called that) is creating a unique directory for each user so the app knows where to find their documents. Put each different document type in a unique sub-directory and you've really narrowed down where to find what you're looking for.

Now, my logic for this being practical is that for the most part database engines were designed to solve just a few problems:

1. Slow processors took a long time ripping through a bunch of files while searching for a specific piece of data.
2. RAM was expensive and a lack of enough RAM made managing large numbers of files impractical and limited what an OS could support.
3. Hard Drive space was expensive, so storing a bunch of files was also expensive.

But now, RAM and ROM is comparatively cheap, and processors and OSs are way faster than they were 15 years ago, so this approach keeps becoming more practical for some applications. In my case, the users of the apps I build will never create hundreds of thousands of files. Ten thousand would be the upper ends of what they'd ever create, so this actually works pretty good, and it's very simple to build and maintain.

I've done tests on ripping through 5000 files (with an app like the demo linked above) to find a unique string in one or more files and the result times are not that bad. I suspect they'd be faster if I used ModPerl or FastCGI, but I deploy on a VPS so that's not been an option. My tests resulted in the initial search being a bit slow, but a second search is pretty fast, so I suspect Apache is cacheing some data but I really don't know much about how that works.

I have some apps with several thousand users, and some with over 100,000 files in the system. They all run on a VPS and they're pretty darn fast, so again, I'm not finding a compelling reason to move to a SQL database engine.

I use a flexible interpretation of a MVC design approach in my apps, and it would seem to me that if there were ever a necessity to move to a SQL database it should be fairly easy to change the routines to get and put data, and to load the existing data into the database. If that's the case, then my approach might be useful for RAD (rapid application development) if nothing else.

For my own sake, what I am trying to do is limit complexity. Not at all costs, but I do set a high bar for the returns. Complexity, in my opinion and experience, gets expensive fast. I think it's fair to point out that a SQL database engine may offer another point of entry for hackers to create mayhem. I'm not saying that my approach is more secure, but it seems to me that you must constantly be staying on top of issues specific to any database engine you're using, and that may create additional expense which may be unnecessary.

I understand that if you must have a Relational database my approach may not work, but again, with the apps I've created I've not come across that need. So I believe there are some good reasons to have a simple way, like that in CGI.pm and CGI:Session to store and load data using files.

Kindest Regards,

Bill Stephenson


##### CGI::Application community mailing list ################
## ##
## To unsubscribe, or change your message delivery options, ##
## visit: http://www.erlbaum.net/mailman/listinfo/cgiapp ##
## ##
## Web archive: http://www.erlbaum.net/pipermail/cgiapp/ ##
## Wiki: http://cgiapp.erlbaum.net/ ##
## ##
################################################################
Mike Tonks
2012-09-13 11:59:53 UTC
Permalink
Hi Bill,

This is fascinating, but I think you're abusing CGI.pm for something
it was never intended for.

How about using XML::Simple to encode the data and write that into the
flat files?

# Grab a hashref of data from the posted form
my $data = $cgi->Vars;

# Dump data into file
XMLout($data, OutputFile => $filename);

...

# read data from file
my $data = XMLin($filename);

# use HTML::Template to display it
$template->param(%$data);

etc
Post by Bill Stephenson
Post by Mark Stosberg
There not yet specific plans for how CGI.pm will be replaced. How do you
use the save/restore feature?
Thank you, Mark. I appreciate your taking my concerns under consideration.
I've sort of taken my own path to create web apps, and while it works for me, I've gotten some blowback for it a few times over the years, but I really don't mind that, so I'll explain it.
app -> http://raspberryperl.com/cgi-bin/NoteApp/notes.cgi
code -> http://raspberryperl.com/NoteAppCode/
open(my $NOTE, "> $note_path/$notepad_number")
or &Note_home("Error 3: That didn't work");
$cgi->save($NOTE);
close $NOTE;
$NOTE = new CGI($FILE); # Throw out the old $NOTE, replace it with a new one
close $FILE;
return ($NOTE);
$template->param(note_subject => $cgi->param('note_subject'));
I generally use the epoch time of creation to name the file. This gives me an easy way to search by date for documents.
1344045036.txt
0001.txt
In that case, if you know the document number, finding and loading the data is incredibly fast because you're using the system's b-tree to locate it. The trick (if it can be called that) is creating a unique directory for each user so the app knows where to find their documents. Put each different document type in a unique sub-directory and you've really narrowed down where to find what you're looking for.
1. Slow processors took a long time ripping through a bunch of files while searching for a specific piece of data.
2. RAM was expensive and a lack of enough RAM made managing large numbers of files impractical and limited what an OS could support.
3. Hard Drive space was expensive, so storing a bunch of files was also expensive.
But now, RAM and ROM is comparatively cheap, and processors and OSs are way faster than they were 15 years ago, so this approach keeps becoming more practical for some applications. In my case, the users of the apps I build will never create hundreds of thousands of files. Ten thousand would be the upper ends of what they'd ever create, so this actually works pretty good, and it's very simple to build and maintain.
I've done tests on ripping through 5000 files (with an app like the demo linked above) to find a unique string in one or more files and the result times are not that bad. I suspect they'd be faster if I used ModPerl or FastCGI, but I deploy on a VPS so that's not been an option. My tests resulted in the initial search being a bit slow, but a second search is pretty fast, so I suspect Apache is cacheing some data but I really don't know much about how that works.
I have some apps with several thousand users, and some with over 100,000 files in the system. They all run on a VPS and they're pretty darn fast, so again, I'm not finding a compelling reason to move to a SQL database engine.
I use a flexible interpretation of a MVC design approach in my apps, and it would seem to me that if there were ever a necessity to move to a SQL database it should be fairly easy to change the routines to get and put data, and to load the existing data into the database. If that's the case, then my approach might be useful for RAD (rapid application development) if nothing else.
For my own sake, what I am trying to do is limit complexity. Not at all costs, but I do set a high bar for the returns. Complexity, in my opinion and experience, gets expensive fast. I think it's fair to point out that a SQL database engine may offer another point of entry for hackers to create mayhem. I'm not saying that my approach is more secure, but it seems to me that you must constantly be staying on top of issues specific to any database engine you're using, and that may create additional expense which may be unnecessary.
I understand that if you must have a Relational database my approach may not work, but again, with the apps I've created I've not come across that need. So I believe there are some good reasons to have a simple way, like that in CGI.pm and CGI:Session to store and load data using files.
Kindest Regards,
Bill Stephenson
##### CGI::Application community mailing list ################
## ##
## To unsubscribe, or change your message delivery options, ##
## visit: http://www.erlbaum.net/mailman/listinfo/cgiapp ##
## ##
## Web archive: http://www.erlbaum.net/pipermail/cgiapp/ ##
## Wiki: http://cgiapp.erlbaum.net/ ##
## ##
################################################################
##### CGI::Application community mailing list ################
## ##
## To unsubscribe, or change your message delivery options, ##
## visit: http://www.erlbaum.net/mailman/listinfo/cgiapp ##
## ##
## Web archive: http://www.erlbaum.net/pipermail/cgiapp/ ##
## Wiki: http://cgiapp.erlbaum.net/ ##
## ##
################################################################
Jerry Kaidor
2012-09-13 17:02:35 UTC
Permalink
Post by Mike Tonks
Hi Bill,
This is fascinating, but I think you're abusing CGI.pm for something
it was never intended for.
*** Which is one of the glories of open source. Things keep getting used
for stuff that the original writers never envisioned.

- Jerry Kaidor




##### CGI::Application community mailing list ################
## ##
## To unsubscribe, or change your message delivery options, ##
## visit: http://www.erlbaum.net/mailman/listinfo/cgiapp ##
## ##
## Web archive: http://www.erlbaum.net/pipermail/cgiapp/ ##
## Wiki: http://cgiapp.erlbaum.net/ ##
## ##
################################################################
Bill Stephenson
2012-09-13 17:40:36 UTC
Permalink
Post by Jerry Kaidor
Post by Mike Tonks
Hi Bill,
This is fascinating, but I think you're abusing CGI.pm for something
it was never intended for.
*** Which is one of the glories of open source. Things keep getting used
for stuff that the original writers never envisioned.
I know that you're right according to common practice, so I have to admit it made me laugh reading that this morning for that very reason.

But... in my (weak) defense, in chapter three, page 119, of Lincoln's book, "The official guide to programming with CGI.pm" is the "Advanced Trick" that explains "Saving State to Files", and that's all I'm really doing here, and nothing more, so I think it's not really accurate to say that how I'm using CGI.pm was never envisioned or intended, or if that's truly the case, I've already explained why it may work now when it may not have when the book was written.

I'd like to offer a few more things to consider...

The OS's native file system is really a database too, and a pretty powerful one, so it seems logical to me that before you start looking to add another layer on top of the OS to manage data you should ask if you have a good reason.

I think it's fair to say that this is a question that most frameworks forget to ask when they build their foundation. They assume you're going to want and need a SQL database. I think an option to use a very simple data format is a worthy one. I think that out of the box, a framework should provide a means to do what I did with that demo. I should not have to use SQL to create an app. (of course, that's entirely selfish, and I don't expect anyone to feel at all compelled to accommodate that.)

If we look at web apps designed to run on mobile devices, that are by design pretty simple and tightly focused, than this simple and basic approach to handling data might be a very valuable option. The data format CGI.pm uses is already supported by most web clients, so a way to take advantage of that compatibility make sense to me.

If we consider that we're now at a point where we can include a computer with the software we create (as opposed to the other way around that it's always been) then using the native OS file system offers opportunities that we shouldn't overlook. Your software owns that entire file system now, it's the only thing that will be using it.

The big buzz right now is all about cloud computing, but web app builders have been doing that for a long time now and we know the downsides. The future, as far as I can see forward, looks to me like one where users can have a computer dedicated on site that runs the same app as one they have on a cloud (our web apps) and the user can choose where their data resides, on site, on a cloud, or a combination of both. It has to go this way because we all know that clouds can burst and computers that will run our web apps are getting incredibly cheap and small, so using them both together is the future (well, according to me anyway )

If that's where we're going than we need something to make it easy for the end user to customize their own software. Something so simple that most anyone can do it, or hire someone to do it. This also provides a market for software we make because if our software is simple enough for the end user to modify they have good reason to buy it. Complexity from the start shoots that model in both feet, but as an option it extends the value greatly.

These are a few of the things I ponder when I think about and explore frameworks.

##### CGI::Application community mailing list ################
## ##
## To unsubscribe, or change your message delivery options, ##
## visit: http://www.erlbaum.net/mailman/listinfo/cgiapp ##
## ##
## Web archive: http://www.erlbaum.net/pipermail/cgiapp/ ##
## Wiki: http://cgiapp.erlbaum.net/ ##
## ##
################################################################
Mark Stosberg
2012-09-15 15:58:39 UTC
Permalink
Post by Bill Stephenson
I know that you're right according to common practice, so I have to
admit it made me laugh reading that this morning for that very reason.
But... in my (weak) defense, in chapter three, page 119, of Lincoln's
book, "The official guide to programming with CGI.pm" is the "Advanced
Trick" that explains "Saving State to Files", and that's all I'm
really doing here, and nothing more, so I think it's not really
accurate to say that how I'm using CGI.pm was never envisioned or
intended, or if that's truly the case, I've already explained why it
may work now when it may not have when the book was written.
As software ages, some features lose favor. We end up with books like
"Perl Best Practices" which advise completely ignoring some features, of
Perl and "JavaScript: The Good Parts", which does the same for
JavaScript.

There may have been a time when it was considered a good practice to use
CGI.pm for data persistence. It is no longer the case.
Post by Bill Stephenson
If we look at web apps designed to run on mobile devices, that are by
design pretty simple and tightly focused, than this simple and basic
approach to handling data might be a very valuable option.
Both Android and iOS have official SQLite support and APIs. Android's
demo application for using SQLite is .... a Notepad.

http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html
Post by Bill Stephenson
The data format CGI.pm uses is already supported by most web clients,
so a way to take advantage of that compatibility make sense to me.
Most web clients support JSON now, which allows for more complex
structures than the simple key/value pair that CGI.pm uses.
Post by Bill Stephenson
These are a few of the things I ponder when I think about and explore frameworks.
Thank you for your thoughts.

Mark

##### CGI::Application community mailing list ################
## ##
## To unsubscribe, or change your message delivery options, ##
## visit: http://www.erlbaum.net/mailman/listinfo/cgiapp ##
## ##
## Web archive: http://www.erlbaum.net/pipermail/cgiapp/ ##
## Wiki: http://cgiapp.erlbaum.net/ ##
## ##
################################################################
Bill Stephenson
2012-09-18 17:19:46 UTC
Permalink
Post by Mark Stosberg
Most web clients support JSON now, which allows for more complex
structures than the simple key/value pair that CGI.pm uses.
Mark, I think this is relevant to what I'm advocating here.

That JSON support is accomplished with javascript parsing a string of JSON data that is stored in the localStorage key/value format. I think that's a very clever use of the localStorage feature because it extends the functionality without adding complexity.

Here's an interesting article on that:

https://hacks.mozilla.org/2012/03/there-is-no-simple-solution-for-local-storage/

That article points out the value of the simplicity in having the localStorage function and the key/value format, and also how the IndexedDB feature is not so simple. So, I'm not at all alone in seeing the benefits of these simple to use functions and this format. That simplicity is really quite ingenious, and I think this is what's important to keep in mind.

What developers are doing with localStorage and JSON on the client side is really not any different in concept than storing a string of JSON data with CGI.pm's save function on the server side. I think that sounds pretty handy.

Here's a quote from the author about that:

"This local storage solution has a few very tempting features for web developers:

• It is dead simple
• It uses strings for storage instead of complex databases (and you can store more complex data using JSON encoding) ..."

In that article the author, Chris Heilmann, also discusses how unforeseen uses of the localStorage feature have revealed issues with how it is implemented. He offers several ideas on how to deal with those issues and he concludes his findings with "We need to fix this".

It seems to me that we are in a somewhat similar situation, but are leaning towards a "We need to ditch this" conclusion.

As I've said, my reasons for advocating for this feature are selfish. I am not qualified to help implement it so how can they be anything but selfish? But, that does not mean others will not also benefit. I think the example of creative and clever usage discussed above helps to demonstrate that.

While I may not be able to help implement the feature, I might be able to help with example code and documentation, and I'd be more than willing to try.

Kindest Regards,

Bill


##### CGI::Application community mailing list ################
## ##
## To unsubscribe, or change your message delivery options, ##
## visit: http://www.erlbaum.net/mailman/listinfo/cgiapp ##
## ##
## Web archive: http://www.erlbaum.net/pipermail/cgiapp/ ##
## Wiki: http://cgiapp.erlbaum.net/ ##
## ##
################################################################
B. Estrade
2012-09-18 17:41:43 UTC
Permalink
Post by Bill Stephenson
Post by Mark Stosberg
Most web clients support JSON now, which allows for more complex
structures than the simple key/value pair that CGI.pm uses.
Mark, I think this is relevant to what I'm advocating here.
That JSON support is accomplished with javascript parsing a string of JSON data that is stored in the localStorage key/value format. I think that's a very clever use of the localStorage feature because it extends the functionality without adding complexity.
https://hacks.mozilla.org/2012/03/there-is-no-simple-solution-for-local-storage/
That article points out the value of the simplicity in having the localStorage function and the key/value format, and also how the IndexedDB feature is not so simple. So, I'm not at all alone in seeing the benefits of these simple to use functions and this format. That simplicity is really quite ingenious, and I think this is what's important to keep in mind.
What developers are doing with localStorage and JSON on the client side is really not any different in concept than storing a string of JSON data with CGI.pm's save function on the server side. I think that sounds pretty handy.
? It is dead simple
? It uses strings for storage instead of complex databases (and you can store more complex data using JSON encoding) ..."
In that article the author, Chris Heilmann, also discusses how unforeseen uses of the localStorage feature have revealed issues with how it is implemented. He offers several ideas on how to deal with those issues and he concludes his findings with "We need to fix this".
It seems to me that we are in a somewhat similar situation, but are leaning towards a "We need to ditch this" conclusion.
As I've said, my reasons for advocating for this feature are selfish. I am not qualified to help implement it so how can they be anything but selfish? But, that does not mean others will not also benefit. I think the example of creative and clever usage discussed above helps to demonstrate that.
While I may not be able to help implement the feature, I might be able to help with example code and documentation, and I'd be more than willing to try.
Kindest Regards,
It is unclear to me exactly what feature you're advocating, even
though I went back and read the previous threads.

I'd like to point out that while it doesn't matter what the client or
the server do, the defacto standard is to send key/value pairs to the
server no matter what the HTTP method is. CGI.pm will happly parse a
k/v string sent via POST just as it would sent via GET; however, if
you send just JSON to the server, you must manually parse whatever is
in the POSTDATA field. That's my experience anyway.

It'd be nice to have something on the server that recognized the JSON
as natively as a k/v query string, particularly for non-GET methods.

Also, YUI 3 has some interesting local storage options.

Brett
Post by Bill Stephenson
Bill
##### CGI::Application community mailing list ################
## ##
## To unsubscribe, or change your message delivery options, ##
## visit: http://www.erlbaum.net/mailman/listinfo/cgiapp ##
## ##
## Web archive: http://www.erlbaum.net/pipermail/cgiapp/ ##
## Wiki: http://cgiapp.erlbaum.net/ ##
## ##
################################################################
--
Register Now for cPanel Conference
Oct 8-10, 2012, Houston, Texas
http://conference.cpanel.net/

##### CGI::Application community mailing list ################
## ##
## To unsubscribe, or change your message delivery options, ##
## visit: http://www.erlbaum.net/mailman/listinfo/cgiapp ##
## ##
## Web archive: http://www.erlbaum.net/pipermail/cgiapp/ ##
## Wiki: http://cgiapp.erlbaum.net/ ##
## ##
################################################################
Mark Stosberg
2012-09-15 15:41:48 UTC
Permalink
Bill--
Post by Bill Stephenson
I've sort of taken my own path to create web apps, and while it works for me, I've gotten some blowback for it a few times over the years, but I really don't mind that, so I'll explain it.
app -> http://raspberryperl.com/cgi-bin/NoteApp/notes.cgi
code -> http://raspberryperl.com/NoteAppCode/
I stated to look at the code, but I didn't get very far until I ran into
this notice:

# Do not read, copy, distribute, execute, run, or use
# this code without express written permission from
# William H. Stephenson.

At that point, I was compelled to immediately close the file and stop
reading.
Post by Bill Stephenson
open(my $NOTE, "> $note_path/$notepad_number")
or &Note_home("Error 3: That didn't work");
$cgi->save($NOTE);
close $NOTE;
I see. I hope that $note_path and $notepad_number are handled
appropriately, so that a user can't end up overwritting unintended file
son our file system.
Post by Bill Stephenson
$NOTE = new CGI($FILE); # Throw out the old $NOTE, replace it with a new one
close $FILE;
return ($NOTE);
Using a representation of an HTTP response as a data storage and
retrieval system makes me shudder. Someone here has already suggested
using XML instead. A format like XML or JSON would offer some greater
flexibility.

I would also suggest considering a DBI backend, such as DBD::CSV,
DBD::AnyData or DBD::SQLite2. This way, your code is a good position to
"scale up" to using a full SQL database if that's ever desired, and you
have a standard set up tools and techniques to use between large
projects that use SQL and your smaller projects too.

I've done a lot of small projects with CGI::Application, and I set a
fairly low bar before I start to involve a SQL database.

Even on low-cost shared hosting accounts, SQL databases are readily
available.
Post by Bill Stephenson
$template->param(note_subject => $cgi->param('note_subject'));
HTML::Template has a feature called 'associate' which makes this kind of
pass-through easier:

https://metacpan.org/module/HTML::Template#Miscellaneous-Options
Post by Bill Stephenson
I generally use the epoch time of creation to name the file. This gives me an easy way to search by date for documents.
1344045036.txt
0001.txt
Either scheme might work well, until you have a lot of documents and
need to search by some other key, requiring opening *every* file to
check something.
Post by Bill Stephenson
In that case, if you know the document number, finding and loading the
data is incredibly fast because you're using the system's b-tree to
locate it. The trick (if it can be called that) is creating a unique
directory for each user so the app knows where to find their
documents. Put each different document type in a unique sub-directory
and you've really narrowed down where to find what you're looking for.
Now, my logic for this being practical is that for the most part
1. Slow processors took a long time ripping through a bunch of files
while searching for a specific piece of data.
2. RAM was expensive and a lack of enough RAM made managing large
numbers of files impractical and limited what an OS could support.
3. Hard Drive space was expensive, so storing a bunch of files was also expensive.
But now, RAM and ROM is comparatively cheap, and processors and OSs
are way faster than they were 15 years ago, so this approach keeps
becoming more practical for some applications. In my case, the users
of the apps I build will never create hundreds of thousands of files.
Ten thousand would be the upper ends of what they'd ever create, so
this actually works pretty good, and it's very simple to build and
maintain.
I thought the beauty of SQL was that you expressed *what you wanted*,
not *how to make it happen*.

I much prefer that to code that open and closes files, scans content
line by line, and greps for values.

But I agree with the overall sentiment that the best tools for complex
projects are often not the same as the best tools for small projects.
Post by Bill Stephenson
I use a flexible interpretation of a MVC design approach in my apps,
and it would seem to me that if there were ever a necessity to move to
a SQL database it should be fairly easy to change the routines to get
and put data, and to load the existing data into the database. If
that's the case, then my approach might be useful for RAD (rapid
application development) if nothing else.
It sounds like you've thought about how you might scale up if you needed
to.
Post by Bill Stephenson
For my own sake, what I am trying to do is limit complexity. Not at
all costs, but I do set a high bar for the returns. Complexity, in my
opinion and experience, gets expensive fast. I think it's fair to
point out that a SQL database engine may offer another point of entry
for hackers to create mayhem. I'm not saying that my approach is more
secure, but it seems to me that you must constantly be staying on top
of issues specific to any database engine you're using, and that may
create additional expense which may be unnecessary.
I also pursue simplicity as a goal. Sometimes it be a challenge to
recognize which of two options is simplist.
Post by Bill Stephenson
I understand that if you must have a Relational database my approach
may not work, but again, with the apps I've created I've not come
across that need. So I believe there are some good reasons to have a
simple way, like that in CGI.pm and CGI:Session to store and load data
using files.
I think you'll find that there will continue to be easy-to-use tools
available to store and access data in files from Perl.

Mark

##### CGI::Application community mailing list ################
## ##
## To unsubscribe, or change your message delivery options, ##
## visit: http://www.erlbaum.net/mailman/listinfo/cgiapp ##
## ##
## Web archive: http://www.erlbaum.net/pipermail/cgiapp/ ##
## Wiki: http://cgiapp.erlbaum.net/ ##
## ##
################################################################
Bill Stephenson
2012-09-15 20:17:01 UTC
Permalink
Post by Mark Stosberg
I stated to look at the code, but I didn't get very far until I ran into
# Do not read, copy, distribute, execute, run, or use
# this code without express written permission from
# William H. Stephenson.
At that point, I was compelled to immediately close the file and stop
reading.
I apologize, that's in a template I set up years ago in BBEdit, I'll remove it. I'll point out that since I put the link to the code there and invite you to use it, that is permission, still, I'll remove it as it really was an oversight. (Actually, it's a joke. It invokes a chuckle in me because it is so ridicules knowing I'm the only one that ever reads and executes my code and most wouldn't want it anyway and I wouldn't lose anything if they took it. You must have thought that too, didn't it make you chuckle just a little bit?)
Post by Mark Stosberg
I see. I hope that $note_path and $notepad_number are handled
appropriately, so that a user can't end up overwritting unintended file
son our file system.
They are hard coded in a set-up file.
Post by Mark Stosberg
Using a representation of an HTTP response as a data storage and
retrieval system makes me shudder.
"Shudder"? ( :D )

Why?

How do you actually avoid that?

I understand that in a publicly shared space you have to filter that input, so that's what you do, as best as you can. But do other modules process that same input differently somehow? Does CGI.pm handle it poorly and in a manner that cannot be addressed? You have to use that same data no matter what, so what makes you shudder?
Post by Mark Stosberg
HTML::Template has a feature called 'associate' which makes this kind of
Well now, that's just magic!

Thanks for pointing that out, I'll give it a spin this evening.

And thanks again for listening. I know you're busy...

Bill




##### CGI::Application community mailing list ################
## ##
## To unsubscribe, or change your message delivery options, ##
## visit: http://www.erlbaum.net/mailman/listinfo/cgiapp ##
## ##
## Web archive: http://www.erlbaum.net/pipermail/cgiapp/ ##
## Wiki: http://cgiapp.erlbaum.net/ ##
## ##
################################################################
Loading...