Additional convenience methods in UriUtils
The generic encode method in UriUtils that encodes any character outside the reserved character set for a URI is meant for "strict" encoding of URI variable values. This commit adds a couple more conveninence methods that accept a Map or array of URI variable values to encode. This facilitates the use case where the URI template is assumed to be encoded while URI variables are encoded strictly to avoid any possibility for unwanted reserved characters: Map<String, ?> encodedUriVars = UriUtils.encodeUriVariables(uriVars); uriComponentsBuilder.build(true).expand(encodedUriVars).toUri(); Issue: SPR-14970
This commit is contained in:
parent
f2e293aadf
commit
bb3b1f2fe2
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -16,10 +16,8 @@
|
|||
|
||||
package org.springframework.web.util;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -127,10 +125,7 @@ public class DefaultUriTemplateHandler extends AbstractUriTemplateHandler {
|
|||
return builder.buildAndExpand(uriVariables).encode();
|
||||
}
|
||||
else {
|
||||
Map<String, Object> encodedUriVars = new HashMap<>(uriVariables.size());
|
||||
for (Map.Entry<String, ?> entry : uriVariables.entrySet()) {
|
||||
encodedUriVars.put(entry.getKey(), applyStrictEncoding(entry.getValue()));
|
||||
}
|
||||
Map<String, ?> encodedUriVars = UriUtils.encodeUriVariables(uriVariables);
|
||||
return builder.buildAndExpand(encodedUriVars);
|
||||
}
|
||||
}
|
||||
|
@ -140,25 +135,11 @@ public class DefaultUriTemplateHandler extends AbstractUriTemplateHandler {
|
|||
return builder.buildAndExpand(uriVariables).encode();
|
||||
}
|
||||
else {
|
||||
Object[] encodedUriVars = new Object[uriVariables.length];
|
||||
for (int i = 0; i < uriVariables.length; i++) {
|
||||
encodedUriVars[i] = applyStrictEncoding(uriVariables[i]);
|
||||
}
|
||||
Object[] encodedUriVars = UriUtils.encodeUriVariables(uriVariables);
|
||||
return builder.buildAndExpand(encodedUriVars);
|
||||
}
|
||||
}
|
||||
|
||||
private String applyStrictEncoding(Object value) {
|
||||
String stringValue = (value != null ? value.toString() : "");
|
||||
try {
|
||||
return UriUtils.encode(stringValue, "UTF-8");
|
||||
}
|
||||
catch (UnsupportedEncodingException ex) {
|
||||
// Should never happen
|
||||
throw new IllegalStateException("Failed to encode URI variable", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private URI createUri(UriComponents uriComponents) {
|
||||
try {
|
||||
// Avoid further encoding (in the case of strictEncoding=true)
|
||||
|
|
|
@ -18,6 +18,11 @@ package org.springframework.web.util;
|
|||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
|
@ -165,6 +170,52 @@ public abstract class UriUtils {
|
|||
return HierarchicalUriComponents.encodeUriComponent(source, encoding, type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode characters outside the unreserved character set as defined in
|
||||
* <a href="https://tools.ietf.org/html/rfc3986#section-2">RFC 3986 Section 2</a>.
|
||||
* <p>This can be used to ensure the given String will not contain any
|
||||
* characters with reserved URI meaning regardless of URI component.
|
||||
* @param source the String to be encoded
|
||||
* @param charset the character encoding to encode to
|
||||
* @return the encoded String
|
||||
*/
|
||||
public static String encode(String source, Charset charset) {
|
||||
HierarchicalUriComponents.Type type = HierarchicalUriComponents.Type.URI;
|
||||
return HierarchicalUriComponents.encodeUriComponent(source, charset, type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply {@link #encode(String, String)} to the values in the given URI
|
||||
* variables and return a new Map containing the encoded values.
|
||||
* @param uriVariables the URI variable values to be encoded
|
||||
* @return the encoded String
|
||||
* @since 5.0
|
||||
*/
|
||||
public static Map<String, String> encodeUriVariables(Map<String, ?> uriVariables) {
|
||||
Map<String, String> result = new LinkedHashMap<>(uriVariables.size());
|
||||
uriVariables.entrySet().stream().forEach(entry -> {
|
||||
String stringValue = (entry.getValue() != null ? entry.getValue().toString() : "");
|
||||
result.put(entry.getKey(), encode(stringValue, StandardCharsets.UTF_8));
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply {@link #encode(String, String)} to the values in the given URI
|
||||
* variables and return a new array containing the encoded values.
|
||||
* @param uriVariables the URI variable values to be encoded
|
||||
* @return the encoded String
|
||||
* @since 5.0
|
||||
*/
|
||||
public static Object[] encodeUriVariables(Object... uriVariables) {
|
||||
return Arrays.stream(uriVariables)
|
||||
.map(value -> {
|
||||
String stringValue = (value != null ? value.toString() : "");
|
||||
return encode(stringValue, StandardCharsets.UTF_8);
|
||||
})
|
||||
.collect(Collectors.toList()).toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode the given encoded URI component.
|
||||
* <p>See {@link StringUtils#uriDecode(String, Charset) for the decoding rules.
|
||||
|
|
Loading…
Reference in New Issue