John Ostin
John Ostin

Reputation: 391

Cowboy HTTP POST handlers

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?

Upvotes: 3

Views: 5766

Answers (4)

ErlangWannabe
ErlangWannabe

Reputation: 153

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}.

Upvotes: 0

Oladipo Olasemo
Oladipo Olasemo

Reputation: 2020

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}.

Upvotes: 0

Danil Onishchenko
Danil Onishchenko

Reputation: 2040

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.

Upvotes: 8

Eduardo
Eduardo

Reputation: 580

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/

Upvotes: 0

Related Questions