From 35e8f1c42366a71169b2405e359a841f5e38b2ba Mon Sep 17 00:00:00 2001 From: Arjen Poutsma Date: Fri, 7 Jun 2024 10:55:53 +0200 Subject: [PATCH] Support queries in opaque URLs Closes gh-32920 --- .../web/util/UriComponentsBuilder.java | 3 ++- .../web/util/UriComponentsBuilderTests.java | 10 ++++++++ .../web/util/UrlParserTests.java | 23 +++++++++++++++++++ 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/spring-web/src/main/java/org/springframework/web/util/UriComponentsBuilder.java b/spring-web/src/main/java/org/springframework/web/util/UriComponentsBuilder.java index 171441ba13a..1a64481252d 100644 --- a/spring-web/src/main/java/org/springframework/web/util/UriComponentsBuilder.java +++ b/spring-web/src/main/java/org/springframework/web/util/UriComponentsBuilder.java @@ -236,7 +236,8 @@ public class UriComponentsBuilder implements UriBuilder, Cloneable { builder.port(urlRecord.port().toString()); } if (urlRecord.path().isOpaque()) { - builder.schemeSpecificPart(urlRecord.path().toString()); + String ssp = urlRecord.path() + urlRecord.search(); + builder.schemeSpecificPart(ssp); } else { builder.path(urlRecord.path().toString()); diff --git a/spring-web/src/test/java/org/springframework/web/util/UriComponentsBuilderTests.java b/spring-web/src/test/java/org/springframework/web/util/UriComponentsBuilderTests.java index 949b1b91706..a5face72d17 100644 --- a/spring-web/src/test/java/org/springframework/web/util/UriComponentsBuilderTests.java +++ b/spring-web/src/test/java/org/springframework/web/util/UriComponentsBuilderTests.java @@ -196,6 +196,16 @@ class UriComponentsBuilderTests { assertThat(result.getQuery()).isNull(); assertThat(result.getFragment()).isEqualTo("baz"); + result = UriComponentsBuilder.fromUriString("mailto:user@example.com?subject=foo").build(); + assertThat(result.getScheme()).isEqualTo("mailto"); + assertThat(result.getUserInfo()).isNull(); + assertThat(result.getHost()).isNull(); + assertThat(result.getPort()).isEqualTo(-1); + assertThat(result.getSchemeSpecificPart()).isEqualTo("user@example.com?subject=foo"); + assertThat(result.getPath()).isNull(); + assertThat(result.getQuery()).isNull(); + assertThat(result.getFragment()).isNull(); + result = UriComponentsBuilder.fromUriString("docs/guide/collections/designfaq.html#28").build(); assertThat(result.getScheme()).isNull(); assertThat(result.getUserInfo()).isNull(); diff --git a/spring-web/src/test/java/org/springframework/web/util/UrlParserTests.java b/spring-web/src/test/java/org/springframework/web/util/UrlParserTests.java index ce8d884afff..2dc1f51a259 100644 --- a/spring-web/src/test/java/org/springframework/web/util/UrlParserTests.java +++ b/spring-web/src/test/java/org/springframework/web/util/UrlParserTests.java @@ -61,8 +61,31 @@ class UrlParserTests { else { assertThat(result.port()).as("Port is not null").isNull(); } + assertThat(result.hasOpaquePath()).as("Result has opaque path").isFalse(); assertThat(result.path().toString()).as("Invalid path").isEqualTo(path); assertThat(result.query()).as("Invalid query").isEqualTo(query); assertThat(result.fragment()).as("Invalid fragment").isEqualTo(fragment); } + + @Test + void parseOpaque() { + testParseOpaque("mailto:user@example.com?subject=foo", "user@example.com", "subject=foo"); + + } + + void testParseOpaque(String input, String path, @Nullable String query) { + UrlParser.UrlRecord result = UrlParser.parse("mailto:user@example.com?subject=foo", EMPTY_URL_RECORD, null, null); + + + assertThat(result.scheme()).as("Invalid scheme").isEqualTo("mailto"); + assertThat(result.hasOpaquePath()).as("Result has no opaque path").isTrue(); + assertThat(result.path().toString()).as("Invalid path").isEqualTo(path); + if (query != null) { + assertThat(result.query()).as("Query is null").isNotNull(); + assertThat(result.query()).as("Invalid query").isEqualTo(query); + } + else { + assertThat(result.query()).as("Query is not null").isNull(); + } + } }