1 |
|
-module(mongoose_client_api_sse). |
2 |
|
|
3 |
|
-behaviour(mongoose_client_api). |
4 |
|
-export([routes/0]). |
5 |
|
|
6 |
|
-behaviour(lasse_handler). |
7 |
|
-export([init/3]). |
8 |
|
-export([handle_notify/2]). |
9 |
|
-export([handle_info/2]). |
10 |
|
-export([handle_error/3]). |
11 |
|
-export([terminate/3]). |
12 |
|
|
13 |
|
-include("mongoose.hrl"). |
14 |
|
-include("jlib.hrl"). |
15 |
|
|
16 |
|
-spec routes() -> mongoose_http_handler:routes(). |
17 |
|
routes() -> |
18 |
57 |
[{"/sse", lasse_handler, #{module => mongoose_client_api_sse}}]. |
19 |
|
|
20 |
|
init(_InitArgs, _LastEvtId, Req) -> |
21 |
4 |
?LOG_DEBUG(#{what => client_api_sse_init, req => Req}), |
22 |
4 |
{cowboy_rest, Req1, State0} = mongoose_client_api:init(Req, []), |
23 |
4 |
{Authorization, Req2, State} = mongoose_client_api:is_authorized(Req1, State0), |
24 |
|
% set 1h timeout to prevent client from frequent disconnections |
25 |
4 |
cowboy_req:cast({set_options, #{ |
26 |
|
idle_timeout => 3600000 |
27 |
|
}}, Req), |
28 |
4 |
maybe_init(Authorization, Req2, State#{id => 1}). |
29 |
|
|
30 |
|
maybe_init(true, Req, #{jid := JID} = State) -> |
31 |
4 |
Session = mongoose_stanza_api:open_session(JID, false), |
32 |
4 |
{ok, Req, State#{session => Session}}; |
33 |
|
maybe_init(true, Req, State) -> |
34 |
|
%% This is for OPTIONS method |
35 |
:-( |
{shutdown, 200, #{}, <<>>, Req, State}; |
36 |
|
maybe_init({false, Value}, Req, State) -> |
37 |
:-( |
Headers = #{<<"www-authenticate">> => Value}, |
38 |
:-( |
{shutdown, 401, Headers, <<>>, Req, State}. |
39 |
|
|
40 |
|
handle_notify(Msg, State) -> |
41 |
:-( |
?UNEXPECTED_INFO(Msg), |
42 |
:-( |
{nosend, State}. |
43 |
|
|
44 |
|
handle_info({route, Acc}, State) -> |
45 |
5 |
#xmlel{ name = TagName } = El = mongoose_acc:element(Acc), |
46 |
5 |
handle_msg(TagName, Acc, El, State); |
47 |
|
handle_info(Msg, State) -> |
48 |
:-( |
?UNEXPECTED_INFO(Msg), |
49 |
:-( |
{nosend, State}. |
50 |
|
|
51 |
|
handle_msg(<<"message">>, Acc, El, State) -> |
52 |
5 |
Timestamp = os:system_time(microsecond), |
53 |
5 |
Type = mongoose_acc:stanza_type(Acc), |
54 |
5 |
maybe_send_message_event(Type, El, Timestamp, State). |
55 |
|
|
56 |
|
handle_error(Msg, Reason, State) -> |
57 |
:-( |
?LOG_WARNING(#{what => sse_handle_error, msg => Msg, reason => Reason}), |
58 |
:-( |
{nosend, State}. |
59 |
|
|
60 |
|
terminate(_Reason, _Req, #{session := Session}) -> |
61 |
:-( |
mongoose_stanza_api:close_session(Session), |
62 |
:-( |
ok; |
63 |
|
terminate(_Reason, _Req, _State) -> |
64 |
:-( |
ok. |
65 |
|
|
66 |
|
maybe_send_message_event(<<"chat">>, Packet, Timestamp, #{id := ID} = State) -> |
67 |
3 |
Data = jiffy:encode(mongoose_client_api_messages:encode(Packet, Timestamp)), |
68 |
3 |
Event = #{id => integer_to_binary(ID), event => <<"message">>, data => Data}, |
69 |
3 |
{send, Event, State#{id := ID + 1}}; |
70 |
|
maybe_send_message_event(<<"groupchat">>, Packet, Timestamp, #{id := ID} = State) -> |
71 |
2 |
Data = jiffy:encode(mongoose_client_api_rooms_messages:encode(Packet, Timestamp)), |
72 |
2 |
Event = #{id => integer_to_binary(ID), event => <<"room.message">>, data => Data}, |
73 |
2 |
{send, Event, State#{id := ID + 1}}; |
74 |
|
maybe_send_message_event(_, _, _, State) -> |
75 |
:-( |
{nosend, State}. |