Skip to content

Commit

Permalink
Enable adapt_psgi for custom controllers
Browse files Browse the repository at this point in the history
Don't assume first argument is a descendant of Kelp
  • Loading branch information
bbrtj committed Jul 6, 2024
1 parent 9651886 commit ceecc66
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 13 deletions.
2 changes: 2 additions & 0 deletions Changes
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
Revision history for Kelp

{{$NEXT}}
[Changes]
- Fixed psgi routes not working with custom controllers

2.16 - 2024-07-05
[New Interface]
Expand Down
28 changes: 23 additions & 5 deletions lib/Kelp/Manual/Controllers.pod
Original file line number Diff line number Diff line change
Expand Up @@ -138,20 +138,38 @@ to enable C<persistent_controllers> regardless of configuration.
sub build_controller {
my ($self, $class) = @_;

return $class->new(app => $self->app);
return $class->new(context => $self);
}

=head3 Step 2: Custom base controller

A base controller class has to implement at least C<before_dispatch> and
C<before_finalize> to be compatible with Kelp.
A base controller class has to implement at least C<context>,
C<before_dispatch> and C<before_finalize> to be compatible with core Kelp. Some
specific modules might assume it's a descendant of Kelp, which may require
adding more methods to achieve compatibility. It may be also a good idea to
implement C<req> and C<res> for easier access.

# lib/MyController.pm
package MyController;

use Kelp::Base;

attr -app => undef;
attr -context => undef;

sub app {
my $self = shift;
return $self->context->app;
}

sub req {
my $self = shift;
return $self->context->req;
}

sub res {
my $self = shift;
return $self->context->res;
}

sub before_dispatch {
my $self = shift;
Expand All @@ -165,7 +183,7 @@ C<before_finalize> to be compatible with Kelp.

sub some_route {
my $self = shift;
$self->app->res->text->render('hello from controller');
$self->res->text->render('hello from controller');
}

=head3 Step 3: setting the custom context in the app
Expand Down
8 changes: 4 additions & 4 deletions lib/Kelp/Util.pm
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,9 @@ sub adapt_psgi
unless ref $app eq 'CODE';

return sub {
my $kelp = shift;
my $path = charset_encode($kelp->request_charset, pop() // '');
my $env = $kelp->req->env;
my $context = shift->context;
my $path = charset_encode($context->app->request_charset, pop() // '');
my $env = $context->req->env;

# remember script and path
my $orig_script = $env->{SCRIPT_NAME};
Expand All @@ -154,7 +154,7 @@ sub adapt_psgi
if (ref $result eq 'ARRAY') {
my ($status, $headers, $body) = @{$result};

my $res = $kelp->res;
my $res = $context->res;
$res->status($status) if $status;
$res->headers($headers) if $headers;
$res->body($body) if $body;
Expand Down
2 changes: 1 addition & 1 deletion t/lib/CustomContext/Context.pm
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ sub build_controller
my ($self, $controller_class) = @_;

$controller_class->new(
app => $self->app,
context => $self,
);
}

Expand Down
23 changes: 21 additions & 2 deletions t/lib/CustomContext/Controller.pm
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,22 @@ package CustomContext::Controller;
use Kelp::Base;
use Carp;

attr -app => sub { croak 'app is required' };
attr -context => sub { croak 'context is required' };

sub app
{
return $_[0]->context->app;
}

sub req
{
return $_[0]->context->req;
}

sub res
{
return $_[0]->context->res;
}

sub before_dispatch
{
Expand All @@ -14,7 +29,7 @@ sub before_dispatch
sub before_finalize
{
my $self = shift;
$self->app->res->header('X-Final' => __PACKAGE__);
$self->res->header('X-Final' => __PACKAGE__);
}

sub build
Expand All @@ -29,6 +44,10 @@ sub build
}
);
$app->add_route('/a/b/c' => 'foo#test');
$app->add_route('/a/b/e' => {
to => 'foo#nested_psgi',
psgi => 1,
});
}

sub bridge
Expand Down
15 changes: 14 additions & 1 deletion t/lib/CustomContext/Controller/Foo.pm
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,22 @@ sub test
{
my ($self) = @_;

$self->app->res->text;
$self->res->text;
return ref $self;
}

sub nested_psgi
{
my ($self) = @_;

return [
200,
['Content-Type' => 'text/plain'],
[
'PSGI OK'
],
];
}

1;

5 changes: 5 additions & 0 deletions t/routes_custom_controller.t
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,10 @@ $t->request_ok(GET '/a/b/d')
->header_is('X-Final', 'MyApp3')
->content_is('MyApp3');

$t->request_ok(GET '/a/b/e')
->content_type_is('text/plain')
->header_is('X-Final', 'CustomContext::Controller')
->content_is('PSGI OK');

done_testing;

0 comments on commit ceecc66

Please sign in to comment.