Brett, Thanks for the feedback.
>> - 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. >> - 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. > 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. >> - 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. :) > 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. > 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. >> - 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. >> - 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. > 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? > 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; } > 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. > 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. 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 > 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. > 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). > 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/ ## ## ## ################################################################