Amon2
view release on metacpan or search on metacpan
lib/Amon2/Plugin/Web/JSON.pm view on Meta::CPAN
package Amon2::Plugin::Web::JSON;
use strict;
use warnings;
use JSON 2 qw/encode_json/;
use Amon2::Util ();
my $_JSON = JSON->new()->ascii(1);
my %_ESCAPE = (
'+' => '\\u002b', # do not eval as UTF-7
'<' => '\\u003c', # do not eval as HTML
'>' => '\\u003e', # ditto.
);
sub init {
my ($class, $c, $conf) = @_;
unless ($c->can('render_json')) {
Amon2::Util::add_method($c, 'render_json', sub {
my ($c, $stuff) = @_;
# for IE7 JSON venularity.
# see http://www.atmarkit.co.jp/fcoding/articles/webapp/05/webapp05a.html
my $output = $_JSON->canonical( $conf->{canonical} ? 1 : 0 )->encode($stuff);
$output =~ s!([+<>])!$_ESCAPE{$1}!g;
my $user_agent = $c->req->user_agent || '';
# defense from JSON hijacking
if ((!$c->request->header('X-Requested-With')) && $user_agent =~ /android/i && defined $c->req->header('Cookie') && ($c->req->method||'GET') eq 'GET') {
my $res = $c->create_response(403);
$res->content_type('text/html; charset=utf-8');
$res->content("Your request may be JSON hijacking.\nIf you are not an attacker, please add 'X-Requested-With' header to each request.");
$res->content_length(length $res->content);
return $res;
}
my $res = $c->create_response(200);
my $encoding = $c->encoding();
$encoding = lc($encoding->mime_name) if ref $encoding;
$res->content_type("application/json; charset=$encoding");
$res->header( 'X-Content-Type-Options' => 'nosniff' ); # defense from XSS
$res->content_length(length($output));
$res->body($output);
if (defined (my $status_code_field = $conf->{status_code_field})) {
$res->header( 'X-API-Status' => $stuff->{$status_code_field} ) if exists $stuff->{$status_code_field};
}
return $res;
});
}
}
1;
__END__
=encoding utf-8
=head1 NAME
Amon2::Plugin::Web::JSON - JSON plugin
=head1 SYNOPSIS
use Amon2::Lite;
__PACKAGE__->load_plugins(qw/Web::JSON/);
get '/' => sub {
my $c = shift;
return $c->render_json(+{foo => 'bar'});
};
__PACKAGE__->to_app();
=head1 DESCRIPTION
This is a JSON plugin.
=head1 METHODS
=over 4
=item C<< $c->render_json(\%dat); >>
Generate JSON data from C<< \%dat >> and returns instance of L<Plack::Response>.
=back
=head1 PARAMETERS
=over 4
=item status_code_field
It specify the field name of JSON to be embedded in the 'X-API-Status' header.
Default is C<< undef >>. If you set the C<< undef >> to disable this 'X-API-Status' header.
__PACKAGE__->load_plugins(
'Web::JSON' => { status_code_field => 'status' }
( run in 1.675 second using v1.01-cache-2.11-cpan-df04353d9ac )