|
|
|
@ -1,5 +1,5 @@ |
|
|
|
/* |
|
|
|
/* |
|
|
|
* Copyright 2002-2012 the original author or authors. |
|
|
|
* Copyright 2002-2014 the original author or authors. |
|
|
|
* |
|
|
|
* |
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
|
|
* you may not use this file except in compliance with the License. |
|
|
|
* you may not use this file except in compliance with the License. |
|
|
|
@ -24,14 +24,15 @@ import java.util.regex.Pattern; |
|
|
|
import org.springframework.util.Assert; |
|
|
|
import org.springframework.util.Assert; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Utility class for URI encoding and decoding based on RFC 3986. Offers encoding methods for the various URI |
|
|
|
* Utility class for URI encoding and decoding based on RFC 3986. |
|
|
|
* components. |
|
|
|
* Offers encoding methods for the various URI components. |
|
|
|
* |
|
|
|
* |
|
|
|
* <p>All {@code encode*(String, String} methods in this class operate in a similar way: |
|
|
|
* <p>All {@code encode*(String, String} methods in this class operate in a similar way: |
|
|
|
* <ul> |
|
|
|
* <ul> |
|
|
|
* <li>Valid characters for the specific URI component as defined in RFC 3986 stay the same.</li> |
|
|
|
* <li>Valid characters for the specific URI component as defined in RFC 3986 stay the same.</li> |
|
|
|
* <li>All other characters are converted into one or more bytes in the given encoding scheme. Each of the |
|
|
|
* <li>All other characters are converted into one or more bytes in the given encoding scheme. |
|
|
|
* resulting bytes is written as a hexadecimal string in the "{@code %<i>xy</i>}" format.</li> |
|
|
|
* Each of the resulting bytes is written as a hexadecimal string in the "{@code %<i>xy</i>}" |
|
|
|
|
|
|
|
* format.</li> |
|
|
|
* </ul> |
|
|
|
* </ul> |
|
|
|
* |
|
|
|
* |
|
|
|
* @author Arjen Poutsma |
|
|
|
* @author Arjen Poutsma |
|
|
|
@ -65,6 +66,7 @@ public abstract class UriUtils { |
|
|
|
"^" + HTTP_PATTERN + "(//(" + USERINFO_PATTERN + "@)?" + HOST_PATTERN + "(:" + PORT_PATTERN + ")?" + ")?" + |
|
|
|
"^" + HTTP_PATTERN + "(//(" + USERINFO_PATTERN + "@)?" + HOST_PATTERN + "(:" + PORT_PATTERN + ")?" + ")?" + |
|
|
|
PATH_PATTERN + "(\\?" + LAST_PATTERN + ")?"); |
|
|
|
PATH_PATTERN + "(\\?" + LAST_PATTERN + ")?"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// encoding
|
|
|
|
// encoding
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
@ -73,7 +75,7 @@ public abstract class UriUtils { |
|
|
|
* <p><strong>Note</strong> that this method does not attempt to encode "=" and "&" |
|
|
|
* <p><strong>Note</strong> that this method does not attempt to encode "=" and "&" |
|
|
|
* characters in query parameter names and query parameter values because they cannot |
|
|
|
* characters in query parameter names and query parameter values because they cannot |
|
|
|
* be parsed in a reliable way. Instead use: |
|
|
|
* be parsed in a reliable way. Instead use: |
|
|
|
* <pre> |
|
|
|
* <pre class="code"> |
|
|
|
* UriComponents uriComponents = UriComponentsBuilder.fromUri("/path?name={value}").buildAndExpand("a=b"); |
|
|
|
* UriComponents uriComponents = UriComponentsBuilder.fromUri("/path?name={value}").buildAndExpand("a=b"); |
|
|
|
* String encodedUri = uriComponents.encode().toUriString(); |
|
|
|
* String encodedUri = uriComponents.encode().toUriString(); |
|
|
|
* </pre> |
|
|
|
* </pre> |
|
|
|
@ -86,19 +88,18 @@ public abstract class UriUtils { |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
@Deprecated |
|
|
|
@Deprecated |
|
|
|
public static String encodeUri(String uri, String encoding) throws UnsupportedEncodingException { |
|
|
|
public static String encodeUri(String uri, String encoding) throws UnsupportedEncodingException { |
|
|
|
Assert.notNull(uri, "'uri' must not be null"); |
|
|
|
Assert.notNull(uri, "URI must not be null"); |
|
|
|
Assert.hasLength(encoding, "'encoding' must not be empty"); |
|
|
|
Assert.hasLength(encoding, "Encoding must not be empty"); |
|
|
|
Matcher m = URI_PATTERN.matcher(uri); |
|
|
|
Matcher matcher = URI_PATTERN.matcher(uri); |
|
|
|
if (m.matches()) { |
|
|
|
if (matcher.matches()) { |
|
|
|
String scheme = m.group(2); |
|
|
|
String scheme = matcher.group(2); |
|
|
|
String authority = m.group(3); |
|
|
|
String authority = matcher.group(3); |
|
|
|
String userinfo = m.group(5); |
|
|
|
String userinfo = matcher.group(5); |
|
|
|
String host = m.group(6); |
|
|
|
String host = matcher.group(6); |
|
|
|
String port = m.group(8); |
|
|
|
String port = matcher.group(8); |
|
|
|
String path = m.group(9); |
|
|
|
String path = matcher.group(9); |
|
|
|
String query = m.group(11); |
|
|
|
String query = matcher.group(11); |
|
|
|
String fragment = m.group(13); |
|
|
|
String fragment = matcher.group(13); |
|
|
|
|
|
|
|
|
|
|
|
return encodeUriComponents(scheme, authority, userinfo, host, port, path, query, fragment, encoding); |
|
|
|
return encodeUriComponents(scheme, authority, userinfo, host, port, path, query, fragment, encoding); |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
else { |
|
|
|
@ -114,7 +115,7 @@ public abstract class UriUtils { |
|
|
|
* <p><strong>Note</strong> that this method does not attempt to encode "=" and "&" |
|
|
|
* <p><strong>Note</strong> that this method does not attempt to encode "=" and "&" |
|
|
|
* characters in query parameter names and query parameter values because they cannot |
|
|
|
* characters in query parameter names and query parameter values because they cannot |
|
|
|
* be parsed in a reliable way. Instead use: |
|
|
|
* be parsed in a reliable way. Instead use: |
|
|
|
* <pre> |
|
|
|
* <pre class="code"> |
|
|
|
* UriComponents uriComponents = UriComponentsBuilder.fromHttpUrl("/path?name={value}").buildAndExpand("a=b"); |
|
|
|
* UriComponents uriComponents = UriComponentsBuilder.fromHttpUrl("/path?name={value}").buildAndExpand("a=b"); |
|
|
|
* String encodedUri = uriComponents.encode().toUriString(); |
|
|
|
* String encodedUri = uriComponents.encode().toUriString(); |
|
|
|
* </pre> |
|
|
|
* </pre> |
|
|
|
@ -127,18 +128,17 @@ public abstract class UriUtils { |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
@Deprecated |
|
|
|
@Deprecated |
|
|
|
public static String encodeHttpUrl(String httpUrl, String encoding) throws UnsupportedEncodingException { |
|
|
|
public static String encodeHttpUrl(String httpUrl, String encoding) throws UnsupportedEncodingException { |
|
|
|
Assert.notNull(httpUrl, "'httpUrl' must not be null"); |
|
|
|
Assert.notNull(httpUrl, "HTTP URL must not be null"); |
|
|
|
Assert.hasLength(encoding, "'encoding' must not be empty"); |
|
|
|
Assert.hasLength(encoding, "Encoding must not be empty"); |
|
|
|
Matcher m = HTTP_URL_PATTERN.matcher(httpUrl); |
|
|
|
Matcher matcher = HTTP_URL_PATTERN.matcher(httpUrl); |
|
|
|
if (m.matches()) { |
|
|
|
if (matcher.matches()) { |
|
|
|
String scheme = m.group(1); |
|
|
|
String scheme = matcher.group(1); |
|
|
|
String authority = m.group(2); |
|
|
|
String authority = matcher.group(2); |
|
|
|
String userinfo = m.group(4); |
|
|
|
String userinfo = matcher.group(4); |
|
|
|
String host = m.group(5); |
|
|
|
String host = matcher.group(5); |
|
|
|
String portString = m.group(7); |
|
|
|
String portString = matcher.group(7); |
|
|
|
String path = m.group(8); |
|
|
|
String path = matcher.group(8); |
|
|
|
String query = m.group(10); |
|
|
|
String query = matcher.group(10); |
|
|
|
|
|
|
|
|
|
|
|
return encodeUriComponents(scheme, authority, userinfo, host, portString, path, query, null, encoding); |
|
|
|
return encodeUriComponents(scheme, authority, userinfo, host, portString, path, query, null, encoding); |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
else { |
|
|
|
@ -168,7 +168,7 @@ public abstract class UriUtils { |
|
|
|
String host, String port, String path, String query, String fragment, String encoding) |
|
|
|
String host, String port, String path, String query, String fragment, String encoding) |
|
|
|
throws UnsupportedEncodingException { |
|
|
|
throws UnsupportedEncodingException { |
|
|
|
|
|
|
|
|
|
|
|
Assert.hasLength(encoding, "'encoding' must not be empty"); |
|
|
|
Assert.hasLength(encoding, "Encoding must not be empty"); |
|
|
|
StringBuilder sb = new StringBuilder(); |
|
|
|
StringBuilder sb = new StringBuilder(); |
|
|
|
|
|
|
|
|
|
|
|
if (scheme != null) { |
|
|
|
if (scheme != null) { |
|
|
|
@ -217,8 +217,7 @@ public abstract class UriUtils { |
|
|
|
* @throws UnsupportedEncodingException when the given encoding parameter is not supported |
|
|
|
* @throws UnsupportedEncodingException when the given encoding parameter is not supported |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public static String encodeScheme(String scheme, String encoding) throws UnsupportedEncodingException { |
|
|
|
public static String encodeScheme(String scheme, String encoding) throws UnsupportedEncodingException { |
|
|
|
return HierarchicalUriComponents.encodeUriComponent(scheme, encoding, |
|
|
|
return HierarchicalUriComponents.encodeUriComponent(scheme, encoding, HierarchicalUriComponents.Type.SCHEME); |
|
|
|
HierarchicalUriComponents.Type.SCHEME); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
@ -229,8 +228,7 @@ public abstract class UriUtils { |
|
|
|
* @throws UnsupportedEncodingException when the given encoding parameter is not supported |
|
|
|
* @throws UnsupportedEncodingException when the given encoding parameter is not supported |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public static String encodeAuthority(String authority, String encoding) throws UnsupportedEncodingException { |
|
|
|
public static String encodeAuthority(String authority, String encoding) throws UnsupportedEncodingException { |
|
|
|
return HierarchicalUriComponents.encodeUriComponent(authority, encoding, |
|
|
|
return HierarchicalUriComponents.encodeUriComponent(authority, encoding, HierarchicalUriComponents.Type.AUTHORITY); |
|
|
|
HierarchicalUriComponents.Type.AUTHORITY); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
@ -241,8 +239,7 @@ public abstract class UriUtils { |
|
|
|
* @throws UnsupportedEncodingException when the given encoding parameter is not supported |
|
|
|
* @throws UnsupportedEncodingException when the given encoding parameter is not supported |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public static String encodeUserInfo(String userInfo, String encoding) throws UnsupportedEncodingException { |
|
|
|
public static String encodeUserInfo(String userInfo, String encoding) throws UnsupportedEncodingException { |
|
|
|
return HierarchicalUriComponents.encodeUriComponent(userInfo, encoding, |
|
|
|
return HierarchicalUriComponents.encodeUriComponent(userInfo, encoding, HierarchicalUriComponents.Type.USER_INFO); |
|
|
|
HierarchicalUriComponents.Type.USER_INFO); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
@ -253,8 +250,7 @@ public abstract class UriUtils { |
|
|
|
* @throws UnsupportedEncodingException when the given encoding parameter is not supported |
|
|
|
* @throws UnsupportedEncodingException when the given encoding parameter is not supported |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public static String encodeHost(String host, String encoding) throws UnsupportedEncodingException { |
|
|
|
public static String encodeHost(String host, String encoding) throws UnsupportedEncodingException { |
|
|
|
return HierarchicalUriComponents |
|
|
|
return HierarchicalUriComponents.encodeUriComponent(host, encoding, HierarchicalUriComponents.Type.HOST); |
|
|
|
.encodeUriComponent(host, encoding, HierarchicalUriComponents.Type.HOST); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
@ -265,8 +261,7 @@ public abstract class UriUtils { |
|
|
|
* @throws UnsupportedEncodingException when the given encoding parameter is not supported |
|
|
|
* @throws UnsupportedEncodingException when the given encoding parameter is not supported |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public static String encodePort(String port, String encoding) throws UnsupportedEncodingException { |
|
|
|
public static String encodePort(String port, String encoding) throws UnsupportedEncodingException { |
|
|
|
return HierarchicalUriComponents |
|
|
|
return HierarchicalUriComponents.encodeUriComponent(port, encoding, HierarchicalUriComponents.Type.PORT); |
|
|
|
.encodeUriComponent(port, encoding, HierarchicalUriComponents.Type.PORT); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
@ -277,8 +272,7 @@ public abstract class UriUtils { |
|
|
|
* @throws UnsupportedEncodingException when the given encoding parameter is not supported |
|
|
|
* @throws UnsupportedEncodingException when the given encoding parameter is not supported |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public static String encodePath(String path, String encoding) throws UnsupportedEncodingException { |
|
|
|
public static String encodePath(String path, String encoding) throws UnsupportedEncodingException { |
|
|
|
return HierarchicalUriComponents |
|
|
|
return HierarchicalUriComponents.encodeUriComponent(path, encoding, HierarchicalUriComponents.Type.PATH); |
|
|
|
.encodeUriComponent(path, encoding, HierarchicalUriComponents.Type.PATH); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
@ -289,8 +283,7 @@ public abstract class UriUtils { |
|
|
|
* @throws UnsupportedEncodingException when the given encoding parameter is not supported |
|
|
|
* @throws UnsupportedEncodingException when the given encoding parameter is not supported |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public static String encodePathSegment(String segment, String encoding) throws UnsupportedEncodingException { |
|
|
|
public static String encodePathSegment(String segment, String encoding) throws UnsupportedEncodingException { |
|
|
|
return HierarchicalUriComponents.encodeUriComponent(segment, encoding, |
|
|
|
return HierarchicalUriComponents.encodeUriComponent(segment, encoding, HierarchicalUriComponents.Type.PATH_SEGMENT); |
|
|
|
HierarchicalUriComponents.Type.PATH_SEGMENT); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
@ -301,8 +294,7 @@ public abstract class UriUtils { |
|
|
|
* @throws UnsupportedEncodingException when the given encoding parameter is not supported |
|
|
|
* @throws UnsupportedEncodingException when the given encoding parameter is not supported |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public static String encodeQuery(String query, String encoding) throws UnsupportedEncodingException { |
|
|
|
public static String encodeQuery(String query, String encoding) throws UnsupportedEncodingException { |
|
|
|
return HierarchicalUriComponents |
|
|
|
return HierarchicalUriComponents.encodeUriComponent(query, encoding, HierarchicalUriComponents.Type.QUERY); |
|
|
|
.encodeUriComponent(query, encoding, HierarchicalUriComponents.Type.QUERY); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
@ -313,8 +305,7 @@ public abstract class UriUtils { |
|
|
|
* @throws UnsupportedEncodingException when the given encoding parameter is not supported |
|
|
|
* @throws UnsupportedEncodingException when the given encoding parameter is not supported |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public static String encodeQueryParam(String queryParam, String encoding) throws UnsupportedEncodingException { |
|
|
|
public static String encodeQueryParam(String queryParam, String encoding) throws UnsupportedEncodingException { |
|
|
|
return HierarchicalUriComponents.encodeUriComponent(queryParam, encoding, |
|
|
|
return HierarchicalUriComponents.encodeUriComponent(queryParam, encoding, HierarchicalUriComponents.Type.QUERY_PARAM); |
|
|
|
HierarchicalUriComponents.Type.QUERY_PARAM); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
@ -325,8 +316,7 @@ public abstract class UriUtils { |
|
|
|
* @throws UnsupportedEncodingException when the given encoding parameter is not supported |
|
|
|
* @throws UnsupportedEncodingException when the given encoding parameter is not supported |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public static String encodeFragment(String fragment, String encoding) throws UnsupportedEncodingException { |
|
|
|
public static String encodeFragment(String fragment, String encoding) throws UnsupportedEncodingException { |
|
|
|
return HierarchicalUriComponents.encodeUriComponent(fragment, encoding, |
|
|
|
return HierarchicalUriComponents.encodeUriComponent(fragment, encoding, HierarchicalUriComponents.Type.FRAGMENT); |
|
|
|
HierarchicalUriComponents.Type.FRAGMENT); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -348,8 +338,8 @@ public abstract class UriUtils { |
|
|
|
* @see java.net.URLDecoder#decode(String, String) |
|
|
|
* @see java.net.URLDecoder#decode(String, String) |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public static String decode(String source, String encoding) throws UnsupportedEncodingException { |
|
|
|
public static String decode(String source, String encoding) 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"); |
|
|
|
int length = source.length(); |
|
|
|
int length = source.length(); |
|
|
|
ByteArrayOutputStream bos = new ByteArrayOutputStream(length); |
|
|
|
ByteArrayOutputStream bos = new ByteArrayOutputStream(length); |
|
|
|
boolean changed = false; |
|
|
|
boolean changed = false; |
|
|
|
@ -376,7 +366,7 @@ public abstract class UriUtils { |
|
|
|
bos.write(ch); |
|
|
|
bos.write(ch); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
return changed ? new String(bos.toByteArray(), encoding) : source; |
|
|
|
return (changed ? new String(bos.toByteArray(), encoding) : source); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|