@@ -179,3 +179,189 @@ func TestPutObject_PresignURL(t *testing.T) {
179179 })
180180 }
181181}
182+
183+ func TestUploadPart_PresignURL (t * testing.T ) {
184+ cases := map [string ]struct {
185+ input s3.UploadPartInput
186+ options s3.PresignOptions
187+ expectPresignedURLHost string
188+ expectRequestURIQuery []string
189+ expectSignedHeader http.Header
190+ expectMethod string
191+ expectError string
192+ }{
193+ "standard case" : {
194+ input : s3.UploadPartInput {
195+ Bucket : aws .String ("mock-bucket" ),
196+ Key : aws .String ("mockkey" ),
197+ PartNumber : 1 ,
198+ UploadId : aws .String ("123456" ),
199+ Body : strings .NewReader ("hello-world" ),
200+ },
201+ expectPresignedURLHost : "https://mock-bucket.s3.us-west-2.amazonaws.com/mockkey?" ,
202+ expectRequestURIQuery : []string {
203+ "X-Amz-Expires=900" ,
204+ "X-Amz-Credential" ,
205+ "X-Amz-Date" ,
206+ "partNumber=1" ,
207+ "uploadId=123456" ,
208+ "x-id=UploadPart" ,
209+ "X-Amz-Signature" ,
210+ },
211+ expectMethod : "PUT" ,
212+ expectSignedHeader : http.Header {
213+ "Content-Length" : []string {"11" },
214+ "Content-Type" : []string {"application/octet-stream" },
215+ "Host" : []string {"mock-bucket.s3.us-west-2.amazonaws.com" },
216+ },
217+ },
218+ "seekable payload" : {
219+ input : s3.UploadPartInput {
220+ Bucket : aws .String ("mock-bucket" ),
221+ Key : aws .String ("mockkey" ),
222+ PartNumber : 1 ,
223+ UploadId : aws .String ("123456" ),
224+ Body : bytes .NewReader ([]byte ("hello-world" )),
225+ },
226+ expectPresignedURLHost : "https://mock-bucket.s3.us-west-2.amazonaws.com/mockkey?" ,
227+ expectRequestURIQuery : []string {
228+ "X-Amz-Expires=900" ,
229+ "X-Amz-Credential" ,
230+ "X-Amz-Date" ,
231+ "partNumber=1" ,
232+ "uploadId=123456" ,
233+ "x-id=UploadPart" ,
234+ "X-Amz-Signature" ,
235+ },
236+ expectMethod : "PUT" ,
237+ expectSignedHeader : http.Header {
238+ "Content-Length" : []string {"11" },
239+ "Content-Type" : []string {"application/octet-stream" },
240+ "Host" : []string {"mock-bucket.s3.us-west-2.amazonaws.com" },
241+ },
242+ },
243+ "unseekable payload" : {
244+ // unseekable payload succeeds as we disable content sha256 computation for streaming input
245+ input : s3.UploadPartInput {
246+ Bucket : aws .String ("mock-bucket" ),
247+ Key : aws .String ("mockkey" ),
248+ PartNumber : 1 ,
249+ UploadId : aws .String ("123456" ),
250+ Body : bytes .NewBuffer ([]byte (`hello-world` )),
251+ },
252+ expectPresignedURLHost : "https://mock-bucket.s3.us-west-2.amazonaws.com/mockkey?" ,
253+ expectRequestURIQuery : []string {
254+ "X-Amz-Expires=900" ,
255+ "X-Amz-Credential" ,
256+ "X-Amz-Date" ,
257+ "partNumber=1" ,
258+ "uploadId=123456" ,
259+ "x-id=UploadPart" ,
260+ "X-Amz-Signature" ,
261+ },
262+ expectMethod : "PUT" ,
263+ expectSignedHeader : http.Header {
264+ "Content-Length" : []string {"11" },
265+ "Content-Type" : []string {"application/octet-stream" },
266+ "Host" : []string {"mock-bucket.s3.us-west-2.amazonaws.com" },
267+ },
268+ },
269+ "empty body" : {
270+ input : s3.UploadPartInput {
271+ Bucket : aws .String ("mock-bucket" ),
272+ Key : aws .String ("mockkey" ),
273+ PartNumber : 1 ,
274+ UploadId : aws .String ("123456" ),
275+ Body : bytes .NewReader ([]byte (`` )),
276+ },
277+ expectPresignedURLHost : "https://mock-bucket.s3.us-west-2.amazonaws.com/mockkey?" ,
278+ expectRequestURIQuery : []string {
279+ "X-Amz-Expires=900" ,
280+ "X-Amz-Credential" ,
281+ "X-Amz-Date" ,
282+ "partNumber=1" ,
283+ "uploadId=123456" ,
284+ "x-id=UploadPart" ,
285+ "X-Amz-Signature" ,
286+ },
287+ expectMethod : "PUT" ,
288+ expectSignedHeader : http.Header {
289+ "Host" : []string {"mock-bucket.s3.us-west-2.amazonaws.com" },
290+ },
291+ },
292+ "nil body" : {
293+ input : s3.UploadPartInput {
294+ Bucket : aws .String ("mock-bucket" ),
295+ Key : aws .String ("mockkey" ),
296+ PartNumber : 1 ,
297+ UploadId : aws .String ("123456" ),
298+ },
299+ expectPresignedURLHost : "https://mock-bucket.s3.us-west-2.amazonaws.com/mockkey?" ,
300+ expectRequestURIQuery : []string {
301+ "X-Amz-Expires=900" ,
302+ "X-Amz-Credential" ,
303+ "X-Amz-Date" ,
304+ "partNumber=1" ,
305+ "uploadId=123456" ,
306+ "x-id=UploadPart" ,
307+ "X-Amz-Signature" ,
308+ },
309+ expectMethod : "PUT" ,
310+ expectSignedHeader : http.Header {
311+ "Host" : []string {"mock-bucket.s3.us-west-2.amazonaws.com" },
312+ },
313+ },
314+ }
315+
316+ for name , c := range cases {
317+ t .Run (name , func (t * testing.T ) {
318+ ctx := context .Background ()
319+ cfg := aws.Config {
320+ Region : "us-west-2" ,
321+ Credentials : unit.StubCredentialsProvider {},
322+ Retryer : func () aws.Retryer {
323+ return aws.NopRetryer {}
324+ },
325+ }
326+ presignClient := s3 .NewPresignClient (s3 .NewFromConfig (cfg ), func (options * s3.PresignOptions ) {
327+ options = & c .options
328+ })
329+
330+ req , err := presignClient .PresignUploadPart (ctx , & c .input )
331+ if err != nil {
332+ if len (c .expectError ) == 0 {
333+ t .Fatalf ("expected no error, got %v" , err )
334+ }
335+ // if expect error, match error and skip rest
336+ if e , a := c .expectError , err .Error (); ! strings .Contains (a , e ) {
337+ t .Fatalf ("expected error to be %s, got %s" , e , a )
338+ }
339+ } else {
340+ if len (c .expectError ) != 0 {
341+ t .Fatalf ("expected error to be %v, got none" , c .expectError )
342+ }
343+ }
344+
345+ if e , a := c .expectPresignedURLHost , req .URL ; ! strings .Contains (a , e ) {
346+ t .Fatalf ("expected presigned url to contain host %s, got %s" , e , a )
347+ }
348+
349+ if len (c .expectRequestURIQuery ) != 0 {
350+ for _ , label := range c .expectRequestURIQuery {
351+ if e , a := label , req .URL ; ! strings .Contains (a , e ) {
352+ t .Fatalf ("expected presigned url to contain %v label in url: %v" , label , req .URL )
353+ }
354+ }
355+ }
356+
357+ if e , a := c .expectSignedHeader , req .SignedHeader ; len (cmp .Diff (e , a )) != 0 {
358+ t .Fatalf ("expected signed header to be %s, got %s, \n diff : %s" , e , a , cmp .Diff (e , a ))
359+ }
360+
361+ if e , a := c .expectMethod , req .Method ; ! strings .EqualFold (e , a ) {
362+ t .Fatalf ("expected presigning Method to be %s, got %s" , e , a )
363+ }
364+
365+ })
366+ }
367+ }
0 commit comments