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 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
| use axum::{ Json, Router, body::Bytes, extract::{Multipart, Path, State}, http::StatusCode, routing::{get, post}, }; use minio::s3::{Client, creds::StaticProvider, http::BaseUrl, types::S3Api}; use tracing::info;
mod config;
#[derive(Clone)] pub struct AppState { pub minio_client: minio::s3::Client, pub minio_bucket_name: String, }
#[tokio::main] async fn main() { tracing_subscriber::fmt::init();
dotenvy::dotenv().ok();
let config = config::AppConfig::from_env().unwrap();
let minio_endpoint: BaseUrl = config.minio_endpoint.parse().unwrap();
let static_provider = StaticProvider::new(&config.minio_access_key, &config.minio_secret_key, None);
let client = Client::new(minio_endpoint, Some(Box::new(static_provider)), None, None);
if let Ok(client) = client { let bucket = client .bucket_exists(&config.minio_bucket_name) .send() .await .unwrap();
if !bucket.exists { info!("MinIO bucket does not exist, creating..."); client .create_bucket(&config.minio_bucket_name) .send() .await .unwrap(); }
info!("MinIO connect successfully.");
let app_state = AppState { minio_client: client, minio_bucket_name: config.minio_bucket_name, };
let app = Router::new() .route("/", get(hello_minio)) .route("/file", post(upload_file)) .route("/file/{object_key}", get(download_file)) .with_state(app_state);
let listener = tokio::net::TcpListener::bind(&config.server_address) .await .unwrap();
tracing::info!("listening on {}", &config.server_address);
axum::serve(listener, app).await.unwrap(); } }
async fn hello_minio() -> (StatusCode, Json<String>) { (StatusCode::OK, Json("hello minio".to_owned())) }
async fn upload_file(state: State<AppState>, mut payload: Multipart) -> (StatusCode, Json<String>) { let field = payload.next_field().await.unwrap().unwrap(); let name = field.name().unwrap().to_string(); if name.eq("file") { let file_name = field.file_name().unwrap().to_string(); let byte = field.bytes().await.unwrap(); state .minio_client .put_object(&state.minio_bucket_name, file_name, byte.into()) .send() .await .unwrap();
(StatusCode::OK, Json("OK".to_string())) } else { ( StatusCode::FORBIDDEN, Json("does not find file key's value".to_string()), ) } }
async fn download_file( state: State<AppState>, Path(object_key): Path<String>, ) -> (StatusCode, Bytes) { let object = state .minio_client .get_object(&state.minio_bucket_name, object_key) .send() .await .unwrap(); let bytes = object .content .to_segmented_bytes() .await .unwrap() .to_bytes(); return (StatusCode::OK, bytes); }
|