google_cloud_storage/http/
mod.rs

1use std::fmt::Display;
2use std::str::FromStr;
3
4use percent_encoding::{utf8_percent_encode, AsciiSet, NON_ALPHANUMERIC};
5use reqwest::Response;
6use serde::{de, Deserialize, Deserializer};
7use serde_json::Value;
8
9//pub mod entity;
10pub mod bucket_access_controls;
11pub mod buckets;
12pub mod channels;
13pub mod default_object_access_controls;
14pub mod error;
15pub mod hmac_keys;
16pub mod notifications;
17pub mod object_access_controls;
18pub mod objects;
19pub mod resumable_upload_client;
20pub mod service_account_client;
21pub mod storage_client;
22
23#[derive(thiserror::Error, Debug)]
24pub enum Error {
25    /// An error returned from the Google Cloud Storage service.
26    #[error(transparent)]
27    Response(#[from] error::ErrorResponse),
28
29    /// An error from the underlying HTTP client.
30    #[error(transparent)]
31    HttpClient(#[from] reqwest::Error),
32
33    /// An error from one of the middleware used.
34    #[error(transparent)]
35    HttpMiddleware(anyhow::Error),
36
37    /// An error from a token source.
38    #[error("token source failed: {0}")]
39    TokenSource(Box<dyn std::error::Error + Send + Sync>),
40
41    /// Invalid Range error
42    #[error("invalid range header, received: {0}")]
43    InvalidRangeHeader(String),
44
45    #[error("Request failed: {0} detail={1}")]
46    RawResponse(reqwest::Error, String),
47}
48
49impl From<reqwest_middleware::Error> for Error {
50    fn from(error: reqwest_middleware::Error) -> Self {
51        match error {
52            reqwest_middleware::Error::Middleware(err) => Error::HttpMiddleware(err),
53            reqwest_middleware::Error::Reqwest(err) => Error::HttpClient(err),
54        }
55    }
56}
57
58/// Checks whether an HTTP response is successful and returns it, or returns an error.
59pub(crate) async fn check_response_status(response: Response) -> Result<Response, Error> {
60    // Check the status code, returning the response if it is not an error.
61    let error = match response.error_for_status_ref() {
62        Ok(_) => return Ok(response),
63        Err(error) => error,
64    };
65
66    // try to extract a response error, falling back to the status error if it can not be parsed.
67    Err(response
68        .json::<error::ErrorWrapper>()
69        .await
70        .map(|wrapper| Error::Response(wrapper.error))
71        .unwrap_or(Error::HttpClient(error)))
72}
73
74pub(crate) trait Escape {
75    fn escape(&self) -> String;
76}
77
78impl Escape for String {
79    fn escape(&self) -> String {
80        utf8_percent_encode(self, ENCODE_SET).to_string()
81    }
82}
83
84const ENCODE_SET: &AsciiSet = &NON_ALPHANUMERIC.remove(b'*').remove(b'-').remove(b'.').remove(b'_');
85
86fn from_str_option<'de, T, D>(deserializer: D) -> Result<Option<T>, D::Error>
87where
88    T: FromStr,
89    T::Err: Display,
90    D: Deserializer<'de>,
91{
92    let s: Result<Value, _> = Deserialize::deserialize(deserializer);
93    match s {
94        Ok(Value::String(s)) => T::from_str(&s).map_err(de::Error::custom).map(Some),
95        Ok(Value::Number(num)) => T::from_str(&num.to_string()).map_err(de::Error::custom).map(Some),
96        Ok(_) => Err(de::Error::custom("Incorrect type")),
97        Err(_) => Ok(None),
98    }
99}
100
101pub fn from_str<'de, T, D>(deserializer: D) -> Result<T, D::Error>
102where
103    T: FromStr,
104    T::Err: Display,
105    D: de::Deserializer<'de>,
106{
107    let s = String::deserialize(deserializer)?;
108    T::from_str(&s).map_err(de::Error::custom)
109}
110
111pub fn is_i64_zero(num: &i64) -> bool {
112    *num == 0
113}
114
115/// Provides serialization and deserialization for base64 encoded fields.
116mod base64 {
117    use base64::prelude::*;
118    use serde::{Deserialize, Deserializer, Serialize, Serializer};
119
120    pub fn serialize<T, S>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
121    where
122        T: AsRef<[u8]>,
123        S: Serializer,
124    {
125        BASE64_STANDARD.encode(value.as_ref()).serialize(serializer)
126    }
127
128    pub fn deserialize<'de, D>(deserializer: D) -> Result<Vec<u8>, D::Error>
129    where
130        D: Deserializer<'de>,
131    {
132        BASE64_STANDARD
133            .decode(String::deserialize(deserializer)?)
134            .map_err(serde::de::Error::custom)
135    }
136}