@@ -35,6 +35,9 @@ class NamespaceS3 {
35
35
this . access_key = s3_params . accessKeyId ;
36
36
this . endpoint = s3_params . endpoint ;
37
37
this . s3 = noobaa_s3_client . get_s3_client_v3_params ( s3_params ) ;
38
+ if ( ! bucket ) {
39
+ throw new Error ( 'NamespaceS3: bucket is required' ) ;
40
+ }
38
41
this . bucket = String ( bucket ) ;
39
42
this . access_mode = s3_params . access_mode ;
40
43
this . stats = stats ;
@@ -207,8 +210,10 @@ class NamespaceS3 {
207
210
await this . s3 . getObject ( request ) :
208
211
await this . s3 . headObject ( request ) ;
209
212
} catch ( err ) {
210
- // catch invalid range error for objects of size 0 and trying head object instead
211
- if ( err . code !== 'InvalidRange' ) {
213
+ // catch invalid range error for objects of size 0 and try head object instead
214
+ const httpCode = err ?. $metadata ?. httpStatusCode ;
215
+ const isInvalidRange = err ?. name === 'InvalidRange' || httpCode === 416 ;
216
+ if ( ! isInvalidRange ) {
212
217
throw err ;
213
218
}
214
219
res = await this . s3 . headObject ( { ...request , Range : undefined } ) ;
@@ -256,7 +261,8 @@ class NamespaceS3 {
256
261
this . bucket ,
257
262
inspect ( _ . omit ( params , 'object_md.ns' ) ) ,
258
263
) ;
259
- if ( obj_out . $metadata . httpStatusCode >= 300 ) return ; // will be handled by error event
264
+ // In v3, non-2xx typically throws; keep this guard harmless.
265
+ if ( obj_out . $metadata . httpStatusCode >= 300 ) throw new Error ( `S3 getObject failed with status ${ obj_out . $metadata . httpStatusCode } ` ) ;
260
266
let count = 1 ;
261
267
// on s3 read_object_md might not return x-amz-tagging-count header, so we get it here
262
268
//params.tag_count = headers['x-amz-tagging-count'];
@@ -270,12 +276,13 @@ class NamespaceS3 {
270
276
// clear count for next updates
271
277
count = 0 ;
272
278
} ) ;
273
- const read_stream = /** @type {import('stream').Readable } **/ obj_out . Body . transformToWebStream ( ) ;
274
- await stream_utils . pipeline ( [ read_stream , count_stream ] , true ) ;
275
- return count_stream ;
279
+ const read_stream = /** @type {import('stream').Readable } */ ( obj_out . Body ) ;
280
+ // Return a live stream to be piped by the caller (endpoint)
281
+ return read_stream . pipe ( count_stream ) ;
276
282
} catch ( err ) {
277
283
this . _translate_error_code ( params , err ) ;
278
284
dbg . warn ( 'NamespaceS3.read_object_stream:' , inspect ( err ) ) ;
285
+ throw err ;
279
286
}
280
287
}
281
288
@@ -350,16 +357,15 @@ class NamespaceS3 {
350
357
}
351
358
}
352
359
dbg . log0 ( 'NamespaceS3.upload_object:' , this . bucket , inspect ( params ) , 'res' , inspect ( res ) ) ;
353
- const etag = s3_utils . parse_etag ( res . ETag ) ;
354
- /** @type {import("@aws-sdk/client-s3").GetObjectAttributesRequest } */
360
+ const etag = s3_utils . parse_etag ( res . ETag || res . CopyObjectResult ?. ETag ) ;
361
+ /** @type {import("@aws-sdk/client-s3").HeadObjectRequest } */
355
362
const request = {
356
363
Bucket : this . bucket ,
357
364
Key : params . key ,
358
365
VersionId : params . version_id ,
359
- ObjectAttributes : params . attributes ,
360
366
} ;
361
367
const res_head = await this . s3 . headObject ( request ) ;
362
- const last_modified_time = await s3_utils . get_http_response_date ( res_head , this . s3 , this . bucket , params . key ) ;
368
+ const last_modified_time = await s3_utils . get_http_response_date ( res_head ) ;
363
369
return { etag, version_id : res . VersionId , last_modified_time } ;
364
370
}
365
371
@@ -477,7 +483,7 @@ class NamespaceS3 {
477
483
Key : params . key ,
478
484
UploadId : params . obj_id ,
479
485
MaxParts : params . max ,
480
- PartNumberMarker : params . num_marker . toString ( ) ,
486
+ PartNumberMarker : params . num_marker ? .toString ( ) ,
481
487
} ;
482
488
const res = await this . s3 . listParts ( req ) ;
483
489
dbg . log0 ( 'NamespaceS3.list_multiparts:' , this . bucket , inspect ( params ) , 'res' , inspect ( res ) ) ;
0 commit comments