Skip to content

Commit 5168e3a

Browse files
committed
Polishing contribution
Closes gh-36400
1 parent d4893fb commit 5168e3a

File tree

11 files changed

+122
-195
lines changed

11 files changed

+122
-195
lines changed

spring-test/src/main/java/org/springframework/mock/web/server/MockServerWebExchange.java

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -49,17 +49,9 @@ private MockServerWebExchange(
4949
MockServerHttpRequest request, @Nullable WebSessionManager sessionManager,
5050
@Nullable ApplicationContext applicationContext, @Nullable Principal principal) {
5151

52-
this(request, sessionManager, applicationContext, null, principal);
53-
}
54-
55-
private MockServerWebExchange(
56-
MockServerHttpRequest request, @Nullable WebSessionManager sessionManager,
57-
@Nullable ApplicationContext applicationContext, @Nullable Boolean defaultHtmlEscape, @Nullable Principal principal) {
58-
5952
super(request, new MockServerHttpResponse(),
6053
sessionManager != null ? sessionManager : new DefaultWebSessionManager(),
61-
ServerCodecConfigurer.create(), new AcceptHeaderLocaleContextResolver(),
62-
applicationContext, defaultHtmlEscape);
54+
ServerCodecConfigurer.create(), new AcceptHeaderLocaleContextResolver(), applicationContext);
6355

6456
this.principalMono = (principal != null) ? Mono.just(principal) : Mono.empty();
6557
}
@@ -180,8 +172,8 @@ public Builder applicationContext(ApplicationContext applicationContext) {
180172
* @since 7.0.6
181173
*/
182174
public Builder defaultHtmlEscape(@Nullable Boolean defaultHtmlEscape) {
183-
this.defaultHtmlEscape = defaultHtmlEscape;
184-
return this;
175+
this.defaultHtmlEscape = defaultHtmlEscape;
176+
return this;
185177
}
186178

187179
/**
@@ -199,7 +191,7 @@ public Builder principal(@Nullable Principal principal) {
199191
*/
200192
public MockServerWebExchange build() {
201193
return new MockServerWebExchange(
202-
this.request, this.sessionManager, this.applicationContext, this.defaultHtmlEscape, this.principal);
194+
this.request, this.sessionManager, this.applicationContext, this.principal);
203195
}
204196
}
205197

spring-web/src/main/java/org/springframework/web/server/ServerWebExchange.java

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,12 @@
4343
*/
4444
public interface ServerWebExchange {
4545

46+
/**
47+
* HTML escape attribute, populated from the value of
48+
* {@link org.springframework.web.server.adapter.WebHttpHandlerBuilder#defaultHtmlEscape(Boolean)}.
49+
*/
50+
String HTML_ESCAPE_ATTRIBUTE = ServerWebExchange.class.getName() + ".HTML_ESCAPE";
51+
4652
/**
4753
* Name of {@link #getAttributes() attribute} whose value can be used to
4854
* correlate log messages for this exchange. Use {@link #getLogPrefix()} to
@@ -169,15 +175,6 @@ default Mono<Void> cleanupMultipart() {
169175
*/
170176
@Nullable ApplicationContext getApplicationContext();
171177

172-
/**
173-
* Return the default HTML escape setting available for the current request,
174-
* or {@code null} if no default was configured at the handler level.
175-
* @return whether default HTML escaping is enabled, or {@code null} if not configured
176-
* @since 7.0.6
177-
* @see org.springframework.web.server.adapter.WebHttpHandlerBuilder#defaultHtmlEscape(boolean)
178-
*/
179-
@Nullable Boolean getDefaultHtmlEscape();
180-
181178
/**
182179
* Returns {@code true} if the one of the {@code checkNotModified} methods
183180
* in this contract were used and they returned true.

spring-web/src/main/java/org/springframework/web/server/ServerWebExchangeDecorator.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -98,11 +98,6 @@ public LocaleContext getLocaleContext() {
9898
return getDelegate().getApplicationContext();
9999
}
100100

101-
@Override
102-
public @Nullable Boolean getDefaultHtmlEscape() {
103-
return getDelegate().getDefaultHtmlEscape();
104-
}
105-
106101
@Override
107102
public Mono<MultiValueMap<String, String>> getFormData() {
108103
return getDelegate().getFormData();

spring-web/src/main/java/org/springframework/web/server/adapter/DefaultServerWebExchange.java

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,6 @@ public class DefaultServerWebExchange implements ServerWebExchange {
101101

102102
private final @Nullable ApplicationContext applicationContext;
103103

104-
private final @Nullable Boolean defaultHtmlEscape;
105-
106104
private volatile boolean notModified;
107105

108106
private Function<String, String> urlTransformer = url -> url;
@@ -116,20 +114,13 @@ public DefaultServerWebExchange(ServerHttpRequest request, ServerHttpResponse re
116114
WebSessionManager sessionManager, ServerCodecConfigurer codecConfigurer,
117115
LocaleContextResolver localeContextResolver) {
118116

119-
this(request, response, sessionManager, codecConfigurer, localeContextResolver, null, null);
117+
this(request, response, sessionManager, codecConfigurer, localeContextResolver, null);
120118
}
121119

122120
public DefaultServerWebExchange(ServerHttpRequest request, ServerHttpResponse response,
123121
WebSessionManager sessionManager, ServerCodecConfigurer codecConfigurer,
124122
LocaleContextResolver localeContextResolver, @Nullable ApplicationContext applicationContext) {
125123

126-
this(request, response, sessionManager, codecConfigurer, localeContextResolver, applicationContext, null);
127-
}
128-
129-
protected DefaultServerWebExchange(ServerHttpRequest request, ServerHttpResponse response,
130-
WebSessionManager sessionManager, ServerCodecConfigurer codecConfigurer,
131-
LocaleContextResolver localeContextResolver, @Nullable ApplicationContext applicationContext, @Nullable Boolean defaultHtmlEscape) {
132-
133124
Assert.notNull(request, "'request' is required");
134125
Assert.notNull(response, "'response' is required");
135126
Assert.notNull(sessionManager, "'sessionManager' is required");
@@ -146,7 +137,6 @@ protected DefaultServerWebExchange(ServerHttpRequest request, ServerHttpResponse
146137
this.formDataMono = initFormData(request, codecConfigurer, getLogPrefix());
147138
this.multipartDataMono = initMultipartData(codecConfigurer, getLogPrefix());
148139
this.applicationContext = applicationContext;
149-
this.defaultHtmlEscape = defaultHtmlEscape;
150140

151141
if (request instanceof AbstractServerHttpRequest abstractServerHttpRequest) {
152142
abstractServerHttpRequest.setAttributesSupplier(() -> this.attributes);
@@ -288,11 +278,6 @@ public LocaleContext getLocaleContext() {
288278
return this.applicationContext;
289279
}
290280

291-
@Override
292-
public @Nullable Boolean getDefaultHtmlEscape() {
293-
return this.defaultHtmlEscape;
294-
}
295-
296281
@Override
297282
public boolean isNotModified() {
298283
return this.notModified;

spring-web/src/main/java/org/springframework/web/server/adapter/HttpWebHandlerAdapter.java

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -97,10 +97,10 @@ public class HttpWebHandlerAdapter extends WebHandlerDecorator implements HttpHa
9797

9898
private ServerRequestObservationConvention observationConvention = DEFAULT_OBSERVATION_CONVENTION;
9999

100-
private @Nullable ApplicationContext applicationContext;
101-
102100
private @Nullable Boolean defaultHtmlEscape;
103101

102+
private @Nullable ApplicationContext applicationContext;
103+
104104
/** Whether to log potentially sensitive info (form data at DEBUG, headers at TRACE). */
105105
private boolean enableLoggingRequestDetails = false;
106106

@@ -233,6 +233,26 @@ public ServerRequestObservationConvention getObservationConvention() {
233233
return this.observationConvention;
234234
}
235235

236+
/**
237+
* Configure whether default HTML escaping is enabled for the web application.
238+
* The setting is then exposed as the exchanger attribute
239+
* {@link ServerWebExchange#HTML_ESCAPE_ATTRIBUTE}.
240+
* @param defaultHtmlEscape whether to enable default HTML escaping
241+
* @since 7.0.6
242+
*/
243+
public void setDefaultHtmlEscape(Boolean defaultHtmlEscape) {
244+
this.defaultHtmlEscape = defaultHtmlEscape;
245+
}
246+
247+
/**
248+
* Return the configured default HTML escape setting,
249+
* or {@code null} if not configured.
250+
* @since 7.0.6
251+
*/
252+
public @Nullable Boolean getDefaultHtmlEscape() {
253+
return this.defaultHtmlEscape;
254+
}
255+
236256
/**
237257
* Configure the {@code ApplicationContext} associated with the web application,
238258
* if it was initialized with one via
@@ -252,25 +272,6 @@ public void setApplicationContext(ApplicationContext applicationContext) {
252272
return this.applicationContext;
253273
}
254274

255-
/**
256-
* Configure a default HTML escape setting to apply to every
257-
* {@link org.springframework.web.server.ServerWebExchange} created
258-
* by this adapter.
259-
* @param defaultHtmlEscape whether to enable default HTML escaping
260-
* @since 7.0.6
261-
*/
262-
public void setDefaultHtmlEscape(Boolean defaultHtmlEscape) {
263-
this.defaultHtmlEscape = defaultHtmlEscape;
264-
}
265-
266-
/**
267-
* Return the configured default HTML escape setting,
268-
* or {@code null} if not configured.
269-
* @since 7.0.6
270-
*/
271-
public @Nullable Boolean getDefaultHtmlEscape() {
272-
return this.defaultHtmlEscape;
273-
}
274275

275276
/**
276277
* This method must be invoked after all properties have been set to
@@ -312,6 +313,10 @@ public Mono<Void> handle(ServerHttpRequest request, ServerHttpResponse response)
312313
exchange.getAttributes().put(
313314
ServerRequestObservationContext.CURRENT_OBSERVATION_CONTEXT_ATTRIBUTE, observationContext);
314315

316+
if (this.defaultHtmlEscape != null) {
317+
exchange.getAttributes().put(ServerWebExchange.HTML_ESCAPE_ATTRIBUTE, this.defaultHtmlEscape);
318+
}
319+
315320
return getDelegate().handle(exchange)
316321
.doOnSuccess(aVoid -> logResponse(exchange))
317322
.onErrorResume(ex -> handleUnresolvedError(exchange, observationContext, ex))
@@ -322,7 +327,7 @@ public Mono<Void> handle(ServerHttpRequest request, ServerHttpResponse response)
322327

323328
protected ServerWebExchange createExchange(ServerHttpRequest request, ServerHttpResponse response) {
324329
return new DefaultServerWebExchange(request, response, this.sessionManager,
325-
getCodecConfigurer(), getLocaleContextResolver(), this.applicationContext, this.defaultHtmlEscape);
330+
getCodecConfigurer(), getLocaleContextResolver(), this.applicationContext);
326331
}
327332

328333
/**

spring-web/src/main/java/org/springframework/web/server/adapter/WebHttpHandlerBuilder.java

Lines changed: 43 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,6 @@ public final class WebHttpHandlerBuilder {
9191

9292
private final List<WebExceptionHandler> exceptionHandlers = new ArrayList<>();
9393

94-
private @Nullable Boolean defaultHtmlEscape;
95-
9694
private @Nullable Function<HttpHandler, HttpHandler> httpHandlerDecorator;
9795

9896
private @Nullable WebSessionManager sessionManager;
@@ -107,6 +105,8 @@ public final class WebHttpHandlerBuilder {
107105

108106
private @Nullable ServerRequestObservationConvention observationConvention;
109107

108+
private @Nullable Boolean defaultHtmlEscape;
109+
110110

111111
/**
112112
* Private constructor to use when initialized from an ApplicationContext.
@@ -125,13 +125,13 @@ private WebHttpHandlerBuilder(WebHttpHandlerBuilder other) {
125125
this.applicationContext = other.applicationContext;
126126
this.filters.addAll(other.filters);
127127
this.exceptionHandlers.addAll(other.exceptionHandlers);
128+
this.httpHandlerDecorator = other.httpHandlerDecorator;
128129
this.sessionManager = other.sessionManager;
129130
this.codecConfigurer = other.codecConfigurer;
130131
this.localeContextResolver = other.localeContextResolver;
131132
this.forwardedHeaderTransformer = other.forwardedHeaderTransformer;
132133
this.observationRegistry = other.observationRegistry;
133134
this.observationConvention = other.observationConvention;
134-
this.httpHandlerDecorator = other.httpHandlerDecorator;
135135
this.defaultHtmlEscape = other.defaultHtmlEscape;
136136
}
137137

@@ -271,6 +271,31 @@ public WebHttpHandlerBuilder exceptionHandlers(Consumer<List<WebExceptionHandler
271271
return this;
272272
}
273273

274+
/**
275+
* Configure a {@link Function} to decorate the {@link HttpHandler} returned
276+
* by this builder which effectively wraps the entire
277+
* {@link WebExceptionHandler} - {@link WebFilter} - {@link WebHandler}
278+
* processing chain. This provides access to the request and response before
279+
* the entire chain and likewise the ability to observe the result of
280+
* the entire chain.
281+
* @param handlerDecorator the decorator to apply
282+
* @since 5.3
283+
*/
284+
public WebHttpHandlerBuilder httpHandlerDecorator(Function<HttpHandler, HttpHandler> handlerDecorator) {
285+
this.httpHandlerDecorator = (this.httpHandlerDecorator != null ?
286+
handlerDecorator.andThen(this.httpHandlerDecorator) : handlerDecorator);
287+
return this;
288+
}
289+
290+
/**
291+
* Whether a decorator for {@link HttpHandler} is configured or not via
292+
* {@link #httpHandlerDecorator(Function)}.
293+
* @since 5.3
294+
*/
295+
public boolean hasHttpHandlerDecorator() {
296+
return (this.httpHandlerDecorator != null);
297+
}
298+
274299
/**
275300
* Configure the {@link WebSessionManager} to set on the
276301
* {@link ServerWebExchange WebServerExchange}.
@@ -292,26 +317,6 @@ public boolean hasSessionManager() {
292317
return (this.sessionManager != null);
293318
}
294319

295-
/**
296-
* Configure a default HTML escape setting to apply to the created
297-
* {@link org.springframework.web.server.ServerWebExchange}.
298-
* @param defaultHtmlEscape whether to enable default HTML escaping
299-
* @return this builder
300-
* @since 7.0.6
301-
*/
302-
public WebHttpHandlerBuilder defaultHtmlEscape(Boolean defaultHtmlEscape) {
303-
this.defaultHtmlEscape = defaultHtmlEscape;
304-
return this;
305-
}
306-
307-
/**
308-
* Return whether a default HTML escape setting has been configured.
309-
* @since 7.0.6
310-
*/
311-
public boolean hasDefaultHtmlEscape() {
312-
return (this.defaultHtmlEscape != null);
313-
}
314-
315320
/**
316321
* Configure the {@link ServerCodecConfigurer} to set on the {@code WebServerExchange}.
317322
* @param codecConfigurer the codec configurer
@@ -394,28 +399,26 @@ public WebHttpHandlerBuilder observationConvention(ServerRequestObservationConve
394399
}
395400

396401
/**
397-
* Configure a {@link Function} to decorate the {@link HttpHandler} returned
398-
* by this builder which effectively wraps the entire
399-
* {@link WebExceptionHandler} - {@link WebFilter} - {@link WebHandler}
400-
* processing chain. This provides access to the request and response before
401-
* the entire chain and likewise the ability to observe the result of
402-
* the entire chain.
403-
* @param handlerDecorator the decorator to apply
404-
* @since 5.3
402+
* Configure whether default HTML escaping is enabled for the web application.
403+
* The setting is then exposed as the exchanger attribute
404+
* {@link ServerWebExchange#HTML_ESCAPE_ATTRIBUTE}.
405+
* <p>This method differentiates between no setting specified at all and
406+
* an actual boolean value specified, allowing to have a context-specific
407+
* default in case of no setting at the global level.
408+
* @param defaultHtmlEscape whether to enable default HTML escaping
409+
* @since 7.0.6
405410
*/
406-
public WebHttpHandlerBuilder httpHandlerDecorator(Function<HttpHandler, HttpHandler> handlerDecorator) {
407-
this.httpHandlerDecorator = (this.httpHandlerDecorator != null ?
408-
handlerDecorator.andThen(this.httpHandlerDecorator) : handlerDecorator);
411+
public WebHttpHandlerBuilder defaultHtmlEscape(@Nullable Boolean defaultHtmlEscape) {
412+
this.defaultHtmlEscape = defaultHtmlEscape;
409413
return this;
410414
}
411415

412416
/**
413-
* Whether a decorator for {@link HttpHandler} is configured or not via
414-
* {@link #httpHandlerDecorator(Function)}.
415-
* @since 5.3
417+
* Whether HTML escaping is enabled for the web application.
418+
* @since 7.0.6
416419
*/
417-
public boolean hasHttpHandlerDecorator() {
418-
return (this.httpHandlerDecorator != null);
420+
public @Nullable Boolean getDefaultHtmlEscape() {
421+
return this.defaultHtmlEscape;
419422
}
420423

421424
/**
@@ -447,7 +450,7 @@ public HttpHandler build() {
447450
if (this.applicationContext != null) {
448451
adapted.setApplicationContext(this.applicationContext);
449452
}
450-
if(this.defaultHtmlEscape != null) {
453+
if (this.defaultHtmlEscape != null) {
451454
adapted.setDefaultHtmlEscape(this.defaultHtmlEscape);
452455
}
453456
adapted.afterPropertiesSet();

0 commit comments

Comments
 (0)