blob: 96058d39e90e8962b38ca210d12afd9001b31a2f [file] [log] [blame]
-module(couch_dbupdates_httpd).
-export([handle_req/1]).
-include_lib("couch_db.hrl").
-record(state, {resp, feed}).
handle_req(#httpd{method='GET'}=Req) ->
ok = couch_httpd:verify_is_server_admin(Req),
Qs = couch_httpd:qs(Req),
Feed = proplists:get_value("feed", Qs, "longpoll"),
Timeout = list_to_integer(
proplists:get_value("timeout", Qs, "60000")
),
Heartbeat0 = proplists:get_value("heartbeat", Qs),
Heartbeat = case {Feed, Heartbeat0} of
{"longpoll", _} -> false;
{_, "false"} -> false;
_ -> true
end,
Options = [{timeout, Timeout}, {heartbeat, Heartbeat}],
{ok, Resp} = case Feed of
"eventsource" ->
Headers = [
{"Content-Type", "text/event-stream"},
{"Cache-Control", "no-cache"}
],
couch_httpd:start_json_response(Req, 200, Headers);
_ ->
couch_httpd:start_json_response(Req, 200)
end,
State = #state{resp=Resp, feed=Feed},
couch_dbupdates:handle_dbupdates(fun handle_update/2,
State, Options).
handle_req(Req, _Db) ->
couch_httpd:send_method_not_allowed(Req, "GET").
handle_update(stop, #state{resp=Resp}) ->
couch_httpd:end_json_response(Resp);
handle_update(heartbeat, #state{resp=Resp}=State) ->
{ok, Resp1} = couch_httpd:send_chunk(Resp, "\n"),
{ok, State#state{resp=Resp1}};
handle_update(Event, #state{resp=Resp, feed="eventsource"}=State) ->
EventObj = event_obj(Event),
{ok, Resp1} = couch_httpd:send_chunk(Resp, ["data: ",
?JSON_ENCODE(EventObj),
"\n\n"]),
{ok, State#state{resp=Resp1}};
handle_update(Event, #state{resp=Resp, feed="continuous"}=State) ->
EventObj = event_obj(Event),
{ok, Resp1} = couch_httpd:send_chunk(Resp, [?JSON_ENCODE(EventObj) |
"\n"]),
{ok, State#state{resp=Resp1}};
handle_update(Event, #state{resp=Resp, feed="longpoll"}) ->
{Props} = event_obj(Event),
JsonObj = {[{<<"ok">>, true} | Props]},
couch_httpd:send_chunk(Resp, ?JSON_ENCODE(JsonObj)),
stop.
event_obj({Type, DbName}) ->
{[{<<"type">>, couch_util:to_binary(Type)},
{<<"db_name">>, couch_util:to_binary(DbName)}]}.