rocket_gitee_pictures/
lib.rs1use deadpool_redis::Pool;
2
3mod redis_pool_wrapper;
4use anyhow;
5use base64;
6use deadpool_redis::{cmd, Pipeline};
7use mime_sniffer::MimeTypeSniffer;
8use reqwest;
9use rocket::data::{Data, ToByteUnit};
10use rocket::http::{
11 ContentType,
12 Method::{Get, Post},
13 Status,
14};
15use rocket::outcome::{try_outcome, IntoOutcome};
16use rocket::response::{self, status::Custom, Responder};
17use rocket::tokio::fs::File;
18use rocket::{catcher, route, Catcher, Request, Response, Route};
19use serde_json;
20use std::cell::RefCell;
21use std::error::Error;
22use std::io::Cursor;
23use std::path::Path;
24use std::path::PathBuf;
25use std::rc::Rc;
26use std::sync::{Arc, Mutex};
27use std::thread;
28#[derive(Clone)]
30pub struct RocketGiteePicturesWrapperConfig {
31 pub redis_host: String,
33 pub redis_port: i32,
35 pub redis_password: String,
37 pub gitee_token: String,
39 pub gitee_owner: String,
41 pub gitee_repo: String,
43 pub gitee_branch: String,
45 pub gitee_refresh_interval: i32,
47}
48
49#[derive(Clone)]
51pub struct RocketGiteePicturesHandler {
52 pub config: RocketGiteePicturesWrapperConfig,
54 pub redis_pool: Pool,
56}
57
58pub async fn load_git_files_path_to_redis(
60 config: &RocketGiteePicturesWrapperConfig,
61 pool: &Pool,
62) -> Result<(), anyhow::Error> {
63 let body = reqwest::get(format!(
65 "https://gitee.com/api/v5/repos/{}/{}/git/trees/{}?access_token={}&recursive=1",
66 &config.gitee_owner, &config.gitee_repo, &config.gitee_branch, &config.gitee_token
67 ))
68 .await?
69 .text()
70 .await?;
71
72 let v: serde_json::Value = serde_json::from_str(&body)?;
74 let tree = v.get("tree");
76 match (tree) {
77 Some(fs) => {
78 let filearray = fs.as_array();
79
80 match (filearray) {
81 Some(files) => {
82 let mut redisconn = pool.get().await?;
84 let mut pipeline = Pipeline::new();
85 for file in files {
86 let filepath = file.get("path").unwrap().as_str().unwrap();
88 let fileurl = file.get("url").unwrap().as_str().unwrap();
90
91 pipeline.cmd("HSET").arg(&[
93 config.gitee_repo.to_owned(),
94 filepath.to_owned(),
95 fileurl.to_owned(),
96 ]);
97 }
98 pipeline.execute_async(&mut redisconn).await?;
99 }
100 None => {}
101 }
102 }
103 None => {}
104 }
105
106 Ok(())
107}
108
109impl RocketGiteePicturesHandler {
111 pub async fn routes(
112 path: &'static str,
113 config: RocketGiteePicturesWrapperConfig,
114 ) -> Vec<Route> {
115 let task_config = config.clone();
116
117 rocket::tokio::spawn(async move {
118 println!("加载gitee文件路径到 redis缓存..");
119 let task_pool = redis_pool_wrapper::get_pool(
121 &task_config.redis_password,
122 &task_config.redis_host,
123 &task_config.redis_port,
124 );
125 loop {
127 load_git_files_path_to_redis(&task_config, &task_pool)
128 .await
129 .unwrap();
130
131 rocket::tokio::time::sleep(std::time::Duration::from_millis(
132 task_config.gitee_refresh_interval as u64,
133 ))
134 .await;
135 }
136 });
137
138 let web_pool = redis_pool_wrapper::get_pool(
140 &config.redis_password,
141 &config.redis_host,
142 &config.redis_port,
143 );
144
145 let handler = Self {
146 config: config.clone(),
147 redis_pool: web_pool,
149 };
150 vec![Route::new(Get, &path, handler)]
152 }
153}
154
155#[rocket::async_trait]
156impl route::Handler for RocketGiteePicturesHandler {
157 async fn handle<'r>(&self, req: &'r Request<'_>, data: Data<'r>) -> route::Outcome<'r> {
158 let image_path = req
160 .segments::<PathBuf>(0..)
161 .unwrap()
162 .to_str()
163 .unwrap()
164 .replace("\\", "/");
165
166 println!("image_path={}", &image_path);
167
168 let redis_pool = &self.redis_pool;
170 let mut redisconn = redis_pool.get().await.unwrap();
172 let v = cmd("HGET")
173 .arg(&[self.config.gitee_repo.to_owned(), image_path.to_owned()])
174 .query_async::<String>(&mut redisconn)
175 .await;
176 let mut file_url: String = String::from("");
178 match v {
179 Ok(s) => {
180 file_url = s.clone();
181 }
182 Err(_e) => {}
183 }
184
185 if file_url == "" {
186 return route::Outcome::from(req, "");
187 }
188
189 let response_body = reqwest::get(format!(
191 "{}?access_token={}",
192 &file_url, &self.config.gitee_token
193 ))
194 .await
195 .unwrap()
196 .text()
197 .await
198 .unwrap();
199
200 let response_body_json: serde_json::Value = serde_json::from_str(&response_body).unwrap();
201 let response_body_content = response_body_json.get("content").unwrap().as_str().unwrap();
202 let response_body_bytes = base64::decode(response_body_content).unwrap();
203 println!("file_url={}", &file_url);
204
205 route::Outcome::from(
206 req,
207 (
208 ContentType::parse_flexible("image/webp").unwrap(),
209 response_body_bytes,
210 ),
211 )
212 }
213}