0
Fork 0
mirror of https://github.com/ninenines/cowboy.git synced 2025-07-14 12:20:24 +00:00
cowboy/guide/loop_handlers.md
Loïc Hoguin 647e95aed1 Replace terminate/2 with terminate/3, adding a Reason
This should have been done a *long* time ago, back when I initially
added Websocket support. This is the first part of two in improving
loop handler support with regards to socket closure.

Reason may include: {normal, shutdown} for the most normal shutdown,
{normal, timeout} for a loop handler timeout shutdown, or {error, _}
if an error occured.
2013-01-22 02:34:18 +01:00

1.9 KiB

Loop handlers

Purpose

Loop handlers are a special kind of HTTP handlers used when the response can not be sent right away. The handler enters instead a receive loop waiting for the right message before it can send a response.

They are most useful when performing long-polling operations or when using server-sent events.

While the same can be accomplished using plain HTTP handlers, it is recommended to use loop handlers because they are well-tested and allow using built-in features like hibernation and timeouts.

Usage

Loop handlers are used for requests where a response might not be immediately available, but where you would like to keep the connection open for a while in case the response arrives. The most known example of such practice is known as long-polling.

Loop handlers can also be used for requests where a response is partially available and you need to stream the response body while the connection is open. The most known example of such practice is known as server-sent events.

Loop handlers essentially wait for one or more Erlang messages and feed these messages to the info/3 callback. It also features the init/3 and terminate/3 callbacks which work the same as for plain HTTP handlers.

The following handler waits for a message {reply, Body} before sending a response. If this message doesn't arrive within 60 seconds, it gives up and a 204 No Content will be replied. It also hibernates the process to save memory while waiting for this message.

-module(my_loop_handler).
-behaviour(cowboy_loop_handler).

-export([init/3]).
-export([info/3]).
-export([terminate/3]).

init({tcp, http}, Req, Opts) ->
    {loop, Req, undefined_state, 60000, hibernate}.

info({reply, Body}, Req, State) ->
    {ok, Req2} = cowboy_req:reply(200, [], Body, Req),
    {ok, Req2, State};
info(Message, Req, State) ->
    {loop, Req, State, hibernate}.

terminate(Reason, Req, State) ->
    ok.