3
3
= UriComponents
4
4
[.small]#Spring MVC and Spring WebFlux#
5
5
6
- `UriComponents` is comparable to `java.net.URI`. However it comes with a dedicated
7
- `UriComponentsBuilder` and supports URI template variables:
6
+ `UriComponentsBuilder` helps to build URI's from URI templates with variables:
8
7
9
8
[source,java,indent=0]
10
9
[subs="verbatim,quotes"]
13
12
14
13
UriComponents uriComponents = UriComponentsBuilder.fromUriString(uriTemplate) // <1>
15
14
.queryParam("q", "{q}") // <2>
16
- .build(); // <3>
15
+ .encode() // <3>
16
+ .build(); // <4>
17
17
18
- URI uri = uriComponents.expand("Westin", "123").encode(). toUri(); // <4 >
18
+ URI uri = uriComponents.expand("Westin", "123").toUri(); // <5 >
19
19
----
20
20
<1> Static factory method with a URI template.
21
- <2> Add or replace URI components.
22
- <3> Build `UriComponents`.
23
- <4> Expand URI variables, encode, and obtain the `URI`.
21
+ <2> Add and/or replace URI components.
22
+ <3> Request to have the URI template and URI variables encoded.
23
+ <4> Build a `UriComponents`.
24
+ <5> Expand variables, and obtain the `URI`.
24
25
25
- The above can be done as a single chain and with a shortcut :
26
+ The above can also be done in shorthand form :
26
27
27
28
[source,java,indent=0]
28
29
[subs="verbatim,quotes"]
29
30
----
30
- String uriTemplate = "http://example.com/hotels/{hotel}";
31
-
32
31
URI uri = UriComponentsBuilder.fromUriString(uriTemplate)
33
32
.queryParam("q", "{q}")
34
- .buildAndExpand("Westin", "123")
35
33
.encode()
34
+ .buildAndExpand("Westin", "123")
36
35
.toUri();
37
36
----
38
37
@@ -41,52 +40,48 @@ The above can be done as a single chain and with a shortcut:
41
40
= UriBuilder
42
41
[.small]#Spring MVC and Spring WebFlux#
43
42
44
- <<web-uricomponents,UriComponentsBuilder>> is an implementation of `UriBuilder`. Together
45
- `UriBuilderFactory` and `UriBuilder` provide a pluggable mechanism for building a URI
46
- from a URI template, as well as a way to share common properties such as a base URI,
47
- encoding strategy , and others.
43
+ <<web-uricomponents,UriComponentsBuilder>> implements `UriBuilder`. A `UriBuilder` in turn
44
+ can be created with a `UriBuilderFactory`. Together `UriBuilderFactory` and `UriBuilder`
45
+ provide a pluggable mechanism to build URIs from URI templates, based on shared
46
+ configuration such as a base url, encoding preferences , and others.
48
47
49
- Both the `RestTemplate` and the `WebClient` can be configured with a `UriBuilderFactory`
50
- in order to customize how URIs are created from URI templates. The default implementation
51
- relies on `UriComponentsBuilder` internally and provides options to configure a common
52
- base URI, an alternative encoding mode strategy, and more .
48
+ The `RestTemplate` and the `WebClient` can be configured with a `UriBuilderFactory`
49
+ to customize the preparation of URIs. `DefaultUriBuilderFactory` is a default
50
+ implementation of `UriBuilderFactory` that uses `UriComponentsBuilder` internally and
51
+ exposes shared configuration options .
53
52
54
- An example of configuring the `RestTemplate`:
53
+ `RestTemplate` example :
55
54
56
55
[source,java,indent=0]
57
56
[subs="verbatim,quotes"]
58
57
----
59
- String baseUrl = "http://example.com";
58
+ // import org.springframework.web.util.DefaultUriBuilderFactory.EncodingMode;
59
+
60
+ String baseUrl = "http://example.org";
60
61
DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory(baseUrl);
62
+ factory.setEncodingMode(EncodingMode.TEMPLATE_AND_VARIABLES);
61
63
62
64
RestTemplate restTemplate = new RestTemplate();
63
65
restTemplate.setUriTemplateHandler(factory);
64
66
----
65
67
66
- Examples of configuring the `WebClient`:
68
+ `WebClient` example :
67
69
68
70
[source,java,indent=0]
69
71
[subs="verbatim,quotes"]
70
72
----
71
- String baseUrl = "http://example.com";
73
+ // import org.springframework.web.util.DefaultUriBuilderFactory.EncodingMode;
74
+
75
+ String baseUrl = "http://example.org";
72
76
DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory(baseUrl);
77
+ factory.setEncodingMode(EncodingMode.TEMPLATE_AND_VARIABLES);
73
78
74
- // Configure the UriBuilderFactory..
75
79
WebClient client = WebClient.builder().uriBuilderFactory(factory).build();
76
-
77
- // Or use shortcut on builder..
78
- WebClient client = WebClient.builder().baseUrl(baseUrl).build();
79
-
80
- // Or use create shortcut...
81
- WebClient client = WebClient.create(baseUrl);
82
80
----
83
81
84
- You can also use `DefaultUriBuilderFactory` directly, as you would `UriComponentsBuilder`.
85
- The main difference is that `DefaultUriBuilderFactory` is stateful and can be re-used to
86
- prepare many URLs, sharing common configuration, such as a base URL, while
87
- `UriComponentsBuilder` is stateless and per URI.
88
-
89
- An example of using the `DefaultUriBuilderFactory`:
82
+ In addition `DefaultUriBuilderFactory` can also be used directly. It is similar to using
83
+ `UriComponentsBuilder` but instead of static factory methods, it is an actual instance
84
+ that holds configuration and preferences:
90
85
91
86
[source,java,indent=0]
92
87
[subs="verbatim,quotes"]
@@ -96,47 +91,65 @@ An example of using the `DefaultUriBuilderFactory`:
96
91
97
92
URI uri = uriBuilderFactory.uriString("/hotels/{hotel}")
98
93
.queryParam("q", "{q}")
99
- .build("Westin", "123"); // encoding strategy applied..
94
+ .build("Westin", "123");
100
95
----
101
96
102
97
103
98
[[web-uri-encoding]]
104
99
= URI Encoding
105
100
[.small]#Spring MVC and Spring WebFlux#
106
101
107
- By default `UriComponents` encodes only characters that are illegal within a given URI
108
- component, but not all characters with reserved meaning. More specifically `UriComponents`
109
- does the following:
102
+ When using `UriComponentsBuilder` directly, this is the preferred way to encode:
110
103
111
- . Expand URI variables.
112
- . Encode each URI component (path, query, etc) individually, by applying percent encoding
113
- to illegal characters such as non-US-ASCII characters as well as any characters that are
114
- illegal within the URI component, as per RFC 3986.
104
+ [source,java,indent=0]
105
+ [subs="verbatim,quotes"]
106
+ ----
107
+ String uriTemplate = "http://example.com/hotels/{hotel}";
108
+
109
+ URI uri = UriComponentsBuilder.fromUriString(uriTemplate)
110
+ .queryParam("q", "{q}")
111
+ .encode()
112
+ .buildAndexpand("Westin", "123")
113
+ .toUri();
114
+ ----
115
115
116
- This is comparable to the way the `java.net.URI` multi-argument constructor works and is
117
- described in the "Escaped octets, quotation, encoding, and decoding" section of its Javadoc.
116
+ First, the URI template is encoded when `UriComponents` is built. Then URI variables are
117
+ encoded separately when expanded. The following rules apply to each:
118
118
119
- In some cases, you may want to ensure that expanded URI variables do not impact the
120
- structure and meaning of the URI. That means encoding not only illegal characters but also
121
- all characters with reserved meaning in a URI.
119
+ * The URI template is encoded by quoting _only_ characters that are illegal within a
120
+ given URI component type. For example, spaces are illegal in a path and therefore encoded.
121
+ * URI variables are encoded more strictly, by quoting both illegal characters and also
122
+ characters with reserved meaning. For example ";" is legal in a path but has reserved
123
+ meaning (as a path parameter separator) and therefore encoded.
122
124
123
- The `WebClient` and the `RestTemplate` can be switched to a different encoding mode
124
- through the <<web-uribuilder,UriBuilderFactory>> strategy :
125
+ The `WebClient` and the `RestTemplate` rely on a `UriBuilderFactory` to expand URI template
126
+ and apply encoding. The `DefaultUriBuilderFactory` provides multiple encoding modes :
125
127
126
128
[source,java,indent=0]
127
129
[subs="verbatim,quotes"]
128
130
----
131
+ // import org.springframework.web.util.DefaultUriBuilderFactory.EncodingMode;
132
+
129
133
String baseUrl = "http://example.com";
130
134
DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory(baseUrl)
131
- factory.setEncodingMode(EncodingMode.VALUES_ONLY);
132
-
133
- WebClient client = WebClient.builder().uriBuilderFactory(factory).build();
135
+ factory.setEncodingMode(EncodingMode.TEMPLATE_AND_VALUES);
134
136
135
137
RestTemplate restTemplate = new RestTemplate();
136
138
restTemplate.setUriTemplateHandler(factory);
139
+
140
+ WebClient client = WebClient.builder().uriBuilderFactory(factory).build();
137
141
----
138
142
139
- Internally `DefaultUriBuilderFactory` delegates to `UriUtils.encode(String, Charset)` to
140
- encode each URI variable value prior to expanding it, effectively encoding both all
141
- non-US-ASCII characters, and characters with reserved meaning in a URI.
143
+ Internally `DefaultUriBuilderFactory` uses `UriComponentsBuilder`. The
144
+ `EncodingMode.TEMPLATE_AND_VALUES` corresponds to the `UriComponentsBuilder` encoding
145
+ example shown earlier. It is the preferred mode.
146
+
147
+ Out of the box, `RestTemplate` is configured with `EncodingMode.URI_COMPONENTS` which has
148
+ been used historically and still is the default for backwards compatibility. It works by
149
+ expanding URI variables first, and then encoding the expanded URI component values,
150
+ quoting _only_ illegal characters within a given URI component type, but not all
151
+ characters with reserved meaning. As of 5.0.8, you can switch to the preferred
152
+ `EncodingMode.TEMPLATE_AND_VALUES`.
142
153
154
+ `WebClient` is configured with `EncodingMode.TEMPLATE_AND_VALUES` by default starting in
155
+ 5.1, In 5.0.x however the default remains `EncodingMode.URI_COMPONENTS`.
0 commit comments