1414import com .sun .net .httpserver .HttpExchange ;
1515import com .sun .net .httpserver .HttpPrincipal ;
1616
17+ import org .elasticsearch .common .Randomness ;
1718import org .elasticsearch .common .Strings ;
1819import org .elasticsearch .common .bytes .BytesArray ;
1920import org .elasticsearch .common .bytes .BytesReference ;
2829import java .net .InetSocketAddress ;
2930import java .net .URI ;
3031import java .nio .charset .StandardCharsets ;
32+ import java .util .ArrayList ;
3133import java .util .List ;
3234import java .util .Objects ;
3335
@@ -45,63 +47,81 @@ public void testRejectsBadUri() {
4547 );
4648 }
4749
50+ private static void assertListObjectsResponse (
51+ S3HttpHandler handler ,
52+ @ Nullable String prefix ,
53+ @ Nullable String delimiter ,
54+ String expectedResponse
55+ ) {
56+ final var queryParts = new ArrayList <String >(3 );
57+ if (prefix != null ) {
58+ queryParts .add ("prefix=" + prefix );
59+ }
60+ if (delimiter != null ) {
61+ queryParts .add ("delimiter=" + delimiter );
62+ }
63+ if (randomBoolean ()) {
64+ // test both ListObjects and ListObjectsV2 - they only differ in terms of pagination but S3HttpHandler doesn't do that
65+ queryParts .add ("list-type=2" );
66+ }
67+ Randomness .shuffle (queryParts );
68+
69+ final var requestUri = "/bucket" + randomFrom ("" , "/" ) + (queryParts .isEmpty () ? "" : "?" + String .join ("&" , queryParts ));
70+ assertEquals ("GET " + requestUri , new TestHttpResponse (RestStatus .OK , expectedResponse ), handleRequest (handler , "GET" , requestUri ));
71+ }
72+
4873 public void testSimpleObjectOperations () {
4974 final var handler = new S3HttpHandler ("bucket" , "path" );
5075
5176 assertEquals (RestStatus .NOT_FOUND , handleRequest (handler , "GET" , "/bucket/path/blob" ).status ());
5277
53- assertEquals (
54- new TestHttpResponse (RestStatus .OK , """
55- <?xml version="1.0" encoding="UTF-8"?><ListBucketResult><Prefix></Prefix></ListBucketResult>""" ),
56- handleRequest (handler , "GET" , "/bucket/?prefix=" )
57- );
78+ assertListObjectsResponse (handler , "" , null , """
79+ <?xml version="1.0" encoding="UTF-8"?><ListBucketResult><Prefix></Prefix><IsTruncated>false</IsTruncated>\
80+ </ListBucketResult>""" );
5881
5982 final var body = randomAlphaOfLength (50 );
6083 assertEquals (RestStatus .OK , handleRequest (handler , "PUT" , "/bucket/path/blob" , body ).status ());
6184 assertEquals (new TestHttpResponse (RestStatus .OK , body ), handleRequest (handler , "GET" , "/bucket/path/blob" ));
6285
63- assertEquals ( new TestHttpResponse ( RestStatus . OK , """
64- <?xml version="1.0" encoding="UTF-8"?><ListBucketResult><Prefix></Prefix>\
86+ assertListObjectsResponse ( handler , "" , null , """
87+ <?xml version="1.0" encoding="UTF-8"?><ListBucketResult><Prefix></Prefix><IsTruncated>false</IsTruncated> \
6588 <Contents><Key>path/blob</Key><Size>50</Size></Contents>\
66- </ListBucketResult>""" ), handleRequest ( handler , "GET" , "/bucket/?prefix=" )) ;
89+ </ListBucketResult>""" );
6790
68- assertEquals ( new TestHttpResponse ( RestStatus . OK , """
69- <?xml version="1.0" encoding="UTF-8"?><ListBucketResult><Prefix>path/</Prefix>\
91+ assertListObjectsResponse ( handler , "path/" , null , """
92+ <?xml version="1.0" encoding="UTF-8"?><ListBucketResult><Prefix>path/</Prefix><IsTruncated>false</IsTruncated> \
7093 <Contents><Key>path/blob</Key><Size>50</Size></Contents>\
71- </ListBucketResult>""" ), handleRequest ( handler , "GET" , "/bucket/?prefix=path/" )) ;
94+ </ListBucketResult>""" );
7295
73- assertEquals (
74- new TestHttpResponse (RestStatus .OK , """
75- <?xml version="1.0" encoding="UTF-8"?><ListBucketResult><Prefix>path/other</Prefix></ListBucketResult>""" ),
76- handleRequest (handler , "GET" , "/bucket/?prefix=path/other" )
77- );
96+ assertListObjectsResponse (handler , "path/other" , null , """
97+ <?xml version="1.0" encoding="UTF-8"?><ListBucketResult><Prefix>path/other</Prefix><IsTruncated>false</IsTruncated>\
98+ </ListBucketResult>""" );
7899
79100 assertEquals (RestStatus .OK , handleRequest (handler , "PUT" , "/bucket/path/subpath1/blob" , randomAlphaOfLength (50 )).status ());
80101 assertEquals (RestStatus .OK , handleRequest (handler , "PUT" , "/bucket/path/subpath2/blob" , randomAlphaOfLength (50 )).status ());
81- assertEquals (new TestHttpResponse (RestStatus .OK , """
82- <?xml version="1.0" encoding="UTF-8"?><ListBucketResult><Prefix>path/</Prefix>\
83- <Delimiter>/</Delimiter><Contents><Key>path/blob</Key><Size>50</Size></Contents>\
102+ assertListObjectsResponse (handler , "path/" , "/" , """
103+ <?xml version="1.0" encoding="UTF-8"?><ListBucketResult>\
104+ <Prefix>path/</Prefix><Delimiter>/</Delimiter><IsTruncated>false</IsTruncated>\
105+ <Contents><Key>path/blob</Key><Size>50</Size></Contents>\
84106 <CommonPrefixes><Prefix>path/subpath1/</Prefix></CommonPrefixes>\
85107 <CommonPrefixes><Prefix>path/subpath2/</Prefix></CommonPrefixes>\
86- </ListBucketResult>""" ), handleRequest ( handler , "GET" , "/bucket/?delimiter=/&prefix=path/" )) ;
108+ </ListBucketResult>""" );
87109
88110 assertEquals (RestStatus .OK , handleRequest (handler , "DELETE" , "/bucket/path/blob" ).status ());
89111 assertEquals (RestStatus .NO_CONTENT , handleRequest (handler , "DELETE" , "/bucket/path/blob" ).status ());
90112
91- assertEquals ( new TestHttpResponse ( RestStatus . OK , """
92- <?xml version="1.0" encoding="UTF-8"?><ListBucketResult><Prefix></Prefix>\
113+ assertListObjectsResponse ( handler , "" , null , """
114+ <?xml version="1.0" encoding="UTF-8"?><ListBucketResult><Prefix></Prefix><IsTruncated>false</IsTruncated> \
93115 <Contents><Key>path/subpath1/blob</Key><Size>50</Size></Contents>\
94116 <Contents><Key>path/subpath2/blob</Key><Size>50</Size></Contents>\
95- </ListBucketResult>""" ), handleRequest ( handler , "GET" , "/bucket/?prefix=" )) ;
117+ </ListBucketResult>""" );
96118
97119 assertEquals (RestStatus .OK , handleRequest (handler , "DELETE" , "/bucket/path/subpath1/blob" ).status ());
98120 assertEquals (RestStatus .OK , handleRequest (handler , "DELETE" , "/bucket/path/subpath2/blob" ).status ());
99121
100- assertEquals (
101- new TestHttpResponse (RestStatus .OK , """
102- <?xml version="1.0" encoding="UTF-8"?><ListBucketResult><Prefix></Prefix></ListBucketResult>""" ),
103- handleRequest (handler , "GET" , "/bucket/?prefix=" )
104- );
122+ assertListObjectsResponse (handler , "" , null , """
123+ <?xml version="1.0" encoding="UTF-8"?><ListBucketResult><Prefix></Prefix><IsTruncated>false</IsTruncated>\
124+ </ListBucketResult>""" );
105125 }
106126
107127 public void testGetWithBytesRange () {
@@ -216,10 +236,10 @@ public void testSingleMultipartUpload() {
216236 </CompleteMultipartUpload>""" , part1Etag , part2Etag ))
217237 );
218238
219- assertEquals ( new TestHttpResponse ( RestStatus . OK , """
220- <?xml version="1.0" encoding="UTF-8"?><ListBucketResult><Prefix></Prefix>\
239+ assertListObjectsResponse ( handler , "" , null , """
240+ <?xml version="1.0" encoding="UTF-8"?><ListBucketResult><Prefix></Prefix><IsTruncated>false</IsTruncated> \
221241 <Contents><Key>path/blob</Key><Size>100</Size></Contents>\
222- </ListBucketResult>""" ), handleRequest ( handler , "GET" , "/bucket/?prefix=" )) ;
242+ </ListBucketResult>""" );
223243
224244 assertEquals (new TestHttpResponse (RestStatus .OK , part1 + part2 ), handleRequest (handler , "GET" , "/bucket/path/blob" ));
225245
0 commit comments