【问题标题】:Cowboy multiple METHOD handler牛仔多 METHOD 处理程序
【发布时间】:2017-06-22 09:41:17
【问题描述】:

尝试通过 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 错误

【问题讨论】:

  • 您在启动此服务器的终端中是否遇到任何错误?
  • 不,当我启动服务器时一切正常
  • 从 api_app.app 中删除了啤酒,连接错误消失了。但现在我面临 500 错误

标签: rest api erlang handler cowboy


【解决方案1】:

因为 {Method, Req1} = cowboy_req:method(Req0) 是一个元组,类似于{&lt;&lt;"PUT"&gt;&gt;, _},而不是二进制&lt;&lt;"PUT"&gt;&gt;

【讨论】:

  • 是的,我可以在用户手册中看到,但我不明白为什么在牛仔 echo_post 示例中是 &lt;&lt;"PUT"&gt;&gt; ::: [github.com/ninenines/cowboy/blob/master/examples/echo_post/src/…
  • 这个问题给99后的团队,用元组
  • {Method, Req1} = cowboy_req:method(Req0) -- 适用于 1.1.x 版本。主版本现在使用二进制
【解决方案2】:

找到了答案。 这是运行良好的代码(使用 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.

【讨论】:

    【解决方案3】:

    你也可以像这样在 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 动词/方法设置单独的处理程序。这也为您提供了更清晰的代码:)

    【讨论】:

      【解决方案4】:

      我采用了一种稍微不同的方法。我没有使用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).
      

      【讨论】:

        猜你喜欢
        • 2017-06-14
        • 2013-12-19
        • 2015-04-18
        • 1970-01-01
        • 2013-05-30
        • 2017-11-29
        • 1970-01-01
        • 2018-08-28
        • 2020-09-28
        相关资源
        最近更新 更多