Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Modern implementation of xmlrpc (using inets), but breaks existing API

  • Loading branch information...
commit 8ca02b0a85c559490925c574ab36bc595389eae8 1 parent 164eb41
@palfrey authored
Showing with 20 additions and 153 deletions.
  1. +20 −153 src/xmlrpc.erl
View
173 src/xmlrpc.erl
@@ -25,162 +25,29 @@
%% SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-module(xmlrpc).
--author('jocke@gleipnir.com').
--export([call/3, call/4, call/5, call/6]).
--export([start_link/1, start_link/5, start_link/6, stop/1]).
+-author('palfrey@tevp.net').
+-export([call/2]).
--include("log.hrl").
+%% Exported: call/2
--record(header, {
- %% int()
- content_length,
- %% close | undefined
- connection
- }).
-
-%% Exported: call/{3,4,5,6}
-
-call(Host, Port, URI, Payload) -> call(Host, Port, URI, Payload, false, 60000).
-
-call(Host, Port, URI, Payload, KeepAlive, Timeout) ->
- case gen_tcp:connect(Host, Port, [{active, false}]) of
- {ok, Socket} -> call(Socket, URI, Payload, KeepAlive, Timeout);
- {error, Reason} when KeepAlive == false -> {error, Reason};
- {error, Reason} -> {error, undefined, Reason}
- end.
-
-call(Socket, URI, Payload) -> call(Socket, URI, Payload, false, 60000).
-
-call(Socket, URI, Payload, KeepAlive, Timeout) ->
- ?DEBUG_LOG({decoded_call, Payload}),
+call(URL, Payload) ->
+ inets:start(),
case xmlrpc_encode:payload(Payload) of
{ok, EncodedPayload} ->
- ?DEBUG_LOG({encoded_call, EncodedPayload}),
- case send(Socket, URI, KeepAlive, EncodedPayload) of
- ok ->
- case parse_response(Socket, Timeout) of
- {ok, Header} ->
- handle_payload(Socket, KeepAlive, Timeout, Header);
- {error, Reason} when KeepAlive == false ->
- gen_tcp:close(Socket),
- {error, Reason};
- {error, Reason} -> {error, Socket, Reason}
- end;
- {error, Reason} when KeepAlive == false ->
- gen_tcp:close(Socket),
- {error, Reason};
- {error, Reason} -> {error, Socket, Reason}
- end;
- {error, Reason} when KeepAlive == false ->
- gen_tcp:close(Socket),
- {error, Reason};
- {error, Reason} -> {error, Socket, Reason}
+ case http:request(post, {URL, [], "text/xml", lists:flatten(EncodedPayload)}, [], []) of
+ {ok, {{_, 200, _}, _, Body}} ->
+ case xmlrpc_decode:payload(Body) of
+ {ok, {response, {fault, Code, String}}} ->
+ {error, {Code, String}};
+ {ok, {response, [Data]}} ->
+ QuoteData = re:replace(Data, "\\\\\"", "\"", [{return, list},global]),
+ {ok, xmerl_scan:string(QuoteData)};
+ {error, Reason} ->
+ {error, Reason}
+ end;
+ {ok, StatusLine} -> {error, StatusLine}
+ end;
+ {error, Reason} ->
+ {error, Reason}
end.
-send(Socket, URI, false, Payload) ->
- send(Socket, URI, "Connection: close\r\n", Payload);
-send(Socket, URI, true, Payload) -> send(Socket, URI, "", Payload);
-send(Socket, URI, Header, Payload) ->
- Request =
- ["POST ", URI, " HTTP/1.1\r\n",
- "Content-Length: ", integer_to_list(lists:flatlength(Payload)),
- "\r\n",
- "User-Agent: Erlang XML-RPC Client 1.13\r\n",
- "Content-Type: text/xml\r\n",
- Header, "\r\n",
- Payload],
- gen_tcp:send(Socket, Request).
-
-parse_response(Socket, Timeout) ->
- inet:setopts(Socket, [{packet, line}]),
- case gen_tcp:recv(Socket, 0, Timeout) of
- {ok, "HTTP/1.1 200 \r\n"} -> parse_header(Socket, Timeout);
- {ok, StatusLine} -> {error, StatusLine};
- {error, Reason} -> {error, Reason}
- end.
-
-parse_header(Socket, Timeout) -> parse_header(Socket, Timeout, #header{}).
-
-parse_header(Socket, Timeout, Header) ->
- case gen_tcp:recv(Socket, 0, Timeout) of
- {ok, "\r\n"} when Header#header.content_length == undefined ->
- {error, missing_content_length};
- {ok, "\r\n"} -> {ok, Header};
- {ok, HeaderField} ->
- case string:tokens(string:to_lower(HeaderField), " \r\n") of
- ["content-length:", ContentLength] ->
- try
- Value = list_to_integer(ContentLength),
- parse_header(Socket, Timeout,
- Header#header{content_length = Value})
- catch
- _ -> {error, {invalid_content_length, ContentLength}}
- end;
- ["connection:", "close"] ->
- parse_header(Socket, Timeout,
- Header#header{connection = close});
- _ ->
- parse_header(Socket, Timeout, Header)
- end;
- {error, Reason} -> {error, Reason}
- end.
-
-handle_payload(Socket, KeepAlive, Timeout, Header) ->
- case get_payload(Socket, Timeout, Header#header.content_length) of
- {ok, Payload} ->
- ?DEBUG_LOG({encoded_response, Payload}),
- case xmlrpc_decode:payload(Payload) of
- {ok, DecodedPayload} when KeepAlive == false ->
- ?DEBUG_LOG({decoded_response, DecodedPayload}),
- gen_tcp:close(Socket),
- {ok, DecodedPayload};
- {ok, DecodedPayload} when KeepAlive == true,
- Header#header.connection == close ->
- ?DEBUG_LOG({decoded_response, DecodedPayload}),
- gen_tcp:close(Socket),
- {ok, Socket, DecodedPayload};
- {ok, DecodedPayload} ->
- ?DEBUG_LOG({decoded_response, DecodedPayload}),
- {ok, Socket, DecodedPayload};
- {error, Reason} when KeepAlive == false ->
- gen_tcp:close(Socket),
- {error, Reason};
- {error, Reason} when KeepAlive == true,
- Header#header.connection == close ->
- gen_tcp:close(Socket),
- {error, Socket, Reason};
- {error, Reason} ->
- {error, Socket, Reason}
- end;
- {error, Reason} when KeepAlive == false ->
- gen_tcp:close(Socket),
- {error, Reason};
- {error, Reason} when KeepAlive == true,
- Header#header.connection == close ->
- gen_tcp:close(Socket),
- {error, Socket, Reason};
- {error, Reason} -> {error, Socket, Reason}
- end.
-
-get_payload(Socket, Timeout, ContentLength) ->
- inet:setopts(Socket, [{packet, raw}]),
- gen_tcp:recv(Socket, ContentLength, Timeout).
-
-%% Exported: start_link/{1,5,6}
-
-start_link(Handler) -> start_link(4567, 1000, 60000, Handler, undefined).
-
-start_link(Port, MaxSessions, Timeout, Handler, State) ->
- start_link(all, Port, MaxSessions, Timeout, Handler, State).
-
-start_link(IP, Port, MaxSessions, Timeout, Handler, State) ->
- OptionList = [{active, false}, {reuseaddr, true}|ip(IP)],
- SessionHandler = {xmlrpc_http, handler, [Timeout, Handler, State]},
- tcp_serv:start_link([Port, MaxSessions, OptionList, SessionHandler]).
-
-ip(all) -> [];
-ip(IP) when is_tuple(IP) -> {ip, IP}.
-
-%% Exported: stop/1
-
-stop(Pid) -> tcp_serv:stop(Pid).
Please sign in to comment.
Something went wrong with that request. Please try again.