Cowboy HTTP POST handlers

5.5k views Asked by At

I'm started learing Erlang. I want to write simple cowboy-based HTTP server, which can receive files sending via HTTP POST. So I create simple handler:

-module(handler).
-behaviour(cowboy_http_handler).
-export([init/3,handle/2,terminate/3]).

init({tcp, http}, Req, _Opts) ->
  {ok, Req, undefined_state}.

handle(Req, State) ->
  Body = <<"<h1>Test</h1>">>,
  {ok, Req2} = cowboy_req:reply(200, [], Body, Req),
  {ok, Req2, State}.

terminate(_Reason, _Req, _State) ->
  ok.

This code can handle GET request. But how can I process HTTP POST request?

4

There are 4 answers

1
Danil Onishchenko On BEST ANSWER

Your code handles requests with any HTTP methods. If you want to handle particular HTTP request method you have to test the method name in callback handle/2. Here you can see a simple example:

handle(Req, State) ->
    {Method, Req2} = cowboy_req:method(Req),
    case Method of
        <<"POST">> ->
            Body = <<"<h1>This is a response for POST</h1>">>;
        <<"GET">> ->
            Body = <<"<h1>This is a response for GET</h1>">>;
        _ ->
            Body = <<"<h1>This is a response for other methods</h1>">>
    end,
    {ok, Req3} = cowboy_req:reply(200, [], Body, Req2),
    {ok, Req3, State}.

To get a content of POST request you can use function cowboy_req:body_qs/2 for example. There are other functions for handling body of HTTP requests in cowboy. Check the documentation and choose the way which is convenient for you.

0
Oladipo Olasemo On

You can use cowboy_rest, implement the content_types_accepted/2 callback method like so:

 content_types_accepted(Req, State) ->
       case cowboy_req:method(Req) of
         {<<"POST">>, _ } ->
           Accepted = {[{<<"application/x-www-form-urlencoded">>, put_file}], Req, State};
         {<<"PUT">>, _ } ->
           Accepted = {[{<<"application/x-www-form-urlencoded">>, post_file}], Req, State}
       end,
 Accepted.

I think this way you can have separate handlers for different HTTP Verbs/Methods. This gives you cleaner code too :)

And the various handlers:

put_file(Req, State) ->

  {true, Req, State}.

post_file(Req, State) ->

  {true, Req, State}.
0
Eduardo On

You can work with 'cowboy_rest' for example: https://github.com/extend/cowboy/blob/master/examples/rest_pastebin/src/toppage_handler.erl

It gives you a more structured way to handle requests.

More info: http://ninenines.eu/docs/en/cowboy/HEAD/manual/cowboy_rest/

0
ErlangWannabe On

Here is a cowboy middleware that will append the method to your handler:

i.e. your handler will become handler_post

-module(middleware).

-export([execute/2]).

execute(Req0, Env0) ->
    {Method0, Req} = cowboy_req:method(Req0),
    Method1 = string:lowercase(Method0),
    Handler0 = proplists:get_value(handler, Env0),
    Handler = list_to_atom(atom_to_list(Handler0) ++ "_" ++ binary_to_list(Method1)),
    Env = [{handler, Handler} | proplists:delete(handler, Env0)],
    {ok, Req, Env}.