I'm writing a middleware that consumes request.body and does some validation like so:
before-matched {
request-body -> (:$email, :$captcha-token, :$captcha-solution, *%_) {
# Validate the email.
unless Email::Valid.mx($email).so {
response.status = 400;
content 'application/json', %(message => 'Invalid Email');
}
# Validate captcha.
unless $captcha.validate($captcha-token, $captcha-solution) {
response.status = 401;
content 'application/json', %(message => 'Invalid Captcha');
}
}
}
post -> 'api', 'subscribe' {
put "outside";
request-body -> (:$name, :$email, *%_) {
put "inside";
dd $name, $email;
content 'application/json', %(message => $name);
}
}
I tried consuming request.body multiple times and the connection hangs. "inside" is never printed (from the example above).
Here is a reproducible example:
use Cro::HTTP::Server;
use Cro::HTTP::Router;
sub MAIN() {
my Cro::Service $http = Cro::HTTP::Server.new(
http => <1.1>,
host => "127.0.0.1",
port => 10000,
application => routes()
);
$http.start;
put "Listening at http://127.0.0.1:10000";
react {
whenever signal(SIGINT) {
say "Shutting down...";
$http.stop;
done;
}
}
}
sub routes() {
route {
before-matched {
request-body-text -> $body {
put "in before-matched: `{$body}'";
}
}
post -> {
put "in post route before request-body-text";
dd request.body-text;
request-body-text -> $body {
put "in post route: `{$body}'";
}
}
}
}
When making a request to this server with curl -v 'http://127.0.0.1:10000' --data-raw 'some-text'
it hangs after printing these lines:
andinus@cadmium /tmp> raku cro-question-mre.raku
Listening at http://127.0.0.1:10000
in before-matched: `some-text'
in post route before request-body-text
Promise.new(scheduler => ThreadPoolScheduler.new(uncaught_handler => Callable), status => PromiseStatus::Planned)
request.body-text
does return a promise, I'm not sure I understand what is happening after that. I tried using this but consuming request.body
once has the same behavior. Am I doing this wrong?