Skip to content

Commit 5382260

Browse files
committed
Client/ServerRequest defensively accesses internal attribute map
Issue: SPR-17486
1 parent 35da9f1 commit 5382260

File tree

2 files changed

+47
-58
lines changed

2 files changed

+47
-58
lines changed

spring-webflux/src/main/java/org/springframework/web/reactive/function/client/ClientRequest.java

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -76,13 +76,7 @@ public interface ClientRequest {
7676
* @return the attribute value
7777
*/
7878
default Optional<Object> attribute(String name) {
79-
Map<String, Object> attributes = attributes();
80-
if (attributes.containsKey(name)) {
81-
return Optional.of(attributes.get(name));
82-
}
83-
else {
84-
return Optional.empty();
85-
}
79+
return Optional.ofNullable(attributes().get(name));
8680
}
8781

8882
/**
@@ -91,8 +85,7 @@ default Optional<Object> attribute(String name) {
9185
Map<String, Object> attributes();
9286

9387
/**
94-
* Writes this request to the given {@link ClientHttpRequest}.
95-
*
88+
* Write this request to the given {@link ClientHttpRequest}.
9689
* @param request the client http request to write to
9790
* @param strategies the strategies to use when writing
9891
* @return {@code Mono<Void>} to indicate when writing is complete

spring-webflux/src/main/java/org/springframework/web/reactive/function/server/ServerRequest.java

Lines changed: 45 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@
5050

5151
/**
5252
* Represents a server-side HTTP request, as handled by a {@code HandlerFunction}.
53-
* Access to headers and body is offered by {@link Headers} and
53+
*
54+
* <p>Access to headers and body is offered by {@link Headers} and
5455
* {@link #body(BodyExtractor)}, respectively.
5556
*
5657
* @author Arjen Poutsma
@@ -60,7 +61,7 @@
6061
public interface ServerRequest {
6162

6263
/**
63-
* Return the HTTP method.
64+
* Get the HTTP method.
6465
* @return the HTTP method as an HttpMethod enum value, or {@code null}
6566
* if not resolvable (e.g. in case of a non-standard HTTP method)
6667
*/
@@ -70,18 +71,18 @@ default HttpMethod method() {
7071
}
7172

7273
/**
73-
* Return the name of the HTTP method.
74+
* Get the name of the HTTP method.
7475
* @return the HTTP method as a String
7576
*/
7677
String methodName();
7778

7879
/**
79-
* Return the request URI.
80+
* Get the request URI.
8081
*/
8182
URI uri();
8283

8384
/**
84-
* Return a {@code UriBuilderComponents} from the URI associated with this
85+
* Get a {@code UriBuilderComponents} from the URI associated with this
8586
* {@code ServerRequest}, while also overlaying with values from the headers
8687
* "Forwarded" (<a href="http://tools.ietf.org/html/rfc7239">RFC 7239</a>),
8788
* or "X-Forwarded-Host", "X-Forwarded-Port", and "X-Forwarded-Proto" if
@@ -91,26 +92,26 @@ default HttpMethod method() {
9192
UriBuilder uriBuilder();
9293

9394
/**
94-
* Return the request path.
95+
* Get the request path.
9596
*/
9697
default String path() {
9798
return uri().getRawPath();
9899
}
99100

100101
/**
101-
* Return the request path as {@code PathContainer}.
102+
* Get the request path as a {@code PathContainer}.
102103
*/
103104
default PathContainer pathContainer() {
104105
return PathContainer.parsePath(path());
105106
}
106107

107108
/**
108-
* Return the headers of this request.
109+
* Get the headers of this request.
109110
*/
110111
Headers headers();
111112

112113
/**
113-
* Return the cookies of this request.
114+
* Get the cookies of this request.
114115
*/
115116
MultiValueMap<String, HttpCookie> cookies();
116117

@@ -166,28 +167,22 @@ default PathContainer pathContainer() {
166167
<T> Flux<T> bodyToFlux(ParameterizedTypeReference<T> typeReference);
167168

168169
/**
169-
* Return the request attribute value if present.
170+
* Get the request attribute value if present.
170171
* @param name the attribute name
171172
* @return the attribute value
172173
*/
173174
default Optional<Object> attribute(String name) {
174-
Map<String, Object> attributes = attributes();
175-
if (attributes.containsKey(name)) {
176-
return Optional.of(attributes.get(name));
177-
}
178-
else {
179-
return Optional.empty();
180-
}
175+
return Optional.ofNullable(attributes().get(name));
181176
}
182177

183178
/**
184-
* Return a mutable map of request attributes.
179+
* Get a mutable map of request attributes.
185180
* @return the request attributes
186181
*/
187182
Map<String, Object> attributes();
188183

189184
/**
190-
* Return the first query parameter with the given name, if present.
185+
* Get the first query parameter with the given name, if present.
191186
* @param name the parameter name
192187
* @return the parameter value
193188
*/
@@ -206,12 +201,12 @@ default Optional<String> queryParam(String name) {
206201
}
207202

208203
/**
209-
* Return all query parameters for this request.
204+
* Get all query parameters for this request.
210205
*/
211206
MultiValueMap<String, String> queryParams();
212207

213208
/**
214-
* Return the path variable with the given name, if present.
209+
* Get the path variable with the given name, if present.
215210
* @param name the variable name
216211
* @return the variable value
217212
* @throws IllegalArgumentException if there is no path variable with the given name
@@ -227,38 +222,38 @@ default String pathVariable(String name) {
227222
}
228223

229224
/**
230-
* Return all path variables for this request.
225+
* Get all path variables for this request.
231226
*/
232227
Map<String, String> pathVariables();
233228

234229
/**
235-
* Return the web session for this request. Always guaranteed to
236-
* return an instance either matching to the session id requested by the
237-
* client, or with a new session id either because the client did not
238-
* specify one or because the underlying session had expired. Use of this
239-
* method does not automatically create a session.
230+
* Get the web session for this request.
231+
* <p>Always guaranteed to return an instance either matching the session id
232+
* requested by the client, or with a new session id either because the client
233+
* did not specify one or because the underlying session had expired.
234+
* <p>Use of this method does not automatically create a session.
240235
*/
241236
Mono<WebSession> session();
242237

243238
/**
244-
* Return the authenticated user for the request, if any.
239+
* Get the authenticated user for the request, if any.
245240
*/
246241
Mono<? extends Principal> principal();
247242

248243
/**
249-
* Return the form data from the body of the request if the Content-Type is
244+
* Get the form data from the body of the request if the Content-Type is
250245
* {@code "application/x-www-form-urlencoded"} or an empty map otherwise.
251246
* <p><strong>Note:</strong> calling this method causes the request body to
252-
* be read and parsed in full and the resulting {@code MultiValueMap} is
247+
* be read and parsed in full, and the resulting {@code MultiValueMap} is
253248
* cached so that this method is safe to call more than once.
254249
*/
255250
Mono<MultiValueMap<String, String>> formData();
256251

257252
/**
258-
* Return the parts of a multipart request if the Content-Type is
253+
* Get the parts of a multipart request if the Content-Type is
259254
* {@code "multipart/form-data"} or an empty map otherwise.
260255
* <p><strong>Note:</strong> calling this method causes the request body to
261-
* be read and parsed in full and the resulting {@code MultiValueMap} is
256+
* be read and parsed in full, and the resulting {@code MultiValueMap} is
262257
* cached so that this method is safe to call more than once.
263258
*/
264259
Mono<MultiValueMap<String, Part>> multipartData();
@@ -285,59 +280,60 @@ static ServerRequest create(ServerWebExchange exchange, List<HttpMessageReader<?
285280
interface Headers {
286281

287282
/**
288-
* Return the list of acceptable {@code MediaType media types},
289-
* as specified by the {@code Accept} header.
290-
* <p>Returns an empty list when the acceptable media types are unspecified.
283+
* Get the list of acceptable media types, as specified by the {@code Accept}
284+
* header.
285+
* <p>Returns an empty list if the acceptable media types are unspecified.
291286
*/
292287
List<MediaType> accept();
293288

294289
/**
295-
* Return the list of acceptable {@code Charset charsets},
296-
* as specified by the {@code Accept-Charset} header.
290+
* Get the list of acceptable charsets, as specified by the
291+
* {@code Accept-Charset} header.
297292
*/
298293
List<Charset> acceptCharset();
299294

300295
/**
301-
* Return the list of acceptable {@code Locale.LanguageRange languages},
302-
* as specified by the {@code Accept-Language} header.
296+
* Get the list of acceptable languages, as specified by the
297+
* {@code Accept-Language} header.
303298
*/
304299
List<Locale.LanguageRange> acceptLanguage();
305300

306301
/**
307-
* Return the length of the body in bytes, as specified by the
302+
* Get the length of the body in bytes, as specified by the
308303
* {@code Content-Length} header.
309304
*/
310305
OptionalLong contentLength();
311306

312307
/**
313-
* Return the {@code MediaType media type} of the body, as specified
314-
* by the {@code Content-Type} header.
308+
* Get the media type of the body, as specified by the
309+
* {@code Content-Type} header.
315310
*/
316311
Optional<MediaType> contentType();
317312

318313
/**
319-
* Return the value of the required {@code Host} header.
320-
* <p>If the header value does not contain a port, the returned
321-
* {@linkplain InetSocketAddress#getPort() port} will be {@code 0}.
314+
* Get the value of the {@code Host} header, if available.
315+
* <p>If the header value does not contain a port, the
316+
* {@linkplain InetSocketAddress#getPort() port} in the returned address will
317+
* be {@code 0}.
322318
*/
323319
@Nullable
324320
InetSocketAddress host();
325321

326322
/**
327-
* Return the value of the {@code Range} header.
323+
* Get the value of the {@code Range} header.
328324
* <p>Returns an empty list when the range is unknown.
329325
*/
330326
List<HttpRange> range();
331327

332328
/**
333-
* Return the header value(s), if any, for the header of the given name.
334-
* <p>Return an empty list if no header values are found.
329+
* Get the header value(s), if any, for the header of the given name.
330+
* <p>Returns an empty list if no header values are found.
335331
* @param headerName the header name
336332
*/
337333
List<String> header(String headerName);
338334

339335
/**
340-
* Return the headers as a {@link HttpHeaders} instance.
336+
* Get the headers as an instance of {@link HttpHeaders}.
341337
*/
342338
HttpHeaders asHttpHeaders();
343339
}

0 commit comments

Comments
 (0)