11const async = require ( 'async' ) ;
22const assert = require ( 'assert' ) ;
3- const { createHash } = require ( 'crypto' ) ;
43const {
54 S3Client,
65 CreateBucketCommand,
@@ -22,64 +21,19 @@ const getConfig = require('../functional/aws-node-sdk/test/support/config');
2221const WAIT_MS = 100 ;
2322let s3Client = null ;
2423
25- /**
26- * Creates an S3 client that uses MD5 checksums for DeleteObjects operations
27- * Based on https://github.com/aws/aws-sdk-js-v3/blob/main/supplemental-docs/MD5_FALLBACK.md
28- */
29- function createS3ClientWithMD5 ( configuration = { } ) {
30- const client = new S3Client ( configuration ) ;
31-
32- client . middlewareStack . add (
33- ( next , context ) => async args => {
34- const needsMD5 = context . commandName === 'DeleteObjectsCommand' ||
35- context . commandName === 'UploadPartCommand' ||
36- context . commandName === 'CompleteMultipartUploadCommand' ;
37-
38- if ( ! needsMD5 ) {
39- return next ( args ) ;
40- }
41-
42- const headers = args . request . headers ;
43-
44- // Remove any checksum headers
45- Object . keys ( headers ) . forEach ( header => {
46- if (
47- header . toLowerCase ( ) . startsWith ( 'x-amz-checksum-' ) ||
48- header . toLowerCase ( ) . startsWith ( 'x-amz-sdk-checksum-' )
49- ) {
50- delete headers [ header ] ;
51- }
52- } ) ;
53-
54- // Add MD5
55- if ( args . request . body ) {
56- const bodyContent = Buffer . from ( args . request . body ) ;
57- // Create a new hash instance for each request
58- headers [ 'Content-MD5' ] = createHash ( 'md5' ) . update ( bodyContent ) . digest ( 'base64' ) ;
59- }
60-
61- return await next ( args ) ;
62- } ,
63- {
64- step : 'build' ,
65- }
66- ) ;
67- return client ;
68- }
69-
7024function wait ( timeoutMs , cb ) {
7125 setTimeout ( cb , timeoutMs ) ;
7226}
7327
7428function createBucket ( bucket , cb ) {
75- return s3Client . send ( new CreateBucketCommand ( { Bucket : bucket } ) )
29+ s3Client . send ( new CreateBucketCommand ( { Bucket : bucket } ) )
7630 . then ( data => cb ( null , data ) )
7731 . catch ( cb ) ;
7832}
7933
8034function deleteBucket ( bucket , cb ) {
81- return s3Client . send ( new DeleteBucketCommand ( { Bucket : bucket } ) )
82- . then ( ( ) => cb ( ) )
35+ s3Client . send ( new DeleteBucketCommand ( { Bucket : bucket } ) )
36+ . then ( ( ) => cb ( null ) )
8337 . catch ( cb ) ;
8438}
8539
@@ -90,14 +44,14 @@ function putObject(bucket, key, size, cb) {
9044 Key : key ,
9145 Body : body ,
9246 } ;
93- return s3Client . send ( new PutObjectCommand ( params ) )
47+ s3Client . send ( new PutObjectCommand ( params ) )
9448 . then ( data => cb ( null , data ) )
9549 . catch ( cb ) ;
9650}
9751
9852function deleteObject ( bucket , key , cb ) {
99- return s3Client . send ( new DeleteObjectCommand ( { Bucket : bucket , Key : key } ) )
100- . then ( ( ) => cb ( ) )
53+ s3Client . send ( new DeleteObjectCommand ( { Bucket : bucket , Key : key } ) )
54+ . then ( ( ) => cb ( null ) )
10155 . catch ( cb ) ;
10256}
10357
@@ -108,29 +62,29 @@ function deleteObjects(bucket, keys, cb) {
10862 Bucket : bucket ,
10963 Delete : deleteRequest ,
11064 } ;
111- return s3Client . send ( new DeleteObjectsCommand ( params ) )
112- . then ( ( ) => cb ( ) )
65+ s3Client . send ( new DeleteObjectsCommand ( params ) )
66+ . then ( ( ) => cb ( null ) )
11367 . catch ( cb ) ;
11468}
11569
11670function copyObject ( bucket , key , cb ) {
11771 const params = { Bucket : bucket , CopySource : `${ bucket } /${ key } ` , Key : `${ key } -copy` } ;
118- return s3Client . send ( new CopyObjectCommand ( params ) )
119- . then ( ( ) => cb ( ) )
72+ s3Client . send ( new CopyObjectCommand ( params ) )
73+ . then ( ( ) => cb ( null ) )
12074 . catch ( cb ) ;
12175}
12276
12377function enableVersioning ( bucket , enable , cb ) {
12478 const versioningStatus = { Status : enable ? 'Enabled' : 'Disabled' } ;
12579 const params = { Bucket : bucket , VersioningConfiguration : versioningStatus } ;
126- return s3Client . send ( new PutBucketVersioningCommand ( params ) )
127- . then ( ( ) => cb ( ) )
80+ s3Client . send ( new PutBucketVersioningCommand ( params ) )
81+ . then ( ( ) => cb ( null ) )
12882 . catch ( cb ) ;
12983}
13084
131- function deleteVersionList ( versionList , bucket , callback ) {
85+ async function deleteVersionList ( versionList , bucket ) {
13286 if ( versionList === undefined || versionList . length === 0 ) {
133- return callback ( ) ;
87+ return ;
13488 }
13589 const deleteRequest = { Objects : [ ] } ;
13690 versionList . forEach ( version => {
@@ -140,36 +94,43 @@ function deleteVersionList(versionList, bucket, callback) {
14094 Bucket : bucket ,
14195 Delete : deleteRequest ,
14296 } ;
143- return s3Client . send ( new DeleteObjectsCommand ( params ) )
144- . then ( ( ) => callback ( ) )
145- . catch ( callback ) ;
97+ await s3Client . send ( new DeleteObjectsCommand ( params ) ) ;
14698}
14799
148- function removeAllVersions ( params , callback ) {
149- const bucket = params . Bucket ;
150- async . waterfall ( [
151- cb => s3Client . send ( new ListObjectVersionsCommand ( params ) )
152- . then ( data => cb ( null , data ) )
153- . catch ( cb ) ,
154- ( data , cb ) => deleteVersionList ( data . DeleteMarkers , bucket , err => cb ( err , data ) ) ,
155- ( data , cb ) => deleteVersionList ( data . Versions , bucket , err => cb ( err , data ) ) ,
156- ( data , cb ) => {
157- if ( data . IsTruncated ) {
158- const params = { Bucket : bucket , KeyMarker : data . NextKeyMarker ,
159- VersionIdMarker : data . NextVersionIdMarker } ;
160- return removeAllVersions ( params , cb ) ;
161- }
162- return cb ( ) ;
163- } ,
164- ] , callback ) ;
100+ async function removeAllVersions ( params , callback ) {
101+ try {
102+ const bucket = params . Bucket ;
103+ const data = await s3Client . send ( new ListObjectVersionsCommand ( params ) ) ;
104+
105+ if ( data . DeleteMarkers && data . DeleteMarkers . length > 0 ) {
106+ await deleteVersionList ( data . DeleteMarkers , bucket ) ;
107+ }
108+
109+ if ( data . Versions && data . Versions . length > 0 ) {
110+ await deleteVersionList ( data . Versions , bucket ) ;
111+ }
112+
113+ if ( data . IsTruncated ) {
114+ const nextParams = {
115+ Bucket : bucket ,
116+ KeyMarker : data . NextKeyMarker ,
117+ VersionIdMarker : data . NextVersionIdMarker
118+ } ;
119+ await removeAllVersions ( nextParams ) ;
120+ }
121+
122+ callback ( ) ;
123+ } catch ( error ) {
124+ callback ( error ) ;
125+ }
165126}
166127
167128function objectMPU ( bucket , key , parts , partSize , callback ) {
168129 let ETags = [ ] ;
169130 let uploadId = null ;
170131 const partNumbers = Array . from ( Array ( parts ) . keys ( ) ) ;
171132 const initiateMPUParams = { Bucket : bucket , Key : key } ;
172- return async . waterfall ( [
133+ async . waterfall ( [
173134 next => s3Client . send ( new CreateMultipartUploadCommand ( initiateMPUParams ) )
174135 . then ( data => {
175136 uploadId = data . UploadId ;
@@ -186,7 +147,7 @@ function objectMPU(bucket, key, parts, partSize, callback) {
186147 UploadId : uploadId ,
187148 Body : body ,
188149 } ;
189- return s3Client . send ( new UploadPartCommand ( uploadPartParams ) )
150+ s3Client . send ( new UploadPartCommand ( uploadPartParams ) )
190151 . then ( data => callback ( null , data . ETag ) )
191152 . catch ( callback ) ;
192153 } , ( err , results ) => {
@@ -204,19 +165,19 @@ function objectMPU(bucket, key, parts, partSize, callback) {
204165 MultipartUpload : completeRequest ,
205166 UploadId : uploadId ,
206167 } ;
207- return s3Client . send ( new CompleteMultipartUploadCommand ( params ) )
168+ s3Client . send ( new CompleteMultipartUploadCommand ( params ) )
208169 . then ( data => next ( null , data ) )
209170 . catch ( next ) ;
210171 } ,
211172 ] , callback ) ;
212173}
213174
214175function removeVersions ( buckets , cb ) {
215- return async . each ( buckets , ( bucket , done ) => removeAllVersions ( { Bucket : bucket } , done ) , cb ) ;
176+ async . each ( buckets , ( bucket , done ) => removeAllVersions ( { Bucket : bucket } , done ) , cb ) ;
216177}
217178
218179function getObject ( bucket , key , cb ) {
219- return s3Client . send ( new GetObjectCommand ( { Bucket : bucket , Key : key } ) )
180+ s3Client . send ( new GetObjectCommand ( { Bucket : bucket , Key : key } ) )
220181 . then ( data => cb ( null , data ) )
221182 . catch ( cb ) ;
222183}
@@ -234,7 +195,7 @@ describe('utapi v2 metrics incoming and outgoing bytes', function t() {
234195 }
235196
236197 before ( ( ) => {
237- s3Client = createS3ClientWithMD5 ( getConfig ( 'default' ) ) ;
198+ s3Client = new S3Client ( getConfig ( 'default' ) ) ;
238199 utapi . start ( ) ;
239200 } ) ;
240201 afterEach ( ( ) => {
0 commit comments