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か
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
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  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