1
-
2
- const Minio = require ( "minio" ) ;
3
1
const request = require ( "supertest" ) ;
2
+ const container = require ( "./support/container.js" ) ;
3
+ const s3Mock = require ( "./support/s3Mock.js" ) ;
4
+
5
+ const TEST_NAME = "base" ;
4
6
5
7
const FILES = {
6
8
"a.txt" : {
@@ -18,56 +20,123 @@ const FILES = {
18
20
"Throw it away!"
19
21
"With not one thing, what there is to throw away?"
20
22
"Then carry it off!"
23
+ ` ,
24
+ } ,
25
+ "b/c/=" : {
26
+ content : `
27
+ This is an awful filename.
28
+ このフィール名を選ばないでください
29
+ `
30
+ } ,
31
+ "b/c/@" : {
32
+ content : ""
33
+ } ,
34
+ "b/c/'(1).txt" : {
35
+ content : "In the midst of movement and chaos, keep stillness inside of you."
36
+ } ,
37
+ "a/plus+plus.txt" : {
38
+ content : `
39
+ 代悲白頭翁 Lament for the White-Haired Old Man
40
+ 洛陽城東桃李花 In the east of Luoyang City, Peach blossoms abound
41
+ 飛來飛去落誰家 Their petals float around, coming and going, to whose house will they fall?
42
+ 洛陽女児惜顔色 Girls in Luoyang cherish their complexion
43
+ 行逢落花長歎息 They breathe a deep sigh upon seeing the petals fall
44
+ 今年花落顔色改 This year the petals fall and their complexion changes
45
+ 明年花開復誰在 Who will be there when the flowers bloom next year?
46
+ 已見松柏摧為薪 I've seen the pines and cypresses destroyed and turned into firewood
47
+ 更聞桑田変成海 I hear that the mulberry fields have fallen into the sea
48
+ 古人無復洛城東 The people of old never came back to the east of Luoyang City
49
+ 今人還對落花風 The people of today likewise face the falling flowers in the wind
50
+ 年年歳歳花相似 Year after year, flowers look alike
51
+ 歳歳年年人不同 Year after year, the people are not the same
52
+ 寄言全盛紅顔子 I want you to get this message, my child, you are in your prime, with a rosy complexion
53
+ 應憐半死白頭翁 Take pity on the half-dead white-haired old man
54
+ 此翁白頭真可憐 You really must take pity on this white-haired old man
55
+ 伊昔紅顔美少年 For once upon a time, I used to be a red-faced handsome young man
56
+ 公子王孫芳樹下 A child of noble birth under a fragrant tree
57
+ 清歌妙舞落花前 Singing and dancing in front of the falling petals
58
+ 光禄池臺開錦繍 At the platform before the mirror pond, beautiful autumn leaves opening all around
59
+ 将軍楼閣畫神仙 The general’s pavilion is painted with gods and goddesses
60
+ 一朝臥病無相識 Once I was sick and no one knew me
61
+ 三春行楽在誰邉 Who will be at the shore for the spring outing?
62
+ 宛轉蛾眉能幾時 For how long will the moths gracefully turn about?
63
+ 須臾鶴髪亂如絲 The crane’s feathers are like tangled threads for just a moment
64
+ 但看古来歌舞地 Yet, look at the ancient places of song and dance
65
+ 惟有黄昏鳥雀悲 Only in twilight, do the birds lament
66
+ `
67
+ } ,
68
+ "системы/%bad%file%name%" : {
69
+ content : `
70
+ Filename encoding issues are hard.
71
+
21
72
`
22
73
}
23
74
} ;
24
75
25
76
const BUCKET_NAME = "bucket-2" ;
26
- const GATEWAY_HOST = "localhost" ;
27
- const GATEWAY_PORT = "8989" ;
28
- const GATEWAY_BASE_URL = `http://${ GATEWAY_HOST } :${ GATEWAY_PORT } ` ;
29
-
30
- beforeAll ( async ( ) => {
31
- const minioClient = new Minio . Client ( {
32
- endPoint : "localhost" ,
33
- port : 9090 ,
34
- useSSL : false ,
35
- accessKey : 'AKIAIOSFODNN7EXAMPLE' ,
36
- secretKey : 'wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY' ,
37
- } ) ;
38
77
39
- await ensureBucketWithObjects ( minioClient , BUCKET_NAME , FILES ) ;
78
+ // Config for the running container per test
79
+
80
+ const CONFIG = container . Config ( {
81
+ env : {
82
+ S3_BUCKET_NAME : BUCKET_NAME ,
83
+ AWS_ACCESS_KEY_ID : "AKIAIOSFODNN7EXAMPLE" ,
84
+ AWS_SECRET_ACCESS_KEY : "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" ,
85
+ S3_SERVER : "minio" ,
86
+ S3_SERVER_PORT : "9000" ,
87
+ S3_SERVER_PROTO : "http" ,
88
+ S3_REGION : "us-east-1" ,
89
+ DEBUG : "true" ,
90
+ S3_STYLE : "virtual" ,
91
+ ALLOW_DIRECTORY_LIST : "false" ,
92
+ PROVIDE_INDEX_PAGE : "" ,
93
+ APPEND_SLASH_FOR_POSSIBLE_DIRECTORY : "" ,
94
+ STRIP_LEADING_DIRECTORY_PATH : "" ,
95
+ PREFIX_LEADING_DIRECTORY_PATH : "" ,
96
+ AWS_SIGS_VERSION : "4" ,
97
+ STATIC_SITE_HOSTING : "" ,
98
+ PROXY_CACHE_MAX_SIZE : "10g" ,
99
+ PROXY_CACHE_INACTIVE : "60m" ,
100
+ PROXY_CACHE_VALID_OK : "1h" ,
101
+ PROXY_CACHE_VALID_NOTFOUND : "1m" ,
102
+ PROXY_CACHE_VALID_FORBIDDEN : "30s" ,
103
+ } ,
104
+ dockerfileName : "Dockerfile.oss" ,
105
+ testName : TEST_NAME ,
106
+ networkName : "s3-gateway-test" ,
40
107
} ) ;
41
108
42
- async function ensureBucketWithObjects ( s3Client , bucketName , objects ) {
43
- if ( await s3Client . bucketExists ( BUCKET_NAME ) ) {
44
- await s3Client . removeObjects ( BUCKET_NAME , Object . keys ( FILES ) ) ;
45
- await s3Client . removeBucket ( BUCKET_NAME ) ;
109
+ const minioClient = s3Mock . Client ( "localhost" , 9090 , "AKIAIOSFODNN7EXAMPLE" , "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" ) ;
110
+
111
+ beforeAll ( async ( ) => {
112
+ try {
113
+ await container . stop ( CONFIG ) ;
114
+ } catch ( e ) {
115
+ console . log ( "no container to stop" ) ;
46
116
}
47
117
48
- await s3Client . makeBucket ( BUCKET_NAME , 'us-east-1' ) ;
118
+ await s3Mock . ensureBucketWithObjects ( minioClient , BUCKET_NAME , FILES ) ;
119
+ await container . build ( CONFIG ) ;
120
+ await container . start ( CONFIG ) ;
121
+ } ) ;
122
+
123
+ afterAll ( async ( ) => {
124
+ await container . stop ( CONFIG ) ;
125
+ await s3Mock . deleteBucket ( minioClient , BUCKET_NAME ) ;
126
+ } ) ;
49
127
50
- for ( const path of Object . keys ( FILES ) ) {
51
- console . log ( `now loading file ${ path } ` ) ;
52
- let buf = Buffer . from ( FILES [ path ] . content , "utf-8" ) ;
53
- let res = await s3Client . putObject ( BUCKET_NAME , path , buf ) ;
54
- console . log ( `Uploaded file: ${ JSON . stringify ( res ) } ` ) ;
55
- }
56
- }
57
128
58
129
describe ( "Ordinary filenames" , ( ) => {
59
130
test ( "simple url" , async ( ) => {
60
131
const objectPath = "a.txt" ;
61
- const res = await request ( GATEWAY_BASE_URL )
62
- . get ( `/${ objectPath } ` ) ;
63
-
132
+ const res = await request ( CONFIG . testContainer . baseUrl ) . get ( `/${ objectPath } ` ) ;
64
133
expect ( res . statusCode ) . toBe ( 200 ) ;
65
134
expect ( res . text ) . toBe ( FILES [ objectPath ] . content ) ;
66
135
} ) ;
67
136
68
137
test ( "many params that should be stripped" , async ( ) => {
69
138
const objectPath = "a.txt" ;
70
- const res = await request ( GATEWAY_BASE_URL )
139
+ const res = await request ( CONFIG . testContainer . baseUrl )
71
140
. get ( "/a.txt?some=param&that=should&be=stripped#aaah" )
72
141
. set ( "accept" , "binary/octet-stream" ) ;
73
142
@@ -77,27 +146,28 @@ describe("Ordinary filenames", () => {
77
146
78
147
test ( "with a more complex path" , async ( ) => {
79
148
const objectPath = "b/c/d.txt" ;
80
- const res = await request ( GATEWAY_BASE_URL )
149
+ const res = await request ( CONFIG . testContainer . baseUrl )
81
150
. get ( "/b/c/d.txt" )
82
151
. set ( "accept" , "binary/octet-stream" ) ;
83
152
84
153
expect ( res . statusCode ) . toBe ( 200 ) ;
85
154
expect ( res . text ) . toBe ( FILES [ objectPath ] . content ) ;
86
155
} ) ;
87
156
88
- test ( "with a more complex path" , async ( ) => {
157
+ test . skip ( "with dot segments in the path" , async ( ) => {
89
158
const objectPath = "b/e.txt" ;
90
- const res = await request ( GATEWAY_BASE_URL )
159
+ const res = await request ( CONFIG . testContainer . baseUrl )
91
160
. get ( "/b/c/../e.txt" )
92
161
. set ( "accept" , "binary/octet-stream" ) ;
93
162
163
+ const reqData = JSON . parse ( JSON . stringify ( res ) ) . req ;
94
164
expect ( res . statusCode ) . toBe ( 200 ) ;
95
165
expect ( res . text ) . toBe ( FILES [ objectPath ] . content ) ;
96
166
} ) ;
97
167
98
168
test ( "another simple path" , async ( ) => {
99
169
const objectPath = "b/e.txt" ;
100
- const res = await request ( GATEWAY_BASE_URL )
170
+ const res = await request ( CONFIG . testContainer . baseUrl )
101
171
. get ( "/b/e.txt" )
102
172
. set ( "accept" , "binary/octet-stream" ) ;
103
173
@@ -107,7 +177,7 @@ describe("Ordinary filenames", () => {
107
177
108
178
test ( "too many forward slashes" , async ( ) => {
109
179
const objectPath = "b/e.txt" ;
110
- const res = await request ( GATEWAY_BASE_URL )
180
+ const res = await request ( CONFIG . testContainer . baseUrl )
111
181
. get ( "/b//e.txt" )
112
182
. set ( "accept" , "binary/octet-stream" ) ;
113
183
@@ -116,9 +186,12 @@ describe("Ordinary filenames", () => {
116
186
} ) ;
117
187
118
188
test ( "very long file name" , async ( ) => {
119
- const objectPath = "a/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.txt" ;
120
- const res = await request ( GATEWAY_BASE_URL )
121
- . get ( "/a/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.txt" )
189
+ const objectPath =
190
+ "a/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.txt" ;
191
+ const res = await request ( CONFIG . testContainer . baseUrl )
192
+ . get (
193
+ "/a/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.txt" ,
194
+ )
122
195
. set ( "accept" , "binary/octet-stream" ) ;
123
196
124
197
expect ( res . statusCode ) . toBe ( 200 ) ;
@@ -127,23 +200,53 @@ describe("Ordinary filenames", () => {
127
200
} ) ;
128
201
129
202
describe ( "strange file names and encodings" , ( ) => {
203
+ test ( "URI encoded equal sign as file name" , async ( ) => {
204
+ const objectPath = "b/c/=" ;
205
+ const res = await request ( CONFIG . testContainer . baseUrl )
206
+ . get ( "/b/c/%3D" )
207
+ . set ( "accept" , "binary/octet-stream" ) ;
208
+
209
+ expect ( res . statusCode ) . toBe ( 200 ) ;
210
+ expect ( res . text ) . toBe ( FILES [ objectPath ] . content ) ;
211
+ } ) ;
130
212
131
- } )
213
+ test ( "URI encoded @ symbol as file name" , async ( ) => {
214
+ const objectPath = "b/c/@" ;
215
+ const res = await request ( CONFIG . testContainer . baseUrl )
216
+ . get ( "/b/c/%40" )
217
+ . set ( "accept" , "binary/octet-stream" ) ;
218
+
219
+ expect ( res . statusCode ) . toBe ( 200 ) ;
220
+ expect ( res . text ) . toBe ( FILES [ objectPath ] . content ) ;
221
+ } ) ;
132
222
133
- // # We try to request URLs that are properly encoded as well as URLs that
134
- // # are not properly encoded to understand what works and what does not.
223
+ test ( "URI with encoded punctuation in file name" , async ( ) => {
224
+ const objectPath = "b/c/'(1).txt" ;
225
+ const res = await request ( CONFIG . testContainer . baseUrl )
226
+ . get ( "/b/c/%27%281%29.txt" )
227
+ . set ( "accept" , "binary/octet-stream" ) ;
135
228
136
- // # Weird filenames
137
- // assertHttpRequestEquals "HEAD" "b/c/%3D" "200"
138
- // assertHttpRequestEquals "HEAD" "b/c/=" "200"
229
+ expect ( res . statusCode ) . toBe ( 200 ) ;
230
+ expect ( res . text ) . toBe ( FILES [ objectPath ] . content ) ;
231
+ } ) ;
139
232
140
- // assertHttpRequestEquals "HEAD" "b/c/%40" "200"
141
- // assertHttpRequestEquals "HEAD" "b/c/@" "200"
233
+ test ( "URI with encoded plus in file name" , async ( ) => {
234
+ const objectPath = "a/plus+plus.txt" ;
235
+ const res = await request ( CONFIG . testContainer . baseUrl )
236
+ . get ( "/a/plus%2Bplus.txt" )
237
+ . set ( "accept" , "binary/octet-stream" ) ;
142
238
143
- // assertHttpRequestEquals "HEAD" "b/c/%27%281%29.txt" "200"
144
- // assertHttpRequestEquals "HEAD" "b/c/'(1).txt" "200"
239
+ expect ( res . statusCode ) . toBe ( 200 ) ;
240
+ expect ( res . text ) . toBe ( FILES [ objectPath ] . content ) ;
241
+ } ) ;
145
242
146
- // # These URLs do not work unencoded
147
- // assertHttpRequestEquals "HEAD" 'a/plus%2Bplus.txt' "200"
148
- // assertHttpRequestEquals "HEAD" "%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%8B/%25bad%25file%25name%25" "200"
243
+ test ( "URI with cyrillic script and punctuation in file name" , async ( ) => {
244
+ const objectPath = "системы/%bad%file%name%" ;
245
+ const res = await request ( CONFIG . testContainer . baseUrl )
246
+ . get ( "/%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%8B/%25bad%25file%25name%25" )
247
+ . set ( "accept" , "binary/octet-stream" ) ;
149
248
249
+ expect ( res . statusCode ) . toBe ( 200 ) ;
250
+ expect ( res . text ) . toBe ( FILES [ objectPath ] . content ) ;
251
+ } ) ;
252
+ } ) ;
0 commit comments