Posted at

RubyでGETリクエストやPOSTリクエストした時のメモ

More than 3 years have passed since last update.

RubyでGETリクエストやPOSTリクエストをする際の色々確認した時のメモ。


参考

library net/http


確認用Webサーバーの準備

今回はNode.js(v4.4.4)でWebサーバーを立てHTTPヘッダーやGETパラメーターを確認しました。

まずはNode.jsのインストール

$curl --silent --location https://rpm.nodesource.com/setup_4.x | bash -

$yum -y install nodejs

以下のようなコードを書きます。


server.js

var http = require('http');

var server = http.createServer(function (req,res) {
// confirm request
console.log(`headers: ${JSON.stringify(req.headers)}`);
console.log(`httpVersion: ${req.httpVersion}`);
console.log(`method: ${req.method}`);
console.log(`url: ${req.url}`);

// response
res.writeHeader(200, {'Content-Type': 'application/json'});
res.end(JSON.stringify({ 'foo': 'bar'}));
});

server.listen({
port: 80
});


起動及び実行時のログは以下のようになります。

# 起動

node server.js

# curlでこのサーバーにリクエストした際の標準出力
headers: {"host":"54.238.183.170","user-agent":"curl/7.43.0","accept":"*/*"}
httpVersion: 1.1
method: GET
url: /

# curlでサーバーにリクエスト(パスを変更)した際の標準出力
headers: {"host":"54.238.183.170","user-agent":"curl/7.43.0","accept":"*/*"}
httpVersion: 1.1
method: GET
url: /hogefufa


GETメソッド


GETリクエストを行って標準出力する

Net::HTTP.get_printを使うことでBodyのみを標準出力します。


hoge.rb

require 'net/http'

# 以下2つのいずれか

# hostとパスを指定する
Net::HTTP.get_print('54.238.183.170', '/')

# URIを指定する
Net::HTTP.get_print(URI.parse('http://54.238.183.170'))


Webサーバー側では以下のように出力されています。

headers: {"accept-encoding":"gzip;q=1.0,deflate;q=0.6,identity;q=0.3","accept":"*/*","user-agent":"Ruby","host":"54.238.183.170"}

httpVersion: 1.1
method: GET
url: /


GETリクエストを行ってHTTPレスポンスのボディを変数に入れる

HTTPレスポンスのボディを変数に設定する場合には以下のようにします。


hoge.rb

require 'net/http'

require 'json'

res = Net::HTTP.get('54.238.183.170', '/')
puts res // {"foo":"bar"}
puts JSON.parse(res)['foo'] // bar
res2 = Net::HTTP.get(URI.parse('http:/
/54.238.183.170'))
puts res2 // {"foo":"bar"}



HTTPレスポンスのステータスコードやヘッダも見たい

Net::HTTP.getではステータスコードやレスポンスヘッダが取得できないのでNet::HTTP.startを利用してリクエストを行います。


hoge.rb

require 'net/http'

require 'json'
require 'uri'

url = URI.parse('http://54.238.183.170')
res = Net::HTTP.start(url.host, url.port) do |http|
http.get('/')
end

puts res.code
puts res.body
res.each_header do |name, val|
puts "name=#{name}, val=#{val}"
end


Net::HTTPResponseが返却されるのでこのオブジェクトから情報を取得します。

$ruby hoge.rb

200
{"foo":"bar"}
name=content-type, val=application/json
name=date, val=Sat, 21 May 2016 09:08:13 GMT
name=connection, val=keep-alive
name=transfer-encoding, val=chunked


HTTPリクエストヘッダを変更したい

リクエスト時のHTTPリクエストヘッダを変更する場合、以下のようにします。


hoge.rb

require 'net/http'

require 'json'
require 'uri'

url = URI.parse('http://54.238.183.170')
req = Net::HTTP::Get.new(url.request_uri)
req['Accept'] = 'application/json'

res = Net::HTTP.start(url.host, url.port) do |http|
http.request(req)
end

puts res.body


Net::HTTP::Get.newによってNet::HTTP::Getオブジェクトを生成します。

Net::HTTP::GetクラスはNet::HTTPHeaderモジュールを利用しており、self[key]->Stringと指定することでHTTヘッダを指定します。

以下のようにWebサーバーの標準出力でもHTTPヘッダーが指定されていることを確認できました。

headers: {"accept-encoding":"gzip;q=1.0,deflate;q=0.6,identity;q=0.3","accept":"application/json","user-agent":"Ruby","host":"54.238.183.170"}

httpVersion: 1.1
method: GET
url: /


リクエストパラメーターをURLエンコードしたい

日本語のリクエストパラメーターを利用する場合にURLエンコードする必要がありますが、その場合以下のようにします。


hoge.rb

require 'net/http'

require 'json'
require 'uri'

params = URI.encode_www_form({ area: 1, city: 'アイウエオ'})
url = URI.parse("http://54.238.183.170/?#{params}")
req = Net::HTTP::Get.new(url.request_uri)
req['Accept'] = 'application/json'

res = Net::HTTP.start(url.host, url.port) do |http|
http.request(req)
end

puts res.body


Webサーバーは以下のように標準出力されています。

headers: {"accept-encoding":"gzip;q=1.0,deflate;q=0.6,identity;q=0.3","accept":"application/json","user-agent":"Ruby","host":"54.238.183.170"}

httpVersion: 1.1
method: GET
url: /?area=1&city=%E3%82%A2%E3%82%A4%E3%82%A6%E3%82%A8%E3%82%AA

上記がエンコードされているかnkfコマンドを使って確認してみます。

$echo %E3%82%A2%E3%82%A4%E3%82%A6%E3%82%A8%E3%82%AA |nkf -w --url-input

アイウエオ


POSTメソッド

今までGETメソッドでやったものをNet::HTTP.post_formを利用したり、Net::HTTP::Post.newを利用してオブジェクトを生成すればOKです。

まずはWebサーバーの設定をPOSTメソッド用に変更します。


server.js

var server = http.createServer(function (req,res) {

// confirm request
console.log(`headers: ${JSON.stringify(req.headers)}`);
console.log(`httpVersion: ${req.httpVersion}`);
console.log(`method: ${req.method}`);
console.log(`url: ${req.url}`);
if (req.method === 'POST' ) {
var data = '';

req.on('data', (chunk) => {
data += chunk;
});

req.on('end', () => {
console.log(`data: ${data}`);

// response
res.writeHeader(200, {'Content-Type': 'application/json'});
res.end(JSON.stringify({ 'foo': 'bar'}));
});
}

});

server.listen({
port: 80
});


Rubyのコードは以下のようにします。


hoge.rb

require 'net/http'

require 'uri'

# POSTするだけ
res = Net::HTTP.post_form(URI.parse('http://54.238.183.170'),{'q' => 'ruby'})
puts res.body

# 詳細
url = URI.parse('http://54.238.183.170/')
req = Net::HTTP::Post.new(url.path)
req.set_form_data({'from' => '2005-01-01', 'to' => '2010-01-01'}, ';')
res = Net::HTTP.new(url.host, url.port).start do |http|
http.request(req)
end

puts res.code
puts res.body


実行するとWebサーバーで以下のような標準出力となります。

headers: {"accept-encoding":"gzip;q=1.0,deflate;q=0.6,identity;q=0.3","accept":"*/*","user-agent":"Ruby","host":"54.238.183.170","content-type":"application/x-www-form-urlencoded","content-length":"6"}

httpVersion: 1.1
method: POST
url: /
data: q=ruby
headers: {"accept-encoding":"gzip;q=1.0,deflate;q=0.6,identity;q=0.3","accept":"*/*","user-agent":"Ruby","content-type":"application/x-www-form-urlencoded","host":"54.238.183.170","content-length":"29"}
httpVersion: 1.1
method: POST
url: /
data: from=2005-01-01;to=2010-01-01

POSTデータが送信できているのが確認できました。