1use crate::generated::{
2 DeleteObjectRequest, GetObjectRequest, PutObjectRequest, UploadPartRequest,
3};
4use rusoto_core::credential::AwsCredentials;
5use rusoto_core::param::{Params, ServiceParams};
6use rusoto_core::region::Region;
7use rusoto_core::signature;
8use rusoto_core::signature::SignedRequest;
9use std::time::Duration;
10pub fn encode_key<T: AsRef<str>>(key: T) -> String {
26 signature::encode_uri_path(key.as_ref())
27}
28
29macro_rules! add_headers {
30 (
31 $input:ident , $req:ident ; $p:ident , $e:expr ; $( $t:tt )*
32 ) => (
33 {
34 if let Some(ref $p) = $input.$p {
35 $req.add_header($e, &$p.to_string());
36 }
37 add_headers! { $input, $req; $( $t )* }
38 }
39 );
40 (
41 $input:pat , $req:expr ;
42 ) => ({
43 });
44}
45
46macro_rules! add_params {
47 (
48 $input:ident , $params:ident ; $p:ident , $e:expr ; $( $t:tt )*
49 ) => (
50 {
51 if let Some(ref $p) = $input.$p {
52 $params.put($e, &$p);
53 }
54 add_params! { $input, $params; $( $t )* }
55 }
56 );
57 (
58 $input:pat , $req:expr ;
59 ) => ({
60 });
61}
62
63pub struct PreSignedRequestOption {
64 pub expires_in: Duration,
65}
66
67impl Default for PreSignedRequestOption {
68 fn default() -> Self {
69 Self {
70 expires_in: Duration::from_secs(3600),
71 }
72 }
73}
74
75pub trait PreSignedRequest {
76 fn get_presigned_url(
78 &self,
79 region: &Region,
80 credentials: &AwsCredentials,
81 option: &PreSignedRequestOption,
82 ) -> String;
83}
84
85impl PreSignedRequest for GetObjectRequest {
86 fn get_presigned_url(
88 &self,
89 region: &Region,
90 credentials: &AwsCredentials,
91 option: &PreSignedRequestOption,
92 ) -> String {
93 let request_uri = format!("/{bucket}/{key}", bucket = self.bucket, key = self.key);
94 let mut request = SignedRequest::new("GET", "s3", ®ion, &request_uri);
95 let mut params = Params::new();
96
97 add_headers!(
98 self, request;
99 range, "Range";
100 if_modified_since, "If-Modified-Since";
101 if_unmodified_since, "If-Unmodified-Since";
102 if_match, "If-Match";
103 if_none_match, "If-None-Match";
104 sse_customer_algorithm, "x-amz-server-side-encryption-customer-algorithm";
105 sse_customer_key, "x-amz-server-side-encryption-customer-key";
106 sse_customer_key_md5, "x-amz-server-side-encryption-customer-key-MD5";
107 );
108
109 add_params!(
110 self, params;
111 part_number, "partNumber";
112 response_content_type, "response-content-type";
113 response_content_language, "response-content-language";
114 response_expires, "response-expires";
115 response_cache_control, "response-cache-control";
116 response_content_disposition, "response-content-disposition";
117 response_content_encoding, "response-content-encoding";
118 version_id, "versionId";
119 );
120
121 request.set_params(params);
122 request.generate_presigned_url(credentials, &option.expires_in, false)
123 }
124}
125
126impl PreSignedRequest for PutObjectRequest {
127 fn get_presigned_url(
129 &self,
130 region: &Region,
131 credentials: &AwsCredentials,
132 option: &PreSignedRequestOption,
133 ) -> String {
134 let request_uri = format!("/{bucket}/{key}", bucket = self.bucket, key = self.key);
135 let mut request = SignedRequest::new("PUT", "s3", ®ion, &request_uri);
136
137 add_headers!(
138 self, request;
139 cache_control, "Cache-Control";
140 content_disposition, "Content-Disposition";
141 content_encoding, "Content-Encoding";
142 content_length, "Content-Length";
143 content_md5, "Content-MD5";
144 content_type, "Content-Type";
145 expires, "Expires";
148 storage_class, "x-amz-storage-class";
149 tagging, "x-amz-tagging";
150 website_redirect_location, "x-amz-website-redirect-location";
151 acl, "x-amz-acl";
152 grant_read, "x-amz-grant-read";
153 grant_read_acp, "x-amz-grant-read-acp";
156 grant_write_acp, "x-amz-grant-write-acp";
157 grant_full_control, "x-amz-grant-full-control";
158 server_side_encryption, "x-amz-server-side-encryption";
159 ssekms_key_id, "x-amz-server-side-encryption-aws-kms-key-id";
160 sse_customer_algorithm, "x-amz-server-side-encryption-customer-algorithm";
163 sse_customer_key, "x-amz-server-side-encryption-customer-key";
164 sse_customer_key_md5, "x-amz-server-side-encryption-customer-key-MD5";
165 );
166
167 if let Some(ref metadata) = self.metadata {
168 for (header_name, header_value) in metadata.iter() {
169 let header = format!("x-amz-meta-{}", header_name);
170 request.add_header(header, header_value);
171 }
172 }
173
174 request.generate_presigned_url(credentials, &option.expires_in, false)
175 }
176}
177
178impl PreSignedRequest for DeleteObjectRequest {
179 fn get_presigned_url(
181 &self,
182 region: &Region,
183 credentials: &AwsCredentials,
184 option: &PreSignedRequestOption,
185 ) -> String {
186 let request_uri = format!("/{bucket}/{key}", bucket = self.bucket, key = self.key);
187 let mut request = SignedRequest::new("DELETE", "s3", ®ion, &request_uri);
188 let mut params = Params::new();
189
190 add_headers!(
191 self, request;
192 mfa, "x-amz-mfa";
193 );
194
195 add_params!(
196 self, params;
197 version_id, "versionId";
198 );
199
200 request.set_params(params);
201 request.generate_presigned_url(credentials, &option.expires_in, false)
202 }
203}
204
205impl PreSignedRequest for UploadPartRequest {
206 fn get_presigned_url(
208 &self,
209 region: &Region,
210 credentials: &AwsCredentials,
211 option: &PreSignedRequestOption,
212 ) -> String {
213 let request_uri = format!("/{bucket}/{key}", bucket = self.bucket, key = self.key);
214 let mut request = SignedRequest::new("PUT", "s3", ®ion, &request_uri);
215
216 request.add_param("partNumber", &self.part_number.to_string());
217 request.add_param("uploadId", &self.upload_id);
218
219 add_headers!(
220 self, request;
221 content_length, "Content-Length";
222 content_md5, "Content-MD5";
223 sse_customer_algorithm, "x-amz-server-side-encryption-customer-algorithm";
224 sse_customer_key, "x-amz-server-side-encryption-customer-key";
225 sse_customer_key_md5, "x-amz-server-side-encryption-customer-key-MD5";
226 request_payer, "x-amz-request-payer";
227 );
228
229 request.generate_presigned_url(credentials, &option.expires_in, false)
230 }
231}