mochiweb adapter for cowboy.


mochicow is a mochiweb adapter for cowboy.

There are 2 ways to use mochicow:

  • as a ranch protocol: It will use the socket acceptor pool of ranch instead of the mochiweb one.

  • as a protocol upgrade. Like websockets you can upgrade a cowboy handler to use a mochiweb loop. It allows you to use both cowboy and mochiweb in your code.

Use the ranch socket pool with mochiweb

To use mochiweb with the ranch acceptor pool, you just need to use the mochicow_protocol module as the prococol when you start a cowboy listener. You pass the mochiweb loop in the protocol options via the loop property.



-export([start/0, stop/0, loop/1]).
-define(LOOP, {?MODULE, loop}).

start() ->
    {ok, _} = application:ensure_all_started(ranch),
    ranch:start_listener(http, 100,
                          ranch_tcp, [{port, 8000}],
                          mochicow_protocol, [{loop, ?LOOP}]).

stop() ->

loop(Req) ->
    Path = Req:get(path),
    Resource = case string:str(Path, "?") of
        0 -> Path;
        N -> string:substr(Path, 1, length(Path) - (N + 1))
    handle_request(Resource, Req).

handle_request("/hello", Req) ->
    Req:respond({200, [{"Content-Type", "text/html"}], <<"Hello to you as well">>});

handle_request(Path, Req) ->
    Get = Req:parse_qs(),
    Post = Req:parse_post(),
    User_agent = Req:get_header_value("user-agent"),
    erlang:display({get, Get}),
    erlang:display({post, Post}),
    erlang:display({user_agent, User_agent}),
    erlang:display({path, Path}),
    Req:respond({200, [{"Content-Type", "text/html"}], <<"Hello World!">>}).

Upgrade the protocol

You can use mochicow to quietly migrate your code from mochiweb to cowboy or use both at the sametime. To do that you will need to use the upgrade "sub-protocol" using mochicow_upgrade as the protocol and compile your code and the following option added to the erlang compiler flags:

{parse_transform, mochicow}

Alternately, you can add it to the module you wish to use with mochiweb:

-compile([{parse_transform, mochicow}]).

the mochicow parse_transform will replace at compilation any call to mochiweb_request by calls to mochicow_request. This is needed due to the way cowboy handle the first steps of the request keeping a buffer around.

Ex to start the cowboy_http_protocol:

-export([start/0, stop/0]).

-define(LOOP, {mochi_handler, loop}).

start() ->
    {ok, _= application:ensure_all_started(cowboy),
     Dispatch = cowboy_router:compile([

        {'_', [
               {'_', mochi_hello_handler, [{loop, {mochi_hello_handler, loop}}]}

    cowboy:start_http(http, 100,  [{port, 8080}], 
                      [{env, [{dispatch, Dispatch}]} ]).

stop() ->

The mochiweb handler:

-export([init/3, loop/1]).

init(_, _, _) ->
    {upgrade, protocol, mochicow_upgrade}.

loop(Req) ->
    Req:respond({200, [{"Content-Type", "text/html"}],
                 <<"Hello from mochiweb">>}).

Usage example

See more usage examples in the examples for the usage. For example launch the hello_cowboy application:

[upgrade_demo] rebar3 shell                                                                            2:39:25  ☁  master ☂ ⚡ ✭
===> Verifying dependencies...
===> Compiling mochicow
===> Compiling upgrade_demo
Erlang/OTP 18 [erts-7.3.1] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:0] [kernel-poll:false]

Eshell V7.3.1  (abort with ^G)
1> hello_cowboy:start().

And query the server you just launched:

An echo server running a mochiweb handler (mochi_echo_handler)

[~] curl -XPOST http://localhost:8080/echo -d'test echo'               2:39:50
test echo

A simple mochiweb handler mochi_hello_handler returning "hello":

[~] curl  http://localhost:8080/hello                                  9:30:22
Hello from mochiweb

The server is mixed with a cowboy habdler cowboy_hello_handler:

[~] curl  http://localhost:8080                                        9:32:04
Hello World!