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
82
83
84
85
86
87
88
89
90
91
92
use crate::{GoogleAuthTokenGenerator, TokenSourceType, GCP_DEFAULT_SCOPES};
use async_trait::async_trait;
use hyper::Uri;
use reqwest::{IntoUrl, Method, Request, RequestBuilder};
use std::sync::Arc;
#[derive(Clone)]
pub struct GoogleRestApi {
    pub client: reqwest::Client,
    pub token_generator: Arc<GoogleAuthTokenGenerator>,
}
impl GoogleRestApi {
    pub async fn new() -> crate::error::Result<Self> {
        Self::with_token_source(TokenSourceType::Default, GCP_DEFAULT_SCOPES.clone()).await
    }
    pub async fn with_token_source(
        token_source_type: TokenSourceType,
        token_scopes: Vec<String>,
    ) -> crate::error::Result<Self> {
        Self::with_client_token_source(reqwest::Client::new(), token_source_type, token_scopes)
            .await
    }
    pub async fn with_client_token_source(
        client: reqwest::Client,
        token_source_type: TokenSourceType,
        token_scopes: Vec<String>,
    ) -> crate::error::Result<Self> {
        let token_generator =
            GoogleAuthTokenGenerator::new(token_source_type, token_scopes).await?;
        Ok(Self {
            client,
            token_generator: Arc::new(token_generator),
        })
    }
    pub async fn with_google_token<'a>(
        &self,
        request: RequestBuilder,
    ) -> crate::error::Result<RequestBuilder> {
        let token = self.token_generator.create_token().await?;
        Ok(request.header(reqwest::header::AUTHORIZATION, token.header_value()))
    }
    pub async fn get<U: IntoUrl>(&self, url: U) -> crate::error::Result<RequestBuilder> {
        self.with_google_token(self.client.request(Method::GET, url))
            .await
    }
    pub async fn post<U: IntoUrl>(&self, url: U) -> crate::error::Result<RequestBuilder> {
        self.with_google_token(self.client.request(Method::POST, url))
            .await
    }
    pub async fn put<U: IntoUrl>(&self, url: U) -> crate::error::Result<RequestBuilder> {
        self.with_google_token(self.client.request(Method::PUT, url))
            .await
    }
    pub async fn patch<U: IntoUrl>(&self, url: U) -> crate::error::Result<RequestBuilder> {
        self.with_google_token(self.client.request(Method::PATCH, url))
            .await
    }
    pub async fn delete<U: IntoUrl>(&self, url: U) -> crate::error::Result<RequestBuilder> {
        self.with_google_token(self.client.request(Method::DELETE, url))
            .await
    }
    pub async fn head<U: IntoUrl>(&self, url: U) -> crate::error::Result<RequestBuilder> {
        self.with_google_token(self.client.request(Method::HEAD, url))
            .await
    }
}
pub fn create_hyper_uri_with_params<'p, PT, TS>(url_str: &str, params: &'p PT) -> Uri
where
    PT: std::iter::IntoIterator<Item = (&'p str, Option<&'p TS>)> + Clone,
    TS: std::string::ToString + 'p,
{
    let url_query_params: Vec<(String, String)> = params
        .clone()
        .into_iter()
        .filter_map(|(k, vo)| vo.map(|v| (k.to_string(), v.to_string())))
        .collect();
    let url: url::Url = url::Url::parse_with_params(url_str, url_query_params)
        .unwrap()
        .as_str()
        .parse()
        .unwrap();
    url.as_str().parse().unwrap()
}