Skip to content

Commit ad025b5

Browse files
committed
Prepend context/servlet path to FormTag action
The Form tag now fills in the context and servlet path if not present in the specified action. Issue: SPR-8684
1 parent ad91fa6 commit ad025b5

File tree

3 files changed

+56
-6
lines changed

3 files changed

+56
-6
lines changed

spring-webmvc/src/main/java/org/springframework/web/servlet/support/RequestContext.java

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import org.springframework.ui.context.support.ResourceBundleThemeSource;
3737
import org.springframework.util.Assert;
3838
import org.springframework.util.ClassUtils;
39+
import org.springframework.util.StringUtils;
3940
import org.springframework.validation.BindException;
4041
import org.springframework.validation.BindingResult;
4142
import org.springframework.validation.Errors;
@@ -422,14 +423,14 @@ public String getContextUrl(String relativeUrl, Map<String, ?> params) {
422423
* context path and the servlet path of the original request. This is useful
423424
* for building links to other resources within the application where a
424425
* servlet mapping of the style {@code "/main/*"} is used.
425-
* <p>Delegates to the UrlPathHelper for decoding the context path.
426-
* @see javax.servlet.http.HttpServletRequest#getContextPath
427-
* @see javax.servlet.http.HttpServletRequest#getServletPath()
428-
* @see #getUrlPathHelper
426+
* Delegates to the UrlPathHelper to determine the context and servlet path.
429427
*/
430428
public String getPathToServlet() {
431-
return this.urlPathHelper.getOriginatingContextPath(this.request)
432-
+ this.urlPathHelper.getOriginatingServletPath(this.request);
429+
String path = this.urlPathHelper.getOriginatingContextPath(this.request);
430+
if (StringUtils.hasText(this.urlPathHelper.getPathWithinServletMapping(this.request))) {
431+
path += this.urlPathHelper.getOriginatingServletPath(this.request);
432+
}
433+
return path;
433434
}
434435

435436
/**

spring-webmvc/src/main/java/org/springframework/web/servlet/tags/form/FormTag.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import org.springframework.util.StringUtils;
3333
import org.springframework.web.servlet.support.RequestDataValueProcessor;
3434
import org.springframework.web.util.HtmlUtils;
35+
import org.springframework.web.util.UrlPathHelper;
3536

3637
/**
3738
* Databinding-aware JSP tag for rendering an HTML '{@code form}' whose
@@ -411,6 +412,10 @@ protected String resolveModelAttribute() throws JspException {
411412
protected String resolveAction() throws JspException {
412413
String action = getAction();
413414
if (StringUtils.hasText(action)) {
415+
String pathToServlet = getRequestContext().getPathToServlet();
416+
if (action.startsWith("/") && !action.startsWith(getRequestContext().getContextPath())) {
417+
action = pathToServlet + action;
418+
}
414419
action = getDisplayString(evaluate(ACTION_ATTRIBUTE, action));
415420
return processAction(action);
416421
}

spring-webmvc/src/test/java/org/springframework/web/servlet/tags/form/FormTagTests.java

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,50 @@ public void testWithActionFromRequest() throws Exception {
166166
assertAttributeNotPresent(output, "name");
167167
}
168168

169+
public void testPrependServletPath() throws Exception {
170+
171+
this.request.setContextPath("/myApp");
172+
this.request.setServletPath("/main");
173+
this.request.setPathInfo("/index.html");
174+
175+
String commandName = "myCommand";
176+
String action = "/form.html";
177+
String enctype = "my/enctype";
178+
String method = "POST";
179+
String onsubmit = "onsubmit";
180+
String onreset = "onreset";
181+
182+
this.tag.setCommandName(commandName);
183+
this.tag.setAction(action);
184+
this.tag.setMethod(method);
185+
this.tag.setEnctype(enctype);
186+
this.tag.setOnsubmit(onsubmit);
187+
this.tag.setOnreset(onreset);
188+
189+
int result = this.tag.doStartTag();
190+
assertEquals(Tag.EVAL_BODY_INCLUDE, result);
191+
assertEquals("Form attribute not exposed", commandName,
192+
getPageContext().getAttribute(FormTag.MODEL_ATTRIBUTE_VARIABLE_NAME, PageContext.REQUEST_SCOPE));
193+
194+
result = this.tag.doEndTag();
195+
assertEquals(Tag.EVAL_PAGE, result);
196+
197+
this.tag.doFinally();
198+
assertNull("Form attribute not cleared after tag ends",
199+
getPageContext().getAttribute(FormTag.MODEL_ATTRIBUTE_VARIABLE_NAME, PageContext.REQUEST_SCOPE));
200+
201+
String output = getOutput();
202+
assertFormTagOpened(output);
203+
assertFormTagClosed(output);
204+
205+
assertContainsAttribute(output, "action", "/myApp/main/form.html");
206+
assertContainsAttribute(output, "method", method);
207+
assertContainsAttribute(output, "enctype", enctype);
208+
assertContainsAttribute(output, "onsubmit", onsubmit);
209+
assertContainsAttribute(output, "onreset", onreset);
210+
assertAttributeNotPresent(output, "name");
211+
}
212+
169213
public void testWithNullResolvedCommand() throws Exception {
170214
try {
171215
tag.setCommandName("${null}");

0 commit comments

Comments
 (0)