LoginSignup
8
2

More than 5 years have passed since last update.

ElixirからCowboy 1.0と2.0を使ってみる Part 3

Posted at

はじめに

ElixirにてCowboyを直接動かすための記事となります。
Cowboy1.0の前回Cowboy2.0の前回の記事では、cowboyにてHTMLページの表示を行いました。
今回はjsonを返すAPIのなりそこないの実装を行っていきます。
1.0と2.0の記事をまとめろっと外部からの声がありましたので、今回から記事をまとめていきたいと思います。

Cowboy1.0のサンプルコードはこちらになります

Cowboy2.0のサンプルコードはこちらになります

バージョン

使用した言語やライブラリのバージョンは下記となります。

cowboy 1.0のバージョン

Version
Elixir 1.3.2
Erlang 19.2
Cowboy 1.0.4

cowboy 2.0のバージョン

Version
Elixir 1.3.2
Erlang 19.2
Cowboy 2.0.0-pre4

毎回同じJSONを返すAPIの作成

さて、まず実装するJSONのAPIですが、毎回同じ内容のJSONを返すAPIを作成していきます。
毎回同じ内容を返すAPIに何の意味があるのか?っという話もありますが、最初の最初として実装していきます。

cowboy 1.0の場合

lib/elixir_cowboy_example/json_handler.ex
defmodule ElixirCowboyExample.JsonHandler do
  def init({:tcp, :http}, req, opts) do
    {:ok, req, opts}
  end

  def handle(req, state) do
    {method, req} = :cowboy_req.method(req)
    {:ok, req} = json_example(method, req)
    {:ok, req, state}
  end

  # bodyに "{\"title\": \"hello cowboy!\"}" を設定し、
  # jsonを返すようにheadersを設定
  def json_example("POST", req) do
    headers = [{"content-type", "application/json"}]
    body = "{\"title\": \"hello cowboy!\"}"
    {:ok, resp} = :cowboy_req.reply(200, headers, body, req)
  end

  def terminate(_reason, _req, _state) do
    :ok
  end
end
lib/elixir_cowboy_example.ex
  def run do
    # http://localhost:4000/json にアクセスした際に
    # jsonを返すようにHandlerの設定
    routes = [
      {"/", ElixirCowboyExample.Handler, []},
      {"/json", ElixirCowboyExample.JsonHandler, []},
      {"/:html", ElixirCowboyExample.Handler, []}
    ]

    dispatch = :cowboy_router.compile([{:_, routes}])

    opts = [port: 4000]
    env = [dispatch: dispatch]

    {:ok, _pid} = :cowboy.start_http(:http, 100, opts, [env: env])
  end

cowboy 2.0の場合

lib/elixir_cowboy_example/json_handler.ex
defmodule ElixirCowboyExample.JsonHandler do
  def init(req, opts) do
    method = :cowboy_req.method(req)
    {:ok, resp} = json_example(method, req)
    {:ok, resp, opts}
  end

  # bodyに "{\"title\": \"hello cowboy!\"}" を設定し、
  # jsonを返すようにheadersを設定
  def json_example("POST", req) do
    headers = %{"content-type" => "application/json"}
    body = "{\"title\": \"hello cowboy!\"}"
    {:ok, resp} = :cowboy_req.reply(200, headers, body, req)
  end
end
lib/elixir_cowboy_example.ex
  def run do
    # http://localhost:4000/json にアクセスした際に
    # jsonを返すようにHandlerの設定
    routes = [
      {"/", ElixirCowboyExample.Handler, []},
      {"/json", ElixirCowboyExample.JsonHandler, []},
      {"/:html", ElixirCowboyExample.Handler, []}
    ]

    dispatch = :cowboy_router.compile([{:_, routes}])

    opts = [{:port, 4000}]
    env = %{dispatch: dispatch}

    {:ok, _pid} = :cowboy.start_clear(:http, 100, opts, %{env: env})
  end

記載したコードの実行

コードの記述が完了しましたので、それでは実行していきましょう。
いつも通り iex -S mix にて cowboy を実行していきます。
今回は、jsonを返すAPIですので、curlで実行していきます。

$ curl -v -H "Accept: application/json" -H "Content-type: application/json" -X POST http://localhost:4000/json
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 4000 (#0)
> POST /json HTTP/1.1
> Host: localhost:4000
> User-Agent: curl/7.43.0
> Accept: application/json
> Content-type: application/json
> Content-Length: 23
> 
* upload completely sent off: 23 out of 23 bytes
< HTTP/1.1 200 OK
< content-length: 26
< content-type: application/json
< date: Sat, 07 Jan 2017 06:59:11 GMT
< server: Cowboy
< 
* Connection #0 to host localhost left intact
{"title": "hello cowboy!"}

受け取ったパラメータからjsonを返す

毎回同じjsonを返すAPIには意味がないので、今回は受け取ったパラメータの内容をJson形式にて返すAPIを実装していきます。

今回の実装では受け取ったパラメータが複数あったとしても一番最初のものしか受け取りませんし、エラー処理も実際に使うためには必要ですが、パラメータの受け渡しをみるためなので、その辺りは気にせずいきます。

cowboy 1.0の場合

lib/elixir_cowboy_example/json_handler.ex
defmodule ElixirCowboyExample.JsonHandler do
  def init({:tcp, :http}, req, opts) do
    {:ok, req, opts}
  end

  def handle(req, state) do
    {method, req} = :cowboy_req.method(req)
    # bodyの中のパラメータの情報を取得する
    {:ok, params, req} = :cowboy_req.body_qs(req)
    {:ok, req} = json_example(method, params, req)
    {:ok, req, state}
  end

  def json_example("POST", :undefined , req) do
    headers = [{"content-type", "application/json"}]
    body = "{\"title\": \"hello cowboy!\"}"
    {:ok, resp} = :cowboy_req.reply(200, headers, body, req)
  end

  def json_example("POST", params, req) do
    # 上記にて受け取ったパラメータはリストの中にtupleで入っているので
    # 情報の抜き出しをおこなう
    param = params |> Enum.at(0) |> elem(1)
    headers = [{"content-type", "application/json"}]
    body = "{\"title\": \"#{param}\"}"
    {:ok, resp} = :cowboy_req.reply(200, headers, body, req)
  end

  def terminate(_reason, _req, _state) do
    :ok
  end
end

cowboy 2.0の場合

lib/elixir_cowboy_example/json_handler.ex
defmodule ElixirCowboyExample.JsonHandler do
  def init(req, opts) do
    method = :cowboy_req.method(req)
    # bodyの中のパラメータの情報を取得する
    # cowboy2.0 ではメソッド名が変わったもよう
    {ok, params, req} = :cowboy_req.read_urlencoded_body(req)
    {:ok, resp} = json_example(method, params, req)
    {:ok, resp, opts}
  end

  def json_example("POST", :undefined, req) do
    headers = %{"content-type" => "application/json"}
    body = "{\"title\": \"hello cowboy!\"}"
    {:ok, resp} = :cowboy_req.reply(200, headers, body, req)
  end

  def json_example("POST", params, req) do
    # 上記にて受け取ったパラメータはリストの中にtupleで入っているので
    # 情報の抜き出しをおこなう
    param = params |> Enum.at(0) |> elem(1)
    headers = %{"content-type" => "application/json"}
    body = "{\"title\": \"#{param}\"}"
    {:ok, resp} = :cowboy_req.reply(200, headers, body, req)
  end
end

記載したコードの実行

コードの記述が完了しましたので、それでは実行していきましょう。
上記で実行したcurlに合わせて、-d オプションにて パラメータの受け渡しを実施します。
結果としてパラメータで渡した内容が返ってくることが見て取れます

$ curl -v -H "Accept: application/json" -H "Content-type: application/json" -X POST -d 'title=test1' http://localhost:4000/json
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 4000 (#0)
> POST /json HTTP/1.1
> Host: localhost:4000
> User-Agent: curl/7.43.0
> Accept: application/json
> Content-type: application/json
> Content-Length: 23
> 
* upload completely sent off: 23 out of 23 bytes
< HTTP/1.1 200 OK
< content-length: 18
< content-type: application/json
< date: Sun, 08 Jan 2017 00:18:26 GMT
< server: Cowboy
< 
* Connection #0 to host localhost left intact
{"title": "test1"}

最後に

JSONを返すAPIの実装をおこなうことができました。
受け取ったパラメータを処理することもできましたので、受け取ったパラメータの内容からEctoからデータベースにアクセスしてJSONを返すこともできるようになったのではないでしょうか?
その辺りを実際に行っていくのは次回以降のどこかで行えたら行っていきたいと考えております。
それではまた次回

参考サイト

Cowboy User Guide

8
2
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
8
2