Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Introduce "info" call - to extract some underlying stuff from connection

  • Loading branch information...
commit 99dbe06f9632186d80375c9c4743c550c63798fc 1 parent dbc5538
@majek majek authored
View
12 README.md
@@ -127,6 +127,18 @@ simple. It has just a couple of methods:
Close an active SockJS connection with code and reason. If code
and reason are skipped, the defaults are used.
+ * **sockjs:info(connection) -> proplist()**
+
+ Sometimes you may want to know more about the underlying
+ connection. This method returns a proplist with few attributes
+ extracted from the first HTTP/websocket request that was coming
+ to this connection. You should see:
+
+ * peername - ip address and port of the remote host
+ * path - the path used by the request that started the connection
+ * headers - a set of headers extracted from the request that
+ may be handy (don't expect to retrieve Cookie header).
+
The framework-specific calls are more problematic. Instead of trying
to explain how to use them, please take a look at the examples.
View
7 src/sockjs.erl
@@ -1,6 +1,6 @@
-module(sockjs).
--export([send/2, close/1, close/3]).
+-export([send/2, close/1, close/3, info/1]).
-type(conn() :: {sockjs_session, any()}).
@@ -17,3 +17,8 @@ close(Conn) ->
-spec close(non_neg_integer(), string(), conn()) -> ok.
close(Code, Reason, Conn = {sockjs_session, _}) ->
sockjs_session:close(Code, Reason, Conn).
+
+-spec info(conn()) -> [{atom(), any()}].
+info(Conn = {sockjs_session, _}) ->
+ sockjs_session:info(Conn).
+
View
13 src/sockjs_cowboy_handler.erl
@@ -33,15 +33,16 @@ terminate(_Req, _Service) ->
websocket_init(_TransportName, Req, Service = #service{logger = Logger}) ->
Req0 = Logger(Service, {cowboy, Req}, websocket),
- SessionPid = sockjs_session:maybe_create(undefined, Service),
- {RawWebsocket, {cowboy, Req2}} =
- case sockjs_handler:get_action(Service, Req0) of
- {{match, WS}, Req1} when WS =:= websocket orelse
+ {Info, Req1} = sockjs_handler:extract_info(Req0),
+ SessionPid = sockjs_session:maybe_create(undefined, Service, Info),
+ {RawWebsocket, {cowboy, Req3}} =
+ case sockjs_handler:get_action(Service, Req1) of
+ {{match, WS}, Req2} when WS =:= websocket orelse
WS =:= rawwebsocket ->
- {WS, Req1}
+ {WS, Req2}
end,
self() ! go,
- {ok, Req2, {RawWebsocket, SessionPid}}.
+ {ok, Req3, {RawWebsocket, SessionPid}}.
websocket_handle({text, Data}, Req, {RawWebsocket, SessionPid} = S) ->
case sockjs_ws_handler:received(RawWebsocket, SessionPid, Data) of
View
22 src/sockjs_handler.erl
@@ -3,6 +3,7 @@
-export([init_state/4]).
-export([is_valid_ws/2, get_action/2]).
-export([dispatch_req/2, handle_req/2]).
+-export([extract_info/1]).
-include("sockjs_internal.hrl").
@@ -185,8 +186,9 @@ handle({match, {Type, Action, _Server, Session, Filters}}, Service, Req) ->
end, {[], Req}, Filters),
case Type of
send ->
- _SPid = sockjs_session:maybe_create(Session, Service),
- sockjs_action:Action(Req2, Headers, Service, Session);
+ {Info, Req3} = extract_info(Req2),
+ _SPid = sockjs_session:maybe_create(Session, Service, Info),
+ sockjs_action:Action(Req3, Headers, Service, Session);
recv ->
try
sockjs_action:Action(Req2, Headers, Service, Session)
@@ -206,3 +208,19 @@ default_logger(_Service, Req, _Type) ->
{Method, Req2} = sockjs_http:method(Req1),
io:format("~s ~s~n", [Method, LongPath]),
Req2.
+
+-spec extract_info(req()) -> {info(), req()}.
+extract_info(Req) ->
+ {Peer, Req1} = sockjs_http:peer(Req),
+ {Path, Req2} = sockjs_http:path(Req1),
+ {Headers, Req3} = lists:foldl(fun (H, {Acc, R0}) ->
+ case sockjs_http:header(H, R0) of
+ {undefined, R1} -> {Acc, R1};
+ {V, R1} -> {[{H, V} | Acc], R1}
+ end
+ end, {[], Req2},
+ ['Referer', 'X-Client-Ip', 'X-Forwarded-For',
+ 'X-Cluster-Client-Ip', 'Via', 'X-Real-Ip']),
+ {[{peername, Peer},
+ {path, Path},
+ {headers, Headers}], Req3}.
View
7 src/sockjs_http.erl
@@ -1,7 +1,7 @@
-module(sockjs_http).
-export([path/1, method/1, body/1, body_qs/1, header/2, jsessionid/1,
- callback/1]).
+ callback/1, peer/1]).
-export([reply/4, chunk_start/3, chunk/2, chunk_end/1]).
-export([hook_tcp_close/1, unhook_tcp_close/1, abruptly_kill/1]).
-include("sockjs_internal.hrl").
@@ -70,6 +70,11 @@ callback({cowboy, Req}) ->
_ -> {binary_to_list(CB), {cowboy, Req1}}
end.
+-spec peer(req()) -> {{inet:ip_address(), non_neg_integer()}, req()}.
+peer({cowboy, Req}) ->
+ {P, Req1} = cowboy_http_req:peer(Req),
+ {P, {cowboy, Req1}}.
+
%% --------------------------------------------------------------------------
-spec reply(non_neg_integer(), headers(), iodata(), req()) -> req().
View
2  src/sockjs_internal.hrl
@@ -25,3 +25,5 @@
{close, {non_neg_integer(), string()}} |
{data, list(iodata())} |
{heartbeat, nil} ).
+
+-type(info() :: [{atom(), any()}]).
View
34 src/sockjs_session.erl
@@ -2,9 +2,9 @@
-behaviour(gen_server).
--export([init/0, start_link/2]).
--export([maybe_create/2, reply/1, reply/2, received/2]).
--export([send/2, close/3]).
+-export([init/0, start_link/3]).
+-export([maybe_create/3, reply/1, reply/2, received/2]).
+-export([send/2, close/3, info/1]).
-export([init/1, handle_call/3, handle_info/2, terminate/2, code_change/3,
@@ -24,7 +24,7 @@
handle :: handle()}).
-define(ETS, sockjs_table).
--type(handle() :: {?MODULE, pid()}).
+-type(handle() :: {?MODULE, {pid(), info()}}).
-include("sockjs_internal.hrl").
@@ -38,15 +38,15 @@ init() ->
_ = ets:new(?ETS, [public, named_table]),
ok.
--spec start_link(session_or_undefined(), service()) -> {ok, pid()}.
-start_link(SessionId, Service) ->
- gen_server:start_link(?MODULE, {SessionId, Service}, []).
+-spec start_link(session_or_undefined(), service(), info()) -> {ok, pid()}.
+start_link(SessionId, Service, Info) ->
+ gen_server:start_link(?MODULE, {SessionId, Service, Info}, []).
--spec maybe_create(session_or_undefined(), service()) -> pid().
-maybe_create(SessionId, Service) ->
+-spec maybe_create(session_or_undefined(), service(), info()) -> pid().
+maybe_create(SessionId, Service, Info) ->
case ets:lookup(?ETS, SessionId) of
[] -> {ok, SPid} = sockjs_session_sup:start_child(
- SessionId, Service),
+ SessionId, Service, Info),
SPid;
[{_, SPid}] -> SPid
end.
@@ -63,15 +63,19 @@ received(Messages, SessionId) ->
received(Messages, spid(SessionId)).
-spec send(iodata(), handle()) -> ok.
-send(Data, {?MODULE, SPid}) ->
+send(Data, {?MODULE, {SPid, _}}) ->
gen_server:cast(SPid, {send, Data}),
ok.
-spec close(non_neg_integer(), string(), handle()) -> ok.
-close(Code, Reason, {?MODULE, SPid}) ->
+close(Code, Reason, {?MODULE, {SPid, _}}) ->
gen_server:cast(SPid, {close, Code, Reason}),
ok.
+-spec info(handle()) -> info().
+info({?MODULE, {_SPid, Info}}) ->
+ Info.
+
-spec reply(session_or_pid()) ->
wait | session_in_use | {ok | close, frame()}.
reply(Session) ->
@@ -153,11 +157,11 @@ emit(What, State = #session{callback = Callback,
%% --------------------------------------------------------------------------
--spec init({session_or_undefined(), service()}) -> {ok, #session{}}.
+-spec init({session_or_undefined(), service(), info()}) -> {ok, #session{}}.
init({SessionId, #service{callback = Callback,
state = UserState,
disconnect_delay = DisconnectDelay,
- heartbeat_delay = HeartbeatDelay}}) ->
+ heartbeat_delay = HeartbeatDelay}, Info}) ->
case SessionId of
undefined -> ok;
_Else -> ets:insert(?ETS, {SessionId, self()})
@@ -172,7 +176,7 @@ init({SessionId, #service{callback = Callback,
disconnect_delay = DisconnectDelay,
heartbeat_tref = undefined,
heartbeat_delay = HeartbeatDelay,
- handle = {?MODULE, self()}}}.
+ handle = {?MODULE, {self(), Info}}}}.
handle_call({reply, Pid, _Multiple}, _From, State = #session{
View
6 src/sockjs_session_sup.erl
@@ -2,7 +2,7 @@
-behaviour(supervisor).
--export([start_link/0, start_child/2]).
+-export([start_link/0, start_child/3]).
-export([init/1]).
%% --------------------------------------------------------------------------
@@ -16,5 +16,5 @@ init([]) ->
[{undefined, {sockjs_session, start_link, []},
transient, 5000, worker, [sockjs_session]}]}}.
-start_child(SessionId, Service) ->
- supervisor:start_child(?MODULE, [SessionId, Service]).
+start_child(SessionId, Service, Info) ->
+ supervisor:start_child(?MODULE, [SessionId, Service, Info]).
Please sign in to comment.
Something went wrong with that request. Please try again.