JCLOUDS-1631: fix AWSRequestAuthorizeSignatureV4 when prefix contains special chars
diff --git a/apis/s3/src/test/java/org/jclouds/s3/filters/RequestAuthorizeSignatureV4Test.java b/apis/s3/src/test/java/org/jclouds/s3/filters/RequestAuthorizeSignatureV4Test.java
index bbe019c..8057888 100644
--- a/apis/s3/src/test/java/org/jclouds/s3/filters/RequestAuthorizeSignatureV4Test.java
+++ b/apis/s3/src/test/java/org/jclouds/s3/filters/RequestAuthorizeSignatureV4Test.java
@@ -89,7 +89,7 @@
          + "SignedHeaders=host;x-amz-content-sha256;x-amz-date, "
          + "Signature=6cc5d0758e2599be7cb172fd57cefab2828201a2b4d372972a83dc304de93958";
 
-   private static final String BUCKET_NAME = "test-bucket";
+   protected static final String BUCKET_NAME = "test-bucket";
    private static final String OBJECT_NAME = "ExampleObject.txt";
 
    @ConfiguresHttpApi
@@ -116,11 +116,11 @@
             .buildInjector();
    }
 
-   public static RequestAuthorizeSignatureV4 filter(Credentials creds) {
+   public RequestAuthorizeSignatureV4 filter(Credentials creds) {
       return injector(creds).getInstance(RequestAuthorizeSignatureV4.class);
    }
 
-   Credentials temporaryCredentials = new Credentials.Builder()
+   protected Credentials temporaryCredentials = new Credentials.Builder()
          .identity(IDENTITY)
          .credential(CREDENTIAL)
          .build();
diff --git a/providers/aws-s3/src/main/java/org/jclouds/aws/s3/filters/AWSRequestAuthorizeSignatureV4.java b/providers/aws-s3/src/main/java/org/jclouds/aws/s3/filters/AWSRequestAuthorizeSignatureV4.java
index 1afa832..2491152 100644
--- a/providers/aws-s3/src/main/java/org/jclouds/aws/s3/filters/AWSRequestAuthorizeSignatureV4.java
+++ b/providers/aws-s3/src/main/java/org/jclouds/aws/s3/filters/AWSRequestAuthorizeSignatureV4.java
@@ -53,7 +53,8 @@
       * with expiration.
       */
 
-      Multimap<String, String> queryMap = queryParser().apply(request.getEndpoint().getQuery());
+      // Do not replace URI.getRawQuery() with URI.getQuery() see: JCLOUDS-1631
+      Multimap<String, String> queryMap = queryParser().apply(request.getEndpoint().getRawQuery());
       if (queryMap.containsKey(AMZ_SIGNATURE_PARAM) || queryMap.containsKey(TEMPORARY_SIGNATURE_PARAM)) {
          return request;
       }
diff --git a/providers/aws-s3/src/test/java/org/jclouds/aws/s3/filter/AwsRequestAuthorizeSignatureV4Test.java b/providers/aws-s3/src/test/java/org/jclouds/aws/s3/filter/AwsRequestAuthorizeSignatureV4Test.java
new file mode 100644
index 0000000..3afb640
--- /dev/null
+++ b/providers/aws-s3/src/test/java/org/jclouds/aws/s3/filter/AwsRequestAuthorizeSignatureV4Test.java
@@ -0,0 +1,53 @@
+package org.jclouds.aws.s3.filter;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.net.HttpHeaders;
+import org.jclouds.aws.s3.filters.AWSRequestAuthorizeSignatureV4;
+import org.jclouds.domain.Credentials;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.reflect.Invocation;
+import org.jclouds.rest.internal.GeneratedHttpRequest;
+import org.jclouds.s3.S3Client;
+import org.jclouds.s3.filters.RequestAuthorizeSignatureV4;
+import org.jclouds.s3.filters.RequestAuthorizeSignatureV4Test;
+import org.jclouds.s3.options.ListBucketOptions;
+import org.testng.annotations.Test;
+
+import static org.jclouds.reflect.Reflection2.method;
+import static org.testng.Assert.assertEquals;
+
+/**
+ * Tests behavior of {@code AWSRequestAuthorizeSignatureV4}
+ */
+// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
+@Test(groups = "unit", testName = "AwsRequestAuthorizeSignatureV4Test")
+public class AwsRequestAuthorizeSignatureV4Test extends RequestAuthorizeSignatureV4Test {
+
+    private static final String LIST_BUCKET_AUTHORIZATION_HEADER_RESULT = "AWS4-HMAC-SHA256 Credential=AKIAPAEBI3QI4EXAMPLE/20150203/cn-north-1/s3/aws4_request," +
+            " SignedHeaders=host;x-amz-content-sha256;x-amz-date, Signature=ec72ac5f67bf86e3b95d122f690a2898224f28328d39131c48221a5dcf0c2cee";
+
+    @Override
+    public RequestAuthorizeSignatureV4 filter(Credentials creds) {
+        return injector(creds).getInstance(AWSRequestAuthorizeSignatureV4.class);
+    }
+
+
+    // JCLOUDS-1631
+    @Test
+    void testListBucketWithSpecialChars() {
+        Invocation invocation = Invocation.create(method(S3Client.class, "listBucket", String.class,
+                        ListBucketOptions[].class),
+                // Simulating ListBucketOptions.Builder.withPrefix("Folder (`~!@#$%^&*-_+[]'|<>.?) Name/") with manual endpoint:
+                ImmutableList.<Object>of(RequestAuthorizeSignatureV4Test.BUCKET_NAME, new ListBucketOptions[0]));
+
+        HttpRequest getObject = GeneratedHttpRequest.builder().method("GET")
+                .invocation(invocation)
+                .endpoint("https://" + BUCKET_NAME + ".s3.cn-north-1.amazonaws.com.cn/?delimiter=/&prefix=Folder%20%28%60%7E%21%40%23%24%25%5E%26%2A-_%2B%5B%5D%27%7C%3C%3E.%3F%29%20Name/")
+                .addHeader(HttpHeaders.HOST, BUCKET_NAME + ".s3.cn-north-1.amazonaws.com.cn")
+                .build();
+
+
+        HttpRequest filtered = filter(temporaryCredentials).filter(getObject);
+        assertEquals(filtered.getFirstHeaderOrNull("Authorization"), LIST_BUCKET_AUTHORIZATION_HEADER_RESULT);
+    }
+}