Skip to content

Commit b416fee

Browse files
committed
Correctly handle includes within 404 forward requests. Fixes #10149
1 parent 938f961 commit b416fee

File tree

2 files changed

+76
-1
lines changed

2 files changed

+76
-1
lines changed

grails-web-url-mappings/src/main/groovy/org/grails/web/mapping/mvc/UrlMappingsHandlerMapping.groovy

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ class UrlMappingsHandlerMapping extends AbstractHandlerMapping {
131131
String version = findRequestedVersion(webRequest)
132132

133133

134-
if(errorStatus) {
134+
if(errorStatus && !WebUtils.isInclude(request)) {
135135
def exception = request.getAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE)
136136
UrlMappingInfo info
137137
if(exception instanceof Throwable) {

grails-web-url-mappings/src/test/groovy/org/codehaus/groovy/grails/web/servlet/mvc/UrlMappingsHandlerMappingSpec.groovy

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,84 @@ import org.grails.web.mapping.DefaultUrlMappingInfo
1010
import org.grails.web.mapping.mvc.GrailsControllerUrlMappings
1111
import org.grails.web.mapping.mvc.UrlMappingsHandlerMapping
1212
import org.grails.web.mapping.mvc.UrlMappingsInfoHandlerAdapter
13+
import org.grails.web.util.WebUtils
1314
import org.springframework.web.context.request.RequestContextHolder
1415
import org.springframework.web.servlet.view.InternalResourceView
16+
import spock.lang.Issue
1517

1618
/**
1719
* Created by graemerocher on 26/05/14.
1820
*/
1921
class UrlMappingsHandlerMappingSpec extends AbstractUrlMappingsSpec {
2022

23+
void "Test that when a request coming from a 404 forward is matched the correct action is executed"() {
24+
given:"A URL mapping definition that has a 404 mapping"
25+
def grailsApplication = new DefaultGrailsApplication(FooController)
26+
grailsApplication.initialise()
27+
def holder = getUrlMappingsHolder {
28+
"/foo/bar"(controller:"foo", action:"bar")
29+
"/foo/error"(controller:"foo", action:"error")
30+
"404"(controller: "foo", action:"notFound")
31+
}
32+
33+
holder = new GrailsControllerUrlMappings(grailsApplication, holder)
34+
def handler = new UrlMappingsHandlerMapping(holder)
35+
36+
when:"A request that contains a 404 error status code is handled"
37+
def webRequest = GrailsWebMockUtil.bindMockWebRequest()
38+
webRequest.renderView = true
39+
def request = webRequest.request
40+
request.setRequestURI("/foo/notThere")
41+
request.setAttribute(WebUtils.ERROR_STATUS_CODE_ATTRIBUTE, "404")
42+
def handlerChain = handler.getHandler(request)
43+
44+
then:"The handler chain is not null"
45+
handlerChain != null
46+
47+
when:"A HandlerAdapter is used"
48+
def handlerAdapter = new UrlMappingsInfoHandlerAdapter()
49+
def result = handlerAdapter.handle(request, webRequest.response, handlerChain.handler)
50+
51+
then:"The controller action that is mapped to the 404 handler is executed"
52+
webRequest.response.contentAsString == 'Not Found'
53+
}
54+
55+
@Issue('https://github.com/grails/grails-core/issues/10149')
56+
void "Test that when an include request from within a 404 forward is matched"() {
57+
given:"A URL mapping definition that has a 404 mapping"
58+
def grailsApplication = new DefaultGrailsApplication(FooController)
59+
grailsApplication.initialise()
60+
def holder = getUrlMappingsHolder {
61+
"/foo/bar"(controller:"foo", action:"bar")
62+
"/foo/error"(controller:"foo", action:"error")
63+
"404"(controller: "foo", action:"notFound")
64+
}
65+
66+
holder = new GrailsControllerUrlMappings(grailsApplication, holder)
67+
def handler = new UrlMappingsHandlerMapping(holder)
68+
69+
when:"A request arrives that is an include within a 404 forward request"
70+
def webRequest = GrailsWebMockUtil.bindMockWebRequest()
71+
webRequest.renderView = true
72+
def request = webRequest.request
73+
request.setRequestURI("/foo/notThere")
74+
request.setAttribute(WebUtils.ERROR_STATUS_CODE_ATTRIBUTE, "404")
75+
request.setAttribute(WebUtils.INCLUDE_REQUEST_URI_ATTRIBUTE, "/foo/bar")
76+
def handlerChain = handler.getHandler(request)
77+
78+
then:"The handler chain is not null"
79+
handlerChain != null
80+
81+
when:"A HandlerAdapter is used"
82+
def handlerAdapter = new UrlMappingsInfoHandlerAdapter()
83+
def result = handlerAdapter.handle(request, webRequest.response, handlerChain.handler)
84+
85+
then:"The correct action was executed to handle the include"
86+
result.viewName == 'bar'
87+
result.model == [foo:'bar']
88+
89+
}
90+
2191
void "Test that a matched URL returns a URLMappingInfo"() {
2292

2393
given:
@@ -93,4 +163,9 @@ class FooController {
93163
def error() {
94164
RequestContextHolder.currentRequestAttributes().response.sendError(405)
95165
}
166+
167+
@Action
168+
def notFound() {
169+
RequestContextHolder.currentRequestAttributes().response.writer << "Not Found"
170+
}
96171
}

0 commit comments

Comments
 (0)