| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package WebService::Simple; | 
| 2 | 8 |  |  | 8 |  | 180876 | use strict; | 
|  | 8 |  |  |  |  | 1046 |  | 
|  | 8 |  |  |  |  | 180 |  | 
| 3 | 8 |  |  | 8 |  | 36 | use warnings; | 
|  | 8 |  |  |  |  | 12 |  | 
|  | 8 |  |  |  |  | 229 |  | 
| 4 | 8 |  |  | 8 |  | 34 | use base qw(LWP::UserAgent Class::Data::ConfigHash); | 
|  | 8 |  |  |  |  | 21 |  | 
|  | 8 |  |  |  |  | 7745 |  | 
| 5 | 8 |  |  | 8 |  | 695658 | use Class::Inspector; | 
|  | 8 |  |  |  |  | 26388 |  | 
|  | 8 |  |  |  |  | 206 |  | 
| 6 | 8 |  |  | 8 |  | 6270 | use Data::Dumper (); | 
|  | 8 |  |  |  |  | 47936 |  | 
|  | 8 |  |  |  |  | 177 |  | 
| 7 | 8 |  |  | 8 |  | 48 | use Digest::MD5  (); | 
|  | 8 |  |  |  |  | 15 |  | 
|  | 8 |  |  |  |  | 124 |  | 
| 8 | 8 |  |  | 8 |  | 36 | use URI::Escape; | 
|  | 8 |  |  |  |  | 17 |  | 
|  | 8 |  |  |  |  | 491 |  | 
| 9 | 8 |  |  | 8 |  | 5558 | use URI::QueryParam; | 
|  | 8 |  |  |  |  | 4677 |  | 
|  | 8 |  |  |  |  | 213 |  | 
| 10 | 8 |  |  | 8 |  | 38 | use HTTP::Message; | 
|  | 8 |  |  |  |  | 14 |  | 
|  | 8 |  |  |  |  | 172 |  | 
| 11 | 8 |  |  | 8 |  | 5666 | use Hash::MultiValue; | 
|  | 8 |  |  |  |  | 18065 |  | 
|  | 8 |  |  |  |  | 223 |  | 
| 12 | 8 |  |  | 8 |  | 4373 | use WebService::Simple::Response; | 
|  | 8 |  |  |  |  | 20 |  | 
|  | 8 |  |  |  |  | 201 |  | 
| 13 | 8 |  |  | 8 |  | 5338 | use UNIVERSAL::require; | 
|  | 8 |  |  |  |  | 10695 |  | 
|  | 8 |  |  |  |  | 70 |  | 
| 14 |  |  |  |  |  |  |  | 
| 15 |  |  |  |  |  |  | our $VERSION = '0.25'; | 
| 16 |  |  |  |  |  |  |  | 
| 17 |  |  |  |  |  |  | __PACKAGE__->config( | 
| 18 |  |  |  |  |  |  | base_url        => '', | 
| 19 |  |  |  |  |  |  | response_parser => { module => "XML::Simple" }, | 
| 20 |  |  |  |  |  |  | ); | 
| 21 |  |  |  |  |  |  |  | 
| 22 |  |  |  |  |  |  | sub new { | 
| 23 | 12 |  |  | 12 | 1 | 10538 | my $class    = shift; | 
| 24 | 12 |  |  |  |  | 47 | my %args     = @_; | 
| 25 |  |  |  |  |  |  | my $base_url = delete $args{base_url} | 
| 26 |  |  |  |  |  |  | || $class->config->{base_url} | 
| 27 | 12 |  | 0 |  |  | 55 | || Carp::croak("base_url is required"); | 
| 28 | 12 |  |  |  |  | 88 | $base_url = URI->new($base_url); | 
| 29 | 12 |  | 100 |  |  | 57929 | my $basic_params = delete $args{params} || delete $args{param} || {}; | 
| 30 | 12 |  | 50 |  |  | 78 | my $debug = delete $args{debug} || 0; | 
| 31 |  |  |  |  |  |  |  | 
| 32 |  |  |  |  |  |  | my $response_parser = delete $args{response_parser} | 
| 33 | 12 |  | 66 |  |  | 141 | || $class->config->{response_parser}; | 
| 34 | 12 | 50 | 33 |  |  | 350 | if (   !$response_parser | 
| 35 | 12 |  |  |  |  | 278 | || !eval { $response_parser->isa('WebService::Simple::Parser') } ) | 
| 36 |  |  |  |  |  |  | { | 
| 37 | 12 |  | 33 |  |  | 39 | my $config = $response_parser || $class->config->{response_parser}; | 
| 38 | 12 | 100 |  |  |  | 42 | if ( !ref $config ) { | 
| 39 | 3 |  |  |  |  | 10 | $config = { module => $config }; | 
| 40 |  |  |  |  |  |  | } | 
| 41 | 12 |  |  |  |  | 28 | my $module = $config->{module}; | 
| 42 | 12 | 50 |  |  |  | 50 | if ( $module !~ s/^\+// ) { | 
| 43 | 12 |  |  |  |  | 36 | $module = __PACKAGE__ . "::Parser::$module"; | 
| 44 |  |  |  |  |  |  | } | 
| 45 | 12 | 100 |  |  |  | 105 | if ( !Class::Inspector->loaded($module) ) { | 
| 46 | 8 | 50 |  |  |  | 749 | $module->require or die; | 
| 47 |  |  |  |  |  |  | } | 
| 48 | 12 | 50 |  |  |  | 251 | $response_parser = $module->new( %{ $config->{args} || {} } ); | 
|  | 12 |  |  |  |  | 148 |  | 
| 49 |  |  |  |  |  |  | } | 
| 50 |  |  |  |  |  |  |  | 
| 51 | 12 |  |  |  |  | 34 | my $cache = delete $args{cache}; | 
| 52 | 12 | 50 | 33 |  |  | 58 | if ( !$cache || ref $cache eq 'HASH' ) { | 
| 53 | 12 | 50 |  |  |  | 125 | my $config = ref $cache eq 'HASH' ? $cache : $class->config->{cache}; | 
| 54 | 12 | 50 |  |  |  | 346 | if ($config) { | 
| 55 | 0 | 0 |  |  |  | 0 | if ( !ref $config ) { | 
| 56 | 0 |  |  |  |  | 0 | $config = { module => $config }; | 
| 57 |  |  |  |  |  |  | } | 
| 58 |  |  |  |  |  |  |  | 
| 59 | 0 |  |  |  |  | 0 | my $module = $config->{module}; | 
| 60 | 0 | 0 |  |  |  | 0 | if ( !Class::Inspector->loaded($module) ) { | 
| 61 | 0 | 0 |  |  |  | 0 | $module->require or die; | 
| 62 |  |  |  |  |  |  | } | 
| 63 |  |  |  |  |  |  | $cache = | 
| 64 |  |  |  |  |  |  | $module->new( $config->{hashref_args} | 
| 65 |  |  |  |  |  |  | ? $config->{args} | 
| 66 | 0 | 0 |  |  |  | 0 | : %{ $config->{args} } ); | 
|  | 0 |  |  |  |  | 0 |  | 
| 67 |  |  |  |  |  |  | } | 
| 68 |  |  |  |  |  |  | } | 
| 69 |  |  |  |  |  |  |  | 
| 70 | 12 |  |  |  |  | 97 | my $self = $class->SUPER::new(%args); | 
| 71 | 12 |  |  |  |  | 31 | $self->{base_url}        = $base_url; | 
| 72 | 12 |  |  |  |  | 40 | $self->{basic_params}    = $basic_params; | 
| 73 | 12 |  |  |  |  | 24 | $self->{response_parser} = $response_parser; | 
| 74 | 12 |  |  |  |  | 26 | $self->{cache}           = $cache; | 
| 75 | 12 |  |  |  |  | 22 | $self->{compression}     = delete $args{compression}; | 
| 76 | 12 |  |  |  |  | 22 | $self->{content_type}    = delete $args{content_type}; | 
| 77 | 12 |  |  |  |  | 26 | $self->{croak}           = delete $args{croak}; | 
| 78 | 12 |  |  |  |  | 26 | $self->{debug}           = $debug; | 
| 79 |  |  |  |  |  |  |  | 
| 80 | 12 | 100 | 66 |  |  | 53 | if($self->{content_type} && $self->{content_type} eq 'application/json'){ | 
| 81 | 1 |  |  |  |  | 5 | $self->__init_request_parser_json(); | 
| 82 |  |  |  |  |  |  | }else{ | 
| 83 | 11 |  |  | 0 |  | 56 | $self->{request_parser} = sub { return \$_[0] }; | 
|  | 0 |  |  |  |  | 0 |  | 
| 84 |  |  |  |  |  |  | } | 
| 85 |  |  |  |  |  |  |  | 
| 86 | 12 |  |  |  |  | 44 | return $self; | 
| 87 |  |  |  |  |  |  | } | 
| 88 |  |  |  |  |  |  |  | 
| 89 | 12 |  |  | 12 |  | 864 | sub _agent       { "libwww-perl/$LWP::VERSION+". __PACKAGE__ .'/'.$VERSION } | 
| 90 |  |  |  |  |  |  |  | 
| 91 | 34 |  |  | 34 | 1 | 72 | sub base_url        { $_[0]->{base_url} } | 
| 92 | 34 |  |  | 34 | 1 | 201 | sub basic_params    { $_[0]->{basic_params} } | 
| 93 | 37 |  |  | 37 | 1 | 150 | sub response_parser { $_[0]->{response_parser} } | 
| 94 | 0 |  |  | 0 | 0 | 0 | sub request_parser  { $_[0]->{request_parser} } | 
| 95 | 28 |  |  | 28 | 1 | 49 | sub cache           { $_[0]->{cache} } | 
| 96 |  |  |  |  |  |  |  | 
| 97 |  |  |  |  |  |  | sub __cache_get { | 
| 98 | 14 |  |  | 14 |  | 17 | my $self  = shift; | 
| 99 | 14 |  |  |  |  | 28 | my $cache = $self->cache; | 
| 100 | 14 | 50 |  |  |  | 43 | return unless $cache; | 
| 101 |  |  |  |  |  |  |  | 
| 102 | 0 |  |  |  |  | 0 | my $key = $self->__cache_key(shift); | 
| 103 | 0 |  |  |  |  | 0 | return $cache->get( $key, @_ ); | 
| 104 |  |  |  |  |  |  | } | 
| 105 |  |  |  |  |  |  |  | 
| 106 |  |  |  |  |  |  | sub __cache_set { | 
| 107 | 14 |  |  | 14 |  | 15 | my $self  = shift; | 
| 108 | 14 |  |  |  |  | 28 | my $cache = $self->cache; | 
| 109 | 14 | 50 |  |  |  | 33 | return unless $cache; | 
| 110 |  |  |  |  |  |  |  | 
| 111 | 0 |  |  |  |  | 0 | my $key = $self->__cache_key(shift); | 
| 112 | 0 |  |  |  |  | 0 | return $cache->set( $key, @_ ); | 
| 113 |  |  |  |  |  |  | } | 
| 114 |  |  |  |  |  |  |  | 
| 115 |  |  |  |  |  |  | sub __cache_remove { | 
| 116 | 0 |  |  | 0 |  | 0 | my $self  = shift; | 
| 117 | 0 |  |  |  |  | 0 | my $cache = $self->cache; | 
| 118 | 0 | 0 |  |  |  | 0 | return unless $cache; | 
| 119 |  |  |  |  |  |  |  | 
| 120 | 0 |  |  |  |  | 0 | my $key = $self->__cache_key(shift); | 
| 121 | 0 |  |  |  |  | 0 | return $cache->remove( $key, @_ ); | 
| 122 |  |  |  |  |  |  | } | 
| 123 |  |  |  |  |  |  |  | 
| 124 |  |  |  |  |  |  | sub __cache_key { | 
| 125 | 0 |  |  | 0 |  | 0 | my $self = shift; | 
| 126 | 0 |  |  |  |  | 0 | local $Data::Dumper::Indent   = 1; | 
| 127 | 0 |  |  |  |  | 0 | local $Data::Dumper::Terse    = 1; | 
| 128 | 0 |  |  |  |  | 0 | local $Data::Dumper::Sortkeys = 1; | 
| 129 | 0 |  |  |  |  | 0 | return Digest::MD5::md5_hex( Data::Dumper::Dumper( $_[0] ) ); | 
| 130 |  |  |  |  |  |  | } | 
| 131 |  |  |  |  |  |  |  | 
| 132 |  |  |  |  |  |  | sub __init_request_parser_json { | 
| 133 | 2 |  |  | 2 |  | 3 | my $self = shift; | 
| 134 | 2 |  |  |  |  | 816 | require WebService::Simple::Parser::JSON; | 
| 135 | 2 |  |  |  |  | 11 | my $json_parser = WebService::Simple::Parser::JSON->new(); | 
| 136 | 2 |  |  | 2 |  | 10 | $self->{request_parser_json} = sub { $json_parser->parse_request(@_); } | 
| 137 | 2 |  |  |  |  | 10 | } | 
| 138 |  |  |  |  |  |  |  | 
| 139 |  |  |  |  |  |  | sub request_url { | 
| 140 | 35 |  |  | 35 | 1 | 1115 | my $self = shift; | 
| 141 | 35 |  |  |  |  | 116 | my %args = @_; | 
| 142 |  |  |  |  |  |  |  | 
| 143 | 35 | 100 |  |  |  | 281 | my $uri = ref($args{url}) =~ m/^URI/ ? $args{url}->clone() : URI->new($args{url}); | 
| 144 | 35 | 100 |  |  |  | 468 | if ( my $extra_path = $args{extra_path} ) { | 
| 145 | 13 |  |  |  |  | 77 | $extra_path =~ s!^/!!; | 
| 146 | 13 |  |  |  |  | 46 | $uri->path( $uri->path . $extra_path ); | 
| 147 |  |  |  |  |  |  | } | 
| 148 | 35 | 100 |  |  |  | 573 | if($args{params}) { | 
| 149 | 33 | 100 |  |  |  | 84 | if(ref $args{params} eq 'Hash::MultiValue') { | 
| 150 | 32 |  |  |  |  | 107 | for my $key ($args{params}->keys) { | 
| 151 | 34 |  |  |  |  | 801 | $uri->query_param_append($key, $args{params}->get($key)); | 
| 152 |  |  |  |  |  |  | } | 
| 153 |  |  |  |  |  |  | }else{ | 
| 154 | 1 |  |  |  |  | 3 | $uri->query_form(%{$args{params}}); | 
|  | 1 |  |  |  |  | 9 |  | 
| 155 |  |  |  |  |  |  | } | 
| 156 |  |  |  |  |  |  | } | 
| 157 | 35 |  |  |  |  | 2354 | return $uri; | 
| 158 |  |  |  |  |  |  | } | 
| 159 |  |  |  |  |  |  |  | 
| 160 |  |  |  |  |  |  | sub get { | 
| 161 | 14 |  |  | 14 | 1 | 11733 | my $self = shift; | 
| 162 | 14 |  |  |  |  | 24 | my ($url, $extra) = ("", {}); | 
| 163 |  |  |  |  |  |  |  | 
| 164 | 14 | 100 |  |  |  | 35 | if ( ref $_[0] eq 'HASH' ) { | 
| 165 | 6 |  |  |  |  | 11 | $extra = shift @_; | 
| 166 |  |  |  |  |  |  | } | 
| 167 |  |  |  |  |  |  | else { | 
| 168 | 8 |  |  |  |  | 12 | $url = shift @_; | 
| 169 | 8 | 100 |  |  |  | 20 | if ( ref $_[0] eq 'HASH' ) { | 
| 170 | 4 |  |  |  |  | 13 | $extra = shift @_; | 
| 171 |  |  |  |  |  |  | } | 
| 172 |  |  |  |  |  |  | } | 
| 173 |  |  |  |  |  |  |  | 
| 174 |  |  |  |  |  |  | my $uri = $self->request_url( | 
| 175 |  |  |  |  |  |  | url => $self->base_url, | 
| 176 |  |  |  |  |  |  | extra_path => $url, | 
| 177 | 14 |  |  |  |  | 35 | params => Hash::MultiValue->new(%{$self->basic_params}, %$extra), | 
|  | 14 |  |  |  |  | 28 |  | 
| 178 |  |  |  |  |  |  | ); | 
| 179 |  |  |  |  |  |  |  | 
| 180 | 14 | 50 |  |  |  | 43 | warn "Request URL is $uri\n" if $self->{debug}; | 
| 181 |  |  |  |  |  |  |  | 
| 182 | 14 |  |  |  |  | 165 | my @headers = @_; | 
| 183 | 14 | 50 | 33 |  |  | 42 | unless(defined($self->{compression}) && !$self->{compression}){ | 
| 184 | 14 |  |  |  |  | 35 | my $can_accept = HTTP::Message::decodable(); | 
| 185 | 14 |  |  |  |  | 92277 | push @headers, ('Accept-Encoding' => $can_accept) ; | 
| 186 |  |  |  |  |  |  | } | 
| 187 |  |  |  |  |  |  |  | 
| 188 | 14 |  |  |  |  | 17 | my $response; | 
| 189 | 14 |  |  |  |  | 47 | $response = $self->__cache_get( [ $uri, @headers ] ); | 
| 190 | 14 | 50 |  |  |  | 33 | if ($response) { | 
| 191 | 0 | 0 |  |  |  | 0 | if ($response->isa('WebService::Simple::Response')) { # backward compatibility | 
| 192 | 0 |  |  |  |  | 0 | return $response; | 
| 193 |  |  |  |  |  |  | } else { | 
| 194 | 0 |  |  |  |  | 0 | return WebService::Simple::Response->new_from_response( | 
| 195 |  |  |  |  |  |  | response => $response, | 
| 196 |  |  |  |  |  |  | parser => $self->response_parser | 
| 197 |  |  |  |  |  |  | ); | 
| 198 |  |  |  |  |  |  | } | 
| 199 |  |  |  |  |  |  | } | 
| 200 |  |  |  |  |  |  |  | 
| 201 | 14 |  |  |  |  | 52 | $response = $self->SUPER::get( $uri, @headers ); | 
| 202 |  |  |  |  |  |  |  | 
| 203 | 14 | 50 |  |  |  | 10932 | if ( $response->is_success ) { | 
| 204 | 14 |  |  |  |  | 112 | $self->__cache_set( [ $uri, @headers ], $response ); | 
| 205 | 14 |  |  |  |  | 34 | $response = WebService::Simple::Response->new_from_response( | 
| 206 |  |  |  |  |  |  | response => $response, | 
| 207 |  |  |  |  |  |  | parser   => $self->response_parser | 
| 208 |  |  |  |  |  |  | ); | 
| 209 |  |  |  |  |  |  | }else{ | 
| 210 | 0 | 0 | 0 |  |  | 0 | Carp::croak("request to $uri failed") unless defined($self->{croak}) && !$self->{croak}; | 
| 211 |  |  |  |  |  |  | } | 
| 212 |  |  |  |  |  |  |  | 
| 213 | 14 |  |  |  |  | 85 | return $response; | 
| 214 |  |  |  |  |  |  | } | 
| 215 |  |  |  |  |  |  |  | 
| 216 |  |  |  |  |  |  | sub post { | 
| 217 | 20 |  |  | 20 | 1 | 14476 | my $self = shift; | 
| 218 | 20 |  |  |  |  | 44 | my ( $url, $extra ) = ( '', {} ); | 
| 219 |  |  |  |  |  |  |  | 
| 220 | 20 | 100 |  |  |  | 78 | if ( ref $_[0] eq 'HASH' ) { # post(\%arg [, @header ]) | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
| 221 | 10 |  |  |  |  | 19 | $extra = shift @_; | 
| 222 |  |  |  |  |  |  | } | 
| 223 |  |  |  |  |  |  | elsif ( ref $_[1] eq 'HASH' ) { # post($url, \%arg [, @header ]) | 
| 224 | 5 |  |  |  |  | 9 | $url = shift @_; | 
| 225 | 5 |  |  |  |  | 10 | $extra = shift @_; | 
| 226 |  |  |  |  |  |  | } | 
| 227 |  |  |  |  |  |  | elsif ( @_ % 2 ) { # post($url [, @header ]) | 
| 228 | 2 |  |  |  |  | 6 | $url = shift @_; | 
| 229 |  |  |  |  |  |  | } | 
| 230 |  |  |  |  |  |  |  | 
| 231 | 20 |  |  |  |  | 47 | my @headers = @_; | 
| 232 | 20 | 50 | 33 |  |  | 61 | unless(defined($self->{compression}) && !$self->{compression}){ | 
| 233 | 20 |  |  |  |  | 57 | my $can_accept = HTTP::Message::decodable(); | 
| 234 | 20 |  |  |  |  | 54363 | push @headers, ('Accept-Encoding' => $can_accept) ; | 
| 235 |  |  |  |  |  |  | } | 
| 236 | 20 |  |  |  |  | 66 | my %headers = @headers; | 
| 237 |  |  |  |  |  |  |  | 
| 238 |  |  |  |  |  |  | # Content-Type tells us where "extra params" go: form-urlencoded -> $uri / json/xml -> $content | 
| 239 | 20 |  |  |  |  | 26 | my ($uri,$response); | 
| 240 |  |  |  |  |  |  |  | 
| 241 | 20 | 100 | 66 |  |  | 129 | if( ($self->{content_type} && $self->{content_type} eq 'application/json') || ($headers{'Content-Type'} && $headers{'Content-Type'} eq 'application/json') ){ | 
|  |  |  | 66 |  |  |  |  | 
|  |  |  | 66 |  |  |  |  | 
| 242 | 2 | 100 |  |  |  | 7 | $self->__init_request_parser_json() unless $self->{request_parser_json}; | 
| 243 |  |  |  |  |  |  |  | 
| 244 | 2 |  |  |  |  | 7 | $uri = $self->request_url( | 
| 245 |  |  |  |  |  |  | url => $self->base_url, | 
| 246 |  |  |  |  |  |  | extra_path => $url, | 
| 247 |  |  |  |  |  |  | # params => Hash::MultiValue->new(%{$self->basic_params}, %$extra), # this'll go to content | 
| 248 |  |  |  |  |  |  | ); | 
| 249 |  |  |  |  |  |  | # $uri->query_form(undef); # we'll leave all params on the url | 
| 250 |  |  |  |  |  |  |  | 
| 251 | 2 |  |  |  |  | 11 | my $req = HTTP::Request->new(POST => $uri, \@headers); | 
| 252 | 2 |  |  |  |  | 250 | $req->content_type('application/json'); | 
| 253 | 2 |  |  |  |  | 61 | $req->content($self->{request_parser_json}->({ %{$self->basic_params}, %$extra })); | 
|  | 2 |  |  |  |  | 5 |  | 
| 254 | 2 |  |  |  |  | 38 | $response = $self->SUPER::request($req); | 
| 255 |  |  |  |  |  |  | }else{ | 
| 256 |  |  |  |  |  |  | $uri = $self->request_url( | 
| 257 |  |  |  |  |  |  | url => $self->base_url, | 
| 258 |  |  |  |  |  |  | extra_path => $url, | 
| 259 | 18 |  |  |  |  | 47 | params => Hash::MultiValue->new(%{$self->basic_params}, %$extra), | 
|  | 18 |  |  |  |  | 39 |  | 
| 260 |  |  |  |  |  |  | ); | 
| 261 | 18 |  |  |  |  | 55 | my $content = $uri->query_form_hash(); | 
| 262 | 18 |  |  |  |  | 923 | $uri->query_form(undef); | 
| 263 |  |  |  |  |  |  |  | 
| 264 | 18 | 50 |  |  |  | 520 | push(@headers, 'Content-Type' => $self->{content_type}) if $self->{content_type}; | 
| 265 |  |  |  |  |  |  |  | 
| 266 | 18 |  |  |  |  | 66 | $response = $self->SUPER::post( $uri, $content, @headers ); | 
| 267 |  |  |  |  |  |  | } | 
| 268 |  |  |  |  |  |  |  | 
| 269 | 20 | 50 |  |  |  | 17535 | if ( $response->is_success ) { | 
| 270 | 20 |  |  |  |  | 154 | $response = WebService::Simple::Response->new_from_response( | 
| 271 |  |  |  |  |  |  | response => $response, | 
| 272 |  |  |  |  |  |  | parser   => $self->response_parser | 
| 273 |  |  |  |  |  |  | ); | 
| 274 |  |  |  |  |  |  | }else{ | 
| 275 | 0 | 0 | 0 |  |  | 0 | Carp::croak("request to $uri failed") unless defined($self->{croak}) && !$self->{croak}; | 
| 276 |  |  |  |  |  |  | } | 
| 277 |  |  |  |  |  |  |  | 
| 278 | 20 |  |  |  |  | 117 | return $response; | 
| 279 |  |  |  |  |  |  | } | 
| 280 |  |  |  |  |  |  |  | 
| 281 |  |  |  |  |  |  | 1; | 
| 282 |  |  |  |  |  |  |  | 
| 283 |  |  |  |  |  |  | __END__ |