#! perl -I. -w
BEGIN {
$ENV
{DANCER_ENVIRONMENT} =
'test'
;
$ENV
{DANCER_APPDIR} =
'.'
;
}
use
Dancer
qw/:syntax !pass !warning/
;
my
$client
= MyTest::Client->new(
ping_value
=>
'pong'
);
my
$dispatch
= {
'MyTest::API'
=> MyTest::API->new(
test_client
=>
$client
),
};
my
$config
= {
config
=>
'config'
,
code_wrapper
=>
sub
{
my
(
$code
,
$package
,
$method
) =
splice
(
@_
, 0, 3);
my
$instance
=
$dispatch
->{
$package
};
$instance
->
$code
(
@_
);
},
};
set(
plugins
=> {
'RPC::JSONRPC'
=> {
'/jsonrpc'
=> {
'MyTest::API'
=> {
ping
=>
'rpc_ping'
},
},
},
'RPC::XMLRPC'
=> {
'/xmlrpc'
=> {
'MyTest::API'
=> {
ping
=>
'rpc_ping'
},
},
},
'RPC::RESTRPC'
=> {
'/restrpc'
=> {
'MyTest::API'
=> {
ping
=>
'rpc_ping'
},
},
},
}
);
for
my
$path
(
keys
%{ config->{plugins}{
'RPC::JSONRPC'
} }) {
jsonrpc
$path
=>
$config
;
}
for
my
$path
(
keys
%{ config->{plugins}{
'RPC::XMLRPC'
} }) {
xmlrpc
$path
=>
$config
;
}
for
my
$path
(
keys
%{ config->{plugins}{
'RPC::RESTRPC'
} }) {
restrpc
$path
=>
$config
;
}
note(
"Send request to the *working* app without catch-all"
);
{
my
$response
= dancer_response(
POST
=>
'/jsonrpc'
,
{
headers
=> [
content_type
=>
'application/json'
,
],
body
=> as_jsonrpc(
'ping'
),
}
);
response_contains_ok(
$response
,
200,
'application/json'
,
{
result
=>
'pong'
},
"ok(jsonrpc: ping)"
);
$response
= dancer_response(
POST
=>
'/xmlrpc'
,
{
headers
=> [
content_type
=>
'text/xml'
,
],
body
=> as_xmlrpc(
'ping'
),
}
);
response_contains_ok(
$response
,
200,
'text/xml'
,
{
result
=>
'pong'
},
"ok(xmlrpc: ping)"
);
$response
= dancer_response(
POST
=>
'/restrpc/ping'
,
{
headers
=> [
content_type
=>
'application/json'
,
],
}
);
response_contains_ok(
$response
,
200,
'application/json'
,
{
result
=>
'pong'
},
"ok(restrpc: ping)"
);
}
note(
"Send *rubbish* to the working app **without** catch-all"
);
{
my
$response
= dancer_response(
POST
=>
'/jsonrpc'
,
{
headers
=> [
content_type
=>
'application/rubbish'
,
],
body
=> as_jsonrpc(
'ping'
),
}
);
is(
$response
->status, 404,
"URI not found for content-type(jsonrpc)"
);
is(
$response
->content_type,
'text/html'
,
"Content-Type set to html"
);
$response
= dancer_response(
POST
=>
'/xmlrpc'
,
{
headers
=> [
content_type
=>
'application/rubbish'
,
],
body
=> as_xmlrpc(
'ping'
),
}
);
response_contains_ok(
$response
, 404,
'text/html'
,
qr/Unable to process your query/
);
$response
= dancer_response(
POST
=>
'/restrpc/ping'
,
{
headers
=> [
content_type
=>
'application/rubbish'
,
],
}
);
response_contains_ok(
$response
, 404,
'text/html'
,
qr/Unable to process your query/
);
}
ok(setup_default_route(),
"setting the catchall route"
);
note(
"Send *rubbish* to the working app **with** catch-all"
);
{
my
$response
= dancer_response(
POST
=>
'/jsonrpc'
,
{
headers
=> [
content_type
=>
'application/rubbish'
,
],
body
=> as_jsonrpc(
'ping'
),
}
);
response_contains_ok(
$response
,
404,
'text/plain'
,
"Error! '/jsonrpc' was not found for 'application/rubbish'"
,
);
$response
= dancer_response(
POST
=>
'/rubbish'
,
{
headers
=> [
content_type
=>
'application/json'
,
accept
=>
'application/json'
,
],
body
=> as_jsonrpc(
'ping'
),
}
);
response_contains_ok(
$response
,
200,
'application/json'
,
{
code
=> -32601,
message
=>
"Method 'ping' not found"
,
}
);
$response
= dancer_response(
POST
=>
'/rubbish'
,
{
headers
=> [
content_type
=>
'text/xml'
,
],
body
=> as_xmlrpc(
'ping'
),
}
);
response_contains_ok(
$response
,
200,
'text/xml'
,
{
faultCode
=> -32601,
faultString
=>
"Method 'ping' not found"
,
}
);
$response
= dancer_response(
POST
=>
'/rubbish/ping'
,
{
headers
=> [
content_type
=>
'application/json'
,
accept
=>
'application/json'
,
],
body
=>
''
,
}
);
response_contains_ok(
$response
,
200,
'application/json'
,
{
error
=> {
code
=> -32601,
message
=>
"Method 'ping' not found"
,
}
}
);
}
done_testing();
sub
as_jsonrpc {
my
(
$method
,
$params
) =
@_
;
return
to_json(
{
jsonrpc
=>
'2.0'
,
id
=>
"ID-$0-$$"
,
method
=>
$method
,
(
defined
(
$params
) ? (
params
=>
$params
) : ())
}
);
}
sub
as_xmlrpc {
my
(
$method
,
$params
) =
@_
;
return
RPC::XML::request->new(
$method
=>
$params
)->as_string();
}
sub
response_contains_ok {
my
(
$response
,
$status
,
$content_type
,
$content
,
$message
) =
@_
;
$message
||=
'response_contains_ok'
;
my
$parser
= RPC::XML::ParserFactory->new();
my
$ok
= 1;
$ok
&&= is(
$response
->status,
$status
,
"$message: status ($status)"
);
$ok
&&= is(
$response
->content_type,
$content_type
,
"$message: content-type ($content_type)"
);
my
$data
;
if
(
$response
->content_type =~ m{(application|text)/xml}) {
$data
=
$parser
->parse(
$response
->content)->value->value;
$ok
&&= is_deeply(
$data
,
$content
,
"$message: content (xmlrpc)"
);
}
elsif
(
$response
->content_type eq
'application/json'
) {
$data
= from_json(
$response
->content, {
allow_nonref
=> 1});
if
(
defined
(
$data
) and
ref
(
$data
) eq
'HASH'
and
exists
(
$data
->{jsonrpc}) and
$data
->{jsonrpc} eq
'2.0'
)
{
if
(
exists
(
$data
->{error})) {
$ok
&&= is_deeply(
$data
->{error},
$content
,
"$message: content (jsonrpc-error)"
);
}
else
{
$ok
&&= is_deeply(
$data
->{result},
$content
,
"$message: content (jsonrpc-result)"
);
}
}
}
else
{
$data
=
$response
->content;
if
(
ref
(
$content
) eq
'Regexp'
) {
$ok
&&= like(
$data
,
$content
,
"$message: content ($content)"
);
}
else
{
$ok
&&= is_deeply(
$data
,
$content
,
"$message: content (plain)"
);
}
}
diag(
"$message: diag "
, explain(
$data
))
if
not
$ok
;
return
$ok
;
}