Weebo
Weebo is an XML-RPC parser/formatter for Elixir, with full data-type support.
Weebo can be combined with GenServer, Phoenix, HTTPoison (and others!) to create fully-featured XML-RPC clients & servers.
request = Weebo.parse("<?xml version=\"1.0\"?><methodCall><methodName>math.sum</methodName><params><param><value><int>1</int></value></param><param><value><int>2</int></value></param><param><value><int>3</int></value></param></params></methodCall>")
#=> %Weebo.Request{method: "math.sum", params: [1, 2, 3]}
sum = Enum.sum(request.params)
response = %Weebo.Response{error: nil, params: [sum]}
Weebo.format(response)
#=> "<?xml version=\"1.0\"?><methodResponse><params><param><value><int>6</int></value></param></params></methodResponse>"Installation
Add Weebo to your mix dependencies:
def deps do
[{:weebo, "~> 0.1"}]
end
Then run mix deps.get and mix deps.compile.
API Documentation
Full documentation is available on Hex — http://hexdocs.pm/weebo/
Data Type Mapping
All the following data-types are supported, and will be automatically serialized
in format/1 and parse/1:
| XMLRPC | Elixir |
|---|---|
<string> |
Bitstring "string" |
<int> |
Integer 8 |
<boolean> |
Boolean true false |
<double> |
Float 6.3 |
<array> |
List [1, 2, 3] |
<struct> |
Map %{key: "value"} |
<dateTime.iso8601> |
Tuple {{2015, 6, 7}, {16, 24, 18}} |
<nil> |
Nil atom nil |
In addition, the following extra data-types are supported only in parse/1:
| XMLRPC | Elixir |
|---|---|
<base64> |
Bitstring "string" (will decode the base64 first) |
<i4> |
Integer 8 |
Examples
Creating a client with HTTPoison
For quick-n-dirty usage, you can just use Weebo directly encode/decode request/response bodies:
body = %Weebo.Request{method: "sample.sumAndDifference", params: [5, 3]}
|> Weebo.format
res = HTTPoison.post!("http://some-wordpress-site.com/xmlrpc.php", body)
Weebo.parse(res.body)
#=> %Weebo.Response{error: nil, params: [%{difference: 2, sum: 8}]}Or for more encapsulation, you can use HTTPoison's base wrapper to auto-parse & format requests:
defmodule XMLRPC do
use HTTPoison.Base
def process_request_body(body), do: Weebo.format(body)
def process_response_body(body), do: Weebo.parse(body)
end
body = %Weebo.Request{method: "sample.sumAndDifference", params: [5, 3]}
res = XMLRPC.post!("http://some-wordpress-site.com/xmlrpc.php", body)
res.body
#=> %Weebo.Response{error: nil, params: [%{difference: 2, sum: 8}]}
You can then build out your XMLRPC module to handle more features like
authentication, error handling, etc.
Creating a server with Phoenix
Phoenix might be a little overkill for just a stand-alone XML-RPC server, but if you already have an existing application that you want to add XML-RPC support to, then you're in luck!
First add a route to your router.ex file:
post "/xmlrpc", XmlRpcController, :process
Then in your xml_rpc_controller.ex:
defmodule MyApp.XmlRpcController do
use MyApp.Web, :controller
def process(conn, _params) do
{:ok, body, _conn} = read_body(conn)
xml_req = Weebo.parse(body)
res = case xml_req.method do
"math.sum" ->
sum = Enum.sum(xml_req.params)
%Weebo.Response{params: [sum]}
_ ->
%Weebo.Response{error: %{faultCode: 404, faultString: "Not found."}}
end
render conn, Weebo.format(res)
end
endUsed Weebo in another awesome way?
Please open an issue/pull-request on GitHub and I'll get it added to this README!
Acknowledgements
Thank you to @expelledboy for releasing their exml package. Although I wasn't able to use it directly, it served as a base for Weebo's internal XML interface.
Also thanks goes to @seansawyer for their awesome erlang_iso8601 library, which Weebo uses for timestamp parsing & formatting.