aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/call/account.rs16
-rw-r--r--src/client.rs47
-rw-r--r--src/error/mod.rs25
-rw-r--r--src/response/mod.rs4
4 files changed, 63 insertions, 29 deletions
diff --git a/src/call/account.rs b/src/call/account.rs
index 865baf6..08bf077 100644
--- a/src/call/account.rs
+++ b/src/call/account.rs
@@ -22,8 +22,12 @@ impl From<Login<'_>> for xmlrpc::Value {
}
impl Call for Login<'_> {
- fn method_name(&self) -> &'static str { "account.login" }
- fn expected(&self) -> &'static [i32] { &[1000] }
+ fn method_name(&self) -> &'static str {
+ "account.login"
+ }
+ fn expected(&self) -> &'static [i32] {
+ &[1000]
+ }
}
// Contains no information. This just signals to the server
@@ -37,6 +41,10 @@ impl From<Logout> for xmlrpc::Value {
}
impl Call for Logout {
- fn method_name(&self) -> &'static str { "account.logout" }
- fn expected(&self) -> &'static [i32] { &[1500] }
+ fn method_name(&self) -> &'static str {
+ "account.logout"
+ }
+ fn expected(&self) -> &'static [i32] {
+ &[1500]
+ }
}
diff --git a/src/client.rs b/src/client.rs
index a1047ff..0f2890d 100644
--- a/src/client.rs
+++ b/src/client.rs
@@ -7,6 +7,7 @@ use reqwest::{blocking, Url};
/// The INWX environment to use. The Sandbox is good for testing
/// or debugging purposes.
+#[derive(Clone, Copy, Debug)]
pub enum Endpoint {
Production,
Sandbox,
@@ -21,9 +22,9 @@ impl From<Endpoint> for &str {
}
}
-impl Into<Url> for Endpoint {
- fn into(self) -> Url {
- Url::parse(self.into()).unwrap()
+impl From<Endpoint> for Url {
+ fn from(endpoint: Endpoint) -> Self {
+ Url::parse(endpoint.into()).unwrap()
}
}
@@ -58,47 +59,45 @@ impl Client {
/// if successful and if the status code
/// matches one of the expected status codes.
pub fn call(&self, call: impl call::Call) -> Result<response::Response> {
- let transport = self.inner.http.post(self.inner.endpoint.into());
+ let expected = call.expected();
- let request = xmlrpc::Request::new(call.method_name());
- request.arg(call);
+ let transport = self.inner.http.post::<Url>(self.inner.endpoint.into());
+
+ let request = xmlrpc::Request::new(call.method_name()).arg(call);
let raw = request.call(transport)?;
match raw {
xmlrpc::Value::Struct(map) => {
- let code = map.get("code")
- .ok_or(Error::Inexistent("code"))?;
+ let code = map.get("code").ok_or(Error::Inexistent("code"))?;
match code {
xmlrpc::Value::Int(code) => {
- if call.expected().contains(code) {
- let data = map.get("resData")
- .ok_or(Error::Inexistent("resData"))?;
+ if expected.contains(code) {
+ let data = map.get("resData").ok_or(Error::Inexistent("resData"))?;
match data {
- xmlrpc::Value::Struct(response) => {
- Ok(response::Response {
- status: *code,
- data: response,
- })
- },
- _ => Err(Error::Type("resData", "Struct")),
+ xmlrpc::Value::Struct(response) => Ok(response::Response {
+ status: *code,
+ data: response.clone(),
+ }),
+ _ => Err(Error::Type("resData", "Struct", data.clone())),
}
} else {
- Err(Error::BadStatus(call.expected(), code))
+ Err(Error::BadStatus(expected, *code))
}
- },
- _ => Err(Error::Type("code", "Int")),
+ }
+ _ => Err(Error::Type("code", "Int", code.clone())),
}
- },
- _ => Err(Error::BadResponse(raw)),
+ }
+ _ => Err(Error::BadResponse(raw.clone())),
}
}
}
impl Drop for Client {
fn drop(&mut self) {
- self.call(call::account::Logout);
+ // Ignore the result. Failed logout doesn't really matter.
+ self.call(call::account::Logout).ok();
}
}
diff --git a/src/error/mod.rs b/src/error/mod.rs
index 8be0874..9c8bdfc 100644
--- a/src/error/mod.rs
+++ b/src/error/mod.rs
@@ -5,6 +5,11 @@ use std::fmt;
pub enum Error {
ParseUrl(url::ParseError),
Reqwest(reqwest::Error),
+ XmlRpc(xmlrpc::Error),
+ Inexistent(&'static str),
+ Type(&'static str, &'static str, xmlrpc::Value),
+ BadResponse(xmlrpc::Value),
+ BadStatus(&'static [i32], i32),
}
impl std::error::Error for Error {}
@@ -14,6 +19,20 @@ impl fmt::Display for Error {
match self {
Error::ParseUrl(err) => write!(fmt, "can't parse Url: {}", err),
Error::Reqwest(err) => write!(fmt, "reqwest error: {}", err),
+ Error::XmlRpc(err) => write!(fmt, "xmlrpc error: {}", err),
+ Error::Inexistent(what) => {
+ write!(fmt, "parameter {} does not exist", what)
+ }
+ Error::Type(what, exp, got) => {
+ write!(
+ fmt,
+ "parameter {what} is of wrong type {got:?} (expected: {exp})"
+ )
+ }
+ Error::BadResponse(resp) => write!(fmt, "bad response: {:?}", resp),
+ Error::BadStatus(expected, got) => {
+ write!(fmt, "bad status {} (expected: {:?}", got, expected)
+ }
}
}
}
@@ -30,5 +49,11 @@ impl From<reqwest::Error> for Error {
}
}
+impl From<xmlrpc::Error> for Error {
+ fn from(err: xmlrpc::Error) -> Self {
+ Self::XmlRpc(err)
+ }
+}
+
/// A `Result` alias where the `Err` case is `inwx::Error`.
pub type Result<T> = std::result::Result<T, Error>;
diff --git a/src/response/mod.rs b/src/response/mod.rs
index ddaa5f2..5c1584f 100644
--- a/src/response/mod.rs
+++ b/src/response/mod.rs
@@ -1,7 +1,9 @@
+use std::collections::BTreeMap;
+
/// A Response to an API call including status and data.
/// Data is guaranteed to be a `Struct`.
/// [`Struct`]: xmlrpc::Value::Struct
pub struct Response {
pub status: i32,
- pub data: xmlrpc::Value,
+ pub data: BTreeMap<String, xmlrpc::Value>,
}