Skip to content

Commit

Permalink
Support route block plugins in before/after blocks
Browse files Browse the repository at this point in the history
This should unblock being able to use templates in before/after, as
requseted in croservices/cro-webapp#73.
  • Loading branch information
jnthn committed Jul 15, 2022
1 parent 024a926 commit c4fac86
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 3 deletions.
14 changes: 11 additions & 3 deletions lib/Cro/HTTP/Router.pm6
Original file line number Diff line number Diff line change
Expand Up @@ -1113,12 +1113,14 @@ module Cro::HTTP::Router {

my class BeforeMiddleTransform does Cro::HTTP::Middleware::Conditional {
has &.block;
has $.route-set;

method process(Supply $pipeline --> Supply) {
supply {
whenever $pipeline -> $request {
my $*CRO-ROUTER-REQUEST := $request;
my $*CRO-ROUTER-RESPONSE := Cro::HTTP::Response.new(:$request);
my $*CRO-MIDDLEWARE-ROUTE-SET = $!route-set;
&!block($request);
emit $*CRO-ROUTER-RESPONSE.status.defined
?? $*CRO-ROUTER-RESPONSE
Expand All @@ -1130,6 +1132,7 @@ module Cro::HTTP::Router {

my class AfterMiddleTransform does Cro::Transform {
has &.block;
has $.route-set;

method consumes() { Cro::HTTP::Response }
method produces() { Cro::HTTP::Response }
Expand All @@ -1138,6 +1141,7 @@ module Cro::HTTP::Router {
supply {
whenever $pipeline -> $response {
my $*CRO-ROUTER-RESPONSE := $response;
my $*CRO-MIDDLEWARE-ROUTE-SET = $!route-set;
&!block($response);
emit $response;
}
Expand All @@ -1160,7 +1164,7 @@ module Cro::HTTP::Router {
#| Run the specified block before any routing takes place. If it produces, a
#| response by itself, then no routing will be performed.
multi sub before(&middleware --> Nil) is export {
my $conditional = BeforeMiddleTransform.new(block => &middleware);
my $conditional = BeforeMiddleTransform.new(block => &middleware, route-set => $*CRO-ROUTE-SET);
$*CRO-ROUTE-SET.add-before($conditional.request);
$*CRO-ROUTE-SET.add-after($conditional.response);
}
Expand Down Expand Up @@ -1189,7 +1193,7 @@ module Cro::HTTP::Router {
#| regardless of any route being matched (so if no route matched, this
#| would get the 404 response to process).
multi sub after(&middleware --> Nil) is export {
my $transformer = AfterMiddleTransform.new(block => &middleware);
my $transformer = AfterMiddleTransform.new(block => &middleware, route-set => $*CRO-ROUTE-SET);
$*CRO-ROUTE-SET.add-after($transformer);
}

Expand Down Expand Up @@ -1364,11 +1368,15 @@ module Cro::HTTP::Router {
}

#| Get the configuration data added for the current route block as well as those
#| has been included into. This can only be called in a request handler.
#| has been included into. This can only be called in a request handler or a
#| before/after middleware block.
sub router-plugin-get-configs(Cro::HTTP::Router::PluginKey $key, Str :$error-sub = $key.id --> List) is export(:plugin) {
with $*CRO-ROUTER-ROUTE-HANDLER {
.get-plugin-configs($key)
}
orwith $*CRO-MIDDLEWARE-ROUTE-SET {
.get-plugin-configs($key)
}
else {
die X::Cro::HTTP::Router::OnlyInHandler.new(:what($error-sub));
}
Expand Down
62 changes: 62 additions & 0 deletions t/http-router-plugin.t
Original file line number Diff line number Diff line change
Expand Up @@ -106,4 +106,66 @@ subtest 'Access to configuration with include' => {
}
}

my $test-before = route {
add-message 'b';

before {
if request.query-value('q') eq any(all-messages()) {
not-found;
}
}

get -> 'ok' {
content 'text/plain', 'ok';
}
}

subtest 'Access to configuration in before block' => {
my $in = Supplier.new;
my Channel $out = $test-before.transformer($in.Supply).Channel;

$in.emit: Cro::HTTP::Request.new(http-version => '1.1', method => 'GET', target => '/ok?q=a');
given $out.receive {
isa-ok $_, Cro::HTTP::Response, 'Got a response';
is .status, 200, 'Got 200 when before middleware ran and did not produce response';
}

$in.emit: Cro::HTTP::Request.new(http-version => '1.1', method => 'GET', target => '/ok?q=b');
given $out.receive {
isa-ok $_, Cro::HTTP::Response, 'Got a response';
is .status, 404, 'Got 404 when before middleware ran and changed response';
}
}

my $test-after = route {
add-message 'x';

after {
if response.request.query-value('q') eq any(all-messages()) {
not-found;
}
}

get -> 'ok' {
content 'text/plain', 'ok';
}
}

subtest 'Access to configuration in after block' => {
my $in = Supplier.new;
my Channel $out = $test-after.transformer($in.Supply).Channel;

$in.emit: Cro::HTTP::Request.new(http-version => '1.1', method => 'GET', target => '/ok?q=y');
given $out.receive {
isa-ok $_, Cro::HTTP::Response, 'Got a response';
is .status, 200, 'Got 200 when after middleware ran and did not change response';
}

$in.emit: Cro::HTTP::Request.new(http-version => '1.1', method => 'GET', target => '/ok?q=x');
given $out.receive {
isa-ok $_, Cro::HTTP::Response, 'Got a response';
is .status, 404, 'Got 404 when after middleware ran and changed response';
}
}

done-testing;

0 comments on commit c4fac86

Please sign in to comment.