SPR-5973: UriComponents no longer a Map, moved all static methods from UriComponents to builder, added expand method to UriComponents
This commit is contained in:
parent
dd1f3f8e0f
commit
663f056329
|
|
@ -20,17 +20,17 @@ import java.io.ByteArrayOutputStream;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.EnumMap;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
import org.springframework.util.LinkedMultiValueMap;
|
import org.springframework.util.LinkedMultiValueMap;
|
||||||
import org.springframework.util.MultiValueMap;
|
import org.springframework.util.MultiValueMap;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
@ -48,229 +48,54 @@ import org.springframework.util.StringUtils;
|
||||||
* @since 3.1
|
* @since 3.1
|
||||||
* @see UriComponentsBuilder
|
* @see UriComponentsBuilder
|
||||||
*/
|
*/
|
||||||
public final class UriComponents implements Map<UriComponents.Type, String> {
|
public final class UriComponents {
|
||||||
|
|
||||||
/**
|
private static final String DEFAULT_ENCODING = "UTF-8";
|
||||||
* The default encoding used for various encode methods.
|
|
||||||
*/
|
|
||||||
public static final String DEFAULT_ENCODING = "UTF-8";
|
|
||||||
|
|
||||||
private static final String SCHEME_PATTERN = "([^:/?#]+):";
|
private static final char PATH_DELIMITER = '/';
|
||||||
|
|
||||||
private static final String HTTP_PATTERN = "(http|https):";
|
/** Captures URI template variable names. */
|
||||||
|
private static final Pattern NAMES_PATTERN = Pattern.compile("\\{([^/]+?)\\}");
|
||||||
|
|
||||||
private static final String USERINFO_PATTERN = "([^@/]*)";
|
private final String scheme;
|
||||||
|
|
||||||
private static final String HOST_PATTERN = "([^/?#:]*)";
|
private final String userInfo;
|
||||||
|
|
||||||
private static final String PORT_PATTERN = "(\\d*)";
|
private final String host;
|
||||||
|
|
||||||
private static final String PATH_PATTERN = "([^?#]*)";
|
private final int port;
|
||||||
|
|
||||||
private static final String QUERY_PATTERN = "([^#]*)";
|
private final List<String> pathSegments;
|
||||||
|
|
||||||
private static final String LAST_PATTERN = "(.*)";
|
private final MultiValueMap<String, String> queryParams;
|
||||||
|
|
||||||
// Regex patterns that matches URIs. See RFC 3986, appendix B
|
private final String fragment;
|
||||||
private static final Pattern URI_PATTERN = Pattern.compile(
|
|
||||||
"^(" + SCHEME_PATTERN + ")?" + "(//(" + USERINFO_PATTERN + "@)?" + HOST_PATTERN + "(:" + PORT_PATTERN +
|
|
||||||
")?" + ")?" + PATH_PATTERN + "(\\?" + QUERY_PATTERN + ")?" + "(#" + LAST_PATTERN + ")?");
|
|
||||||
|
|
||||||
private static final Pattern HTTP_URL_PATTERN = Pattern.compile(
|
|
||||||
"^" + HTTP_PATTERN + "(//(" + USERINFO_PATTERN + "@)?" + HOST_PATTERN + "(:" + PORT_PATTERN + ")?" + ")?" +
|
|
||||||
PATH_PATTERN + "(\\?" + LAST_PATTERN + ")?");
|
|
||||||
|
|
||||||
|
|
||||||
private static final String PATH_DELIMITER = "/";
|
|
||||||
|
|
||||||
private static final Pattern QUERY_PARAM_PATTERN = Pattern.compile("([^&=]+)=?([^&=]+)?");
|
|
||||||
|
|
||||||
private final Map<Type, String> uriComponents;
|
|
||||||
|
|
||||||
private final boolean encoded;
|
private final boolean encoded;
|
||||||
|
|
||||||
private UriComponents(Map<Type, String> uriComponents, boolean encoded) {
|
public UriComponents(String scheme,
|
||||||
Assert.notEmpty(uriComponents, "'uriComponents' must not be empty");
|
String userInfo,
|
||||||
this.uriComponents = Collections.unmodifiableMap(uriComponents);
|
String host,
|
||||||
this.encoded = encoded;
|
int port,
|
||||||
}
|
List<String> pathSegments,
|
||||||
|
MultiValueMap<String, String> queryParams,
|
||||||
/**
|
String fragment,
|
||||||
* Creates a new {@code UriComponents} object from the given string URI.
|
boolean encoded) {
|
||||||
*
|
this.scheme = scheme;
|
||||||
* @param uri the source URI
|
this.userInfo = userInfo;
|
||||||
* @return the URI components of the URI
|
this.host = host;
|
||||||
*/
|
this.port = port;
|
||||||
public static UriComponents fromUriString(String uri) {
|
if (pathSegments == null) {
|
||||||
Assert.notNull(uri, "'uri' must not be null");
|
pathSegments = Collections.emptyList();
|
||||||
Matcher m = URI_PATTERN.matcher(uri);
|
}
|
||||||
if (m.matches()) {
|
this.pathSegments = Collections.unmodifiableList(pathSegments);
|
||||||
Map<UriComponents.Type, String> result = new EnumMap<UriComponents.Type, String>(UriComponents.Type.class);
|
if (queryParams == null) {
|
||||||
|
queryParams = new LinkedMultiValueMap<String, String>(0);
|
||||||
result.put(UriComponents.Type.SCHEME, m.group(2));
|
}
|
||||||
result.put(UriComponents.Type.AUTHORITY, m.group(3));
|
this.queryParams = CollectionUtils.unmodifiableMultiValueMap(queryParams);
|
||||||
result.put(UriComponents.Type.USER_INFO, m.group(5));
|
this.fragment = fragment;
|
||||||
result.put(UriComponents.Type.HOST, m.group(6));
|
this.encoded = encoded;
|
||||||
result.put(UriComponents.Type.PORT, m.group(8));
|
}
|
||||||
result.put(UriComponents.Type.PATH, m.group(9));
|
|
||||||
result.put(UriComponents.Type.QUERY, m.group(11));
|
|
||||||
result.put(UriComponents.Type.FRAGMENT, m.group(13));
|
|
||||||
|
|
||||||
return new UriComponents(result, false);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new IllegalArgumentException("[" + uri + "] is not a valid URI");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new {@code UriComponents} object from the string HTTP URL.
|
|
||||||
*
|
|
||||||
* @param httpUrl the source URI
|
|
||||||
* @return the URI components of the URI
|
|
||||||
*/
|
|
||||||
public static UriComponents fromHttpUrl(String httpUrl) {
|
|
||||||
Assert.notNull(httpUrl, "'httpUrl' must not be null");
|
|
||||||
Matcher m = HTTP_URL_PATTERN.matcher(httpUrl);
|
|
||||||
if (m.matches()) {
|
|
||||||
Map<UriComponents.Type, String> result = new EnumMap<UriComponents.Type, String>(UriComponents.Type.class);
|
|
||||||
|
|
||||||
result.put(UriComponents.Type.SCHEME, m.group(1));
|
|
||||||
result.put(UriComponents.Type.AUTHORITY, m.group(2));
|
|
||||||
result.put(UriComponents.Type.USER_INFO, m.group(4));
|
|
||||||
result.put(UriComponents.Type.HOST, m.group(5));
|
|
||||||
result.put(UriComponents.Type.PORT, m.group(7));
|
|
||||||
result.put(UriComponents.Type.PATH, m.group(8));
|
|
||||||
result.put(UriComponents.Type.QUERY, m.group(10));
|
|
||||||
|
|
||||||
return new UriComponents(result, false);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new IllegalArgumentException("[" + httpUrl + "] is not a valid HTTP URL");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new {@code UriComponents} object from the given {@code URI}.
|
|
||||||
*
|
|
||||||
* @param uri the URI
|
|
||||||
* @return the URI components of the URI
|
|
||||||
*/
|
|
||||||
public static UriComponents fromUri(URI uri) {
|
|
||||||
Assert.notNull(uri, "'uri' must not be null");
|
|
||||||
|
|
||||||
Map<Type, String> uriComponents = new EnumMap<Type, String>(Type.class);
|
|
||||||
if (uri.getScheme() != null) {
|
|
||||||
uriComponents.put(Type.SCHEME, uri.getScheme());
|
|
||||||
}
|
|
||||||
if (uri.getRawAuthority() != null) {
|
|
||||||
uriComponents.put(Type.AUTHORITY, uri.getRawAuthority());
|
|
||||||
}
|
|
||||||
if (uri.getRawUserInfo() != null) {
|
|
||||||
uriComponents.put(Type.USER_INFO, uri.getRawUserInfo());
|
|
||||||
}
|
|
||||||
if (uri.getHost() != null) {
|
|
||||||
uriComponents.put(Type.HOST, uri.getHost());
|
|
||||||
}
|
|
||||||
if (uri.getPort() != -1) {
|
|
||||||
uriComponents.put(Type.PORT, Integer.toString(uri.getPort()));
|
|
||||||
}
|
|
||||||
if (uri.getRawPath() != null) {
|
|
||||||
uriComponents.put(Type.PATH, uri.getRawPath());
|
|
||||||
}
|
|
||||||
if (uri.getRawQuery() != null) {
|
|
||||||
uriComponents.put(Type.QUERY, uri.getRawQuery());
|
|
||||||
}
|
|
||||||
if (uri.getRawFragment() != null) {
|
|
||||||
uriComponents.put(Type.FRAGMENT, uri.getRawFragment());
|
|
||||||
}
|
|
||||||
return new UriComponents(uriComponents, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates an instance of the {@code UriComponents} object from the given components. All the given arguments
|
|
||||||
* can be {@code null} and are considered to be unencoded.
|
|
||||||
*/
|
|
||||||
public static UriComponents fromUriComponents(String scheme,
|
|
||||||
String authority,
|
|
||||||
String userInfo,
|
|
||||||
String host,
|
|
||||||
String port,
|
|
||||||
String path,
|
|
||||||
String query,
|
|
||||||
String fragment) {
|
|
||||||
return fromUriComponents(scheme, authority, userInfo, host, port, path, query, fragment, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates an instance of the {@code UriComponents} object from the given components. All the given arguments
|
|
||||||
* can be {@code null}.
|
|
||||||
*
|
|
||||||
* @param encoded {@code true} if the arguments are encoded; {@code false} otherwise
|
|
||||||
*/
|
|
||||||
public static UriComponents fromUriComponents(String scheme,
|
|
||||||
String authority,
|
|
||||||
String userInfo,
|
|
||||||
String host,
|
|
||||||
String port,
|
|
||||||
String path,
|
|
||||||
String query,
|
|
||||||
String fragment,
|
|
||||||
boolean encoded) {
|
|
||||||
Map<Type, String> uriComponents = new EnumMap<Type, String>(Type.class);
|
|
||||||
if (scheme != null) {
|
|
||||||
uriComponents.put(Type.SCHEME, scheme);
|
|
||||||
}
|
|
||||||
if (authority != null) {
|
|
||||||
uriComponents.put(Type.AUTHORITY, authority);
|
|
||||||
}
|
|
||||||
if (userInfo != null) {
|
|
||||||
uriComponents.put(Type.USER_INFO, userInfo);
|
|
||||||
}
|
|
||||||
if (host != null) {
|
|
||||||
uriComponents.put(Type.HOST, host);
|
|
||||||
}
|
|
||||||
if (port != null) {
|
|
||||||
uriComponents.put(Type.PORT, port);
|
|
||||||
}
|
|
||||||
if (path != null) {
|
|
||||||
uriComponents.put(Type.PATH, path);
|
|
||||||
}
|
|
||||||
if (query != null) {
|
|
||||||
uriComponents.put(Type.QUERY, query);
|
|
||||||
}
|
|
||||||
if (fragment != null) {
|
|
||||||
uriComponents.put(Type.FRAGMENT, fragment);
|
|
||||||
}
|
|
||||||
return new UriComponents(uriComponents, encoded);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates an instance of the {@code UriComponents} object that contains the given components map.
|
|
||||||
*
|
|
||||||
* @param uriComponents the component to initialize with
|
|
||||||
*/
|
|
||||||
public static UriComponents fromUriComponentMap(Map<Type, String> uriComponents) {
|
|
||||||
boolean encoded;
|
|
||||||
if (uriComponents instanceof UriComponents) {
|
|
||||||
encoded = ((UriComponents) uriComponents).encoded;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
encoded = false;
|
|
||||||
}
|
|
||||||
return new UriComponents(uriComponents, encoded);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates an instance of the {@code UriComponents} object that contains the given components map.
|
|
||||||
*
|
|
||||||
* @param uriComponents the component to initialize with
|
|
||||||
* @param encoded whether the components are encpded
|
|
||||||
*/
|
|
||||||
public static UriComponents fromUriComponentMap(Map<Type, String> uriComponents, boolean encoded) {
|
|
||||||
return new UriComponents(uriComponents, encoded);
|
|
||||||
}
|
|
||||||
|
|
||||||
// component getters
|
// component getters
|
||||||
|
|
||||||
|
|
@ -280,16 +105,7 @@ public final class UriComponents implements Map<UriComponents.Type, String> {
|
||||||
* @return the scheme. Can be {@code null}.
|
* @return the scheme. Can be {@code null}.
|
||||||
*/
|
*/
|
||||||
public String getScheme() {
|
public String getScheme() {
|
||||||
return get(Type.SCHEME);
|
return scheme;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the authority.
|
|
||||||
*
|
|
||||||
* @return the authority. Can be {@code null}.
|
|
||||||
*/
|
|
||||||
public String getAuthority() {
|
|
||||||
return get(Type.AUTHORITY);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -298,7 +114,7 @@ public final class UriComponents implements Map<UriComponents.Type, String> {
|
||||||
* @return the user info. Can be {@code null}.
|
* @return the user info. Can be {@code null}.
|
||||||
*/
|
*/
|
||||||
public String getUserInfo() {
|
public String getUserInfo() {
|
||||||
return get(Type.USER_INFO);
|
return userInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -307,36 +123,47 @@ public final class UriComponents implements Map<UriComponents.Type, String> {
|
||||||
* @return the host. Can be {@code null}.
|
* @return the host. Can be {@code null}.
|
||||||
*/
|
*/
|
||||||
public String getHost() {
|
public String getHost() {
|
||||||
return get(Type.HOST);
|
return host;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the port as string.
|
* Returns the port. Returns {@code -1} if no port has been set.
|
||||||
*
|
*
|
||||||
* @return the port as string. Can be {@code null}.
|
* @return the port
|
||||||
*/
|
*/
|
||||||
public String getPort() {
|
public int getPort() {
|
||||||
return get(Type.PORT);
|
return port;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the port as integer. Returns {@code -1} if no port has been set.
|
* Returns the path.
|
||||||
*
|
*
|
||||||
* @return the port the port as integer
|
* @return the path. Can be {@code null}.
|
||||||
*/
|
*/
|
||||||
public int getPortAsInteger() {
|
public String getPath() {
|
||||||
String port = getPort();
|
if (!pathSegments.isEmpty()) {
|
||||||
return port != null ? Integer.parseInt(port) : -1;
|
StringBuilder pathBuilder = new StringBuilder();
|
||||||
}
|
for (String pathSegment : pathSegments) {
|
||||||
|
if (StringUtils.hasLength(pathSegment)) {
|
||||||
|
boolean startsWithSlash = pathSegment.charAt(0) == PATH_DELIMITER;
|
||||||
|
boolean endsWithSlash =
|
||||||
|
pathBuilder.length() > 0 && pathBuilder.charAt(pathBuilder.length() - 1) == PATH_DELIMITER;
|
||||||
|
|
||||||
/**
|
if (!endsWithSlash && !startsWithSlash) {
|
||||||
* Returns the path.
|
pathBuilder.append('/');
|
||||||
*
|
}
|
||||||
* @return the path. Can be {@code null}.
|
else if (endsWithSlash && startsWithSlash) {
|
||||||
*/
|
pathSegment = pathSegment.substring(1);
|
||||||
public String getPath() {
|
}
|
||||||
return get(Type.PATH);
|
pathBuilder.append(pathSegment);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
return pathBuilder.toString();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the list of path segments.
|
* Returns the list of path segments.
|
||||||
|
|
@ -344,41 +171,54 @@ public final class UriComponents implements Map<UriComponents.Type, String> {
|
||||||
* @return the path segments. Empty if no path has been set.
|
* @return the path segments. Empty if no path has been set.
|
||||||
*/
|
*/
|
||||||
public List<String> getPathSegments() {
|
public List<String> getPathSegments() {
|
||||||
String path = getPath();
|
return pathSegments;
|
||||||
if (path != null) {
|
|
||||||
return Arrays.asList(StringUtils.tokenizeToStringArray(path, PATH_DELIMITER));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the query.
|
* Returns the query.
|
||||||
*
|
*
|
||||||
* @return the query. Can be {@code null}.
|
* @return the query. Can be {@code null}.
|
||||||
*/
|
*/
|
||||||
public String getQuery() {
|
public String getQuery() {
|
||||||
return get(Type.QUERY);
|
if (!queryParams.isEmpty()) {
|
||||||
}
|
StringBuilder queryBuilder = new StringBuilder();
|
||||||
|
for (Map.Entry<String, List<String>> entry : queryParams.entrySet()) {
|
||||||
|
String name = entry.getKey();
|
||||||
|
List<String> values = entry.getValue();
|
||||||
|
if (CollectionUtils.isEmpty(values)) {
|
||||||
|
if (queryBuilder.length() != 0) {
|
||||||
|
queryBuilder.append('&');
|
||||||
|
}
|
||||||
|
queryBuilder.append(name);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (Object value : values) {
|
||||||
|
if (queryBuilder.length() != 0) {
|
||||||
|
queryBuilder.append('&');
|
||||||
|
}
|
||||||
|
queryBuilder.append(name);
|
||||||
|
|
||||||
/**
|
if (value != null) {
|
||||||
|
queryBuilder.append('=');
|
||||||
|
queryBuilder.append(value.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return queryBuilder.toString();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
* Returns the map of query parameters.
|
* Returns the map of query parameters.
|
||||||
*
|
*
|
||||||
* @return the query parameters. Empty if no query has been set.
|
* @return the query parameters. Empty if no query has been set.
|
||||||
*/
|
*/
|
||||||
public MultiValueMap<String, String> getQueryParams() {
|
public MultiValueMap<String, String> getQueryParams() {
|
||||||
MultiValueMap<String, String> result = new LinkedMultiValueMap<String, String>();
|
return queryParams;
|
||||||
String query = getQuery();
|
|
||||||
if (query != null) {
|
|
||||||
Matcher m = QUERY_PARAM_PATTERN.matcher(query);
|
|
||||||
while (m.find()) {
|
|
||||||
String name = m.group(1);
|
|
||||||
String value = m.group(2);
|
|
||||||
result.add(name, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -387,11 +227,17 @@ public final class UriComponents implements Map<UriComponents.Type, String> {
|
||||||
* @return the fragment. Can be {@code null}.
|
* @return the fragment. Can be {@code null}.
|
||||||
*/
|
*/
|
||||||
public String getFragment() {
|
public String getFragment() {
|
||||||
return get(Type.FRAGMENT);
|
return fragment;
|
||||||
}
|
}
|
||||||
|
|
||||||
// other functionality
|
// encoding
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes all URI components using their specific encoding rules, and returns the result as a new
|
||||||
|
* {@code UriComponents} instance. This method uses UTF-8 to encode.
|
||||||
|
*
|
||||||
|
* @return the encoded uri components
|
||||||
|
*/
|
||||||
public UriComponents encode() {
|
public UriComponents encode() {
|
||||||
try {
|
try {
|
||||||
return encode(DEFAULT_ENCODING);
|
return encode(DEFAULT_ENCODING);
|
||||||
|
|
@ -416,16 +262,29 @@ public final class UriComponents implements Map<UriComponents.Type, String> {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
final Map<Type, String> encoded = new EnumMap<Type, String>(Type.class);
|
String encodedScheme = encodeUriComponent(this.scheme, encoding, Type.SCHEME);
|
||||||
for (Entry<Type, String> entry : uriComponents.entrySet()) {
|
String encodedUserInfo = encodeUriComponent(this.userInfo, encoding, Type.USER_INFO);
|
||||||
Type key = entry.getKey();
|
String encodedHost = encodeUriComponent(this.host, encoding, Type.HOST);
|
||||||
String value = entry.getValue();
|
List<String> encodedPathSegments = new ArrayList<String>(this.pathSegments.size());
|
||||||
if (value != null) {
|
for (String pathSegment : this.pathSegments) {
|
||||||
value = encodeUriComponent(value, encoding, key);
|
String encodedPathSegment = encodeUriComponent(pathSegment, encoding, Type.PATH_SEGMENT);
|
||||||
}
|
encodedPathSegments.add(encodedPathSegment);
|
||||||
encoded.put(key, value);
|
}
|
||||||
}
|
MultiValueMap<String, String> encodedQueryParams =
|
||||||
return new UriComponents(encoded, true);
|
new LinkedMultiValueMap<String, String>(this.queryParams.size());
|
||||||
|
for (Map.Entry<String, List<String>> entry : this.queryParams.entrySet()) {
|
||||||
|
String encodedName = encodeUriComponent(entry.getKey(), encoding, Type.QUERY_PARAM);
|
||||||
|
List<String> encodedValues = new ArrayList<String>(entry.getValue().size());
|
||||||
|
for (String value : entry.getValue()) {
|
||||||
|
String encodedValue = encodeUriComponent(value, encoding, Type.QUERY_PARAM);
|
||||||
|
encodedValues.add(encodedValue);
|
||||||
|
}
|
||||||
|
encodedQueryParams.put(encodedName, encodedValues);
|
||||||
|
}
|
||||||
|
String encodedFragment = encodeUriComponent(this.fragment, encoding, Type.FRAGMENT);
|
||||||
|
|
||||||
|
return new UriComponents(encodedScheme, encodedUserInfo, encodedHost, this.port, encodedPathSegments,
|
||||||
|
encodedQueryParams, encodedFragment, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -434,25 +293,25 @@ public final class UriComponents implements Map<UriComponents.Type, String> {
|
||||||
*
|
*
|
||||||
* @param source the source string
|
* @param source the source string
|
||||||
* @param encoding the encoding of the source string
|
* @param encoding the encoding of the source string
|
||||||
* @param uriComponent the URI component for the source
|
* @param type the URI component for the source
|
||||||
* @param encodingOptions the options used when encoding. May be {@code null}.
|
|
||||||
* @return the encoded URI
|
* @return the encoded URI
|
||||||
* @throws IllegalArgumentException when the given uri parameter is not a valid URI
|
* @throws IllegalArgumentException when the given uri parameter is not a valid URI
|
||||||
* @see EncodingOption
|
|
||||||
*/
|
*/
|
||||||
static String encodeUriComponent(String source,
|
static String encodeUriComponent(String source, String encoding, Type type)
|
||||||
String encoding,
|
throws UnsupportedEncodingException {
|
||||||
UriComponents.Type uriComponent) throws UnsupportedEncodingException {
|
if (source == null) {
|
||||||
Assert.hasLength(encoding, "'encoding' must not be empty");
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.hasLength(encoding, "'encoding' must not be empty");
|
||||||
|
|
||||||
byte[] bytes = encodeInternal(source.getBytes(encoding), uriComponent);
|
byte[] bytes = encodeBytes(source.getBytes(encoding), type);
|
||||||
return new String(bytes, "US-ASCII");
|
return new String(bytes, "US-ASCII");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte[] encodeInternal(byte[] source,
|
private static byte[] encodeBytes(byte[] source, Type type) {
|
||||||
UriComponents.Type uriComponent) {
|
Assert.notNull(source, "'source' must not be null");
|
||||||
Assert.notNull(source, "'source' must not be null");
|
Assert.notNull(type, "'type' must not be null");
|
||||||
Assert.notNull(uriComponent, "'uriComponent' must not be null");
|
|
||||||
|
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream(source.length);
|
ByteArrayOutputStream bos = new ByteArrayOutputStream(source.length);
|
||||||
for (int i = 0; i < source.length; i++) {
|
for (int i = 0; i < source.length; i++) {
|
||||||
|
|
@ -460,7 +319,7 @@ public final class UriComponents implements Map<UriComponents.Type, String> {
|
||||||
if (b < 0) {
|
if (b < 0) {
|
||||||
b += 256;
|
b += 256;
|
||||||
}
|
}
|
||||||
if (uriComponent.isAllowed(b)) {
|
if (type.isAllowed(b)) {
|
||||||
bos.write(b);
|
bos.write(b);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
@ -476,51 +335,181 @@ public final class UriComponents implements Map<UriComponents.Type, String> {
|
||||||
return bos.toByteArray();
|
return bos.toByteArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// expanding
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replaces all URI template variables with the values from a given map. The map keys represent
|
||||||
|
* variable names; the values variable values. The order of variables is not significant.
|
||||||
|
|
||||||
|
* @param uriVariables the map of URI variables
|
||||||
|
* @return the expanded uri components
|
||||||
|
*/
|
||||||
|
public UriComponents expand(Map<String, ?> uriVariables) {
|
||||||
|
Assert.notNull(uriVariables, "'uriVariables' must not be null");
|
||||||
|
|
||||||
|
String expandedScheme = expandUriComponent(this.scheme, uriVariables);
|
||||||
|
String expandedUserInfo = expandUriComponent(this.userInfo, uriVariables);
|
||||||
|
String expandedHost = expandUriComponent(this.host, uriVariables);
|
||||||
|
List<String> expandedPathSegments = new ArrayList<String>(this.pathSegments.size());
|
||||||
|
for (String pathSegment : this.pathSegments) {
|
||||||
|
String expandedPathSegment = expandUriComponent(pathSegment, uriVariables);
|
||||||
|
expandedPathSegments.add(expandedPathSegment);
|
||||||
|
}
|
||||||
|
MultiValueMap<String, String> expandedQueryParams =
|
||||||
|
new LinkedMultiValueMap<String, String>(this.queryParams.size());
|
||||||
|
for (Map.Entry<String, List<String>> entry : this.queryParams.entrySet()) {
|
||||||
|
String expandedName = expandUriComponent(entry.getKey(), uriVariables);
|
||||||
|
List<String> expandedValues = new ArrayList<String>(entry.getValue().size());
|
||||||
|
for (String value : entry.getValue()) {
|
||||||
|
String expandedValue = expandUriComponent(value, uriVariables);
|
||||||
|
expandedValues.add(expandedValue);
|
||||||
|
}
|
||||||
|
expandedQueryParams.put(expandedName, expandedValues);
|
||||||
|
}
|
||||||
|
String expandedFragment = expandUriComponent(this.fragment, uriVariables);
|
||||||
|
|
||||||
|
return new UriComponents(expandedScheme, expandedUserInfo, expandedHost, this.port, expandedPathSegments,
|
||||||
|
expandedQueryParams, expandedFragment, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String expandUriComponent(String source, Map<String, ?> uriVariables) {
|
||||||
|
if (source == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (source.indexOf('{') == -1) {
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
Matcher matcher = NAMES_PATTERN.matcher(source);
|
||||||
|
StringBuffer sb = new StringBuffer();
|
||||||
|
while (matcher.find()) {
|
||||||
|
String match = matcher.group(1);
|
||||||
|
String variableName = getVariableName(match);
|
||||||
|
Object variableValue = uriVariables.get(variableName);
|
||||||
|
String uriVariableValueString = getVariableValueAsString(variableValue);
|
||||||
|
String replacement = Matcher.quoteReplacement(uriVariableValueString);
|
||||||
|
matcher.appendReplacement(sb, replacement);
|
||||||
|
}
|
||||||
|
matcher.appendTail(sb);
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replaces all URI template variables with the values from a given array. The array represent variable values.
|
||||||
|
* The order of variables is significant.
|
||||||
|
|
||||||
|
* @param uriVariableValues URI variable values
|
||||||
|
* @return the expanded uri components
|
||||||
|
*/
|
||||||
|
public UriComponents expand(Object... uriVariableValues) {
|
||||||
|
Assert.notNull(uriVariableValues, "'uriVariableValues' must not be null");
|
||||||
|
|
||||||
|
Iterator<Object> valueIterator = Arrays.asList(uriVariableValues).iterator();
|
||||||
|
|
||||||
|
String expandedScheme = expandUriComponent(this.scheme, valueIterator);
|
||||||
|
String expandedUserInfo = expandUriComponent(this.userInfo, valueIterator);
|
||||||
|
String expandedHost = expandUriComponent(this.host, valueIterator);
|
||||||
|
List<String> expandedPathSegments = new ArrayList<String>(this.pathSegments.size());
|
||||||
|
for (String pathSegment : this.pathSegments) {
|
||||||
|
String expandedPathSegment = expandUriComponent(pathSegment, valueIterator);
|
||||||
|
expandedPathSegments.add(expandedPathSegment);
|
||||||
|
}
|
||||||
|
MultiValueMap<String, String> expandedQueryParams =
|
||||||
|
new LinkedMultiValueMap<String, String>(this.queryParams.size());
|
||||||
|
for (Map.Entry<String, List<String>> entry : this.queryParams.entrySet()) {
|
||||||
|
String expandedName = expandUriComponent(entry.getKey(), valueIterator);
|
||||||
|
List<String> expandedValues = new ArrayList<String>(entry.getValue().size());
|
||||||
|
for (String value : entry.getValue()) {
|
||||||
|
String expandedValue = expandUriComponent(value, valueIterator);
|
||||||
|
expandedValues.add(expandedValue);
|
||||||
|
}
|
||||||
|
expandedQueryParams.put(expandedName, expandedValues);
|
||||||
|
}
|
||||||
|
String expandedFragment = expandUriComponent(this.fragment, valueIterator);
|
||||||
|
|
||||||
|
return new UriComponents(expandedScheme, expandedUserInfo, expandedHost, this.port, expandedPathSegments,
|
||||||
|
expandedQueryParams, expandedFragment, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String expandUriComponent(String source, Iterator<Object> valueIterator) {
|
||||||
|
if (source == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (source.indexOf('{') == -1) {
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
Matcher matcher = NAMES_PATTERN.matcher(source);
|
||||||
|
StringBuffer sb = new StringBuffer();
|
||||||
|
while (matcher.find()) {
|
||||||
|
if (!valueIterator.hasNext()) {
|
||||||
|
throw new IllegalArgumentException("Not enough variable values available to expand [" + source + "]");
|
||||||
|
}
|
||||||
|
Object variableValue = valueIterator.next();
|
||||||
|
String uriVariableValueString = getVariableValueAsString(variableValue);
|
||||||
|
String replacement = Matcher.quoteReplacement(uriVariableValueString);
|
||||||
|
matcher.appendReplacement(sb, replacement);
|
||||||
|
}
|
||||||
|
matcher.appendTail(sb);
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private String getVariableName(String match) {
|
||||||
|
int colonIdx = match.indexOf(':');
|
||||||
|
return colonIdx == -1 ? match : match.substring(0, colonIdx);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getVariableValueAsString(Object variableValue) {
|
||||||
|
return variableValue != null ? variableValue.toString() : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// other functionality
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a URI string from this {@code UriComponents} instance.
|
* Returns a URI string from this {@code UriComponents} instance.
|
||||||
*
|
*
|
||||||
* @return the URI created from the given components
|
* @return the URI string
|
||||||
*/
|
*/
|
||||||
public String toUriString() {
|
public String toUriString() {
|
||||||
StringBuilder uriBuilder = new StringBuilder();
|
StringBuilder uriBuilder = new StringBuilder();
|
||||||
|
|
||||||
if (getScheme() != null) {
|
if (scheme != null) {
|
||||||
uriBuilder.append(getScheme());
|
uriBuilder.append(scheme);
|
||||||
uriBuilder.append(':');
|
uriBuilder.append(':');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getUserInfo() != null || getHost() != null || getPort() != null) {
|
if (userInfo != null || host != null) {
|
||||||
uriBuilder.append("//");
|
uriBuilder.append("//");
|
||||||
if (getUserInfo() != null) {
|
if (userInfo != null) {
|
||||||
uriBuilder.append(getUserInfo());
|
uriBuilder.append(userInfo);
|
||||||
uriBuilder.append('@');
|
uriBuilder.append('@');
|
||||||
}
|
}
|
||||||
if (getHost() != null) {
|
if (host != null) {
|
||||||
uriBuilder.append(getHost());
|
uriBuilder.append(host);
|
||||||
}
|
}
|
||||||
if (getPort() != null) {
|
if (port != -1) {
|
||||||
uriBuilder.append(':');
|
uriBuilder.append(':');
|
||||||
uriBuilder.append(getPort());
|
uriBuilder.append(port);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (getAuthority() != null) {
|
|
||||||
uriBuilder.append("//");
|
String path = getPath();
|
||||||
uriBuilder.append(getAuthority());
|
if (path != null) {
|
||||||
|
uriBuilder.append(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getPath() != null) {
|
String query = getQuery();
|
||||||
uriBuilder.append(getPath());
|
if (query != null) {
|
||||||
}
|
|
||||||
|
|
||||||
if (getQuery() != null) {
|
|
||||||
uriBuilder.append('?');
|
uriBuilder.append('?');
|
||||||
uriBuilder.append(getQuery());
|
uriBuilder.append(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getFragment() != null) {
|
if (fragment != null) {
|
||||||
uriBuilder.append('#');
|
uriBuilder.append('#');
|
||||||
uriBuilder.append(getFragment());
|
uriBuilder.append(fragment);
|
||||||
}
|
}
|
||||||
|
|
||||||
return uriBuilder.toString();
|
return uriBuilder.toString();
|
||||||
|
|
@ -529,7 +518,7 @@ public final class UriComponents implements Map<UriComponents.Type, String> {
|
||||||
/**
|
/**
|
||||||
* Returns a {@code URI} from this {@code UriComponents} instance.
|
* Returns a {@code URI} from this {@code UriComponents} instance.
|
||||||
*
|
*
|
||||||
* @return the URI created from the given components
|
* @return the URI
|
||||||
*/
|
*/
|
||||||
public URI toUri() {
|
public URI toUri() {
|
||||||
try {
|
try {
|
||||||
|
|
@ -537,13 +526,8 @@ public final class UriComponents implements Map<UriComponents.Type, String> {
|
||||||
return new URI(toUriString());
|
return new URI(toUriString());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (getUserInfo() != null || getHost() != null || getPort() != null) {
|
return new URI(getScheme(), getUserInfo(), getHost(), getPort(), getPath(), getQuery(),
|
||||||
return new URI(getScheme(), getUserInfo(), getHost(), getPortAsInteger(), getPath(), getQuery(),
|
getFragment());
|
||||||
getFragment());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return new URI(getScheme(), getAuthority(), getPath(), getQuery(), getFragment());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (URISyntaxException ex) {
|
catch (URISyntaxException ex) {
|
||||||
|
|
@ -551,76 +535,57 @@ public final class UriComponents implements Map<UriComponents.Type, String> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Map implementation
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (o instanceof UriComponents) {
|
||||||
|
UriComponents other = (UriComponents) o;
|
||||||
|
|
||||||
public int size() {
|
if (scheme != null ? !scheme.equals(other.scheme) : other.scheme != null) {
|
||||||
return this.uriComponents.size();
|
return false;
|
||||||
}
|
}
|
||||||
|
if (userInfo != null ? !userInfo.equals(other.userInfo) : other.userInfo != null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (host != null ? !host.equals(other.host) : other.host != null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (port != other.port) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!pathSegments.equals(other.pathSegments)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!queryParams.equals(other.queryParams)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (fragment != null ? !fragment.equals(other.fragment) : other.fragment != null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isEmpty() {
|
@Override
|
||||||
return this.uriComponents.isEmpty();
|
public int hashCode() {
|
||||||
}
|
int result = scheme != null ? scheme.hashCode() : 0;
|
||||||
|
result = 31 * result + (userInfo != null ? userInfo.hashCode() : 0);
|
||||||
|
result = 31 * result + (host != null ? host.hashCode() : 0);
|
||||||
|
result = 31 * result + port;
|
||||||
|
result = 31 * result + pathSegments.hashCode();
|
||||||
|
result = 31 * result + queryParams.hashCode();
|
||||||
|
result = 31 * result + (fragment != null ? fragment.hashCode() : 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean containsKey(Object key) {
|
@Override
|
||||||
return this.uriComponents.containsKey(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean containsValue(Object value) {
|
|
||||||
return this.uriComponents.containsValue(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String get(Object key) {
|
|
||||||
return this.uriComponents.get(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String put(Type key, String value) {
|
|
||||||
return this.uriComponents.put(key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String remove(Object key) {
|
|
||||||
return this.uriComponents.remove(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void putAll(Map<? extends Type, ? extends String> m) {
|
|
||||||
this.uriComponents.putAll(m);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clear() {
|
|
||||||
this.uriComponents.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Set<Type> keySet() {
|
|
||||||
return this.uriComponents.keySet();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Collection<String> values() {
|
|
||||||
return this.uriComponents.values();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Set<Entry<Type, String>> entrySet() {
|
|
||||||
return this.uriComponents.entrySet();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (o instanceof UriComponents) {
|
|
||||||
UriComponents other = (UriComponents) o;
|
|
||||||
return this.uriComponents.equals(other.uriComponents);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return this.uriComponents.hashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return this.uriComponents.toString();
|
return toUriString();
|
||||||
}
|
}
|
||||||
|
|
||||||
// inner types
|
// inner types
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,12 @@ import java.net.URI;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.LinkedMultiValueMap;
|
||||||
|
import org.springframework.util.MultiValueMap;
|
||||||
import org.springframework.util.ObjectUtils;
|
import org.springframework.util.ObjectUtils;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
|
@ -49,6 +53,34 @@ public class UriComponentsBuilder {
|
||||||
|
|
||||||
private static final char PATH_DELIMITER = '/';
|
private static final char PATH_DELIMITER = '/';
|
||||||
|
|
||||||
|
private static final Pattern QUERY_PARAM_PATTERN = Pattern.compile("([^&=]+)=?([^&=]+)?");
|
||||||
|
|
||||||
|
private static final String SCHEME_PATTERN = "([^:/?#]+):";
|
||||||
|
|
||||||
|
private static final String HTTP_PATTERN = "(http|https):";
|
||||||
|
|
||||||
|
private static final String USERINFO_PATTERN = "([^@/]*)";
|
||||||
|
|
||||||
|
private static final String HOST_PATTERN = "([^/?#:]*)";
|
||||||
|
|
||||||
|
private static final String PORT_PATTERN = "(\\d*)";
|
||||||
|
|
||||||
|
private static final String PATH_PATTERN = "([^?#]*)";
|
||||||
|
|
||||||
|
private static final String QUERY_PATTERN = "([^#]*)";
|
||||||
|
|
||||||
|
private static final String LAST_PATTERN = "(.*)";
|
||||||
|
|
||||||
|
// Regex patterns that matches URIs. See RFC 3986, appendix B
|
||||||
|
private static final Pattern URI_PATTERN = Pattern.compile(
|
||||||
|
"^(" + SCHEME_PATTERN + ")?" + "(//(" + USERINFO_PATTERN + "@)?" + HOST_PATTERN + "(:" + PORT_PATTERN +
|
||||||
|
")?" + ")?" + PATH_PATTERN + "(\\?" + QUERY_PATTERN + ")?" + "(#" + LAST_PATTERN + ")?");
|
||||||
|
|
||||||
|
private static final Pattern HTTP_URL_PATTERN = Pattern.compile(
|
||||||
|
"^" + HTTP_PATTERN + "(//(" + USERINFO_PATTERN + "@)?" + HOST_PATTERN + "(:" + PORT_PATTERN + ")?" + ")?" +
|
||||||
|
PATH_PATTERN + "(\\?" + LAST_PATTERN + ")?");
|
||||||
|
|
||||||
|
|
||||||
private String scheme;
|
private String scheme;
|
||||||
|
|
||||||
private String userInfo;
|
private String userInfo;
|
||||||
|
|
@ -59,7 +91,7 @@ public class UriComponentsBuilder {
|
||||||
|
|
||||||
private final List<String> pathSegments = new ArrayList<String>();
|
private final List<String> pathSegments = new ArrayList<String>();
|
||||||
|
|
||||||
private final StringBuilder queryBuilder = new StringBuilder();
|
private final MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<String, String>();
|
||||||
|
|
||||||
private String fragment;
|
private String fragment;
|
||||||
|
|
||||||
|
|
@ -76,7 +108,7 @@ public class UriComponentsBuilder {
|
||||||
// Factory methods
|
// Factory methods
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a new, empty URI builder.
|
* Returns a new, empty builder.
|
||||||
*
|
*
|
||||||
* @return the new {@code UriComponentsBuilder}
|
* @return the new {@code UriComponentsBuilder}
|
||||||
*/
|
*/
|
||||||
|
|
@ -85,7 +117,7 @@ public class UriComponentsBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a URI builder that is initialized with the given path.
|
* Returns a builder that is initialized with the given path.
|
||||||
*
|
*
|
||||||
* @param path the path to initialize with
|
* @param path the path to initialize with
|
||||||
* @return the new {@code UriComponentsBuilder}
|
* @return the new {@code UriComponentsBuilder}
|
||||||
|
|
@ -97,7 +129,7 @@ public class UriComponentsBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a URI builder that is initialized with the given {@code URI}.
|
* Returns a builder that is initialized with the given {@code URI}.
|
||||||
*
|
*
|
||||||
* @param uri the URI to initialize with
|
* @param uri the URI to initialize with
|
||||||
* @return the new {@code UriComponentsBuilder}
|
* @return the new {@code UriComponentsBuilder}
|
||||||
|
|
@ -108,6 +140,67 @@ public class UriComponentsBuilder {
|
||||||
return builder;
|
return builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a builder that is initialized with the given URI string.
|
||||||
|
*
|
||||||
|
* @param uri the URI string to initialize with
|
||||||
|
* @return the new {@code UriComponentsBuilder}
|
||||||
|
*/
|
||||||
|
public static UriComponentsBuilder fromUriString(String uri) {
|
||||||
|
Assert.hasLength(uri, "'uri' must not be empty");
|
||||||
|
Matcher m = URI_PATTERN.matcher(uri);
|
||||||
|
if (m.matches()) {
|
||||||
|
UriComponentsBuilder builder = new UriComponentsBuilder();
|
||||||
|
|
||||||
|
builder.scheme(m.group(2));
|
||||||
|
builder.userInfo(m.group(5));
|
||||||
|
builder.host(m.group(6));
|
||||||
|
String port = m.group(8);
|
||||||
|
if (StringUtils.hasLength(port)) {
|
||||||
|
builder.port(Integer.parseInt(port));
|
||||||
|
}
|
||||||
|
builder.path(m.group(9));
|
||||||
|
builder.query(m.group(11));
|
||||||
|
builder.fragment(m.group(13));
|
||||||
|
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new IllegalArgumentException("[" + uri + "] is not a valid URI");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@code UriComponents} object from the string HTTP URL.
|
||||||
|
*
|
||||||
|
* @param httpUrl the source URI
|
||||||
|
* @return the URI components of the URI
|
||||||
|
*/
|
||||||
|
public static UriComponentsBuilder fromHttpUrl(String httpUrl) {
|
||||||
|
Assert.notNull(httpUrl, "'httpUrl' must not be null");
|
||||||
|
Matcher m = HTTP_URL_PATTERN.matcher(httpUrl);
|
||||||
|
if (m.matches()) {
|
||||||
|
UriComponentsBuilder builder = new UriComponentsBuilder();
|
||||||
|
|
||||||
|
builder.scheme(m.group(1));
|
||||||
|
builder.userInfo(m.group(4));
|
||||||
|
builder.host(m.group(5));
|
||||||
|
String port = m.group(7);
|
||||||
|
if (StringUtils.hasLength(port)) {
|
||||||
|
builder.port(Integer.parseInt(port));
|
||||||
|
}
|
||||||
|
builder.path(m.group(8));
|
||||||
|
builder.query(m.group(10));
|
||||||
|
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new IllegalArgumentException("[" + httpUrl + "] is not a valid HTTP URL");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// build methods
|
// build methods
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -116,12 +209,19 @@ public class UriComponentsBuilder {
|
||||||
* @return the URI components
|
* @return the URI components
|
||||||
*/
|
*/
|
||||||
public UriComponents build() {
|
public UriComponents build() {
|
||||||
String port = portAsString();
|
return build(false);
|
||||||
String path = pathAsString();
|
}
|
||||||
String query = queryAsString();
|
|
||||||
return UriComponents.fromUriComponents(scheme, null, userInfo, host, port, path, query, fragment, false);
|
/**
|
||||||
|
* Builds a {@code UriComponents} instance from the various components contained in this builder.
|
||||||
|
*
|
||||||
|
* @param encoded whether all the components set in this builder are encoded ({@code true}) or not ({@code false}).
|
||||||
|
* @return the URI components
|
||||||
|
*/
|
||||||
|
public UriComponents build(boolean encoded) {
|
||||||
|
return new UriComponents(scheme, userInfo, host, port, pathSegments, queryParams, fragment, encoded);
|
||||||
}
|
}
|
||||||
|
|
||||||
// URI components methods
|
// URI components methods
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -146,14 +246,12 @@ public class UriComponentsBuilder {
|
||||||
this.port = uri.getPort();
|
this.port = uri.getPort();
|
||||||
}
|
}
|
||||||
if (StringUtils.hasLength(uri.getPath())) {
|
if (StringUtils.hasLength(uri.getPath())) {
|
||||||
String[] pathSegments = StringUtils.tokenizeToStringArray(uri.getPath(), "/");
|
|
||||||
|
|
||||||
this.pathSegments.clear();
|
this.pathSegments.clear();
|
||||||
Collections.addAll(this.pathSegments, pathSegments);
|
path(uri.getPath());
|
||||||
}
|
}
|
||||||
if (StringUtils.hasLength(uri.getQuery())) {
|
if (StringUtils.hasLength(uri.getQuery())) {
|
||||||
this.queryBuilder.setLength(0);
|
this.queryParams.clear();
|
||||||
this.queryBuilder.append(uri.getQuery());
|
query(uri.getQuery());
|
||||||
}
|
}
|
||||||
if (uri.getFragment() != null) {
|
if (uri.getFragment() != null) {
|
||||||
this.fragment = uri.getFragment();
|
this.fragment = uri.getFragment();
|
||||||
|
|
@ -220,36 +318,15 @@ public class UriComponentsBuilder {
|
||||||
* @return this UriComponentsBuilder
|
* @return this UriComponentsBuilder
|
||||||
*/
|
*/
|
||||||
public UriComponentsBuilder path(String path) {
|
public UriComponentsBuilder path(String path) {
|
||||||
Assert.notNull(path, "path must not be null");
|
if (path != null) {
|
||||||
|
String[] pathSegments = StringUtils.tokenizeToStringArray(path, "/");
|
||||||
String[] pathSegments = StringUtils.tokenizeToStringArray(path, "/");
|
pathSegment(pathSegments);
|
||||||
return pathSegment(pathSegments);
|
} else {
|
||||||
|
pathSegments.clear();
|
||||||
|
}
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String pathAsString() {
|
|
||||||
if (!pathSegments.isEmpty()) {
|
|
||||||
StringBuilder pathBuilder = new StringBuilder();
|
|
||||||
for (String pathSegment : pathSegments) {
|
|
||||||
boolean startsWithSlash = pathSegment.charAt(0) == PATH_DELIMITER;
|
|
||||||
boolean endsWithSlash =
|
|
||||||
pathBuilder.length() > 0 && pathBuilder.charAt(pathBuilder.length() - 1) == PATH_DELIMITER;
|
|
||||||
|
|
||||||
if (!endsWithSlash && !startsWithSlash) {
|
|
||||||
pathBuilder.append('/');
|
|
||||||
}
|
|
||||||
else if (endsWithSlash && startsWithSlash) {
|
|
||||||
pathSegment = pathSegment.substring(1);
|
|
||||||
}
|
|
||||||
pathBuilder.append(pathSegment);
|
|
||||||
}
|
|
||||||
return pathBuilder.toString();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Appends the given path segments to the existing path of this builder. Each given path segments may contain URI
|
* Appends the given path segments to the existing path of this builder. Each given path segments may contain URI
|
||||||
* template variables.
|
* template variables.
|
||||||
|
|
@ -264,6 +341,28 @@ public class UriComponentsBuilder {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Appends the given query to the existing query of this builder. The given query may contain URI template variables.
|
||||||
|
*
|
||||||
|
* @param query the URI path
|
||||||
|
* @return this UriComponentsBuilder
|
||||||
|
*/
|
||||||
|
public UriComponentsBuilder query(String query) {
|
||||||
|
if (query != null) {
|
||||||
|
Matcher m = QUERY_PARAM_PATTERN.matcher(query);
|
||||||
|
while (m.find()) {
|
||||||
|
String name = m.group(1);
|
||||||
|
String value = m.group(2);
|
||||||
|
queryParam(name, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
queryParams.clear();
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Appends the given query parameter to the existing query parameters. The given name or any of the values may contain
|
* Appends the given query parameter to the existing query parameters. The given name or any of the values may contain
|
||||||
* URI template variables. If no values are given, the resulting URI will contain the query parameter name only (i.e.
|
* URI template variables. If no values are given, the resulting URI will contain the query parameter name only (i.e.
|
||||||
|
|
@ -274,33 +373,18 @@ public class UriComponentsBuilder {
|
||||||
* @return this UriComponentsBuilder
|
* @return this UriComponentsBuilder
|
||||||
*/
|
*/
|
||||||
public UriComponentsBuilder queryParam(String name, Object... values) {
|
public UriComponentsBuilder queryParam(String name, Object... values) {
|
||||||
Assert.notNull(name, "'name' must not be null");
|
Assert.notNull(name, "'name' must not be null");
|
||||||
|
if (!ObjectUtils.isEmpty(values)) {
|
||||||
if (ObjectUtils.isEmpty(values)) {
|
for (Object value : values) {
|
||||||
if (queryBuilder.length() != 0) {
|
String valueAsString = value != null ? value.toString() : null;
|
||||||
queryBuilder.append('&');
|
queryParams.add(name, valueAsString);
|
||||||
}
|
}
|
||||||
queryBuilder.append(name);
|
}
|
||||||
}
|
else {
|
||||||
else {
|
queryParams.add(name, null);
|
||||||
for (Object value : values) {
|
}
|
||||||
if (queryBuilder.length() != 0) {
|
return this;
|
||||||
queryBuilder.append('&');
|
}
|
||||||
}
|
|
||||||
queryBuilder.append(name);
|
|
||||||
|
|
||||||
if (value != null) {
|
|
||||||
queryBuilder.append('=');
|
|
||||||
queryBuilder.append(value.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String queryAsString() {
|
|
||||||
return queryBuilder.length() != 0 ? queryBuilder.toString() : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the URI fragment. The given fragment may contain URI template variables, and may also be {@code null} to clear
|
* Sets the URI fragment. The given fragment may contain URI template variables, and may also be {@code null} to clear
|
||||||
|
|
|
||||||
|
|
@ -21,13 +21,10 @@ import java.io.UnsupportedEncodingException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.EnumMap;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
|
@ -70,18 +67,9 @@ public class UriTemplate implements Serializable {
|
||||||
this.uriTemplate = uriTemplate;
|
this.uriTemplate = uriTemplate;
|
||||||
this.variableNames = parser.getVariableNames();
|
this.variableNames = parser.getVariableNames();
|
||||||
this.matchPattern = parser.getMatchPattern();
|
this.matchPattern = parser.getMatchPattern();
|
||||||
this.uriComponents = UriComponents.fromUriString(uriTemplate);
|
this.uriComponents = UriComponentsBuilder.fromUriString(uriTemplate).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
public UriTemplate(Map<UriComponents.Type, String> uriComponents) {
|
|
||||||
this.uriComponents = UriComponents.fromUriComponentMap(uriComponents);
|
|
||||||
String uriTemplate = this.uriComponents.toUriString();
|
|
||||||
Parser parser = new Parser(uriTemplate);
|
|
||||||
this.uriTemplate = uriTemplate;
|
|
||||||
this.variableNames = parser.getVariableNames();
|
|
||||||
this.matchPattern = parser.getMatchPattern();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the names of the variables in the template, in order.
|
* Return the names of the variables in the template, in order.
|
||||||
* @return the template variable names
|
* @return the template variable names
|
||||||
|
|
@ -110,93 +98,11 @@ public class UriTemplate implements Serializable {
|
||||||
* or if it does not contain values for all the variable names
|
* or if it does not contain values for all the variable names
|
||||||
*/
|
*/
|
||||||
public URI expand(Map<String, ?> uriVariables) {
|
public URI expand(Map<String, ?> uriVariables) {
|
||||||
UriComponents expandedComponents = expandAsUriComponents(uriVariables, true);
|
UriComponents expandedComponents = uriComponents.expand(uriVariables);
|
||||||
return expandedComponents.toUri();
|
UriComponents encodedComponents = expandedComponents.encode();
|
||||||
|
return encodedComponents.toUri();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Given the Map of variables, expands this template into a URI. The Map keys represent variable names,
|
|
||||||
* the Map values variable values. The order of variables is not significant.
|
|
||||||
* <p>Example:
|
|
||||||
* <pre class="code">
|
|
||||||
* UriTemplate template = new UriTemplate("http://example.com/hotels/{hotel}/bookings/{booking}");
|
|
||||||
* Map<String, String> uriVariables = new HashMap<String, String>();
|
|
||||||
* uriVariables.put("booking", "42");
|
|
||||||
* uriVariables.put("hotel", "1");
|
|
||||||
* System.out.println(template.expand(uriVariables));
|
|
||||||
* </pre>
|
|
||||||
* will print: <blockquote><code>http://example.com/hotels/1/bookings/42</code></blockquote>
|
|
||||||
*
|
|
||||||
* @param uriVariables the map of URI variables
|
|
||||||
* @return the expanded URI
|
|
||||||
* @throws IllegalArgumentException if <code>uriVariables</code> is <code>null</code>;
|
|
||||||
* or if it does not contain values for all the variable names
|
|
||||||
*/
|
|
||||||
public String expandAsString(final Map<String, ?> uriVariables, boolean encode) {
|
|
||||||
UriComponents expandedComponents = expandAsUriComponents(uriVariables, encode);
|
|
||||||
return expandedComponents.toUriString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public UriComponents expandAsUriComponents(final Map<String, ?> uriVariables, boolean encode) {
|
|
||||||
Assert.notNull(uriVariables, "'uriVariables' must not be null");
|
|
||||||
Set<String> variablesSet = new HashSet<String>(this.variableNames);
|
|
||||||
variablesSet.removeAll(uriVariables.keySet());
|
|
||||||
Assert.isTrue(variablesSet.isEmpty(),
|
|
||||||
"'uriVariables' does not contain keys for all variables: " + variablesSet);
|
|
||||||
|
|
||||||
Map<UriComponents.Type, String> expandedComponents = new EnumMap<UriComponents.Type, String>(UriComponents.Type.class);
|
|
||||||
|
|
||||||
for (Map.Entry<UriComponents.Type, String> entry : this.uriComponents.entrySet()) {
|
|
||||||
UriComponents.Type key = entry.getKey();
|
|
||||||
String value = entry.getValue();
|
|
||||||
String expandedValue = expandUriComponent(key, value, uriVariables);
|
|
||||||
expandedComponents.put(key, expandedValue);
|
|
||||||
}
|
|
||||||
UriComponents result = UriComponents.fromUriComponentMap(expandedComponents);
|
|
||||||
if (encode) {
|
|
||||||
result = result.encode();
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String expandUriComponent(UriComponents.Type componentType, String value, Map<String, ?> uriVariables) {
|
|
||||||
if (value == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (value.indexOf('{') == -1) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
Matcher matcher = NAMES_PATTERN.matcher(value);
|
|
||||||
StringBuffer sb = new StringBuffer();
|
|
||||||
while (matcher.find()) {
|
|
||||||
String match = matcher.group(1);
|
|
||||||
String variableName = getVariableName(match);
|
|
||||||
Object variableValue = uriVariables.get(variableName);
|
|
||||||
String uriVariableValueString = getVariableValueAsString(variableValue);
|
|
||||||
String replacement = Matcher.quoteReplacement(uriVariableValueString);
|
|
||||||
matcher.appendReplacement(sb, replacement);
|
|
||||||
}
|
|
||||||
matcher.appendTail(sb);
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getVariableName(String match) {
|
|
||||||
int colonIdx = match.indexOf(':');
|
|
||||||
return colonIdx == -1 ? match : match.substring(0, colonIdx);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Template method that returns the string representation of the given URI template value.
|
|
||||||
*
|
|
||||||
* <p>Defaults implementation simply calls {@link Object#toString()}, or returns an empty string for {@code null}.
|
|
||||||
*
|
|
||||||
* @param variableValue the URI template variable value
|
|
||||||
* @return the variable value as string
|
|
||||||
*/
|
|
||||||
protected String getVariableValueAsString(Object variableValue) {
|
|
||||||
return variableValue != null ? variableValue.toString() : "";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given an array of variables, expand this template into a full URI. The array represent variable values.
|
* Given an array of variables, expand this template into a full URI. The array represent variable values.
|
||||||
* The order of variables is significant.
|
* The order of variables is significant.
|
||||||
|
|
@ -212,50 +118,11 @@ public class UriTemplate implements Serializable {
|
||||||
* or if it does not contain sufficient variables
|
* or if it does not contain sufficient variables
|
||||||
*/
|
*/
|
||||||
public URI expand(Object... uriVariableValues) {
|
public URI expand(Object... uriVariableValues) {
|
||||||
UriComponents expandedComponents = expandAsUriComponents(uriVariableValues, true);
|
UriComponents expandedComponents = uriComponents.expand(uriVariableValues);
|
||||||
return expandedComponents.toUri();
|
UriComponents encodedComponents = expandedComponents.encode();
|
||||||
|
return encodedComponents.toUri();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Given an array of variables, expand this template into a full URI String. The array represent variable values.
|
|
||||||
* The order of variables is significant.
|
|
||||||
* <p>Example:
|
|
||||||
* <pre class="code">
|
|
||||||
* UriTemplate template = new UriTemplate("http://example.com/hotels/{hotel}/bookings/{booking}");
|
|
||||||
* System.out.println(template.expand("1", "42));
|
|
||||||
* </pre>
|
|
||||||
* will print: <blockquote><code>http://example.com/hotels/1/bookings/42</code></blockquote>
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param uriVariableValues the array of URI variables
|
|
||||||
* @return the expanded URI
|
|
||||||
* @throws IllegalArgumentException if <code>uriVariables</code> is <code>null</code>
|
|
||||||
* or if it does not contain sufficient variables
|
|
||||||
*/
|
|
||||||
public String expandAsString(boolean encode, Object[] uriVariableValues) {
|
|
||||||
UriComponents expandedComponents = expandAsUriComponents(uriVariableValues, encode);
|
|
||||||
return expandedComponents.toUriString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public UriComponents expandAsUriComponents(Object[] uriVariableValues, boolean encode) {
|
|
||||||
Assert.notNull(uriVariableValues, "'uriVariableValues' must not be null");
|
|
||||||
if (uriVariableValues.length < this.variableNames.size()) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"Not enough of variables values in [" + this.uriTemplate + "]: expected at least " +
|
|
||||||
this.variableNames.size() + "; got " + uriVariableValues.length);
|
|
||||||
}
|
|
||||||
Map<String, Object> uriVariables = new LinkedHashMap<String, Object>(this.variableNames.size());
|
|
||||||
|
|
||||||
for (int i = 0, size = variableNames.size(); i < size; i++) {
|
|
||||||
String variableName = variableNames.get(i);
|
|
||||||
Object variableValue = uriVariableValues[i];
|
|
||||||
uriVariables.put(variableName, variableValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
return expandAsUriComponents(uriVariables, encode);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// matching
|
// matching
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -302,7 +169,9 @@ public class UriTemplate implements Serializable {
|
||||||
* <p>Defaults to {@link UriUtils#encodeUri(String, String)}.
|
* <p>Defaults to {@link UriUtils#encodeUri(String, String)}.
|
||||||
* @param uri the URI to encode
|
* @param uri the URI to encode
|
||||||
* @return the encoded URI
|
* @return the encoded URI
|
||||||
|
* @deprecated No longer in use, with no direct replacement
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
protected URI encodeUri(String uri) {
|
protected URI encodeUri(String uri) {
|
||||||
try {
|
try {
|
||||||
String encoded = UriUtils.encodeUri(uri, "UTF-8");
|
String encoded = UriUtils.encodeUri(uri, "UTF-8");
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,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 encodeUri(String uri, String encoding) throws UnsupportedEncodingException {
|
public static String encodeUri(String uri, String encoding) throws UnsupportedEncodingException {
|
||||||
UriComponents uriComponents = UriComponents.fromUriString(uri);
|
UriComponents uriComponents = UriComponentsBuilder.fromUriString(uri).build();
|
||||||
UriComponents encoded = uriComponents.encode(encoding);
|
UriComponents encoded = uriComponents.encode(encoding);
|
||||||
return encoded.toUriString();
|
return encoded.toUriString();
|
||||||
}
|
}
|
||||||
|
|
@ -68,7 +68,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 encodeHttpUrl(String httpUrl, String encoding) throws UnsupportedEncodingException {
|
public static String encodeHttpUrl(String httpUrl, String encoding) throws UnsupportedEncodingException {
|
||||||
UriComponents uriComponents = UriComponents.fromHttpUrl(httpUrl);
|
UriComponents uriComponents = UriComponentsBuilder.fromHttpUrl(httpUrl).build();
|
||||||
UriComponents encoded = uriComponents.encode(encoding);
|
UriComponents encoded = uriComponents.encode(encoding);
|
||||||
return encoded.toUriString();
|
return encoded.toUriString();
|
||||||
}
|
}
|
||||||
|
|
@ -99,8 +99,13 @@ public abstract class UriUtils {
|
||||||
String query,
|
String query,
|
||||||
String fragment,
|
String fragment,
|
||||||
String encoding) throws UnsupportedEncodingException {
|
String encoding) throws UnsupportedEncodingException {
|
||||||
UriComponents uriComponents = UriComponents.fromUriComponents(scheme, authority, userInfo, host, port, path, query, fragment);
|
int portAsInt = port != null ? Integer.parseInt(port) : -1;
|
||||||
UriComponents encoded = uriComponents.encode(encoding);
|
|
||||||
|
UriComponentsBuilder builder = UriComponentsBuilder.newInstance();
|
||||||
|
builder.scheme(scheme).userInfo(userInfo).host(host).port(portAsInt);
|
||||||
|
builder.path(path).query(query).fragment(fragment);
|
||||||
|
|
||||||
|
UriComponents encoded = builder.build().encode(encoding);
|
||||||
|
|
||||||
return encoded.toUriString();
|
return encoded.toUriString();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,10 +18,14 @@ package org.springframework.web.util;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import org.springframework.util.LinkedMultiValueMap;
|
||||||
|
import org.springframework.util.MultiValueMap;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
/** @author Arjen Poutsma */
|
/** @author Arjen Poutsma */
|
||||||
public class UriComponentsBuilderTests {
|
public class UriComponentsBuilderTests {
|
||||||
|
|
@ -71,40 +75,90 @@ public class UriComponentsBuilderTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void pathSegments() throws URISyntaxException {
|
public void fromUriString() {
|
||||||
UriComponentsBuilder builder = UriComponentsBuilder.newInstance();
|
UriComponents result = UriComponentsBuilder.fromUriString("http://www.ietf.org/rfc/rfc3986.txt").build();
|
||||||
URI result = builder.pathSegment("foo").pathSegment("bar").build().toUri();
|
assertEquals("http", result.getScheme());
|
||||||
|
assertNull(result.getUserInfo());
|
||||||
|
assertEquals("www.ietf.org", result.getHost());
|
||||||
|
assertEquals(-1, result.getPort());
|
||||||
|
assertEquals("/rfc/rfc3986.txt", result.getPath());
|
||||||
|
assertEquals(Arrays.asList("rfc", "rfc3986.txt"), result.getPathSegments());
|
||||||
|
assertNull(result.getQuery());
|
||||||
|
assertNull(result.getFragment());
|
||||||
|
|
||||||
URI expected = new URI("/foo/bar");
|
result = UriComponentsBuilder.fromUriString(
|
||||||
assertEquals("Invalid result URI", expected, result);
|
"http://arjen:foobar@java.sun.com:80/javase/6/docs/api/java/util/BitSet.html?foo=bar#and(java.util.BitSet)")
|
||||||
|
.build();
|
||||||
|
assertEquals("http", result.getScheme());
|
||||||
|
assertEquals("arjen:foobar", result.getUserInfo());
|
||||||
|
assertEquals("java.sun.com", result.getHost());
|
||||||
|
assertEquals(80, result.getPort());
|
||||||
|
assertEquals("/javase/6/docs/api/java/util/BitSet.html", result.getPath());
|
||||||
|
assertEquals("foo=bar", result.getQuery());
|
||||||
|
MultiValueMap<String, String> expectedQueryParams = new LinkedMultiValueMap<String, String>(1);
|
||||||
|
expectedQueryParams.add("foo", "bar");
|
||||||
|
assertEquals(expectedQueryParams, result.getQueryParams());
|
||||||
|
assertEquals("and(java.util.BitSet)", result.getFragment());
|
||||||
|
|
||||||
|
result = UriComponentsBuilder.fromUriString("mailto:java-net@java.sun.com").build();
|
||||||
|
assertEquals("mailto", result.getScheme());
|
||||||
|
assertNull(result.getUserInfo());
|
||||||
|
assertNull(result.getHost());
|
||||||
|
assertEquals(-1, result.getPort());
|
||||||
|
assertEquals("java-net@java.sun.com", result.getPathSegments().get(0));
|
||||||
|
assertNull(result.getQuery());
|
||||||
|
assertNull(result.getFragment());
|
||||||
|
|
||||||
|
result = UriComponentsBuilder.fromUriString("docs/guide/collections/designfaq.html#28").build();
|
||||||
|
assertNull(result.getScheme());
|
||||||
|
assertNull(result.getUserInfo());
|
||||||
|
assertNull(result.getHost());
|
||||||
|
assertEquals(-1, result.getPort());
|
||||||
|
assertEquals("/docs/guide/collections/designfaq.html", result.getPath());
|
||||||
|
assertNull(result.getQuery());
|
||||||
|
assertEquals("28", result.getFragment());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void path() throws URISyntaxException {
|
||||||
|
UriComponentsBuilder builder = UriComponentsBuilder.fromPath("/foo/bar");
|
||||||
|
UriComponents result = builder.build();
|
||||||
|
|
||||||
|
assertEquals("/foo/bar", result.getPath());
|
||||||
|
assertEquals(Arrays.asList("foo", "bar"), result.getPathSegments());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void queryParam() throws URISyntaxException {
|
public void pathSegments() throws URISyntaxException {
|
||||||
UriComponentsBuilder builder = UriComponentsBuilder.newInstance();
|
UriComponentsBuilder builder = UriComponentsBuilder.newInstance();
|
||||||
URI result = builder.queryParam("baz", "qux", 42).build().toUri();
|
UriComponents result = builder.pathSegment("foo").pathSegment("bar").build();
|
||||||
|
|
||||||
URI expected = new URI("?baz=qux&baz=42");
|
assertEquals("/foo/bar", result.getPath());
|
||||||
assertEquals("Invalid result URI", expected, result);
|
assertEquals(Arrays.asList("foo", "bar"), result.getPathSegments());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void queryParams() throws URISyntaxException {
|
||||||
|
UriComponentsBuilder builder = UriComponentsBuilder.newInstance();
|
||||||
|
UriComponents result = builder.queryParam("baz", "qux", 42).build();
|
||||||
|
|
||||||
|
assertEquals("baz=qux&baz=42", result.getQuery());
|
||||||
|
MultiValueMap<String, String> expectedQueryParams = new LinkedMultiValueMap<String, String>(2);
|
||||||
|
expectedQueryParams.add("baz", "qux");
|
||||||
|
expectedQueryParams.add("baz", "42");
|
||||||
|
assertEquals(expectedQueryParams, result.getQueryParams());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void emptyQueryParam() throws URISyntaxException {
|
public void emptyQueryParam() throws URISyntaxException {
|
||||||
UriComponentsBuilder builder = UriComponentsBuilder.newInstance();
|
UriComponentsBuilder builder = UriComponentsBuilder.newInstance();
|
||||||
URI result = builder.queryParam("baz").build().toUri();
|
UriComponents result = builder.queryParam("baz").build();
|
||||||
|
|
||||||
URI expected = new URI("?baz");
|
assertEquals("baz", result.getQuery());
|
||||||
assertEquals("Invalid result URI", expected, result);
|
MultiValueMap<String, String> expectedQueryParams = new LinkedMultiValueMap<String, String>(2);
|
||||||
|
expectedQueryParams.add("baz", null);
|
||||||
|
assertEquals(expectedQueryParams, result.getQueryParams());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void combineWithUriTemplate() throws URISyntaxException {
|
|
||||||
UriComponentsBuilder builder = UriComponentsBuilder.fromPath("/{foo}");
|
|
||||||
UriComponents components = builder.build();
|
|
||||||
UriTemplate template = new UriTemplate(components);
|
|
||||||
URI uri = template.expand("bar baz");
|
|
||||||
assertEquals(new URI("/bar%20baz"), uri);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,102 +18,32 @@ package org.springframework.web.util;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.springframework.util.LinkedMultiValueMap;
|
|
||||||
import org.springframework.util.MultiValueMap;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.*;
|
||||||
import static org.junit.Assert.assertNull;
|
|
||||||
|
|
||||||
/** @author Arjen Poutsma */
|
/** @author Arjen Poutsma */
|
||||||
public class UriComponentsTests {
|
public class UriComponentsTests {
|
||||||
|
|
||||||
@Test
|
|
||||||
public void fromUri() {
|
|
||||||
Map<UriComponents.Type, String> result = UriComponents.fromUriString("http://www.ietf.org/rfc/rfc3986.txt");
|
|
||||||
assertEquals("http", result.get(UriComponents.Type.SCHEME));
|
|
||||||
assertNull(result.get(UriComponents.Type.USER_INFO));
|
|
||||||
assertEquals("www.ietf.org", result.get(UriComponents.Type.HOST));
|
|
||||||
assertNull(result.get(UriComponents.Type.PORT));
|
|
||||||
assertEquals("/rfc/rfc3986.txt", result.get(UriComponents.Type.PATH));
|
|
||||||
assertNull(result.get(UriComponents.Type.QUERY));
|
|
||||||
assertNull(result.get(UriComponents.Type.FRAGMENT));
|
|
||||||
|
|
||||||
result = UriComponents.fromUriString(
|
|
||||||
"http://arjen:foobar@java.sun.com:80/javase/6/docs/api/java/util/BitSet.html?foo=bar#and(java.util.BitSet)");
|
|
||||||
assertEquals("http", result.get(UriComponents.Type.SCHEME));
|
|
||||||
assertEquals("arjen:foobar", result.get(UriComponents.Type.USER_INFO));
|
|
||||||
assertEquals("java.sun.com", result.get(UriComponents.Type.HOST));
|
|
||||||
assertEquals("80", result.get(UriComponents.Type.PORT));
|
|
||||||
assertEquals("/javase/6/docs/api/java/util/BitSet.html", result.get(UriComponents.Type.PATH));
|
|
||||||
assertEquals("foo=bar", result.get(UriComponents.Type.QUERY));
|
|
||||||
assertEquals("and(java.util.BitSet)", result.get(UriComponents.Type.FRAGMENT));
|
|
||||||
|
|
||||||
result = UriComponents.fromUriString("mailto:java-net@java.sun.com");
|
|
||||||
assertEquals("mailto", result.get(UriComponents.Type.SCHEME));
|
|
||||||
assertNull(result.get(UriComponents.Type.USER_INFO));
|
|
||||||
assertNull(result.get(UriComponents.Type.HOST));
|
|
||||||
assertNull(result.get(UriComponents.Type.PORT));
|
|
||||||
assertEquals("java-net@java.sun.com", result.get(UriComponents.Type.PATH));
|
|
||||||
assertNull(result.get(UriComponents.Type.QUERY));
|
|
||||||
assertNull(result.get(UriComponents.Type.FRAGMENT));
|
|
||||||
|
|
||||||
result = UriComponents.fromUriString("docs/guide/collections/designfaq.html#28");
|
|
||||||
assertNull(result.get(UriComponents.Type.SCHEME));
|
|
||||||
assertNull(result.get(UriComponents.Type.USER_INFO));
|
|
||||||
assertNull(result.get(UriComponents.Type.HOST));
|
|
||||||
assertNull(result.get(UriComponents.Type.PORT));
|
|
||||||
assertEquals("docs/guide/collections/designfaq.html", result.get(UriComponents.Type.PATH));
|
|
||||||
assertNull(result.get(UriComponents.Type.QUERY));
|
|
||||||
assertEquals("28", result.get(UriComponents.Type.FRAGMENT));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void pathSegments() {
|
|
||||||
String path = "/foo/bar";
|
|
||||||
UriComponents components = UriComponents.fromUriComponentMap(Collections.singletonMap(UriComponents.Type.PATH, path));
|
|
||||||
List<String> expected = Arrays.asList("foo", "bar");
|
|
||||||
|
|
||||||
List<String> pathSegments = components.getPathSegments();
|
|
||||||
assertEquals(expected, pathSegments);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void queryParams() {
|
|
||||||
String query = "foo=bar&foo=baz&qux";
|
|
||||||
UriComponents components = UriComponents.fromUriComponentMap(
|
|
||||||
Collections.singletonMap(UriComponents.Type.QUERY, query));
|
|
||||||
MultiValueMap<String, String> expected = new LinkedMultiValueMap<String, String>(1);
|
|
||||||
expected.put("foo", Arrays.asList("bar", "baz"));
|
|
||||||
expected.set("qux", null);
|
|
||||||
|
|
||||||
MultiValueMap<String, String> result = components.getQueryParams();
|
|
||||||
assertEquals(expected, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void encode() {
|
public void encode() {
|
||||||
UriComponents uriComponents = UriComponents.fromUriString("http://example.com/hotel list");
|
UriComponents uriComponents = UriComponentsBuilder.fromPath("/hotel list").build();
|
||||||
UriComponents encoded = uriComponents.encode();
|
UriComponents encoded = uriComponents.encode();
|
||||||
assertEquals("/hotel%20list", encoded.getPath());
|
assertEquals("/hotel%20list", encoded.getPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void toUriEncoded() throws URISyntaxException {
|
public void toUriEncoded() throws URISyntaxException {
|
||||||
UriComponents uriComponents = UriComponents.fromUriString("http://example.com/hotel list/Z\u00fcrich");
|
UriComponents uriComponents = UriComponentsBuilder.fromUriString("http://example.com/hotel list/Z\u00fcrich").build();
|
||||||
UriComponents encoded = uriComponents.encode();
|
UriComponents encoded = uriComponents.encode();
|
||||||
assertEquals(new URI("http://example.com/hotel%20list/Z%C3%BCrich"), encoded.toUri());
|
assertEquals(new URI("http://example.com/hotel%20list/Z%C3%BCrich"), encoded.toUri());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void toUriNotEncoded() throws URISyntaxException {
|
public void toUriNotEncoded() throws URISyntaxException {
|
||||||
UriComponents uriComponents = UriComponents.fromUriString("http://example.com/hotel list/Z\u00fcrich");
|
UriComponents uriComponents = UriComponentsBuilder.fromUriString("http://example.com/hotel list/Z\u00fcrich").build();
|
||||||
assertEquals(new URI("http://example.com/hotel%20list/Z\u00fcrich"), uriComponents.toUri());
|
assertEquals(new URI("http://example.com/hotel%20list/Z\u00fcrich"), uriComponents.toUri());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -89,22 +89,6 @@ public class UriTemplateTests {
|
||||||
assertEquals("Invalid expanded template", new URI("http://example.com/hotel%20list/Z%C3%BCrich"), result);
|
assertEquals("Invalid expanded template", new URI("http://example.com/hotel%20list/Z%C3%BCrich"), result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
|
||||||
public void expandMapInvalidAmountVariables() throws Exception {
|
|
||||||
UriTemplate template = new UriTemplate("http://example.com/hotels/{hotel}/bookings/{booking}");
|
|
||||||
template.expand(Collections.singletonMap("hotel", "1"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
|
||||||
public void expandMapUnboundVariables() throws Exception {
|
|
||||||
Map<String, String> uriVariables = new HashMap<String, String>(2);
|
|
||||||
uriVariables.put("booking", "42");
|
|
||||||
uriVariables.put("bar", "1");
|
|
||||||
UriTemplate template = new UriTemplate("http://example.com/hotels/{hotel}/bookings/{booking}");
|
|
||||||
template.expand(uriVariables);
|
|
||||||
}
|
|
||||||
|
|
||||||
@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}");
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ import java.io.UnsupportedEncodingException;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Arjen Poutsma
|
* @author Arjen Poutsma
|
||||||
|
|
@ -111,23 +111,19 @@ public class UriUtilsTests {
|
||||||
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%C3%BCrich",
|
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(
|
||||||
"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)",
|
||||||
ENC));
|
ENC));
|
||||||
assertEquals("Invalid encoded URI", "mailto:java-net@java.sun.com",
|
assertEquals("Invalid encoded URI", "http://java.sun.com/j2se/1.3",
|
||||||
UriUtils.encodeUri("mailto:java-net@java.sun.com", ENC));
|
UriUtils.encodeUri("http://java.sun.com/j2se/1.3", ENC));
|
||||||
assertEquals("Invalid encoded URI", "news:comp.lang.java", UriUtils.encodeUri("news:comp.lang.java", ENC));
|
assertEquals("Invalid encoded URI", "/docs/guide/collections/designfaq.html#28",
|
||||||
assertEquals("Invalid encoded URI", "urn:isbn:096139210x", UriUtils.encodeUri("urn:isbn:096139210x", ENC));
|
UriUtils.encodeUri("/docs/guide/collections/designfaq.html#28", ENC));
|
||||||
assertEquals("Invalid encoded URI", "http://java.sun.com/j2se/1.3/",
|
assertEquals("Invalid encoded URI", "/../../../demo/jfc/SwingSet2/src/SwingSet2.java",
|
||||||
UriUtils.encodeUri("http://java.sun.com/j2se/1.3/", ENC));
|
UriUtils.encodeUri("/../../../demo/jfc/SwingSet2/src/SwingSet2.java", ENC));
|
||||||
assertEquals("Invalid encoded URI", "docs/guide/collections/designfaq.html#28",
|
|
||||||
UriUtils.encodeUri("docs/guide/collections/designfaq.html#28", ENC));
|
|
||||||
assertEquals("Invalid encoded URI", "../../../demo/jfc/SwingSet2/src/SwingSet2.java",
|
|
||||||
UriUtils.encodeUri("../../../demo/jfc/SwingSet2/src/SwingSet2.java", ENC));
|
|
||||||
assertEquals("Invalid encoded URI", "file:///~/calendar", UriUtils.encodeUri("file:///~/calendar", ENC));
|
assertEquals("Invalid encoded URI", "file:///~/calendar", UriUtils.encodeUri("file:///~/calendar", ENC));
|
||||||
assertEquals("Invalid encoded URI", "http://example.com/query=foo@bar",
|
assertEquals("Invalid encoded URI", "http://example.com/query=foo@bar",
|
||||||
UriUtils.encodeUri("http://example.com/query=foo@bar", ENC));
|
UriUtils.encodeUri("http://example.com/query=foo@bar", ENC));
|
||||||
|
|
@ -140,8 +136,8 @@ public class UriUtilsTests {
|
||||||
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%C3%BCrich",
|
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", "http://ws.geonames.org/searchJSON?q=T%C5%8Dky%C5%8D&style=FULL&maxRows=300",
|
assertEquals("Invalid encoded HTTP URL", "http://ws.geonames.org/searchJSON?q=T%C5%8Dky%C5%8D&style=FULL&maxRows=300",
|
||||||
UriUtils.encodeHttpUrl("http://ws.geonames.org/searchJSON?q=T\u014dky\u014d&style=FULL&maxRows=300", ENC));
|
UriUtils.encodeHttpUrl("http://ws.geonames.org/searchJSON?q=T\u014dky\u014d&style=FULL&maxRows=300", ENC));
|
||||||
assertEquals("Invalid encoded HTTP URL",
|
assertEquals("Invalid encoded HTTP URL",
|
||||||
|
|
@ -150,8 +146,8 @@ public class UriUtilsTests {
|
||||||
"http://arjen:foobar@java.sun.com:80/javase/6/docs/api/java/util/BitSet.html?foo=bar", ENC));
|
"http://arjen:foobar@java.sun.com:80/javase/6/docs/api/java/util/BitSet.html?foo=bar", ENC));
|
||||||
assertEquals("Invalid encoded HTTP URL", "http://search.twitter.com/search.atom?q=%23avatar",
|
assertEquals("Invalid encoded HTTP URL", "http://search.twitter.com/search.atom?q=%23avatar",
|
||||||
UriUtils.encodeHttpUrl("http://search.twitter.com/search.atom?q=#avatar", ENC));
|
UriUtils.encodeHttpUrl("http://search.twitter.com/search.atom?q=#avatar", ENC));
|
||||||
assertEquals("Invalid encoded HTTP URL", "http://java.sun.com/j2se/1.3/",
|
assertEquals("Invalid encoded HTTP URL", "http://java.sun.com/j2se/1.3",
|
||||||
UriUtils.encodeHttpUrl("http://java.sun.com/j2se/1.3/", ENC));
|
UriUtils.encodeHttpUrl("http://java.sun.com/j2se/1.3", ENC));
|
||||||
assertEquals("Invalid encoded HTTP URL", "http://example.com/query=foo@bar",
|
assertEquals("Invalid encoded HTTP URL", "http://example.com/query=foo@bar",
|
||||||
UriUtils.encodeHttpUrl("http://example.com/query=foo@bar", ENC));
|
UriUtils.encodeHttpUrl("http://example.com/query=foo@bar", ENC));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue