1
1
/*
2
- * Copyright 2002-2022 the original author or authors.
2
+ * Copyright 2002-2023 the original author or authors.
3
3
*
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
19
19
import java .time .Duration ;
20
20
import java .util .Collections ;
21
21
import java .util .List ;
22
+ import java .util .Map ;
22
23
import java .util .concurrent .atomic .AtomicReference ;
23
24
24
25
import org .junit .jupiter .api .BeforeEach ;
32
33
import org .springframework .context .annotation .Configuration ;
33
34
import org .springframework .core .codec .CharSequenceEncoder ;
34
35
import org .springframework .http .HttpStatus ;
36
+ import org .springframework .http .MediaType ;
35
37
import org .springframework .http .codec .EncoderHttpMessageWriter ;
38
+ import org .springframework .http .codec .ServerCodecConfigurer ;
36
39
import org .springframework .stereotype .Controller ;
40
+ import org .springframework .web .bind .annotation .ControllerAdvice ;
37
41
import org .springframework .web .bind .annotation .RequestBody ;
38
42
import org .springframework .web .bind .annotation .RequestMapping ;
39
43
import org .springframework .web .bind .annotation .ResponseBody ;
40
44
import org .springframework .web .reactive .accept .HeaderContentTypeResolver ;
45
+ import org .springframework .web .reactive .handler .SimpleUrlHandlerMapping ;
46
+ import org .springframework .web .reactive .resource .ResourceWebHandler ;
47
+ import org .springframework .web .reactive .result .SimpleHandlerAdapter ;
41
48
import org .springframework .web .reactive .result .method .annotation .RequestMappingHandlerAdapter ;
42
49
import org .springframework .web .reactive .result .method .annotation .RequestMappingHandlerMapping ;
43
50
import org .springframework .web .reactive .result .method .annotation .ResponseBodyResultHandler ;
51
+ import org .springframework .web .reactive .result .method .annotation .ResponseEntityExceptionHandler ;
52
+ import org .springframework .web .reactive .result .method .annotation .ResponseEntityResultHandler ;
44
53
import org .springframework .web .server .NotAcceptableStatusException ;
45
54
import org .springframework .web .server .ResponseStatusException ;
46
55
import org .springframework .web .server .ServerWebExchange ;
47
56
import org .springframework .web .server .WebExceptionHandler ;
48
57
import org .springframework .web .server .WebHandler ;
49
58
import org .springframework .web .server .handler .ExceptionHandlingWebHandler ;
50
59
import org .springframework .web .testfixture .http .server .reactive .MockServerHttpRequest ;
60
+ import org .springframework .web .testfixture .http .server .reactive .MockServerHttpResponse ;
51
61
import org .springframework .web .testfixture .server .MockServerWebExchange ;
52
62
53
63
import static org .assertj .core .api .Assertions .assertThat ;
@@ -69,10 +79,11 @@ public class DispatcherHandlerErrorTests {
69
79
70
80
@ BeforeEach
71
81
public void setup () {
72
- AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext ();
73
- ctx .register (TestConfig .class );
74
- ctx .refresh ();
75
- this .dispatcherHandler = new DispatcherHandler (ctx );
82
+ AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext ();
83
+ context .register (TestConfig .class );
84
+ context .refresh ();
85
+
86
+ this .dispatcherHandler = new DispatcherHandler (context );
76
87
}
77
88
78
89
@@ -94,6 +105,28 @@ public void noHandler() {
94
105
StepVerifier .create (mono ).consumeErrorWith (ex -> assertThat (ex ).isNotSameAs (exceptionRef .get ())).verify ();
95
106
}
96
107
108
+ @ Test
109
+ public void noStaticResource () {
110
+ AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext ();
111
+ context .register (StaticResourceConfig .class );
112
+ context .refresh ();
113
+
114
+ MockServerHttpRequest request = MockServerHttpRequest .get ("/resources/non-existing" ).build ();
115
+ MockServerWebExchange exchange = MockServerWebExchange .from (request );
116
+ new DispatcherHandler (context ).handle (exchange ).block ();
117
+
118
+ MockServerHttpResponse response = exchange .getResponse ();
119
+ assertThat (response .getStatusCode ()).isEqualTo (HttpStatus .NOT_FOUND );
120
+ assertThat (response .getHeaders ().getContentType ()).isEqualTo (MediaType .APPLICATION_PROBLEM_JSON );
121
+ assertThat (response .getBodyAsString ().block ()).isEqualTo ("""
122
+ {"type":"about:blank",\
123
+ "title":"Not Found",\
124
+ "status":404,\
125
+ "detail":"No static resource non-existing.",\
126
+ "instance":"/resources/non-existing"}\
127
+ """ );
128
+ }
129
+
97
130
@ Test
98
131
public void controllerReturnsMonoError () {
99
132
MockServerWebExchange exchange = MockServerWebExchange .from (MockServerHttpRequest .get ("/error-signal" ));
@@ -223,6 +256,50 @@ private static class Foo {
223
256
}
224
257
225
258
259
+ @ Configuration
260
+ @ SuppressWarnings ({"unused" , "WeakerAccess" })
261
+ static class StaticResourceConfig {
262
+
263
+ @ Bean
264
+ public SimpleUrlHandlerMapping resourceMapping (ResourceWebHandler resourceWebHandler ) {
265
+ SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping ();
266
+ mapping .setUrlMap (Map .of ("/resources/**" , resourceWebHandler ));
267
+ return mapping ;
268
+ }
269
+
270
+ @ Bean
271
+ public RequestMappingHandlerAdapter requestMappingHandlerAdapter () {
272
+ return new RequestMappingHandlerAdapter ();
273
+ }
274
+
275
+ @ Bean
276
+ public SimpleHandlerAdapter simpleHandlerAdapter () {
277
+ return new SimpleHandlerAdapter ();
278
+ }
279
+
280
+ @ Bean
281
+ public ResourceWebHandler resourceWebHandler () {
282
+ return new ResourceWebHandler ();
283
+ }
284
+
285
+ @ Bean
286
+ public ResponseEntityResultHandler responseEntityResultHandler () {
287
+ ServerCodecConfigurer configurer = ServerCodecConfigurer .create ();
288
+ return new ResponseEntityResultHandler (configurer .getWriters (), new HeaderContentTypeResolver ());
289
+ }
290
+
291
+ @ Bean
292
+ GlobalExceptionHandler globalExceptionHandler () {
293
+ return new GlobalExceptionHandler ();
294
+ }
295
+ }
296
+
297
+
298
+ @ ControllerAdvice
299
+ private static class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
300
+ }
301
+
302
+
226
303
private static class ServerError500ExceptionHandler implements WebExceptionHandler {
227
304
228
305
@ Override
0 commit comments