LoginSignup
48
46

More than 5 years have passed since last update.

ElixirのHTTPoisonライブラリの使い方

Last updated at Posted at 2015-09-12

HTTPoisonはHTTPクライアントのことです.なぜHTTPoisonを使うかというと,バックエンドはErlangのHackneyライブラリが使われているからです.Hackneyはバイナリを使うので,それが気に入っています.今回GithubのAPIを通して,HTTPoisonライブラリの基本的な使い方をまとめたいと思います.

Setup

$ mix new githubapi --module Github

mix.exsへ以下の記述を追加します.

def application do
  # ここに`:httpoison`を書いておくとモジュールに`HTTPoison.startを書かなくても済む
  [applications: [:logger, :httpoison]]                                                                                                end

def deps do
  [{:httpoison, "~> 0.7.2"},
   {:poison, "~> 1.5"}
  ]
end
$ mix deps.get

lib/githubapi.exファイルは以下のようになっています.

defmodule Github do

  def zen do # これから実装する関数
  ...
  end

  def list_repos do
  ...
  end   
  ...
  ...
end

GET 禅

毎回違うを取得してみます.

$ curl https://api.github.com/zen
Anything added dilutes everything else.

HTTPoisonでのやり方

def zen do
  url = "https://api.github.com/zen"
  response = HTTPoison.get!(url)
  Logger.info "レスポンス: #{inspect response}"
end

実行結果

$ iex -S mix 

iex(1)> Github.zen

18:37:09.866 [info]  レスポンス: %HTTPoison.Response{body: "Non-blocking is better than blocking.", headers: [{"Server", "GitHub.com"}, {"Date", "Sat, 12 Sep 2015 09:37:08 GMT"}, {"Content-Type", "text/plain;charset=utf-8"}, {"Content-Length", "37"}, {"Status", "200 OK"}, {"X-RateLimit-Limit", "60"}, {"X-RateLimit-Remaining", "57"}, {"X-RateLimit-Reset", "1442051552"}, {"X-XSS-Protection", "1; mode=block"}, {"X-Frame-Options", "deny"}, {"Content-Security-Policy", "default-src 'none'"}, {"Access-Control-Allow-Credentials", "true"}, {"Access-Control-Expose-Headers", "ETag, Link, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval"}, {"Access-Control-Allow-Origin", "*"}, {"X-GitHub-Request-Id", "6A89D658:C023:20C345:55F3F243"}, {"Strict-Transport-Security", "max-age=31536000; includeSubdomains; preload"}, {"X-Content-Type-Options", "nosniff"}, {"Vary", "Accept-Encoding"}, {"X-Served-By", "b0ef53392caa42315c6206737946d931"}], status_code: 200}
:ok

レスポンスを見てみると%HTTPoison.Response{body: ..., headers: ..., status_code: ...}のような形のstructです.その中のbodyフィールドを抽出するのは簡単(response.body)です.

def zen do
  url = "https://api.github.com/zen"
  response = HTTPoison.get!(url)
  # Logger.info "レスポンス: #{inspect response}"

  # bodyを抽出
  body = response.body
  Logger.info "body: #{inspect body}"
end

結果

iex(1)> Github.zen

18:52:19.126 [info]  body: "Encourage flow."

get!関数の最後に!が付いているのは理由についてソースを見てみましょう.要は失敗すると例外を起こすようにすることです.

Issues a GET request to the given url, raising an exception in case of failure.

すでに気づいたと思いますが,レスポンスの中のheaderstuplelistになっています.Enumを使って,headersを出力してみます.

def zen do
  url = "https://api.github.com/zen"
  response = HTTPoison.get!(url)
  # Logger.info "レスポンス: #{inspect response}"

  # bodyを抽出
  # body = response.body
  # Logger.info "body: #{inspect body}"

  # headerを出力
  headers = response.headers
  Enum.map(headers, fn {header, value} -> IO.puts "#{header}: #{value}\n" end)
end

結果

iex(1)> Github.zen
Server: GitHub.com

Date: Sat, 12 Sep 2015 10:16:20 GMT

Content-Type: text/plain;charset=utf-8

Content-Length: 26

Status: 200 OK

X-RateLimit-Limit: 60

X-RateLimit-Remaining: 58
......
......
[:ok, :ok, :ok, :ok, :ok, :ok, :ok, :ok, :ok, :ok, :ok, :ok, :ok, :ok, :ok, :ok,
 :ok, :ok, :ok]

Githubのrepoをリストアップ

認証されたユーザーとしてレポジトリをリストアップしてみます.そのためにtokenが必要で,ここで生成することができます.

$ curl -i -H 'Authorization: token ****************************************' https://api.github.com/user/repos

HTTPoisonでのやり方

def list_repos do
  url = "https://api.github.com/user/repos"
  token = "***************************************"
  headers = [{"Authorization", "token #{token}"}]
  response = HTTPoison.get!(url, headers)
  Logger.info "response: #{inspect response.body}"

結果
大量なデータが出力されるので,省いておきます.

iex(1)> Github.list_repos
:ok
19:50:59.235 [info]  response: "[{\"id\":9593030,\"name\":\"Addition\",
.....
.....
.....
]

これでget!関数にheaerの追加のやり方も分かりました.どんなフォーマットの引数を渡せばいいかを知るためにソースコードを見るとわかります.

レポジトリのIssueを作成 (POST)

このAPIの仕様はここからアクセスできます.

$ curl -i -H 'Authorization: token ***************************************' \
>   -d '{
>        "title": "New logo",
>        "body": "We should have one",
>        "labels": ["design", "feature"]
>      }' https://api.github.com/repos/ColdFreak/ppool/issues

ここでjson形式のPOSTデータを送ります."labels"の部分2つの要素が入っているリストになっています.

HTTPoisonでのやり方

def create_issue do
  url = "https://api.github.com/repos/ColdFreak/ppool/issues"
  token = "***************************************"

  response = HTTPoison.post!(url,  "{\"title\": \"Add variable\", \"body\": \"Add max overflow\", \"labels\": [\"design\", \"feature\"\]}", %{"Authorization" => "token #{token}"})

  Logger.info "response: #{inspect response}"
end

post!関数の使い方は同じくソースコードの中で調べるとわかります.
def post!(url, body, headers \\ [], options \\ []), do: request!(:post, url, body, headers, options)
二番目の引数に直接json形式のデータを作って渡しています.labelsの部分は配列になっています.三番目の引数はheaderで,上のようなMapの形で渡しても大丈夫です.

作成されていることは確認できました.

スクリーンショット 2015-09-12 22.21.43.png

もう一つのやり方はPoisonというJSONライブラリを使う方法です.

def create_issue_2 do
  url = "https://api.github.com/repos/ColdFreak/ppool/issues"
  token = "***************************************"

  headers = [{"Authorization", "token #{token}"}]
  json_data = %{title: "test issue", body: "test body", labels: ["design", "feature"]} |> Poison.encode!

  response = HTTPoison.post!(url,  json_data, headers)
  Logger.info "response: #{inspect response}"

Mapでデータを準備して,Poison.encode!渡して,JSONを生成してくれます.
スクリーンショット 2015-09-12 22.36.52.png

48
46
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
48
46