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 15     15   98 use strict;
  15         18  
  15         514  
3 15     15   59 use warnings;
  15         20  
  15         392  
4 15     15   57 use utf8;
  15         17  
  15         67  
5 15     15   251 use Carp;
  15         26  
  15         792  
6 15     15   8924 use JSON;
  15         136316  
  15         116  
7 15     15   9653 use URL::Encode qw/url_params_flat/;
  15         52032  
  15         12276  
8              
9             sub new {
10 17     17 0 40 my ($class) = @_;
11              
12 17         96 bless {
13             }, $class;
14             }
15              
16             sub parse {
17 17     17 0 37 my ($self, $req, $param_description) = @_;
18              
19 17 50       162 unless ($req->isa('HTTP::Request')) {
20 0         0 croak 'Request must be instance of HTTP::Request or subclass of that';
21             }
22              
23 17         73 my $body = $req->content;
24 17         276 my $content_type = $req->content_type;
25              
26 17         609 my $is_json = 0;
27 17 100       97 if ($content_type =~ m!^application/json!) {
28 14         98 $body = to_json(from_json($req->decoded_content), { pretty => 1 });
29 14         2911 $is_json = 1;
30             }
31              
32 17         44 my $target_server = '';
33 17 100 66     65 if ($req->uri->scheme && $req->uri->authority) {
34 11         832 $target_server = $req->uri->scheme . '://' . $req->uri->authority;
35             }
36              
37             return {
38 17         559 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 17     17   208 my ($self, $request_parameters, $is_json, $param_description) = @_;
49              
50 17         33 my $parameters;
51 17 100       58 if ($is_json) {
52 14         179 $request_parameters = JSON::decode_json($request_parameters);
53 14         64 $parameters = $self->_parse_json_hash($request_parameters, 0, $param_description);
54             }
55             else {
56 3         7 my @parameters = @{url_params_flat($request_parameters)};
  3         18  
57 3         182 my @keys = @parameters[ grep { ! ($_ % 2) } 0 .. $#parameters ];
  12         44  
58 3         9 @parameters = map { "- `$_`" } @keys;
  6         21  
59 3         10 $parameters = \@parameters;
60             }
61              
62 17         103 return $parameters;
63             }
64              
65             sub _parse_json_hash {
66 24     24   37 my ($self, $request_parameters, $layer, $param_description) = @_;
67              
68 24         50 my $indent = ' ' x $layer;
69              
70 24         28 my @parameters;
71 24 100       63 if (ref $request_parameters eq 'HASH') {
72 22         89 my @keys = keys %$request_parameters;
73 22         87 @keys = sort {$a cmp $b} @keys;
  24         51  
74 22         43 for my $key (@keys) {
75 44         57 my $value = $request_parameters->{$key};
76 44   100     166 my $param_dscr = $param_description->{$key} || '';
77 44 100 66     105 if ($param_dscr && !$indent) {
78 2         3 $param_dscr = " - $param_dscr";
79             }
80              
81 44 100       265 if ( ! defined $value) {
    100          
    100          
    100          
82 2         12 push @parameters, "$indent- `$key`: Nullable$param_dscr";
83             }
84             elsif ($value =~ /^\d+$/) {
85             # detect number or string internally
86 19 100       69 if (($value ^ $value) eq '0') {
87 18         74 push @parameters, "$indent- `$key`: Number (e.g. $value)$param_dscr";
88             }
89             else {
90 1         6 push @parameters, qq{$indent- `$key`: String (e.g. "$value")$param_dscr};
91             }
92             }
93             elsif (ref $value eq 'HASH') {
94 5         11 push @parameters, "$indent- `$key`: JSON$param_dscr";
95 5         4 push @parameters, @{$self->_parse_json_hash($value, ++$layer)};
  5         27  
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         17  
100             }
101             else {
102 17         74 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       20 if ($value =~ /^\d/) {
    100          
    100          
109 1         2 push @parameters, "$indent- Number (e.g. $value)";
110             }
111             elsif (ref $value eq 'HASH') {
112 3         5 push @parameters, "$indent- Anonymous JSON";
113 3         3 push @parameters, @{$self->_parse_json_hash($value, ++$layer)};
  3         11  
114             }
115             elsif (ref $value eq 'ARRAY') {
116 1         2 push @parameters, "$indent- Anonymous Array";
117 1         1 push @parameters, @{$self->_parse_json_hash($value, ++$layer)};
  1         8  
118             }
119             else {
120 1         3 push @parameters, qq{$indent- String (e.g. "$value")};
121             }
122 6         8 $layer--;
123             }
124             }
125              
126 24         106 return \@parameters;
127             }
128             1;