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