| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package Web::ComposableRequest::Base; | 
| 2 |  |  |  |  |  |  |  | 
| 3 | 1 |  |  | 1 |  | 3 | use namespace::autoclean; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 4 |  | 
| 4 |  |  |  |  |  |  |  | 
| 5 | 1 |  |  | 1 |  | 499 | use HTTP::Body; | 
|  | 1 |  |  |  |  | 32269 |  | 
|  | 1 |  |  |  |  | 34 |  | 
| 6 | 1 |  |  |  |  | 115 | use HTTP::Status                      qw( HTTP_EXPECTATION_FAILED | 
| 7 |  |  |  |  |  |  | HTTP_INTERNAL_SERVER_ERROR | 
| 8 | 1 |  |  | 1 |  | 398 | HTTP_REQUEST_ENTITY_TOO_LARGE ); | 
|  | 1 |  |  |  |  | 3067 |  | 
| 9 | 1 |  |  | 1 |  | 6 | use Scalar::Util                      qw( weaken ); | 
|  | 1 |  |  |  |  | 3 |  | 
|  | 1 |  |  |  |  | 41 |  | 
| 10 | 1 |  |  | 1 |  | 4 | use Try::Tiny; | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 44 |  | 
| 11 | 1 |  |  | 1 |  | 4 | use Web::ComposableRequest::Constants qw( EXCEPTION_CLASS NUL TRUE ); | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 12 |  | 
| 12 | 1 |  |  |  |  | 7 | use Web::ComposableRequest::Util      qw( decode_array decode_hash first_char | 
| 13 |  |  |  |  |  |  | is_arrayref is_hashref new_uri | 
| 14 | 1 |  |  | 1 |  | 347 | throw ); | 
|  | 1 |  |  |  |  | 2 |  | 
| 15 | 1 |  |  | 1 |  | 477 | use Unexpected::Functions             qw( Unspecified ); | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 10 |  | 
| 16 | 1 |  |  |  |  | 10 | use Unexpected::Types                 qw( ArrayRef CodeRef HashRef LoadableClass | 
| 17 |  |  |  |  |  |  | NonEmptySimpleStr NonZeroPositiveInt | 
| 18 |  |  |  |  |  |  | Object PositiveInt SimpleStr Str | 
| 19 | 1 |  |  | 1 |  | 223 | Undef ); | 
|  | 1 |  |  |  |  | 1 |  | 
| 20 | 1 |  |  | 1 |  | 1112 | use Moo; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 7 |  | 
| 21 |  |  |  |  |  |  |  | 
| 22 |  |  |  |  |  |  | # Attribute constructors | 
| 23 |  |  |  |  |  |  | my $_build_body = sub { | 
| 24 | 5 |  |  | 5 |  | 57 | my $self = shift; my $content = $self->_content; my $len = length $content; | 
|  | 5 |  |  |  |  | 107 |  | 
|  | 5 |  |  |  |  | 298 |  | 
| 25 |  |  |  |  |  |  |  | 
| 26 | 5 |  |  |  |  | 104 | my $body = HTTP::Body->new( $self->content_type, $len ); | 
| 27 |  |  |  |  |  |  |  | 
| 28 | 5 |  |  |  |  | 564 | $body->cleanup( TRUE ); $body->tmpdir( $self->_config->tempdir ); | 
|  | 5 |  |  |  |  | 90 |  | 
| 29 |  |  |  |  |  |  |  | 
| 30 | 5 | 100 |  |  |  | 87 | $len or return $body; | 
| 31 |  |  |  |  |  |  |  | 
| 32 | 2 |  |  | 2 |  | 98 | try   { $self->_decode_body( $body, $content ) } | 
| 33 |  |  |  |  |  |  | catch { | 
| 34 |  |  |  |  |  |  | # uncoverable subroutine | 
| 35 |  |  |  |  |  |  | # uncoverable statement | 
| 36 | 0 |  |  | 0 |  | 0 | $self->_log->( { level => 'error', message => $_ } ); | 
| 37 | 2 |  |  |  |  | 17 | }; | 
| 38 |  |  |  |  |  |  |  | 
| 39 | 2 |  |  |  |  | 71 | return $body; | 
| 40 |  |  |  |  |  |  | }; | 
| 41 |  |  |  |  |  |  |  | 
| 42 |  |  |  |  |  |  | my $_build__content = sub { | 
| 43 | 5 |  |  | 5 |  | 50 | my $self    = shift; | 
| 44 | 5 | 100 |  |  |  | 102 | my $cl      = $self->content_length  or return NUL; | 
| 45 | 2 | 50 |  |  |  | 120 | my $fh      = $self->_env->{ 'psgi.input' } or return NUL; | 
| 46 | 2 |  |  |  |  | 5 | my $content = NUL; | 
| 47 |  |  |  |  |  |  |  | 
| 48 |  |  |  |  |  |  | try { | 
| 49 | 2 | 50 |  | 2 |  | 157 | $fh->can( 'seek' ) and $fh->seek( 0, 0 ); | 
| 50 | 2 |  |  |  |  | 44 | $fh->read( $content, $cl, 0 ); | 
| 51 | 2 | 50 |  |  |  | 42 | $fh->can( 'seek' ) and $fh->seek( 0, 0 ); | 
| 52 |  |  |  |  |  |  | } | 
| 53 |  |  |  |  |  |  | catch { | 
| 54 |  |  |  |  |  |  | # uncoverable subroutine | 
| 55 |  |  |  |  |  |  | # uncoverable statement | 
| 56 | 0 |  |  | 0 |  | 0 | $self->_log->( { level => 'error', message => $_ } ); | 
| 57 | 2 |  |  |  |  | 25 | }; | 
| 58 |  |  |  |  |  |  |  | 
| 59 | 2 |  |  |  |  | 109 | return $content; | 
| 60 |  |  |  |  |  |  | }; | 
| 61 |  |  |  |  |  |  |  | 
| 62 |  |  |  |  |  |  | my $_build_tunnel_method = sub { | 
| 63 | 3 |  | 100 | 3 |  | 659 | return $_[ 0 ]->body_params->(  '_method', { optional => TRUE } ) | 
| 64 |  |  |  |  |  |  | || $_[ 0 ]->query_params->( '_method', { optional => TRUE } ) | 
| 65 |  |  |  |  |  |  | || 'not_found'; | 
| 66 |  |  |  |  |  |  | }; | 
| 67 |  |  |  |  |  |  |  | 
| 68 |  |  |  |  |  |  | # Public attributes | 
| 69 |  |  |  |  |  |  | has 'address'        => is => 'lazy', isa => SimpleStr, | 
| 70 | 1 |  | 50 | 1 |  | 1468 | builder           => sub { $_[ 0 ]->_env->{ 'REMOTE_ADDR' } // NUL }; | 
| 71 |  |  |  |  |  |  |  | 
| 72 |  |  |  |  |  |  | has 'base'           => is => 'lazy', isa => Object, | 
| 73 | 1 |  |  | 1 |  | 384 | builder           => sub { new_uri $_[ 0 ]->scheme, $_[ 0 ]->_base }, | 
| 74 |  |  |  |  |  |  | init_arg          => undef; | 
| 75 |  |  |  |  |  |  |  | 
| 76 |  |  |  |  |  |  | has 'body'           => is => 'lazy', isa => Object, builder => $_build_body; | 
| 77 |  |  |  |  |  |  |  | 
| 78 |  |  |  |  |  |  | has 'content_length' => is => 'lazy', isa => PositiveInt, | 
| 79 | 5 |  | 100 | 5 |  | 157 | builder           => sub { $_[ 0 ]->_env->{ 'CONTENT_LENGTH' } // 0 }; | 
| 80 |  |  |  |  |  |  |  | 
| 81 |  |  |  |  |  |  | has 'content_type'   => is => 'lazy', isa => SimpleStr, | 
| 82 | 5 |  | 100 | 5 |  | 146 | builder           => sub { $_[ 0 ]->_env->{ 'CONTENT_TYPE' } // NUL }; | 
| 83 |  |  |  |  |  |  |  | 
| 84 |  |  |  |  |  |  | has 'host'           => is => 'lazy', isa => NonEmptySimpleStr, | 
| 85 | 1 |  |  | 1 |  | 830 | builder           => sub { (split m{ : }mx, $_[ 0 ]->hostport)[ 0 ] }; | 
| 86 |  |  |  |  |  |  |  | 
| 87 |  |  |  |  |  |  | has 'hostport'       => is => 'lazy', isa => NonEmptySimpleStr, | 
| 88 | 2 |  | 50 | 2 |  | 127 | builder           => sub { $_[ 0 ]->_env->{ 'HTTP_HOST' } // 'localhost' }; | 
| 89 |  |  |  |  |  |  |  | 
| 90 |  |  |  |  |  |  | has 'method'         => is => 'lazy', isa => SimpleStr, | 
| 91 | 1 |  | 50 | 1 |  | 497 | builder           => sub { lc( $_[ 0 ]->_env->{ 'REQUEST_METHOD' } // NUL )}; | 
| 92 |  |  |  |  |  |  |  | 
| 93 |  |  |  |  |  |  | has 'path'           => is => 'lazy', isa => SimpleStr, builder => sub { | 
| 94 | 2 |  | 50 | 2 |  | 100 | my $v             =  $_[ 0 ]->_env->{ 'PATH_INFO' } // '/'; | 
| 95 | 2 |  |  |  |  | 10 | $v             =~ s{ \A / }{}mx; $v =~ s{ \? .* \z }{}mx; $v }; | 
|  | 2 |  |  |  |  | 7 |  | 
|  | 2 |  |  |  |  | 35 |  | 
| 96 |  |  |  |  |  |  |  | 
| 97 |  |  |  |  |  |  | has 'port'           => is => 'lazy', isa => NonZeroPositiveInt, | 
| 98 | 1 |  | 50 | 1 |  | 548 | builder           => sub { $_[ 0 ]->_env->{ 'SERVER_PORT' } // 80 }; | 
| 99 |  |  |  |  |  |  |  | 
| 100 |  |  |  |  |  |  | has 'protocol'       => is => 'lazy', isa => NonEmptySimpleStr, | 
| 101 | 1 |  |  | 1 |  | 448 | builder           => sub { $_[ 0 ]->_env->{ 'SERVER_PROTOCOL' } }; | 
| 102 |  |  |  |  |  |  |  | 
| 103 |  |  |  |  |  |  | has 'query'          => is => 'lazy', isa => Str, builder => sub { | 
| 104 | 1 | 50 |  | 1 |  | 481 | my $v             =  $_[ 0 ]->_env->{ 'QUERY_STRING' }; $v ? "?${v}" : NUL }; | 
|  | 1 |  |  |  |  | 29 |  | 
| 105 |  |  |  |  |  |  |  | 
| 106 |  |  |  |  |  |  | has 'referer'        => is => 'lazy', isa => Str, | 
| 107 | 1 |  | 50 | 1 |  | 546 | builder           => sub { $_[ 0 ]->_env->{ 'HTTP_REFERER' } // NUL }; | 
| 108 |  |  |  |  |  |  |  | 
| 109 |  |  |  |  |  |  | has 'remote_host'    => is => 'lazy', isa => SimpleStr, | 
| 110 | 1 |  | 50 | 1 |  | 474 | builder           => sub { $_[ 0 ]->_env->{ 'REMOTE_HOST' } // NUL }; | 
| 111 |  |  |  |  |  |  |  | 
| 112 |  |  |  |  |  |  | has 'scheme'         => is => 'lazy', isa => NonEmptySimpleStr, | 
| 113 | 3 |  | 50 | 3 |  | 82 | builder           => sub { $_[ 0 ]->_env->{ 'psgi.url_scheme' } // 'http' }; | 
| 114 |  |  |  |  |  |  |  | 
| 115 |  |  |  |  |  |  | has 'script'         => is => 'lazy', isa => SimpleStr, builder => sub { | 
| 116 | 2 |  | 50 | 2 |  | 186 | my $v             =  $_[ 0 ]->_env->{ 'SCRIPT_NAME' } // '/'; | 
| 117 | 2 |  |  |  |  | 9 | $v             =~ s{ / \z }{}gmx; $v }; | 
|  | 2 |  |  |  |  | 40 |  | 
| 118 |  |  |  |  |  |  |  | 
| 119 |  |  |  |  |  |  | has 'tunnel_method'  => is => 'lazy', isa => NonEmptySimpleStr, | 
| 120 |  |  |  |  |  |  | builder           => $_build_tunnel_method; | 
| 121 |  |  |  |  |  |  |  | 
| 122 |  |  |  |  |  |  | has 'upload'         => is => 'lazy', isa => Object | Undef, | 
| 123 |  |  |  |  |  |  | predicate         => TRUE; | 
| 124 |  |  |  |  |  |  |  | 
| 125 |  |  |  |  |  |  | has 'uri'            => is => 'lazy', isa => Object, builder => sub { | 
| 126 | 1 |  |  | 1 |  | 59 | new_uri $_[ 0 ]->scheme, $_[ 0 ]->_base.$_[ 0 ]->path.$_[ 0 ]->query }; | 
| 127 |  |  |  |  |  |  |  | 
| 128 |  |  |  |  |  |  | # Private attributes | 
| 129 |  |  |  |  |  |  | has '_args'    => is => 'ro',   isa => ArrayRef, | 
| 130 | 5 |  |  | 5 |  | 226 | builder     => sub { [] }, init_arg => 'args'; | 
| 131 |  |  |  |  |  |  |  | 
| 132 |  |  |  |  |  |  | has '_base'    => is => 'lazy', isa => NonEmptySimpleStr, builder => sub { | 
| 133 | 2 |  |  | 2 |  | 120 | $_[ 0 ]->scheme.'://'.$_[ 0 ]->hostport.$_[ 0 ]->script.'/' }; | 
| 134 |  |  |  |  |  |  |  | 
| 135 |  |  |  |  |  |  | has '_config'  => is => 'ro',   isa => Object, | 
| 136 |  |  |  |  |  |  | required    => TRUE, init_arg => 'config'; | 
| 137 |  |  |  |  |  |  |  | 
| 138 |  |  |  |  |  |  | has '_content' => is => 'lazy', isa => Str, | 
| 139 |  |  |  |  |  |  | builder     => $_build__content; | 
| 140 |  |  |  |  |  |  |  | 
| 141 |  |  |  |  |  |  | has '_env'     => is => 'ro',   isa => HashRef, | 
| 142 |  |  |  |  |  |  | init_arg    => 'env', required => TRUE; | 
| 143 |  |  |  |  |  |  |  | 
| 144 |  |  |  |  |  |  | has '_log'     => is => 'lazy', isa => CodeRef, | 
| 145 | 1 |  | 50 | 1 |  | 113 | builder     => sub { $_[ 0 ]->_env->{ 'psgix.logger' } // sub {} }, | 
|  |  |  |  | 1 |  |  |  | 
| 146 |  |  |  |  |  |  | init_arg    => 'log'; | 
| 147 |  |  |  |  |  |  |  | 
| 148 |  |  |  |  |  |  | has '_params'  => is => 'ro',   isa => HashRef, | 
| 149 | 2 |  |  | 2 |  | 102 | builder     => sub { {} }, init_arg => 'params'; | 
| 150 |  |  |  |  |  |  |  | 
| 151 |  |  |  |  |  |  | # Construction | 
| 152 |  |  |  |  |  |  | sub BUILD { | 
| 153 | 7 |  |  | 7 | 1 | 21443 | my $self = shift; my $enc = $self->_config->encoding; | 
|  | 7 |  |  |  |  | 75 |  | 
| 154 |  |  |  |  |  |  |  | 
| 155 | 7 |  |  |  |  | 37 | decode_array $enc, $self->_args; decode_hash $enc, $self->_params; | 
|  | 7 |  |  |  |  | 38 |  | 
| 156 |  |  |  |  |  |  |  | 
| 157 | 7 |  |  |  |  | 36 | return; | 
| 158 |  |  |  |  |  |  | } | 
| 159 |  |  |  |  |  |  |  | 
| 160 |  |  |  |  |  |  | # Private functions | 
| 161 |  |  |  |  |  |  | my $_defined_or_throw = sub { | 
| 162 |  |  |  |  |  |  | my ($k, $v, $opts) = @_; $opts->{optional} and return $v; | 
| 163 |  |  |  |  |  |  |  | 
| 164 |  |  |  |  |  |  | $k =~ m{ \A \d+ \z }mx and $k = "arg[${k}]"; | 
| 165 |  |  |  |  |  |  |  | 
| 166 |  |  |  |  |  |  | defined $v or throw 'Parameter [_1] undefined value', [ $k ], | 
| 167 |  |  |  |  |  |  | level => 6, rv => HTTP_EXPECTATION_FAILED; | 
| 168 |  |  |  |  |  |  |  | 
| 169 |  |  |  |  |  |  | return $v; | 
| 170 |  |  |  |  |  |  | }; | 
| 171 |  |  |  |  |  |  |  | 
| 172 |  |  |  |  |  |  | my $_get_last_value = sub { | 
| 173 |  |  |  |  |  |  | my ($k, $v, $opts) = @_; return $_defined_or_throw->( $k, $v->[-1], $opts ); | 
| 174 |  |  |  |  |  |  | }; | 
| 175 |  |  |  |  |  |  |  | 
| 176 |  |  |  |  |  |  | my $_get_value_or_values = sub { | 
| 177 |  |  |  |  |  |  | my ($params, $name, $opts) = @_; | 
| 178 |  |  |  |  |  |  |  | 
| 179 |  |  |  |  |  |  | defined $name or throw Unspecified, [ 'name' ], | 
| 180 |  |  |  |  |  |  | level => 5, rv => HTTP_INTERNAL_SERVER_ERROR; | 
| 181 |  |  |  |  |  |  |  | 
| 182 |  |  |  |  |  |  | my $v = (is_arrayref $params and $name eq '-1') ? [ @{ $params } ] | 
| 183 |  |  |  |  |  |  | : (is_arrayref $params                  ) ? $params->[ $name ] | 
| 184 |  |  |  |  |  |  | : (                        $name eq '-1') ? { %{ $params } } | 
| 185 |  |  |  |  |  |  | : $params->{ $name }; | 
| 186 |  |  |  |  |  |  |  | 
| 187 |  |  |  |  |  |  | return $_defined_or_throw->( $name, $v, $opts ); | 
| 188 |  |  |  |  |  |  | }; | 
| 189 |  |  |  |  |  |  |  | 
| 190 |  |  |  |  |  |  | my $_get_defined_value = sub { | 
| 191 |  |  |  |  |  |  | my ($params, $name, $opts) = @_; | 
| 192 |  |  |  |  |  |  |  | 
| 193 |  |  |  |  |  |  | my $v = $_get_value_or_values->( $params, $name, $opts ); | 
| 194 |  |  |  |  |  |  |  | 
| 195 |  |  |  |  |  |  | return (is_arrayref $v) ? $_get_last_value->( $name, $v, $opts ) : $v; | 
| 196 |  |  |  |  |  |  | }; | 
| 197 |  |  |  |  |  |  |  | 
| 198 |  |  |  |  |  |  | my $_get_defined_values = sub { | 
| 199 |  |  |  |  |  |  | my ($params, $name, $opts) = @_; | 
| 200 |  |  |  |  |  |  |  | 
| 201 |  |  |  |  |  |  | my $v = $_get_value_or_values->( $params, $name, $opts ); | 
| 202 |  |  |  |  |  |  |  | 
| 203 |  |  |  |  |  |  | return (is_arrayref $v) ? $v : [ $v ]; | 
| 204 |  |  |  |  |  |  | }; | 
| 205 |  |  |  |  |  |  |  | 
| 206 |  |  |  |  |  |  | my $_scrub_value = sub { | 
| 207 |  |  |  |  |  |  | my ($name, $v, $opts) = @_; my $pattern = $opts->{scrubber}; my $len; | 
| 208 |  |  |  |  |  |  |  | 
| 209 |  |  |  |  |  |  | $pattern and defined $v and $v =~ s{ $pattern }{}gmx; | 
| 210 |  |  |  |  |  |  |  | 
| 211 |  |  |  |  |  |  | $name =~ m{ \A [\-]? \d+ \z }mx and $name = "arg[${name}]"; | 
| 212 |  |  |  |  |  |  |  | 
| 213 |  |  |  |  |  |  | $opts->{optional} or $opts->{allow_null} or $len = length $v | 
| 214 |  |  |  |  |  |  | or  throw Unspecified, [ $name ], level => 4, | 
| 215 |  |  |  |  |  |  | rv => HTTP_EXPECTATION_FAILED; | 
| 216 |  |  |  |  |  |  |  | 
| 217 |  |  |  |  |  |  | $len and $len > $opts->{max_length} | 
| 218 |  |  |  |  |  |  | and throw 'Parameter [_1] size [_2] too big', [ $name, $len ], level => 4, | 
| 219 |  |  |  |  |  |  | rv => HTTP_REQUEST_ENTITY_TOO_LARGE; | 
| 220 |  |  |  |  |  |  | return $v; | 
| 221 |  |  |  |  |  |  | }; | 
| 222 |  |  |  |  |  |  |  | 
| 223 |  |  |  |  |  |  | my $_scrub_hash = sub { | 
| 224 |  |  |  |  |  |  | my ($params, $opts) = @_; | 
| 225 |  |  |  |  |  |  |  | 
| 226 |  |  |  |  |  |  | my $hash = $_get_defined_value->( $params, -1, $opts ); | 
| 227 |  |  |  |  |  |  | my @keys = keys %{ $hash }; | 
| 228 |  |  |  |  |  |  |  | 
| 229 |  |  |  |  |  |  | for my $k (@keys) { | 
| 230 |  |  |  |  |  |  | my $v = delete $hash->{ $k }; | 
| 231 |  |  |  |  |  |  |  | 
| 232 |  |  |  |  |  |  | $hash->{ $_scrub_value->( 'key', $k, $opts ) } | 
| 233 |  |  |  |  |  |  | = (is_arrayref $v && $opts->{multiple}) ? | 
| 234 |  |  |  |  |  |  | [ map { $_scrub_value->( $k, $_, $opts ) } @{ $v } ] | 
| 235 |  |  |  |  |  |  | : (is_arrayref $v) ? $_get_last_value->( $k, $v, $opts ) | 
| 236 |  |  |  |  |  |  | : $_scrub_value->( $k, $v, $opts ); | 
| 237 |  |  |  |  |  |  | } | 
| 238 |  |  |  |  |  |  |  | 
| 239 |  |  |  |  |  |  | return $hash; | 
| 240 |  |  |  |  |  |  | }; | 
| 241 |  |  |  |  |  |  |  | 
| 242 |  |  |  |  |  |  | my $_get_scrubbed_param = sub { | 
| 243 |  |  |  |  |  |  | my ($self, $params, $name, $opts) = @_; $opts = { %{ $opts // {} } }; | 
| 244 |  |  |  |  |  |  |  | 
| 245 |  |  |  |  |  |  | $opts->{max_length} //= $self->_config->max_asset_size; | 
| 246 |  |  |  |  |  |  | $opts->{scrubber  } //= $self->_config->scrubber; | 
| 247 |  |  |  |  |  |  | $opts->{hashref   } and return $_scrub_hash->( $params, $opts ); | 
| 248 |  |  |  |  |  |  | $opts->{multiple  } and return | 
| 249 |  |  |  |  |  |  | [ map { $opts->{raw} ? $_ : $_scrub_value->( $name, $_, $opts ) } | 
| 250 |  |  |  |  |  |  | @{ $_get_defined_values->( $params, $name, $opts ) } ]; | 
| 251 |  |  |  |  |  |  |  | 
| 252 |  |  |  |  |  |  | my $v = $_get_defined_value->( $params, $name, $opts ); | 
| 253 |  |  |  |  |  |  |  | 
| 254 |  |  |  |  |  |  | return $opts->{raw} ? $v : $_scrub_value->( $name, $v, $opts ); | 
| 255 |  |  |  |  |  |  | }; | 
| 256 |  |  |  |  |  |  |  | 
| 257 |  |  |  |  |  |  | # Private methods | 
| 258 |  |  |  |  |  |  | sub _decode_body { | 
| 259 | 1 |  |  | 1 |  | 2 | my ($self, $body, $content) = @_; | 
| 260 |  |  |  |  |  |  |  | 
| 261 | 1 |  |  |  |  | 7 | $body->add( $content ); decode_hash $self->_config->encoding, $body->param; | 
|  | 1 |  |  |  |  | 776 |  | 
| 262 |  |  |  |  |  |  |  | 
| 263 | 1 |  |  |  |  | 3 | return; | 
| 264 |  |  |  |  |  |  | } | 
| 265 |  |  |  |  |  |  |  | 
| 266 |  |  |  |  |  |  | # Public methods | 
| 267 |  |  |  |  |  |  | sub body_params { | 
| 268 | 8 |  |  | 8 | 1 | 770 | my $self = shift; weaken( $self ); | 
|  | 8 |  |  |  |  | 27 |  | 
| 269 |  |  |  |  |  |  |  | 
| 270 | 8 |  |  |  |  | 201 | my $params = $self->body->param; weaken( $params ); | 
|  | 8 |  |  |  |  | 173 |  | 
| 271 |  |  |  |  |  |  |  | 
| 272 |  |  |  |  |  |  | return sub { | 
| 273 |  |  |  |  |  |  | return $_get_scrubbed_param-> | 
| 274 |  |  |  |  |  |  | ( $self, $params, (defined $_[ 0 ] && !is_hashref $_[ 0 ]) | 
| 275 | 8 | 100 | 66 | 8 |  | 42 | ? @_ : (-1, { %{ $_[ 0 ] // {} }, hashref => TRUE }) ); | 
|  | 2 |  | 50 |  |  | 18 |  | 
| 276 | 8 |  |  |  |  | 47 | }; | 
| 277 |  |  |  |  |  |  | } | 
| 278 |  |  |  |  |  |  |  | 
| 279 |  |  |  |  |  |  | sub query_params { | 
| 280 | 25 |  |  | 25 | 1 | 59 | my $self = shift; weaken( $self ); | 
|  | 25 |  |  |  |  | 70 |  | 
| 281 |  |  |  |  |  |  |  | 
| 282 | 25 |  |  |  |  | 50 | my $params = $self->_params; weaken( $params ); | 
|  | 25 |  |  |  |  | 41 |  | 
| 283 |  |  |  |  |  |  |  | 
| 284 |  |  |  |  |  |  | return sub { | 
| 285 |  |  |  |  |  |  | return $_get_scrubbed_param-> | 
| 286 |  |  |  |  |  |  | ( $self, $params, (defined $_[ 0 ] && !is_hashref $_[ 0 ]) | 
| 287 | 25 | 100 | 66 | 25 |  | 120 | ? @_ : (-1, { %{ $_[ 0 ] // {} }, hashref => TRUE }) ); | 
|  | 2 |  | 50 |  |  | 17 |  | 
| 288 | 25 |  |  |  |  | 131 | }; | 
| 289 |  |  |  |  |  |  | } | 
| 290 |  |  |  |  |  |  |  | 
| 291 |  |  |  |  |  |  | sub uri_for { | 
| 292 | 3 |  | 50 | 3 | 1 | 99 | my ($self, $path, @args) = @_; $path //= NUL; | 
|  | 3 |  |  |  |  | 8 |  | 
| 293 |  |  |  |  |  |  |  | 
| 294 | 3 |  |  |  |  | 62 | my $base = $self->_base; my @query_params = (); my $uri_params = []; | 
|  | 3 |  |  |  |  | 92 |  | 
|  | 3 |  |  |  |  | 7 |  | 
| 295 |  |  |  |  |  |  |  | 
| 296 | 3 | 100 |  |  |  | 12 | if (is_arrayref $args[ 0 ]) { | 
|  |  | 100 |  |  |  |  |  | 
| 297 | 1 |  |  |  |  | 3 | $uri_params = shift @args; @query_params = @args; | 
|  | 1 |  |  |  |  | 2 |  | 
| 298 |  |  |  |  |  |  | } | 
| 299 |  |  |  |  |  |  | elsif (is_hashref $args[ 0 ]) { | 
| 300 | 1 |  | 50 |  |  | 5 | $uri_params   =    $args[ 0 ]->{uri_params  } // []; | 
| 301 | 1 |  | 50 |  |  | 2 | @query_params = @{ $args[ 0 ]->{query_params} // [] }; | 
|  | 1 |  |  |  |  | 6 |  | 
| 302 | 1 | 50 |  |  |  | 4 | $args[ 0 ]->{base} and $base = $args[ 0 ]->{base}; | 
| 303 |  |  |  |  |  |  | } | 
| 304 |  |  |  |  |  |  |  | 
| 305 | 3 | 50 |  |  |  | 13 | first_char $path ne '/' and $path = $base.$path; | 
| 306 |  |  |  |  |  |  |  | 
| 307 |  |  |  |  |  |  | $uri_params->[ 0 ] and $path = join '/', $path, | 
| 308 | 3 | 50 |  |  |  | 11 | grep { defined and length } @{ $uri_params }; | 
|  | 2 | 100 |  |  |  | 11 |  | 
|  | 2 |  |  |  |  | 3 |  | 
| 309 |  |  |  |  |  |  |  | 
| 310 | 3 |  |  |  |  | 56 | my $uri = new_uri $self->scheme, $path; | 
| 311 |  |  |  |  |  |  |  | 
| 312 | 3 | 50 |  |  |  | 9 | $query_params[ 0 ] and $uri->query_form( @query_params ); | 
| 313 |  |  |  |  |  |  |  | 
| 314 | 3 |  |  |  |  | 21 | return $uri; | 
| 315 |  |  |  |  |  |  | } | 
| 316 |  |  |  |  |  |  |  | 
| 317 |  |  |  |  |  |  | sub uri_params { | 
| 318 | 4 |  |  | 4 | 1 | 7 | my $self = shift; weaken( $self ); | 
|  | 4 |  |  |  |  | 11 |  | 
| 319 |  |  |  |  |  |  |  | 
| 320 | 4 |  |  |  |  | 12 | my $params = $self->_args; weaken( $params ); | 
|  | 4 |  |  |  |  | 11 |  | 
| 321 |  |  |  |  |  |  |  | 
| 322 |  |  |  |  |  |  | return sub { | 
| 323 |  |  |  |  |  |  | return $_get_scrubbed_param-> | 
| 324 |  |  |  |  |  |  | ( $self, $params, (defined $_[ 0 ] && !is_hashref $_[ 0 ]) | 
| 325 | 4 | 100 | 66 | 4 |  | 26 | ? @_ : (-1, { %{ $_[ 0 ] // {} }, multiple => TRUE }) ); | 
|  | 1 |  | 50 |  |  | 8 |  | 
| 326 | 4 |  |  |  |  | 23 | }; | 
| 327 |  |  |  |  |  |  | } | 
| 328 |  |  |  |  |  |  |  | 
| 329 |  |  |  |  |  |  | 1; | 
| 330 |  |  |  |  |  |  |  | 
| 331 |  |  |  |  |  |  | __END__ |