s3_signer/multipart_upload/
create.rs1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Deserialize, Serialize)]
4pub struct CreateUploadQueryParameters {
5 pub bucket: String,
6 pub path: String,
7}
8
9#[derive(Debug, Deserialize, Serialize)]
10#[cfg_attr(feature = "server", derive(utoipa::ToSchema))]
11pub struct CreateUploadResponse {
12 pub upload_id: String,
13}
14
15#[cfg(feature = "server")]
16pub(crate) mod server {
17 use super::{CreateUploadQueryParameters, CreateUploadResponse};
18 use crate::{multipart_upload::S3Client, to_ok_json_response, Error, S3Configuration};
19 use rusoto_s3::{CreateMultipartUploadRequest, S3};
20 use std::convert::TryFrom;
21 use warp::{
22 hyper::{Body, Response},
23 Filter, Rejection, Reply,
24 };
25
26 #[utoipa::path(
28 post,
29 context_path = "/multipart-upload",
30 path = "",
31 tag = "Multipart upload",
32 responses(
33 (status = 200, description = "Successfully created multipart upload", body = CreateUploadResponse),
34 ),
35 params(
36 ("bucket" = String, Query, description = "Name of the bucket"),
37 ("path" = String, Query, description = "Key of the object to upload")
38 ),
39 )]
40 pub(crate) fn route(
41 s3_configuration: &S3Configuration,
42 ) -> impl Filter<Extract = (impl Reply,), Error = Rejection> + Clone {
43 let s3_configuration = s3_configuration.clone();
44 warp::path::end()
45 .and(warp::post())
46 .and(warp::query::<CreateUploadQueryParameters>())
47 .and(warp::any().map(move || s3_configuration.clone()))
48 .and_then(
49 |parameters: CreateUploadQueryParameters, s3_configuration: S3Configuration| async move {
50 handle_create_multipart_upload(&s3_configuration, parameters.bucket, parameters.path)
51 .await
52 },
53 )
54 }
55
56 async fn handle_create_multipart_upload(
57 s3_configuration: &S3Configuration,
58 bucket: String,
59 key: String,
60 ) -> Result<Response<Body>, Rejection> {
61 log::info!("Create multipart upload...");
62 let client = S3Client::try_from(s3_configuration)?;
63 client
64 .execute(|client: rusoto_s3::S3Client| async move {
65 let request = CreateMultipartUploadRequest {
66 bucket,
67 key,
68 ..Default::default()
69 };
70
71 client
72 .create_multipart_upload(request)
73 .await
74 .map_err(|error| warp::reject::custom(Error::MultipartUploadCreationError(error)))
75 .and_then(|output| {
76 output
77 .upload_id
78 .ok_or_else(|| {
79 warp::reject::custom(Error::MultipartUploadError(
80 "Invalid multipart upload creation response".to_string(),
81 ))
82 })
83 .and_then(|upload_id| {
84 let body_response = CreateUploadResponse { upload_id };
85 to_ok_json_response(&body_response)
86 })
87 })
88 })
89 .await
90 }
91}