perl-catalyst / catalyst-runtime Goto Github PK
View Code? Open in Web Editor NEWThe Elegant MVC Web Application Framework
The Elegant MVC Web Application Framework
possible return::multilevel would be a better approach and would like us not overload what an exception means for catalyst.
What is Catalyst view on static asset management? This is something I always struggled with what to do with a Catalyst app. I do a typical make / make test/ make install for the app and my assets actually get installed in the PERL5LIB directory, which was I was a bit weirded out by at first but now I like that all my assets for my app get packaged up too and it's one cohesive unit. I've heard others just copy the app directory around instead of doing a real "install"
Is this why asset management isn't supported at all? There are packages such as File::Assets and Controller::Combine but assets should be munged at build time. It seems it would be nice if catalyst has some built-in something that would at least concat / uglify / fingerprint js and css. File::Assets gets close but it happens at runtime (and looks like might be abandoned).
I was thinking perhaps Module::Install::Catalyst should be enhanced to support the features of File::Assets plus concat as a good first start but I saw Ether was trying to nudge away from Module::Install so maybe something for whatever the new thing is (i can't remember what it was).
Seems might be good for people that don't also run a nodejs environment and have all the task-runners that handle a lot of this stuff (which is what my plan is).
We should make some changes to the stash middleware so that its more like (https://github.com/jjn1056/Plack-Middleware-Return-MultiLevel)
setup_actions runs after setup_components, which means that controllers are setup before the actions that are inside them. This makes it hard to do some things with controllers at setup_components, since they are in some way not truly completely setup.
The proposal is to change this so that controller setup_action on their actions using the setup_components phase
If you have a controller like this
sub path1 :Path { ... }
sub path2 :Path() { ... }
sub path3 :Path('') { ... }
path1 and path3 get mounted as path actions but path2 is ignored. path2 should be the same as 1/3
or something like it (possible to combine with some enhanced ability for components to declare dependencies as to improve dependeny injection)
Tired of writing
and always forgetting that :) Lets let $res->location take a URI object, since that is a common case for $c->uri_for.
Currently this method expects a valid PSGI response. Allow this method to also accept an $object that does ->as_psgi, such that in that case we call ->as_psgi with no arguments and expect that to provide the response.
I'd like a canonical spot where configuration
Lines 1282-1286 could be made into a method. In #catalyst, jnap suggested a method called "init_plugins"
19:05 @jnap I should add a 'init_plugin' or something so we ca avoid that
more later
the use case here is to allow for an argument to uri_for to be somehow altered by the called action such that we'd make it easier to do automatic naming of content addressable storage in static like controllers.
I'm gearing up for the QA Hackathon and I'm just trying to upgrade the API side of MetaCPAN to the latest Catalyst, but I've got some failing tests which show:
# Failed test 'Content-type'
# at t/server/controller/source.t line 79.
# got: 'text/plain'
# expected: 'text/plain; charset=UTF-8'
ok 8 - Change-log content
Build is at https://travis-ci.org/CPAN-API/cpan-api/jobs/113828722#L3061
I'm wondering what happened to the charset. @shadowcat-mst suggested I open an issue here to see if anyone could help.
Thanks very much!
Current catalyst adds exceptions to $c->error and generally trys to catch them in a global Root.end action. This is fine for simple applications but has two issues I have run into.
global end action gets very complex for any application of size. Often becomes a mess, a sort of "gods action."
The error is handled at a distance from where it was actually caused. There is no good way to 'restart or resume' from the point of error, and the actions that general the error have no good way to influence how the error is handled.
If would be nice if you could declare at the application level, and augment/modify at the context scope, classes of errors and handlers for them. For example if you hit a DBIC not found error, that could be setup to redirect to a not found or database error pages.
Would give you a way to approximate something like continuations, just not as good.
For chained actions you'd need to be able to pass a reference to th next action in the chain so you could recover from the error and proceed.
advantages would include the ability to declare upfront how to handle certain types of errors and actions can change or augment those. Would come closer to resembling lisp continuations, which I find to be the only sane exception system I've every used :)
Another nice benefit is we could build on the code we added to support HTTP Exceptions (this system would actually just be a generalization of that, and the custom code written for HTTP Exceptions would be removed and subsumed by this.
Here's an example, you have an action that takes an Arg and uses it to lookup a database row. However if the Arg causes an exception, instead of aborting the entire request and dumping a generic error page we replace the row with a new one, and continue processing. (I know that's a bit hand wavy...)
So when we cargo culled the encoding plugin, it looks like we brought in some stuff that is not considered good practices. THere's some usage of is_utf8 that supposed it totally wrong. I thin @karenetheridge seemed to understand it.
View
--template_for
--render, render_with
???
we should probably not encode unless the content type is one of the ones we think gets encoded
I've seen a lot of people adding cutting action matching for the more common http(s) scheme types. lets have something like this in core. it should support ws was as well.
also it would be ideal if we'd be able to call $c->url_for on this and it sets the schema correctly based on the called endpoint
for session there is a standard plack middleware, but not sure if the same exists for authentication (or if this even makes sense).
The gist here is that if Catalyst Six runs as a sub application under an existing Cat 5 application, we'd want to be able to share down at least sessions and possible authentication so we need I think somehow to expose those bits either as middleware or via some other technique. This is a research story to think about that and work out the approach and outline any tasks we should be prior to catalyst 6
The experiment to expose the stash via a PSGI middleware interface, although did not appear to cause lasting harm, has not lead us to conclude the idea that catalyst context could be reconceptualized as collection of middleware is not currently a good way to constructed a well designed applied. We should revert that commit.
basic matching on search query
We need advent articles, have a look at previous years for examples, http://www.catalystframework.org/calendar/
Code related to these methods is inside a scope that is doing nothing
AFAIK we never well defined what Myapp->component (->model, ->controller, ->view) should do. We sometimes just say 'avoid it'.
But there seems to be legitimate cases when one wants to introspect a catalyst app (like for generating offline docs).
I'd like to define how this should work and what the limitations are:
but basically there's only three options I can see. 1) die or warn and skip when calling $app->componet($with_ACCEPT_CTX), 2) automatically mock $app to $ctx and proceed or 3) return the result of ->COMPONENT and expect the user to be smart enough to do the right thing
8:44 AM or I guess we could say "You can never do $app->component...."
8:45 AM I think its useful enough for introspection reasons to not do that.
just a placeholder before I forget
see https://questhub.io/realm/perl/quest/53ac18ceb587a41557000119
for the bigger thinking here
Catalyst will pass thru an thrown exception if its an object that does ->code but this can pass too easily. She change this to expect the value in code to look that an http status, so we can tighten up the check
I'd like a canonical spot where configuration is expected to be setup and finished setup. After that you may not alter configuration. We should take the opportunity to
As a followup we'd need to refactor the common config loader to be a role that uses this
https://gist.github.com/jjn1056/a455d0cf857871c40ab8
Currently if an action midpoint lacks captureargs, it becomes an end point as in the above gist, where the Args is presumed ... so these midpoints become both midpoints AND endpoints
Any true endpoint without a Args declaration is presumed Args (...)
even odder, if an action in a chain does do Args(1) and then another action chains off it, it becomes a CaptureArgs(0) midpoint.
Maybe we like this?
Hi,
Currently when I try to load a Plack::Middleware that is not installed using:
PACKAGE->config(
'psgi_middleware' => [
'Session' => { store => 'File' },
],
);
I get the following error message:
Can't call method "can" on an undefined value at /Users/ynonperek/perl5/perlbrew/perls/perl-5.16.3/lib/site_perl/5.16.3/Catalyst.pm line 1172.
Compilation failed in require at /Users/ynonperek/perl5/perlbrew/perls/perl-5.16.3/lib/site_perl/5.16.3/Catalyst/ScriptRunner.pm line 50.
An error message telling the plack middleware is missing (and states the name of the missing middleware) is desired.
it would be nice if we could avoid needing the stash to set these.
other possible approaches (or coapproaches) would be action roles to set the :CurrentView(HTML), etc. but not sure how that fits into an overall philsophy of attributes.
And need to check that combine arg and capture syntax
Been using Catalyst for quite some time, and have found it to be a really great framework. Unfortunately, I came across something the other day that seemed a little confusing. I feel a code change, or documentation change may be appropriate.
I am using version 5.90092, but I believe the behavior is the same on the latest.
A data dump of the following:
my( $res, $c) = ctx_request(GET '/test_psgi_keys?x&a=1&b=2');
produces:
$c->req->query_parameters = { x => undef, a = 1, b = 2 }
$c->req->query_keywords = undef
A data dump of the following:
my( $res, $c) = ctx_request(GET '/test_psgi_keys?x');
produces:
$c->req->query_parameters = {}
$c->req->query_keywords = "x"
I feel like in the second case that the query_parameter member should instead be:
$c->req->query_parameters = { x => undef }
The query_keywords documentation states:
"Contains the keywords portion of a query string, when no '=' signs are present."
The query_parameters documentation states:
"Returns a reference to a hash containing query string (GET) parameters. Values can be either a scalar or an arrayref containing scalars."
The query_keywords member appears to have been created to support the isindex element, which is going through various states of deprecation. I understand there are a lot of finer points to this discussion, but I felt it pertinent to open this up for discussion.
A "checkout" is never defined, neither in theory nor in practice, but it controls vital behavior in @inc setting which, incidentally, broke my dayjob app. Lovely
Allow one to get at a containing Catalyst application and context from the PSGI env, so that when you are using catalyst to delegate to other web frameworks, that child application can access stuff like the parent's models.
It seems to me life would be better if $c->req
could not be altered. It's very tempting for Catalyst newbs (myself included, years ago) to alter the http request (filling it with lies), and then regret it later when MyApp grows. Better to stop people from shooting themselves in their future feet. Thanks.
???
One thing about chained actions that seems to make things hard for people is that it is a bit on the verbose side. One thought is to do a better job inferring a value for Args / Captures in the case when that attribute is not defined. The suggestion:
When an action is not the last action in the chain, omitting CaptureArgs is the same as saying CaptureArgs(0).
When the action is the last in the Chain, we infer 'Args' as the final value. I think this is correct since for Path and Local actions we infer Args in the dispatcher so its consistent.
Question
Would we prefer to infer Args(0) over Args for the final? Looking over my code that seems to be more common, although it might just be a side effect of the fact I need to put Args there to signify 'end of chain'
@jnap> has_error, $c->last_error ->shift_errors
11:33 AM @jnap last_error is the one I use the most
11:34 AM yeah I saw those helpers
11:34 AM so the last one is actully the same as shift?
11:34 AM @jnap shift shifts it off the arrow
11:34 AM @jnap array
11:35 AM @jnap hmmm so does last_error, I think that is not correct.
11:35 AM :D
11:36 AM @jnap I'm going to open a bug on that, last_error should not mutate
11:36 AM sounds like last_error should pop
11:36 AM without actually removin
11:36 AM ($c->error)[-1]
11:36 AM @jnap right, I'll open a bug on it.
11:37 AM @jnap and mark it in change notes. For the most part since most of the time there is only one error anyway you probably never notice
although ->to_psgi_app is more descriptive, the common accepted case in Plack is ->to_app. Let's stop fighting a lost battle
Usually in a HTTP request the method should be all caps, like GET
or POST
. That's documented in the RFC. But Catalyst is nice to us and allows get
or post
for regular request. If this is a bug or a feature is not the issue of this ticket, but it is important to acknowledge it as behaviour that has been there for a while.
If there is a data_handlers
handler present and the Conent-Type matches, Catalyst uses that handler to lazily build body_data
in the request object. But it only does that if the HTTP Method is uppercase. If not, that thing is never called.
I came across this while writing a unit test. I didn't pay close attention and figured HTTP::Request would figure out on its own what I want. I was wrong.
Following is a test-script that will show how it is possible to use both GET
and get
as a HTTP method and receive the same response. It also has two calls that resemble a REST call with Content-Type and Accept headers of application/json
. Those are sent with PUT
and put
. The latter fails.
use strict;
use warnings;
use Test::More;
use Plack::Test;
use HTTP::Request;
package MyApp::Controller::Root {
use base 'Catalyst::Controller';
use Data::Dumper;
$Data::Dumper::Indent = 0;
sub test_put : Local : Args(0) : Method('PUT') : Consumes('application/json') {
my ( $self, $c ) = @_;
$c->res->body( Dumper( $c->req->body_data ) );
}
sub test_get : Local {
my ( $self, $c ) = @_;
$c->res->body('Hello World!');
}
};
package MyApp {
use Catalyst;
use JSON 'decode_json';
use Test::Simple;
__PACKAGE__->config(
data_handlers => {
# This data_handler is just here to explicitly illustrate that there is one.
# It is the example one from https://metacpan.org/pod/Catalyst#DATA-HANDLERS
# that is there by default.
'application/json' => sub {
ok 1, 'in data_handler'; # we have a plan!
local $/;
decode_json $_->getline;
},
},
);
MyApp->setup;
};
ok my $psgi = MyApp->psgi_app, 'build psgi app';
test_psgi $psgi, sub {
my $cb = shift;
# the first two subtests are to illustrate that for a regular
# request that does not go through the data_handlers the case
# (upper/lower) of the HTTP Method is irrelevant
subtest 'GET /root/test_get' => sub {
my $res = $cb->( HTTP::Request->new( GET => '/root/test_get' ) );
is $res->code, 200, 'OK';
is $res->decoded_content, 'Hello World!', 'says "Hello World!"';
};
subtest 'get /root/test_get' => sub {
my $res = $cb->( HTTP::Request->new( get => '/root/test_get' ) );
is $res->code, 200, 'OK';
is $res->decoded_content, 'Hello World!', 'says "Hello World!"';
};
# All is well if our HTTP Method is all-uppercase. The data_handler
# gets it and unjsons it.
subtest 'PUT /root/test_put' => sub {
plan tests => 3;
my $res = $cb->(
HTTP::Request->new(
PUT => '/root/test_put',
HTTP::Headers->new(
'Accept' => 'application/json',
'Content-Type' => 'application/json'
),
'{ "foo" : "bar" }',
)
);
is $res->code, 200, 'OK';
is $res->decoded_content, q($VAR1 = {'foo' => 'bar'};), '$VAR1 contains a hashref';
};
# But if the HTTP Method is lowercase it gets ignored.
subtest 'put json all lowercase' => sub {
plan tests => 3;
my $res = $cb->(
HTTP::Request->new(
put => '/root/test_put',
HTTP::Headers->new(
'Accept' => 'application/json',
'Content-Type' => 'application/json'
),
'{"foo" : "bar" }',
)
);
is $res->code, 200, 'OK';
is $res->decoded_content, q($VAR1 = {'foo' => 'bar'};), '$VAR1 contains a hashref';
};
};
done_testing;
This can simply be run with prove
or perl
. Here's my output.
$ perl catalyst_test_lowercase_http_handler.pl
ok 1 - build psgi app
# Subtest: GET /root/test_get
ok 1 - OK
ok 2 - says "Hello World!"
1..2
ok 2 - GET /root/test_get
# Subtest: get /root/test_get
ok 1 - OK
ok 2 - says "Hello World!"
1..2
ok 3 - get /root/test_get
# Subtest: PUT /root/test_put
1..3
ok 1 - in data_handler
ok 2 - OK
ok 3 - $VAR1 contains a hashref
ok 4 - PUT /root/test_put
# Subtest: put json all lowercase
1..3
ok 1 - OK
not ok 2 - $VAR1 contains a hashref
# Failed test '$VAR1 contains a hashref'
# at catalyst_test_lowercase_http_handler.pl line 101.
# got: '$VAR1 = undef;'
# expected: '$VAR1 = {'foo' => 'bar'};'
# Looks like you planned 3 tests but ran 2.
# Looks like you failed 1 test of 2 run.
not ok 5 - put json all lowercase
# Failed test 'put json all lowercase'
# at catalyst_test_lowercase_http_handler.pl line 102.
1..5
# Looks like you failed 1 test of 5.
At the beginning of this ticket we have noted that Catalyst allows lowercase HTTP methods in general. According to the RFC, the method should be upper case. As there is a response to the put
call where the body is $VAR1 = undef;
shows that it lets the wrong call through, but the data_handlers
behaviour breaks.
So there is clearly something wrong here. I am not sure which part exactly is the wrong behaviour. We could argue either of these two cases:
data_handlers
it should also be supported because of backwards compatibilityHowever, the way it is now it is inconsistent, so something should be done about it.
we need to allow this for people with read file instead of get line
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.