Skip to content

Commit 20f4e90

Browse files
committed
UrlPathHelper cuts off trailing servlet-path slashes for root mappings (on WebSphere; SPR-7052)
1 parent c24bafd commit 20f4e90

File tree

3 files changed

+74
-14
lines changed

3 files changed

+74
-14
lines changed

org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/config/MvcNamespaceTests.java

Lines changed: 63 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,7 @@
3333
import org.springframework.format.annotation.DateTimeFormat;
3434
import org.springframework.format.annotation.DateTimeFormat.ISO;
3535
import org.springframework.format.support.FormattingConversionServiceFactoryBean;
36-
import org.springframework.http.converter.ByteArrayHttpMessageConverter;
37-
import org.springframework.http.converter.FormHttpMessageConverter;
3836
import org.springframework.http.converter.HttpMessageConverter;
39-
import org.springframework.http.converter.StringHttpMessageConverter;
40-
import org.springframework.http.converter.json.MappingJacksonHttpMessageConverter;
41-
import org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter;
42-
import org.springframework.http.converter.xml.SourceHttpMessageConverter;
4337
import org.springframework.mock.web.MockHttpServletRequest;
4438
import org.springframework.mock.web.MockHttpServletResponse;
4539
import org.springframework.mock.web.MockServletContext;
@@ -239,6 +233,7 @@ public void testViewControllers() throws Exception {
239233
mapping.setDefaultHandler(new TestController());
240234

241235
MockHttpServletRequest request = new MockHttpServletRequest();
236+
request.setMethod("GET");
242237

243238
HandlerExecutionChain chain = mapping.getHandler(request);
244239
assertEquals(4, chain.getInterceptors().length);
@@ -253,7 +248,6 @@ public void testViewControllers() throws Exception {
253248
assertNotNull(adapter);
254249

255250
request.setRequestURI("/foo");
256-
request.setMethod("GET");
257251
chain = mapping2.getHandler(request);
258252
assertEquals(4, chain.getInterceptors().length);
259253
assertTrue(chain.getInterceptors()[1] instanceof ConversionServiceExposingInterceptor);
@@ -262,16 +256,77 @@ public void testViewControllers() throws Exception {
262256
ModelAndView mv = adapter.handle(request, new MockHttpServletResponse(), chain.getHandler());
263257
assertNull(mv.getViewName());
264258

265-
request.setRequestURI("/bar");
259+
request.setRequestURI("/myapp/app/bar");
260+
request.setContextPath("/myapp");
261+
request.setServletPath("/app");
262+
chain = mapping2.getHandler(request);
263+
assertEquals(4, chain.getInterceptors().length);
264+
assertTrue(chain.getInterceptors()[1] instanceof ConversionServiceExposingInterceptor);
265+
assertTrue(chain.getInterceptors()[2] instanceof LocaleChangeInterceptor);
266+
assertTrue(chain.getInterceptors()[3] instanceof ThemeChangeInterceptor);
267+
ModelAndView mv2 = adapter.handle(request, new MockHttpServletResponse(), chain.getHandler());
268+
assertEquals("baz", mv2.getViewName());
269+
270+
request.setRequestURI("/myapp/app/");
271+
request.setContextPath("/myapp");
272+
request.setServletPath("/app");
266273
chain = mapping2.getHandler(request);
267274
assertEquals(4, chain.getInterceptors().length);
268275
assertTrue(chain.getInterceptors()[1] instanceof ConversionServiceExposingInterceptor);
269276
assertTrue(chain.getInterceptors()[2] instanceof LocaleChangeInterceptor);
270277
assertTrue(chain.getInterceptors()[3] instanceof ThemeChangeInterceptor);
278+
ModelAndView mv3 = adapter.handle(request, new MockHttpServletResponse(), chain.getHandler());
279+
assertEquals("root", mv3.getViewName());
280+
}
281+
282+
/** WebSphere gives trailing servlet path slashes by default!! */
283+
@Test
284+
public void testViewControllersOnWebSphere() throws Exception {
285+
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(appContext);
286+
reader.loadBeanDefinitions(new ClassPathResource("mvc-config-view-controllers.xml", getClass()));
287+
assertEquals(9, appContext.getBeanDefinitionCount());
288+
appContext.refresh();
289+
290+
SimpleUrlHandlerMapping mapping2 = appContext.getBean(SimpleUrlHandlerMapping.class);
291+
SimpleControllerHandlerAdapter adapter = appContext.getBean(SimpleControllerHandlerAdapter.class);
292+
293+
MockHttpServletRequest request = new MockHttpServletRequest();
294+
request.setMethod("GET");
295+
request.setRequestURI("/myapp/app/bar");
296+
request.setContextPath("/myapp");
297+
request.setServletPath("/app/");
298+
HandlerExecutionChain chain = mapping2.getHandler(request);
299+
assertEquals(4, chain.getInterceptors().length);
300+
assertTrue(chain.getInterceptors()[1] instanceof ConversionServiceExposingInterceptor);
301+
assertTrue(chain.getInterceptors()[2] instanceof LocaleChangeInterceptor);
302+
assertTrue(chain.getInterceptors()[3] instanceof ThemeChangeInterceptor);
271303
ModelAndView mv2 = adapter.handle(request, new MockHttpServletResponse(), chain.getHandler());
272304
assertEquals("baz", mv2.getViewName());
305+
306+
request.setRequestURI("/myapp/app/");
307+
request.setContextPath("/myapp");
308+
request.setServletPath("/app/");
309+
chain = mapping2.getHandler(request);
310+
assertEquals(4, chain.getInterceptors().length);
311+
assertTrue(chain.getInterceptors()[1] instanceof ConversionServiceExposingInterceptor);
312+
assertTrue(chain.getInterceptors()[2] instanceof LocaleChangeInterceptor);
313+
assertTrue(chain.getInterceptors()[3] instanceof ThemeChangeInterceptor);
314+
ModelAndView mv3 = adapter.handle(request, new MockHttpServletResponse(), chain.getHandler());
315+
assertEquals("root", mv3.getViewName());
316+
317+
request.setRequestURI("/myapp/");
318+
request.setContextPath("/myapp");
319+
request.setServletPath("/");
320+
chain = mapping2.getHandler(request);
321+
assertEquals(4, chain.getInterceptors().length);
322+
assertTrue(chain.getInterceptors()[1] instanceof ConversionServiceExposingInterceptor);
323+
assertTrue(chain.getInterceptors()[2] instanceof LocaleChangeInterceptor);
324+
assertTrue(chain.getInterceptors()[3] instanceof ThemeChangeInterceptor);
325+
mv3 = adapter.handle(request, new MockHttpServletResponse(), chain.getHandler());
326+
assertEquals("root", mv3.getViewName());
273327
}
274328

329+
275330
@Controller
276331
public static class TestController {
277332

org.springframework.web.servlet/src/test/resources/org/springframework/web/servlet/config/mvc-config-view-controllers.xml

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,17 @@
55
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
66
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
77

8-
<mvc:annotation-driven />
8+
<mvc:annotation-driven/>
99

10-
<mvc:view-controller path="/foo" />
10+
<mvc:view-controller path="/foo"/>
1111

12-
<mvc:view-controller path="/bar" view-name="baz" />
12+
<mvc:view-controller path="/bar" view-name="baz"/>
13+
14+
<mvc:view-controller path="/" view-name="root"/>
1315

1416
<mvc:interceptors>
15-
<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor" />
16-
<bean class="org.springframework.web.servlet.theme.ThemeChangeInterceptor" />
17+
<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"/>
18+
<bean class="org.springframework.web.servlet.theme.ThemeChangeInterceptor"/>
1719
</mvc:interceptors>
1820

1921
</beans>

org.springframework.web/src/main/java/org/springframework/web/util/UrlPathHelper.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818

1919
import java.io.UnsupportedEncodingException;
2020
import java.net.URLDecoder;
21-
2221
import javax.servlet.http.HttpServletRequest;
2322

2423
import org.apache.commons.logging.Log;
@@ -226,6 +225,10 @@ public String getServletPath(HttpServletRequest request) {
226225
if (servletPath == null) {
227226
servletPath = request.getServletPath();
228227
}
228+
if (servletPath.length() > 1 && servletPath.endsWith("/")) {
229+
// Probably on WebSphere: removing trailing slash...
230+
servletPath = servletPath.substring(0, servletPath.length() - 1);
231+
}
229232
return servletPath;
230233
}
231234

0 commit comments

Comments
 (0)