HTTPではGETとPOST時に値を追加してリクエストすることがよくあります。ですので今回はGETとPOST時の値の取得の仕方について記載していきます。
はじめに
ErlangとCowboyの環境設定については以下の記事に記載しています。気になる方は参考にしてみてください。
CowboyでHello Worldのサンプルを動かしてみる
Cowboyでのハンドラーの設定
まずはちゃっちゃかとハンドラーの設定をします。
Dispatch = cowboy_router:compile([
{'_', [
{"/get", get_handler, []},
{"/post", post_handler, []}
]}
]),
{ok, _} = cowboy:start_clear(http, [{port, 8010}], #{
env => #{dispatch => Dispatch}
}),
/get
パスではget_handler
を、/post
パスではpost_handler
を実行するようにします。
あとは8010ポートでリクエストを待ち受けるようにします。
GETでの値の取得
GETでリクエストが来た際に、値を取得します。今回はecho=[何かしら]
でリクエストがくる想定で値を取得しています。まずは全体像になります。
init(Req0, Opts) ->
Method = cowboy_req:method(Req0),
#{echo := Echo} = cowboy_req:match_qs([{echo, [], undefined}], Req0),
Req = echo(Method, Echo, Req0),
{ok, Req, Opts}.
echo(<<"GET">>, undefined, Req) ->
cowboy_req:reply(400, #{}, <<"Missing echo parameter.">>, Req);
echo (<<"GET">>, Echo, Req) ->
cowboy_req:reply(200, #{
<<"content-type">> => <<"text/plain; charset=utf-8">>
}, Echo, Req);
echo (_, _, Req) ->
cowboy_req:reply(405, Req).
Method = cowboy_req:method(Req0),
でリクエストできたメソッドを取得します。ここで取得できるのはGETになる想定です。もしGET以外できた場合は405をレスポンスするようになっています。
#{echo := Echo} = cowboy_req:match_qs([{echo, [], undefined}], Req0),
でリクエストされた値を取得します。第一引数にリクエストされてきたどの値を取得するかを決めます。{echo, [], undefined}
ではechoのキーのものを取得するように設定されてます。もしechoがない場合はデフォルト値としてundefined
が返ります。
Req = echo(Method, Echo, Req0),
で取得したリクエスト値を元にレスポンスを返します。
echo(<<"GET">>, undefined, Req) ->
cowboy_req:reply(400, #{}, <<"Missing echo parameter.">>, Req);
echo (<<"GET">>, Echo, Req) ->
cowboy_req:reply(200, #{
<<"content-type">> => <<"text/plain; charset=utf-8">>
}, Echo, Req);
echo (_, _, Req) ->
cowboy_req:reply(405, Req).
echo
関数内ではリクエストにechoのキーがあった場合は200のステータスで取得した値をBodyにセットしてレスポンスします。
もし、echoのキーがなかった場合は、400のステータスで"Missing echo parameter."をbodyにセットしてレスポンスします。
POSTでの値の取得
次はPOSTでのリクエスト値の取得方法になります。まじは全体像を。
init(Req0, Opts) ->
Method = cowboy_req:method(Req0),
HasBody = cowboy_req:has_body(Req0),
Req = maybe_echo(Method, HasBody, Req0),
{ok, Req, Opts}.
maybe_echo(<<"POST">>, true, Req0) ->
{ok, PostValue, Req} = cowboy_req:read_urlencoded_body(Req0),
Echo = proplists:get_value(<<"echo">>, PostValue, undefined),
echo(Echo, Req);
maybe_echo(<<"POST">>, false, Req) ->
cowboy_req:reply(400, #{}, <<"Missing body.">>, Req);
maybe_echo(_, _, Req) ->
cowboy_req:reply(405, Req).
echo(undefined, Req) ->
cowboy_req:reply(400, #{}, <<"Missing echo parameter.">>, Req);
echo(Echo, Req) ->
cowboy_req:reply(200, #{
<<"content-type">> => <<"text/plain; charset=utf-8">>
}, Echo, Req).
Method = cowboy_req:method(Req0),
はGETと同様、HTTPのメソッドを取得します。ここではPOSTがくる想定です。
HasBody = cowboy_req:has_body(Req0),
でリクエストがBodyを持っているかどうかを判定しています。つまり、POSTリクエスト内に値があるかどうかをチェックしています。
maybe_echo(<<"POST">>, true, Req0) ->
{ok, PostValue, Req} = cowboy_req:read_urlencoded_body(Req0),
Echo = proplists:get_value(<<"echo">>, PostValue),
echo(Echo, Req);
maybe_echo(<<"POST">>, false, Req) ->
cowboy_req:reply(400, #{}, <<"Missing body.">>, Req);
上記のもので値が取得できたかどうかをチェックしてします。第二引数にcowboy_req:has_body(Req0)
の結果が入りますので、リクエストに値が入ってた場合はtrue、入ってなかった場合はfalseのmaybe_echo
が実行されます。
cowboy_req:has_body(Req0)
がtrueの場合はBodyの値を取得します。
Echo = proplists:get_value(<<"echo">>, PostValue),
でリクエスト内にechoのキーの値を取得します。
echo(undefined, Req) ->
cowboy_req:reply(400, #{}, <<"Missing echo parameter.">>, Req);
echo(Echo, Req) ->
cowboy_req:reply(200, #{
<<"content-type">> => <<"text/plain; charset=utf-8">>
}, Echo, Req).
最後に、echoキーがある場合はレスポンスのBodyにechoキーの値をセットします。
echoキーがなかった場合はデフォルト値のundefinedが第一引数にくるので、400のステータスでエラーを返します。
まとめ
GETとPOSTでの値が取得できるようになりました。これとDBとを組み合わせれば、DBから値の取得や追加、更新、削除処理とができるようになりますね。
ただ、POSTの値の取得の仕方がちょっと気にくわないかな、、、もう少しCowboyで取得を簡単にできれば嬉しいですね。