diff --git a/common/uri/src/main/java/io/helidon/common/uri/UriEncoding.java b/common/uri/src/main/java/io/helidon/common/uri/UriEncoding.java index 70a5e1f213e..f7abb5e1ce8 100644 --- a/common/uri/src/main/java/io/helidon/common/uri/UriEncoding.java +++ b/common/uri/src/main/java/io/helidon/common/uri/UriEncoding.java @@ -43,19 +43,27 @@ private UriEncoding() { /** * Decode a URI segment. + *
+ * Percent characters {@code "%s"} found between brackets {@code "[]"} are not decoded to support IPv6 literal. + * E.g. {@code http://[fe80::1%lo0]:8080}. + *
+ * See RFC 6874, section 2.
*
* @param uriSegment URI segment with percent encoding
* @return decoded string
*/
public static String decodeUri(String uriSegment) {
- if (uriSegment.isEmpty()) {
- return "";
- }
- if (uriSegment.indexOf('%') == -1 && uriSegment.indexOf('+') == -1) {
- return uriSegment;
- }
+ return decodeUri(uriSegment, true);
+ }
- return decode(uriSegment);
+ /**
+ * Decode a URI query.
+ *
+ * @param uriQuery URI query with percent encoding
+ * @return decoded string
+ */
+ public static String decodeQuery(String uriQuery) {
+ return decodeUri(uriQuery, false);
}
/**
@@ -123,7 +131,18 @@ private static void appendEscape(StringBuilder appender, int b) {
appender.append(HEX_DIGITS[b & 0x0F]);
}
- private static String decode(String string) {
+ private static String decodeUri(String uriSegment, boolean ignorePercentInBrackets) {
+ if (uriSegment.isEmpty()) {
+ return "";
+ }
+ if (uriSegment.indexOf('%') == -1 && uriSegment.indexOf('+') == -1) {
+ return uriSegment;
+ }
+ return decode(uriSegment, ignorePercentInBrackets);
+ }
+
+ // see java.net.URI.decode(String, boolean)
+ private static String decode(String string, boolean ignorePercentInBrackets) {
int len = string.length();
StringBuilder sb = new StringBuilder(len);
@@ -141,7 +160,7 @@ private static String decode(String string) {
} else if (betweenBrackets && c == ']') {
betweenBrackets = false;
}
- if (c != '%' || betweenBrackets) {
+ if (c != '%' || (betweenBrackets && ignorePercentInBrackets)) {
sb.append(c == '+' && !betweenBrackets ? ' ' : c); // handles '+' decoding
if (++i >= len) {
break;
diff --git a/common/uri/src/main/java/io/helidon/common/uri/UriQueryImpl.java b/common/uri/src/main/java/io/helidon/common/uri/UriQueryImpl.java
index dbe14f22650..fd6544cc808 100644
--- a/common/uri/src/main/java/io/helidon/common/uri/UriQueryImpl.java
+++ b/common/uri/src/main/java/io/helidon/common/uri/UriQueryImpl.java
@@ -31,7 +31,7 @@
import io.helidon.common.mapper.OptionalValue;
import io.helidon.common.mapper.Value;
-import static io.helidon.common.uri.UriEncoding.decodeUri;
+import static io.helidon.common.uri.UriEncoding.decodeQuery;
// must be lazily populated to prevent perf overhead when queries are ignored
final class UriQueryImpl implements UriQuery {
@@ -215,11 +215,11 @@ private void ensureDecoded() {
private void addDecoded(Map