Skip to content

Commit 51fd2b3

Browse files
committed
correct handling of invalid token errors, and add support for HTTP 403 access denied errors
1 parent 5c5248c commit 51fd2b3

File tree

2 files changed

+34
-5
lines changed

2 files changed

+34
-5
lines changed

src/client_helpers.rs

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,19 @@ struct TopLevelError<T> {
1616
pub error: T,
1717
}
1818

19+
/// This is actually [`auth::RateLimitError`] but re-imported here with less type info because the
20+
/// auth namespace is not necessarily compiled in, but this must always be available.
1921
#[derive(Debug, Deserialize)]
2022
struct RateLimitedError {
21-
pub reason: RateLimitedReason,
23+
pub reason: OpenUnionTag,
2224

2325
#[serde(default)] // too_many_write_operations errors don't include this field; default to 0.
2426
pub retry_after: u32,
2527
}
2628

27-
// Rather than deserializing into an enum, just capture the tag value.
29+
/// Rather than deserializing into an enum, just capture the tag value.
2830
#[derive(Debug, Deserialize)]
29-
struct RateLimitedReason {
31+
struct OpenUnionTag {
3032
#[serde(rename = ".tag")]
3133
tag: String,
3234
}
@@ -75,8 +77,29 @@ pub fn request_with_body<T: DeserializeOwned, E: DeserializeOwned + StdError, P:
7577
Err(Error::BadRequest(response))
7678
},
7779
401 => {
78-
Err(Error::InvalidToken(response))
80+
match serde_json::from_str::<TopLevelError<OpenUnionTag>>(&response) {
81+
Ok(deserialized) => {
82+
error!("invalid token: {}", deserialized.error.tag);
83+
Err(Error::InvalidToken(deserialized.error.tag))
84+
}
85+
Err(de_error) => {
86+
error!("Failed to deserialize JSON from API error: {}", de_error);
87+
Err(Error::Json(de_error))
88+
}
89+
}
7990
},
91+
403 => {
92+
match serde_json::from_str::<TopLevelError<serde_json::Value>>(&response) {
93+
Ok(deserialized) => {
94+
error!("access denied: {:?}", deserialized.error);
95+
Err(Error::AccessDenied(deserialized.error))
96+
}
97+
Err(de_error) => {
98+
error!("Failed to deserialize JSON from API error: {}", de_error);
99+
Err(Error::Json(de_error))
100+
}
101+
}
102+
}
80103
409 => {
81104
// Response should be JSON-deseraializable into the strongly-typed
82105
// error specified by type parameter E.

src/lib.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) 2019-2020 Dropbox, Inc.
1+
// Copyright (c) 2019-2021 Dropbox, Inc.
22

33
#![deny(
44
missing_docs,
@@ -67,6 +67,12 @@ pub enum Error {
6767
retry_after_seconds: u32,
6868
},
6969

70+
/// The user or team account doesn't have access to the endpoint or feature.
71+
/// Value is a JSON object which matches the [`auth::AccessError`] type (if that namespace
72+
/// feature is enabled).
73+
#[error("Dropbox API denied access to the resource: {0}")]
74+
AccessDenied(serde_json::Value),
75+
7076
/// The Dropbox API server had an internal error.
7177
#[error("Dropbox API had an internal server error: {0}")]
7278
ServerError(String),

0 commit comments

Comments
 (0)