Commit decaacdd authored by Madhura Bhave's avatar Madhura Bhave

Account for application path for Jersey servlet endpoints

Closes gh-14895
parent 8560010b
...@@ -28,6 +28,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClas ...@@ -28,6 +28,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClas
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletPath; import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletPath;
import org.springframework.boot.autoconfigure.web.servlet.JerseyApplicationPath;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
...@@ -82,11 +83,21 @@ public class ServletEndpointManagementContextConfiguration { ...@@ -82,11 +83,21 @@ public class ServletEndpointManagementContextConfiguration {
@ConditionalOnMissingClass("org.springframework.web.servlet.DispatcherServlet") @ConditionalOnMissingClass("org.springframework.web.servlet.DispatcherServlet")
public static class JerseyServletEndpointManagementContextConfiguration { public static class JerseyServletEndpointManagementContextConfiguration {
private final ApplicationContext context;
public JerseyServletEndpointManagementContextConfiguration(
ApplicationContext context) {
this.context = context;
}
@Bean @Bean
public ServletEndpointRegistrar servletEndpointRegistrar( public ServletEndpointRegistrar servletEndpointRegistrar(
WebEndpointProperties properties, WebEndpointProperties properties,
ServletEndpointsSupplier servletEndpointsSupplier) { ServletEndpointsSupplier servletEndpointsSupplier) {
return new ServletEndpointRegistrar(properties.getBasePath(), JerseyApplicationPath jerseyApplicationPath = this.context
.getBean(JerseyApplicationPath.class);
return new ServletEndpointRegistrar(
jerseyApplicationPath.getRelativePath(properties.getBasePath()),
servletEndpointsSupplier.getEndpoints()); servletEndpointsSupplier.getEndpoints());
} }
......
...@@ -156,7 +156,7 @@ public abstract class AbstractEndpointRequestIntegrationTests { ...@@ -156,7 +156,7 @@ public abstract class AbstractEndpointRequestIntegrationTests {
} }
interface TestPathMappedEndpoint public interface TestPathMappedEndpoint
extends ExposableEndpoint<Operation>, PathMappedEndpoint { extends ExposableEndpoint<Operation>, PathMappedEndpoint {
} }
......
...@@ -23,6 +23,7 @@ import java.util.List; ...@@ -23,6 +23,7 @@ import java.util.List;
import org.glassfish.jersey.server.ResourceConfig; import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.server.model.Resource; import org.glassfish.jersey.server.model.Resource;
import org.junit.Test;
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties; import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
import org.springframework.boot.actuate.endpoint.http.ActuatorMediaType; import org.springframework.boot.actuate.endpoint.http.ActuatorMediaType;
...@@ -41,12 +42,14 @@ import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfi ...@@ -41,12 +42,14 @@ import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfi
import org.springframework.boot.autoconfigure.security.servlet.SecurityRequestMatcherProviderAutoConfiguration; import org.springframework.boot.autoconfigure.security.servlet.SecurityRequestMatcherProviderAutoConfiguration;
import org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration; import org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.test.context.FilteredClassLoader;
import org.springframework.boot.test.context.runner.WebApplicationContextRunner; import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext; import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.test.web.reactive.server.WebTestClient;
/** /**
* Integration tests for {@link EndpointRequest} with Jersey. * Integration tests for {@link EndpointRequest} with Jersey.
...@@ -60,6 +63,8 @@ public class JerseyEndpointRequestIntegrationTests ...@@ -60,6 +63,8 @@ public class JerseyEndpointRequestIntegrationTests
protected WebApplicationContextRunner getContextRunner() { protected WebApplicationContextRunner getContextRunner() {
return new WebApplicationContextRunner( return new WebApplicationContextRunner(
AnnotationConfigServletWebServerApplicationContext::new) AnnotationConfigServletWebServerApplicationContext::new)
.withClassLoader(new FilteredClassLoader(
"org.springframework.web.servlet.DispatcherServlet"))
.withUserConfiguration(JerseyEndpointConfiguration.class, .withUserConfiguration(JerseyEndpointConfiguration.class,
SecurityConfiguration.class, BaseConfiguration.class) SecurityConfiguration.class, BaseConfiguration.class)
.withConfiguration(AutoConfigurations.of( .withConfiguration(AutoConfigurations.of(
...@@ -70,6 +75,41 @@ public class JerseyEndpointRequestIntegrationTests ...@@ -70,6 +75,41 @@ public class JerseyEndpointRequestIntegrationTests
JerseyAutoConfiguration.class)); JerseyAutoConfiguration.class));
} }
@Test
public void toLinksWhenApplicationPathSetShouldMatch() {
getContextRunner().withPropertyValues("spring.jersey.application-path=/admin")
.run((context) -> {
WebTestClient webTestClient = getWebTestClient(context);
webTestClient.get().uri("/admin/actuator/").exchange().expectStatus()
.isOk();
webTestClient.get().uri("/admin/actuator").exchange().expectStatus()
.isOk();
});
}
@Test
public void toEndpointWhenApplicationPathSetShouldMatch() {
getContextRunner().withPropertyValues("spring.jersey.application-path=/admin")
.run((context) -> {
WebTestClient webTestClient = getWebTestClient(context);
webTestClient.get().uri("/admin/actuator/e1").exchange()
.expectStatus().isOk();
});
}
@Test
public void toAnyEndpointWhenApplicationPathSetShouldMatch() {
getContextRunner().withPropertyValues("spring.jersey.application-path=/admin",
"spring.security.user.password=password").run((context) -> {
WebTestClient webTestClient = getWebTestClient(context);
webTestClient.get().uri("/admin/actuator/e2").exchange()
.expectStatus().isUnauthorized();
webTestClient.get().uri("/admin/actuator/e2")
.header("Authorization", getBasicAuth()).exchange()
.expectStatus().isOk();
});
}
@Configuration @Configuration
@EnableConfigurationProperties(WebEndpointProperties.class) @EnableConfigurationProperties(WebEndpointProperties.class)
static class JerseyEndpointConfiguration { static class JerseyEndpointConfiguration {
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
package org.springframework.boot.autoconfigure.jersey; package org.springframework.boot.autoconfigure.jersey;
import java.util.Arrays; import java.util.Collections;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.List; import java.util.List;
...@@ -53,6 +53,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplicat ...@@ -53,6 +53,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplicat
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration; import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration; import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration;
import org.springframework.boot.autoconfigure.web.servlet.JerseyApplicationPath;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.DynamicRegistrationBean; import org.springframework.boot.web.servlet.DynamicRegistrationBean;
import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.boot.web.servlet.FilterRegistrationBean;
...@@ -96,8 +97,6 @@ public class JerseyAutoConfiguration implements ServletContextAware { ...@@ -96,8 +97,6 @@ public class JerseyAutoConfiguration implements ServletContextAware {
private final List<ResourceConfigCustomizer> customizers; private final List<ResourceConfigCustomizer> customizers;
private String path;
public JerseyAutoConfiguration(JerseyProperties jersey, ResourceConfig config, public JerseyAutoConfiguration(JerseyProperties jersey, ResourceConfig config,
ObjectProvider<List<ResourceConfigCustomizer>> customizers) { ObjectProvider<List<ResourceConfigCustomizer>> customizers) {
this.jersey = jersey; this.jersey = jersey;
...@@ -107,16 +106,15 @@ public class JerseyAutoConfiguration implements ServletContextAware { ...@@ -107,16 +106,15 @@ public class JerseyAutoConfiguration implements ServletContextAware {
@PostConstruct @PostConstruct
public void path() { public void path() {
resolveApplicationPath();
customize(); customize();
} }
private void resolveApplicationPath() { private String resolveApplicationPath() {
if (StringUtils.hasLength(this.jersey.getApplicationPath())) { if (StringUtils.hasLength(this.jersey.getApplicationPath())) {
this.path = parseApplicationPath(this.jersey.getApplicationPath()); return this.jersey.getApplicationPath();
} }
else { else {
this.path = findApplicationPath(AnnotationUtils.findAnnotation( return findApplicationPath(AnnotationUtils.findAnnotation(
this.config.getApplication().getClass(), ApplicationPath.class)); this.config.getApplication().getClass(), ApplicationPath.class));
} }
} }
...@@ -130,6 +128,12 @@ public class JerseyAutoConfiguration implements ServletContextAware { ...@@ -130,6 +128,12 @@ public class JerseyAutoConfiguration implements ServletContextAware {
} }
} }
@Bean
@ConditionalOnMissingBean
public JerseyApplicationPath jerseyApplicationPath() {
return this::resolveApplicationPath;
}
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
public FilterRegistrationBean<RequestContextFilter> requestContextFilter() { public FilterRegistrationBean<RequestContextFilter> requestContextFilter() {
...@@ -143,13 +147,15 @@ public class JerseyAutoConfiguration implements ServletContextAware { ...@@ -143,13 +147,15 @@ public class JerseyAutoConfiguration implements ServletContextAware {
@Bean @Bean
@ConditionalOnMissingBean(name = "jerseyFilterRegistration") @ConditionalOnMissingBean(name = "jerseyFilterRegistration")
@ConditionalOnProperty(prefix = "spring.jersey", name = "type", havingValue = "filter") @ConditionalOnProperty(prefix = "spring.jersey", name = "type", havingValue = "filter")
public FilterRegistrationBean<ServletContainer> jerseyFilterRegistration() { public FilterRegistrationBean<ServletContainer> jerseyFilterRegistration(
JerseyApplicationPath applicationPath) {
FilterRegistrationBean<ServletContainer> registration = new FilterRegistrationBean<>(); FilterRegistrationBean<ServletContainer> registration = new FilterRegistrationBean<>();
registration.setFilter(new ServletContainer(this.config)); registration.setFilter(new ServletContainer(this.config));
registration.setUrlPatterns(Arrays.asList(this.path)); registration.setUrlPatterns(
Collections.singletonList(applicationPath.getUrlMapping()));
registration.setOrder(this.jersey.getFilter().getOrder()); registration.setOrder(this.jersey.getFilter().getOrder());
registration.addInitParameter(ServletProperties.FILTER_CONTEXT_PATH, registration.addInitParameter(ServletProperties.FILTER_CONTEXT_PATH,
stripPattern(this.path)); stripPattern(applicationPath.getPath()));
addInitParameters(registration); addInitParameters(registration);
registration.setName("jerseyFilter"); registration.setName("jerseyFilter");
registration.setDispatcherTypes(EnumSet.allOf(DispatcherType.class)); registration.setDispatcherTypes(EnumSet.allOf(DispatcherType.class));
...@@ -166,9 +172,10 @@ public class JerseyAutoConfiguration implements ServletContextAware { ...@@ -166,9 +172,10 @@ public class JerseyAutoConfiguration implements ServletContextAware {
@Bean @Bean
@ConditionalOnMissingBean(name = "jerseyServletRegistration") @ConditionalOnMissingBean(name = "jerseyServletRegistration")
@ConditionalOnProperty(prefix = "spring.jersey", name = "type", havingValue = "servlet", matchIfMissing = true) @ConditionalOnProperty(prefix = "spring.jersey", name = "type", havingValue = "servlet", matchIfMissing = true)
public ServletRegistrationBean<ServletContainer> jerseyServletRegistration() { public ServletRegistrationBean<ServletContainer> jerseyServletRegistration(
JerseyApplicationPath applicationPath) {
ServletRegistrationBean<ServletContainer> registration = new ServletRegistrationBean<>( ServletRegistrationBean<ServletContainer> registration = new ServletRegistrationBean<>(
new ServletContainer(this.config), this.path); new ServletContainer(this.config), applicationPath.getUrlMapping());
addInitParameters(registration); addInitParameters(registration);
registration.setName(getServletRegistrationName()); registration.setName(getServletRegistrationName());
registration.setLoadOnStartup(this.jersey.getServlet().getLoadOnStartup()); registration.setLoadOnStartup(this.jersey.getServlet().getLoadOnStartup());
...@@ -188,14 +195,7 @@ public class JerseyAutoConfiguration implements ServletContextAware { ...@@ -188,14 +195,7 @@ public class JerseyAutoConfiguration implements ServletContextAware {
if (annotation == null) { if (annotation == null) {
return "/*"; return "/*";
} }
return parseApplicationPath(annotation.value()); return annotation.value();
}
private static String parseApplicationPath(String applicationPath) {
if (!applicationPath.startsWith("/")) {
applicationPath = "/" + applicationPath;
}
return applicationPath.equals("/") ? "/*" : applicationPath + "/*";
} }
@Override @Override
......
/*
* Copyright 2012-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.security.servlet;
import org.springframework.boot.autoconfigure.web.servlet.JerseyApplicationPath;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
/**
* {@link RequestMatcherProvider} that provides an {@link AntPathRequestMatcher} that can
* be used for Jersey applications.
*
* @author Madhura Bhave
* @since 2.0.7
*/
public class JerseyRequestMatcherProvider implements RequestMatcherProvider {
private final JerseyApplicationPath jerseyApplicationPath;
public JerseyRequestMatcherProvider(JerseyApplicationPath jerseyApplicationPath) {
this.jerseyApplicationPath = jerseyApplicationPath;
}
@Override
public RequestMatcher getRequestMatcher(String pattern) {
return new AntPathRequestMatcher(
this.jerseyApplicationPath.getRelativePath(pattern));
}
}
...@@ -15,9 +15,13 @@ ...@@ -15,9 +15,13 @@
*/ */
package org.springframework.boot.autoconfigure.security.servlet; package org.springframework.boot.autoconfigure.security.servlet;
import org.glassfish.jersey.server.ResourceConfig;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.web.servlet.JerseyApplicationPath;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.security.web.util.matcher.RequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher;
...@@ -31,15 +35,36 @@ import org.springframework.web.servlet.handler.HandlerMappingIntrospector; ...@@ -31,15 +35,36 @@ import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
* @since 2.0.5 * @since 2.0.5
*/ */
@Configuration @Configuration
@ConditionalOnClass({ RequestMatcher.class, DispatcherServlet.class }) @ConditionalOnClass({ RequestMatcher.class })
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
@ConditionalOnBean(HandlerMappingIntrospector.class)
public class SecurityRequestMatcherProviderAutoConfiguration { public class SecurityRequestMatcherProviderAutoConfiguration {
@Bean @Configuration
public RequestMatcherProvider requestMatcherProvider( @ConditionalOnClass(DispatcherServlet.class)
HandlerMappingIntrospector introspector) { @ConditionalOnBean(HandlerMappingIntrospector.class)
return new MvcRequestMatcherProvider(introspector); public static class MvcRequestMatcherConfiguration {
@Bean
@ConditionalOnClass(DispatcherServlet.class)
public RequestMatcherProvider requestMatcherProvider(
HandlerMappingIntrospector introspector) {
return new MvcRequestMatcherProvider(introspector);
}
}
@Configuration
@ConditionalOnClass(ResourceConfig.class)
@ConditionalOnMissingClass("org.springframework.web.servlet.DispatcherServlet")
@ConditionalOnBean(JerseyApplicationPath.class)
public static class JerseyRequestMatcherConfiguration {
@Bean
public RequestMatcherProvider requestMatcherProvider(
JerseyApplicationPath applicationPath) {
return new JerseyRequestMatcherProvider(applicationPath);
}
} }
} }
/*
* Copyright 2012-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.web.servlet;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
/**
* Interface that can be used by auto-configurations that need path details Jersey's
* application path that serves as the base URI for the application.
*
* @author Madhura Bhave
* @since 2.0.7
*/
@FunctionalInterface
public interface JerseyApplicationPath {
/**
* Returns the configured path of the application.
* @return the configured path
*/
String getPath();
/**
* Return a form of the given path that's relative to the Jersey application path.
* @param path the path to make relative
* @return the relative path
*/
default String getRelativePath(String path) {
String prefix = getPrefix();
if (!path.startsWith("/")) {
path = "/" + path;
}
return prefix + path;
}
/**
* Return a cleaned up version of the path that can be used as a prefix for URLs. The
* resulting path will have path will not have a trailing slash.
* @return the prefix
* @see #getRelativePath(String)
*/
default String getPrefix() {
String result = getPath();
int index = result.indexOf('*');
if (index != -1) {
result = result.substring(0, index);
}
if (result.endsWith("/")) {
result = result.substring(0, result.length() - 1);
}
return result;
}
/**
* Return a URL mapping pattern that can be used with a
* {@link ServletRegistrationBean} to map Jersey's servlet.
* @return the path as a servlet URL mapping
*/
default String getUrlMapping() {
String path = getPath();
if (!path.startsWith("/")) {
path = "/" + path;
}
if (path.equals("/")) {
return "/*";
}
if (path.contains("*")) {
return path;
}
if (path.endsWith("/")) {
return path + "*";
}
return path + "/*";
}
}
...@@ -18,6 +18,7 @@ package org.springframework.boot.autoconfigure.security.servlet; ...@@ -18,6 +18,7 @@ package org.springframework.boot.autoconfigure.security.servlet;
import org.junit.Test; import org.junit.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.web.servlet.JerseyApplicationPath;
import org.springframework.boot.test.context.FilteredClassLoader; import org.springframework.boot.test.context.FilteredClassLoader;
import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.boot.test.context.runner.WebApplicationContextRunner; import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
...@@ -36,23 +37,44 @@ public class SecurityRequestMatcherProviderAutoConfigurationTests { ...@@ -36,23 +37,44 @@ public class SecurityRequestMatcherProviderAutoConfigurationTests {
private WebApplicationContextRunner contextRunner = new WebApplicationContextRunner() private WebApplicationContextRunner contextRunner = new WebApplicationContextRunner()
.withConfiguration(AutoConfigurations .withConfiguration(AutoConfigurations
.of(SecurityRequestMatcherProviderAutoConfiguration.class)) .of(SecurityRequestMatcherProviderAutoConfiguration.class));
.withUserConfiguration(TestConfiguration.class);
@Test
public void configurationConditionalOnWebApplication() {
new ApplicationContextRunner()
.withConfiguration(AutoConfigurations
.of(SecurityRequestMatcherProviderAutoConfiguration.class))
.withUserConfiguration(TestMvcConfiguration.class)
.run((context) -> assertThat(context)
.doesNotHaveBean(RequestMatcherProvider.class));
}
@Test
public void configurationConditionalOnRequestMatcherClass() {
this.contextRunner
.withClassLoader(new FilteredClassLoader(
"org.springframework.security.web.util.matcher.RequestMatcher"))
.run((context) -> assertThat(context)
.doesNotHaveBean(RequestMatcherProvider.class));
}
@Test @Test
public void registersMvcRequestMatcherProviderIfMvcPresent() { public void registersMvcRequestMatcherProviderIfMvcPresent() {
this.contextRunner.run((context) -> assertThat(context) this.contextRunner.withUserConfiguration(TestMvcConfiguration.class)
.hasSingleBean(MvcRequestMatcherProvider.class)); .run((context) -> assertThat(context)
.getBean(RequestMatcherProvider.class)
.isInstanceOf(MvcRequestMatcherProvider.class));
} }
@Test @Test
public void mvcRequestMatcherProviderConditionalOnWebApplication() { public void registersRequestMatcherForJerseyProviderIfJerseyPresentAndMvcAbsent() {
new ApplicationContextRunner() this.contextRunner
.withConfiguration(AutoConfigurations .withClassLoader(new FilteredClassLoader(
.of(SecurityRequestMatcherProviderAutoConfiguration.class)) "org.springframework.web.servlet.DispatcherServlet"))
.withUserConfiguration(TestConfiguration.class) .withUserConfiguration(TestJerseyConfiguration.class)
.run((context) -> assertThat(context) .run((context) -> assertThat(context)
.doesNotHaveBean(MvcRequestMatcherProvider.class)); .getBean(RequestMatcherProvider.class)
.isInstanceOf(JerseyRequestMatcherProvider.class));
} }
@Test @Test
...@@ -65,12 +87,12 @@ public class SecurityRequestMatcherProviderAutoConfigurationTests { ...@@ -65,12 +87,12 @@ public class SecurityRequestMatcherProviderAutoConfigurationTests {
} }
@Test @Test
public void mvcRequestMatcherProviderConditionalOnRequestMatcherClass() { public void jerseyRequestMatcherProviderConditionalOnResourceConfigClass() {
this.contextRunner this.contextRunner
.withClassLoader(new FilteredClassLoader( .withClassLoader(new FilteredClassLoader(
"org.springframework.security.web.util.matcher.RequestMatcher")) "org.glassfish.jersey.server.ResourceConfig"))
.run((context) -> assertThat(context) .run((context) -> assertThat(context)
.doesNotHaveBean(MvcRequestMatcherProvider.class)); .doesNotHaveBean(JerseyRequestMatcherProvider.class));
} }
@Test @Test
...@@ -82,8 +104,19 @@ public class SecurityRequestMatcherProviderAutoConfigurationTests { ...@@ -82,8 +104,19 @@ public class SecurityRequestMatcherProviderAutoConfigurationTests {
.doesNotHaveBean(MvcRequestMatcherProvider.class)); .doesNotHaveBean(MvcRequestMatcherProvider.class));
} }
@Test
public void jerseyRequestMatcherProviderConditionalOnJerseyApplicationPathBean() {
new WebApplicationContextRunner()
.withConfiguration(AutoConfigurations
.of(SecurityRequestMatcherProviderAutoConfiguration.class))
.withClassLoader(new FilteredClassLoader(
"org.springframework.web.servlet.DispatcherServlet"))
.run((context) -> assertThat(context)
.doesNotHaveBean(JerseyRequestMatcherProvider.class));
}
@Configuration @Configuration
static class TestConfiguration { static class TestMvcConfiguration {
@Bean @Bean
public HandlerMappingIntrospector introspector() { public HandlerMappingIntrospector introspector() {
...@@ -92,4 +125,14 @@ public class SecurityRequestMatcherProviderAutoConfigurationTests { ...@@ -92,4 +125,14 @@ public class SecurityRequestMatcherProviderAutoConfigurationTests {
} }
@Configuration
static class TestJerseyConfiguration {
@Bean
public JerseyApplicationPath jerseyApplicationPath() {
return () -> "/admin";
}
}
} }
/*
* Copyright 2012-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.web.servlet;
import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link JerseyApplicationPath}.
*
* @author Madhura Bhave
*/
public class JerseyApplicationPathTests {
@Test
public void getRelativePathReturnsRelativePath() {
assertThat(((JerseyApplicationPath) () -> "spring").getRelativePath("boot"))
.isEqualTo("spring/boot");
assertThat(((JerseyApplicationPath) () -> "spring/").getRelativePath("boot"))
.isEqualTo("spring/boot");
assertThat(((JerseyApplicationPath) () -> "spring").getRelativePath("/boot"))
.isEqualTo("spring/boot");
assertThat(((JerseyApplicationPath) () -> "spring/*").getRelativePath("/boot"))
.isEqualTo("spring/boot");
}
@Test
public void getPrefixWhenHasSimplePathReturnPath() {
assertThat(((JerseyApplicationPath) () -> "spring").getPrefix())
.isEqualTo("spring");
}
@Test
public void getPrefixWhenHasPatternRemovesPattern() {
assertThat(((JerseyApplicationPath) () -> "spring/*.do").getPrefix())
.isEqualTo("spring");
}
@Test
public void getPrefixWhenPathEndsWithSlashRemovesSlash() {
assertThat(((JerseyApplicationPath) () -> "spring/").getPrefix())
.isEqualTo("spring");
}
@Test
public void getUrlMappingWhenPathIsEmptyReturnsSlash() {
assertThat(((JerseyApplicationPath) () -> "").getUrlMapping()).isEqualTo("/*");
}
@Test
public void getUrlMappingWhenPathIsSlashReturnsSlash() {
assertThat(((JerseyApplicationPath) () -> "/").getUrlMapping()).isEqualTo("/*");
}
@Test
public void getUrlMappingWhenPathContainsStarReturnsPath() {
assertThat(((JerseyApplicationPath) () -> "/spring/*.do").getUrlMapping())
.isEqualTo("/spring/*.do");
}
@Test
public void getUrlMappingWhenHasPathNotEndingSlashReturnsSlashStarPattern() {
assertThat(((JerseyApplicationPath) () -> "/spring/boot").getUrlMapping())
.isEqualTo("/spring/boot/*");
}
@Test
public void getUrlMappingWhenHasPathDoesNotStartWithSlashPrependsSlash() {
assertThat(((JerseyApplicationPath) () -> "spring/boot").getUrlMapping())
.isEqualTo("/spring/boot/*");
}
@Test
public void getUrlMappingWhenHasPathEndingWithSlashReturnsSlashStarPattern() {
assertThat(((JerseyApplicationPath) () -> "/spring/boot/").getUrlMapping())
.isEqualTo("/spring/boot/*");
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment