@@ -324,5 +324,146 @@ describe('DELETE object', () => {
324
324
}
325
325
) ) ;
326
326
} ) ;
327
+
328
+ describe ( 'with conditional headers (unofficial, for backbeat)' , ( ) => {
329
+ const bucketName = 'testconditionaldelete' ;
330
+ const testObjectKey = 'conditional-test-object' ;
331
+ const testObjectBody = 'body' ;
332
+ let objectLastModified ;
333
+
334
+ before ( async ( ) => {
335
+ await s3 . createBucket ( { Bucket : bucketName } ) . promise ( ) ;
336
+ } ) ;
337
+
338
+ beforeEach ( async ( ) => {
339
+ // Re-create the object for each test since some tests will delete it
340
+ await s3 . putObject ( {
341
+ Bucket : bucketName ,
342
+ Key : testObjectKey ,
343
+ Body : testObjectBody ,
344
+ } ) . promise ( ) ;
345
+ const head = await s3 . headObject ( {
346
+ Bucket : bucketName ,
347
+ Key : testObjectKey ,
348
+ } ) . promise ( ) ;
349
+ objectLastModified = head . LastModified ;
350
+ } ) ;
351
+
352
+ after ( async ( ) => {
353
+ await bucketUtil . empty ( bucketName ) ;
354
+ await bucketUtil . deleteOne ( bucketName ) ;
355
+ } ) ;
356
+
357
+ function deleteObjectConditional ( s3 , params , headers , next ) {
358
+ const request = s3 . deleteObject ( params ) ;
359
+ request . on ( 'build' , ( ) => {
360
+ for ( const [ key , value ] of Object . entries ( headers ) ) {
361
+ request . httpRequest . headers [ key ] = value ;
362
+ }
363
+ } ) ;
364
+ return request . send ( next ) ;
365
+ }
366
+
367
+ describe ( 'If-Unmodified-Since header tests' , ( ) => {
368
+ it ( 'should delete when condition is true (date after object modification)' , done => {
369
+ const futureDate = new Date ( objectLastModified . getTime ( ) + 60_000 ) ; // 1 minute later
370
+
371
+ deleteObjectConditional ( s3 , {
372
+ Bucket : bucketName ,
373
+ Key : testObjectKey ,
374
+ } , {
375
+ 'If-Unmodified-Since' : futureDate . toUTCString ( ) ,
376
+ } , ( err , data ) => {
377
+ assert . ifError ( err ) ;
378
+ assert . deepStrictEqual ( data , { } ) ;
379
+ s3 . headObject ( {
380
+ Bucket : bucketName ,
381
+ Key : testObjectKey ,
382
+ } , err => {
383
+ assert . strictEqual ( err . code , 'NotFound' ) ;
384
+ done ( ) ;
385
+ } ) ;
386
+ } ) ;
387
+ } ) ;
388
+
389
+ it ( 'should fail (412) to delete when condition is false (date before object modification)' , done => {
390
+ const pastDate = new Date ( objectLastModified . getTime ( ) - 60_000 ) ; // 1 minute earlier
391
+
392
+ deleteObjectConditional ( s3 , {
393
+ Bucket : bucketName ,
394
+ Key : testObjectKey ,
395
+ } , {
396
+ 'If-Unmodified-Since' : pastDate . toUTCString ( ) ,
397
+ } , err => {
398
+ assert . strictEqual ( err . code , 'PreconditionFailed' ) ;
399
+ assert . strictEqual ( err . statusCode , 412 ) ;
400
+ done ( ) ;
401
+ } ) ;
402
+ } ) ;
403
+ } ) ;
404
+
405
+ describe ( 'If-Modified-Since header tests' , ( ) => {
406
+ it ( 'should delete when condition is true (date before object modification)' , done => {
407
+ const pastDate = new Date ( objectLastModified . getTime ( ) - 60_000 ) ; // 1 minute earlier
408
+
409
+ deleteObjectConditional ( s3 , {
410
+ Bucket : bucketName ,
411
+ Key : testObjectKey ,
412
+ } , {
413
+ 'If-Modified-Since' : pastDate . toUTCString ( ) ,
414
+ } , ( err , data ) => {
415
+ assert . ifError ( err ) ;
416
+ assert . deepStrictEqual ( data , { } ) ;
417
+ s3 . headObject ( {
418
+ Bucket : bucketName ,
419
+ Key : testObjectKey ,
420
+ } , err => {
421
+ assert . strictEqual ( err . code , 'NotFound' ) ;
422
+ done ( ) ;
423
+ } ) ;
424
+ } ) ;
425
+ } ) ;
426
+
427
+ it ( 'should fail (304) to delete when condition is false (date after object modification)' , done => {
428
+ const futureDate = new Date ( objectLastModified . getTime ( ) + 60_000 ) ; // 1 minute later
429
+
430
+ deleteObjectConditional ( s3 , {
431
+ Bucket : bucketName ,
432
+ Key : testObjectKey ,
433
+ } , {
434
+ 'If-Modified-Since' : futureDate . toUTCString ( ) ,
435
+ } , err => {
436
+ assert . strictEqual ( err . code , 'NotModified' ) ;
437
+ assert . strictEqual ( err . statusCode , 304 ) ;
438
+ done ( ) ;
439
+ } ) ;
440
+ } ) ;
441
+ } ) ;
442
+
443
+ describe ( 'combined conditional headers' , ( ) => {
444
+ it ( 'should delete when both If-Modified-Since and If-Unmodified-Since conditions are true' , done => {
445
+ const pastDate = new Date ( objectLastModified . getTime ( ) - 60_000 ) ; // 1 minute earlier
446
+ const futureDate = new Date ( objectLastModified . getTime ( ) + 60_000 ) ; // 1 minute later
447
+
448
+ deleteObjectConditional ( s3 , {
449
+ Bucket : bucketName ,
450
+ Key : testObjectKey ,
451
+ } , {
452
+ 'If-Modified-Since' : pastDate . toUTCString ( ) ,
453
+ 'If-Unmodified-Since' : futureDate . toUTCString ( ) ,
454
+ } , ( err , data ) => {
455
+ assert . ifError ( err ) ;
456
+ assert . deepStrictEqual ( data , { } ) ;
457
+ s3 . headObject ( {
458
+ Bucket : bucketName ,
459
+ Key : testObjectKey ,
460
+ } , err => {
461
+ assert . strictEqual ( err . code , 'NotFound' ) ;
462
+ done ( ) ;
463
+ } ) ;
464
+ } ) ;
465
+ } ) ;
466
+ } ) ;
467
+ } ) ;
327
468
} ) ;
328
469
} ) ;
0 commit comments