|
51
|
0 |
0 |
0 |
eval {
do {
my $code = $self->can("__$method") || throw("Invalid $name service method", {'method', $method}, 1);
return &$code($self, $args)
}
} || (ref $@ eq 'HASH' && $@->{'error'} ? $@ : {'error', "Trouble running $name service method", 'service', $name}) |
|
145
|
5 |
0 |
0 |
eval {
do {
_decode_utf8_recurse($args) if $enc;
$req = eval {
do {
$self->json->encode($args)
}
} || throw("Trouble encoding $name service json", {'msg', $@}, 1);
my $sign = defined $pass ? do {
my $t = int $begin;
'X-Respite-Auth: ' . (&$val('md5_pass') ? md5_hex($pass) : md5_hex("${pass}:${t}:${url}:" . md5_hex($req)) . ":$t") . "\r\n"
} : '';
$cookie = $cookie ? "Cookie: $cookie\r\n" : '';
my $sock;
my $i = 0;
while (++$i) {
$sock = $no_ssl ? 'IO::Socket::INET'->new("${host}:$port") : 'IO::Socket::SSL'->new('PeerAddr', $host, 'PeerPort', $port, 'SSL_verify_mode', &$val('ssl_verify_mode', 0));
last if $sock or not $retry or &Time::HiRes::time() - $begin > 3;
&Respite::Client::sleep(0.5);
};
unless ($sock) {
throw("Could not connect to $name service", {'host', $host, 'port', $port, 'url', $url, 'msg', !$no_ssl && ($IO::Socket::SSL::SSL_ERROR || $!), 'detail', "$@", 'ssl', !$no_ssl, 'tries', $i});
};
my $out = "POST $url HTTP/1.0\r\n$cookie${sign}Host: $host\r\nContent-length: " . length($req) . "\r\nContent-type: application/json\r\n\r\n$req";
warn 'DEBUG_Respite: Connected to http' . ($no_ssl ? '' : 's') . "://${host}:$port/\n$out\n" if $ENV{'DEBUG_Respite'};
print $sock $out;
my($len, $type, $line);
throw("Got non-200 status from $name service", {'status', $line, 'url', $url}) unless $line = readline $sock and $line =~ m[^HTTP/\S+ 200\b];
while (defined($line = readline $sock)) {
throw('Failed to find line termination', {'line', $line}) unless $line =~ s/\r?\n$//;
last if $line eq '';
my($key, $val) = split(/\s*:\s*/, $line, 2);
$head{$key} = $head{$key} ? ref $head{$key} ? [@{$head{$key};}, $val] : [$head{$key}, $val] : $val;
$len = $val =~ /^\d+$/ ? $val : throw('Invalid content length', {'h', \%head}) if lc $key eq 'content-length';
};
throw("Failed to find content length in $name service response") unless $len;
throw("Content too large in $name service", {'length', $len}) if $len > 100000000;
my $data = '';
while (1) {
throw('Failed to read bytes', {'needed', $len, 'got', length $data}) unless read $sock, $data, $len, length $data;
last if length $data >= $len;
};
close $sock;
alarm $old;
throw("Invalid $name service json object string") unless $data =~ /^\s*\{/;
my $resp = eval {
do {
$self->json->decode($data)
}
} || throw("Failed to decode $name service json response data", {'msg', $@});
_encode_utf8_recurse($resp) if $enc;
$resp
}
} || do {
alarm $old;
+{'error', "Failed to get valid $name service response: $@"}
} |