2
votes

How can I set status code in my REST POST resource.

Now I'm doing this

make_post(Req, State) ->
  lager:info("post"),
  Resp = cowboy_req:set_resp_body(<<"HELLO POST\n">>, Req),
  {ok, Resp3} = cowboy_req:reply(201, Resp),
  {true, Resp3, State}.

But I receive such errors:

1:43:10.510 [info] [nonode@nohost#pbshare_logic_registration#<0.205.0>] [handle_info#35] :Exit Logic from <0.204.0> Reason: {function_clause,[{cowboy_req,reply,[204,[],<<>>,{http_req,#Port<0.6355>,ranch_tcp,keepalive,<0.204.0>,<<"POST">>,'HTTP/1.1',{{127,0,0,1},50024},<<"localhost">>,undefined,8080,<<"/rest/registration/make">>,[<<"make">>],<<>>,undefined,[],[{<<"user-agent">>,<<"curl/7.29.0">>},{<<"host">>,<<"localhost:8080">>},{<<"accept">>,<<"/">>},{<<"content-type">>,<<"application/json">>},{<<"content-length">>,<<"14">>}],[{<<"content-length">>,14},{<<"expect">>,undefined},{<<"content-length">>,14},{<<"content-type">>,{<<"application">>,<<"json">>,[]}},{<<"if-modified-since">>,undefined},{<<"if-none-match">>,undefined},{<<"if-unmodified-since">>,undefined},{<<"if-match">>,undefined},{<<"accept">>,[{{<<"">>,<<"">>,[]},1000,[]}]}],undefined,[{charset,undefined},{media_type,{<<"application">>,<<"json">>,[]}}],done,undefined,<<>>,false,done,[],<<>>,undefined}],[{file,"src/cowboy_req.erl"},{line,948}]},{cowboy_rest,respond,3,[{file,"src/cowboy_rest.erl"},{line,1085}]},{cowboy_rest,upgrade,4,[{file,"src/cowboy_rest.erl"},{line,75}]},{cowboy_protocol,execute,4,[{file,"src/cowboy_protocol.erl"},{line,523}]}]} 21:43:10.510 [error] [Undefined#Undefined#emulator] [Undefined#Undefined] :Error in process <0.204.0> with exit value: {function_clause,[{cowboy_req,reply,[204,[],<<0 bytes>>,{http_req,#Port<0.6355>,ranch_tcp,keepalive,<0.204.0>,<<4 bytes>>,'HTTP/1.1',{{127,0,0,1},50024},<<9 bytes>>,undefined,8080,<<23 bytes>>,[<<4 bytes>>],<<0 bytes>>,undefined,[],[{<<10 bytes>>,<<11 bytes>>},{<<4 bytes>>,<<14 bytes>>},{<<6 bytes>>,<<3 bytes>>},{<<12 bytes>>,<<16 bytes>>},{<<14 bytes>>,<<2 bytes>>}],[{<<14 bytes>>,14},{<<6 bytes>>,undefined},{<<14 bytes>>,14},{<<12 bytes>>,{<<11 bytes>>,<<4 bytes>>,[]}},{<<17 bytes>>,undefined},{<<13 bytes>>,undefined},{<<19 bytes>>,undefined},{<<8 bytes>>,undefined...

It seems that cowboy tries to send response once again after my reply. But I didn't any other method in API which can change status code.

2
In your code, what does set_response_body do? Is it supposed to do the same thing as cowboy_req:set_response_body/2?mbesso
yes, it does Resp3 = cowboy_req:set_resp_body(<<"HELLO POST\n">>, Req)Max Grigoriev
I'm not totally clear on what you're saying your set_response_body does -- do you mind adding it to your question?jtmoulia
I modified my question and added cowboy_req:set_resp_body.Max Grigoriev

2 Answers

8
votes

The right solution is to return not {true, Resp3, State}. but {halt, Resp3, State}. In this case cowboy doesn't continue processing the request.

2
votes

Cowboy's rest-handler will attempt to set the response status code according to the return values of the callback functions (see http://ninenines.eu/docs/en/cowboy/HEAD/guide/rest_handlers).

In order to indicate that a resource has been created (returning 201) you hence need to implement the callback for resource_exists in addition to the body-creating function. You will also need to indicate the url for the newly created resource in the body-creating function.

Here is what I think will work for you (remember to export resource_exists or the default function will be used):

resource_exists(Req, State) ->
    {false, Req, State}.

make_post(Req, State) ->
    Req2 = cowboy_req:set_resp_body(<<"Hello world">>, Req),
    {{true, "/foo/bar"}, Req2, State}.