はじめに
タイトルのままですが、Elixir+PhoenixでGCMサーバーのAPIを叩いてPush通知を送る簡単なWebAPIをつくってみました。
経緯
僕自身は普段CakePHPで開発することが多いのですが、最近はスマホアプリ全盛(あとSPA。今後はIoT?)でMVCなWebアプリを開発する機会が減ってきていて、サーバー側はRestなWebAPIを開発することが多くなってきています。
そうするとCakePHPはフルスタック過ぎるし、もっと高性能なAPIサーバーつくりたいなと思いながらもGolangは乗り遅れちゃったし、Node.jsはたまに使うけど個人的に肌なじみがあまりよくなく、何かイケてる言語ないかなぁと悶々としていたところ、@naoya@githubさんが紹介していたスライドをみて興味を持ちました。
言語的な特徴には触れない(他の方が語っていること以外は語れない)ので、他の方の投稿を参照してください。
環境構築
インストール on Mac
brewで簡単に入れられます。
$ brew install elixir
Hello, world!
iexコマンドでコマンドプロンプトで対話的に実行出来ます。
rubyのirbコマンドと同じです。
$ iex
iex(1)> IO.puts "Hello, world!"
Hello, world
:ok
ここまでは楽勝。
Phoenixインストール
現状最もメジャーなフレームワークであるPhoenixをインストールします。
APIサーバーつくりたいだけなので、Railsライクなのはややオーバースペックな気もしますが、馴染みやすいので入り口としてはよいかなと思っています。
$ mix archive.install https://github.com/phoenixframework/phoenix/releases/download/v1.0.3/phoenix_new-1.0.3.ez
アプリ作成 / 起動
Phoenixアプリをつくります。
mixコマンドはRailsで言うrailsコマンドです。
$ mix phoenix.new gcm_app
サーバー起動もRails的な感じ。
アプリのルートディレクトリに移動してから下記コマンドを実行します。
$ mix phoenix.server
Unchecked dependencies for environment dev:
* phoenix_live_reload (Hex package)
the dependency is not available, run `mix deps.get`
* cowboy (Hex package)
the dependency is not available, run `mix deps.get`
* phoenix_html (Hex package)
the dependency is not available, run `mix deps.get`
* phoenix (Hex package)
the dependency is not available, run `mix deps.get`
* postgrex (Hex package)
the dependency is not available, run `mix deps.get`
* phoenix_ecto (Hex package)
the dependency is not available, run `mix deps.get`
** (Mix) Can't continue due to errors on dependencies
依存パッケージあたりでエラーになってしまった。。
言われた通りに以下を実行します。
$ mix deps.get
依存パッケージのチェックをしてくれる模様。
再度サーバー起動してみると、成功したっぽい。
上記URLでWelocome to Phoenix!なページが表示されます。
API開発
HTTPクライアントインストール
HTTPクライアントであるHTTPoisonを入れます。
~mix.exsのdepsの箇所にHTTPoisonの設定を追加します。
defp deps do
[{:phoenix, "~> 1.0.3"},
{:phoenix_ecto, "~> 1.1"},
{:postgrex, ">= 0.0.0"},
{:phoenix_html, "~> 2.1"},
{:phoenix_live_reload, "~> 1.0", only: :dev},
{:cowboy, "~> 1.0"},
{:httpoison, "~> 0.7.2"}]
end
そして、依存パッケージインストール。
$ mix deps.get
インストール後、~mix.exsのapplicationの箇所にもHTTPoisonの設定を追加します。
これで実行時HTTPoison.startが不要になるっぽい。
def application do
[mod: {GcmApp, []},
applications: [:phoenix, :phoenix_html, :cowboy, :logger,
:phoenix_ecto, :postgrex, :httpoison]]
end
ルーター設定
デフォルトのAPI用のルーター設定はコメントアウトされているので、以下のように修正します。
scope "/api", GcmApp do
pipe_through :api
get "/push/:message/", PageController, :push
end
メイン処理
~web/controllers/page_controller.exにpushメソッドを以下のように追加します。
GCMの仕様については省略。
def push(conn, %{"message" => message}) do
url = "https://android.googleapis.com/gcm/send"
api_key = "********"
registraion_ids = ["hogehogehogehoge"]
headers = [{"Content-Type", "application/json;charset=UTF-8"},
{"Authorization", "key=#{api_key}"}]
json_data = %{collapse_key: "ff1",
delay_while_idle: true,
time_to_live: 864000,
data: %{title: "gcm_app", message: message},
registration_ids: registraion_ids} |> Poison.encode!
# HTTPoison.start # 不要だった
response = HTTPoison.post!(url, json_data, headers)
# IO.puts response.body # デバッグ用
case response do
%{status_code: 200, body: body} -> json conn, Poison.decode!(body)
%{status_code: code} -> json conn, %{error: code}
end
end
API実行
開発が完了したら、サーバーを起動してAPIを実行!
成功した場合、下記のようなレスポンスが返ってきます。
$ curl http://localhost:4000/api/push/finalfantasy
{"success":1,"results":[{"message_id":"0:1446717643350281%3207dc8500018b71"}],"multicast_id":9177386917145341445,"failure":0,"canonical_ids":0}
そして、Androidアプリに"finalfantasy"というPushメッセージが通知されます。
テスト
ユニットテストについては次の機会に←
まとめ
Elixir(と言うか新しい言語)たのしい!
でも、まずは動かしてみたレベルなので、まだまだ文法とか内部構造とか理解していないので、これから勉強していこう。ベンチマークもとりたいな。
参考文献 / 参考URL
Elixir ご紹介:
https://speakerdeck.com/naoya/elixir-goshao-jie
Installing Elixir:
http://elixir-lang.org/install.html
Elixir 基礎文法最速マスター:
http://qiita.com/niku/items/729ece76d78057b58271
Elixir のパターンマッチを攻略しよう:
http://qiita.com/naoya@github/items/9da982febe89d83cb5b5
Installation · Phoenix:
http://www.phoenixframework.org/docs/installation
Phoenix アプリケーションを作成する:
http://qiita.com/mserizawa/items/a861b4aa0d55b42b2324
edgurgel/httpoison:
https://github.com/edgurgel/httpoison
ElixirのHTTPoisonライブラリの使い方:
http://qiita.com/ColdFreak/items/4beb6cacfbb39baa955f
Phoenix で外部 API にリクエストする API を作る:
http://qiita.com/mserizawa/items/3ac483aca4f2926fa1a9
『WEB+DB PRESS Vol.88』(技術評論社):
http://gihyo.jp/magazine/wdpress/archive/2015/vol88