Help us understand the problem. What is going on with this article?

Ruby HTTPクライアントの比較表

More than 1 year has passed since last update.

Rubyには標準でnet/httpが入っていますが、これはちょっと低レイヤ寄りで使いづらいので、使いやすくしたHTTPクライアントライブラリが多数あります。

ありすぎてどれを選んでいいか調べていたところ、HTTPClientの作者さんによる比較スライドを見つけました:
http://www.slideshare.net/HiroshiNakamura/rubyhttp-clients-comparison

まとめると

  • httpartyとrest-clientが2大人気(ソースはGemのダウンロード数とgithubのスター数。faradayはラッパーなので別枠)
  • この2つで出来ることはほとんど同じ
  • 違いはDigest認証(httppartyは可)、multipart post(rest-clientは可)くらい
  • どちらもKeep-Aliveに対応していない
  • HTTPClientはDigest認証も対応しているし、Keep-Aliveも自動的に面倒見てくれるし、機能的にはフルカバーっぽい

こちらの記事でも「HTTPClientは宣伝がうまくないだけでベストなgemだ」みたいな事が書かれている。
https://bibwild.wordpress.com/2012/04/30/httpclient-is-a-nice-http-client-forin-ruby/

…しかし、もしかしたらすでにfaradayがデファクトスタンダードになりつつあるのかもしれない。
faradayの短所はドキュメントがしっかりしてないことだな。

HTTPClientの使い方

require 'httpclient'

client = HTTPClient.new
client.debug_dev = $stderr    # デバッグ情報を標準エラー出力に

query = {'q' => 'google 倒産', 'hl' => 'ja'}
# get
res = client.get('https://google.co.jp', :query => query, :follow_redirect => true)
# post
#res = client.post('http://httpbin.org/post', :body => query)

puts "code=#{res.code}"    # res.code : Fixnum
puts HTTP::Status.successful?(res.code)
p res.headers
puts res.body

github:https://github.com/nahi/httpclient
ドキュメント:http://www.rubydoc.info/gems/httpclient/HTTPClient

プロキシの使用

HTTPClientは(net/httpと同じく)環境変数http_proxyを参照する。
明示的にプロキシを指定したい場合は:

proxy = 'http://**********:8080'
client = HTTPClient.new(proxy)

# さらにプロキシにBASIC認証したい場合は:
#user = 'proxy'
#password = 'proxy'
#client.set_proxy_auth(user, password)
#p client.get(url)

環境変数http_proxyを無視してプロキシを使用しないようにするには:

client = HTTPClient.new
client.proxy = nil

リクエストヘッダの指定

res = client.get('https://google.co.jp', query: query, header: [["User-Agent", "hoge"]], follow_redirect: true)

Faradayの使い方

一番シンプルな方法

require "faraday"
res = Faraday.get "http://httpbin.org/get", {a: "hoge"}
res = Faraday.post "http://httpbin.org/post", {a: "hoge"}
p res.status    # => 200
p res.success?  # => true
res.headers.each do |k, v|
  puts "#{k}: #{v}"
end
puts res.body

もう少し凝った方法

conn = Faraday.new(:url => 'http://sushi.com') do |faraday|
  faraday.request  :url_encoded             # form-encode POST params
  faraday.response :logger                  # log requests to STDOUT
  faraday.adapter  Faraday.default_adapter  # make requests with Net::HTTP
end

## GET ##

response = conn.get '/nigiri/sake.json'     # GET http://sushi.com/nigiri/sake.json
response.body

conn.get '/nigiri', { :name => 'Maguro' }   # GET http://sushi.com/nigiri?name=Maguro

conn.get do |req|                           # GET http://sushi.com/search?page=2&limit=100
  req.url '/search', :page => 2
  req.params['limit'] = 100
end

## POST ##

conn.post '/nigiri', { :name => 'Maguro' }  # POST "name=maguro" to http://sushi.com/nigiri

# post payload as JSON instead of "www-form-urlencoded" encoding:
conn.post do |req|
  req.url '/nigiri'
  req.headers['Content-Type'] = 'application/json'
  req.body = '{ "name": "Unagi" }'
end

## Per-request options ##

conn.get do |req|
  req.url '/search'
  req.options.timeout = 5           # open/read timeout in seconds
  req.options.open_timeout = 2      # connection open timeout in seconds
end

ホスト部とパス部を分けずに書くこともできるらしい

faraday = Faraday.new
res = faraday.post "http://httpbin.org/post", {q: "hgoehoge", a: 123}

1行でJSONをPOSTする

res = Faraday.post "https://httpbin.org/post", JSON.generate({hoge: 123, moge: [1,2,3]}), content_type: "application/json"

標準出力でなく指定ファイルにログを吐く方法

require "logger"

my_logger = Logger.new("logfile.log")
my_logger.level = Logger::DEBUG

conn = Faraday.new(:url => "https://httpbin.org") do |faraday|
  faraday.request  :url_encoded
  faraday.response :logger, my_logger # <-- sets a custom logger.
  faraday.adapter  Faraday.default_adapter
end


conn.get "/get", {hoge: 123}

net/httpの使い方

require "net/http"
require "uri"

シンプルなGET

url = "https://ipinfo.io"
puts Net::HTTP.get(URI.parse(url))
# => String(レスポンスボディ)

シンプルなPOST(x-www-form-urlencoded)

url = "https://httpbin.org/post"
params = {a: 123, b: "hoge"}
ret = Net::HTTP.post_form(URI.parse(url), params)
puts ret.code
puts ret.body

シンプルなPOST(JSON)

url = "https://httpbin.org/post"
payload =  {
  a: 123, b:"hoge"
}

uri = URI.parse(url)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
req = Net::HTTP::Post.new(uri.request_uri)
req["Content-Type"] = "application/json"
req.body = payload.to_json
res = http.request(req)

puts "code -> #{res.code}"
res.each_capitalized_name do |name|
  value = res[name]
  puts "#{name} = #{value}"
end
puts "body -> #{res.body}"

つぶやき

HTTPクライアントの使い方を調べるときは以下のやり方を抑えておこうと思った。

  • シンプルなGET
  • シンプルなPOST(x-www-form-urlencoded)
  • JSONのPOST
  • リクエストヘッダの指定
  • リダイレクトをたどるか
  • プロキシの指定
  • BASIC認証
  • ファイルのアップロード
  • レスポンスのステータスコードはIntegerかStringか
aosho235
1981年生まれ。駅すぱあとの会社で新規サービスを開発しています。好きなレイヤーはOS~ミドルウェア。好きなことは開発を楽にするためのツールやフレームワークの整備、自分自身が便利と思うものを作ること。新しいものを追うより、自分が自信を持って使える技術で効率的に開発するのが好き。そのため使うライブラリやサービスの挙動は仔細に把握しておきたいものです。
https://aosho235.com/
val
経路検索システム「駅すぱあと」をはじめ、全国のデータと高い信頼性をベースにさまざまなサービスを展開。
https://www.val.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away