RubyでAPIを叩く(#3 DigitalOcean net/http編)

[前回](http://qiita.com/kazuyat/items/ca4ba93efd3e730a49ac)はcurlコマンドを使って直接APIを叩きました。今回はRubyからAPIを叩いてみます。

RubyでHTTP(S）の通信を操作する方法は色々ありますが、まずは基本ということでnet/http(s)を使います。ぶっちゃけ、APIを叩くならもっと便利なライブラリもいくつかあるのですが…。

## Droplet一覧を取得する
まずはいつものをやります。

```ruby:do_listdroplet.rb
require 'net/https'
require 'uri'

droplet_ep = 'https://api.digitalocean.com/v2/droplets'
token = '(トークン)'

uri = URI.parse(droplet_ep)
http = Net::HTTP.new(uri.host, uri.port)

http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE

req = Net::HTTP::Get.new(uri.request_uri)
req["Authorization"] = "bearer #{token}"

res = http.request(req)
puts res.code, res.msg
puts res.body
```

GETのときはあまりポイントがない？のですが、APIはたいていSSLなのでnet/httpsをrequireした上で、SSLを使うときのお約束を設定すること、またDigitalOceanに限らずAPIを叩く場合、ヘッダにトークン情報を入れることが多いので、リクエストする際につけておく必要があります。

また上記のコードのままだとres.bodyにjson形式のレスポンスがまるごと入ったままになってしまうので、Ruby上で扱いやすいようにparseしてあげます。

```ruby:do_listdroplets2.rb
require 'net/https'
require 'uri'
require 'json'

droplet_ep = 'https://api.digitalocean.com/v2/droplets'
token = '(トークン)'

uri = URI.parse(droplet_ep)
http = Net::HTTP.new(uri.host, uri.port)

http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE

req = Net::HTTP::Get.new(uri.request_uri)
req["Authorization"] = "bearer #{token}"

res = http.request(req)
puts res.code, res.msg
api_response = JSON.parse(res.body)
api_response['droplets'].each do |item|
  puts item['name'], item['disk'], item['memory']
end
```

APIレスポンスがRubyのhashにパースされるため、その中から任意の情報を取得することができるようになります。

## POSTしてみる
前回curlで行ったDroplet作成をnet/httpでやってみます。

```ruby:do_createdroplet.rb
require 'net/https'
require 'uri'
require 'json'

droplet_ep = 'https://api.digitalocean.com/v2/droplets'
token = '(トークン)'

uri = URI.parse(droplet_ep)
http = Net::HTTP.new(uri.host, uri.port)

http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE

req = Net::HTTP::Post.new(uri.request_uri)
req["Authorization"] = "bearer #{token}"
req["Content-Type"] = "application/json"

data = {
	"name" => "testserver",
	"region" => "sgp1",
	"size" => "512MB",
	"image" => "ubuntu-14-04-x64",
	"ipv6" => "false"
}.to_json

req.body = data
res = http.request(req)

puts res.code, res.msg, res.body
```

上半分はさっきとほぼ同じですね。
reqをPOSTとして生成したのと、POSTする内容をhashで作っておいて、jsonに変換しているところがポイントかと思います(まぁ、私も100％受け売りですが)。またPOSTの中身がJSONなので、必ずリクエストヘッダにContent-Typeをセットする必要があります。

curlの場合、しんどいのがPOSTのペイロードでJSONを手書きしなければいけないところなので、ここが多少なりとも記述しやすい形になるのは非常にありがたいところです。

## Deleteしてみる
今回も、最後は削除です。
本来はIDを何らかの方法で特定する(ARGVで突っ込むとか)するのがミソだと思うのですが、今回はさっき作ったDropletのIDをハードコードしてしまいます。

```ruby:do_delete_droplet.rb
require 'net/https'
require 'uri'

droplet_id = '28670468'

droplet_ep = "https://api.digitalocean.com/v2/droplets/#{droplet_id}"
token = '(トークン)'

uri = URI.parse(droplet_ep)
http = Net::HTTP.new(uri.host, uri.port)

http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE

req = Net::HTTP::Delete.new(uri.request_uri)
req["Authorization"] = "bearer #{token}"

res = http.request(req)
puts res.code, res.msg, res.body
```

エンドポイントを作るときに、先にIDを埋め込んじゃってます。
発行すると204 no contentが返ってきて、Dropletは削除されました。

## もっと楽していいかな
今回はあえてnet/httpを使ってみましたが、冒頭触れたとおりRubyにはもっと便利なライブラリがいっぱいありますし、当のDigitalOcean公式SDKはfaradayというライブラリを使ってたりします。次回以降、それらも掘り下げていきたいなと思います。