aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2020-05-23 16:16:25 -0400
committerJesse Luehrs <doy@tozt.net>2020-05-23 16:16:25 -0400
commit80acb66445a612798ddf74bd6df60b51fd674fa0 (patch)
tree9c6b5fe2cb6bf33c79523a2ab2dcd9d0124c3e32 /src
parentc9473e0b61bc9d8264a6ce939ed74c3d9b8f4db5 (diff)
downloadrbw-80acb66445a612798ddf74bd6df60b51fd674fa0.tar.gz
rbw-80acb66445a612798ddf74bd6df60b51fd674fa0.zip
better error messages when parsing a server message
Diffstat (limited to 'src')
-rw-r--r--src/api.rs26
-rw-r--r--src/error.rs5
-rw-r--r--src/json.rs38
-rw-r--r--src/lib.rs1
4 files changed, 56 insertions, 14 deletions
diff --git a/src/api.rs b/src/api.rs
index 09c90b1..c0125d6 100644
--- a/src/api.rs
+++ b/src/api.rs
@@ -1,5 +1,9 @@
use crate::prelude::*;
+use crate::json::{
+ DeserializeJsonWithPath as _, DeserializeJsonWithPathAsync as _,
+};
+
#[derive(serde::Serialize, Debug)]
struct PreloginReq {
email: String,
@@ -385,8 +389,7 @@ impl Client {
.send()
.await
.context(crate::error::Reqwest)?;
- let prelogin_res: PreloginRes =
- res.json().await.context(crate::error::Reqwest)?;
+ let prelogin_res: PreloginRes = res.json_with_path().await?;
Ok(prelogin_res.kdf_iterations)
}
@@ -417,7 +420,7 @@ impl Client {
.context(crate::error::Reqwest)?;
if let reqwest::StatusCode::OK = res.status() {
let connect_res: ConnectPasswordRes =
- res.json().await.context(crate::error::Reqwest)?;
+ res.json_with_path().await?;
Ok((
connect_res.access_token,
connect_res.refresh_token,
@@ -425,8 +428,7 @@ impl Client {
))
} else {
let code = res.status().as_u16();
- let error_res: ConnectErrorRes =
- res.json().await.context(crate::error::Reqwest)?;
+ let error_res: ConnectErrorRes = res.json_with_path().await?;
if error_res.error_model.message
== "Username or password is incorrect. Try again"
{
@@ -455,8 +457,7 @@ impl Client {
.context(crate::error::Reqwest)?;
match res.status() {
reqwest::StatusCode::OK => {
- let sync_res: SyncRes =
- res.json().await.context(crate::error::Reqwest)?;
+ let sync_res: SyncRes = res.json_with_path().await?;
let folders = sync_res.folders.clone();
let ciphers = sync_res
.ciphers
@@ -760,8 +761,7 @@ impl Client {
.context(crate::error::Reqwest)?;
match res.status() {
reqwest::StatusCode::OK => {
- let folders_res: FoldersRes =
- res.json().context(crate::error::Reqwest)?;
+ let folders_res: FoldersRes = res.json_with_path()?;
Ok(folders_res
.data
.iter()
@@ -794,8 +794,7 @@ impl Client {
.context(crate::error::Reqwest)?;
match res.status() {
reqwest::StatusCode::OK => {
- let folders_res: FoldersResData =
- res.json().context(crate::error::Reqwest)?;
+ let folders_res: FoldersResData = res.json_with_path()?;
Ok(folders_res.id)
}
reqwest::StatusCode::UNAUTHORIZED => {
@@ -822,8 +821,7 @@ impl Client {
.form(&connect_req)
.send()
.context(crate::error::Reqwest)?;
- let connect_res: ConnectRefreshTokenRes =
- res.json().context(crate::error::Reqwest)?;
+ let connect_res: ConnectRefreshTokenRes = res.json_with_path()?;
Ok(connect_res.access_token)
}
@@ -844,7 +842,7 @@ impl Client {
.await
.context(crate::error::Reqwest)?;
let connect_res: ConnectRefreshTokenRes =
- res.json().await.context(crate::error::Reqwest)?;
+ res.json_with_path().await?;
Ok(connect_res.access_token)
}
diff --git a/src/error.rs b/src/error.rs
index a6e6a84..6e8a51e 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -43,6 +43,11 @@ pub enum Error {
#[snafu(display("invalid mac"))]
InvalidMac,
+ #[snafu(display("{}", source))]
+ JSON {
+ source: serde_path_to_error::Error<serde_json::Error>,
+ },
+
#[snafu(display("failed to load config: {}", source))]
LoadConfig { source: std::io::Error },
diff --git a/src/json.rs b/src/json.rs
new file mode 100644
index 0000000..2816a1f
--- /dev/null
+++ b/src/json.rs
@@ -0,0 +1,38 @@
+use crate::prelude::*;
+
+pub trait DeserializeJsonWithPath {
+ fn json_with_path<T: serde::de::DeserializeOwned>(self) -> Result<T>;
+}
+
+impl DeserializeJsonWithPath for String {
+ fn json_with_path<T: serde::de::DeserializeOwned>(self) -> Result<T> {
+ let jd = &mut serde_json::Deserializer::from_str(&self);
+ serde_path_to_error::deserialize(jd).context(crate::error::JSON)
+ }
+}
+
+impl DeserializeJsonWithPath for reqwest::blocking::Response {
+ fn json_with_path<T: serde::de::DeserializeOwned>(self) -> Result<T> {
+ let bytes = self.bytes().context(crate::error::Reqwest)?;
+ let jd = &mut serde_json::Deserializer::from_slice(&bytes);
+ serde_path_to_error::deserialize(jd).context(crate::error::JSON)
+ }
+}
+
+#[async_trait::async_trait]
+pub trait DeserializeJsonWithPathAsync {
+ async fn json_with_path<T: serde::de::DeserializeOwned>(
+ self,
+ ) -> Result<T>;
+}
+
+#[async_trait::async_trait]
+impl DeserializeJsonWithPathAsync for reqwest::Response {
+ async fn json_with_path<T: serde::de::DeserializeOwned>(
+ self,
+ ) -> Result<T> {
+ let bytes = self.bytes().await.context(crate::error::Reqwest)?;
+ let jd = &mut serde_json::Deserializer::from_slice(&bytes);
+ serde_path_to_error::deserialize(jd).context(crate::error::JSON)
+ }
+}
diff --git a/src/lib.rs b/src/lib.rs
index f010bf0..6605c22 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -19,6 +19,7 @@ pub mod dirs;
pub mod edit;
pub mod error;
pub mod identity;
+pub mod json;
pub mod locked;
pub mod pinentry;
mod prelude;