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::client::request::OperationDeadline;
12use crate::error::S3Error;
13use crate::operation::{
14 AbortMultipartUploadRequest, CompleteMultipartUploadOutput, CompleteMultipartUploadRequest,
15 CreateMultipartUploadOutput, CreateMultipartUploadRequest, ListMultipartUploadsOutput,
16 ListMultipartUploadsRequest, RequestIds, UploadPartOutput, UploadPartRequest,
17};
18use crate::protocol::{
19 CompleteMultipartResponse, parse_complete_multipart_upload, parse_create_multipart_upload,
20 parse_list_multipart_uploads, serialize_complete_multipart_upload,
21};
22use crate::stream::ByteStream;
23
24impl S3Client {
25 pub async fn create_multipart_upload(
32 &self,
33 request: CreateMultipartUploadRequest,
34 ) -> Result<CreateMultipartUploadOutput, S3Error> {
35 let deadline = self.deadline();
36 self.create_multipart_upload_with_deadline(request, &deadline)
37 .await
38 }
39
40 pub(in crate::client) async fn create_multipart_upload_with_deadline(
41 &self,
42 request: CreateMultipartUploadRequest,
43 deadline: &OperationDeadline,
44 ) -> Result<CreateMultipartUploadOutput, S3Error> {
45 let target = self.operation_target(Some(request.key.as_str()))?;
46 let headers = create_headers(&request)?;
47 let response = self
48 .send_signed(
49 Method::POST,
50 target,
51 &create_query(),
52 headers,
53 None,
54 deadline,
55 )
56 .await?;
57 let request_ids = request_ids(response.headers());
58 let body = self
59 .collect_response(response, self.config().max_xml_response_size(), deadline)
60 .await?;
61 let mut output =
62 parse_create_multipart_upload(&body, self.config().max_xml_response_size())
63 .map_err(crate::client::request::protocol_error)?;
64 output.request_ids = request_ids;
65 Ok(output)
66 }
67
68 pub async fn upload_part(
75 &self,
76 request: UploadPartRequest,
77 ) -> Result<UploadPartOutput, S3Error> {
78 let deadline = self.deadline();
79 self.upload_part_with_deadline(request, &deadline).await
80 }
81
82 pub(in crate::client) async fn upload_part_with_deadline(
83 &self,
84 request: UploadPartRequest,
85 deadline: &OperationDeadline,
86 ) -> Result<UploadPartOutput, S3Error> {
87 let target = self.operation_target(Some(request.key().as_str()))?;
88 let query = upload_part_query(request.part_number().get(), request.upload_id());
89 let headers = checksum_headers(request.checksum())?;
90 let part_number = request.part_number();
91 let body = deadline.prepare_body(request.into_body()).await?;
92 let response = self
93 .send_signed(Method::PUT, target, &query, headers, Some(&body), deadline)
94 .await?;
95 let headers = response.headers().clone();
96 self.drain_success_response(response, deadline).await?;
97 let e_tag = required_header(
98 &headers,
99 ETAG.as_str(),
100 "upload-part response has no usable ETag",
101 )?;
102 let checksum = response_checksums(&headers)?;
103 let request_ids = request_ids(&headers);
104 Ok(UploadPartOutput {
105 part_number,
106 e_tag,
107 checksum,
108 request_ids,
109 })
110 }
111
112 pub async fn complete_multipart_upload(
119 &self,
120 request: CompleteMultipartUploadRequest,
121 ) -> Result<CompleteMultipartUploadOutput, S3Error> {
122 let deadline = self.deadline();
123 self.complete_multipart_upload_with_deadline(request, &deadline)
124 .await
125 }
126
127 pub(in crate::client) async fn complete_multipart_upload_with_deadline(
128 &self,
129 request: CompleteMultipartUploadRequest,
130 deadline: &OperationDeadline,
131 ) -> Result<CompleteMultipartUploadOutput, S3Error> {
132 let target = self.operation_target(Some(request.key.as_str()))?;
133 let query = upload_query(request.upload_id());
134 let document =
135 serialize_complete_multipart_upload(&request, self.config().max_xml_response_size())
136 .map_err(crate::client::request::protocol_error)?;
137 let body = deadline.prepare_body(ByteStream::from(document)).await?;
138 let mut headers = HeaderMap::new();
139 headers.insert(CONTENT_TYPE, HeaderValue::from_static("application/xml"));
140 let response = self
141 .send_signed(Method::POST, target, &query, headers, Some(&body), deadline)
142 .await?;
143 let response_headers = response.headers().clone();
144 let request_ids = request_ids(&response_headers);
145 let version_id = optional_header(&response_headers, "x-amz-version-id")?;
146 let body = self
147 .collect_response(response, self.config().max_xml_response_size(), deadline)
148 .await?;
149 match parse_complete_multipart_upload(&body, self.config().max_xml_response_size())
150 .map_err(crate::client::request::protocol_error)?
151 {
152 CompleteMultipartResponse::Complete(mut output) => {
153 output.version_id = version_id;
154 output.request_ids = request_ids;
155 Ok(output)
156 }
157 CompleteMultipartResponse::EmbeddedError(parsed) => {
158 Err(embedded_complete_error(&response_headers, parsed))
159 }
160 }
161 }
162
163 pub async fn abort_multipart_upload(
170 &self,
171 request: AbortMultipartUploadRequest,
172 ) -> Result<RequestIds, S3Error> {
173 let deadline = self.deadline();
174 self.abort_multipart_upload_with_deadline(request, &deadline)
175 .await
176 }
177
178 pub(in crate::client) async fn abort_multipart_upload_with_deadline(
179 &self,
180 request: AbortMultipartUploadRequest,
181 deadline: &OperationDeadline,
182 ) -> Result<RequestIds, S3Error> {
183 let target = self.operation_target(Some(request.key().as_str()))?;
184 let query = upload_query(request.upload_id());
185 let response = self
186 .send_signed(
187 Method::DELETE,
188 target,
189 &query,
190 HeaderMap::new(),
191 None,
192 deadline,
193 )
194 .await?;
195 let request_ids = request_ids(response.headers());
196 self.drain_success_response(response, deadline).await?;
197 Ok(request_ids)
198 }
199
200 pub async fn list_multipart_uploads(
207 &self,
208 request: ListMultipartUploadsRequest,
209 ) -> Result<ListMultipartUploadsOutput, S3Error> {
210 let target = self.operation_target(None)?;
211 let query = list_query(&request)?;
212 let deadline = self.deadline();
213 let response = self
214 .send_signed(
215 Method::GET,
216 target,
217 &query,
218 HeaderMap::new(),
219 None,
220 &deadline,
221 )
222 .await?;
223 let request_ids = request_ids(response.headers());
224 let body = self
225 .collect_response(response, self.config().max_xml_response_size(), &deadline)
226 .await?;
227 let mut output = parse_list_multipart_uploads(&body, self.config().max_xml_response_size())
228 .map_err(crate::client::request::protocol_error)?;
229 output.request_ids = request_ids;
230 Ok(output)
231 }
232}