s3_wire/client/multipart/
operations.rs1use http::header::{CONTENT_TYPE, ETAG};
2use http::{HeaderMap, HeaderValue, Method};
3
4use super::errors::embedded_complete_error;
5use super::headers::{
6 checksum_headers, create_headers, optional_header, request_ids, required_header,
7 response_checksums,
8};
9use super::query::{create_query, list_query, upload_part_query, upload_query};
10use crate::client::S3Client;
11use crate::error::S3Error;
12use crate::operation::{
13 AbortMultipartUploadRequest, CompleteMultipartUploadOutput, CompleteMultipartUploadRequest,
14 CreateMultipartUploadOutput, CreateMultipartUploadRequest, ListMultipartUploadsOutput,
15 ListMultipartUploadsRequest, RequestIds, UploadPartOutput, UploadPartRequest,
16};
17use crate::protocol::{
18 CompleteMultipartResponse, parse_complete_multipart_upload, parse_create_multipart_upload,
19 parse_list_multipart_uploads, serialize_complete_multipart_upload,
20};
21use crate::stream::ByteStream;
22
23impl S3Client {
24 pub async fn create_multipart_upload(
31 &self,
32 request: CreateMultipartUploadRequest,
33 ) -> Result<CreateMultipartUploadOutput, S3Error> {
34 let target = self.multipart_object_target(Some(request.key.as_str()))?;
35 let headers = create_headers(&request)?;
36 let deadline = self.deadline();
37 let response = self
38 .send_signed(
39 Method::POST,
40 target,
41 &create_query(),
42 headers,
43 None,
44 &deadline,
45 )
46 .await?;
47 let request_ids = request_ids(response.headers());
48 let body = self
49 .collect_response(response, self.config().max_xml_response_size(), &deadline)
50 .await?;
51 let mut output =
52 parse_create_multipart_upload(&body, self.config().max_xml_response_size())
53 .map_err(crate::client::request::protocol_error)?;
54 output.request_ids = request_ids;
55 Ok(output)
56 }
57
58 pub async fn upload_part(
65 &self,
66 request: UploadPartRequest<ByteStream>,
67 ) -> Result<UploadPartOutput, S3Error> {
68 let target = self.multipart_object_target(Some(request.key().as_str()))?;
69 let query = upload_part_query(request.part_number().get(), request.upload_id());
70 let headers = checksum_headers(request.checksum())?;
71 let part_number = request.part_number();
72 let body = request.into_body().prepare().await?;
73 let deadline = self.deadline();
74 let response = self
75 .send_signed(Method::PUT, target, &query, headers, Some(&body), &deadline)
76 .await?;
77 let headers = response.headers();
78 let e_tag = required_header(
79 headers,
80 ETAG.as_str(),
81 "upload-part response has no usable ETag",
82 )?;
83 let checksum = response_checksums(headers)?;
84 let request_ids = request_ids(headers);
85 Ok(UploadPartOutput {
86 part_number,
87 e_tag,
88 checksum,
89 request_ids,
90 })
91 }
92
93 pub async fn complete_multipart_upload(
100 &self,
101 request: CompleteMultipartUploadRequest,
102 ) -> Result<CompleteMultipartUploadOutput, S3Error> {
103 let target = self.multipart_object_target(Some(request.key.as_str()))?;
104 let query = upload_query(request.upload_id());
105 let document =
106 serialize_complete_multipart_upload(&request, self.config().max_xml_response_size())
107 .map_err(crate::client::request::protocol_error)?;
108 let body = ByteStream::from(document).prepare().await?;
109 let mut headers = HeaderMap::new();
110 headers.insert(CONTENT_TYPE, HeaderValue::from_static("application/xml"));
111 let deadline = self.deadline();
112 let response = self
113 .send_signed(
114 Method::POST,
115 target,
116 &query,
117 headers,
118 Some(&body),
119 &deadline,
120 )
121 .await?;
122 let response_headers = response.headers().clone();
123 let request_ids = request_ids(&response_headers);
124 let version_id = optional_header(&response_headers, "x-amz-version-id")?;
125 let body = self
126 .collect_response(response, self.config().max_xml_response_size(), &deadline)
127 .await?;
128 match parse_complete_multipart_upload(&body, self.config().max_xml_response_size())
129 .map_err(crate::client::request::protocol_error)?
130 {
131 CompleteMultipartResponse::Complete(mut output) => {
132 output.version_id = version_id;
133 output.request_ids = request_ids;
134 Ok(output)
135 }
136 CompleteMultipartResponse::EmbeddedError(parsed) => {
137 Err(embedded_complete_error(&response_headers, parsed))
138 }
139 }
140 }
141
142 pub async fn abort_multipart_upload(
149 &self,
150 request: AbortMultipartUploadRequest,
151 ) -> Result<RequestIds, S3Error> {
152 let target = self.multipart_object_target(Some(request.key().as_str()))?;
153 let query = upload_query(request.upload_id());
154 let deadline = self.deadline();
155 let response = self
156 .send_signed(
157 Method::DELETE,
158 target,
159 &query,
160 HeaderMap::new(),
161 None,
162 &deadline,
163 )
164 .await?;
165 Ok(request_ids(response.headers()))
166 }
167
168 pub async fn list_multipart_uploads(
175 &self,
176 request: ListMultipartUploadsRequest,
177 ) -> Result<ListMultipartUploadsOutput, S3Error> {
178 let target = self.multipart_object_target(None)?;
179 let query = list_query(&request)?;
180 let deadline = self.deadline();
181 let response = self
182 .send_signed(
183 Method::GET,
184 target,
185 &query,
186 HeaderMap::new(),
187 None,
188 &deadline,
189 )
190 .await?;
191 let request_ids = request_ids(response.headers());
192 let body = self
193 .collect_response(response, self.config().max_xml_response_size(), &deadline)
194 .await?;
195 let mut output = parse_list_multipart_uploads(&body, self.config().max_xml_response_size())
196 .map_err(crate::client::request::protocol_error)?;
197 output.request_ids = request_ids;
198 Ok(output)
199 }
200
201 fn multipart_object_target(
202 &self,
203 key: Option<&str>,
204 ) -> Result<crate::endpoint::EndpointUrl, S3Error> {
205 self.config().endpoint().object_url(
206 self.config().bucket(),
207 key,
208 self.config().addressing_style(),
209 )
210 }
211}