Process XML-RPC requests via p1_xml and ejabberd_http
This commit is contained in:
parent
e109f352e3
commit
1d782db84f
|
@ -31,5 +31,6 @@
|
||||||
host = <<"">> :: binary(),
|
host = <<"">> :: binary(),
|
||||||
port = 5280 :: inet:port_number(),
|
port = 5280 :: inet:port_number(),
|
||||||
tp = http, % :: protocol(),
|
tp = http, % :: protocol(),
|
||||||
|
opts = [] :: list(),
|
||||||
headers = [] :: [{atom() | binary(), binary()}]}).
|
headers = [] :: [{atom() | binary(), binary()}]}).
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,7 @@ Deps = [{p1_cache_tab, ".*", {git, "git://github.com/processone/cache_tab"}},
|
||||||
{esip, ".*", {git, "git://github.com/processone/p1_sip"}},
|
{esip, ".*", {git, "git://github.com/processone/p1_sip"}},
|
||||||
{p1_stun, ".*", {git, "git://github.com/processone/stun"}},
|
{p1_stun, ".*", {git, "git://github.com/processone/stun"}},
|
||||||
{p1_yaml, ".*", {git, "git://github.com/processone/p1_yaml"}},
|
{p1_yaml, ".*", {git, "git://github.com/processone/p1_yaml"}},
|
||||||
{xmlrpc, ".*", {git, "git://github.com/rds13/xmlrpc"}},
|
{ehyperloglog, ".*", {git, "https://github.com/vaxelfel/eHyperLogLog.git"}},
|
||||||
{p1_utils, ".*", {git, "git://github.com/processone/p1_utils"}}],
|
{p1_utils, ".*", {git, "git://github.com/processone/p1_utils"}}],
|
||||||
|
|
||||||
ConfigureCmd = fun(Pkg, Flags) ->
|
ConfigureCmd = fun(Pkg, Flags) ->
|
||||||
|
|
|
@ -65,6 +65,7 @@
|
||||||
request_tp,
|
request_tp,
|
||||||
request_headers = [],
|
request_headers = [],
|
||||||
end_of_request = false,
|
end_of_request = false,
|
||||||
|
options = [],
|
||||||
default_host,
|
default_host,
|
||||||
trail = <<>>
|
trail = <<>>
|
||||||
}).
|
}).
|
||||||
|
@ -133,6 +134,10 @@ init({SockMod, Socket}, Opts) ->
|
||||||
true -> [{[<<"http-poll">>], ejabberd_http_poll}];
|
true -> [{[<<"http-poll">>], ejabberd_http_poll}];
|
||||||
false -> []
|
false -> []
|
||||||
end,
|
end,
|
||||||
|
XMLRPC = case proplists:get_bool(xmlrpc, Opts) of
|
||||||
|
true -> [{[], ejabberd_xmlrpc}];
|
||||||
|
false -> []
|
||||||
|
end,
|
||||||
DefinedHandlers = gen_mod:get_opt(
|
DefinedHandlers = gen_mod:get_opt(
|
||||||
request_handlers, Opts,
|
request_handlers, Opts,
|
||||||
fun(Hs) ->
|
fun(Hs) ->
|
||||||
|
@ -141,7 +146,7 @@ init({SockMod, Socket}, Opts) ->
|
||||||
Mod} || {Path, Mod} <- Hs]
|
Mod} || {Path, Mod} <- Hs]
|
||||||
end, []),
|
end, []),
|
||||||
RequestHandlers = DefinedHandlers ++ Captcha ++ Register ++
|
RequestHandlers = DefinedHandlers ++ Captcha ++ Register ++
|
||||||
Admin ++ Bind ++ Poll,
|
Admin ++ Bind ++ Poll ++ XMLRPC,
|
||||||
?DEBUG("S: ~p~n", [RequestHandlers]),
|
?DEBUG("S: ~p~n", [RequestHandlers]),
|
||||||
|
|
||||||
DefaultHost = gen_mod:get_opt(default_host, Opts, fun(A) -> A end, undefined),
|
DefaultHost = gen_mod:get_opt(default_host, Opts, fun(A) -> A end, undefined),
|
||||||
|
@ -150,6 +155,7 @@ init({SockMod, Socket}, Opts) ->
|
||||||
State = #state{sockmod = SockMod1,
|
State = #state{sockmod = SockMod1,
|
||||||
socket = Socket1,
|
socket = Socket1,
|
||||||
default_host = DefaultHost,
|
default_host = DefaultHost,
|
||||||
|
options = Opts,
|
||||||
request_handlers = RequestHandlers},
|
request_handlers = RequestHandlers},
|
||||||
receive_headers(State).
|
receive_headers(State).
|
||||||
|
|
||||||
|
@ -359,7 +365,7 @@ process(Handlers, Request) ->
|
||||||
false -> process(HandlersLeft, Request)
|
false -> process(HandlersLeft, Request)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
process_request(#state{request_method = Method,
|
process_request(#state{request_method = Method, options = Options,
|
||||||
request_path = {abs_path, Path}, request_auth = Auth,
|
request_path = {abs_path, Path}, request_auth = Auth,
|
||||||
request_lang = Lang, request_handlers = RequestHandlers,
|
request_lang = Lang, request_handlers = RequestHandlers,
|
||||||
request_host = Host, request_port = Port,
|
request_host = Host, request_port = Port,
|
||||||
|
@ -389,6 +395,7 @@ process_request(#state{request_method = Method,
|
||||||
IP = analyze_ip_xff(IPHere, XFF, Host),
|
IP = analyze_ip_xff(IPHere, XFF, Host),
|
||||||
Request = #request{method = Method,
|
Request = #request{method = Method,
|
||||||
path = LPath,
|
path = LPath,
|
||||||
|
opts = Options,
|
||||||
q = LQuery,
|
q = LQuery,
|
||||||
auth = Auth,
|
auth = Auth,
|
||||||
lang = Lang,
|
lang = Lang,
|
||||||
|
@ -413,7 +420,7 @@ process_request(#state{request_method = Method,
|
||||||
make_text_output(State, Status, Headers, Output)
|
make_text_output(State, Status, Headers, Output)
|
||||||
end
|
end
|
||||||
end;
|
end;
|
||||||
process_request(#state{request_method = Method,
|
process_request(#state{request_method = Method, options = Options,
|
||||||
request_path = {abs_path, Path}, request_auth = Auth,
|
request_path = {abs_path, Path}, request_auth = Auth,
|
||||||
request_content_length = Len, request_lang = Lang,
|
request_content_length = Len, request_lang = Lang,
|
||||||
sockmod = SockMod, socket = Socket, request_host = Host,
|
sockmod = SockMod, socket = Socket, request_host = Host,
|
||||||
|
@ -450,6 +457,7 @@ process_request(#state{request_method = Method,
|
||||||
Request = #request{method = Method,
|
Request = #request{method = Method,
|
||||||
path = LPath,
|
path = LPath,
|
||||||
q = LQuery,
|
q = LQuery,
|
||||||
|
opts = Options,
|
||||||
auth = Auth,
|
auth = Auth,
|
||||||
data = Data,
|
data = Data,
|
||||||
lang = Lang,
|
lang = Lang,
|
||||||
|
|
|
@ -201,11 +201,7 @@ listen_tcp(PortIP, Module, SockOpts, Port, IPS) ->
|
||||||
catch
|
catch
|
||||||
_:_ -> []
|
_:_ -> []
|
||||||
end,
|
end,
|
||||||
DeliverAs = case Module of
|
Res = gen_tcp:listen(Port, [binary,
|
||||||
ejabberd_xmlrpc -> list;
|
|
||||||
_ -> binary
|
|
||||||
end,
|
|
||||||
Res = gen_tcp:listen(Port, [DeliverAs,
|
|
||||||
{packet, 0},
|
{packet, 0},
|
||||||
{active, false},
|
{active, false},
|
||||||
{reuseaddr, true},
|
{reuseaddr, true},
|
||||||
|
|
|
@ -17,11 +17,12 @@
|
||||||
|
|
||||||
-author('badlop@process-one.net').
|
-author('badlop@process-one.net').
|
||||||
|
|
||||||
-export([start/2, handler/2, socket_type/0, transform_listen_option/2]).
|
-export([start/2, handler/2, process/2, socket_type/0,
|
||||||
|
transform_listen_option/2]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("logger.hrl").
|
-include("logger.hrl").
|
||||||
|
-include("ejabberd_http.hrl").
|
||||||
-include("mod_roster.hrl").
|
-include("mod_roster.hrl").
|
||||||
|
|
||||||
-include("jlib.hrl").
|
-include("jlib.hrl").
|
||||||
|
@ -170,12 +171,14 @@
|
||||||
%% -----------------------------
|
%% -----------------------------
|
||||||
|
|
||||||
start({gen_tcp = _SockMod, Socket}, Opts) ->
|
start({gen_tcp = _SockMod, Socket}, Opts) ->
|
||||||
%MaxSessions = gen_mod:get_opt(maxsessions, Opts,
|
ejabberd_http:start({gen_tcp, Socket}, [{xmlrpc, true}|Opts]).
|
||||||
% fun(I) when is_integer(I), I>0 -> I end,
|
|
||||||
% 10),
|
socket_type() -> raw.
|
||||||
Timeout = gen_mod:get_opt(timeout, Opts,
|
|
||||||
fun(I) when is_integer(I), I>0 -> I end,
|
%% -----------------------------
|
||||||
5000),
|
%% HTTP interface
|
||||||
|
%% -----------------------------
|
||||||
|
process(_, #request{method = 'POST', data = Data, opts = Opts}) ->
|
||||||
AccessCommandsOpts = gen_mod:get_opt(access_commands, Opts,
|
AccessCommandsOpts = gen_mod:get_opt(access_commands, Opts,
|
||||||
fun(L) when is_list(L) -> L end,
|
fun(L) when is_list(L) -> L end,
|
||||||
[]),
|
[]),
|
||||||
|
@ -201,19 +204,28 @@ start({gen_tcp = _SockMod, Socket}, Opts) ->
|
||||||
[?MODULE, Wrong]),
|
[?MODULE, Wrong]),
|
||||||
[]
|
[]
|
||||||
end, AccessCommandsOpts),
|
end, AccessCommandsOpts),
|
||||||
GetAuth = case [ACom
|
GetAuth = case [ACom || {Ac, _, _} = ACom <- AccessCommands, Ac /= all] of
|
||||||
|| {Ac, _, _} = ACom <- AccessCommands, Ac /= all]
|
[] -> false;
|
||||||
of
|
_ -> true
|
||||||
[] -> false;
|
|
||||||
_ -> true
|
|
||||||
end,
|
end,
|
||||||
Handler = {?MODULE, handler},
|
State = #state{access_commands = AccessCommands, get_auth = GetAuth},
|
||||||
State = #state{access_commands = AccessCommands,
|
case xmlrpc_decode:payload(Data) of
|
||||||
get_auth = GetAuth},
|
{error, _} = Err ->
|
||||||
Pid = proc_lib:spawn(xmlrpc_http, handler, [Socket, Timeout, Handler, State]),
|
?ERROR_MSG("XML-RPC request ~s failed with reason: ~p",
|
||||||
{ok, Pid}.
|
[Data, Err]),
|
||||||
|
{400, [],
|
||||||
socket_type() -> raw.
|
#xmlel{name = <<"h1">>, attrs = [],
|
||||||
|
children = [{xmlcdata, <<"Malformed Request">>}]}};
|
||||||
|
{ok, RPC} ->
|
||||||
|
?DEBUG("got XML-RPC request: ~p", [RPC]),
|
||||||
|
{false, Result} = handler(State, RPC),
|
||||||
|
{ok, XML} = xmlrpc_encode:payload(Result),
|
||||||
|
{200, [], [{<<"Content-Type">>, <<"text/xml">>}], XML}
|
||||||
|
end;
|
||||||
|
process(_, _) ->
|
||||||
|
{400, [],
|
||||||
|
#xmlel{name = <<"h1">>, attrs = [],
|
||||||
|
children = [{xmlcdata, <<"400 Bad Request">>}]}}.
|
||||||
|
|
||||||
%% -----------------------------
|
%% -----------------------------
|
||||||
%% Access verification
|
%% Access verification
|
||||||
|
|
Loading…
Reference in New Issue