はじめに
ElixirにてCowboyを直接動かすための記事となります。
Cowboy1.0の前回やCowboy2.0の前回の記事では、cowboyにてHTMLページの表示を行いました。
今回はjsonを返すAPIのなりそこないの実装を行っていきます。
1.0と2.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の場合
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
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の場合
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
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の場合
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の場合
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を返すこともできるようになったのではないでしょうか?
その辺りを実際に行っていくのは次回以降のどこかで行えたら行っていきたいと考えております。
それではまた次回