Skip to content

Commit eac0ddc

Browse files
committed
Update URI Encoding section
1 parent a363a22 commit eac0ddc

File tree

1 file changed

+41
-30
lines changed

1 file changed

+41
-30
lines changed

src/docs/asciidoc/web/web-uris.adoc

Lines changed: 41 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -99,37 +99,47 @@ that holds configuration and preferences:
9999
= URI Encoding
100100
[.small]#Spring MVC and Spring WebFlux#
101101

102-
When using `UriComponentsBuilder` directly, this is the preferred way to encode:
102+
`UriComponentsBuilder` exposes encoding options at 2 levels:
103+
104+
. {api-spring-framework}/web/util/UriComponentsBuilder.html#encode--[UriComponentsBuilder#encode()] -
105+
pre-encodes the URI template first, then strictly encodes URI variables when expanded.
106+
. {api-spring-framework}/web/util/UriComponents.html#encode--[UriComponents#encode()] -
107+
encodes URI components _after_ URI variables are expanded.
108+
109+
Both options replace non-ASCII and illegal characters with escaped octets, however option
110+
1 also replaces characters with reserved meaning that appear in URI variables.
111+
112+
[TIP]
113+
====
114+
Consider ";" which is legal in a path but has reserved meaning. Option 1 replaces
115+
";" with "%3B" in URI variables but not in the URI template. By contrast, option 2 never
116+
replaces ";" since it is a legal character in a path.
117+
====
118+
119+
For most cases option 1 is likely to give the expected result because in treats URI
120+
variables as opaque data to be fully encoded, while option 2 is useful only if
121+
intentionally expanding URI variables that contain reserved characters.
122+
123+
Example usage using option 1:
103124

104125
[source,java,indent=0]
105126
[subs="verbatim,quotes"]
106127
----
107-
String uriTemplate = "http://example.com/hotels/{hotel}";
108-
109-
URI uri = UriComponentsBuilder.fromUriString(uriTemplate)
128+
UriComponentsBuilder.fromPath("/hotel list/{city}")
110129
.queryParam("q", "{q}")
111130
.encode()
112-
.buildAndexpand("Westin", "123")
113-
.toUri();
114-
----
115-
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:
131+
.buildAndexpand("New York", "foo+bar")
132+
.toUriString();
118133
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.
134+
// Result is "/hotel%20list/New%20York?foo%2Bbar"
135+
----
124136

125-
The `WebClient` and the `RestTemplate` rely on a `UriBuilderFactory` to expand URI template
126-
and apply encoding. The `DefaultUriBuilderFactory` provides multiple encoding modes:
137+
The `WebClient` and the `RestTemplate` expand and encode URI templates internally through
138+
the `UriBuilderFactory` strategy. Both can be configured wiht a custom instance:
127139

128140
[source,java,indent=0]
129141
[subs="verbatim,quotes"]
130142
----
131-
// import org.springframework.web.util.DefaultUriBuilderFactory.EncodingMode;
132-
133143
String baseUrl = "http://example.com";
134144
DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory(baseUrl)
135145
factory.setEncodingMode(EncodingMode.TEMPLATE_AND_VALUES);
@@ -140,16 +150,17 @@ and apply encoding. The `DefaultUriBuilderFactory` provides multiple encoding mo
140150
WebClient client = WebClient.builder().uriBuilderFactory(factory).build();
141151
----
142152

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.
153+
The `DefaultUriBuilderFactory` implementation shown above uses `UriComponentsBuilder`
154+
internally. The approach to encoding is controlled through one of the encoding modes
155+
listed below:
146156

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`.
157+
* `TEMPLATE_AND_VALUES` -- uses `UriComponentsBuilder#encode()`, corresponding to option
158+
1 above, to pre-encode the URI template and strictly encode URI variables when expanded.
159+
* `VALUES_ONLY` -- variant of `TEMPLATE_AND_VALUES` that does not encode the URI template.
160+
* `URI_COMPONENTS` -- uses `UriComponents#encode()`, corresponding to option 2 above, to
161+
encode URI component value _after_ URI variables are expanded.
162+
* `NONE` -- no encoding is applied.
153163

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`.
164+
Out of the box the `RestTemplate` uses `EncodingMode.URI_COMPONENTS` for historic reasons
165+
and for backwards compatibility. The `WebClient` uses `EncodingMode.TEMPLATE_AND_VALUES`
166+
starting in 5.1, and `EncodingMode.URI_COMPONENTS` in 5.0.x.

0 commit comments

Comments
 (0)