Help us understand the problem. What is going on with this article?

Elixir+PhoenixでGCMのAPIを叩いてPush通知を送る簡単なAPIをつくってみた

More than 3 years have passed since last update.

はじめに

タイトルのままですが、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

依存パッケージのチェックをしてくれる模様。
再度サーバー起動してみると、成功したっぽい。

http://localhost:4000/

上記URLでWelocome to Phoenix!なページが表示されます。

phoenix_20151105.png

API開発

HTTPクライアントインストール

HTTPクライアントであるHTTPoisonを入れます。
~mix.exsのdepsの箇所にHTTPoisonの設定を追加します。

mix.exs
  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が不要になるっぽい。

mix.exs
  def application do
    [mod: {GcmApp, []},
     applications: [:phoenix, :phoenix_html, :cowboy, :logger,
                    :phoenix_ecto, :postgrex, :httpoison]]
  end

ルーター設定

デフォルトのAPI用のルーター設定はコメントアウトされているので、以下のように修正します。

router.ex
  scope "/api", GcmApp do
    pipe_through :api

    get "/push/:message/", PageController, :push
  end

メイン処理

~web/controllers/page_controller.exにpushメソッドを以下のように追加します。
GCMの仕様については省略。

page_controller.ex
  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

nanapi
nanapiは、世の中のあらゆる「やり方」を世界一集めることを目指します。
http://nanapi.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした