gcslib/
lib.rs

1use anyhow::Result;
2use google_auth::TokenManager;
3use serde::{Deserialize, Serialize};
4
5#[derive(Clone)]
6pub struct Client {
7    token_manager: TokenManager,
8}
9pub struct Bucket {
10    client: Client,
11    name: String,
12}
13
14impl Client {
15    pub async fn new() -> Result<Client> {
16        let tm = TokenManager::new(&[]).await?;
17        Ok(Client { token_manager: tm })
18    }
19    pub fn bucket(&self, name: &str) -> Bucket {
20        Bucket {
21            name: name.to_string(),
22            client: self.clone(),
23        }
24    }
25}
26
27impl Bucket {
28    pub async fn list(&mut self, prefix: &str) -> Result<Response> {
29        let url = format!(
30            "https://storage.googleapis.com/storage/v1/b/{}/o?prefix={}",
31            self.name, prefix
32        );
33        let access_token = self.client.token_manager.token().await?;
34        let client = reqwest::Client::new();
35        let res = client
36            .get(&url)
37            .header(reqwest::header::AUTHORIZATION, access_token)
38            .header(reqwest::header::ACCEPT, "application/json")
39            .send()
40            .await?;
41        let res: Response = res.json().await?;
42        Ok(res)
43    }
44
45    pub async fn insert(&mut self, data: Vec<u8>, file_name: &str) -> Result<Object> {
46        let url = format!(
47            "https://storage.googleapis.com/upload/storage/v1/b/{}/o?uploadType=media&name={}",
48            self.name, file_name
49        );
50        let access_token = self.client.token_manager.token().await?;
51        let client = reqwest::Client::new();
52        let len = data.len();
53        let res = client
54            .post(&url)
55            .body(data)
56            .header(reqwest::header::AUTHORIZATION, access_token)
57            .header(reqwest::header::CONTENT_LENGTH, len)
58            .header(
59                reqwest::header::CONTENT_TYPE,
60                "application/json;charset=UTF-8",
61            )
62            .send()
63            .await?;
64        let object: Object = res.json().await?;
65        Ok(object)
66    }
67}
68
69#[derive(Deserialize, Serialize, Debug)]
70pub struct Error {
71    error: ErrorPayload,
72}
73
74#[derive(Deserialize, Serialize, Debug)]
75pub struct ErrorPayload {
76    code: u32,
77    message: String,
78}
79
80#[derive(Deserialize, Serialize, Debug)]
81#[serde(untagged)]
82pub enum Response {
83    Error(Error),
84    Objects(Objects),
85}
86
87#[derive(Deserialize, Serialize, Debug)]
88pub struct Objects {
89    kind: String,
90    pub items: Vec<Object>,
91}
92
93#[derive(Deserialize, Serialize, Debug, Clone)]
94#[serde(rename_all = "camelCase")]
95pub struct Object {
96    kind: String,
97    id: String,
98    self_link: String,
99    media_link: String,
100    name: String,
101    bucket: String,
102    generation: String,
103    metageneration: String,
104    content_type: Option<String>,
105    storage_class: String,
106    size: String,
107    md5_hash: String,
108    crc32c: String,
109    etag: String,
110    time_created: String,
111    updated: String,
112    time_storage_class_updated: String,
113}
114
115impl Object {
116    pub async fn download(&self, mut client: Client) -> Result<String> {
117        let http_client = reqwest::Client::new();
118        let resp = http_client
119            .get(&self.media_link)
120            .header(
121                reqwest::header::AUTHORIZATION,
122                client.token_manager.token().await?,
123            )
124            .header(
125                reqwest::header::AUTHORIZATION,
126                client.token_manager.token().await?,
127            )
128            .send()
129            .await?;
130        let body = resp.text().await?;
131        Ok(body)
132    }
133}