Rubyの HTTP クライアントを試そう

Ruby で HTTP クライアントを動かしたので、メモがてらまとめます。


参考

下準備

1
2
3
4
5
# 適当なディレクトリを作成して
bundle init

# 何かがインストールされるわけではないが .bundle以下の作成のために以下コマンドを実行
bundle install --path=vendor/bundle

nahi/httpclient を試す

インストール

Gemfile に以下を追記し、bundle installを実行。

Gemfile
1
gem 'httpclient', '~> 2.2'

実装

test1.rbを以下の通り作成。

test1.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
require "httpclient"

client = HTTPClient.new()

res = client.get("https://www.google.co.jp/")

# レスポンス全体を表示
puts res.inspect

# レスポンスステータス
puts res.status

# header 中を見たいので.inspectで展開
puts res.header.inspect

# body
puts res.body

# cookies 中を見たいので.inspectで展開
puts res.cookies.inspect

実行

bundle exec ruby test1.rbを実行すると、以下のように出力される。

1
2
#<HTTP::Message:0x0000000003658ff8 @http_header=#<HTTP::Message::Headers:0x0000000003658f80 @http_version="1.1", @body_size=0, @chunked=false, @request_method="GET", @request_uri=#<URI::HTTPS https://www.google.co.jp/>, @request_query=nil, @request_absolute_uri=nil, @status_code=200, @reason_phrase="OK", @body_type=nil, @body_charset=nil, @body_date=nil, @body_encoding=#<Encoding:Shift_JIS>, @is_request=false, @header_item=[["Date", "Sat, 06 Jun 2020 00:00:15 GMT"], ["Expires", "-1"], ["Cache-Control", "private, max-age=0"], ["Content-Type", "text/html; charset=Shift_JIS"], ["P3P", "CP
# 以下省略

google 検索のトップページが取得できました。

パラメータを渡してみる

google で検索すると、多数のパラメータが付与されますが、検索したワードは、qoqというキーで渡しているようです。こちらを試してみます。

test1.rbを以下の通り作成。

test2.rb
1
2
3
4
5
6
7
8
9
10
11
12
require "httpclient"

client = HTTPClient.new()

query = { "q": "ruby", "oq": "ruby"}

res = client.get("https://www.google.co.jp/search", query: query)

# 長すぎるのでファイルに出力
File.open("result.txt", mode = "w"){|f|
f.write(res.body)
}

bundle exec ruby test2.rbを実行すると、結果がresult.txtに書き込まれます。
明らかに取得された文字列の量は google のトップページとは異なっていますが、ブラウザで検索した時の結果とは違うようです。

POST を試す

POST を試したいとところですが、Google に問い合わせるのも限界なので、別の方法で通信先を用意します。
json-serverを使うのも手ですが、今回はあくまで ruby で進めてみます。
webmockgem を使用します。

Gemfile に以下を追記し、bundle installを実行。

Gemfile
1
gem 'webmock'

以下のようにtest3.rbを作成。

test3.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
require "httpclient"
require 'webmock'
include WebMock::API

# 以下webmock設定
WebMock.enable!

# stabに定義したもの以外の外部へのアクセスを許可
WebMock.allow_net_connect!
# stab定義
# status=200が返る
stub_request(:any, "test.com")

# getの要求だけに答えるstab設定
stub_request(:get, "test.com/api").to_return(
body: {status:"fail", msg:"Request Please Post", data:{} }.to_json
)
# postの要求だけに答えるstab設定
stub_request(:post, "test.com/api").to_return(
body: {status:"success", msg:"OK create", data:{text:"TestData post"} }.to_json
)
# putの要求だけに答えるstab設定
stub_request(:put, "test.com/api").to_return(
body: {status:"success", msg:"OK update", data:{text:"TestData put"} }.to_json
)
# patchの要求だけに答えるstab設定
stub_request(:patch, "test.com/api").to_return(
body: {status:"success", msg:"OK update", data:{text:"TestData patch"} }.to_json
)
# deleteの要求だけに答えるstab設定
stub_request(:delete, "test.com/api").to_return(
body: {status:"success", msg:"OK delete" }.to_json
)


# アクセス処理本体
client = HTTPClient.new()

res = client.get("http://test.com")
puts res.status
puts res.body

res = client.get("http://test.com/api")
puts res.status
puts res.body

res = client.put("http://test.com/api")
puts res.status
puts res.body

res = client.patch("http://test.com/api")
puts res.status
puts res.body

res = client.delete("http://test.com/api")
puts res.status
puts res.body

res = client.post("http://test.com/api")
puts res.status
puts res.body

# bodyはjsonなのでパースして使う。
data = JSON.parse(res.body)
puts data["data"]["text"]

bundle exec ruby text3.rbで実行すると、以下のように出力されます。

1
2
3
4
5
6
7
8
9
10
11
12
13
200

200
{"status":"fail","msg":"Request Please Post","data":{}}
200
{"status":"success","msg":"OK update","data":{"text":"TestData put"}}
200
{"status":"success","msg":"OK update","data":{"text":"TestData patch"}}
200
{"status":"success","msg":"OK delete"}
200
{"status":"success","msg":"OK create","data":{"text":"TestData post"}}
TestData post

以降はすべて webmock を使用して確認してゆきます。

rest-client を試す

今度は、rest-clientを試してみます。

インストール

Gemfile に以下を追記し、bundle installを実行。

Gemfile
1
gem 'rest-client'

実装

以下の通り、test4.rbを作成します。

test4.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
require "rest-client"
require 'webmock'
include WebMock::API

# 以下webmock設定
WebMock.enable!

# stabに定義したもの以外の外部へのアクセスを許可
WebMock.allow_net_connect!
# stab定義
# status=200が返る
stub_request(:any, "test.com")

# getの要求だけに答えるstab設定
stub_request(:get, "test.com/api").to_return(
body: {status:"fail", msg:"Request Please Post", data:{} }.to_json
)
# postの要求だけに答えるstab設定
stub_request(:post, "test.com/api").to_return(
body: {status:"success", msg:"OK create", data:{text:"TestData post"} }.to_json
)
# putの要求だけに答えるstab設定
stub_request(:put, "test.com/api").to_return(
body: {status:"success", msg:"OK update", data:{text:"TestData put"} }.to_json
)
# patchの要求だけに答えるstab設定
stub_request(:patch, "test.com/api").to_return(
body: {status:"success", msg:"OK update", data:{text:"TestData patch"} }.to_json
)
# deleteの要求だけに答えるstab設定
stub_request(:delete, "test.com/api").to_return(
body: {status:"success", msg:"OK delete" }.to_json
)

# アクセス処理本体
res = RestClient.get("http://test.com")
# レスポンスコード
puts res.code
# レスポンスcookies
puts res.cookies
# レスポンスheader
puts res.headers
# レスポンスbody
puts res.body


res = RestClient.get("http://test.com/api")
puts res.code
puts res.body

res = RestClient.put("http://test.com/api",{params:{text:"update"}})
puts res.code
puts res.body

res = RestClient.patch("http://test.com/api",{params:{text:"update"}})
puts res.code
puts res.body

res = RestClient.delete("http://test.com/api")
puts res.code
puts res.body

res = RestClient.post("http://test.com/api",{params:{text:"create"}})
puts res.code
puts res.body

# bodyはjsonなのでパースして使う。
data = JSON.parse(res.body)
puts data["data"]["text"]

.post .put .patchは、パラメータを要求するので、モックなので何も影響しませんが渡しておきます。
{}でもいいです。

実行

bundle exec ruby text4.rbで実行すると、以下のように出力されます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
200
{}
{}

200
{"status":"fail","msg":"Request Please Post","data":{}}
200
{"status":"success","msg":"OK update","data":{"text":"TestData put"}}
200
{"status":"success","msg":"OK update","data":{"text":"TestData patch"}}
200
{"status":"success","msg":"OK delete"}
200
{"status":"success","msg":"OK create","data":{"text":"TestData post"}}
TestData post

rest-client の動作確認できました。


今回はhttpclientgem とrest-clientgem を動作確認、関連してwebmockgem を使用してみました。
RestAPI を使うことはもちろん、ウェブページの内容を取得できたので、クロールもできそうです。

ではでは。