sub
throw {
my
$class_or_obj
=
shift
;
die
( blessed
$class_or_obj
?
$class_or_obj
:
$class_or_obj
->new(
@_
) );
}
q{""}
=>
'as_string'
,
fallback
=> 1;
has
message
=> (
is
=>
'ro'
,
isa
=>
'Str'
,
required
=> 1,
);
has
status
=> (
is
=>
'ro'
,
isa
=>
'Int'
,
default
=>
sub
{ 400 },
);
has
bad_request_data
=> (
is
=>
'ro'
,
isa
=>
'Bool'
,
);
has
sql_error
=> (
is
=>
'ro'
,
isa
=>
'Bool'
,
);
has
internal
=> (
is
=>
'ro'
,
isa
=>
'Bool'
,
);
has
json_api_version
=> (
is
=>
'ro'
,
isa
=>
'Str'
,
default
=>
sub
{
'1.0'
},
writer
=>
'_set_json_api_version'
);
sub
as_string {
my
$self
=
shift
;
return
$self
->message;
}
sub
as_response {
my
$self
=
shift
;
my
$status
=
$self
->status;
my
$detail
=
$self
->message;
if
(
$self
->sql_error ) {
$detail
=
"SQL error: $detail"
;
}
elsif
(
$self
->bad_request_data ) {
$detail
=
"Bad request data: $detail"
;
}
else
{
$status
= 500;
warn
$detail
if
$detail
;
$detail
=
"A fatal error has occured, please check server logs"
;
}
return
$status
, [], +{
jsonapi
=> {
version
=>
$self
->json_api_version },
errors
=> [ {
detail
=>
$detail
,
status
=>
$status
} ],
};
}
sub
new_from_exception {
my
(
$class
,
$e
) =
@_
;
return
$e
if
blessed(
$e
) &&
$e
->isa(
$class
);
my
%args_for_new
=
$class
->_handle_exception_obj(
$e
);
unless
(
$args_for_new
{status} and
$args_for_new
{message} ) {
%args_for_new
= (
status
=> 500,
message
=>
''
,
);
warn
"$e"
;
}
return
$class
->new(
%args_for_new
);
}
sub
_handle_exception_obj {
my
(
$self
,
$e
) =
@_
;
return
unless
blessed(
$e
) or
$e
->isa(
'Moose::Exception'
);
if
(
$e
->isa(
'Moose::Exception::AttributeIsRequired'
) ) {
my
$attribute
=
$e
->attribute_name;
return
_bad_req(
"Parameter `$attribute` is required"
);
}
elsif
(
$e
->isa(
'Moose::Exception::ValidationFailedForTypeConstraint'
) or
$e
->isa(
'Moose::Exception::ValidationFailedForInlineTypeConstraint'
)
) {
my
$class
= find_meta(
$e
->class_name );
my
$attribute
=
$class
->get_attribute(
$e
->attribute_name );
my
$value_nice
= JSON::XS->new->allow_nonref->utf8->canonical->encode(
$e
->value );
if
( !
$attribute
) {
my
$attr
=
$e
->attribute_name;
return
_bad_req(
"Parameter `$attr` got an expected data type: $value_nice"
);
}
my
$attribute_name
=
$attribute
->name;
my
$type_name
= _moose_type_to_nice_description(
$attribute
->{isa} );
return
_bad_req(
"Parameter `$attribute_name` expected $type_name, but got a $value_nice"
);
}
return
;
}
sub
_bad_req {
return
(
message
=>
shift
,
status
=> 400,
bad_request_data
=> 1,
);
}
sub
_moose_type_to_nice_description {
my
(
$type_name
) =
@_
;
$type_name
=~ s/ArrayRef/Collection/g;
$type_name
=~ s/HashRef/Resource/g;
$type_name
=~ s/Maybe\[(.+)]/null or $1/g;
$type_name
=~ s/\|/ or /g;
return
$type_name
;
}
__PACKAGE__->meta->make_immutable;
no
Moose; 1;