Cowboy 多方法处理器
Cowboy multiple METHOD handler
正在尝试通过 Cowboy 设置 restful API
我需要为所有方法使用一个处理程序的主要事情
这里是路由器::
start(_Type, _Args) ->
Dispatch = cowboy_router:compile([
{'_', [
{"/api", handler, []},
{"/api/:id", handler, []}
]}
]),
{ok, _} = cowboy:start_clear(http, 100, [{port, 8080}], #{
env => #{dispatch => Dispatch}
}),
api_sup:start_link().
这是处理程序代码::
-module(handler).
-export([init/3, handle/2]).
init(_Transport, Req, []) ->
{ok, Req, undefined}.
handle(Req, Opts) ->
case cowboy_req:method(Req) of
<<"POST">> ->
Body = cowboy_req:has_body(Req),
Request = postMethod(<<"POST">>, Body, Req),
{ok, Request, Opts};
<<"GET">> ->
#{id := Id} = cowboy_req:match_qs([{id, [], undefined}], Req),
Request = getMethod(<<"GET">>, Id, Req),
{ok, Request, Opts};
<<"PUT">> ->
Body = cowboy_req:has_body(Req),
Request = putMethod(<<"PUT">>, Body, Req),
{ok, Request, Opts};
<<"DELETE">> ->
#{id := Id} = cowboy_req:match_qs([{id, [], undefined}], Req),
Request = deleteMethod(<<"DELETE">>, Id, Req),
{ok, Request, Opts}
end.
postMethod(<<"POST">>, _Body, Req) ->
cowboy_req:reply(200, #{<<"content-type">> => <<"application/json; charset=utf-8">>}, <<"{\"status\": \"POST\"}">>, Req).
getMethod(<<"GET">>, _Id, Req) ->
cowboy_req:reply(200, #{<<"content-type">> => <<"application/json; charset=utf-8">>}, <<"{\"status\": \"GET\"}">>, Req).
putMethod(<<"PUT">>, _Body, Req) ->
cowboy_req:reply(200, #{<<"content-type">> => <<"application/json; charset=utf-8">>}, <<"{\"status\": \"PUT\"}">>, Req).
deleteMethod(<<"DELETE">>, _Id, Req) ->
cowboy_req:reply(200, #{<<"content-type">> => <<"application/json; charset=utf-8">>}, <<"{\"status\": \"DELETE\"}">>, Req).
我收到错误:牛仔 500 错误
因为
{Method, Req1} = cowboy_req:method(Req0)
是一个元组,像 {<<"PUT">>, _}
,不是二进制 <<"PUT">>
找到答案了。
这是工作正常的代码(使用 Cowboy 的主版本)
-module(handler).
-export([init/2]).
-export([content_types_provided/2]).
-export([content_types_accepted/2]).
-export([allowed_methods/2]).
-export([router/2]).
init(Req, Opts) ->
{cowboy_rest, Req, Opts}.
allowed_methods(Req, State) ->
{[<<"GET">>, <<"POST">>, <<"PUT">>, <<"DELETE">>], Req, State}.
content_types_provided(Req, State) ->
{[{<<"application/json">>, router}], Req, State}.
content_types_accepted(Req, State) ->
{[{<<"application/json">>, router}], Req, State}.
router(Req, Opts) ->
case cowboy_req:method(Req) of
<<"POST">> ->
{<<"{\"status\": \"POST\"}">>, Req, State};
<<"GET">> ->
{<<"{\"status\": \"GET\"}">>, Req, State};
<<"PUT">> ->
{<<"{\"status\": \"PUT\"}">>, Req, State};
<<"DELETE">> ->
{<<"{\"status\": \"DELETE\"}">>, Req, State}
end.
您还可以在 content_types_accepted/2 回调方法中添加路由器逻辑,如下所示:
content_types_accepted(Req, State) ->
case cowboy_req:method(Req) of
{<<"POST">>, _ } ->
Accepted = {[{<<"application/json">>, post_json}], Req, State};
{<<"PUT">>, _ } ->
Accepted = {[{<<"application/json">>, put_json}], Req, State}
end,
Accepted.
我认为这样您可以为不同的 HTTP Verbs/Methods 设置单独的处理程序。这也为您提供了更清晰的代码:)
我采用了稍微不同的方法。我没有使用 case
,而是使用函数,模式匹配请求中的方法,然后使用代码 405 Method Unsupported.
-module(handler).
-export([init/2]).
init(Req0, State) ->
Req = case api:validate_headers(api_key, Req0) of
ok -> handle(Req0, State);
{error, Error} -> api:reply_failure(403, Error, Req0)
end,
{ok, Req, State}.
handle(Req0=#{method := <<"GET">>}, _) ->
Data = "...", % Some data goes here
api:reply_success([{<<"data">>, Data}], Req0);
handle(Req0=#{method := <<"POST">>}, _) ->
Data = "...", % Some data goes here
api:reply_success([{<<"data">>, Data}], Req0);
handle(Req=#{method := <<"OPTIONS">>}, _) ->
api:reply_options(Req);
handle(Req, _) ->
cowboy_req:reply(405, Req).
正在尝试通过 Cowboy 设置 restful API 我需要为所有方法使用一个处理程序的主要事情
这里是路由器::
start(_Type, _Args) ->
Dispatch = cowboy_router:compile([
{'_', [
{"/api", handler, []},
{"/api/:id", handler, []}
]}
]),
{ok, _} = cowboy:start_clear(http, 100, [{port, 8080}], #{
env => #{dispatch => Dispatch}
}),
api_sup:start_link().
这是处理程序代码::
-module(handler).
-export([init/3, handle/2]).
init(_Transport, Req, []) ->
{ok, Req, undefined}.
handle(Req, Opts) ->
case cowboy_req:method(Req) of
<<"POST">> ->
Body = cowboy_req:has_body(Req),
Request = postMethod(<<"POST">>, Body, Req),
{ok, Request, Opts};
<<"GET">> ->
#{id := Id} = cowboy_req:match_qs([{id, [], undefined}], Req),
Request = getMethod(<<"GET">>, Id, Req),
{ok, Request, Opts};
<<"PUT">> ->
Body = cowboy_req:has_body(Req),
Request = putMethod(<<"PUT">>, Body, Req),
{ok, Request, Opts};
<<"DELETE">> ->
#{id := Id} = cowboy_req:match_qs([{id, [], undefined}], Req),
Request = deleteMethod(<<"DELETE">>, Id, Req),
{ok, Request, Opts}
end.
postMethod(<<"POST">>, _Body, Req) ->
cowboy_req:reply(200, #{<<"content-type">> => <<"application/json; charset=utf-8">>}, <<"{\"status\": \"POST\"}">>, Req).
getMethod(<<"GET">>, _Id, Req) ->
cowboy_req:reply(200, #{<<"content-type">> => <<"application/json; charset=utf-8">>}, <<"{\"status\": \"GET\"}">>, Req).
putMethod(<<"PUT">>, _Body, Req) ->
cowboy_req:reply(200, #{<<"content-type">> => <<"application/json; charset=utf-8">>}, <<"{\"status\": \"PUT\"}">>, Req).
deleteMethod(<<"DELETE">>, _Id, Req) ->
cowboy_req:reply(200, #{<<"content-type">> => <<"application/json; charset=utf-8">>}, <<"{\"status\": \"DELETE\"}">>, Req).
我收到错误:牛仔 500 错误
因为
{Method, Req1} = cowboy_req:method(Req0)
是一个元组,像 {<<"PUT">>, _}
,不是二进制 <<"PUT">>
找到答案了。 这是工作正常的代码(使用 Cowboy 的主版本)
-module(handler).
-export([init/2]).
-export([content_types_provided/2]).
-export([content_types_accepted/2]).
-export([allowed_methods/2]).
-export([router/2]).
init(Req, Opts) ->
{cowboy_rest, Req, Opts}.
allowed_methods(Req, State) ->
{[<<"GET">>, <<"POST">>, <<"PUT">>, <<"DELETE">>], Req, State}.
content_types_provided(Req, State) ->
{[{<<"application/json">>, router}], Req, State}.
content_types_accepted(Req, State) ->
{[{<<"application/json">>, router}], Req, State}.
router(Req, Opts) ->
case cowboy_req:method(Req) of
<<"POST">> ->
{<<"{\"status\": \"POST\"}">>, Req, State};
<<"GET">> ->
{<<"{\"status\": \"GET\"}">>, Req, State};
<<"PUT">> ->
{<<"{\"status\": \"PUT\"}">>, Req, State};
<<"DELETE">> ->
{<<"{\"status\": \"DELETE\"}">>, Req, State}
end.
您还可以在 content_types_accepted/2 回调方法中添加路由器逻辑,如下所示:
content_types_accepted(Req, State) ->
case cowboy_req:method(Req) of
{<<"POST">>, _ } ->
Accepted = {[{<<"application/json">>, post_json}], Req, State};
{<<"PUT">>, _ } ->
Accepted = {[{<<"application/json">>, put_json}], Req, State}
end,
Accepted.
我认为这样您可以为不同的 HTTP Verbs/Methods 设置单独的处理程序。这也为您提供了更清晰的代码:)
我采用了稍微不同的方法。我没有使用 case
,而是使用函数,模式匹配请求中的方法,然后使用代码 405 Method Unsupported.
-module(handler).
-export([init/2]).
init(Req0, State) ->
Req = case api:validate_headers(api_key, Req0) of
ok -> handle(Req0, State);
{error, Error} -> api:reply_failure(403, Error, Req0)
end,
{ok, Req, State}.
handle(Req0=#{method := <<"GET">>}, _) ->
Data = "...", % Some data goes here
api:reply_success([{<<"data">>, Data}], Req0);
handle(Req0=#{method := <<"POST">>}, _) ->
Data = "...", % Some data goes here
api:reply_success([{<<"data">>, Data}], Req0);
handle(Req=#{method := <<"OPTIONS">>}, _) ->
api:reply_options(Req);
handle(Req, _) ->
cowboy_req:reply(405, Req).