-
Notifications
You must be signed in to change notification settings - Fork 63
Example Perl Client
Magali Ruffier edited this page Jul 29, 2016
·
6 revisions
#Used by the basic clients
requires 'JSON';
requires 'JSON::XS';
requires 'HTTP::Tiny';
# Used by the mojo client
requires 'Mojo';
#!/usr/bin/env perl
use strict;
use warnings;
use HTTP::Tiny;
use Time::HiRes;
use JSON;
my $http = HTTP::Tiny->new();
my $server = 'http://rest.ensembl.org';
my $global_headers = { 'Content-Type' => 'application/json' };
my $last_request_time = Time::HiRes::time();
my $request_count = 0;
run();
sub run {
my ($species, $symbol) = @ARGV;
$species ||= 'human';
$symbol ||= 'BRAF';
my $variants = get_variants($species, $symbol);
foreach my $v (@{$variants}) {
printf("%s:%d-%d:%d ==> %s (%s)\n", $v->{seq_region_name}, $v->{start}, $v->{end}, $v->{strand}, $v->{id}, $v->{consequence_type});
}
return;
}
sub get_variants {
my ($species, $symbol) = @_;
my $genes = perform_json_action("/xrefs/symbol/${species}/${symbol}", {object_type => 'gene'});
if(! @{$genes}) {
die "No genes found for symbol $symbol";
}
my $gene_stable_id = $genes->[0]->{id};
my $variants = perform_json_action("/overlap/id/${gene_stable_id}", {feature => 'variation'});
return $variants;
}
sub perform_json_action {
my ($endpoint, $parameters) = @_;
my $headers = $global_headers;
my $content = perform_rest_action($endpoint, $parameters, $headers);
return {} unless $content;
my $json = decode_json($content);
return $json;
}
sub perform_rest_action {
my ($endpoint, $parameters, $headers) = @_;
$parameters ||= {};
$headers ||= {};
$headers->{'Content-Type'} = 'application/json' unless exists $headers->{'Content-Type'};
if($request_count == 15) { # check every 15
my $current_time = Time::HiRes::time();
my $diff = $current_time - $last_request_time;
# if less than a second then sleep for the remainder of the second
if($diff < 1) {
Time::HiRes::sleep(1-$diff);
}
# reset
$last_request_time = Time::HiRes::time();
$request_count = 0;
}
my $url = $server.$endpoint;
if(%{$parameters}) {
my @params;
foreach my $key (keys %{$parameters}) {
my $value = $parameters->{$key};
push(@params, "$key=$value");
}
my $param_string = join(';', @params);
$url.= '?'.$param_string;
}
my $response = $http->get($url, {headers => $headers});
my $status = $response->{status};
if(!$response->{success}) {
# Quickly check for rate limit exceeded & Retry-After (lowercase due to our client)
if($status == 429 && exists $response->{headers}->{'retry-after'}) {
my $retry = $response->{headers}->{'retry-after'};
Time::HiRes::sleep($retry);
# After sleeping see that we re-request
return perform_rest_action($endpoint, $parameters, $headers);
}
else {
my ($status, $reason) = ($response->{status}, $response->{reason});
die "Failed for $endpoint! Status code: ${status}. Reason: ${reason}\n";
}
}
$request_count++;
if(length $response->{content}) {
return $response->{content};
}
return;
}
#!/usr/bin/env perl
use strict;
use warnings;
use Mojo::UserAgent;
use Mojo::URL;
use JSON;
my $ua = Mojo::UserAgent->new();
# $ua->proxy->detect;
my $server = 'http://rest.ensembl.org';
my $last_request_time = Time::HiRes::time();
my $request_count = 0;
run();
sub run {
my ($species, $symbol) = @ARGV;
$species ||= 'human';
$symbol ||= 'BRAF';
my $variants = get_variants($species, $symbol);
foreach my $v (@{$variants}) {
printf("%s:%d-%d:%d ==> %s (%s)\n", $v->{seq_region_name}, $v->{start}, $v->{end}, $v->{strand}, $v->{id}, $v->{consequence_type});
}
return;
}
sub get_variants {
my ($species, $symbol) = @_;
my $genes = perform_json_action("/xrefs/symbol/${species}/${symbol}", {object_type => 'gene'});
if(! @{$genes}) {
die "No genes found for symbol $symbol";
}
my $gene_stable_id = $genes->[0]->{id};
my $variants = perform_json_action("/overlap/id/${gene_stable_id}", {feature => 'variation'});
return $variants;
}
sub perform_json_action {
my ($endpoint, $parameters, $headers) = @_;
$parameters ||= {};
$headers ||= {};
if($request_count == 15) { # check every 15
my $current_time = Time::HiRes::time();
my $diff = $current_time - $last_request_time;
# if less than a second then sleep for the remainder of the second
if($diff < 1) {
Time::HiRes::sleep(1-$diff);
}
# reset
$last_request_time = Time::HiRes::time();
$request_count = 0;
}
# Build the URL
my $url = Mojo::URL->new();
$url->scheme('http');
$url->host($server);
$url->path($endpoint);
$url->query($parameters);
my $url_string = $url->to_string();
# Do the get
$headers->{'Content-Type'} = 'application/json' unless exists $headers->{'Content-Type'};
my $tx = $ua->get($url_string => $headers);
if (my $res = $tx->success) {
# you can use mojo's internal JSON parser but JSON::XS::decode_json() is faster
# return $res->json;
return decode_json($res->body);
}
my ($err, $code) = $tx->error; #Codes mean HTTP errors
if($code && $code == 429 && $tx->res->headers->header('Retry-After')) {
my $retry = $tx->res->headers->header('Retry-After');
Time::HiRes::sleep($retry);
return perform_json_action($endpoint, $parameters, $headers);
}
warn $code ? "$code response: $err" : "Connection error: $err";
return {};
}