Re: [Catalyst] Why no extra attributes on Private actions?
On Mon, Aug 17, 2009 at 8:14 AM, Eden Cardim edencar...@gmail.com wrote: I don't understand your obsession over :Private. A method tagged with :Action, or any other attribute that doesn't make it use one of the available dispatch types is effectively *the same thing* as a Private action, except it doesn't restrict the use of other attributes, is this not what you want? Personally, I've dumped most uses of method attributes altogether, in favor of the config-based scheme, except for a few cases of chaining, so I'd vouch for dumping :Private as well. Sorry, it does sound like an obsession. And yes you are right there are other approaches. It's not a big deal. Obviously, the intent of Private is to have a forward-able action that cannot be dispatched directly. It's a pretty basic part of Catalyst to have actions that cannot be dispatched directly, so Private (or a way to express the same thing) is useful. The implementation enforces this by prohibiting any additional attributes instead of just prohibiting attributes handled by different dispatch types.:Action just takes advantage of the implementation details -- it's not a real action attribute at this time I believe. The issue that came up was I knew I could simply avoid using :Private to use additional attributes, but then I didn't want to create an action for every method that had attributes, either. We are just investigating different approaches at this time, so it may turn out that we go for the config-based approach as you noted. The people with java experience seem to favor the config-based approach. Anyway, I've moved on to obsessing about other things. -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Inconsistent hierarchy....
On Tue, Aug 18, 2009 at 3:59 AM, mrchips mailli...@aspiretools.co.ukwrote: Lucky me :) I downgraded to 5.7015 and everything is fine (no surprise there)..so it seems CDBI just doesn't work with 5.8 I have two old application using CDBI and they run fine with Catalyst 5.8. I had the standard NEXT warnings, but that was easy to suppress. I'm very impressed what a good job the Cat developers did making the 5.8 move smooth. -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] use base vs use parent
On Tue, Aug 25, 2009 at 11:55 AM, Evan Carroll li...@evancarroll.comwrote: When should be use parent be used and not use base or it really doesn't matter which one is used? parent.pm when you can use cpan, base.pm when you can't. If it's a Moose class should you always use extends over both? Hum, the CatalystAndMoose manual doesn't even show the application base class inheriting: http://search.cpan.org/~hkclark/Catalyst-Manual-5.8000/lib/Catalyst/Manual/CatalystAndMoose.pod#THE_CONTEXT_CLASS Unlike in the Intro which shows use parent. (The CatAndMoose page also shows $app, which isn't defined). Not sure if this is by design or not, but the application base class automatically inherits from Catalyst and Catalyst::Controller. -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Handling configuration outside the Catalyst application
On Thu, Aug 27, 2009 at 7:10 PM, Daniel Austin daniel.aus...@gmail.com wrote: Hello How are you handling configuration for applications or code that run outside of Catalyst? For example, in my model tests, I have code like this: use MyCompany::CatApp; my $app = MyCompany::CatApp-new(); my $model = $app-model('DB::Model')-new({}); ok( $model-insert ); etc. This way the model tests are talking to the right database as configured for that environment. But it seems slow to run and it's not the right coupling if I have, say, a cronjob that wants to use the same models. Are there any patterns anyone can recommend? I have a config module that I use everywhere. I specify a running mode, such as testing, staging, and production so that the correct config is pulled. $ script/dump_config.pl --mode=production log4perl { enable = 1, level = info, } $ script/dump_config.pl --mode=development log4perl { enable = 1, level = debug, } Catalyst uses a plugin for that module. I also have another module that uses that configuration class. It makes it easy to write cron scripts. #!/usr/bin/perl use App::ConfigUtil; # define options for this script my %options = ( minutes_old = { help = 'Items must be minutes_old to be removed format = '=i', default = 60, }, ); my $app= App::ConfigUtil-new( \%options ); my $config = $app-config; # same config Catalyst sees my $db = $app-database; $app-lock(20); # lock this cron job for 20 seconds (since running on multiple servers) $db-model( 'Foo' )-remove_old; Then it's just ./clean_foo --mode=production --minutes_old=120 But, now I'm thinking about making all access go through Catalyst. That is, a cron job would log in via the API and then use and API method to do its work. Wouldn't need to be a web request, of course. Then I've got one access layer to the application and can have ACL rules for the cron user and unified logging. -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Splitting up a large application: Shared config and templates for multiple applications
On Fri, Aug 28, 2009 at 6:41 AM, Matt Whipple m...@mattwhipple.com wrote: Anyone building applications out of multiple small Catalyst applications like this? How do you set up the apps to share templates and a config? Anything more interesting than passing in paths? One downside of this approach is we end up with a handful of very similar looking applications (same set of plugins, etc.), not to mention have to be careful about how session data is shared, and so on. I wounder if it would be difficulst to customize the catalyst.pl script to include a standard set of plugins/roles that we use in every application -- e.g. have a skeleton app. Subclass. This could probably take care of sharing the template/config resources also, but otherwise I'd probably lean towards symlinking over modifying each app. Subclass what? I was thinking that I'd have to use an environment variable to point to the location of the base application (the one with the base tempates and app-wide config) and then add to the template INCLUDE_PATH. Or maybe have the applications look at $app_home/../$base_app/. Seems there was some discussion not too long ago of drop-in modules for application, similar to what many CMSs have. -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
[Catalyst] ActionClass vs. Moose Role?
I was starting to implement a custom ActionClass (similar to RenderView) and then wondered if it would be better written as a Moose role. Is there a reason to use one over another? Last I looked, an action is limited to a single ActionClass (although it's easy to deal with that), but depending on how it's done, could apply multiple roles. That is, one way would be to define the end() method in the role and not even have it in the consuming controller class, or another would be to have a end() stub in the controller and and then use before 'end' in the role. That way multiple roles could be applied. Any guidance here? Is everything going to be a role at some point? ;) -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] ActionClass vs. Moose Role?
On Fri, Aug 28, 2009 at 10:29 AM, Tomas Doran bobtf...@bobtfish.net wrote: On 28 Aug 2009, at 18:25, Bill Moseley wrote: I was starting to implement a custom ActionClass (similar to RenderView) and then wondered if it would be better written as a Moose role. Maybe - depends what you're doing. They're doing different things really, and I'd need more details to make a recommendation. Well, if you were going to write something like RenderView now would you still write it as an ActionClass? The purpose is to have a standard end() that I use in multiple applications -- similar to RenderView as I mentioned. I guess the difference is if you want to apply code to any action vs. a specific action. RenderView is typically applied just to the end() method (or a method forwarded to from end() ), so maybe it's really better as a role since it would always alter end(). But if I want to apply code to different (and specific) actions then ActionClass is probably better since it can be set per action. Anyway, using before 'end' is probably the way to go in the role instead of sub end. BTW -- will the helpers for catalyst.pl start generating Moose-ified context and controller classes at some point soon? -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
[Catalyst] Class data in a Moose::Role plugin
I also tried with Catalyst::ClassData. Must be missing something. All modules up to date. On Perl 5.10.0. $ catalyst.pl MyApp $ cat lib/Catalyst/Plugin/Role.pm package Catalyst::Plugin::Role; use Moose::Role; use MooseX::ClassAttribute; class_has 'Cache' = ( is = 'rw', isa = 'HashRef', default = sub { {} }, ); 1; $ script/myapp_server.pl Could not load class (Catalyst::Plugin::Role) because : Catalyst::Plugin::Role already has a metaclass, but it does not inherit Moose::Meta::Class (Moose::Meta::Role=HASH(0xa38ff10)) at /usr/local/share/perl/5.10.0/Moose.pm line 162 Moose::init_meta('Moose', 'metaclass', undef, 'for_class', 'Catalyst::Plugin::Role') called at /usr/local/share/perl/5.10.0/MooseX/ClassAttribute.pm line 22 MooseX::ClassAttribute::init_meta('MooseX::ClassAttribute', 'for_class', 'Catalyst::Plugin::Role', 'metaclass', undef) called at /usr/local/share/perl/5.10.0/Moose/Exporter.pm line 405 Moose::Exporter::__ANON__('MooseX::ClassAttribute') called at /home/moseley/MyApp/script/../lib/Catalyst/Plugin/Role.pm line 3 Catalyst::Plugin::Role::BEGIN() called at /usr/local/share/perl/5.10.0/MooseX/ClassAttribute.pm line 3 eval {...} called at /usr/local/share/perl/5.10.0/MooseX/ClassAttribute.pm line 3 require Catalyst/Plugin/Role.pm called at /usr/local/lib/perl/5.10.0/Class/MOP.pm line 134 eval {...} called at /usr/local/lib/perl/5.10.0/Class/MOP.pm line 134 Class::MOP::_try_load_one_class('Catalyst::Plugin::Role') called at /usr/local/lib/perl/5.10.0/Class/MOP.pm line 95 Class::MOP::load_first_existing_class('Catalyst::Plugin::Role') called at /usr/local/lib/perl/5.10.0/Class/MOP.pm line 140 Class::MOP::load_class('Catalyst::Plugin::Role') called at /usr/local/share/perl/5.10.0/Catalyst.pm line 2563 Catalyst::setup_plugins('MyApp', 'ARRAY(0xa2d1598)') called at /usr/local/share/perl/5.10.0/Catalyst.pm line 1028 Catalyst::setup('MyApp') called at /home/moseley/MyApp/script/../lib/MyApp.pm line 35 require MyApp.pm called at script/myapp_server.pl line 66 main::__ANON__() called at script/myapp_server.pl line 107 BEGIN failed--compilation aborted at /home/moseley/MyApp/script/../lib/Catalyst/Plugin/Role.pm line 3. Compilation failed in require at /usr/local/lib/perl/5.10.0/Class/MOP.pm line 134. at /usr/local/lib/perl/5.10.0/Class/MOP.pm line 119 Class::MOP::load_first_existing_class('Catalyst::Plugin::Role') called at /usr/local/lib/perl/5.10.0/Class/MOP.pm line 140 Class::MOP::load_class('Catalyst::Plugin::Role') called at /usr/local/share/perl/5.10.0/Catalyst.pm line 2563 Catalyst::setup_plugins('MyApp', 'ARRAY(0xa2d1598)') called at /usr/local/share/perl/5.10.0/Catalyst.pm line 1028 Catalyst::setup('MyApp') called at /home/moseley/MyApp/script/../lib/MyApp.pm line 35 require MyApp.pm called at script/myapp_server.pl line 66 main::__ANON__() called at script/myapp_server.pl line 107 Compilation failed in require at script/myapp_server.pl line 66. With Catalyst::ClassData: mose...@bumby2:~/MyApp$ cat lib/Catalyst/Plugin/Role.pm package Catalyst::Plugin::Role; use Moose::Role; use Catalyst::ClassData; __PACKAGE__-mk_classdata( 'foo' ); 1; mose...@bumby2:~/MyApp$ script/myapp_test.pl / Could not load class (MyApp) because : Could not load class (Catalyst::Plugin::Role) because : Can't locate object method mk_classdata via package Catalyst::Plugin::Role at /home/moseley/MyApp/script/../lib/Catalyst/Plugin/Role.pm line 5. Compilation failed in require at /usr/local/lib/perl/5.10.0/Class/MOP.pm line 134. ... -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
[Catalyst] Where to add access control? Override execute() or dispatch()?
I'm in the process of adding custom access control for actions. I've been looking over C::P::Authorization::ACL. It overrides execute() which is run for every method called by the dispatcher, which includes begin, auto, the action itself, and end. Depending on how the ACLs are specified, the plugin wll block access to the actual action, but begin, auto, and end will still run. I'm trying to decide if this is the best approach, or if would be better to test the ACL before dispatching. The issue is if the request is for /foo/bar, and an ACL rule blocks that, should Foo::(begin|end|auto) still run? Or should it act as if the /foo/bar action doesn't exist and not run any begin, auto, or end in the Foo controller? -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] selectively using the wrapper
On Wed, Sep 16, 2009 at 9:11 AM, Ascii King t...@swattermatter.com wrote: Bill Moseley wrote: In my mind the wrapper is a view issue, so I set the wrapper in the template not in the controller. I have a wrapper that is called for *every* page that is used to build the page. META is compile time, IIRC, so I use [% page.layout = 'foo' %] then in wrapper.tt http://wrapper.tt I have a CASE statement that sets the wrappers based on page.layout set in the base template. IIRC, I use page.layout (instead of say just layout) because WRAPPER does a shallow localization of the stash. Thanks again, guys. It took me a few reads to figure out what this meant, but I'm glad I understand it now. I agree that the wrapper should be called from the template. I suspect it will make my life a little easier. Not sure what you mean by template there, but maybe this makes it clearer: View::TT: COMPILE_DIR: __TEMPDIR(templates)__ WRAPPER: page/wrapper.tt PRE_PROCESS: config.tt PRE_CHOMP: 0 POST_CHOMP: 0 TIMER: 0 STAT_TTL: 60 ENCODING: UTF-8 Template Toolkit then will call page/wrapper.tt for template passed to process(). Then the template sets the page.layout and page/wrapper.ttdecides how to build the entire page based on that layout. -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Re: Calling Controller Methods from inside begin or auto.
On Wed, Sep 30, 2009 at 5:23 AM, Derek Wueppelmann dwuep...@gmail.comwrote: On Tue, 2009-09-29 at 14:39 +0200, Aristotle Pagaltzis wrote: * monkey dwuep...@gmail.com [2009-09-29 14:35]: Is there another way to do the above without having to write the auth handling at the top of every method used to display pages? Chained dispatch. Do an auth check early in the chain, then the actions down the chain don’t need to do it. So I found a different way to do this. It's pretty close to my original method I had mentioned, but instead of calling $self-auth_required I changed it to: $c-action-class-auth_required() Which has the desired effect. Now all I need to do is if a controller does not require authentication in order to be viewed I override the auth_required method in that controller to return 0 instead of the default 1. Does that approach provide you with enough fine-grained access control? I suppose you can check the action name in auth_required(). There are a number of existing modules to consider, for example: Catalyst::Action::Role::ACL Catalyst::Plugin::Authorization::ACL I've also used an approach where I check for roles in each controller's auto method, and I've also used method attributes to indicate the access level required for each action (which has the benefit where I can require *every* dispatched action to have an access level specified or be blocked). I also do not detach to a login page, rather I always redirect. Not sure I remember the details of that choice, but one reason might have been I didn't want a URL for one resource to return a 200 yet not return the response for that URL and instead return a login form. -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Re: Calling Controller Methods from inside begin or auto.
On Wed, Sep 30, 2009 at 7:30 AM, Derek Wueppelmann dwuep...@gmail.comwrote: I'm actually doing forwards to my login page right now. So that when a user logs in they can still see the page they were originally trying to view. I capture the URL they were attempting to view in the login process. And then redirect back to that original page after login? I pass that data via the cache or session. $c-cache-set( $key, { orig_url = $url, message = 'Auhorization is required', }); $c-res-redirect( $c-uri_for( '/login', { info = $key } ) ); Catalyst docs show an example using auto. BTW - shouldn't the redirect be an absolute-URI? sub auto : Private { my ( $self, $c ) = @_; if ( !$c-user_exists ) { # Catalyst::Plugin::Authentication $c-res-redirect( '/login' ); # require login return 0; # abort request and go immediately to end() } return 1; # success; carry on to next action } RFC3986 has: absolute-URI = scheme : hier-part [ ? query ] And 2616: Location = Location : absoluteURI -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Re: Calling Controller Methods from inside begin or auto.
On Wed, Sep 30, 2009 at 10:13 AM, Aristotle Pagaltzis pagalt...@gmx.dewrote: I detach. My login action sets status 403 and pragma no-cache (etc) when it’s not requested directly. I’d love to be able to just send 401 instead and let the user agent take care of everything (which would transparently and securely deal with POSTs sent with expired auth credentials) – unfortunately the HTTP Auth UI in browsers is universally shoddy. If I felt the need, I could also check for browser vs automated agent and send either form + 403 to browsers and just a 401 to other clients. Looking at my code I also return 401 for API requests. I have a note in the code that there was problems returning 403 on some browsers although maybe that was just old IE when the content body was too short and it would display its own message. And looking at old svn logs I found another reason I redirect -- which might be how my code grew over time. At one point I added a remember me feature. So I have code in the controller's auto() which is basically return unless $c-test_role( @roles ); That test_role() method first checks if logged in, and if not logged in then does the redirect. But, before doing the redirect it attempts an automatic login via the remember me feature. The problem there was then the action's auto() and begin() methods were not run with the user logged in, which was important for other reasons. I would have expected to do the remember me login earlier (e.g. in root's auto() ) and avoided that issue, but mabye I had a reason otherwise. Anyway, the redirect does allow the login action to be called as a normal request (with login's auto and begin methods run). Granted, now there's $c-go to do a full dispatch, but redirect seems cleaner at the expense of a redirect. -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Deployment in practice
2009/10/9 Octavian Râşniţă orasn...@gmail.com Hi, I've recently started to use Mercurial for revision control and the pages regarding the deployment of a Catalyst app from the Catalyst wiki also help me very much, but I still don't know what would be the best method for uploading the files to the server. How do you do it? Archive the entire app an dupload to the server then change the permissions of the files and folders there? Or upload the modified files one by one? Or generate a tarball on each revision and unarchive and make, make test it on the server? I have a script on a build server that does an svn export of a specific branch and version (or latest trunk if no version specified). The script then runs the test suite, runs the build scripts that generate minified css, javascript, and anything else that prepares the package such as create a meta file with build info, and then builds a tarball named after the reversion. Also, a symlink is created as latest on the build server. Then on target machines (testing, staging, and production) I have a push script that fetches the tarball (based on a specific version or latest), untars it on the machine. It's untarred into a directory named after the revision it came from. Tests are run that verify that it can talk to whatever it needs (database, services). Then do a graceful stop of the existing server, move symbolic links, start the server back up and then use wget to validate a number of test URLs. Depending on the update some servers may get pulled out of the balancer before upgrading to do it in stages. Pushing a previous version will just update the symlinks if they revesion exists. Not perfect but seems to work ok for now. -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Choosing the language
2009/10/12 Octavian Râşniţă orasn...@gmail.com Hi, Is there a recommendation for storing the language ID in the URL in order to be as easy to get it from there? I want to have unique links for each URL, so I can't just put it in the cookies. Using ?lang=EN seems to be the easiest way, although it doesn't look nice. My other post about passing around query parameters is related. Happens that one of the parameters is a lang setting. I've always preferred using a path prefix instead of a query parameter. For one things it make relative urls work. Another is that, IIRC, there were proxies that would not cache content with query parameters. I'm not sure if that's a real concern any more -- or if there's any other reasons to avod the query parameter approach. Another parameter that might be passed, in my case, is a session id. I'm not a fan of that, but apparently there's some cases where it's needed (site in an iframe??). At one time I also put that into a path prefix. Putting it as the first element in the path info looks nice, but I don't know how to get it from there in a single controller/action and not in every action separately. The wiki article Larry posted is very close to what I do. -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
[Catalyst] Validating single arg id
I have a number of methods that start something like this: sub view : Local Args(1) { my ( $self, $c, $id ) = @_; my $obj = $c-model( 'DB::Foo' )-find( $id ) || return $c-res-status( 404 ); If $id is not valid then I might, as in that example, return with a 404 status. Of course, if $id is suppose to be an integer and a non-integer or an integer out of range is provided then the the database will throw an exception, which I want to prevent. I want valid ids to return an object and *anything* else to return undef before hitting the database. This is pretty low-level validation -- just validating primary key. For more complex validation I use a form validation module. Obviously, I could do something like return $c-res-status(404) unless $c-model('DB::Foo')-is_valid_id( $id ) in every method, but that's not very DRY. What I've done in the past is override the find() or search() method in my model base class so that whatever $id is passed it is validated. Specific model classes can override the is_valid_id() method if they use keys that are not a common key format (i.e. different integer range or non-integer key). What's you approach to validating that $id in situations like this where there's a single id? Do you just let the database throw the exception? I prefer to return 404s for invalid ids, regardless of their format (and likewise for ids that point to valid object, but are not owned by the current user instead of a 403). -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Validating single arg id
On Fri, Oct 16, 2009 at 7:31 AM, J. Shirley jshir...@gmail.com wrote: What database do you use? In MySQL and SQLite I get no exception at all: Postgresql. $ perl -Ilib -e 'use MyApp; my $obj = MyApp-model('Schema::User')-find(bogus); print defined? . ( defined $obj ? yes : no ) . \n'; no DBIx::Class::ResultSet::find(): DBI Exception: DBD::Pg::st execute failed: ERROR: invalid input syntax for integer: bogus [for Statement SELECT me.id ... sub safe_find { my ( $self, $id ) = @_; if ( $id =~ /^(\d+)$/ ) { return $self-find($1); } die I pity the fool; } Yes, that's one approach.But, I'm not sure I can think of a reason why I would not want to always do that, so might as well just override find (or really search_rs, as that is what is called by find) and check id (or ids) there. But, there need to think about where, columns, and so on. -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Re: Validating single arg id
On Sat, Oct 17, 2009 at 12:50 PM, Aristotle Pagaltzis pagalt...@gmx.dewrote: * iain iainhubb...@googlemail.com [2009-10-16 17:30]: until we did this we had boilerplate validation at the top of all the local actions. ++ Bill, in another thread you asked me for an example of how Chained helps make things like complex auth checks more DRY. I’ve been meaning to respond with an example out of my $job codebase, but until I get around to it, here’s your hands-on example of something it’d buy your codebase immediately. :-) I meant to respond about that. Perhaps I'm missing something, but the chained example works great if there multiple actions that need to get at that Foo object. They can all chain back to the same root which validates the id and then fetches the Foo object with that id and stuffs it into the stash. But, its often the case (well, my case) that there's only *one* action that fetches Foo, but there's also single actions for find()ing a number of other objects. If I'm following the chained example correctly, then there would be root for each -- Foo, Bar, Baz, and so on each running basically the same validation. I suppose the root can be written in a way to fetch many different object types by inspecting the current action and thus the fetch for Foo, Bar, Baz, etc. objects could all have the same root of the chain. If I have many actions that do $c-model( $whatever )-find( $id ) and I want to validate id doesn't it seems like find() (or really search_rs() ) would be the method to override? Perhaps a better approach would be add a safe_find() as J. Shirley suggested, but what good are methods if you don't override them. ;) -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Re: Adding default query parameters to generated links.
On Sat, Oct 17, 2009 at 12:42 PM, Aristotle Pagaltzis pagalt...@gmx.dewrote: * Tomas Doran bobtf...@bobtfish.net [2009-10-13 00:00]: I'd very likely go with this myself. You can apply it as a role, and then trivially remove it later, it's wrapping one method and so low impact, and there are no negative consequences if your session goes away for any reason.. Just feels like less moving parts to me... Less implicit state on the server = better HTTP style: I agree with you here. • Easier to scale: at the app level, no session to replicate between web servers or communicate via the DB; above the app level, easier to use proxies to selectively route/cache stuff by inspecting URIs I wish that was possible, but in this case the session data structure is a beast. I'm currently pulling data from the existing app's session and populating $c-session for the data that needs to be used. • Better user experience: allows multiple tabs with different interaction state in each This is something you have mentioned before, and I'm on board with this. I assume you mean a session id in the URL, right? http://en.wikipedia.org/wiki/Session_fixation#Do_not_accept_session_identifiers_from_GET_.2F_POST_variables recommends not having a session id in the URL. One way to mitigate risks is by changing session ids often (as recommended by the article). But, assumes web requests are serial in nature, which they are not. So, it's not that simple to just send back a new session id every request or ever few minutes. -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Re: Validating single arg id
On Wed, Oct 21, 2009 at 6:52 AM, Aristotle Pagaltzis pagalt...@gmx.dewrote: * Zbigniew Lukasiak zzb...@gmail.com [2009-10-21 14:15]: What is the advantage of this over: sub view : Local { my ( $self, $c, $id ) = @_; $self-start( $c, $id ); # do something with $c-stash-{obj} return 1; } Consider `/forum/7/topic/13/post/4/editform`. The end point in that chain would be sub editform : Chained('post') { my ( $self, $c ) = @_; # ... } The equivalent URI with Local would be `/editpost/7/13/4` and the action would look like this: sub editform : Local { my ( $self, $c, $forum, $topic, $post ) = @_; $self-load_post( $forum, $topic, $post ); # ... } I think that depends on your data. If $forum, $topic, and $post make up a path on disk then yes, the chain is really useful. If $post is a primary key and there's a relationship $post-topic-forum then there's no need for those, of course, and confusion if $post-topic is not the same id as passed in the URL for the forum. Perhaps a good use for the chain there is for access control -- the current user might only have access to some forums so a chain makes it easy to do that kind of validation early in the chain and then detach if access fails. The chain also allows fetching the $forum and $topic objects and place them in the stash. But, again if they are related can load the $post with a join and avoid separate calls to the database. (But, it may be the case that caching the $forum and $topic individually make sense.) Anyway, my actions often look like this: (a bit oversimplified) package MyApp::Forum::Post; sub view : Local { my ( $self, $c, $post_id ) = @_; $c-stash-{post} = $c-user-fetch_post( $id ) || return $c-res-status( 404 ); } Kind of ugly calling that on the user object, but it's just an example. That method, for example, might do a join with the forum and topic tables and also with a permissions table to make sure the user can access the post. I do prefer the /forum/post/334/view type of URLs, though, but my CRUD actions often end up like this: /forum/post - list /forum/post/edit - create (POST) /forum/post/edit/22 - view (GET) update (PUT/POST) /forum/post/delete/22 And it's very DRY because there's separate model method for each. The create method may have a different URL structure to specify the topic, or it might be ?topic=123, or it might be part of the post parameters. -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Question about C:P:Unicode(::Encoding)
On Sat, Oct 24, 2009 at 1:26 PM, Bernhard Graf cataly...@augensalat.dewrote: These plugins hook into prepare_parameters() to decode data. Why does it leave query_- and body_parameters untouched? Always seemed like a bug to me. http://www.mail-archive.com/catalyst@lists.scsys.co.uk/msg02350.html http://www.mail-archive.com/catalyst@lists.scsys.co.uk/msg05312.html http://www.mail-archive.com/catalyst@lists.scsys.co.uk/msg04321.html I wonder about something like this, although might be cases where there's something in there that should not be decoded. after 'prepare_body_parameters' = sub { my $c = shift; my $v = Data::Visitor::Callback-new( ignore_return_values = 1, value= sub { $_ = decode_utf8( $_, $CHECK ) unless Encode::is_utf8( $_ ); }, ); $v-visit( $c-req-body_parameters ); return; }; Although I have cryptic notes elsewhere where I had problems with Data::Visitor. Hum, should have taken better notes. -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
[Catalyst] Suppressing exceptions in Engine / UploadProgress
I'm running under mod_perl, and when a user aborts an upload I get an error in the log. [error] Caught exception in engine Apache2::RequestIO::read: (70014) End of file found at /usr/local/share/perl/5.10.0/Catalyst/Engine/Apache.pm line 187 I don't see that it's possible, but is there any way to ignore some exceptions (similar to how execute() can ignore a detach)? Not sure there's a good case for it, other than to simply ignore the above. (I can modify my log monitoring to ignore those, for example). But, there doesnt's seen to be any way to get out of that block without generating an error message. eval { if ($class-debug) { my $secs = time - $START || 1; my $av = sprintf '%.3f', $COUNT / $secs; my $time = localtime time; $class-log-info(*** Request $COUNT ($av/s) [$$] [$time] ***); } my $c = $class-prepare(@arguments); $c-dispatch; $status = $c-finalize; }; if ( my $error = $@ ) { chomp $error; $class-log-error(qq/Caught exception in engine $error/); } Maybe I could override prepare() and return a different $c object with dummy dispatch and finalize methods, but I suspect another prepare() and that approach would break. BTW -- I was looking at this along with the UploadProgress plugin. It does this to catch aborted uploads. The plugin is a bit old, but doesn't seem like overriding croak is a good way to catch exceptions. Is there any reason not to wrap prepare_body in an eval? Yep, I just tried and under mod_perl2 this doesn't catch aborted uploads. my $croaked; { no warnings 'redefine'; local *Carp::croak = sub { $croaked = shift; }; $c-NEXT::prepare_body(@_); } if ( $croaked ) { if ( my $id = $c-req-query_parameters-{progress_id} ) { $c-log-info( UploadProgress: User aborted upload $id ); # Update progress to flag this so javascript will stop polling my $progress = $c-cache-get( 'upload_progress_' . $id ) || {}; $progress-{aborted} = 1; $c-cache-set( 'upload_progress_' . $id, $progress ); } # rethrow the error Catalyst::Exception-throw( $croaked ); } -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
[Catalyst] Request: Wrong Content-Length value: 2628941
I see this error every once in a while. It does not seem like an aborted connection (I get a different error for that). Is there any other reason why the read() method might returning false before done. while ( my $buffer = $self-read($c) ) { $c-prepare_body_chunk($buffer); } I suppose if $buffer just happened to be zero. Probably should be checking defined there. Could this message be updated to report the length of the body read, too? And maybe display the last X bytes of data read might be useful in some cases. -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Re: Language selection in URLs
On Wed, Nov 18, 2009 at 9:55 AM, Aristotle Pagaltzis pagalt...@gmx.dewrote: * Joel Bernstein j...@fysh.org [2009-11-15 16:30]: No no no! Allow the client and server to negotiate what content to serve for the resource identified. As a URI to a resource which may vary according to many dimensions, /path/to/some/content is fine. GET /path/to/content HTTP/1.1 Accept-Language: en Accept: text/html Conneg sucks. It’s a good idea for non-human-readable content served in a variety of formats, but for variants of anything that’s like a “page” you should have separate URIs, so that people can reliably bookmark one of them, or send someone else a link to talk about it and not have the other person see a completely different page (or file or whatever), etc. It’s OK to accept conneg on neutral URIs and then *redirect* to specific URIs based on the Accept-* headers. But don’t make conneg the *only* way to pick a specific version of a resource. I think this is very good advice. If you really must stick it in the URL, I'd go for something like: /path/to/content/en /path/to/content/pt_BR etc Worst of all worlds, IMO. The query parameter is easiest to implement for the server, while the path prefix allows the user to hack the URI conveniently (so the latter is what I would do). Your suggestion is harder to implement than both and makes URIs annoying to hack. I think Catalyst makes the path prefix the easiest. WIth the query parameter (which I'm doing now to be compliant with a legacy app) it's trivial to by using around uri_for, but I'd much rather do something once (modify $-req-base) than override every uri_for. I do have a slight fear of the query parameter messing with caching. I doubt it's much of an issue these days, though. -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Avoiding UTF8 in Catalyst
On Sat, Nov 21, 2009 at 2:22 PM, Marc SCHAEFER schae...@alphanet.ch wrote: Hi, my goal: no UTF8, in short: Can you explain why? That sounds like something to regret later down the road. Even if your templates have latin1 characters you can still output utf8. Less to to worry about with entity encoding, I guess. - all the perl code, all the data files, all the template files and the UNIX locale are all in ISO-8859-1 Hopefully you don't have much text in your perl code. Get the database into utf8 will be a win long term. - the HTML result should be in ISO-8859-1 (Content-Type: text/html; charset=iso-8859-1) You need to encode the body, too. Plugin: Unicode::Encoding was just updated by Tom, IIRC. - the Content-Length: should be correct. First, I modified lib/MyApp/View/TT.pm as follows: __PACKAGE__-config(TEMPLATE_EXTENSION = '.tt', DEFAULT_ENCODING = 'ISO-8859-1', WRAPPER = 'wrapper.tt'); There's a DEFAULT_ENCODING option? Isn't it just ENCODING? Apparently all diacritic characters are expanded into HTML entities. Where does that happen? -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Avoiding UTF8 in Catalyst
On Mon, Nov 23, 2009 at 2:01 AM, Marc SCHAEFER schae...@alphanet.ch wrote: On Sat, Nov 21, 2009 at 05:16:24PM -0800, Bill Moseley wrote: Apparently all diacritic characters are expanded into HTML entities. Where does that happen? It looks like it's TT::View's htmlentity which does this, not just for and friends. It's not a big issue for me. Maybe it could even be parametered. Still not following. You are talking about Catalyst::View::TT? BTW -- when looking at C::V::TT I see where you got that DEFAULT_ENCODING from -- it's documented in C::V::TT. As far as I know there's no such setting in Template Toolkit. There's ENCODING to specify the encoding of your templates. If your templates are 8859-1 with 8 bit characters my suggestion would be to convert them to utf-8 and set ENCODING to utf8 for the templates, and move toward utf8 everywhere.Make sure you use the plugin to decode and encode. -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Re: Avoiding UTF8 in Catalyst
On Mon, Nov 23, 2009 at 10:14 AM, Aristotle Pagaltzis pagalt...@gmx.dewrote: Encode the string to the destination encoding (not just character set), so that the string represents an encoded octet stream, and then look at the plain old character length of that string. That will always give you the right answer, regardless of whether that string is packed bytes or variable-width integers. Correct. And I'd argue that when it's time to set the length it should die if utf8 flag is still set. When calculating the length the content should have already been encoded. Again, at some point decoding and encoding should be core not just a plugin. It's an important part of the request cycle. -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Request: Wrong Content-Length value: 2628941
On Mon, Nov 30, 2009 at 6:21 PM, Tomas Doran bobtf...@bobtfish.net wrote: On 15 Nov 2009, at 16:07, Tomas Doran wrote: I suppose if $buffer just happened to be zero. Probably should be checking defined there. Yep, that should be fixed. This has been fixed in trunk, r12100 http://dev.catalystframework.org/svnweb/Catalyst/revision?rev=12100 Does that look sane to you? Sure. Always good to have sane code. Thanks for taking time for this. Like I said, I get these errors every so often, and it would be nice to understand why -- not sure if it's a broken client or perhaps some encoding error. Not sure what additional error message would be helpful, though. Thanks again, -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
[Catalyst] Sub-classing Application
I have an existing application Foo. I'd like to create a new application Bar that has very similar actions. What I'm wondering is if there's a way where I could run catalyst.pl Bar to create a new empty application and then tell it to inherit from Foo. That is load_components would load all of Foo's Models, View, Controllers (basically creating in-memory empty sub-classes for each component) and setting up all actions as if they were in Bar. I could then override or add additinal actions as needed to Bar::Controller::Whatever, which would inherit from Foo::Controller::Whatever. Any ideas how to implement something like that? -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Sub-classing Application
On Wed, Dec 16, 2009 at 8:31 AM, J. Shirley jshir...@gmail.com wrote: The documentation seems quite sparse, but if you look at the source it just essentially does: my $locator = Module::Pluggable::Object-new( search_path = [ map { s/^(?=::)/$class/; $_; } @paths ], %$config ); If you have MyApp-config-{search_extra} = [ 'Foo::Controller', 'Foo::Model' ]; it should DTRT. It almost works, but it sets up actions for both controllers using each controller's class. That is, if I start application Bar and pass in search_extra = [qw/ Foo::Controller / ] then indeed actions from Foo::Controller::* will get added to the application. But, they are added with the Foo:: namespace. that is, that controller is not a parent-class of Bar::Controller::*. It also means I can't easly overide. If I have hello() in both thes controllers: Foo::Controller::Whatever::hello() Bar::Controller::Whatever::hello() I then get: [debug] Loaded Path actions: .-+--. | Path| Private | +-+--+ | / | /index | | / | /index | | / | /default | | / | /default | | /whatever/hello | /whatever/hello | | /whatever/hello | /whatever/hello | | /whatever/howdy | /whatever/howdy | '-+--' So, I guess what I really would like is a way to have it load the Foo::* modules but register their actions in the associated Bar:: namespace so that /whatever/hello calls Bar::Whatever::hello but Foo::Whatever is the parent class if hello() doesn't exist in Bar. (That sentense make sense?) I guess that means when Foo::Controller::Whatever is found, register the actions in the Bar::Whatever namespace and push Foo::Whatever onto @Bar::Whatever::ISA. The problem I'm looking at is rebranding applications. In the past I've managed to modify config based on, say, domain name and use a different root (for templates, css, images, etc.) But, over time the application has to be forked due to changes in code. But, 90% of the controller code is still the same between the two applications. So, it would be handy to say, this application inheits from Foo, but these with a few methods added or overridden. -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Sub-classing Application
On Wed, Dec 16, 2009 at 9:59 AM, J. Shirley jshir...@gmail.com wrote: It seems you're after something that would best be accomplished using roles that get composed into the controller. Ah, of course. I think that's a good idea. I rewrote a bunch of plugins and other code using Roles and indeed it was pretty painless. Means I need to make mostly duplicate and empty controllers for both Foo and Bar applications but seems like a reasonable price to pay. Now, I just need to think about good ways to inherit my temples (if not simply modifying my INCLUDE_PATH) so that templates can be shared (or overridden). Thanks, -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Sub-classing Application
On Sun, Dec 20, 2009 at 3:05 PM, Matthias Dietrich mdietr...@cpan.orgwrote: Hi, I'd like to catch up this slightly old topic... I've build a small app for a customer and want to pull out some sections to build a small CMS I can use in several upcoming apps. I don't want to copy-paste everything everytime an app comes up or update all instances. So it would be very nice to teach an arbitrary Catalyst app to glue everything from another app (controllers, models *and* views (note: html and static files, too!)) into the arbitrary app. There were several ideas in the past on this list to featurize apps, like the solution CatalystX::Featurizer/CatalystX::Features posted by Rodrigo. The problem with this solution is: features cannot just be released to CPAN and used by other persons without requiring them to change their Catalyst app heavily. What I'm thinking of is something like use base/parent with specifying an action where the external Catalyst app is connected. I'm more concerned about code reuse and maintenance in a set of large and similar applications. CatalystX::Features seems like a good approach for a large application that is made up of different features (or products) that may be managed by different teams. That's a slightly different problem than one of code-reuse I initially posted about. In addition to the need to have features/components/products managed separately and combined into a larger application I need to use those parts in different applications that are slightly different. That is, I need a second application that is very similar to the first, but with slightly different controllers and somewhat different templates, css, js. etc. So, I've been thinking about building the controllers as Moose roles. Then build CatalystX::Features grouped by application where the Feature's controllers use the roles (and override as needed). I'm much less clear how to reuse/share templates and css between applications -- but in that case it might just be better to copy. The trade-off will be files scattered all over the place, something developers are still trying to get used to with basic Catalyst. Maybe someone here can come up with something more clever. But, do need a better way to manage large applications. I'm also debating CatalystX::Features approach vs. just using separate applications (with shared sessions, etc.). That's a bit more flexible for deployment (e.g. some features on a subset of servers) but sharing of common templates, css, js, etc. is more of a challenge. -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] proper flow control with $c-foward, in search of greater grok
On Fri, Jan 8, 2010 at 6:55 AM, Tomas Doran bobtf...@bobtfish.net wrote: $c-response-redirect($c-uri_for(/user/$user_id/blog/$blog_id/entry/list)); Eww, don't do that. You want $c-response-redirect($c-uri_for_action('/user/blog/entry/list', [$user_id, $blog_id])); I agree that's the right approach, but not sure I see why the Eww in this specific case. Can you explain? -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
[Catalyst] Not cleaning up temporary files / HTTP::Body
HTTP::Body::Multipart creates temporary files for uploads. The temp files are created with File::Temp( UNLINK = 1 ). Catalyst then deletes these temp files in $c-finalize. The problem is that an exception can happen and then the temp files are not deleted. Happens quite often, it turns out. I seem to always see this in the logs at the time of the orphaned temp file: Caught exception in engine Apache2::RequestIO::read: (104) Connection reset by peer Aborting an upload isn't that unusual. I can set temp directory for these uploads and use cron to clean them out, but I wonder if they could not be cleaned up better automatically. For example, unlink in DESTROY when the request object goes out of scope. Or perhaps better, don't have HTTP::Body set UNLINK = 1 by default and when the upload object finally goes out of scope File::Temp will remove the temp file. HTTP::Body explicitly removes the File::Temp object from the upload part, but I'm not sure why it needs to do that. Why not leave the File::Temp object in the upload part object then let it go out of scope at the end of the request. Where should this be addressed? In Catalyst or in HTTP::Body? -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Re: modules for conditional GET ?
On Sun, Jan 17, 2010 at 11:35 PM, Dami Laurent (PJ) laurent.d...@justice.ge.ch wrote: Indeed, this is exactly what I want to do. The app has a config file (not a Catalyst config file, but another file having to do with business logic), and some super-users have a mechanism for hot uploading of a new config to the server, at any time. A few app pages are expensive to compute, and they depend on the client and on that config file. So clients should keep asking for those pages at each request, and depending on the If-Modified-Since header and on the timestamp for the config file, the server can decide if it's worth recomputing the page for that client, or rather send a cheap 304 Not Modified. Be careful about using timestamps if you are running multiple web servers behind a load balancer (or may expand to where you will be behind a balancer). Here's a read on Etags: http://developer.yahoo.net/blog/archives/2007/07/high_performanc_11.html For resources such as css, js, images I tend to create URLs that include an md5. Those include cache headers that don't expire and thus when the content changes the URL changes. I have also done that with text/html pages, but it's less common. For a config file you can send the config through Object::Signature to get an md5. You could recalculate and cache that whenever a new config is uploaded. For static pages (for non-logged in users) the pages tend to get cached for some number of minutes as it's not critical that a change is seen exactly the same time by all users. Dynamic content is not cached, of course, but elements of the page may be cached in memcached. -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Error handling
On Mon, Jan 18, 2010 at 9:05 AM, Steve Kleiman st...@prodhub.com wrote: Thanks for all the feedback on how to log from within a schema. Log4perl is my hero. I'm still looking for a way to capture runtime errors and ideally email them out in addition to logging to a file. I use log4perl to send error level messages to an additional log file. Then I use cron to check for errors every few minutes and send a notification email. I like that better than the possibility of hundreds of processes cranking out mail at the same time. The plan is to move to a logging server to centralize this a bit more. -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
[Catalyst] Catalyst::Controller::REST vs. Catalyst::Controller::DBIC::API
I'm looking at adding an API interface to an application and looking at the modules listed in the subject. Anyone have experience with both? Any recommendations or experiences you can share? I have another application that I added an API to using XML RPC. It works by adding attributes to actions not unlike Catalyst::Plugin::Server::XMLRPC. It's been very helpful to have the API use the exact same controller actions as the web interface. Some of the existing controllers contain complex logic, so obviously want to use that same code for the API as well. -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
[Catalyst] How to de-serialize json?
Following up on our recent simulating discussion on adding an API to an application, I wonder is someone can help me understand something: Catalyst uses HTTP::Body to parse body content. It currently handles these request content types: our $TYPES = { 'application/octet-stream' = 'HTTP::Body::OctetStream', 'application/x-www-form-urlencoded' = 'HTTP::Body::UrlEncoded', 'multipart/form-data' = 'HTTP::Body::MultiPart', 'multipart/related' = 'HTTP::Body::XFormsMultipart', 'application/xml' = 'HTTP::Body::XForms' }; But, Catalyst::Controller::DBIC::API and Catalyst::Controller::Rest both use Catalyst::Action::Deserialize. My question is this: why use an action class instead of extending HTTP::Body to deserialize the content? Isn't it HTTP::Body's job to decode the body based on the content-type of the request? I'm just wondering if I'm missing some important reason why these other request content types are handled differently. Seems like HTTP::Body is the correct place to do all decoding. Decoded JSON, for example, would just end up in $c-req-params and controllers could be oblivious to the encoding of the request (similar to how we don't really care how params are decoded if the body is x-www-form-urlencoded or form-data). True, could end up with a request parameter that is a hashref, but I don't see anything wrong with that as long as parameters are validated correctly. So, why different approaches to decoding request body content? -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] How to de-serialize json?
On Sat, Jan 23, 2010 at 1:40 PM, J. Shirley jshir...@gmail.com wrote: If I assume that decoding is synonymous with de-serialization, it makes more sense. At first thought, I just don't think they're that similar, though. Maybe in implementations (comparing JSON to HTTP POST parameters) it is, but in the case of HTTP::Body decoding a mime64-encoded JPEG, it isn't at all. With a jpeg I assume the content type would be form-data (that included an upload in the form) where the file ends up in $req-uploads, not as a request parameter. I find decoding requests analogous to Views. In my apps controllers take input (params, arguments and uploads) and the result is data in the stash. Then the View has the job of serializing (normally to HTML via template, but no reason it can't be JSON or anything else). In fact I have many controller actions that are used for both normal full-page HTTP requests and AJAX requests. So, similar to how the controller action does not know or care what view is going to be used, the controller action doesn't know or care how the request is serialized over the wire. That's how I picture it. From a behavior standpoint, having a POST/PUT'd JSON segment that ends up in -params would be maddening to me. They aren't parameters, not even in the loosest of the RFC interpretations. I'm trying to understand that point of view. Why is that maddening? If you have a request serialized as json then $req-parameters would go unused and instead have the deserialzed request end up some place else, say as $req-data? I have an XMLRPC API to an application. I implemented it by creating an HTTP::Body subclass that parses the XMLRPC XML body. The method ends up mapped to an action, the params ends up as body parameters, and base64 elements end up as uploads. As a result existing controller actions can be used for both XMLRPC request and for normal web requests. All I have to do to expose the action in the API is add XMLRPC( $method_name ) as a action attribute. Catalyst::Engine hard-codes HTTP::Body. I think it would be more flexible if the body parser class could be a config option (to allow easy sub-classing), -- similar to how the request class can be defined -- but it's not that difficult to set up now. Just have to add the content type to %HTTP::Body::TYPES. Thanks for your comments, I appreciate the feedback. -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] How to de-serialize json?
On Sat, Jan 23, 2010 at 5:39 PM, Hans Dieter Pearcey hdp.perl.catalyst.us...@weftsoar.net wrote: Excerpts from Bill Moseley's message of Sat Jan 23 19:45:28 -0500 2010: With a jpeg I assume the content type would be form-data (that included an upload in the form) where the file ends up in $req-uploads, not as a request parameter. That assumption may hold true for *your* applications, but he didn't say anything about a form or even a web browser. It's perfectly reasonable, especially in the context of REST APIs, to talk about non-form-based request bodies. (I've written actions that accepted PUT requests with a content-type of application/vnd.ms-excel, for example.) But, that's a different content type. I assumed form-data. So, in this case in my HTTP::Body deserialization layer approach, I'd thus add: $HTTP::Body::Types('application/vnd.ms-excel') = 'My::ExcelParser'; which would result in $req-uploads having an upload object for the spreadsheet. My::ExcelParser would probably be a thin sub-class of something like My::Upload. Then the same controller would work with both a web request with an upload field or this REST request and expect to find the upload object in $req-uploads. -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] How to de-serialize json?
On Sat, Jan 23, 2010 at 7:20 PM, Hans Dieter Pearcey hdp.perl.catalyst.us...@weftsoar.net wrote: As far as I can tell, you missed the point of my message, which makes me wonder if I've missed the point of yours. Are you talking about a set of conventions you'd like to be able to build for your own use on top of HTTP::Body, or a set of conventions that you expect everyone will want and so should be built into HTTP::Body, or something else entirely? I thought you were saying that the request might not be a normal form posting, and I was saying only that HTTP::Body can support that, too. I was not suggesting everyone should use one method over another. HTTP::Body seems (to me) like the natural place to deserialize. Yet, the REST modules I cited use an action class to deserialize. Thus, I was wondering if there was a specific reasons for that approach that I had not understood. That's really all. -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Where is the form field lost?
On Sun, Jan 24, 2010 at 7:03 AM, Octavian Rasnita orasn...@gmail.comwrote: I need to know if the form didn't have a file upload field, or if it had it but no file was uploaded. Give your upload field(s) a name like upload_1 and then see if it exists in uploads. Can you give me a hint where I should look for finding where the empty file upload field is skipped if it is empty? That's how HTTP::Body works. If there's a filename, which there is with upload fields, but the file name is empty, then it's skipped. if ( exists $part-{filename} ) { if ( $part-{filename} ne ) { $part-{fh}-close if defined $part-{fh}; delete @{$part}{qw[ data done fh ]}; $self-upload( $part-{name}, $part ); } } BTW -- I think that delete of fh should not happen (and the temp file should be set to unlink on destroy). Otherwise you can end up with orphaned temp files. -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Where is the form field lost?
On Sun, Jan 24, 2010 at 8:31 AM, Octavian Rasnita orasn...@gmail.comwrote: Give your upload field(s) a name like upload_1 and then see if it exists in uploads. I gave it the name file, but if the file is not uploaded, it doesn't appear in uploads(). (I hope file is OK as a name, no?) Why do you need to know that a field existed on the form but was submitted empty? Checkboxes don't submit if not checked. You get what's included in the post and have to work from that. Either you have an upload or not, right? Aha, so I should look better in HTTP::Body. Is there a reason it does that? (Leaves alone all other empty form fields but deletes the empty file upload fields?) Without commends in the code or documentation can't really know the author's reasoning. I guess it assume uploads go to temp files and no need to do that if there's no content. (IIRC, I thought filename was optional, but maybe I'm mistaken.) I'm kind of curious why it does this: if ( $part-{fh} ( my $length = length( $part-{data} ) ) ) { $part-{fh}-write( substr( $part-{data}, 0, $length, '' ), $length ); } instead of: print $part-{fh} $part-{data} if $part-{fh}; Maybe for fear of line ending conversion?? -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] UTF-8 and mails
On Mon, Jan 25, 2010 at 6:54 AM, Bernhard Graf cataly...@augensalat.dewrote: Does Mail::Sender::Easy automatically encode _text into the encoding given in charset? If not, then /you/ have to do it: Encode::encode(utf-8, $string); That's what I do. Specifically, I have this for generating inline text emails: for my $template ( @templates ) { my $body_content = $self-render_email_template( $template, $c-{stash} ); push @parts, Email::MIME-create( attributes = { content_type = ( $template =~ /_html$/ ? 'text/html' : 'text/plain' ), charset = 'utf-8', disposition = 'inline', encoding = 'base64', }, body = encode_utf8( $body_content ), ); } } Concerning use utf8: As soon as you have any non-ASCII literals in your code (Herr Müller), then you want to use that, BUT only if your perl code file is also utf-8 encoded. Read the perl man pages about unicode, if you are not sure. Read them twice, and then once more. ;-) It's not a shame, if you don't get the whole picture at first. And IMO string literals are better left in templates, in the databaes, and .po files. I use English, so I don't worry about utf-8 variable names. I always assumed at some point utf8 would become the default for Perl source, though. -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] How to de-serialize json?
On Tue, Jan 26, 2010 at 6:33 AM, J. Shirley jshir...@gmail.com wrote: I'm all for reusable code, but in no way should HTTP::Body start taking this behavior by default. I'm not really that sure how effective it is, anyway. No, I was not suggesting that would be the default (although I'm not sure why not handling other serializations by default is a bad idea). Not sure what you mean by effective. decode_json( $c-req-body ); Is just not that hard :) Of course it's not that hard. Of course, this isn't hard, either: [1] map { s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg; $_ } split /[;=]/, $c-req-body; I see those as similar operations. The request is serialized in both cases. But, one should not have to worry about adding low-level details like that to application code when using an elegant web framework. ;) No big deal. I was just curious why the HTTP::Body approach was not used in the existing REST/RPC modules, as that was already the place used by Catalyst to de-serialize the body. I thought maybe there was a reason I might not understood, which is why I asked. [1] Or whatever the correct approach is, and apologies to Damian for the map. -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] How to de-serialize json?
On Wed, Jan 27, 2010 at 1:16 PM, Tomas Doran bobtf...@bobtfish.net wrote: On 27 Jan 2010, at 15:33, Bill Moseley wrote: No big deal. I was just curious why the HTTP::Body approach was not used in the existing REST/RPC modules, as that was already the place used by Catalyst to de-serialize the body. I thought maybe there was a reason I might not understood, which is why I asked. HTTP::Body isn't really structured for this - you can (and I _do_ in one of my apps) add or override the content type handlers. However as it's class data, this is perl interpreter wide - which means that two different applications with conflicting requirements can't exist in the same mod_perl interpreter - not awesome. I see. So you are saying that Content-Type: application/json might need to be deserialized differently in different applications that share the same interpreter? Obviously, json could decode into an array ref so that could not be mapped to request parameters. Is that what you mean? Or that an application might want the raw json? -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Using Catalyst with mod_per or FastCGI on heavy traffic web application
Just so it's not one-sided, I moved from FastCGI to mod_perl some years back. Start up and restart time was one issue, IIRC, but mod_perl was trivial to configure and solved stability issues we were seeing. I never went back, so maybe it's better now. Is there now a manager that will spawn more FastCGI processes based on load? The Catalyst server is used for development. The app knows it's running with that engine and disables the SSL requirements, but logs that the page would be blocked if not in SSL. Starting different configurations is no problem at all. I have an app startup script that generates the httpd.conf file from configuration files at startup time. It's basically start_app --app=foo --mode=testing. The apps have dev, testing, qa, stating, and production modes, so as you can see it's not a big deal. All those are on different machines, but different modes can use different ports, of course, so can be on the same machine. I'm usingCronolog so there's no log rotation/restart needs. mod_perl does seem a bit heavy weight just to serve requests, especially since all we use is the response handler. We also don't use many modules (SSL is not handled by Apache). I've meant to look at other server options, but there's not pressing need. I don't really see how what server you use effects error messages. Stderr is stderr. I would never use the canned Apache error responses anyway for a site. True, Apache can run as only one user. But, that's normally the apache (or whatever) user which has very limited access, which is what you want. So, I don't see a benefit of running as different users. Apps may need to run on multiple machines so only part of the file system need access to would be for temp files. I think mod_perl is daunting to some due to all the possibilities (and default httpd.conf Apache provides) but really the config required to get it to serve a Catalyst app is just a few lines. My entire files are pretty small: $ fgrep -v '#' httpd.conf | grep -v '^$' |grep -v LoadModule | grep -v 'Module' | wc -l 40 -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Using Catalyst with mod_per or FastCGI on heavy traffic web application
On Fri, Jan 29, 2010 at 10:59 PM, Adam Mackler nab...@mackler.org wrote: But with mod_perl, when you're restarting your application, you're starting the whole web server, so during that time...which can be longer than you expect for a number of reasons...people attempting to reach your site will get browser errors saying your site is down or unreachable. But with fastcgi, the web server keeps running and can serve a static error page while the fastcgi server is not available. And with no perl in the mix, restarting the web server itself takes less time and can be done more gracefully. That makes no sense. If fastcgi processes are down, then, well they are down. If all your mod_perl servers are down, they are, well, down. Maybe you are assuming the Apache that is running mod_perl also serves static content? Or that there's only one web server? Or there's no load balancer? Or it's not run with a reverse proxy as is the standard approach? We found that restarting with FastCGI took longer. Maybe that was because each process has to compile the app (instead of compile and fork to many processes?). Is that true? I can't remember. -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
[Catalyst] Large requests with JSON?
As you might have picked up I'm working on an REST api that uses JSON in the request. I need to also allow large file uploads. HTTP::Body::OctetStream will chunk the request body and send to a temp file, but Catalyst::Action::Deserialize::JSON will load the temp file into memory. Obviously, want to limit that. AFAIK, there's no way to stream parse JSON (so that only part is in memory at any given time). What would be the recommended serialization for uploaded files -- just use multipart/form-data for the uploads? BTW -- I don't see any code in HTTP::Body to limit body size. Doesn't that seem like a pretty easy DoS for Catalyst apps? I do set a request size limit in the web server, but if I need to allow 1/2GB uploads or so then could kill the machine pretty easily, no? -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Large requests with JSON?
On Fri, Feb 5, 2010 at 8:56 PM, Tomas Doran bobtf...@bobtfish.net wrote: On 5 Feb 2010, at 20:54, Bill Moseley wrote: AFAIK, there's no way to stream parse JSON (so that only part is in memory at any given time). What would be the recommended serialization for uploaded files -- just use multipart/form-data for the uploads? Don't? Why not just do a PUT request with all the data as unmangled binary? As in don't provide a way to upload meta data along with the file (name, date, description, author, title, reference id) like the web upload allows with multipart/form-data? Or invent some new serialization where the meta data is embedded in the upload? Or do a POST with the file, then flag the new upload as incomplete until a PUT is done to set associated meta data? The API is suppose to offer much of the same functionality as the web interface. JSON is somewhat nice because, well, customers have requested it, and also that it lends itself to more complex (not flat) data representations. Of course, urlencoded doesn't have to be flat -- we have some YUI-based AJAX code that sends json in $c-req-params-{data}. But I digress. The 'multipart/form-data' is nice because if the client is well behaved uploads are chunked to disk. XML can also do this, too (I have an HTTP::Body subclass for XML-RPC that chunks base64 elements to disk). BTW -- I don't see any code in HTTP::Body to limit body size. Doesn't that seem like a pretty easy DoS for Catalyst apps? I do set a request size limit in the web server, but if I need to allow 1/2GB uploads or so then could kill the machine pretty easily, no? Well, you set it at the web server.. That stops both overlarge content-length requests, and when the body exceeds the specified content length. Yes, for example in Apache LimitRequestBody can be set and if you send a content-length header larger than that value the request is rejected right away. And, IIRC, Apache will just discard any data over the what is specified in the content-length header (i.e. Catalyst won't see any data past the content length from Apache). But yes, you have to provision temp file space for n files in flight x max file size... You are making an assumption that the request body actually makes it to a temp file. Imagine you allow uploads of CD iso files, so say 700MB. So, you set the webserver's limit to that. Normally, when someone uploads HTTP::Body you expect OctetStream or form-data posts which ends up buffering to disk. Now, if someone sets their content type to Urlencoded then HTTP::Body just gathers up that 700MB in memory. MaxClients is 50, so do that math. Granted someone would have to work very hard to get enough data at once all to the same web server, and if an attacker is that determined they could find other equally damaging attacks. And a good load balancer can monitor memory on disk space on the web servers and stop sending requests to a server low on resources. Most applications don't have this problem since uploading that large of a file is likely rare. Well, that assumes that everyone is using something in front of Catalyst that limits upload size (like Apache's LimitRequestBody). It's unusual to have a very large valid Urlencoded (or non-upload form-data) body in a normal request (that's a lot of radio buttons and text to type!) so, it would is not be wise for HTTP::Body to limit the size of $self-{buffer} to something sane? I suppose it could flush to disk after getting too big, but that doesn't really help because some serializations require reading the entire thing into memory to parse. -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Re: action_for with user_id removed ...
On Sat, Feb 6, 2010 at 2:25 AM, Kiffin Gish kiffin.g...@planet.nl wrote: From an HTTP point of view it is unwise to make endpoint URIs like that which can refer to many different resources at any one point in time. I'm not so sure that I agree, though I can appreciate your point of view. We have debated this in our apps, too. If some set of URLs are only valid once a user logs in then do they have an implicit domain? Plus, it sure is handy in documentation to say: To update your personal profile go to: http://example.com/myprofile vs. To update your personal profile go to: http://example.com/user/your id here/profile Because you know what the tech support calls will be like -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Re: Large requests with JSON?
On Sat, Feb 6, 2010 at 11:29 AM, Aristotle Pagaltzis pagalt...@gmx.dewrote: * Bill Moseley mose...@hank.org [2010-02-06 17:30]: As in don't provide a way to upload meta data along with the file (name, date, description, author, title, reference id) like the web upload allows with multipart/form-data? Or invent some new serialization where the meta data is embedded in the upload? Neither, depending on your metadata. The things you did mention could quite well be sent as request headers. No need to put another envelope inside the HTTP request envelope. Could you be more specific? For example API request to 1) create a new user in account #1234 with name, email, etc. 2) create a user but also provide a photo when creating the user 3) upload a document for the user and the document must include an associated collection of meta data (e.g. filename, timestamp, author etc.). The uploaded document must include this meta data before it can be accepted. -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Run catalyst tests against another database
On Sat, Feb 6, 2010 at 2:01 PM, John Atzger jatz...@hotmail.com wrote: I want my Catalyst tests to run against a test database. I wrote this: package MyApp::Model::DB; use strict; use base 'Catalyst::Model::DBIC::Schema'; BEGIN { require MyApp; my $db = $ENV{HARNESS_ACTIVE} ? 'test' : 'myapp'; my $config = MyApp-config-{database}{$db}; __PACKAGE__-config( schema_class = 'MyApp::Schema', connect_info = { dsn = $config-{dsn}, user = $config-{user}, password = $config-{password}, ); } I don't want test information in my code. How do people do this? I use separate config files that get merged into the main config. -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
[Catalyst] JSON views and CamelCase column names
As you know, by default the TT View maps actions to template files based on the action's name. The controllers place data into the stash and the templates render that into markup. I need to do something similar with JSON output. The current JSON View will turn data in the stash into JSON, but what I need is code that sits between the controller action and the JSON view that is action-specific (just like the templates are action-specific). This code would take the objects in the stash and build a hash used by the JSON view. I need to do this for a large number of actions, so I'm looking for something to work for all controllers. I could do this in the controller (map the data into the stash for the JSON view), but the same controllers are used for many views, so the controller's job is just to populate the stash with model objects. The rendering of HTML, as well as rendering to JSON, is a View task. The TT View has a system for running code (the templates) for each action. I'm looking for suggestions how to implement something similar when rendering JSON. That is, having the view call methods based on the action name -- and suggestions were those methods should live. Those action-specific view methods would be responsible for mapping to a hash structure the JSON view will render. In case the question wasn't clear: how should I implement a View that has methods associated with specific controllers and where should that live? Of course, I'm interested in hearing other approaches, too. There's a part 2 of this question: For the JSON responses the view will be mostly returning column data fetched from the model (using DBIC queries). The database column names are not CamelCase, but the front-end/Javascript programmers favor CamelCase. That means for every action we need to map data from the stash to a JSON response and at the same time map to the CamelCase names. I'm not thrilled about that mapping -- I'd prefer to use the column names to reduce confusion and simplify code, but that's another story. Also, these JSON responses will become part of the public API, so once we start down the CamelCase path we are there for good... Maybe this is a DBIC-list question, but I'm wondering if anyone has a clever way where I could map the DBIC objects to a hash but where the CamelCase names are used instead of the existing column names. It's painful enough without having to do it for every action explicitly. Something similar to DBIC's HashRefInflator. -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Check session expiry without extending it
On Thu, Mar 4, 2010 at 7:05 AM, Peter Karman pe...@peknet.com wrote: // make sure we are logged in before every xhr request Ext.Ajax.on('beforerequest', function(conn, opts) { if (!AIR.Auth.isAuthenticated()) { AIR.Auth.login(); return false; } return true; }); I thought about this, but in our case the ajax was checking for a specific session because the server-side session had state info need for the ajax request. So, just allowing the user to log in again was not possible. That's probably bad design on top of bad design. In our case probably better to rethink then entire process and just make request that can be independent and either work or fail in some graceful way. making assumptions about expected state is problem the root cause. -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Which C::View::PDF should I use?
On Friday, March 5, 2010, Charlie Garrison garri...@zeta.org.au wrote: Good afternoon, Thanks, that was a good intro. It looks like I could almost get away with a simple LaTeX table for the form. But I can see myself getting bogged down by the details; I think latex is going to be too hard for this project. I may still come back to it as best option though. If your needs are pretty simple there's HTMLDOC. I've used it for simple reports and invoices. http://www.easysw.com/htmldoc/ It doesn't sound like it would be right in this case (modifying existing pdf) but it's worth knowing about. -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Best practices: XML output from static XML
On Sat, Mar 6, 2010 at 6:34 AM, J. Shirley jshir...@gmail.com wrote: Just one last question. When you talk about using 'lib/MyApp/View/MyView.pm', you mean that is also correct to create a simple perl Module for your view. Then implement process method in the View.pm and forward the context from the Controller ( $c-forward( $c-view('MyView') ); )? David Yup, that is exactly right. Expanding this thread a bit... I asked a related question in another thread. What if you want a view that needs separate code for each action? For example, when no template is explicitly defined in the action, C::View::TT will pass control to a template based on the action's name. Each action can have its own associated template. Likewise, for a different type of output I might need code to run for each action. Say the controller action for the path /music/recent_uploads places a list of objects in the stash. Rendering with HTML sends it to TT (e.g /templates/music/recent_uploads.tt). But, what if the client wants, say an RSS feed or JSON response for that same action? Doesn't that seems like a View's job to turn that into a feed or JSON? But for both of those examples I need code to serialize those objects in the stash (into a feed or JSON). So, my question is 1) how to map the action into a view method, and 2) where those view methods should live? I don't think a separate view for every possible action is the correct approach. Seems better to have in an end() method simply: $c-forward( $c-view( $view_type ) ); A simplistic or naive View approach might look like: sub process { my ( $self, $c ) = @_; my $method = $c-action-reverse; $method =~ s{/}{_}; $self-$method( $c ) if $self-can( $method ); } But, that's flat and ugly. I could keep the view code in with the controllers which in some way makes maintenance easier (related code is together), but then the view is not separate. my $method = $c-action-name; $method .= '_render_json'; $c-action-controller-$method( $c ); So, what's the recommended approach to per-action view code? -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Best practices: XML output from static XML
when the response is actually json. -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Best practices: XML output from static XML
names. Second, the ::REST approach has the controller actions building the entity structure which feels more like a view operation. Minor point but turning, say, a DateTime object into a human-readable format (or ISO8601 for JSON response) both seem like views. -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Taking advantage of idle periods by performing some action(s)
On Thu, Mar 25, 2010 at 5:30 AM, Ido Perlmuter i...@ido50.net wrote: I'm looking for direction on how to possibly implement a feature in a Catalyst app that automatically performs some action, or actions, when the app is idle and hasn't been accepting requests (either none or some small number). For example, let's say I want my app to take advantage of such situations by indexing documents to KinoSearch, rebuilding a sitemap.xml file, whatever. Doesn't really seems like the job of a Catalyst app to run background tasks. What's wrong with cron? It can run a script and see if the machine's load is low (or some other measurement) before deciding to run. Thing is, I do not want (if possible) to implement a job queue such as TheSchwartz. I do not want an outside worker, I want my app to be the worker, and let it decide by itself what to do instead of take jobs from a queue. Yes, you do want an outside worker. It can be part of your app, but it should be separate from Catalyst. Put it in a model class. Ok, sure you could have cron run App/script/app_test.pl /path/to/action but why load all of Catalyst just to run some code in your application? -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Taking advantage of idle periods by performing some action(s)
On Thu, Mar 25, 2010 at 8:04 AM, Ido Perlmuter i...@ido50.net wrote: Kiffin, thanks for the heads up about Plugin::Scheduler, seems to fit my needs quite good. I used that plugin in an early application that is still running. I've never spent the time to debug, but I've had times when it seems an error in one job resulted in other jobs not running. So, if you really want to send requests to your running Catalyst application then I'd use cron and lwp/wget instead of the plugin. -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Catalyst Redirect to https
2010/3/25 Octavian Rasnita orasn...@gmail.com The back end servers don't know if the current request is an http or an https one and on each redirect, they do the redirection using the http scheme. (I have also set the configuration option using_frontend_proxy to true.) Also, because the back end servers receive only http requests, $c-req-secure is always equal to 0. I have read that I can set the HTTPS environment variable to On and I put the following line in the configuration file of the load balancer Apache server in the virtualhost that handles SSL requests: SetEnv HTTPS On Does that header get to Catalyst? Obviously, check that first. I have this in a after 'prepare_headers': $res-secure( 1 ) if lc( $req-header( 'Https' ) || '' ) eq 'on'; The load balancer sends all traffic to the same port. The load balancer sets that header for SSL traffic. I used to send to two different ports and then detect SSL based on the port number. Same result either way. -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Catalyst Redirect to https
On Fri, Mar 26, 2010 at 12:46 AM, Octavian Rasnita orasn...@gmail.comwrote: *From:* Bill Moseley mose...@hank.org SetEnv HTTPS On Does that header get to Catalyst? Obviously, check that first. I didn't know that HTTPS should be an HTTP header and not an environment variable so I have also added as a header. Sorry, I missed that you were setting the environment var -- I assumed you were setting a header in your load balancer. Obviously, the front-end web server's environment is not shared with the back-end's environment. You have the front-end load balancer add a header to SSL requests when being proxied to the backend. Then the backend looks for the this header and, if set, sets $c-req-secure(1); You just need some way for the front-end to tell you which requests are SSL on the front end. As mentioned, another approach is to use two different ports on the backend. And finally, even though I forced $c-req-secure to be true, $c-uri_for_action still uses the http scheme and not https so in the entire application the redirects won't be done correctly and this is the big problem. You need to set $request-secure(1) earlier in the request so that when $base is created it has the correct scheme. Here's a simple example application: $ cat lib/ssl.pm lib/ssl/Controller/Root.pm package ssl; use Moose; use namespace::autoclean -except = 'meta'; extends 'Catalyst'; __PACKAGE__-setup(); after 'prepare_headers' = sub { my $self = shift; $self-req-secure( $ENV{SSL} ); }; 1; package ssl::Controller::Root; use Moose; use namespace::autoclean -except = 'meta'; BEGIN { extends 'Catalyst::Controller' } __PACKAGE__-config-{namespace} = ''; sub hello : Local { my ( $self, $c ) = @_; $c-res-body( $c-uri_for( '/hello' ) ); }; 1; ~/ssl$ script/ssl_test.pl /hello http://localhost/hello ~/ssl$ SSL=1 script/ssl_test.pl /hello https://localhost/hello Don't get confused by that example where I'm checking $ENV. You will want to check a request header (or port) as that's how the front-end can communicate with the back-end. Note that Catalyst::Apache::Engine will check for $ENV{HTTPS} is ON but for that to happen you would have to do something like $ENV{HTTPS} = $c-req-headers( 'HTTPS' ) very early in the request (or get Apache to set it based on the request header. I find it easier to just explicitly set secure(1) based on a header (or port). -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Picking template type based on input
On Fri, Mar 26, 2010 at 5:50 AM, Tomas Doran bobtf...@bobtfish.net wrote: The controller asks the model for some data, and then chooses how to present that data (whilst the view actually handles the presentation details. That means the controllers have to be aware of the view. That is, the controllers have to know what view is going to be used so that it can fetch the data needed for that specific view. Is that what you are saying? -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Picking template type based on input
On Sun, Mar 28, 2010 at 7:12 AM, Jon mailinglists jon.ml...@gmail.comwrote: In my catalyst app I have this sub (not really, but this makes things easier to follow): sub get_info : Local { my ($self, $c) = @_; my $info = $c-user-member_info; my $res = 'MyNamespace.callback({ResultSet:{totalResultsAvailable:73399,firstResultPosition:0,totalResultsReturned:20,Result:[{Title:'.$info-get_column('first_name').' '.$info-get_column('last_name').',zip_code:'.$info-get_column('areacode').'}]}});'; $c-response-body($res); } I think I get it now. I first thought you were talking about users adding javascript to pages you render -- that is, allowing someone to inject script onto your pages. (I'm hoping someone will jump in an correct anything I say wrong here -- which often seems like the best way to get a response here...) I think the short answer is, don't return JSONP -- don't return JSON wrapped in a function call. That's a way to bypass security provided by the same-origin policy. Let me restate what I think you are saying: 1. The good site (MY-CATALYST-SERVER in your example) returns the JSONP above as long as the user is logged in. By logged in that means the request includes a valid session id in the cookie. 2. In another tab of the same browser when viewing a page from evil_empire.com a request is made to http://MY-CATALYST-SERVER:3000/member/get_info. 3. That request will include the cookie required to gain access (and thus return private user data). 4. Javascript is returned that includes a call to a function passing the user's private data to that function. 5. evil_empire.com now has access to the user's name and zip code. Yes, this is true. This is a security hole. But by returning JSONP you gave away this access. JSONP is application/javascript -- and as such it can be loaded from any domain. Loading javascript is not limited by same-origin policy. (If it was then Content Delivery Networks would be of limited use.). Note, this has nothing to do with YUI.Get. evil_empire.com just needs to add a script tag to their page to fetch the JSONP from your app. YUI.Get just provides a dynamic way to accomplish that. Your application should only return data via JSON, not JSONP. For a script to read JSON data it needs to use XMLHttpRequest and that request is limited by the same-origin policy. That is, javascript running on evil_empire.com's page cannot do an AJAX request to your catalyst application. Hopefully, that's clear -- and correct. ;) -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Picking template type based on input
On Sun, Mar 28, 2010 at 3:13 PM, Tomas Doran bobtf...@bobtfish.net wrote: Speaking of XSRF: It would be possible to parse the HTML your app output, add an extra hidden field to any forms you had generated in the page, and then look for a previously generated token and redirect / refuse the request if it wasn't present. I do this -- every POST must include token, and the token can only be used once. That means the the form must be fetched before bing posted (to generate the token). I'm not sure I understand XSRF enough to know if there's a way to get around the token (or trick the browser into doing a POST for, say, and img. And for a SSL only site that requires login, I'm also not so sure the token requirement helps that much for security. The original purpose was to slow down form spamming and to prevent double-posting of forms. The tokesn don't work so well with an API, of course, but XSRF needs a browser, AFAIK (hard to trick a user of an API into making a request..) However this would obviously not catch forms generated purely from Javascript (and a number of other cases), and so I'm somewhat doubtful of its value in more complex applications. I can certainly remember the stuff which tries to achieve this that is baked into Rails making me scream :) I'm not clear how javascript is an issue here, unless the attacker has injected javascript into my site. The example on Wikipedia for XSRF is to add a link to your bank on the attackers site, which you view: img src= http://bank.example/withdraw?account=bobamount=100for=mallory; Which is a pretty bad bank that allows that. A third-party (evil) page can include the above and force a GET request that is not noticed, but to make a POST it would have to have a form where the response is from the bank. That is, you would see the bank's response page. Can't do it via an AJAX request because of the same-origin policy. Slippery stuff. -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Picking template type based on input
On Sun, Mar 28, 2010 at 6:05 PM, Tomas Doran bobtf...@bobtfish.net wrote: On 29 Mar 2010, at 01:06, Bill Moseley wrote: I do this -- every POST must include token, and the token can only be used once. That means the the form must be fetched before bing posted (to generate the token). Have anything generic you'd care to share? :) Nothing generic -- and it's not rocket science, either. Or very glamorous. I simply have a template macro for creating my form tag which also includes the hidden field with the token id. Then part of form validation processed used for every post I check that the token was provided and is valid. The token is either in the database or in memcached. (I have a form_posted() method that does this check, along check for the correct method (PUT or POST) .) The issue is that if you're generating a form in javascript, and submitting it in javascript, then something finding forms in the page output (and adding a token automatically), which was what I initially suggested - would fail to find the form, and ergo you'd have an issue :) (i.e. it couldn't 'just work automatically' in that case without the application collaborating in some manor). I think I get it. Thanks, -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Picking template type based on input
On Mon, Mar 29, 2010 at 2:12 AM, Jon mailinglists jon.ml...@gmail.comwrote: It seems like it is. I just stumbled upon this when checking out YUI 3, and had managed to stay oblivious to this problem before. I then went on with checking if one could make an attack that way and got a bit scared by the results and asked here. Classic case of reinventing wheels. I called it XSS because I figured it was scripts running across sites, but apparently this is XSRF as you said. I think you are missing it still. It's not really XSRF. These terms are a bit fuzzy and overloaded, but in general: XSS is where an attacker places script on the attacked site. This is accomplished by correctly not filtering user input. One example is a blog site where the attacker places script on a common page that many others view. Another approach is for the attacker to create a link to the site they wish to attack which includes javascript and trick people into clicking the link. When the script runs it can, for example, send the cookie to the attacker's site and then the user can use that session id to gain access. XSRF is (typically, AFAIK) where the attacker's site includes a tag that generates a request to another site. Wikipedia is worth reading, and it includes this example: img src= http://bank.example/withdraw?account=bobamount=100for=mallory; The attacker has to know (or hope) the person that is viewing the page with the img has an account at bank.example and that they are logged in (or have a remember me cookie). Of course, the img does a GET request to the poorly-coded bank site and incorrectly causes something to happen. This works because the browser will send the cookie with the request. Now to your example. It's ok to load and run javascript from a third party site. And any data that javascrpt brings in will be available to the page that is loading the script. This is expected. It's also expected that the browser will send the site's cookie along with the request. Your example seems like XSRF because the attacking site is requesting a resource (javascript) from your site -- just like the img above is making a request to another site. It's also similar because in both your example and the XSRF example above, the site is doing something dumb. The bank.example site is dumb because it's allowing a GET request to make a change. Your example is making the mistake of providing javascript that gives private data away. And that's why AJAX requests follow same-origin policy. It provides a way to fetch data from a site, but only from the site that the browser is viewing. (Sure, the attacking site could create a form (perhaps in a hidden iframe) and POST that, but hopefully your bank will return an Are you sure you want to transfer your money to Mallory? confirmation screen first.) Wouldn't it make sense to have and option in Authorization which generates and stores a token server side, in either a database or in the session (like Bill seems to do) at login time. If I'm not horribly mistaken would one token be enough for a session since the attack is blind and there's no way for a 3rd party to figure it out unless using brute force. If that is correct, one can go about playing CRUD and allowing /member/get_info?token=... and /member/set_info?token=... with GET requests? First, don't set_info with a GET request. That just makes the XSRF easy. Second, if this is to protect against your example that returns JSONP (and thus leaks personal user info) then, the real solution is to not return JSONP. I think the tokens are a mixed bag. Yes, the tokens would help, but if you have them on your URLs then you have to worry about bookmarking and link leaking. The tokens I use help with POSTing forms, but for critical changes I still add an Are you sure? page. -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
[Catalyst] HttpOnly flag dependency.
About a year ago Scott Thomson provided a patch to CGI::Cookie::Simple for supporting the HttpOnly flag. 1.109 2009-04-16 - Added support for HttpOnly to CGI::Simple::Cookie. Thanks to Scott Thomson for the patch. I don't see that dependency in Catalyst::Runtime or C::P::Session::State::Cookie. Could that be added to Runtime? Thanks, -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Distributing and updating Cat apps
2010/3/30 Tomáš Znamenáček tomas.znamena...@gmail.com I have a Catalyst application that I would like to upload from the development box to the production server. Is there some kind of best practice to do that? My requirements: I don't think there's any standard approach. I know many people seem to just do a checkout from the repository. 1) The process should take care of the dependencies and run the tests before installing. (Let’s say the deps are declared in Makefile.PL or Build.PL.) I have a separate cron job that polls the repository looking for changes. When it notices that a new version has been checked in it checks it out and runs the full test suite. A big fat email goes out if test do not pass. If it passes, but a previous run failed an email also goes back congratulating everyone on fixing the problem. This works well because the same process can be used on multiple applications and is constantly running -- not just when it's crunch time to push a release. 2) It would be nice to keep the application isolated in one directory so that I can keep several instances under the same account to do primitive staging. Agreed. I have a separate build process. This is a simple process and doesn't run any tests (because the build process may happen on a build server w/o dependencies needed by the application). This simply does an svn export, then it runs build/build_app.sh which then runs whatever scripts are needed to build that specific application. For example, minify and combine css and javascript, etc. Then a tarball is built of this export (named after the application and version) and made available on a web server. This can then be pushed to any server. The push process simply fetches the tarball from the build web server, unpacks it into it's version-specific directory and runs the Makefile to test for dependencies on the target machine. If that passes a symlink is updated to point to this new version and the web server is restarted. The symlink makes it easy to revert to a previous version or to have multiple versions on the same machine for testing. The applications have separate YAML files for different environments. There might be dev.yml, testing.yml, qa.yml, and produciton.yml. Each machine has a file in /etc/$app_name that sets what environment the application should start in (i.e. what YAML config file to use). Push to testing and the app starts and uses the testing database as configured in testing.yml. I've used this method for pushing directly to production, but in other cases use it for staging and then rsync to production servers from staging. I’ve read something about local::lib, but I’m still not sure about how to put things together. This has to be a common scenario, isn’t it? When you are finished updating the development version, what do you call to upload the update to the production server and what exactly happens along the way? Good question. Hopefully someone has a great solution. In the past I've used cfengine to make sure machines have the right dependencies. I've also used a local lib and rsynced that and messed with @INC and PERL5LIB, which doesn't make me happy. (Think about init.d scripts, cron jobs, etc.) The next approach is to build packages (deb or rpm) of the application and dependencies and let the OS package manager handle it all. The goal there, besides making it easy for deployment, is to break out common code shared by apps into libraries. That said, there is something to be said with throwing everything in the application's lib directory since you know when it's pushed you will have exactly the same code used in development. Lot easier to revert when everything is under a a single symlink. I've heard of people that build an entire Perl installation and keep that separate from the OS installed Perl. -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
[Catalyst] [OT] XSS, XSRF, and REST
We love our acronyms. As discussed in another recent exciting thread, I use a unique, single-use token on forms that must be returned with a POST. This seems to be the best approach to prevent XSRF[1]. But, what about for a (RESTful) API where it's common to receive a PUT or POST request without expecting that a GET was done immediately before to fetch the token? In those cases I cannot expect that the unique token would be provided. Therefore, I need a way relax the token requirement for some requests, but only if I'm sure it's not coming from a browser that might be generated via an XSRF attack. Is it enough to allow the requests if a valid session is is provided in a Cookie *plus* one of: - A valid token in the body parameters (as the case for a valid web request) - A valid JSON body in the request (assumes that a XSRF could not trick a browser into sending json, etc.) - A X-Requested-With: 'XMLHttpRequest header (or similar header) that would indicate that the request was not generated from a web browser (via XSRF attack) because it included a header not normally sent by browsers. - Require API users to fetch a token and place it in a HTTP header or body for every request (that seems expensive). Hum, if a GET can fetch a token could the attacker use Flash/Siverlight to accomplish the GET and gain access to the response data? Of course, the first two won't work if there's no body (say a DELETE). Do (will?) browsers send a DELETE with form method=delete? What approach can you recommend for determining that a request is not from a XSRF-susceptible client? [1] A second commonly suggested approach for protecting against XSRF is to include the session id in the POST. Then the server can compare the session id in the cookie (something the XSRF attacking site would not have) to the session id sent in a body parameter. The problem I have with this approach is then the client (the web browser) must have access to the session id either via javascript or directly in the markup. I use the HttpOnly to prevent javascript access (in complying browsers). And I feel like providing the session ID in the markup opens up the possibility of XSS that would send the session id to an attacker. Of course, a successful XSS attack and your wide open anyway. -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Distributing and updating Cat apps
On Mon, Apr 5, 2010 at 2:31 AM, Oleg Kostyuk cub.ua...@gmail.com wrote: 2010/3/30 Bill Moseley mose...@hank.org: .. The applications have separate YAML files for different environments. There might be dev.yml, testing.yml, qa.yml, and produciton.yml. Each machine has a file in /etc/$app_name that sets what environment the application should start in (i.e. what YAML config file to use). Push to testing and the app starts and uses the testing database as configured in testing.yml. Catalyst already have such possibility: read end of DESCRIPTION in Catalyst::Plugin::ConfigLoader, and more details in description of get_config_local_suffix(). Yes, similar. ConfigLoader didn't exist when I wrote the above, and it's not a plugin (the Plugin is just a thin wrapper) -- it's available outside of Catalyst which is very useful.Wasn't there talk a while back about splitting up ConfigLoader to make it available outside of Catalyst and with the ability to merge files? -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Distributing and updating Cat apps
On Thu, Apr 1, 2010 at 12:51 AM, Toby Corkindale toby.corkind...@strategicdata.com.au wrote: We package things up into Debian-style packages, and then upload those to a local repository of packages. Then servers can just be updated using the standard system tools (apt). Hi Toby, This is really the direction I'm heading now (although it's looking like CentOS and RPMs). Can you answer a few general questions? Are you using Template Toolkit? How (or really where) are the templates managed? Where do they get installed, how does the TT View know where to find them, etc? Do they end up in /usr/share/app/ for example? I'm sure you never have to roll-back a release, but I also assume you are prepared to roll-back if needed. How does that process work? What about your static content (css, js, images)? Where do those get installed? Any special tricks when using an app in development vs. production? (For example, under dev I use source css, js, but otherwise the app uses combined and compresses css and js. You have a choice of either packaging up every single Perl dependency into a Debian package too (which is a world of pain), or installing all your dependencies into a local directory that you ship with the application. I recommend the latter.. (you'll still need to include dependencies on things like the C libraries for your database client, etc though, in the debian control file.) We are doing a mix. But, for the most part we are creating single modules (packages). Mostly that was to encourage inclusions of unit tests and just more fine-grained management. But, it is more work, true. -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
[Catalyst] Catalyst::Utils::home()
I was hoping to use Catalyst::Utils::home outside of Catalyst -- I can do that but I must load the application because home() looks in %INC to find where the application class is located. It's not a huge problem to load the class, but it's not necessary for my needs. Do you see any reason why home() could not walk @INC looking for the app .pm file if not found in %INC? Or is there another approach to find home? Oh, btw -- # we found nothing return 0; maybe just return; -- or simply die Cannot determine home for App $class; -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
[Catalyst] Automated testing?
I have a cron job that watches for changes to SVN, and when found the cron script exports the code and runs the tests. The idea is to notify developers if they check in code that causes testing to fail. I'd like to move away from using my custom scripts to a more generic tool that will do automated testing for all our packaged Perl code, not just the Catalyst apps. (Since the Catalyst app is just another Perl distribution). Perhaps something similar to what cpan testers use where email notifications are sent but also provide a web-based history of testing. Do you do anything similar? Anyone using Smolder and/or SmokeRunner::Multi or other standard tools for their in-house code? Thanks, -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] RunAfterRequest/delayed Catalyst view
On Fri, Apr 30, 2010 at 2:38 PM, Steve Kleiman st...@prodhub.com wrote: Here goes...hopefully a simple test case for the RunAfterRequest oddness. This is really not the response you were hoping for, but have you considered not using RunAfterRequest? I either send email directly during the request to the local sendmail or I write it to a store and another (non-web) process on a separate machine (or machines) manage delivering the mail. -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
[Catalyst] Returning error codes to the user.
I have a CRUD interface to an application. This is used for both the Web and directly as an API. The model uses DBIC which, as you know, allows chaining resultsets, which I use to add additional constraints to the result set. So, a request for, say, /user/1234 might result in: $c-model( 'App::User' )-search( { 'me.id' = $requested_user_id, 'me.active = 1, 'me.date_expires' = [ { '' = \'now()' }, # past expired { '=' = undef }, # or never expires ], 'account.active'= 1, 'account.balance' = { '' = 0 }, 'account.locked'= 0, 'account.date_expires' = [ { '' = \'now()' }, # past expired { '=' = undef }, # or never expires ], }, { join = 'account', }, ); [That's not a great example because we assume that user and account might get checked when first logging in. Ignore that. Just assume a query that does a lot of joins to test if a given object can be accessed.] The request either succeeds (200) or fails (404). The VAST majority of the time the ID provided will return a row because a valid ID was provided by the application itself in the first place. But, for a tiny, tiny percent a request might fail. Then the question is *why* did it fail? What WHERE condition or join failed? Just like our favorite topic premature optimization, I don't think it would be wise to write the above in multiple stages (and multiple requests to the database) just to check each step for something that almost never fails. On the other hand, it's not unreasonable for an API request to return a reason why something failed. Sure would make tech support's life easier. So, what would you recommend? Have a separate /user/$id/debug method that does a separate step-by-step of the business logic? Scrap all that really handy chaining of resultsets that works so well with Catalyst's chained actions? -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] RunAfterRequest/delayed Catalyst view
On Fri, Apr 30, 2010 at 3:59 PM, Steve Kleiman st...@prodhub.com wrote: That's definitely my fallback if necessary. I really like using the Catalyst-centric option because it's easier for my brain to compartmentalize. It keeps the email dispatching process consistent with the rest of the Email::Template paradigm used throughout my app. Also it's not just for email I'm using RunAfterRequest...it's a bunch of slow database processing that leads up to the generation of the email. So I was hoping to drop the whole bit into RunAfterRequest instead of having a cron job deal with it. Keeps all my stuff in one place and for a Catalyst newbie that's a nice thing (if it works). Ya, it's a fine line. I tend to think Catalyst's job is to handle a request and return the response as soon as possible and then move on to serve another request. But, if you have processes to spare then why not use them? Might need to think about other things like how a long running process might effect the need to restart the sever, etc. Job queues are nice. -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Returning error codes to the user.
On Sat, May 1, 2010 at 6:17 PM, Tomas Doran bobtf...@bobtfish.net wrote: So, what would you recommend? Have a separate /user/$id/debug method that does a separate step-by-step of the business logic? Scrap all that really handy chaining of resultsets that works so well with Catalyst's chained actions? Given that 'a tiny, tiny percent a request might fail', why not do the step by step for the tiny failed set and then present the reason to the user for those? (Or am I missing something obvious here?) You are not missing anything if that's your recommendation. I assume lots of people here are creating real web applications with Catalyst so was inquiring how others handle this situation in the design of their applications. I have a CRUD controller base class to help generate a RESTful-like API that is used by both API users and with an AJAX-based application, which I assume is not that uncommon with Catalyst apps. For example, when a PUT /thingy/52113 fails (which means the query used to fetch the item failed), how do you reported to the user? A 404 with a text description? Some kind of error code in the response body? I my case, I'm added a method explain_not_found() to the base class that can be overridden in the controller to provide specific details in textual format. That method would be used to break the query into parts to test each join and condition, for example. As a side note: Frankly, I enjoy the discussions of real problems and solutions on this list. I try not to find it discouraging that old topics like benchmarking methods calls and the few inflammatory remarks seem to get so much traction. :) -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Returning error codes to the user.
On Sun, May 2, 2010 at 12:53 PM, Matt S Trout m...@shadowcat.co.uk wrote: Am I correct in thinking that's built up in multiple -search calls? Somewhat, yes. ... if you keep all the intermediate resultsets around in the stash or wherever (or better still refactor to resultset methods and have your custom resultset class keep the intermediate resultsets around) then it seems like it should be pretty easy to walk back up the chain making the extra queries until one returns data - at which point you know the last step you walked back up is the problem child for this request. That's an interesting idea. So, instead of adding multiple constraints in a single call to search I could do it individually. I'm not sure if I need to subclass the resultset_class -- could just add a controller base class method. i.e.: $self-add_to_resultset( $c, 'User account must be active', { me.active = 1 }, ); $self-add_to_resultset( $c, 'User account expired', { 'me.date_expires' = [ { '' = \'now()' }, # past expired { '=' = undef }, # or never expires ], }, ); $self-add_to_resultset( $c, 'Parent account must be active', { 'account.active' = 1 }, { join = 'account' }, ); etc. Then, as you say, if $self-current_resultset-first (top of stack) fails then work down the stack until find the spot where the query passes and return the previous message. Thanks, -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Catalyst::Plugin::Session: Duplicate entry errors
On Fri, May 7, 2010 at 2:33 AM, Tobias Kremer tobias.kre...@gmail.comwrote: I'm not sure why this is happening because the _load_row() method of the store delegate explicitly wraps everything in a txn_do() which should make the find_or_create() atomic and not prone to concurrent select/insert/update problems. Does it make it atomic or just fail if a second session tries to create with the same primary key? Looking at some old code I see that I first attempt a create, and if that fails with a duplicate error I then do a find. Don't need a transaction for that. -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
[Catalyst] Adding build scripts to Makefile.PL
I have a number of scrips that need to be run when building an application. For example, I have a script that minifies javascript and css. In many cases it's a real Makefile dependency -- need to run a command to turn one file into another -- but in some cases don't know the sources of the targets (i.e. a script just finds all .css files and minifies them) so might just want to run a command every time make is run. Anyone have examples of how to set this up in Makefile.PL (which uses Module::Install)? Thanks, -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Adding build scripts to Makefile.PL
On Mon, May 10, 2010 at 9:31 PM, Florian Ragwitz r...@debian.org wrote: On Mon, May 10, 2010 at 06:15:03PM -0700, Bill Moseley wrote: I have a number of scrips that need to be run when building an application. For example, I have a script that minifies javascript and css. In many cases it's a real Makefile dependency -- need to run a command to turn one file into another -- but in some cases don't know the sources of the targets (i.e. a script just finds all .css files and minifies them) so might just want to run a command every time make is run. You can do globbing in your Makefile.PL, or use a script to just find the files, and have a target that depends on whatever the script outputed, or whatever. Ok, thanks. Do you have an example you can share? Thankfully it's been years since I created a Makefile by hand. ;) Will that work in cases where there's no direct input and output files? Seems I remember using .PHONEY targets when I needed to run programs that didn't alway produce a direct output -- that or create flag files to compare against. I have build scripts that combine .js and .css files into collections and then outputs four versions (text, gzipped, and both with a version string), another that extracts text to localize from javascript and validates that the strings can be looked up in a db, one that builds jemplate files and another that builds .js from other sources. Some use File::Find to find sources and others use config files. Another processes images and other media. The source file list can be very large, of course. Anyone have examples of how to set this up in Makefile.PL (which uses Module::Install)? Module::Install has a postamble() command to add makefile snippets to the generated Makefile.PL I've used postamble to add new targets (make foo) but I'm not clear how to make just make depend on them. Maybe that's not the correct approach, but I want our existing tools that build RPMs to run this code as part of the normal make process . Thanks, -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
[Catalyst] Catalyst::Model::DBIC::Schema and ACCEPT_CONTEXT -- current user in model
I've managed to keep context related items (e.g. current user) out of my DBIC model up until now. Now finding it would be very helpful to be able to call a method on a row object and have access to the current user. So, I'm trying to hunt down an example of how to make a current user available to row objects. Seems this has come up many times but not having much Google luck. Anyone have a link or an example? Thanks, -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Catalyst::Model::DBIC::Schema and ACCEPT_CONTEXT -- current user in model
On Thu, May 13, 2010 at 2:54 PM, Kieren Diment dim...@gmail.com wrote: sub ACCEPT_CONTEXT { my ($self, $c ) = @_; my $new = $self-meta-clone_object($self, arg = $c-stash-{something}); return $new; } Hum, I'm not clear how that works with Catalyst::Model::DBIC::Schema, because I want to be able to call current_user on any row object. $track-current_user. Again, I have some aversion to saving a current user in my model. That was more my question. Getting something to work is easy enough, just not sure it's the best approach. For example: In my Music::Schema base class I add an accessor: has 'current_user' = ( is = 'rw' ); Then in my Result base class add a convenience method: sub current_user { return shift-result_source-schema-current_user } Now, I might want to have a method $track-can_user_access so in my Track class: sub can_user_access { my ( $track, $current_user ) = @_; # Use saved user if one not passed. $current_user ||= $track-current_user || die 'no current_user'; ... return $has_access; Finally, in Catalyst my Model class would then look like: package MyApp::Model::Music; use Moose; extends 'Catalyst::Model::DBIC::Schema'; use namespace::autoclean; before 'ACCEPT_CONTEXT' = sub { my ( $self, $c ) = @_; $self-schema-current_user( $c-current_user ); }; __PACKAGE__-meta-make_immutable; 1; That implementation is simple enough, but not clear is it's the best approach. Backing up, the issue that came up is I have a base class used for setting up very common actions for an API. The controllers for, say, /music/track/$id are set up with configuration only: package MyApp::Controller::Music::Track; BEGIN { extends 'MyApp::Controller::API' } __PACKAGE__-config( return_colums = [qw/ id track_name position can_user_access /], ); 1; The controller base class then builds a response that includes those columns and methods. But, the base class doesn't know when to pass in the current user to a method (e.g. for can_user_access). So, I either extend the config to tell the base class to pass the current user to some methods: pass_user_to_meethod = [ 'can_user_access' ] Or I use something like ACCEPT_CONTEXT to set the current user in the schema. Better ideas? This is going to be a killer Music app. I just hope CDs don't go out of style. -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Not cleaning up temporary files / HTTP::Body
On Fri, May 21, 2010 at 10:24 AM, Tomas Doran bobtf...@bobtfish.net wrote: On 13 Jan 2010, at 14:53, Bill Moseley wrote: Where should this be addressed? In Catalyst or in HTTP::Body? I'm all for it being addressed as suggested, in both places (for extra double sure). It's been five months since I looked at this. HTTP::Body now has an option to have it remove the temp files on DESTROY, but catalyst would have to set that. I see that what I did was replace the Multipart handler with one that simply sets UNLINK = 1 and have not had any problems since. We removed the cron job we used to use for keeping /tmp clean. -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
[Catalyst] Catalyst::Model::DBIC::Schema and dbh_maker
I would like my Catalyst::Model::DBIC::Schema model class to be able to inspect the configuration and modify connect_info. Specifically, based on a flag in the config either pass connect_info unmodified or replace dsn/user/password with a dbh_maker sub. What seems to work ok is to use before ' COMPONENT' = sub {} and simply modify the passed in arguments. I do not have any config in the model class that I need to worry about merging with the passed in arguments. Is this a reasonable way to do this? -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Refactoring question
On Thu, May 27, 2010 at 5:38 AM, Steve st...@matsch.com wrote: I think your business logic should be moved to the model, not the controller. The model does the heavy lifting. My model is currently comprised only of my DBIC Result and ResultSet classes. Are you suggesting that some of the logic in my controllers should be moved into my DBIC classes, or should I create new Moose classes. If Moose, how do I 'hook up' those classes to Catalyst? There's always room for another layer of abstraction. That said, I find that adding custom ResultSet and Result methods (and using custom base classes for both) handles most of the abstraction. You can abstract most calls so that you aren't writing little, if any, DBIC-looking code in your controllers. The Controller actions should be pretty tiny -- just a few lines at most. Decouple as much as possible. If you have to fire up your web application in order to test database insertion, that's wrong. Build the model so that you can use Perl one liners to manipulate data through it. True, although I've been working on an app that is entirely AJAX-based so the Catalyst app is exposed as an API of URLs (I'll avoid the term REST here). So, that means all access to the app is via the API -- even for cron scripts. As a result, the bulk of the tests are talking to the app via URLs and HTTP method names. (PUT /user/1234). We still have tests for the model, but no other code uses the model directly (by contract). We still push as much code low into the model as possible. And to your original post: Take a look at http://search.cpan.org/~masaki/Catalyst-Controller-Resources-0.08/ . I would split up your existing controllers. Think about the objects returned and name them them the same. I often have model class names that are the same as controller class names (and form classes). Need to get a user? /user/$id Instead of a verb like /ViewStmt use a name for the thing you want: /statement/$id or /invoice/$id. I'd be interested to hear opinions about your admin interface, but, I often mirror existing controllers with /admin/user/$id (admin's view of a user). I often have a /login controller -- POST /login creates a new token (cookie). Then there's room for /login/forgot_my_password kind of thing. -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Refactoring question
On Thu, May 27, 2010 at 8:09 AM, Steve st...@matsch.com wrote: At present, the only DBIC-looking code is contained in two lines (chaining resultsets). I'm not sure it's worth the effort for this application, but it certainly will be for others. Can you elaborate on the custom base classes idea? Sorry for not being clear. I was referring to DBIC base Result and base ResultSet classes. In which case the controllers would be...? Admin, User, and Statement? Yes. -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
[Catalyst] Catalyst::TraitFor::Model::DBIC::Schema::Replicated connect info
The docs show: __PACKAGE__-config({ traits = ['Replicated'] connect_info = ['dbi:mysql:master', 'user', 'pass'], replicants = [ ['dbi:mysql:slave1', 'user', 'pass'], ['dbi:mysql:slave2', 'user', 'pass'], ['dbi:mysql:slave3', 'user', 'pass'], ], balancer_args = { master_read_weight = 0.3 } }); Shouldn't that be regular connect_info? my %config = ( traits = ['Replicated'], connect_info = { dsn = 'dbi:mysql:master', user = 'username', pass = 'password', }, replicants = [ { dsn = 'dbi:mysql:slave1', user = 'username', pass = 'password', }, { dsn = 'dbi:mysql:slave1', user = 'username', pass = 'password', }, ], balancer_args = { master_read_weight = 0.3 } ); -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
[Catalyst] Re: Catalyst::TraitFor::Model::DBIC::Schema::Replicated connect info
It would seem there's a coercion for the synopsis syntax. So, I'm not clear if I'm using it incorrectly or if there's a problem. So, if I take the SYNOPSIS example: my %data = ( traits = ['Replicated'], connect_info = ['dbi:mysql:master', 'user', 'pass'], replicants = [ ['dbi:mysql:slave1', 'user', 'pass'], ['dbi:mysql:slave2', 'user', 'pass'], ['dbi:mysql:slave3', 'user', 'pass'], ], balancer_args = { master_read_weight = 0.3 } ); and convert to YAML: balancer_args: master_read_weight: 0.3 connect_info: - dbi:mysql:master - user - pass replicants: - - dbi:mysql:slave1 - user - pass - - dbi:mysql:slave2 - user - pass - - dbi:mysql:slave3 - user - pass traits: - Replicated Then try with my actual YAML: balancer_args: master_read_weight: 0.3 connect_info: - dbi:Pg:dbname=test - - replicants: - - dbi:Pg:dbname=slave - - traits: - Replicated Use of uninitialized value $driver in concatenation (.) or string at /usr/local/share/perl/5.10.0/DBIx/Class/Storage/DBI.pm line 935. DBIx::Class::Storage::throw_exception(): Can't locate DBIx/Class/Storage/DBI/.pm in @INC The hash-base connect_info works fine. -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Re: Catalyst::TraitFor::Model::DBIC::Schema::Replicated connect info
On Mon, Jun 7, 2010 at 12:58 PM, Rafael Kitover rkito...@cpan.org wrote: The ::DBI::Replicated storage, to my knowledge, has only been tested on MySQL. If you are using it successfully with Postgres I would love to hear the details. Which replication software you are using, and does it work as you expect. I've just started looking into using Replicated. Slony is used for replication and there's discussion of using pgbouncer for slave connection pooling. An existing application that uses the same database has a DBI subclass that works at the $dbh level to provide replication, so looking at using that also. Memcached is track when to force reads to the master after a write. This is keyed by user id -- i.e. once a user does a write then they are forced to the master for an amount of time to let the slaves catch up. What I'm now wondering about is where I could hook in to determine when a write to the master happens so I can make all subsequent queries also go to the master and to set a flag in memcached for other processes to detect. But, this is a discussion that should be on the DBIC list. -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
[Catalyst] Wrong Content-Length value: 392918
I see these errors a few times a day. I wonder why this is happening -- could the browser really send the wrong content length? I seem to see it often in ajax calls for a progress bar, but also during file uploads and sometimes for just a normal post. Is there any additional info that could be included in the exception message that would help explain this? Perhaps the length of data actual read in addition to the content-length -- and maybe even the last few bytes read and the content-type? Could a failed or closed connection be causing this (and reported in the message)? # paranoia against wrong Content-Length header my $remaining = $length - $self-read_position; if ( $remaining 0 ) { $self-finalize_read($c); Catalyst::Exception-throw( Wrong Content-Length value: $length ); } -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
[Catalyst] Module::Install::Catalyst very slow
When I run Makefile.PL the Module::Install::Catalyst step can take a number of minutes -- it just took five minutes on one machine just now. I assume that's because of the recursive copy. Does the build process require actual copies or could symlinks be used to speed up this process? -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
[Catalyst] Trapping exceptions in Catalyst.pm
In execute() there's this code: eval { $c-state( $code-execute( $class, $c, @{ $c-req-args } ) || 0 ) }; $c-_stats_finish_execute( $stats_info ) if $c-use_stats and $stats_info; my $last = pop( @{ $c-stack } ); if ( my $error = $@ ) { The problem is that it's possible for the eval to fail but $@ is not set. An example is where Locale::Maketext localizes $@ so that exceptions come back with $@ undefined (for some odd reason). In general, it's better to test the return value from eval directly instead of depend on $...@. Something like: my $has_exception; eval { $c-state( $code-execute( $class, $c, @{ $c-req-args } ) || 0 ); 1; } || $has_exception++; ... if ( $has_exception ) { Or use the eval {; 1 } || do { my $msg = $@; ...}; style. -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Speeding up recovery from 503 errors + backend
On Mon, Aug 2, 2010 at 12:58 AM, Paul Makepeace pa...@paulm.com wrote: From time to time I forget to restart the Catalyst backend and Apache reports the usual 503 Service Temporarily Unavailable error. Annoyingly, even when the backend is restarted Apache seems to negatively cache that backend gone away result and keep serving 503s. Is there a way to have it re-check every time, or some other solution that doesn't require an Apache restart? See the retry setting: http://httpd.apache.org/docs/2.2/mod/mod_proxy.html#proxypass We have the same issue when using mod_rewrite to proxy with [P]. You might want to look at using some other type of front end proxy, too, perhaps Perlbal. -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] process a restored request
On Wed, Aug 4, 2010 at 11:22 AM, Steve st...@matsch.com wrote: Original post: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/msg01222.html My apologies for rehashing this old post, but this is such a *nice* thing to do for users that I'm sort of surprised the solution hasn't been implemented as a plugin or something, at least so far as I can tell... I'm trying to implement this elegant solution, but am getting stuck with the 'just dump any POST data back out into hidden fields in the login form, don't change the URL, and have the login form processed in a forward() from auto or similar rather than doing a detach' part. I think the suggestion was in auto always check if authenticated. If not authenticated, then attempt to authenticate with existing form data (e.g. if a username and password have been posted). if that succeeds then just continue on to the requested action. If cannot authenticate then display a login form but also include all other parameters that were posted in hidden fields. Set the action to post back to the original action. Repeat. You probably want to track the original request method (GET POST PUT DELETE) so that when the form is submitted (and finally authenticated) your action sees the original request method. If there's upload data then you would need to handle that additionally. My questions are as follows: What hidden field or fields are in the login form? One for each posted parameter. Where in the code sample are the items stashed? (or are they stored elsewhere?) When rendering the form. You are using the client as a store. Where in the code sample do we pick up after successful authentication in order to (forward, detach, redirect - pick one or supply alt.)? You don't. if the original post was to /user (e.g. to create a new user) then the login form looks just like your normal login form, but the action is a POST to /user. -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] I18N with variables
On Fri, Aug 6, 2010 at 6:16 AM, Matthias Dietrich mdietr...@cpan.orgwrote: I'm using short identifiers for my I18N texts, like Home.Greeting which is then translated to Hi there for en_us or Hallöchen for de_de. When I added a small CMS to a customer's application all texts should also be translated. So I saved any text to I18N key CMS.NavigationPoint.PageKey.* within the right language file (actually I'm using C::P::I18N::DBI), * for Title or Content or similar. I've been arguing with work about how to key our text. So far we continue to use the English in the loc() tags in the templates, and then the I18N team uses a script to pull out this text which gets sent to translation services. The risk is text gets into the templates that for some reason does not get pulled out. The developers like the English in the templates as it makes them easy to read, and it means they don't really have to stop when entering new text. Just seems like in the long run this will be unmaintainable and error prone. (Well, not in the long run as it already is error prone.) I've been arguing for a system where we use some kind of ID for the keys. I'm not so sure the key format matters -- could be just a primary key in the db, for example. This could be a stage done by the designers so the design spec just indicates a message id. Then code development and translation can happen at the same time. Is anyone using a system like that? And more specifically, what application are you using to manage the translation database? We have started to write one, but it's a bit more than trivial as we need it to work with different translation services, track history/changes, multiple applications, etc. So, it would make more sense to use an existing tool. So, I'd like to hear about your translation workflow and any tools you are using. Thanks, -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Module::Install::Catalyst very slow
On Fri, Jul 30, 2010 at 8:13 AM, Curtis Jewell p...@csjewell.fastmail.uswrote: So the build process can't symlink without checking for support for it first. (Catalyst DOES run on Win32, after all, as well as the Unixen.) Of course. Here's an svn export of an app: $ find . | wc -l 35677 $ fgrep 'model name' /proc/cpuinfo | uniq -c 8 model name : Intel(R) Xeon(R) CPU E5335 @ 2.00GHz (not that the number of cores makes a difference here) $ time perl Makefile.PL ... real4m25.784s user0m4.670s sys 0m5.110s See any situations where symlink (as in attached diff) would not work? On Fri, 30 Jul 2010 07:46 -0700, Bill Moseley mose...@hank.org wrote: When I run Makefile.PL the Module::Install::Catalyst step can take a number of minutes -- it just took five minutes on one machine just now. I assume that's because of the recursive copy. Does the build process require actual copies or could symlinks be used to speed up this process? -- Curtis Jewell csjew...@cpan.org http://csjewell.dreamwidth.org/ p...@csjewell.fastmail.us http://csjewell.comyr.org/perl/ Your random numbers are not that random -- perl-5.10.1.tar.gz/util.c Strawberry Perl for Windows betas: http://strawberryperl.com/beta/ ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/ -- Bill Moseley mose...@hank.org Module-Install-Catalyst.diff Description: Binary data ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/
Re: [Catalyst] Module::Install::Catalyst very slow
Oh, that patch will break when used on an existing tree, so don't use. And I'm not clear how distclean will work with the symlinks. So, if destination is already a symlink is there anything to do? Assume it's already linked. And if it's a regular dir then do the rcopy? I'm using this just to speed up places where people are running the Makefile.PL script somewhat often. But, as a replacement for rcopy a bit more testing is needed to see what might break. Sorry for the noise. On Mon, Aug 16, 2010 at 5:03 PM, Bill Moseley mose...@hank.org wrote: On Fri, Jul 30, 2010 at 8:13 AM, Curtis Jewell p...@csjewell.fastmail.uswrote: So the build process can't symlink without checking for support for it first. (Catalyst DOES run on Win32, after all, as well as the Unixen.) Of course. Here's an svn export of an app: $ find . | wc -l 35677 $ fgrep 'model name' /proc/cpuinfo | uniq -c 8 model name : Intel(R) Xeon(R) CPU E5335 @ 2.00GHz (not that the number of cores makes a difference here) $ time perl Makefile.PL ... real4m25.784s user0m4.670s sys 0m5.110s See any situations where symlink (as in attached diff) would not work? On Fri, 30 Jul 2010 07:46 -0700, Bill Moseley mose...@hank.org wrote: When I run Makefile.PL the Module::Install::Catalyst step can take a number of minutes -- it just took five minutes on one machine just now. I assume that's because of the recursive copy. Does the build process require actual copies or could symlinks be used to speed up this process? -- Curtis Jewell csjew...@cpan.org http://csjewell.dreamwidth.org/ p...@csjewell.fastmail.us http://csjewell.comyr.org/perl/ Your random numbers are not that random -- perl-5.10.1.tar.gz/util.c Strawberry Perl for Windows betas: http://strawberryperl.com/beta/ ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/ -- Bill Moseley mose...@hank.org -- Bill Moseley mose...@hank.org ___ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/