File Coverage

blib/lib/Test/JsonAPI/Autodoc/Request.pm
Criterion Covered Total %
statement 81 82 98.7
branch 27 28 96.4
condition 6 8 75.0
subroutine 10 10 100.0
pod 0 2 0.0
total 124 130 95.3


line stmt bran cond sub pod time code
1             package Test::JsonAPI::Autodoc::Request;
2 14     14   54 use strict;
  14         19  
  14         408  
3 14     14   53 use warnings;
  14         16  
  14         320  
4 14     14   53 use utf8;
  14         15  
  14         57  
5 14     14   231 use Carp;
  14         16  
  14         739  
6 14     14   8389 use JSON;
  14         118671  
  14         61  
7 14     14   7597 use URL::Encode qw/url_params_flat/;
  14         43980  
  14         10413  
8              
9             sub new {
10 15     15 0 32 my ($class) = @_;
11              
12 15         74 bless {
13             }, $class;
14             }
15              
16             sub parse {
17 15     15 0 34 my ($self, $req, $param_description) = @_;
18              
19 15 50       122 unless ($req->isa('HTTP::Request')) {
20 0         0 croak 'Request must be instance of HTTP::Request or subclass of that';
21             }
22              
23 15         54 my $body = $req->content;
24 15         226 my $content_type = $req->content_type;
25              
26 15         461 my $is_json = 0;
27 15 100       79 if ($content_type =~ m!^application/json!) {
28 12         66 $body = to_json(from_json($req->decoded_content), { pretty => 1 });
29 12         2173 $is_json = 1;
30             }
31              
32 15         32 my $target_server = '';
33 15 100 66     48 if ($req->uri->scheme && $req->uri->authority) {
34 9         667 $target_server = $req->uri->scheme . '://' . $req->uri->authority;
35             }
36              
37             return {
38 15         456 content_type => $content_type,
39             method => $req->method,
40             parameters => $self->_parse_request_parameters($body, $is_json, $param_description),
41             path => $req->uri->path,
42             query => $req->uri->query,
43             server => $target_server,
44             }
45             }
46              
47             sub _parse_request_parameters {
48 15     15   185 my ($self, $request_parameters, $is_json, $param_description) = @_;
49              
50 15         27 my $parameters;
51 15 100       59 if ($is_json) {
52 12         112 $request_parameters = JSON::decode_json($request_parameters);
53 12         49 $parameters = $self->_parse_json_hash($request_parameters, 0, $param_description);
54             }
55             else {
56 3         5 my @parameters = @{url_params_flat($request_parameters)};
  3         20  
57 3         183 my @keys = @parameters[ grep { ! ($_ % 2) } 0 .. $#parameters ];
  12         25  
58 3         8 @parameters = map { "- `$_`" } @keys;
  6         19  
59 3         8 $parameters = \@parameters;
60             }
61              
62 15         96 return $parameters;
63             }
64              
65             sub _parse_json_hash {
66 22     22   32 my ($self, $request_parameters, $layer, $param_description) = @_;
67              
68 22         41 my $indent = ' ' x $layer;
69              
70 22         21 my @parameters;
71 22 100       51 if (ref $request_parameters eq 'HASH') {
72 20         59 my @keys = keys %$request_parameters;
73 20         68 @keys = sort {$a cmp $b} @keys;
  24         47  
74 20         34 for my $key (@keys) {
75 40         50 my $value = $request_parameters->{$key};
76 40   100     125 my $param_dscr = $param_description->{$key} || '';
77 40 100 66     90 if ($param_dscr && !$indent) {
78 2         4 $param_dscr = " - $param_dscr";
79             }
80              
81 40 100       208 if ( ! defined $value) {
    100          
    100          
    100          
82 2         8 push @parameters, "$indent- `$key`: Nullable$param_dscr";
83             }
84             elsif ($value =~ /^\d+$/) {
85             # detect number or string internally
86 17 100       44 if (($value ^ $value) eq '0') {
87 16         69 push @parameters, "$indent- `$key`: Number (e.g. $value)$param_dscr";
88             }
89             else {
90 1         4 push @parameters, qq{$indent- `$key`: String (e.g. "$value")$param_dscr};
91             }
92             }
93             elsif (ref $value eq 'HASH') {
94 5         10 push @parameters, "$indent- `$key`: JSON$param_dscr";
95 5         3 push @parameters, @{$self->_parse_json_hash($value, ++$layer)};
  5         34  
96             }
97             elsif (ref $value eq 'ARRAY') {
98 1         3 push @parameters, "$indent- `$key`: Array$param_dscr";
99 1         1 push @parameters, @{$self->_parse_json_hash($value, ++$layer)};
  1         15  
100             }
101             else {
102 15         60 push @parameters, qq{$indent- `$key`: String (e.g. "$value")$param_dscr};
103             }
104             }
105             }
106             else {
107 2         3 for my $value (@$request_parameters) {
108 6 100       19 if ($value =~ /^\d/) {
    100          
    100          
109 1         3 push @parameters, "$indent- Number (e.g. $value)";
110             }
111             elsif (ref $value eq 'HASH') {
112 3         6 push @parameters, "$indent- Anonymous JSON";
113 3         2 push @parameters, @{$self->_parse_json_hash($value, ++$layer)};
  3         8  
114             }
115             elsif (ref $value eq 'ARRAY') {
116 1         3 push @parameters, "$indent- Anonymous Array";
117 1         1 push @parameters, @{$self->_parse_json_hash($value, ++$layer)};
  1         8  
118             }
119             else {
120 1         2 push @parameters, qq{$indent- String (e.g. "$value")};
121             }
122 6         8 $layer--;
123             }
124             }
125              
126 22         95 return \@parameters;
127             }
128             1;