Cowboy - 未调用 REST 回调

Cowboy - REST callback isn't called

我正在尝试实现 Rest 处理程序并有下一个代码:

-module(example_handler).
-behaviour(cowboy_handler).

-export([init/2,
         allowed_methods/2,
         content_types_provided/2,
         get_json/2]).

init(Req, State) ->
    {cowboy_rest, Req, State}.

allowed_methods(Req, State) ->
    io:format("allowed_methods~n"),
    {[<<"GET">>, <<"POST">>], Req, State}.

content_types_provided(Req, State) ->
    io:format("content_types_provided~n"),
    {[{{<<"application">>, <<"json">>, []}, get_json}], Req, State}.

get_json(_Req, _State) ->
    io:format("get_json~n")

然后当我尝试使用 curl 发送请求时:

curl -H "Accept: application/json" -X POST http://localhost:8080/xxx/xx

我得到下一个输出:

allowed_methods
content_types_provided

get_json() 没有被调用!但是当我使用 GET 方法时,一切看起来都很好:

curl -H "Accept: application/json" -X GET http://localhost:8080/xxx/xx
----------------------------------------------------------------------
allowed_methods
content_types_provided
get_json

我错过了什么?

TL;DR

content_types_providedcontent_types_accepted不一样;因为你正在处理 POST 你需要后者。


在我使用的 Cowboy 2.0.0 中,content_types_provided 回调 return 资源按优先顺序提供的媒体类型列表。所以,当你使用:

content_types_provided(Req, State) ->
  {[
    {{<<"application">>, <<"json">>, []}, get_json}
  ], Req, State}.

您基本上是在告诉 Cowboy,从现在开始,此 处理程序 支持 JSON 响应。这就是为什么当您执行 GET 时,您将成功获得 HTTP 200 (OK)...但是 POST 不起作用。

另一方面,content_types_accepted 回调允许声明 content-types 接受什么。您确实可以发送 POST 请求,因为您在 allowed_methods 回调中添加了 <<"POST">> 但这将导致 HTTP 415 (Unsupported Media Type) 响应,因为 您还没有告诉 cowboy_rest 你想接受 application/json.

这应该对你有用:

-module(example_handler).

-export([init/2]).

-export([
  allowed_methods/2,
  content_types_accepted/2,
  content_types_provided/2
]).

-export([get_json/2, post_json/2]).

%%%==============================================
%%% Exports
%%%==============================================
init(Req, Opts) ->
  {cowboy_rest, Req, Opts}.

allowed_methods(Req, State) ->
  lager:debug("allowed_methods"),
  {[<<"GET">>, <<"POST">>], Req, State}.

content_types_accepted(Req, State) ->
  lager:debug("content_types_accepted"),
  {[
    {{<<"application">>, <<"json">>, []}, post_json}
  ], Req, State}.

content_types_provided(Req, State) ->
  lager:debug("content_types_provided"),
  {[
    {{<<"application">>, <<"json">>, []}, get_json}
  ], Req, State}.

get_json(Req, State) ->
  lager:debug("get_json"),
  {<<"{ \"hello\": \"there\" }">>, Req, State}.

post_json(Req, State) ->
  lager:debug("post_json"),
  {true, Req, State}.

%%%==============================================
%%% Internal
%%%==============================================