diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/support/RequestContext.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/support/RequestContext.java index 3f586a9446..cf63a425c3 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/support/RequestContext.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/support/RequestContext.java @@ -36,6 +36,7 @@ import org.springframework.ui.context.ThemeSource; import org.springframework.ui.context.support.ResourceBundleThemeSource; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; +import org.springframework.util.StringUtils; import org.springframework.validation.BindException; import org.springframework.validation.BindingResult; import org.springframework.validation.Errors; @@ -422,14 +423,14 @@ public class RequestContext { * context path and the servlet path of the original request. This is useful * for building links to other resources within the application where a * servlet mapping of the style {@code "/main/*"} is used. - *

Delegates to the UrlPathHelper for decoding the context path. - * @see javax.servlet.http.HttpServletRequest#getContextPath - * @see javax.servlet.http.HttpServletRequest#getServletPath() - * @see #getUrlPathHelper + * Delegates to the UrlPathHelper to determine the context and servlet path. */ public String getPathToServlet() { - return this.urlPathHelper.getOriginatingContextPath(this.request) - + this.urlPathHelper.getOriginatingServletPath(this.request); + String path = this.urlPathHelper.getOriginatingContextPath(this.request); + if (StringUtils.hasText(this.urlPathHelper.getPathWithinServletMapping(this.request))) { + path += this.urlPathHelper.getOriginatingServletPath(this.request); + } + return path; } /** diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/tags/form/FormTag.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/tags/form/FormTag.java index d3b6752ade..120b910727 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/tags/form/FormTag.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/tags/form/FormTag.java @@ -32,6 +32,7 @@ import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; import org.springframework.web.servlet.support.RequestDataValueProcessor; import org.springframework.web.util.HtmlUtils; +import org.springframework.web.util.UrlPathHelper; /** * Databinding-aware JSP tag for rendering an HTML '{@code form}' whose @@ -411,6 +412,10 @@ public class FormTag extends AbstractHtmlElementTag { protected String resolveAction() throws JspException { String action = getAction(); if (StringUtils.hasText(action)) { + String pathToServlet = getRequestContext().getPathToServlet(); + if (action.startsWith("/") && !action.startsWith(getRequestContext().getContextPath())) { + action = pathToServlet + action; + } action = getDisplayString(evaluate(ACTION_ATTRIBUTE, action)); return processAction(action); } diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/tags/form/FormTagTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/tags/form/FormTagTests.java index 23bacd5b94..c3cd6764af 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/tags/form/FormTagTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/tags/form/FormTagTests.java @@ -166,6 +166,50 @@ public class FormTagTests extends AbstractHtmlElementTagTests { assertAttributeNotPresent(output, "name"); } + public void testPrependServletPath() throws Exception { + + this.request.setContextPath("/myApp"); + this.request.setServletPath("/main"); + this.request.setPathInfo("/index.html"); + + String commandName = "myCommand"; + String action = "/form.html"; + String enctype = "my/enctype"; + String method = "POST"; + String onsubmit = "onsubmit"; + String onreset = "onreset"; + + this.tag.setCommandName(commandName); + this.tag.setAction(action); + this.tag.setMethod(method); + this.tag.setEnctype(enctype); + this.tag.setOnsubmit(onsubmit); + this.tag.setOnreset(onreset); + + int result = this.tag.doStartTag(); + assertEquals(Tag.EVAL_BODY_INCLUDE, result); + assertEquals("Form attribute not exposed", commandName, + getPageContext().getAttribute(FormTag.MODEL_ATTRIBUTE_VARIABLE_NAME, PageContext.REQUEST_SCOPE)); + + result = this.tag.doEndTag(); + assertEquals(Tag.EVAL_PAGE, result); + + this.tag.doFinally(); + assertNull("Form attribute not cleared after tag ends", + getPageContext().getAttribute(FormTag.MODEL_ATTRIBUTE_VARIABLE_NAME, PageContext.REQUEST_SCOPE)); + + String output = getOutput(); + assertFormTagOpened(output); + assertFormTagClosed(output); + + assertContainsAttribute(output, "action", "/myApp/main/form.html"); + assertContainsAttribute(output, "method", method); + assertContainsAttribute(output, "enctype", enctype); + assertContainsAttribute(output, "onsubmit", onsubmit); + assertContainsAttribute(output, "onreset", onreset); + assertAttributeNotPresent(output, "name"); + } + public void testWithNullResolvedCommand() throws Exception { try { tag.setCommandName("${null}");