#Used by the basic clientsrequires'JSON';requires'JSON::XS';requires'HTTP::Tiny';# Used by the mojo clientrequires'Mojo';
HTTP::Tiny
#!/usr/bin/env perlusestrict;usewarnings;useHTTP::Tiny;useTime::HiRes;useJSON;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);foreachmy$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'unlessexists$headers->{'Content-Type'};if($request_count==15){# check every 15my$current_time=Time::HiRes::time();my$diff=$current_time-$last_request_time;# if less than a second then sleep for the remainder of the secondif($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;foreachmy$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-requestreturnperform_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;}
Mojo Client
#!/usr/bin/env perlusestrict;usewarnings;useMojo::UserAgent;useMojo::URL;useJSON;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);foreachmy$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 15my$current_time=Time::HiRes::time();my$diff=$current_time-$last_request_time;# if less than a second then sleep for the remainder of the secondif($diff<1){Time::HiRes::sleep(1-$diff);}# reset$last_request_time=Time::HiRes::time();$request_count=0;}# Build the URLmy$url=Mojo::URL->new();$url->scheme('http');$url->host('beta.rest.ensembl.org');$url->path($endpoint);$url->query($parameters);my$url_string=$url->to_string();# Do the get$headers->{'Content-Type'}='application/json'unlessexists$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;returndecode_json($res->body);}my($err,$code)=$tx->error;#Codes mean HTTP errorsif($code&&$code==429&&$tx->res->headers->header('Retry-After')){my$retry=$tx->res->headers->header('Retry-After');Time::HiRes::sleep($retry);returnperform_json_action($endpoint,$parameters,$headers);}warn$code?"$code response: $err":"Connection error: $err";return{};}