Skip to content

Commit 28f98b3

Browse files
committed
Improve Error Message
Closes gh-13667
1 parent ed96e2c commit 28f98b3

File tree

2 files changed

+23
-4
lines changed

2 files changed

+23
-4
lines changed

config/src/main/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistry.java

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import java.util.ArrayList;
2020
import java.util.Arrays;
21+
import java.util.Collection;
2122
import java.util.LinkedHashMap;
2223
import java.util.List;
2324
import java.util.Map;
@@ -320,14 +321,17 @@ public C requestMatchers(HttpMethod method, String... patterns) {
320321
if (!hasDispatcherServlet(registrations)) {
321322
return requestMatchers(RequestMatchers.antMatchersAsArray(method, patterns));
322323
}
323-
Assert.isTrue(registrations.size() == 1,
324-
"This method cannot decide whether these patterns are Spring MVC patterns or not. If this endpoint is a Spring MVC endpoint, please use requestMatchers(MvcRequestMatcher); otherwise, please use requestMatchers(AntPathRequestMatcher).");
324+
if (registrations.size() > 1) {
325+
String errorMessage = computeErrorMessage(registrations.values());
326+
throw new IllegalArgumentException(errorMessage);
327+
}
325328
return requestMatchers(createMvcMatchers(method, patterns).toArray(new RequestMatcher[0]));
326329
}
327330

328331
private Map<String, ? extends ServletRegistration> mappableServletRegistrations(ServletContext servletContext) {
329332
Map<String, ServletRegistration> mappable = new LinkedHashMap<>();
330-
for (Map.Entry<String, ? extends ServletRegistration> entry : servletContext.getServletRegistrations().entrySet()) {
333+
for (Map.Entry<String, ? extends ServletRegistration> entry : servletContext.getServletRegistrations()
334+
.entrySet()) {
331335
if (!entry.getValue().getMappings().isEmpty()) {
332336
mappable.put(entry.getKey(), entry.getValue());
333337
}
@@ -355,6 +359,19 @@ private boolean hasDispatcherServlet(Map<String, ? extends ServletRegistration>
355359
return false;
356360
}
357361

362+
private String computeErrorMessage(Collection<? extends ServletRegistration> registrations) {
363+
String template = "This method cannot decide whether these patterns are Spring MVC patterns or not. "
364+
+ "If this endpoint is a Spring MVC endpoint, please use requestMatchers(MvcRequestMatcher); "
365+
+ "otherwise, please use requestMatchers(AntPathRequestMatcher).\n\n"
366+
+ "This is because there is more than one mappable servlet in your servlet context: %s.\n\n"
367+
+ "For each MvcRequestMatcher, call MvcRequestMatcher#setServletPath to indicate the servlet path.";
368+
Map<String, Collection<String>> mappings = new LinkedHashMap<>();
369+
for (ServletRegistration registration : registrations) {
370+
mappings.put(registration.getClassName(), registration.getMappings());
371+
}
372+
return String.format(template, mappings);
373+
}
374+
358375
/**
359376
* <p>
360377
* If the {@link HandlerMappingIntrospector} is available in the classpath, maps to an

config/src/test/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistryTests.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,13 @@ public <O> O postProcess(O object) {
6363
private WebApplicationContext context;
6464

6565
@BeforeEach
66-
public void setUp() {
66+
public void setUp() throws Exception {
6767
this.matcherRegistry = new TestRequestMatcherRegistry();
6868
this.context = mock(WebApplicationContext.class);
6969
given(this.context.getBean(ObjectPostProcessor.class)).willReturn(NO_OP_OBJECT_POST_PROCESSOR);
7070
given(this.context.getServletContext()).willReturn(MockServletContext.mvc());
7171
this.matcherRegistry.setApplicationContext(this.context);
72+
mockMvcPresentClasspath(true);
7273
}
7374

7475
@Test
@@ -219,6 +220,7 @@ public void requestMatchersWhenAmbiguousServletsThenException() {
219220

220221
@Test
221222
public void requestMatchersWhenUnmappableServletsThenSkips() {
223+
mockMvcIntrospector(true);
222224
MockServletContext servletContext = new MockServletContext();
223225
given(this.context.getServletContext()).willReturn(servletContext);
224226
servletContext.addServlet("dispatcherServlet", DispatcherServlet.class).addMapping("/");

0 commit comments

Comments
 (0)