Skip to content

Commit 5017333

Browse files
committed
Percent encoding query parameters separated from url encoding
1 parent 129ee46 commit 5017333

File tree

4 files changed

+53
-1
lines changed

4 files changed

+53
-1
lines changed

ds3-sdk-integration/src/test/java/com/spectralogic/ds3client/integration/Smoke_Test.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,27 @@ public void getObjectsWithPagination() throws IOException, URISyntaxException {
177177

178178
}
179179

180+
@Test
181+
public void getBucketWithAmpersandFolderName() throws IOException, URISyntaxException {
182+
final String bucketName = "test_ampersand_folder";
183+
final String folderName = "test&folder/";
184+
try {
185+
HELPERS.ensureBucketExists(bucketName, envDataPolicyId);
186+
loadBookTestDataWithPrefix(client, bucketName, folderName);
187+
188+
final HeadObjectResponse response = client.headObject(new HeadObjectRequest(
189+
bucketName, folderName + "beowulf.txt"));
190+
assertThat(response.getStatus(),
191+
is(HeadObjectResponse.Status.EXISTS));
192+
193+
final GetBucketResponse getBucket = client.getBucket(new GetBucketRequest(bucketName));
194+
assertThat(getBucket.getListBucketResult(), is(notNullValue()));
195+
assertThat(getBucket.getListBucketResult().getObjects().size(), is(4));
196+
} finally {
197+
deleteAllContents(client, bucketName);
198+
}
199+
}
200+
180201
private static boolean s3ObjectExists(final List<S3Object> objects, final String fileName) {
181202
for (final S3Object obj : objects) {
182203
if (obj.getName().equals(fileName)) {

ds3-sdk/src/main/java/com/spectralogic/ds3client/commands/interfaces/AbstractRequest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ protected final <T> void updateQueryParam(final String name, final T param) {
7575
this.queryParams.remove(name);
7676
}
7777
else {
78-
this.queryParams.put(name, SafeStringManipulation.safeUrlEscape(param));
78+
this.queryParams.put(name, SafeStringManipulation.safeQueryParamEscape(param));
7979
}
8080
}
8181
}

ds3-sdk/src/main/java/com/spectralogic/ds3client/utils/SafeStringManipulation.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,34 @@ public final class SafeStringManipulation {
3232
"!$'()*,&=" + // removed ; (so it will be escaped) and added / (so it will not)
3333
"@:/"; // Their urlFragmentEscaper uses URL_PATH_OTHER_SAFE_CHARS_LACKING_PLUS + "+/?"+
3434

35+
/**
36+
* Specified as query safe characters in spec https://tools.ietf.org/html/rfc3986#section-3.4
37+
* with the following exceptions:
38+
* Encoding: "&", ":", "+", "=" as they have special meaning
39+
* Not Encoding: "/"
40+
*/
41+
private static final String DS3_QUERY_PARAM_SAFE_CHARS = "-._~!$'()*,;@/";
42+
3543
private static final Escaper DS3_URL_FRAGMENT_ESCAPER =
3644
new PercentEscaper(DS3_URL_PATH_FRAGMENT_SAFE_CHARS, false);
3745

46+
private static final Escaper DS3_QUERY_PARAM_ESCAPER =
47+
new PercentEscaper(DS3_QUERY_PARAM_SAFE_CHARS, false);
48+
3849
private SafeStringManipulation() {
3950
//pass
4051
}
4152

53+
/**
54+
* Percent encodes user-provided query parameter values.
55+
*/
56+
public static <T> String safeQueryParamEscape(final T obj) {
57+
if (obj == null) {
58+
return null;
59+
}
60+
return DS3_QUERY_PARAM_ESCAPER.escape(safeToString(obj));
61+
}
62+
4263
public static <T> String safeUrlEscape(final T obj) {
4364
if (obj == null) {
4465
return null;
@@ -58,6 +79,7 @@ public static <T> String safeToString(final T obj) {
5879
}
5980
return obj.toString();
6081
}
82+
6183
public static Escaper getDs3Escaper() {
6284
// escaped characters in DS3 path and query parameter value segments
6385
return DS3_URL_FRAGMENT_ESCAPER;

ds3-sdk/src/test/java/com/spectralogic/ds3client/utils/SafeString_Manipulation_Test.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,4 +108,13 @@ public void safeUrlEscape_Test() {
108108
assertThat(SafeStringManipulation.safeUrlEscape("one2three+four"), is("one2three%2Bfour"));
109109
assertThat(SafeStringManipulation.safeUrlEscape("one two three"), is("one%20two%20three"));
110110
}
111+
112+
@Test
113+
public void safeQueryParamEscape_Test() {
114+
assertThat(SafeStringManipulation.safeQueryParamEscape(null), is(nullValue()));
115+
assertThat(SafeStringManipulation.safeQueryParamEscape(""), is(""));
116+
assertThat(SafeStringManipulation.safeQueryParamEscape("one2three+four"), is("one2three%2Bfour"));
117+
assertThat(SafeStringManipulation.safeQueryParamEscape("one two three"), is("one%20two%20three"));
118+
assertThat(SafeStringManipulation.safeQueryParamEscape("one&two&three"), is("one%26two%26three"));
119+
}
111120
}

0 commit comments

Comments
 (0)