@@ -181,7 +181,7 @@ impl S3 for ArunaS3Service {
181181 } ) ?;
182182
183183 let response = CompleteMultipartUploadOutput {
184- e_tag : Some ( format ! ( "-{}" , object. id. to_string ( ) ) ) ,
184+ e_tag : Some ( format ! ( "-{}" , object. id) ) ,
185185 ..Default :: default ( )
186186 } ;
187187
@@ -812,6 +812,125 @@ impl S3 for ArunaS3Service {
812812 Ok ( resp)
813813 }
814814
815+ #[ tracing:: instrument( err) ]
816+ #[ allow( clippy:: blocks_in_conditions) ]
817+ async fn list_objects (
818+ & self ,
819+ req : S3Request < ListObjectsInput > ,
820+ ) -> S3Result < S3Response < ListObjectsOutput > > {
821+ let CheckAccessResult { headers, .. } = req
822+ . extensions
823+ . get :: < CheckAccessResult > ( )
824+ . cloned ( )
825+ . ok_or_else ( || {
826+ error ! ( error = "No context found" ) ;
827+ s3_error ! ( InternalError , "No context found" )
828+ } ) ?;
829+ // Fetch the project name, delimiter and prefix from the request
830+ let project_name = & req. input . bucket ;
831+ let delimiter = req. input . delimiter ;
832+ let prefix = req. input . prefix . filter ( |prefix| !prefix. is_empty ( ) ) ;
833+
834+ // Check if bucket exists as root in cache of paths
835+ match self . cache . get_path ( project_name. as_str ( ) ) {
836+ Some ( _) => { }
837+ None => {
838+ error ! ( "No bucket found" ) ;
839+ return Err ( s3_error ! ( NoSuchBucket , "No bucket found" ) ) ;
840+ }
841+ } ;
842+
843+ let max_keys = match req. input . max_keys {
844+ Some ( k) if k < 1000 => k as usize ,
845+ _ => 1000usize ,
846+ } ;
847+
848+ let start_at = match & req. input . marker {
849+ Some ( marker) => marker,
850+ None => "" ,
851+ } ;
852+
853+ let ( keys, common_prefixes, next_marker) = list_response (
854+ & self . cache ,
855+ & delimiter,
856+ & prefix,
857+ project_name,
858+ start_at,
859+ max_keys,
860+ true ,
861+ )
862+ . await
863+ . map_err ( |_| {
864+ error ! ( error = "Keys not found in ListObjects" ) ;
865+ s3_error ! ( NoSuchKey , "Keys not found in ListObjects" )
866+ } ) ?;
867+
868+ let common_prefixes = Some (
869+ common_prefixes
870+ . into_iter ( )
871+ . map ( |e| CommonPrefix { prefix : Some ( e) } )
872+ . collect ( ) ,
873+ ) ;
874+ let contents = Some (
875+ keys. into_iter ( )
876+ . map ( |e| Object {
877+ checksum_algorithm : None ,
878+ e_tag : Some ( e. etag . to_string ( ) ) ,
879+ key : Some ( e. key ) ,
880+ last_modified : e. created_at . map ( |t| {
881+ s3s:: dto:: Timestamp :: from (
882+ time:: OffsetDateTime :: from_unix_timestamp ( t. and_utc ( ) . timestamp ( ) )
883+ . unwrap_or_else ( |_| {
884+ error ! ( error = "Unable to parse timestamp" ) ;
885+ time:: OffsetDateTime :: now_utc ( )
886+ } ) ,
887+ )
888+ } ) ,
889+ owner : None ,
890+ size : Some ( e. size ) ,
891+ ..Default :: default ( )
892+ } )
893+ . collect ( ) ,
894+ ) ;
895+
896+ let result = ListObjectsOutput {
897+ common_prefixes,
898+ contents,
899+ marker : req. input . marker ,
900+ delimiter,
901+ encoding_type : None ,
902+ is_truncated : Some ( next_marker. is_some ( ) ) ,
903+ max_keys : Some ( max_keys. try_into ( ) . map_err ( |err| {
904+ error ! ( error = ?err, "Conversion failure" ) ;
905+ s3_error ! ( InternalError , "[BACKEND] Conversion failure: {}" , err)
906+ } ) ?) ,
907+ name : Some ( project_name. clone ( ) ) ,
908+ next_marker,
909+ prefix,
910+ ..Default :: default ( )
911+ } ;
912+ debug ! ( ?result) ;
913+
914+ let mut resp = S3Response :: new ( result) ;
915+
916+ if let Some ( headers) = headers {
917+ for ( k, v) in headers {
918+ resp. headers . insert (
919+ HeaderName :: from_bytes ( k. as_bytes ( ) ) . map_err ( |_| {
920+ error ! ( error = "Unable to parse header name" ) ;
921+ s3_error ! ( InternalError , "Unable to parse header name" )
922+ } ) ?,
923+ HeaderValue :: from_str ( & v) . map_err ( |_| {
924+ error ! ( error = "Unable to parse header value" ) ;
925+ s3_error ! ( InternalError , "Unable to parse header value" )
926+ } ) ?,
927+ ) ;
928+ }
929+ }
930+
931+ Ok ( resp)
932+ }
933+
815934 #[ tracing:: instrument( err) ]
816935 #[ allow( clippy:: blocks_in_conditions) ]
817936 async fn list_objects_v2 (
@@ -878,6 +997,7 @@ impl S3 for ArunaS3Service {
878997 project_name,
879998 & start_after,
880999 max_keys,
1000+ false ,
8811001 )
8821002 . await
8831003 . map_err ( |_| {
0 commit comments