diff --git a/src/main/java/org/scribe/utils/URLUtils.java b/src/main/java/org/scribe/utils/URLUtils.java index 30abc59..ffd6600 100644 --- a/src/main/java/org/scribe/utils/URLUtils.java +++ b/src/main/java/org/scribe/utils/URLUtils.java @@ -31,7 +31,7 @@ public class URLUtils } /** - * Turns a map into a form-url-encoded string (key=value&key2=value2) + * Turns a map into a form-urlencoded string * * @param map any map * @return form-url-encoded string @@ -47,32 +47,43 @@ public class URLUtils StringBuffer encodedString = new StringBuffer(map.size() * 20); for (String key : map.keySet()) { - if(encodedString.length() > 0) + encodedString.append(PARAM_SEPARATOR).append(formURLEncode(key)); + if(map.get(key) != null) { - encodedString.append(PARAM_SEPARATOR); + encodedString.append(PAIR_SEPARATOR).append(formURLEncode(map.get(key))); } - encodedString.append(percentEncode(key)).append(PAIR_SEPARATOR).append(percentEncode(map.get(key))); } - return encodedString.toString(); + return encodedString.toString().substring(1); } /** * Percent encodes a string * - * @param plain + * @param string plain string * @return percent encoded string */ public static String percentEncode(String string) + { + String encoded = formURLEncode(string); + for (EncodingRule rule : ENCODING_RULES) + { + encoded = rule.apply(encoded); + } + return encoded; + } + + /** + * Translates a string into application/x-www-form-urlencoded format + * + * @param plain + * @return form-urlencoded string + */ + public static String formURLEncode(String string) { Preconditions.checkNotNull(string, "Cannot encode null string"); try { - String encoded = URLEncoder.encode(string, UTF_8); - for(EncodingRule rule : ENCODING_RULES) - { - encoded = rule.apply(encoded); - } - return encoded; + return URLEncoder.encode(string, UTF_8); } catch (UnsupportedEncodingException uee) { @@ -81,12 +92,12 @@ public class URLUtils } /** - * Percent decodes a string + * Decodes a application/x-www-form-urlencoded string * - * @param string percent encoded string + * @param string form-urlencoded string * @return plain string */ - public static String percentDecode(String string) + public static String formURLDecode(String string) { Preconditions.checkNotNull(string, "Cannot decode null string"); try @@ -110,12 +121,27 @@ public class URLUtils { Preconditions.checkNotNull(url, "Cannot append to null URL"); String queryString = URLUtils.formURLEncodeMap(params); - if (queryString.length() == 0) return url; + if (queryString.equals(EMPTY_STRING)) + { + return url; + } + else + { + url += url.indexOf(QUERY_STRING_SEPARATOR) != -1 ? PARAM_SEPARATOR : QUERY_STRING_SEPARATOR; + url += queryString; + return url; + } + } - // Check if there are parameters in the url already and use '&' instead of '?' - url += url.indexOf(QUERY_STRING_SEPARATOR) != -1 ? PARAM_SEPARATOR : QUERY_STRING_SEPARATOR; - url += queryString; - return url; + public static String concatSortedPercentEncodedParams(Map params) + { + StringBuilder result = new StringBuilder(); + for (String key : params.keySet()) + { + result.append(key).append(PAIR_SEPARATOR); + result.append(params.get(key)).append(PARAM_SEPARATOR); + } + return result.toString().substring(0, result.length() - 1); } private static final class EncodingRule diff --git a/src/test/java/org/scribe/utils/URLUtilsTest.java b/src/test/java/org/scribe/utils/URLUtilsTest.java index 8a8be2a..522cdc4 100644 --- a/src/test/java/org/scribe/utils/URLUtilsTest.java +++ b/src/test/java/org/scribe/utils/URLUtilsTest.java @@ -16,7 +16,7 @@ public class URLUtilsTest params.put("key with spaces", "value with spaces"); params.put("&symbols!", "#!"); - String expected = "key=value&key%20with%20spaces=value%20with%20spaces&%26symbols%21=%23%21"; + String expected = "key=value&key+with+spaces=value+with+spaces&%26symbols%21=%23%21"; assertEquals(expected, URLUtils.formURLEncodeMap(params)); } @@ -28,6 +28,17 @@ public class URLUtilsTest assertEquals(expected, URLUtils.formURLEncodeMap(params)); } + @Test + public void shouldFormURLEncodeMapWithMissingValues() + { + Map params = new LinkedHashMap(); + params.put("key", "value"); + params.put("key with spaces", null); + + String expected = "key=value&key+with+spaces"; + assertEquals(expected, URLUtils.formURLEncodeMap(params)); + } + @Test public void shouldPercentEncodeString() { @@ -37,24 +48,32 @@ public class URLUtilsTest } @Test - public void shouldPercentDecodeString() + public void shouldFormURLEncodeString() { - String toDecode = "this+is+a+test+%26%5E"; - String expected = "this is a test &^"; - assertEquals(expected, URLUtils.percentDecode(toDecode)); + String toEncode = "this is a test &^"; + String expected = "this+is+a+test+%26%5E"; + assertEquals(expected, URLUtils.formURLEncode(toEncode)); } @Test - public void shouldEncodeAllSpecialCharacters() + public void shouldFormURLDecodeString() + { + String toDecode = "this+is+a+test+%26%5E"; + String expected = "this is a test &^"; + assertEquals(expected, URLUtils.formURLDecode(toDecode)); + } + + @Test + public void shouldPercentEncodeAllSpecialCharacters() { String plain = "!*'();:@&=+$,/?#[]"; String encoded = "%21%2A%27%28%29%3B%3A%40%26%3D%2B%24%2C%2F%3F%23%5B%5D"; assertEquals(encoded, URLUtils.percentEncode(plain)); - assertEquals(plain, URLUtils.percentDecode(encoded)); + assertEquals(plain, URLUtils.formURLDecode(encoded)); } @Test - public void shouldNotEncodeReservedCharacters() + public void shouldNotPercentEncodeReservedCharacters() { String plain = "abcde123456-._~"; String encoded = plain; @@ -79,7 +98,7 @@ public class URLUtilsTest public void shouldThrowExceptionIfStringToDecodeIsNull() { String toDecode = null; - URLUtils.percentDecode(toDecode); + URLUtils.formURLDecode(toDecode); } @Test(expected = IllegalArgumentException.class) @@ -103,7 +122,7 @@ public class URLUtilsTest public void shouldAppendParametersToSimpleUrl() { String url = "http://www.example.com"; - String expectedUrl = "http://www.example.com?param1=value1¶m2=value%20with%20spaces"; + String expectedUrl = "http://www.example.com?param1=value1¶m2=value+with+spaces"; Map params = new HashMap(); params.put("param1", "value1"); @@ -117,7 +136,7 @@ public class URLUtilsTest public void shouldAppendParametersToUrlWithQuerystring() { String url = "http://www.example.com?already=present"; - String expectedUrl = "http://www.example.com?already=present¶m1=value1¶m2=value%20with%20spaces"; + String expectedUrl = "http://www.example.com?already=present¶m1=value1¶m2=value+with+spaces"; Map params = new HashMap(); params.put("param1", "value1"); @@ -128,7 +147,7 @@ public class URLUtilsTest } @Test - public void shouldEncodePlusSymbol() + public void shouldPercentEncodePlusSymbol() { String plain = "7aEP+jNAwvjc0mjhqg0nuXPf"; String encoded = "7aEP%2BjNAwvjc0mjhqg0nuXPf"; @@ -137,11 +156,11 @@ public class URLUtilsTest } @Test - public void shouldDecodePlusSymbol() + public void shouldURLDecodePlusSymbol() { String encoded = "oauth_verifier=7aEP%2BjNAwvjc0mjhqg0nuXPf"; String expected = "oauth_verifier=7aEP+jNAwvjc0mjhqg0nuXPf"; - Assert.assertEquals(expected, URLUtils.percentDecode(encoded)); + Assert.assertEquals(expected, URLUtils.formURLDecode(encoded)); } }