SPR-7107 - RestTemplate/UriTemplate/UriUtils improperly encoding UTF-8

This commit is contained in:
Arjen Poutsma 2010-04-19 08:28:10 +00:00
parent e60389283d
commit b25462ddf9
4 changed files with 28 additions and 16 deletions

View File

@ -424,22 +424,33 @@ public abstract class UriUtils {
throws UnsupportedEncodingException { throws UnsupportedEncodingException {
Assert.notNull(source, "'source' must not be null"); Assert.notNull(source, "'source' must not be null");
Assert.hasLength(encoding, "'encoding' must not be empty"); Assert.hasLength(encoding, "'encoding' must not be empty");
ByteArrayOutputStream bos = new ByteArrayOutputStream(source.length() * 2);
for (int i = 0; i < source.length(); i++) { byte[] bytes = encode(source.getBytes(encoding), notEncoded);
int ch = source.charAt(i); return new String(bytes, "US-ASCII");
if (notEncoded.get(ch)) { }
bos.write(ch);
private static byte[] encode(byte[] source, BitSet notEncoded) {
Assert.notNull(source, "'source' must not be null");
ByteArrayOutputStream bos = new ByteArrayOutputStream(source.length * 2);
for (int i = 0; i < source.length; i++) {
int b = source[i];
if (b < 0) {
b += 256;
}
if (notEncoded.get(b)) {
bos.write(b);
} }
else { else {
bos.write('%'); bos.write('%');
char hex1 = Character.toUpperCase(Character.forDigit((ch >> 4) & 0xF, 16)); char hex1 = Character.toUpperCase(Character.forDigit((b >> 4) & 0xF, 16));
char hex2 = Character.toUpperCase(Character.forDigit(ch & 0xF, 16)); char hex2 = Character.toUpperCase(Character.forDigit(b & 0xF, 16));
bos.write(hex1); bos.write(hex1);
bos.write(hex2); bos.write(hex2);
} }
} }
return new String(bos.toByteArray(), encoding); return bos.toByteArray();
} }
/** /**

View File

@ -165,7 +165,7 @@ public class RestTemplateIntegrationTests {
@Test @Test
public void uri() throws InterruptedException, URISyntaxException { public void uri() throws InterruptedException, URISyntaxException {
String result = template.getForObject(URI + "/uri/{query}", String.class, "Z\u00fcrich"); String result = template.getForObject(URI + "/uri/{query}", String.class, "Z\u00fcrich");
assertEquals("Invalid request URI", "/uri/Z%FCrich", result); assertEquals("Invalid request URI", "/uri/Z%C3%BCrich", result);
result = template.getForObject(URI + "/uri/query={query}", String.class, "foo@bar"); result = template.getForObject(URI + "/uri/query={query}", String.class, "foo@bar");
assertEquals("Invalid request URI", "/uri/query=foo@bar", result); assertEquals("Invalid request URI", "/uri/query=foo@bar", result);

View File

@ -87,9 +87,9 @@ public class UriTemplateTests {
@Test @Test
public void expandEncoded() throws Exception { public void expandEncoded() throws Exception {
UriTemplate template = new UriTemplate("http://example.com//hotel list/{hotel}"); UriTemplate template = new UriTemplate("http://example.com/hotel list/{hotel}");
URI result = template.expand("Z\u00fcrich"); URI result = template.expand("Z\u00fcrich");
assertEquals("Invalid expanded template", new URI("http://example.com//hotel%20list/Z%FCrich"), result); assertEquals("Invalid expanded template", new URI("http://example.com/hotel%20list/Z%C3%BCrich"), result);
} }
@Test @Test

View File

@ -53,7 +53,7 @@ public class UriUtilsTest {
public void encodePath() throws UnsupportedEncodingException { public void encodePath() throws UnsupportedEncodingException {
assertEquals("Invalid encoded result", "/foo/bar", UriUtils.encodePath("/foo/bar", ENC)); assertEquals("Invalid encoded result", "/foo/bar", UriUtils.encodePath("/foo/bar", ENC));
assertEquals("Invalid encoded result", "/foo%20bar", UriUtils.encodePath("/foo bar", ENC)); assertEquals("Invalid encoded result", "/foo%20bar", UriUtils.encodePath("/foo bar", ENC));
assertEquals("Invalid encoded result", "/Z%FCrich", UriUtils.encodePath("/Z\u00fcrich", ENC)); assertEquals("Invalid encoded result", "/Z%C3%BCrich", UriUtils.encodePath("/Z\u00fcrich", ENC));
} }
@Test @Test
@ -67,6 +67,7 @@ public class UriUtilsTest {
assertEquals("Invalid encoded result", "foobar", UriUtils.encodeQuery("foobar", ENC)); assertEquals("Invalid encoded result", "foobar", UriUtils.encodeQuery("foobar", ENC));
assertEquals("Invalid encoded result", "foo%20bar", UriUtils.encodeQuery("foo bar", ENC)); assertEquals("Invalid encoded result", "foo%20bar", UriUtils.encodeQuery("foo bar", ENC));
assertEquals("Invalid encoded result", "foobar/+", UriUtils.encodeQuery("foobar/+", ENC)); assertEquals("Invalid encoded result", "foobar/+", UriUtils.encodeQuery("foobar/+", ENC));
assertEquals("Invalid encoded result", "T%C5%8Dky%C5%8D", UriUtils.encodeQuery("T\u014dky\u014d", ENC));
} }
@Test @Test
@ -101,8 +102,8 @@ public class UriUtilsTest {
UriUtils.encodeUri("http://www.ietf.org/rfc/rfc3986.txt", ENC)); UriUtils.encodeUri("http://www.ietf.org/rfc/rfc3986.txt", ENC));
assertEquals("Invalid encoded URI", "https://www.ietf.org/rfc/rfc3986.txt", assertEquals("Invalid encoded URI", "https://www.ietf.org/rfc/rfc3986.txt",
UriUtils.encodeUri("https://www.ietf.org/rfc/rfc3986.txt", ENC)); UriUtils.encodeUri("https://www.ietf.org/rfc/rfc3986.txt", ENC));
assertEquals("Invalid encoded URI", "http://www.google.com/?q=z%FCrich", assertEquals("Invalid encoded URI", "http://www.google.com/?q=Z%C3%BCrich",
UriUtils.encodeUri("http://www.google.com/?q=z\u00fcrich", ENC)); UriUtils.encodeUri("http://www.google.com/?q=Z\u00fcrich", ENC));
assertEquals("Invalid encoded URI", assertEquals("Invalid encoded URI",
"http://arjen:foobar@java.sun.com:80/javase/6/docs/api/java/util/BitSet.html?foo=bar#and(java.util.BitSet)", "http://arjen:foobar@java.sun.com:80/javase/6/docs/api/java/util/BitSet.html?foo=bar#and(java.util.BitSet)",
UriUtils.encodeUri( UriUtils.encodeUri(
@ -130,8 +131,8 @@ public class UriUtilsTest {
UriUtils.encodeHttpUrl("http://www.ietf.org/rfc/rfc3986.txt", ENC)); UriUtils.encodeHttpUrl("http://www.ietf.org/rfc/rfc3986.txt", ENC));
assertEquals("Invalid encoded URI", "https://www.ietf.org/rfc/rfc3986.txt", assertEquals("Invalid encoded URI", "https://www.ietf.org/rfc/rfc3986.txt",
UriUtils.encodeHttpUrl("https://www.ietf.org/rfc/rfc3986.txt", ENC)); UriUtils.encodeHttpUrl("https://www.ietf.org/rfc/rfc3986.txt", ENC));
assertEquals("Invalid encoded HTTP URL", "http://www.google.com/?q=z%FCrich", assertEquals("Invalid encoded HTTP URL", "http://www.google.com/?q=Z%C3%BCrich",
UriUtils.encodeHttpUrl("http://www.google.com/?q=z\u00fcrich", ENC)); UriUtils.encodeHttpUrl("http://www.google.com/?q=Z\u00fcrich", ENC));
assertEquals("Invalid encoded HTTP URL", assertEquals("Invalid encoded HTTP URL",
"http://arjen:foobar@java.sun.com:80/javase/6/docs/api/java/util/BitSet.html?foo=bar", "http://arjen:foobar@java.sun.com:80/javase/6/docs/api/java/util/BitSet.html?foo=bar",
UriUtils.encodeHttpUrl( UriUtils.encodeHttpUrl(