File Coverage

blib/lib/Amon2/Web/Request.pm
Criterion Covered Total %
statement 77 86 89.5
branch 13 28 46.4
condition 10 21 47.6
subroutine 16 18 88.8
pod 9 9 100.0
total 125 162 77.1


line stmt bran cond sub pod time code
1             package Amon2::Web::Request;
2 18     18   4452 use strict;
  18         56  
  18         519  
3 18     18   90 use warnings;
  18         32  
  18         495  
4 18     18   1769 use parent qw/Plack::Request/;
  18         1403  
  18         105  
5 18     18   1110721 use Encode ();
  18         54  
  18         284  
6 18     18   87 use Carp ();
  18         45  
  18         320  
7 18     18   8529 use URI::QueryParam;
  18         14203  
  18         598  
8 18     18   136 use Hash::MultiValue;
  18         38  
  18         15752  
9              
10             sub new {
11 50     50 1 28813 my ($class, $env, $context_class) = @_;
12 50         271 my $self = $class->SUPER::new($env);
13 50 100       562 if (@_==3) {
14 22         66 $self->{_web_pkg} = $context_class;
15             }
16 50         192 return $self;
17             }
18              
19             sub _encoding {
20 3     3   6 my $self = shift;
21 3 50       18 return $self->{_web_pkg} ? $self->{_web_pkg}->context->encoding : Amon2->context->encoding;
22             }
23              
24             # -------------------------------------------------------------------------
25             # This object returns decoded parameter values by default
26              
27             sub body_parameters {
28 1     1 1 2 my ($self) = @_;
29 1   33     25 $self->{'amon2.body_parameters'} ||= $self->_decode_parameters($self->SUPER::body_parameters());
30             }
31              
32             sub query_parameters {
33 2     2 1 550 my ($self) = @_;
34 2   66     17 $self->{'amon2.query_parameters'} ||= $self->_decode_parameters($self->SUPER::query_parameters());
35             }
36              
37             sub _decode_parameters {
38 2     2   352 my ($self, $stuff) = @_;
39              
40 2         6 my $encoding = $self->_encoding();
41 2         13 my @flatten = $stuff->flatten();
42 2         28 my @decoded;
43 2         10 while ( my ($k, $v) = splice @flatten, 0, 2 ) {
44 3         190 push @decoded, Encode::decode($encoding, $k), Encode::decode($encoding, $v);
45             }
46 2         67 return Hash::MultiValue->new(@decoded);
47             }
48             sub parameters {
49 3     3 1 1435 my $self = shift;
50              
51 3   66     15 $self->env->{'amon2.request.merged'} ||= do {
52 1         12 my $query = $self->query_parameters;
53 1         51 my $body = $self->body_parameters;
54 1         30 Hash::MultiValue->new( $query->flatten, $body->flatten );
55             };
56             }
57              
58             # -------------------------------------------------------------------------
59             # raw parameter values are also available.
60              
61             sub body_parameters_raw {
62 0     0 1 0 shift->SUPER::body_parameters();
63             }
64             sub query_parameters_raw {
65 0     0 1 0 shift->SUPER::query_parameters();
66             }
67             sub parameters_raw {
68 2     2 1 469 my $self = shift;
69              
70 2   66     8 $self->env->{'plack.request.merged'} ||= do {
71 1         9 my $query = $self->SUPER::query_parameters();
72 1         19 my $body = $self->SUPER::body_parameters();
73 1         12 Hash::MultiValue->new( $query->flatten, $body->flatten );
74             };
75             }
76             sub param_raw {
77 1     1 1 3646 my $self = shift;
78              
79 1 50       5 return keys %{ $self->parameters_raw } if @_ == 0;
  0         0  
80              
81 1         2 my $key = shift;
82 1 50       5 return $self->parameters_raw->{$key} unless wantarray;
83 0         0 return $self->parameters_raw->get_all($key);
84             }
85              
86              
87             # -------------------------------------------------------------------------
88             # uri_with funcition. The code was taken from Catalyst::Request
89             sub uri_with {
90 2     2 1 54 my( $self, $args, $behavior) = @_;
91              
92 2 50       5 Carp::carp( 'No arguments passed to uri_with()' ) unless $args;
93              
94 2         4 my $append = 0;
95 2 0 33     7 if((ref($behavior) eq 'HASH') && defined($behavior->{mode}) && ($behavior->{mode} eq 'append')) {
      33        
96 0         0 $append = 1;
97             }
98              
99 2         4 my $params = do {
100 2         6 foreach my $value ( values %$args ) {
101 2 50       7 next unless defined $value;
102 2 50       9 for ( ref $value eq 'ARRAY' ? @$value : $value ) {
103 2         5 $_ = "$_";
104 2 50       9 utf8::encode($_) if utf8::is_utf8($_);
105             }
106             }
107              
108 2         5 my %params = %{ $self->uri->query_form_hash };
  2         12  
109 2         8259 foreach my $key ( keys %{$args} ) {
  2         8  
110 2         5 my $val = $args->{$key};
111 2 100       8 if (utf8::is_utf8($key)) {
112 1         5 $key = Encode::encode($self->_encoding(), $key);
113             }
114 2 50       37 if ( defined($val) ) {
115              
116 2 50 33     6 if ( $append && exists( $params{$key} ) ) {
117              
118             # This little bit of heaven handles appending a new value onto
119             # an existing one regardless if the existing value is an array
120             # or not, and regardless if the new value is an array or not
121             $params{$key} = [
122             ref( $params{$key} ) eq 'ARRAY'
123 0         0 ? @{ $params{$key} }
124             : $params{$key},
125 0 0       0 ref($val) eq 'ARRAY' ? @{$val} : $val
  0 0       0  
126             ];
127              
128             }
129             else {
130 2         6 $params{$key} = $val;
131             }
132             }
133             else {
134              
135             # If the param wasn't defined then we delete it.
136 0         0 delete( $params{$key} );
137             }
138             }
139 2         5 \%params;
140             };
141              
142 2         7 my $uri = $self->uri->clone;
143 2         501 $uri->query_form($params);
144              
145 2         292 return $uri;
146             }
147              
148             1;
149             __END__
150              
151             =encoding utf-8
152              
153             =head1 NAME
154              
155             Amon2::Web::Request - Amon2 Request Class
156              
157             =head1 DESCRIPTION
158              
159             This is a child class of L<Plack::Request>. Please see L<Plack::Request> for more details.
160              
161             =head1 AUTOMATIC DECODING
162              
163             This class decode query/body parameters automatically.
164             Return value of C<< $req->param() >>, C<< $req->body_parameters >>, etc. is the decoded value.
165              
166             =head1 METHODS
167              
168             =over 4
169              
170             =item C<< $req->uri_with($args, $behavior) >>
171              
172             Returns a rewritten URI object for the current request. Key/value pairs passed in will override existing parameters. You can remove an existing parameter by passing in an undef value. Unmodified pairs will be preserved.
173              
174             You may also pass an optional second parameter that puts uri_with into append mode:
175              
176             $req->uri_with( { key => 'value' }, { mode => 'append' } );
177              
178             =item C<< $req->body_parameters_raw() >>
179              
180             =item C<< $req->query_parameters_raw() >>
181              
182             =item C<< $req->parameters_raw() >>
183              
184             =item C<< $req->param_raw() >>
185              
186             =item C<< $req->param_raw($key) >>
187              
188             =item C<< $req->param_raw($key => $val) >>
189              
190             These methods are the accessor to raw values. 'raw' means the value is not decoded.
191              
192             =back
193              
194             =cut
195