2022-08-01 02:17:59 +02:00
|
|
|
use std::fs;
|
2022-02-18 03:13:08 +01:00
|
|
|
|
2020-02-05 04:53:33 +01:00
|
|
|
use actix_multipart::Multipart;
|
2022-08-01 04:19:39 +02:00
|
|
|
use actix_web::{
|
|
|
|
get, middleware::Logger, post, web, App, Error, HttpResponse, HttpServer, Responder,
|
|
|
|
};
|
2022-08-01 02:17:59 +02:00
|
|
|
use actix_web_lab::respond::Html;
|
|
|
|
use aws_config::meta::region::RegionProviderChain;
|
2020-02-06 02:06:41 +01:00
|
|
|
use dotenv::dotenv;
|
2020-04-01 11:53:59 +02:00
|
|
|
use serde::{Deserialize, Serialize};
|
2022-08-01 04:19:39 +02:00
|
|
|
use serde_json::json;
|
2020-04-01 11:53:59 +02:00
|
|
|
|
2022-08-01 04:19:39 +02:00
|
|
|
mod client;
|
|
|
|
mod temp_file;
|
|
|
|
mod upload_file;
|
2020-04-01 11:53:59 +02:00
|
|
|
mod utils;
|
2022-08-01 02:17:59 +02:00
|
|
|
|
2022-08-01 04:19:39 +02:00
|
|
|
use self::client::Client;
|
|
|
|
use self::temp_file::TempFile;
|
|
|
|
use self::upload_file::UploadedFile;
|
|
|
|
use self::utils::split_payload;
|
2020-02-06 02:06:41 +01:00
|
|
|
|
2022-08-01 04:19:39 +02:00
|
|
|
#[derive(Debug, Deserialize, Serialize)]
|
|
|
|
#[serde(rename_all = "camelCase")]
|
|
|
|
pub struct UploadMeta {
|
|
|
|
namespace: String,
|
2020-02-05 04:53:33 +01:00
|
|
|
}
|
2020-02-06 02:06:41 +01:00
|
|
|
|
2022-08-01 04:19:39 +02:00
|
|
|
impl Default for UploadMeta {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self {
|
|
|
|
namespace: "default".to_owned(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[post("/")]
|
|
|
|
async fn upload_to_s3(
|
2022-08-01 02:17:59 +02:00
|
|
|
s3_client: web::Data<Client>,
|
|
|
|
mut payload: Multipart,
|
2022-08-01 04:19:39 +02:00
|
|
|
) -> Result<impl Responder, Error> {
|
|
|
|
let (data, files) = split_payload(&mut payload).await;
|
|
|
|
log::info!("bytes = {data:?}");
|
2022-08-01 02:17:59 +02:00
|
|
|
|
2022-08-01 04:19:39 +02:00
|
|
|
let upload_meta = serde_json::from_slice::<UploadMeta>(&data).unwrap_or_default();
|
|
|
|
log::info!("converter_struct = {upload_meta:?}");
|
|
|
|
log::info!("tmp_files = {files:?}");
|
2022-08-01 02:17:59 +02:00
|
|
|
|
2022-08-01 04:19:39 +02:00
|
|
|
// make key prefix (make sure it ends with a forward slash)
|
|
|
|
let s3_key_prefix = format!("uploads/{}/", upload_meta.namespace);
|
2022-08-01 02:17:59 +02:00
|
|
|
|
|
|
|
// create tmp file and upload s3 and remove tmp file
|
2022-08-01 04:19:39 +02:00
|
|
|
let uploaded_files = s3_client.upload_files(files, &s3_key_prefix).await?;
|
2022-08-01 02:17:59 +02:00
|
|
|
|
2022-08-01 04:19:39 +02:00
|
|
|
Ok(HttpResponse::Ok().json(json!({
|
|
|
|
"uploadedFiles": uploaded_files,
|
|
|
|
"meta": upload_meta,
|
|
|
|
})))
|
2020-02-05 04:53:33 +01:00
|
|
|
}
|
|
|
|
|
2022-08-01 04:19:39 +02:00
|
|
|
#[get("/")]
|
2022-08-01 02:17:59 +02:00
|
|
|
async fn index() -> impl Responder {
|
|
|
|
Html(include_str!("./index.html").to_owned())
|
2020-02-05 04:53:33 +01:00
|
|
|
}
|
|
|
|
|
2020-09-12 17:49:45 +02:00
|
|
|
#[actix_web::main]
|
2020-02-05 04:53:33 +01:00
|
|
|
async fn main() -> std::io::Result<()> {
|
2020-02-06 02:06:41 +01:00
|
|
|
dotenv().ok();
|
2022-02-18 03:13:08 +01:00
|
|
|
env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));
|
|
|
|
|
2022-08-01 02:17:59 +02:00
|
|
|
log::info!("creating temporary upload directory");
|
|
|
|
|
|
|
|
fs::create_dir_all("./tmp").unwrap();
|
2020-02-06 02:06:41 +01:00
|
|
|
|
2022-08-01 02:17:59 +02:00
|
|
|
log::info!("configuring S3 client");
|
|
|
|
let aws_region = RegionProviderChain::default_provider().or_else("us-east-1");
|
|
|
|
let aws_config = aws_config::from_env().region(aws_region).load().await;
|
2022-08-01 04:19:39 +02:00
|
|
|
|
|
|
|
// create singleton S3 client
|
2022-08-01 02:17:59 +02:00
|
|
|
let s3_client = Client::new(&aws_config);
|
2020-02-06 02:06:41 +01:00
|
|
|
|
2022-08-01 02:17:59 +02:00
|
|
|
log::info!("using AWS region: {}", aws_config.region().unwrap());
|
2020-02-05 04:53:33 +01:00
|
|
|
|
2022-02-18 03:13:08 +01:00
|
|
|
log::info!("starting HTTP server at http://localhost:8080");
|
2020-02-05 04:53:33 +01:00
|
|
|
|
2022-08-01 02:17:59 +02:00
|
|
|
HttpServer::new(move || {
|
2022-02-18 03:13:08 +01:00
|
|
|
App::new()
|
2022-08-01 04:19:39 +02:00
|
|
|
.service(index)
|
|
|
|
.service(upload_to_s3)
|
2022-02-18 03:13:08 +01:00
|
|
|
.wrap(Logger::default())
|
2022-08-01 02:17:59 +02:00
|
|
|
.app_data(web::Data::new(s3_client.clone()))
|
2020-02-05 04:53:33 +01:00
|
|
|
})
|
2022-08-01 02:17:59 +02:00
|
|
|
.workers(2)
|
2022-02-18 03:13:08 +01:00
|
|
|
.bind(("127.0.0.1", 8080))?
|
2020-02-05 04:53:33 +01:00
|
|
|
.run()
|
|
|
|
.await
|
|
|
|
}
|