RubyでGETリクエストやPOSTリクエストをする際の色々確認した時のメモ。
参考
確認用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
以下のようなコードを書きます。
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のみを標準出力します。
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レスポンスのボディを変数に設定する場合には以下のようにします。
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を利用してリクエストを行います。
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リクエストヘッダを変更する場合、以下のようにします。
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エンコードする必要がありますが、その場合以下のようにします。
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メソッド用に変更します。
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のコードは以下のようにします。
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データが送信できているのが確認できました。