Web Development

40.1 Cowboy — HTTP/1.1, HTTP/2, WebSocket server

WebSocket handler:

Other Cowboy features: REST handlers (cowboy_rest with content negotiation callbacks), middlewares, streaming, HTTP/2, TLS (cowboy:start_tls).

%% rebar.config: {deps, [cowboy]}.
-module(hello_app).
-behaviour(application).
-export([start/2, stop/1]).

start(_Type, _Args) ->
    Dispatch = cowboy_router:compile([
        {'_', [
            {"/", hello_handler, []},
            {"/users/:id", user_handler, []},
            {"/ws", ws_handler, []},
            {"/static/[...]", cowboy_static, {priv_dir, hello, "static"}}
        ]}
    ]),
    {ok, _} = cowboy:start_clear(http_listener, [{port, 8080}], #{env => #{dispatch => Dispatch}}),
    hello_sup:start_link().

stop(_State) -> ok = cowboy:stop_listener(http_listener).
-module(hello_handler).
-export([init/2]).

init(Req0, State) ->
    Req = cowboy_req:reply(200, #{<<"content-type">> => <<"text/plain">>}, <<"Hello, Erlang!">>, Req0),
    {ok, Req, State}.
-module(user_handler).
-export([init/2]).

init(Req0 = #{method := <<"GET">>}, State) ->
    Id = cowboy_req:binding(id, Req0),
    Body = iolist_to_binary(json:encode(#{id => Id, name => <<"Ann">>})),
    Req = cowboy_req:reply(200, #{<<"content-type">> => <<"application/json">>}, Body, Req0),
    {ok, Req, State};
init(Req0, State) ->
    {ok, cowboy_req:reply(405, Req0), State}.
-module(ws_handler).
-export([init/2, websocket_init/1, websocket_handle/2, websocket_info/2]).

init(Req, State) -> {cowboy_websocket, Req, State}.
websocket_init(State) -> {[{text, <<"welcome">>}], State}.
websocket_handle({text, Msg}, State) -> {[{text, <<"echo: ", Msg/binary>>}], State};
websocket_handle(_, State) -> {[], State}.
websocket_info({broadcast, Msg}, State) -> {[{text, Msg}], State};
websocket_info(_, State) -> {[], State}.

40.2 Other web frameworks & servers

full web framework on Cowboy (routing, controllers, templates, plugins) minimal, fast HTTP server older HTTP toolkit full-featured web server (one of the oldest) built into OTP

40.3 HTTP clients

Popular libraries: hackney, gun (HTTP/1.1, HTTP/2, WebSocket client), katipo, shotgun.

%% Built-in httpc (inets)
inets:start(), ssl:start(),
{ok, {{_, 200, _}, _Headers, Body}} = httpc:request(get, {"https://example.com", []},
    [{ssl, [{verify, verify_peer}, {cacerts, public_key:cacerts_get()}]}], []).

40.4 Databases & storage

PostgreSQL: epgsql, pgo MySQL: mysql-otp Redis: eredis Cassandra: marina, erlcass

Embedded: ETS, DETS, Mnesia, leveled, eleveldb, esqlite

Erlang-built databases: CouchDB, Riak, Khepri (Raft-based tree store, RabbitMQ)

40.5 Messaging

RabbitMQ (AMQP broker, written in Erlang) + amqp_client EMQX, VerneMQ (MQTT brokers) brod (Kafka client)