RESTを介したWebサービスの相互運用性

最新のWebサービスを開発する場合、いくつかの異種システムのシンプルで透過的な相互作用をどのように提供するかという問題がしばしば発生します。 幸いなことに、幅広い選択肢があります。SOAPCORBADCE / RPC 、そしてもちろんRESTです。 それに基づいたクロスプラットフォームAPIの作成について説明します。



どうしてですか?



確かに、1つのツール(Perl(+好みのフレームワーク)またはRails)を選択して、その上ですべてを実行できる場合、なぜ「庭を囲う」と異種システムを使用するのでしょうか。 ほぼ同じ理由で、溝付きネジにはマイナスドライバーを使用し、プラスネジにはプラスドライバーを使用します。逆も同様です(もちろん可能ですが、効果的ではありません)。 各ツールは、特定のタスクセットにより適しています。



リモートでインストールされたエージェントを使用して情報を収集するWebサービスがあるとします。 これがボットネットではなく(現在は異なる動作をする)、YouTubeなどのオンラインリソースからビデオコンテンツをダウンロードするシステムであるとします。



チャネルは常に良好であるとは限らず、オペレーターは時々 スロットリングを行います。 しかし、通常のHTTP / FTPを介して高速で既製のファイルをダウンロードするために「エージェント」にタスクを与えるのは良いことです。



そのため、シンプルで便利なため、メインWebサービスはRailsで開発し、ほとんどすべてのUnixおよび一部のWindowsサーバーで使用可能な言語(Perl)でエージェントを非常に「薄く」するのが理にかなっています。



どうする



記事の冒頭で述べたように、現在、サービス間にAPIを実装するための多くのプロトコルがあります。 この場合、以前は考えもせず、古典的なSOAP(本質的にはXML + HTTP)を使用していました。 幸いなことに、 PerlRailsの 両方に適した実装ツールあります



しかし、今ではRESTful APIがますます人気を集めており、それには正当な理由があります。 スキーム、定義、追加のWSDLファイル、その他の困難は必要ありません。 このアプローチの本質は、HTTPコマンド(GET、PUT、POST、DELETE)を対応するURIと組み合わせて使用​​することです。 コマンドとURIに応じて、アクションが実行されます。 応答には同じHTTP応答が使用されます。 詳細については、記号と例を使用して、 こちらをご覧ください



この例では、Perlがサーバーとして機能し、Railsがクライアントとして機能します。

それで、何を実装するのですか?



Perl側


モジュールなしのPerl自体は非常に限られたツールです。 したがって、すべての長所と便利さを使用するには、 Mojoliciousモジュールが必要です。Mojoliciousモジュールは、「Perlプログラミング言語用の次世代Webフレームワーク」として位置付けられています。



それに基づいて、RESTfulサーバーとRESTfulクライアントの両方を作成できます。



Rails側


最近まで、このイデオロギーがフレームワークに頭から足まで浸透しているという事実にもかかわらず、RailsにはサードパーティのサービスとのREST対話のための通常のメカニズムがありませんでした。 したがって、 さまざまな成功の度合いでこの問題を解決するために、 さまざまな GEMが作成されました。



幸い、組み込みのRailsメカニズム、つまりActiveResourceクラスを完全に使用できるようになりました。これにより、 ActiveRecordとほぼ同じ方法でリモートサービスを操作できます。



方法





Perl側


Perl側に多くのDownloadsオブジェクトがあり、Rails側でそれらを使用して次のことを実行するとします。



Mojoliciousを使用すると、タスク用のRESTful Webサービスを非常に簡単に作成できます。



#!/usr/bin/perl -w use Mojolicious::Lite; #      #     /  #   : URI     my $downloads = []; foreach my $id (0..10) { $downloads->[$id] = { 'id' => $id, 'uri' => "http://site.com/download_$id", 'name' => "Video $id", 'size' => (int(rand(10000)) + 1) * 1024 }; } #    - #  (create) post '/downloads/' => sub { my $self = shift; #    Rails    JSON # ,    my $params = Mojo::JSON->decode($self->req->body)->{'download'}; #      id  #      my $id = $#{ $downloads } + 1; my $uri = $params->{'uri'} || 'http://localhost/video.mp4'; my $name = $params->{'name'} || "Video $id"; my $size = $params->{'size'} || (int(rand(10000)) + 1) * 1024; $downloads->[$id] = { 'id' => $id, 'uri' => $uri, 'name' => $name, 'size' => $size }; #       $self->render_json($downloads->[$id]); }; #    (index) get '/downloads' => sub { my $self = shift; $self->render_json($downloads); }; #      (find/show) get '/downloads/:id' => sub { my $self = shift; my $id = $self->param('id'); if (!exists($downloads->[$id])) { #     - 404 $self->render_not_found; } else { #  -   $self->render_json($downloads->[$id]); } }; #  (update) put '/downloads/:id' => sub { my $self = shift; my $params = Mojo::JSON->decode($self->req->body)->{'download'}; my $id = $self->param('id'); my $uri = $params->{'uri'} || 'http://localhost/video.mp4'; my $name = $params->{'name'} || "Video $id"; my $size = $params->{'size'} || (int(rand(10000)) + 1) * 1024; if (!exists($downloads->[$id])) { $self->render_not_found; } else { $downloads->[$id] = { 'id' => $id, 'uri' => $uri, 'name' => $name, 'size' => $size }; $self->render_json($downloads->[$id]); } }; #  (delete) del '/downloads/:id' => sub { my $self = shift; my $id = $self->param('id'); if (!exists($downloads->[$id])) { $self->render_not_found; } else { delete $downloads->[$id]; #  HTTP 200 OK -    $self->rendered; } }; #    -   post '/downloads/:id/start' => sub { my $self = shift; my $id = $self->param('id'); if (!exists($downloads->[$id])) { $self->render_not_found; } else { $self->rendered; } }; #    app->start;
      
      







サービスを開始します。 標準の3000はRailsインストールと競合する可能性が高いため、ポート3001を使用します。

 ./restful-server.pl daemon --listen=http://*:3001
      
      







Rails側


この例の一部として、すべてのRailsは、RESTful PerlサーバーでActiveResourceクラスの機能をチェックすることになります。



目的のクラスを作成します。

 class Download < ActiveResource::Base #  Perl- self.site = 'http://localhost:3001' end
      
      







これで、このクラスでRailsの通常のアクションを実行できます。



すべてのオブジェクトを検索:

 > Download.find(:all) => [#<Download:0x00000004b77060 @attributes={"name"=>"Video 0", "id"=>"0", "size"=>7654400, "uri"=>"http://site.com/download_0"}, @prefix_options={}, @persisted=true>, #<Download:0x0000000446f740 @attributes={"name"=>"Video 1", "id"=>"1", "size"=>8672256, "uri"=>"http://site.com/download_1"}, @prefix_options={}, @persisted=true>, #<Download:0x0000000446d300 @attributes={"name"=>"Video 2", "id"=>"2", "size"=>5931008, "uri"=>"http://site.com/download_2"}, @prefix_options={}, @persisted=true>, #<Download:0x0000000446c888 @attributes={"name"=>"Video 3", "id"=>"3", "size"=>2273280, "uri"=>"http://site.com/download_3"}, @prefix_options={}, @persisted=true>, #<Download:0x000000045c7c50 @attributes={"name"=>"Video 4", "id"=>"4", "size"=>8466432, "uri"=>"http://site.com/download_4"}, @prefix_options={}, @persisted=true>, #<Download:0x000000045c6ee0 @attributes={"name"=>"Video 5", "id"=>"5", "size"=>7057408, "uri"=>"http://site.com/download_5"}, @prefix_options={}, @persisted=true>, #<Download:0x000000045c5d60 @attributes={"name"=>"Video 6", "id"=>"6", "size"=>2351104, "uri"=>"http://site.com/download_6"}, @prefix_options={}, @persisted=true>, #<Download:0x00000004116058 @attributes={"name"=>"Video 7", "id"=>"7", "size"=>5640192, "uri"=>"http://site.com/download_7"}, @prefix_options={}, @persisted=true>, #<Download:0x00000004114320 @attributes={"name"=>"Video 8", "id"=>"8", "size"=>9701376, "uri"=>"http://site.com/download_8"}, @prefix_options={}, @persisted=true>, #<Download:0x0000000411b080 @attributes={"name"=>"Video 9", "id"=>"9", "size"=>9717760, "uri"=>"http://site.com/download_9"}, @prefix_options={}, @persisted=true>, #<Download:0x00000004a46330 @attributes={"name"=>"Video 10", "id"=>"10", "size"=>6734848, "uri"=>"http://site.com/download_10"}, @prefix_options={}, @persisted=true>]
      
      







特定のオブジェクトを検索します。

 > Download.find(5) => #<Download:0x00000004aa5420 @attributes={"name"=>"Video 5", "id"=>"5", "size"=>7057408, "uri"=>"http://site.com/download_5"}, @prefix_options={}, @persisted=true>
      
      







存在しないオブジェクトを検索します。 render_not_foundの仕組みに注意してください

 > Download.find(100) ActiveResource::ResourceNotFound: Failed. Response code = 404. Response message = Not Found.
      
      







オブジェクトの作成:

 > download = Download.new => #<Download:0x00000004802380 @attributes={}, @prefix_options={}, @persisted=false> > download.name = "New Video" => "New Video" > download.uri = "http://site.com/video.mp4" => "http://site.com/video.mp4" > download.size = 23452363 => 23452363 > download.save => true > Download.last => #<Download:0x000000049408f0 @attributes={"name"=>"New Video", "id"=>11, "size"=>23452363, "uri"=>"http://site.com/video.mp4"}, @prefix_options={}, @persisted=true>
      
      







オブジェクトの変更:

 > download = Download.find(5) => #<Download:0x0000000473ee30 @attributes={"name"=>"Video 5", "id"=>"5", "size"=>7057408, "uri"=>"http://site.com/download_5"}, @prefix_options={}, @persisted=true> > download.name = "New Video 5" => "New Video 5" > download.save => true > Download.find(5) => #<Download:0x000000043dade8 @attributes={"name"=>"New Video 5", "id"=>"5", "size"=>7057408, "uri"=>"http://site.com/download_5"}, @prefix_options={}, @persisted=true>
      
      







オブジェクトを削除:

 > Download.find(5).destroy => #<Net::HTTPOK 200 OK readbody=true> > Download.find(5) ActiveResource::ResourceNotFound: Failed. Response code = 404. Response message = Not Found.
      
      







非標準関数の呼び出し:

 > Download.find(1).post(:start) => #<Net::HTTPOK 200 OK readbody=true>
      
      







次は?



この例は、次の方向で開発できます。





使用バージョン






All Articles