gcloud_sdk/rest_apis/
rest_api_client.rs

1use crate::{GoogleAuthTokenGenerator, TokenSourceType, GCP_DEFAULT_SCOPES};
2use async_trait::async_trait;
3use hyper::Uri;
4use reqwest::{IntoUrl, Method, Request, RequestBuilder};
5use std::sync::Arc;
6
7#[derive(Clone)]
8pub struct GoogleRestApi {
9    pub client: reqwest::Client,
10    pub token_generator: Arc<GoogleAuthTokenGenerator>,
11}
12
13impl GoogleRestApi {
14    pub async fn new() -> crate::error::Result<Self> {
15        Self::with_token_source(TokenSourceType::Default, GCP_DEFAULT_SCOPES.clone()).await
16    }
17
18    pub async fn with_token_source(
19        token_source_type: TokenSourceType,
20        token_scopes: Vec<String>,
21    ) -> crate::error::Result<Self> {
22        let client = reqwest::Client::new();
23        Self::with_client_token_source(client, token_source_type, token_scopes).await
24    }
25
26    pub async fn with_client_token_source(
27        client: reqwest::Client,
28        token_source_type: TokenSourceType,
29        token_scopes: Vec<String>,
30    ) -> crate::error::Result<Self> {
31        let token_generator =
32            GoogleAuthTokenGenerator::new(token_source_type, token_scopes).await?;
33
34        Ok(Self {
35            client,
36            token_generator: Arc::new(token_generator),
37        })
38    }
39
40    pub async fn with_google_token<'a>(
41        &self,
42        request: RequestBuilder,
43    ) -> crate::error::Result<RequestBuilder> {
44        let token = self.token_generator.create_token().await?;
45        Ok(request.header(reqwest::header::AUTHORIZATION, token.header_value()))
46    }
47
48    pub async fn get<U: IntoUrl>(&self, url: U) -> crate::error::Result<RequestBuilder> {
49        self.with_google_token(self.client.request(Method::GET, url))
50            .await
51    }
52    pub async fn post<U: IntoUrl>(&self, url: U) -> crate::error::Result<RequestBuilder> {
53        self.with_google_token(self.client.request(Method::POST, url))
54            .await
55    }
56    pub async fn put<U: IntoUrl>(&self, url: U) -> crate::error::Result<RequestBuilder> {
57        self.with_google_token(self.client.request(Method::PUT, url))
58            .await
59    }
60    pub async fn patch<U: IntoUrl>(&self, url: U) -> crate::error::Result<RequestBuilder> {
61        self.with_google_token(self.client.request(Method::PATCH, url))
62            .await
63    }
64    pub async fn delete<U: IntoUrl>(&self, url: U) -> crate::error::Result<RequestBuilder> {
65        self.with_google_token(self.client.request(Method::DELETE, url))
66            .await
67    }
68    pub async fn head<U: IntoUrl>(&self, url: U) -> crate::error::Result<RequestBuilder> {
69        self.with_google_token(self.client.request(Method::HEAD, url))
70            .await
71    }
72}
73
74pub fn create_hyper_uri_with_params<'p, PT, TS>(url_str: &str, params: &'p PT) -> Uri
75where
76    PT: std::iter::IntoIterator<Item = (&'p str, Option<&'p TS>)> + Clone,
77    TS: std::string::ToString + 'p,
78{
79    let url_query_params: Vec<(String, String)> = params
80        .clone()
81        .into_iter()
82        .filter_map(|(k, vo)| vo.map(|v| (k.to_string(), v.to_string())))
83        .collect();
84
85    let url: url::Url = url::Url::parse_with_params(url_str, url_query_params)
86        .unwrap()
87        .as_str()
88        .parse()
89        .unwrap();
90
91    url.as_str().parse().unwrap()
92}