Stripes

Inconsistency in how a request URI is determined

Details

Description

AnnotatedClassActionResolver#getRequestedPath(..) returns the URI of the request, but it does so by constructing it from getServletPath() + getPathInfo(). All the clean URL code calls getRequestURI() instead. This can cause tricky problems during development with some URLs that are able to resolve the ActionBean but not to parse the URI parameters. For example, given a prefix mapping of /action/* and @UrlBinding("/action/foo/{$event}/{param}"), the URI //myContext/action/foo/bar/blah would correctly resolve to an ActionBean because getServletPath() returns /action instead of //action, but getRequestURI() returns //myContext/action/foo/bar/blah, which the URI parameter parsing code cannot handle.

Activity

Hide
Ben Gunter added a comment - 01/Oct/08 8:12 PM

AnnotatedClassActionResolver.getRequestedPath(..) calls HttpServletRequest.getRequestURI() instead of constructing the URI from servletPath and pathInfo.

Show
Ben Gunter added a comment - 01/Oct/08 8:12 PM AnnotatedClassActionResolver.getRequestedPath(..) calls HttpServletRequest.getRequestURI() instead of constructing the URI from servletPath and pathInfo.
Hide
John Newman added a comment - 03/Oct/08 12:33 PM

Hi Ben,

I think the change you made to AnnotatedClassActionResolver.getActionBean in rev 960 introduced a small bug.

I have Search.action bound to "/" via the trick with

<welcome-file-list>
<welcome-file>index.ftl</welcome-file>
<welcome-file>Search.action</welcome-file>
</welcome-file-list>

and an empty file in the application root called Search.action

After rev 960, when I goto http://locahost/MyApp/ I get an exception instead of being taken to the bean:
java.lang.StringIndexOutOfBoundsException: String index out of range: 0
at java.lang.String.charAt(String.java:558)
at net.sourceforge.stripes.controller.NameBasedActionResolver.getFindViewAttempts(NameBasedActionResolver.java:368)
at net.sourceforge.stripes.controller.NameBasedActionResolver.findView(NameBasedActionResolver.java:321)
at net.sourceforge.stripes.controller.NameBasedActionResolver.handleActionBeanNotFound(NameBasedActionResolver.java:292)
at net.sourceforge.stripes.controller.NameBasedActionResolver.getActionBean(NameBasedActionResolver.java:267)
at net.sourceforge.stripes.controller.AnnotatedClassActionResolver.getActionBean(AnnotatedClassActionResolver.java:279)
at net.sourceforge.stripes.controller.DispatcherHelper$1.intercept(DispatcherHelper.java:106)
at net.sourceforge.stripes.controller.ExecutionContext.proceed(ExecutionContext.java:158)
at edu.upmc.ccweb.core.modules.login.stripes.SecurityInterceptor.intercept(SecurityInterceptor.java:101)
at net.sourceforge.stripes.controller.ExecutionContext.proceed(ExecutionContext.java:155)
at net.sourceforge.stripes.integration.spring.SpringInterceptor.intercept(SpringInterceptor.java:64)
at net.sourceforge.stripes.controller.ExecutionContext.proceed(ExecutionContext.java:155)
at net.sourceforge.stripes.controller.BeforeAfterMethodInterceptor.intercept(BeforeAfterMethodInterceptor.java:113)
at net.sourceforge.stripes.controller.ExecutionContext.proceed(ExecutionContext.java:155)
at net.sourceforge.stripes.controller.ExecutionContext.wrap(ExecutionContext.java:74)
at net.sourceforge.stripes.controller.DispatcherHelper.resolveActionBean(DispatcherHelper.java:102)
at net.sourceforge.stripes.controller.DispatcherServlet.resolveActionBean(DispatcherServlet.java:245)
at net.sourceforge.stripes.controller.DispatcherServlet.doPost(DispatcherServlet.java:148)
at net.sourceforge.stripes.controller.DispatcherServlet.doGet(DispatcherServlet.java:67)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:690)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at net.sourceforge.stripes.controller.StripesFilter.doFilter(StripesFilter.java:246)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:198)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:230)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:179)
at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:84)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:157)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:262)
at org.apache.coyote.ajp.AjpProcessor.process(AjpProcessor.java:437)
at org.apache.coyote.ajp.AjpProtocol$AjpConnectionHandler.process(AjpProtocol.java:366)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:446)
at java.lang.Thread.run(Thread.java:595)

Reverting the changes from 960 does not produce this exception and the app works normally.

Show
John Newman added a comment - 03/Oct/08 12:33 PM Hi Ben, I think the change you made to AnnotatedClassActionResolver.getActionBean in rev 960 introduced a small bug. I have Search.action bound to "/" via the trick with <welcome-file-list> <welcome-file>index.ftl</welcome-file> <welcome-file>Search.action</welcome-file> </welcome-file-list> and an empty file in the application root called Search.action After rev 960, when I goto http://locahost/MyApp/ I get an exception instead of being taken to the bean: java.lang.StringIndexOutOfBoundsException: String index out of range: 0 at java.lang.String.charAt(String.java:558) at net.sourceforge.stripes.controller.NameBasedActionResolver.getFindViewAttempts(NameBasedActionResolver.java:368) at net.sourceforge.stripes.controller.NameBasedActionResolver.findView(NameBasedActionResolver.java:321) at net.sourceforge.stripes.controller.NameBasedActionResolver.handleActionBeanNotFound(NameBasedActionResolver.java:292) at net.sourceforge.stripes.controller.NameBasedActionResolver.getActionBean(NameBasedActionResolver.java:267) at net.sourceforge.stripes.controller.AnnotatedClassActionResolver.getActionBean(AnnotatedClassActionResolver.java:279) at net.sourceforge.stripes.controller.DispatcherHelper$1.intercept(DispatcherHelper.java:106) at net.sourceforge.stripes.controller.ExecutionContext.proceed(ExecutionContext.java:158) at edu.upmc.ccweb.core.modules.login.stripes.SecurityInterceptor.intercept(SecurityInterceptor.java:101) at net.sourceforge.stripes.controller.ExecutionContext.proceed(ExecutionContext.java:155) at net.sourceforge.stripes.integration.spring.SpringInterceptor.intercept(SpringInterceptor.java:64) at net.sourceforge.stripes.controller.ExecutionContext.proceed(ExecutionContext.java:155) at net.sourceforge.stripes.controller.BeforeAfterMethodInterceptor.intercept(BeforeAfterMethodInterceptor.java:113) at net.sourceforge.stripes.controller.ExecutionContext.proceed(ExecutionContext.java:155) at net.sourceforge.stripes.controller.ExecutionContext.wrap(ExecutionContext.java:74) at net.sourceforge.stripes.controller.DispatcherHelper.resolveActionBean(DispatcherHelper.java:102) at net.sourceforge.stripes.controller.DispatcherServlet.resolveActionBean(DispatcherServlet.java:245) at net.sourceforge.stripes.controller.DispatcherServlet.doPost(DispatcherServlet.java:148) at net.sourceforge.stripes.controller.DispatcherServlet.doGet(DispatcherServlet.java:67) at javax.servlet.http.HttpServlet.service(HttpServlet.java:690) at javax.servlet.http.HttpServlet.service(HttpServlet.java:803) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at net.sourceforge.stripes.controller.StripesFilter.doFilter(StripesFilter.java:246) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:198) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:230) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175) at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:179) at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:84) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:157) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:262) at org.apache.coyote.ajp.AjpProcessor.process(AjpProcessor.java:437) at org.apache.coyote.ajp.AjpProtocol$AjpConnectionHandler.process(AjpProtocol.java:366) at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:446) at java.lang.Thread.run(Thread.java:595) Reverting the changes from 960 does not produce this exception and the app works normally.
Hide
Ben Gunter added a comment - 07/Oct/08 9:38 PM

Indeed, this is a bigger problem than it seems at first. Turns out that in the case you cite, the former implementation returns "/Search.action" while the new implementation should return "". That's a pretty significant change. (Not to mention that I pretty well screwed it up by forgetting to trim the context path from the beginning and not using the request URI for includes.)

Right now I'm thinking I need to revert this change since it breaks that trick you and a lot of other folks are using. The question is should other code that calls getRequestURI() be doing it the other way instead? We have code that should be working with the same value instead working with two different values.

Show
Ben Gunter added a comment - 07/Oct/08 9:38 PM Indeed, this is a bigger problem than it seems at first. Turns out that in the case you cite, the former implementation returns "/Search.action" while the new implementation should return "". That's a pretty significant change. (Not to mention that I pretty well screwed it up by forgetting to trim the context path from the beginning and not using the request URI for includes.) Right now I'm thinking I need to revert this change since it breaks that trick you and a lot of other folks are using. The question is should other code that calls getRequestURI() be doing it the other way instead? We have code that should be working with the same value instead working with two different values.
Hide
Ben Gunter added a comment - 16/Oct/08 10:36 PM

This is fixed in both the trunk and the 1.5.x branch. I added a new HttpUtil class and changed all calls to HttpServletRequest.getRequestURI() to HttpUtil.getRequestedPath(HttpServletRequest). The case you reported broken with the previous fix worked with this fix when I tested it. Please try it out in your environment and let us know how it goes.

Show
Ben Gunter added a comment - 16/Oct/08 10:36 PM This is fixed in both the trunk and the 1.5.x branch. I added a new HttpUtil class and changed all calls to HttpServletRequest.getRequestURI() to HttpUtil.getRequestedPath(HttpServletRequest). The case you reported broken with the previous fix worked with this fix when I tested it. Please try it out in your environment and let us know how it goes.

People

Vote (0)
Watch (1)

Dates

  • Created:
    23/May/08 10:35 AM
    Updated:
    04/Jan/11 2:38 PM
    Resolved:
    16/Oct/08 10:36 PM