GithubHelp home page GithubHelp logo

catalyst-runtime's People

Contributors

abraxxa avatar andygrundman avatar arodland avatar autarch avatar bobtfish avatar bricas avatar chansen avatar dhoss avatar dr-kd avatar ferz avatar fordmason avatar gbjk avatar groditi avatar haarg avatar hkclark avatar ilmari avatar jessesheidlower avatar jhannah avatar jjn1056 avatar jrockway avatar karenetheridge avatar kraih avatar marcusramberg avatar mvgrimes avatar nothingmuch avatar rafl avatar rkitover avatar shadowcat-mst avatar vanstyn avatar wreis avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

catalyst-runtime's Issues

Error Callbacks

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.

  1. global end action gets very complex for any application of size. Often becomes a mess, a sort of "gods action."

  2. 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...)

What would it take to make it so that sessions using that standard Catalyst Plugins for sessions and authentication is shared over $psgi_env

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

Default charset disappeared in MetaCPAN (cpan-api) after upgrade from 5.90053 to 5.90103

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!

Asset Management?

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).

  • Mike

new setup step, "setup_config"

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

  1. stop $component->config since this is a common bad practice
  2. ? allow one to set class accessors on application level config.

As a followup we'd need to refactor the common config loader to be a role that uses this

Stop using is_utf8

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.

$c->res->redirect can't take a URI object

Tired of writing

$c->res->location("${$c->uri_for($self->action_for('show_listings'), $listing->id)}");

and always forgetting that :) Lets let $res->location take a URI object, since that is a common case for $c->uri_for.

Fix error message when missing a plack middleware

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.

Move the stash back to core, or a core plugin

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.

The behavior of query_keywords and query_parameters seems orthogonal, but in actuality it is not.

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.

better defaults for chained actions when there is no args/captureargs

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?

The term "checkout" is never defined

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

Can we find a way to infer Args(0) CaptureArgs(0) for Chained

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'

should register_actions be distinct from register components

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

Allow more throwable object types

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

add action :Scheme(https,...)

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

immutable $c->req (Catalyst::Request)

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.

fix ->last error

@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

PSGI ENV keys for Application and Context

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.

data_handlers are not invoked when the HTTP Method is not all uppcrcase

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:

  • in general, only uppercase methods should be supported as only those are in the RFC
  • since lowercase is supported in general, for data_handlers it should also be supported because of backwards compatibility

However, the way it is now it is inconsistent, so something should be done about it.

What to do when trying to lookup a $component that does ACCEPT_CONTEXT in $app scope

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.

Fix the problem where Path() ends up being nothing

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

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.