diff --git a/framework-docs/modules/ROOT/partials/web/web-uris.adoc b/framework-docs/modules/ROOT/partials/web/web-uris.adoc index 330d0c28fd7..8ba08ac1cbd 100644 --- a/framework-docs/modules/ROOT/partials/web/web-uris.adoc +++ b/framework-docs/modules/ROOT/partials/web/web-uris.adoc @@ -234,6 +234,34 @@ Kotlin:: ====== +[[uri-parsing]] += URI Parsing +[.small]#Spring MVC and Spring WebFlux# + +`UriComponentsBuilder` supports two URI parser types: + +1. RFC parser -- this parser type expects URI strings to conform to RFC 3986 syntax, +and treats deviations from the syntax as illegal. + +2. WhatWG parser -- this parser is based on the +https://github.com/web-platform-tests/wpt/tree/master/url[URL parsing algorithm] in the +https://url.spec.whatwg.org[WhatWG URL Living standard]. It provides lenient handling of +a wide range of cases of unexpected input. Browsers implement this in order to handle +leniently user typed URL's. For more details, see the URL Living Standard and URL parsing +https://github.com/web-platform-tests/wpt/tree/master/url[test cases]. + +By default, `RestClient`, `WebClient`, and `RestTemplate` use the RFC parser type, and +expect applications to provide with URL templates that conform to RFC syntax. To change +that you can customize the `UriBuilderFactory` on any of the clients. + +Applications and frameworks may further rely on `UriComponentsBuilder` for their own needs +to parse user provided URL's in order to inspect and possibly validated URI components +such as the scheme, host, port, path, and query. Such components can decide to use the +WhatWG parser type in order to handle URL's more leniently, and to align with the way +browsers parse URI's, in case of a redirect to the input URL or if it is included in a +response to a browser. + + [[uri-encoding]] = URI Encoding [.small]#Spring MVC and Spring WebFlux# diff --git a/spring-web/src/main/java/org/springframework/web/util/DefaultUriBuilderFactory.java b/spring-web/src/main/java/org/springframework/web/util/DefaultUriBuilderFactory.java index ff7450d8543..96639045e61 100644 --- a/spring-web/src/main/java/org/springframework/web/util/DefaultUriBuilderFactory.java +++ b/spring-web/src/main/java/org/springframework/web/util/DefaultUriBuilderFactory.java @@ -97,10 +97,12 @@ public class DefaultUriBuilderFactory implements UriBuilderFactory { /** * Set the {@link UriComponentsBuilder.ParserType} to use. - *

By default, if the parser type is not specified, - * {@link UriComponentsBuilder} uses {@link UriComponentsBuilder.ParserType#RFC}. + *

By default, {@link UriComponentsBuilder} uses the + * {@link UriComponentsBuilder.ParserType#RFC parser type}. * @param parserType the parser type * @since 6.2 + * @see UriComponentsBuilder.ParserType + * @see UriComponentsBuilder#fromUriString(String, UriComponentsBuilder.ParserType) */ public void setParserType(UriComponentsBuilder.ParserType parserType) { this.parserType = parserType; 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 b137d424e8a..409588bd8eb 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 @@ -42,19 +42,23 @@ import org.springframework.web.util.HierarchicalUriComponents.PathComponent; import org.springframework.web.util.UriComponents.UriTemplateVariables; /** - * Builder for {@link UriComponents}. - * - *

Typical usage involves: + * Builder for {@link UriComponents}. Use as follows: *

    - *
  1. Create a {@code UriComponentsBuilder} with one of the static factory methods - * (such as {@link #fromPath(String)} or {@link #fromUri(URI)})
  2. - *
  3. Set the various URI components through the respective methods ({@link #scheme(String)}, - * {@link #userInfo(String)}, {@link #host(String)}, {@link #port(int)}, {@link #path(String)}, - * {@link #pathSegment(String...)}, {@link #queryParam(String, Object...)}, and - * {@link #fragment(String)}.
  4. - *
  5. Build the {@link UriComponents} instance with the {@link #build()} method.
  6. + *
  7. Create a builder through a factory method, e.g. {@link #fromUriString(String)}. + *
  8. Set URI components (e.g. scheme, host, path, etc) through instance methods. + *
  9. Build the {@link UriComponents}.
  10. + *
  11. Expand URI variables from a map or array or variable values. + *
  12. Encode via {@link UriComponents#encode()}.
  13. + *
  14. Use {@link UriComponents#toUri()} or {@link UriComponents#toUriString()}. *
* + *

By default, URI parsing is based on the {@link ParserType#RFC RFC parser type}, + * which expects input strings to conform to RFC 3986 syntax. The alternative + * {@link ParserType#WHAT_WG WhatWG parser type}, based on the algorithm from + * the WhatWG URL Living Standard + * provides more lenient handling of a wide range of cases that occur in user + * types URL's. + * * @author Arjen Poutsma * @author Rossen Stoyanchev * @author Phillip Webb @@ -785,43 +789,39 @@ public class UriComponentsBuilder implements UriBuilder, Cloneable { } - private interface PathComponentBuilder { - - @Nullable - PathComponent build(); - - PathComponentBuilder cloneBuilder(); - } - - /** - * Enum to represent different URI parsing mechanisms. + * Enum to provide a choice of URI parsers to use in {@link #fromUriString(String, ParserType)}. + * @since 6.2 */ public enum ParserType { /** - * Parser that expects URI's conforming to RFC 3986 syntax. + * This parser type expects URI's to conform to RFC 3986 syntax. */ RFC, /** - * Parser based on algorithm defined in the WhatWG URL Living standard. - * Browsers use this algorithm to align on lenient parsing of user typed - * URL's that may deviate from RFC syntax. - *

For more details, see: - *

- *

Use this if you need to leniently handle URL's that don't conform - * to RFC syntax, or for alignment with browser parsing. + * This parser follows the + * URL parsing algorithm + * in the WhatWG URL Living standard that browsers implement to align on + * lenient handling of user typed URL's that may not conform to RFC syntax. + * @see URL Living Standard + * @see URL tests */ WHAT_WG } + private interface PathComponentBuilder { + + @Nullable + PathComponent build(); + + PathComponentBuilder cloneBuilder(); + } + + private static class CompositePathComponentBuilder implements PathComponentBuilder { private final Deque builders = new ArrayDeque<>();