LoginSignup
211
155

More than 5 years have passed since last update.

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

Last updated at Posted at 2016-08-16

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か
211
155
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
211
155