google_cloud_storage/http/
error.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
use std::error::Error;
use std::fmt;

/// An error response returned from Google Cloud Storage.
///
/// See the [`HTTP status and error codes for JSON`][1] documentation for more details.
///
/// [1]: https://cloud.google.com/storage/docs/json_api/v1/status-codes
#[derive(Debug, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ErrorResponse {
    /// An HTTP status value, without the textual description.
    ///
    /// Example values include: `400` (Bad Request), `401` (Unauthorized), and `404` (Not Found).
    pub code: u16,

    /// A container for the error details.
    pub errors: Vec<ErrorResponseItem>,

    /// Description of the error. Same as `errors.message`.
    pub message: String,
}

impl ErrorResponse {
    /// Returns `true` if the error is retriable according to the [GCS documentation][1].
    ///
    /// [1]: https://cloud.google.com/storage/docs/retry-strategy#retryable
    pub fn is_retriable(&self) -> bool {
        matches!(self.code, 408 | 429 | 500..=599)
    }
}

impl fmt::Display for ErrorResponse {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.message.fmt(f)
    }
}

impl Error for ErrorResponse {}

#[derive(Debug, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ErrorResponseItem {
    /// The scope of the error. Example values include: `global` and `push`.
    pub domain: String,

    /// The specific item within the `locationType` that caused the error. For example, if you
    /// specify an invalid value for a parameter, the `location` will be the name of the parameter.
    ///
    /// Example values include: `Authorization`, `project`, and `projection`.
    pub location: Option<String>,

    /// The location or part of the request that caused the error. Use with `location` to pinpoint
    /// the error. For example, if you specify an invalid value for a parameter, the `locationType`
    /// will be `parameter` and the `location` will be the name of the parameter.
    ///
    /// Example values include `header` and `parameter`.
    pub location_type: Option<String>,

    /// Description of the error.
    ///
    /// Example values include `Invalid argument`, `Login required`, and
    /// `Required parameter: project`.
    pub message: String,

    /// Example values include `invalid`, `invalidParameter`, and `required`.
    pub reason: String,
}

impl fmt::Display for ErrorResponseItem {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.message.fmt(f)
    }
}

/// The GCS error response JSON format contains an extra object level that is inconvenient to include in our
/// error.
#[derive(serde::Deserialize)]
pub(crate) struct ErrorWrapper {
    pub(crate) error: ErrorResponse,
}