Skip to content

Commit 37592ea

Browse files
committed
DefaultWebFilterChain is a top-level, public class
Issue: SPR-15348
1 parent ab7db41 commit 37592ea

File tree

3 files changed

+113
-70
lines changed

3 files changed

+113
-70
lines changed
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* Copyright 2002-2017 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.web.server.handler;
17+
18+
import java.util.Arrays;
19+
import java.util.Collections;
20+
import java.util.List;
21+
22+
import reactor.core.publisher.Mono;
23+
24+
import org.springframework.util.Assert;
25+
import org.springframework.util.ObjectUtils;
26+
import org.springframework.web.server.ServerWebExchange;
27+
import org.springframework.web.server.WebFilter;
28+
import org.springframework.web.server.WebFilterChain;
29+
import org.springframework.web.server.WebHandler;
30+
31+
/**
32+
* Default implementation of {@link WebFilterChain}.
33+
*
34+
* @author Rossen Stoyanchev
35+
* @since 5.0
36+
*/
37+
public class DefaultWebFilterChain implements WebFilterChain {
38+
39+
private final List<WebFilter> filters;
40+
41+
private final WebHandler handler;
42+
43+
private volatile int index;
44+
45+
46+
public DefaultWebFilterChain(WebHandler handler, WebFilter... filters) {
47+
Assert.notNull(handler, "WebHandler is required");
48+
this.filters = ObjectUtils.isEmpty(filters) ? Collections.emptyList() : Arrays.asList(filters);
49+
this.handler = handler;
50+
}
51+
52+
53+
@Override
54+
public Mono<Void> filter(ServerWebExchange exchange) {
55+
if (this.index < this.filters.size()) {
56+
WebFilter filter = this.filters.get(this.index++);
57+
return filter.filter(exchange, this);
58+
}
59+
else {
60+
return this.handler.handle(exchange);
61+
}
62+
}
63+
64+
}

spring-web/src/main/java/org/springframework/web/server/handler/FilteringWebHandler.java

Lines changed: 10 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,15 @@
1616

1717
package org.springframework.web.server.handler;
1818

19+
import java.util.Arrays;
1920
import java.util.Collections;
2021
import java.util.List;
2122

2223
import reactor.core.publisher.Mono;
2324

25+
import org.springframework.util.CollectionUtils;
2426
import org.springframework.web.server.ServerWebExchange;
2527
import org.springframework.web.server.WebFilter;
26-
import org.springframework.web.server.WebFilterChain;
2728
import org.springframework.web.server.WebHandler;
2829

2930
/**
@@ -35,7 +36,7 @@
3536
*/
3637
public class FilteringWebHandler extends WebHandlerDecorator {
3738

38-
private final List<WebFilter> filters;
39+
private final WebFilter[] filters;
3940

4041

4142
/**
@@ -44,41 +45,24 @@ public class FilteringWebHandler extends WebHandlerDecorator {
4445
*/
4546
public FilteringWebHandler(WebHandler webHandler, List<WebFilter> filters) {
4647
super(webHandler);
47-
this.filters = Collections.unmodifiableList(filters);
48+
this.filters = !CollectionUtils.isEmpty(filters) ?
49+
filters.toArray(new WebFilter[filters.size()]) : new WebFilter[0];
4850
}
4951

5052

5153
/**
52-
* Return read-only list of the configured filters.
54+
* Return a read-only list of the configured filters.
5355
*/
5456
public List<WebFilter> getFilters() {
55-
return this.filters;
57+
return Arrays.asList(this.filters);
5658
}
5759

5860

5961
@Override
6062
public Mono<Void> handle(ServerWebExchange exchange) {
61-
if (this.filters.isEmpty()) {
62-
return super.handle(exchange);
63-
}
64-
return new DefaultWebFilterChain().filter(exchange);
65-
}
66-
67-
68-
private class DefaultWebFilterChain implements WebFilterChain {
69-
70-
private int index;
71-
72-
@Override
73-
public Mono<Void> filter(ServerWebExchange exchange) {
74-
if (this.index < filters.size()) {
75-
WebFilter filter = filters.get(this.index++);
76-
return filter.filter(exchange, this);
77-
}
78-
else {
79-
return getDelegate().handle(exchange);
80-
}
81-
}
63+
return this.filters.length != 0 ?
64+
new DefaultWebFilterChain(getDelegate(), this.filters).filter(exchange) :
65+
super.handle(exchange);
8266
}
8367

8468
}

spring-web/src/test/java/org/springframework/web/server/handler/FilteringWebHandlerTests.java

Lines changed: 39 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,16 @@
1616

1717
package org.springframework.web.server.handler;
1818

19+
import java.time.Duration;
1920
import java.util.Arrays;
2021
import java.util.Collections;
21-
import java.util.List;
2222

2323
import org.apache.commons.logging.Log;
2424
import org.apache.commons.logging.LogFactory;
25-
import org.junit.Before;
2625
import org.junit.Test;
2726
import reactor.core.publisher.Mono;
2827

2928
import org.springframework.http.HttpStatus;
30-
import org.springframework.http.server.reactive.HttpHandler;
3129
import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest;
3230
import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse;
3331
import org.springframework.web.server.ServerWebExchange;
@@ -49,89 +47,86 @@ public class FilteringWebHandlerTests {
4947

5048
private static Log logger = LogFactory.getLog(FilteringWebHandlerTests.class);
5149

52-
private MockServerHttpRequest request;
53-
54-
private MockServerHttpResponse response;
55-
56-
57-
@Before
58-
public void setUp() throws Exception {
59-
this.request = MockServerHttpRequest.get("http://localhost").build();
60-
this.response = new MockServerHttpResponse();
61-
}
62-
6350

6451
@Test
6552
public void multipleFilters() throws Exception {
66-
StubWebHandler webHandler = new StubWebHandler();
53+
6754
TestFilter filter1 = new TestFilter();
6855
TestFilter filter2 = new TestFilter();
6956
TestFilter filter3 = new TestFilter();
70-
HttpHandler httpHandler = createHttpHandler(webHandler, filter1, filter2, filter3);
71-
httpHandler.handle(this.request, this.response).block();
57+
StubWebHandler targetHandler = new StubWebHandler();
58+
59+
new FilteringWebHandler(targetHandler, Arrays.asList(filter1, filter2, filter3))
60+
.handle(MockServerHttpRequest.get("/").toExchange())
61+
.block(Duration.ZERO);
7262

7363
assertTrue(filter1.invoked());
7464
assertTrue(filter2.invoked());
7565
assertTrue(filter3.invoked());
76-
assertTrue(webHandler.invoked());
66+
assertTrue(targetHandler.invoked());
7767
}
7868

7969
@Test
8070
public void zeroFilters() throws Exception {
81-
StubWebHandler webHandler = new StubWebHandler();
82-
HttpHandler httpHandler = createHttpHandler(webHandler);
83-
httpHandler.handle(this.request, this.response).block();
8471

85-
assertTrue(webHandler.invoked());
72+
StubWebHandler targetHandler = new StubWebHandler();
73+
74+
new FilteringWebHandler(targetHandler, Collections.emptyList())
75+
.handle(MockServerHttpRequest.get("/").toExchange())
76+
.block(Duration.ZERO);
77+
78+
assertTrue(targetHandler.invoked());
8679
}
8780

8881
@Test
8982
public void shortcircuitFilter() throws Exception {
90-
StubWebHandler webHandler = new StubWebHandler();
83+
9184
TestFilter filter1 = new TestFilter();
9285
ShortcircuitingFilter filter2 = new ShortcircuitingFilter();
9386
TestFilter filter3 = new TestFilter();
94-
HttpHandler httpHandler = createHttpHandler(webHandler, filter1, filter2, filter3);
95-
httpHandler.handle(this.request, this.response).block();
87+
StubWebHandler targetHandler = new StubWebHandler();
88+
89+
new FilteringWebHandler(targetHandler, Arrays.asList(filter1, filter2, filter3))
90+
.handle(MockServerHttpRequest.get("/").toExchange())
91+
.block(Duration.ZERO);
9692

9793
assertTrue(filter1.invoked());
9894
assertTrue(filter2.invoked());
9995
assertFalse(filter3.invoked());
100-
assertFalse(webHandler.invoked());
96+
assertFalse(targetHandler.invoked());
10197
}
10298

10399
@Test
104100
public void asyncFilter() throws Exception {
105-
StubWebHandler webHandler = new StubWebHandler();
101+
106102
AsyncFilter filter = new AsyncFilter();
107-
HttpHandler httpHandler = createHttpHandler(webHandler, filter);
108-
httpHandler.handle(this.request, this.response).block();
103+
StubWebHandler targetHandler = new StubWebHandler();
104+
105+
new FilteringWebHandler(targetHandler, Collections.singletonList(filter))
106+
.handle(MockServerHttpRequest.get("/").toExchange())
107+
.block(Duration.ZERO);
109108

110109
assertTrue(filter.invoked());
111-
assertTrue(webHandler.invoked());
110+
assertTrue(targetHandler.invoked());
112111
}
113112

114113
@Test
115114
public void handleErrorFromFilter() throws Exception {
115+
116+
MockServerHttpRequest request = MockServerHttpRequest.get("/").build();
117+
MockServerHttpResponse response = new MockServerHttpResponse();
118+
116119
TestExceptionHandler exceptionHandler = new TestExceptionHandler();
117-
List<ExceptionFilter> filters = Collections.singletonList(new ExceptionFilter());
118-
List<WebExceptionHandler> exceptionHandlers = Collections.singletonList(exceptionHandler);
119120

120121
WebHttpHandlerBuilder.webHandler(new StubWebHandler())
121-
.filters(filters).exceptionHandlers(exceptionHandlers).build()
122-
.handle(this.request, this.response)
122+
.filters(Collections.singletonList(new ExceptionFilter()))
123+
.exceptionHandlers(Collections.singletonList(exceptionHandler)).build()
124+
.handle(request, response)
123125
.block();
124126

125-
assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, this.response.getStatusCode());
126-
127-
Throwable savedException = exceptionHandler.ex;
128-
assertNotNull(savedException);
129-
assertEquals("boo", savedException.getMessage());
130-
}
131-
132-
133-
private HttpHandler createHttpHandler(StubWebHandler webHandler, WebFilter... filters) {
134-
return WebHttpHandlerBuilder.webHandler(webHandler).filters(Arrays.asList(filters)).build();
127+
assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, response.getStatusCode());
128+
assertNotNull(exceptionHandler.ex);
129+
assertEquals("boo", exceptionHandler.ex.getMessage());
135130
}
136131

137132

0 commit comments

Comments
 (0)