Skip to content

Commit 89d919e

Browse files
committed
Fix URI encoding issues related to plus marks
The encoding of URIs for generating AWS signatures and the encoding of URIs to pass on as HTTP headers to S3 were not doing the same operations. This commit brings them in harmony and adds additional integration test cases. Signed-off-by: Elijah Zupancic <[email protected]>
1 parent 0e6e12b commit 89d919e

File tree

2 files changed

+43
-17
lines changed

2 files changed

+43
-17
lines changed

common/etc/nginx/include/s3gateway.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -354,13 +354,14 @@ function s3uri(r) {
354354
if (queryParams.length > 0) {
355355
path = basePath + '?' + queryParams;
356356
} else {
357-
path = basePath + uriPath;
357+
path = _escapeURIPath(basePath + uriPath);
358358
}
359359
} else {
360+
// This is a path that will resolve to an index page
360361
if (provide_index_page && _isDirectory(uriPath) ) {
361362
uriPath += INDEX_PAGE;
362363
}
363-
path = basePath + uriPath;
364+
path = _escapeURIPath(basePath + uriPath);
364365
}
365366

366367
_debug_log(r, 'S3 Request URI: ' + r.method + ' ' + path);
@@ -392,7 +393,7 @@ function _s3DirQueryParams(uriPath, method) {
392393
let decodedUriPath = decodeURIComponent(uriPath);
393394
let without_leading_slash = decodedUriPath.charAt(0) === '/' ?
394395
decodedUriPath.substring(1, decodedUriPath.length) : decodedUriPath;
395-
path += '&prefix=' + encodeURIComponent(without_leading_slash);
396+
path += '&prefix=' + _encodeURIComponent(without_leading_slash);
396397
}
397398

398399
return path;
@@ -569,7 +570,7 @@ function _buildSignatureV4(r, amzDatetime, eightDigitDate, creds, bucket, region
569570
uri = '/';
570571
}
571572
} else {
572-
uri = _escapeURIPath(s3uri(r));
573+
uri = s3uri(r);
573574
}
574575

575576
var canonicalRequest = _buildCanonicalRequest(method, uri, queryParams, host, amzDatetime, creds.sessionToken);

test/integration/test_api.sh

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -156,20 +156,38 @@ assertHttpRequestEquals "HEAD" "b/e.txt" "200"
156156
assertHttpRequestEquals "HEAD" "b//e.txt" "200"
157157
assertHttpRequestEquals "HEAD" "a/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.txt" "200"
158158

159+
# We try to request URLs that are properly encoded as well as URLs that
160+
# are not properly encoded to understand what works and what does not.
161+
159162
# Weird filenames
163+
assertHttpRequestEquals "HEAD" "b/c/%3D" "200"
160164
assertHttpRequestEquals "HEAD" "b/c/=" "200"
165+
166+
assertHttpRequestEquals "HEAD" "b/c/%40" "200"
161167
assertHttpRequestEquals "HEAD" "b/c/@" "200"
168+
169+
assertHttpRequestEquals "HEAD" "b/c/%27%281%29.txt" "200"
162170
assertHttpRequestEquals "HEAD" "b/c/'(1).txt" "200"
171+
172+
# These URLs do not work unencoded
173+
assertHttpRequestEquals "HEAD" 'a/plus%2Bplus.txt' "200"
163174
assertHttpRequestEquals "HEAD" "%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%8B/%25bad%25file%25name%25" "200"
164-
assertHttpRequestEquals "HEAD" 'a/plus+plus.txt' "200"
175+
176+
# Testing these files does not currently work on Windows
165177
if [ ${is_windows} == "0" ]; then
178+
assertHttpRequestEquals "HEAD" "a/c/%E3%81%82" "200"
166179
assertHttpRequestEquals "HEAD" "a/c/あ" "200"
180+
181+
assertHttpRequestEquals "HEAD" "b/%E3%82%AF%E3%82%BA%E7%AE%B1/%E3%82%B4%E3%83%9F.txt" "200"
167182
assertHttpRequestEquals "HEAD" "b/クズ箱/ゴミ.txt" "200"
183+
184+
assertHttpRequestEquals "HEAD" "%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%8B/system.txt" "200"
168185
assertHttpRequestEquals "HEAD" "системы/system.txt" "200"
186+
187+
assertHttpRequestEquals "HEAD" "b/%E3%83%96%E3%83%84%E3%83%96%E3%83%84.txt" "200"
169188
assertHttpRequestEquals "HEAD" "b/ブツブツ.txt" "200"
170-
# The following two objects do not get encoded correctly by curl when requested using their
171-
# unicode names. The are provided as URL encoded as below. This is the same type of encoding
172-
# expected by S3 and divergence from it will not work with nginx either.
189+
190+
# These URLs do not work unencoded
173191
assertHttpRequestEquals "HEAD" 'a/%25%40%21%2A%28%29%3D%24%23%5E%26%7C.txt' "200"
174192
assertHttpRequestEquals "HEAD" 'a/%E3%81%93%E3%82%8C%E3%81%AF%E3%80%80This%20is%20ASCII%20%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%8B%20%20%D7%97%D7%9F%20.txt' "200"
175193
fi
@@ -229,20 +247,25 @@ assertHttpRequestEquals "GET" "a.txt" "data/bucket-1/a.txt"
229247
assertHttpRequestEquals "GET" "a/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.txt" "data/bucket-1/a/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.txt"
230248
assertHttpRequestEquals "GET" "a.txt?some=param&that=should&be=stripped#aaah" "data/bucket-1/a.txt"
231249
assertHttpRequestEquals "GET" "b/c/d.txt" "data/bucket-1/b/c/d.txt"
250+
251+
assertHttpRequestEquals "GET" "b/c/%3D" "data/bucket-1/b/c/="
232252
assertHttpRequestEquals "GET" "b/c/=" "data/bucket-1/b/c/="
253+
254+
assertHttpRequestEquals "GET" "b/c/%27%281%29.txt" "data/bucket-1/b/c/'(1).txt"
233255
assertHttpRequestEquals "GET" "b/c/'(1).txt" "data/bucket-1/b/c/'(1).txt"
256+
234257
assertHttpRequestEquals "GET" "b/e.txt" "data/bucket-1/b/e.txt"
235-
assertHttpRequestEquals "GET" "%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%8B/%25bad%25file%25name%25" "data/bucket-1/системы/%bad%file%name%"
236-
assertHttpRequestEquals "GET" 'a/plus+plus.txt' "data/bucket-1/a/plus+plus.txt"
237258

259+
# These URLs do not work unencoded
260+
assertHttpRequestEquals "GET" 'a/plus%2Bplus.txt' "data/bucket-1/a/plus+plus.txt"
261+
262+
# Testing these files does not currently work on Windows
238263
if [ ${is_windows} == "0" ]; then
239-
assertHttpRequestEquals "GET" "a/c/あ" "data/bucket-1/a/c/あ"
240-
assertHttpRequestEquals "GET" "b/ブツブツ.txt" "data/bucket-1/b/ブツブツ.txt"
241-
assertHttpRequestEquals "GET" "b/クズ箱/ゴミ.txt" "data/bucket-1/b/クズ箱/ゴミ.txt"
242-
assertHttpRequestEquals "GET" "системы/system.txt" "data/bucket-1/системы/system.txt"
243-
# The following two objects do not get encoded correctly by curl when requested using their
244-
# unicode names. The are provided as URL encoded as below. This is the same type of encoding
245-
# expected by S3 and divergence from it will not work with nginx either.
264+
assertHttpRequestEquals "GET" "a/c/%E3%81%82" "data/bucket-1/a/c/あ"
265+
assertHttpRequestEquals "GET" "b/%E3%83%96%E3%83%84%E3%83%96%E3%83%84.txt" "data/bucket-1/b/ブツブツ.txt"
266+
assertHttpRequestEquals "GET" "b/%E3%82%AF%E3%82%BA%E7%AE%B1/%E3%82%B4%E3%83%9F.txt" "data/bucket-1/b/クズ箱/ゴミ.txt"
267+
assertHttpRequestEquals "GET" "%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%8B/system.txt" "data/bucket-1/системы/system.txt"
268+
assertHttpRequestEquals "GET" "%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%8B/%25bad%25file%25name%25" "data/bucket-1/системы/%bad%file%name%"
246269
assertHttpRequestEquals "GET" 'a/%25%40%21%2A%28%29%3D%24%23%5E%26%7C.txt' 'data/bucket-1/a/%@!*()=$#^&|.txt'
247270
assertHttpRequestEquals "GET" 'a/%E3%81%93%E3%82%8C%E3%81%AF%E3%80%80This%20is%20ASCII%20%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%8B%20%20%D7%97%D7%9F%20.txt' "data/bucket-1/a/これは This is ASCII системы חן .txt"
248271
fi
@@ -260,7 +283,9 @@ if [ "${allow_directory_list}" == "1" ]; then
260283
assertHttpRequestEquals "GET" "/" "200"
261284
assertHttpRequestEquals "GET" "b/" "200"
262285
assertHttpRequestEquals "GET" "/b/c/" "200"
286+
assertHttpRequestEquals "GET" "b/%E3%82%AF%E3%82%BA%E7%AE%B1/" "200"
263287
assertHttpRequestEquals "GET" "b/クズ箱/" "200"
288+
assertHttpRequestEquals "GET" "%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%8B/" "200"
264289
assertHttpRequestEquals "GET" "системы/" "200"
265290
if [ "$append_slash" == "1" ]; then
266291
assertHttpRequestEquals "GET" "b" "302"

0 commit comments

Comments
 (0)