Ruby
 Computer >> コンピューター >  >> プログラミング >> Ruby

RubyでHTTPリクエストを送る完全ガイド – net/httpからFaradayまで徹底解説

Webサイトから情報を取得したい、フォームを送信したい、ファイルをアップロードしたい——そんな場面では、HTTPリクエストを送信し、そのレスポンスを処理する必要があります。

この記事では、以下の内容を学ぶことができます。

  • net/httpを使ったシンプルなHTTPリクエストの送信方法
  • SSLリクエストの送信方法
  • POSTリクエストによるデータ送信方法
  • カスタムヘッダーの送信方法
  • 状況に応じた最適なHTTPクライアントの選び方

それでは始めましょう!

HTTPリクエストの基本的な送信方法

Rubyには標準で「net/http」というHTTPクライアントが組み込まれており、あらゆる種類のリクエストを送信できます。

net/httpの使用例は次のとおりです。

require 'net/http'

Net::HTTP.get('example.com', '/index.html')

これを実行すると、ページのHTMLコンテンツが文字列として返されます。しかし、実際にはHTMLの中身だけでなく、HTTPステータスコードも知りたいことが多いはずです。ステータスコードがわからなければ、リクエストが成功したのか失敗したのか判断できません。

ステータスコードを取得するには、次のようにします。

response = Net::HTTP.get_response('example.com', '/')

response.code
# 200

レスポンスの本文が必要な場合は、bodyメソッドを呼び出します。

response.body

HTTParty Gemの使い方

Rubyには開発を楽にしてくれるGemが数多く存在します。そのひとつが「httparty」です。

使い方はこちら

require 'httparty'

response = HTTParty.get('https://example.com')

response.code
# 200

response.body
# ...

HTTP用Gemを使うメリットは以下のとおりです。

  • 使い方がシンプル
  • get_responseのような別メソッドが不要で、getだけでレスポンスオブジェクトが取得できる
  • SSLリクエストが透過的に処理される(次のセクションで解説)

SSLリクエストの送信方法

net/httpでSSLリクエストを送ろうとすると…

Net::HTTP.get_response("example.com", "/", 443)

次のようなエラーが発生します。

Errno::ECONNRESET: Connection reset by peer

正しくは、次のように書く必要があります。

net = Net::HTTP.new("example.com", 443)

net.use_ssl = true
net.get_response("/")

手間を省きたいなら、Gemを使うのがおすすめです。

POSTリクエストでデータを送信する方法

GETリクエストは情報を取得するために使われます。画像やCSS、JavaScriptのダウンロードなどがその例です。

一方、情報を送信したい場合はPOSTリクエストを使用します。

以下はその例です。

HTTParty.post("https://example.com/login", body: { user: "test@example.com", password: "chunky_bacon" })

ファイルをアップロードするにはマルチパートリクエストが必要ですが、HTTPartyはこれに対応していません。代わりにrest-client Gemが使えます。

require 'rest-client'

RestClient.post '/profile', file: File.new('photo.jpg', 'rb')

または、Faraday Gemを使う方法もあります。

require 'faraday'

conn =
Faraday.new do |f|
  f.request :multipart
  f.request :url_encoded

  f.adapter :net_http
end

file_io = Faraday::UploadIO.new('photo.jpg', 'image/jpeg')

conn.post('https://example.com/profile', file: file_io)

カスタムHTTPヘッダーの送信方法

HTTPリクエストにはカスタムヘッダーを含めることができます。これにより、リクエストに追加データを添付できます。具体的には以下のようなものです。

  • Cookie
  • User-Agent
  • キャッシュ設定
  • Content-Type
  • Accept(JSONなどの形式を指定)

やり方は次のとおりです。

Faraday.new('https://example.com', headers: { 'User-Agent' => 'test' }).get

ここではnewでFaradayオブジェクトを生成し、それに対してgetを呼び出しています。

次のような書き方も可能です

Faraday.post(
  "https://example.com/login/oauth/access_token",
  URI.encode_www_form(
    code: params[:code],
    client_id: ENV["example_client_id"],
    client_secret: ENV["example_client_secret"],
  ),
  {
    "Content-Type" => "application/x-www-form-urlencoded",
    "Accept" => "application/json"
  }
)

これはOAuth系のリクエストに特に便利な書き方です。

最適なRuby HTTPクライアントの選び方

Rubyには多数のHTTPクライアントが存在しますが、どれを選べばよいのでしょうか? 判断材料として、主要Gemの比較表を用意しました。

こちらがその表です

リポジトリ スター数 直近コミット数 最終コミット日 最新リリース日 作成日
lostisland/faraday 4817 26 2020-07-09 09:43:09 2020-03-29 13:46:47 2009-12-10 17:14:55
rest-client/rest-client 4913 0 2019-08-25 21:41:17 2019-08-21 22:50:21 2009-12-07 19:34:29
typhoeus/typhoeus 3739 2 2020-05-17 19:33:54 2020-01-15 16:24:17 2009-02-18 23:14:50
jnunemaker/httparty 5220 11 2020-06-10 18:40:13 2020-06-10 18:40:13 2008-07-28 20:55:11
excon/excon 1018 14 2020-06-30 11:30:12 2020-06-17 12:07:02 2009-10-25 17:50:46
httprb/http 2623 13 2020-03-30 12:34:38 2020-02-26 17:33:37 2011-10-06 04:19:10

人気度やメンテナンス状況を確認することは、選択肢を評価するための良い第一歩です。では、それぞれの技術的な違いは何なのでしょうか?

実は、多くのGemはnet/httpライブラリのラッパーです。

  • excon
  • httparty
  • rest-client

一方、Faradayはアダプター型のGemで、異なる実装を切り替えて使えるのが特徴です。そしてTyphoeusは、C言語のlibcurlライブラリのラッパーとなっています。

マルチスレッド処理ならTyphoeus

Typhoeusは、並行処理のコードを一切書かずに同時リクエストをサポートします。1秒あたりのリクエスト数を最大化したい場合、Typhoeusが最適な選択肢となるでしょう。

Typhoeusをマルチスレッドで使う例:

require 'typhoeus'

hydra   = Typhoeus::Hydra.hydra
request = Typhoeus::Request.new("https://www.rubyguides.com")

hydra.queue(request)
hydra.queue(request)

hydra.run

柔軟性重視ならFaraday

Faradayは、net/httpからTyphoeus、さらにはrest-clientまで、同一のインターフェースで任意の実装を選択できます。デフォルトはnet/httpですが、次のように変更可能です。

Faraday.default_adapter = :typhoeus

Faradayのもうひとつの魅力は、ミドルウェアをサポートしている点です。ミドルウェアとは、リクエストやレスポンスを特定の方法で加工するプラグインのようなものです。

require 'faraday_middleware'

client =
  Faraday.new do |f|
    f.response :json
    f.adapter :net_http
  end

client.get('https://api.github.com/repos/vmg/redcarpet/issues')

このミドルウェアにより、レスポンスが自動的にJSONとしてパースされます。逆にJSONを送信したい場合は、f.response :jsonの代わりにf.request :jsonを使用してください。

おまけ:HTTPリクエストのデバッグ方法

コードが実際に何を送信しているのか正確に確認し、正しく動作しているか検証したい場合に使える、ちょっとしたテクニックを紹介します。

次のワンライナーをご覧ください。

ruby -rsocket -e "trap('SIGINT') { exit }; Socket.tcp_server_loop(8080) { |s,_| puts s.readpartial(1024); puts; s.puts 'HTTP/1.1 200'; s.close }

これはポート8080でサーバーを起動し、受信したすべての内容を出力した後、HTTPステータスコードを返して接続を閉じます。localhost:8080宛てにリクエストを送れば、その内容を確認できます。

実行例はこちら

Faraday.new('https://localhost:8080', headers: { 'User-Agent' => 'test', 'foo' => '1234' }).get

# GET / HTTP/1.1
# User-Agent: test
# Foo: 1234
# Accept-Encoding: gzip;q=1.0,deflate;q=0.6,identity;q=0.3
# Accept: */*
# Connection: close
# Host: localhost:8080

その他の選択肢としては、httplogのようなGemや、mitmproxyのようなツールを利用する方法もあります。

まとめ

この記事では、情報を取得する基本的なGETリクエストから、情報を送信するPOSTリクエストまで、さまざまなHTTPリクエストの送信方法を学びました。また、HTTP通信を扱う代表的なRuby Gemの概要も紹介しました。筆者のお気に入りは柔軟性に優れたfaradayですが、自分のニーズに最も合うGemを自由に選んでください。

この記事が役に立ったと思ったら、ぜひ友人にもシェアしてみてください。

最後までお読みいただきありがとうございました!

  1. RubyのEnumerableモジュール入門ガイド〜筆者イチオシのeach_consメソッドを徹底解説〜

    Enumerableモジュールとは? Enumerableは繰り返し処理(イテレーション)用メソッドのコレクションで構成されるRubyのモジュールであり、Rubyが多くの開発者に愛される大きな理由のひとつとなっています。 Enumerableには、次のような便利なメソッドが含まれています: map select inject Enumerableのメソッドは、ブロックを渡すことで動作します。 ブロックの中には、各要素に対して実行したい処理を記述します。 例えば: [1,2,3].map { |n| n * 2 } このコードを実行すると、すべての数値が2倍になった新しい配列が得られます

  2. MacでAndroidメッセージを使いこなす完全ガイド

    AndroidのメッセージをMacで使う?一見不可能に思えますよね。両ブランドは熾烈な競争関係にあるため、「AndroidとMacは相性が悪い」と考える人がほとんどです。しかし、Googleはユーザーにとってより便利で柔軟なコミュニケーション環境を実現するため、Android Messagesを開発しました。 このメッセージングプラットフォームは、Windows PCとMacの両方で利用できます。そのため、Macユーザーでも難しく考える必要はありません。Android Messagesは複数のデバイス間で互換性があるため、さまざまなブランドのガジェットを持つユーザーにとって理想的な選択肢となっ