Catalyst-Plugin-JSONRPC-Server
view release on metacpan or search on metacpan
t/plugin-hardening.t view on Meta::CPAN
use v5.36;
use Test::More;
use Test::Fatal;
use Catalyst::Plugin::JSONRPC::Server;
use Catalyst::Plugin::JSONRPC::Server::Dispatcher;
# --- minimal stub context (no Catalyst), with an optional ->config ----------
package StubResponse {
sub new { bless {}, shift }
sub status { my $s = shift; $s->{status} = shift if @_; $s->{status} }
sub content_type { my $s = shift; $s->{content_type} = shift if @_; $s->{content_type} }
sub body { my $s = shift; $s->{body} = shift if @_; $s->{body} }
}
package StubRequest {
sub new { my ( $class, $body ) = @_; bless { body => $body }, $class }
sub body { $_[0]{body} }
}
package StubContext {
our @ISA = ('Catalyst::Plugin::JSONRPC::Server');
sub new {
my ( $class, %args ) = @_;
bless {
response => StubResponse->new,
request => $args{request},
( exists $args{config} ? ( _config => $args{config} ) : () ),
}, $class;
}
sub response { $_[0]{response} }
sub request { $_[0]{request} }
# Only present when a config was supplied, so we also exercise the
# can('config') guard in the plugin when it is absent.
sub config { $_[0]{_config} }
}
# --------------------------------------------------------------------------
# --- I3: handlers registered on one context must NOT leak into another ------
# On the old per-app %DISPATCHER (keyed by app class) a fresh context would see
# a handler a previous context registered; the per-request dispatcher fixes it.
{
my $c1 = StubContext->new;
$c1->jsonrpc_register( secret => sub ($p) { 'leaked' } );
$c1->jsonrpc_dispatch('{"jsonrpc":"2.0","method":"secret","params":[],"id":1}');
my $c2 = StubContext->new; # a brand-new request
my $data = $c2->jsonrpc_dispatch('{"jsonrpc":"2.0","method":"secret","id":2}');
is( $data->{error}{code}, -32601,
'a handler registered on one context does not leak into another (I3)' );
}
# --- I4: the nothing-to-send status is configurable (202 for the MCP transport)
{
my $c = StubContext->new;
my $d = Catalyst::Plugin::JSONRPC::Server::Dispatcher->new;
$d->register( note => sub ($p) { 'x' } );
my $none = $c->jsonrpc_dispatch_with(
$d, '{"jsonrpc":"2.0","method":"note","params":[1]}', 202 );
is( $none, undef, 'notification still returns undef' );
is( $c->response->status, 202,
'empty-response status honours the caller-supplied 202 (I4)' );
}
# ...and the default is still 204 when not overridden.
{
my $c = StubContext->new;
( run in 0.928 second using v1.01-cache-2.11-cpan-54e63673c56 )