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

  • 39
    いいね
  • 0
    コメント

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は可)くらい
  • HTTPClientはどちらも対応しているし、機能的にはフルカバーっぽい

こちらの記事でも「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"}
puts res.status
puts res.success?
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

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

conn = Faraday.new
res = conn.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か