diff --git a/grails-plugin-interceptors/src/main/groovy/grails/artefact/Interceptor.groovy b/grails-plugin-interceptors/src/main/groovy/grails/artefact/Interceptor.groovy index 266d5968d3c..add9aa89d94 100644 --- a/grails-plugin-interceptors/src/main/groovy/grails/artefact/Interceptor.groovy +++ b/grails-plugin-interceptors/src/main/groovy/grails/artefact/Interceptor.groovy @@ -18,7 +18,6 @@ package grails.artefact import grails.artefact.controller.support.RequestForwarder import grails.artefact.controller.support.ResponseRedirector import grails.artefact.controller.support.ResponseRenderer -import grails.core.GrailsApplication import grails.interceptors.Matcher import grails.util.GrailsNameUtils import grails.web.api.ServletAttributes @@ -35,12 +34,8 @@ import org.grails.web.servlet.mvc.exceptions.ControllerExecutionException import org.grails.web.servlet.view.CompositeViewResolver import org.grails.web.util.GrailsApplicationAttributes import org.grails.web.util.WebUtils -import org.springframework.beans.factory.annotation.Autowired import org.springframework.core.Ordered import org.springframework.web.servlet.ModelAndView -import org.springframework.web.servlet.ViewResolver - -import javax.annotation.PostConstruct import javax.servlet.http.HttpServletRequest import javax.servlet.http.HttpServletResponse import java.util.concurrent.ConcurrentLinkedQueue @@ -95,10 +90,11 @@ trait Interceptor implements ResponseRenderer, ResponseRedirector, RequestForwar def uri = req.requestURI def matchedInfo = request.getAttribute(UrlMappingsHandlerMapping.MATCHED_REQUEST) + UrlMappingInfo grailsMappingInfo = (UrlMappingInfo)matchedInfo for(Matcher matcher in allMatchers) { - if(matcher.doesMatch(uri, grailsMappingInfo)) { + if(matcher.doesMatch(uri, grailsMappingInfo, req.method)) { request.setAttribute(interceptorMatchKey, Boolean.TRUE) return true } diff --git a/grails-plugin-interceptors/src/main/groovy/grails/interceptors/Matcher.groovy b/grails-plugin-interceptors/src/main/groovy/grails/interceptors/Matcher.groovy index 8cd2d69ff05..5d61dbbb4c3 100644 --- a/grails-plugin-interceptors/src/main/groovy/grails/interceptors/Matcher.groovy +++ b/grails-plugin-interceptors/src/main/groovy/grails/interceptors/Matcher.groovy @@ -39,6 +39,15 @@ interface Matcher { */ boolean doesMatch(String uri, UrlMappingInfo info) + /** + * Perform the matches using the http method of the request instead of the UrlMappingInfo + * @param uri + * @param info + * @param method + * @return + */ + boolean doesMatch(String uri, UrlMappingInfo info, String method) + /** * Defines the match for the given arguments * diff --git a/grails-plugin-interceptors/src/main/groovy/org/grails/plugins/web/interceptors/UrlMappingMatcher.groovy b/grails-plugin-interceptors/src/main/groovy/org/grails/plugins/web/interceptors/UrlMappingMatcher.groovy index 1fc4e41620a..3093692eda6 100644 --- a/grails-plugin-interceptors/src/main/groovy/org/grails/plugins/web/interceptors/UrlMappingMatcher.groovy +++ b/grails-plugin-interceptors/src/main/groovy/org/grails/plugins/web/interceptors/UrlMappingMatcher.groovy @@ -57,6 +57,10 @@ class UrlMappingMatcher implements Matcher { } boolean doesMatch(String uri, UrlMappingInfo info) { + return doesMatch(uri, info, null) + } + + boolean doesMatch(String uri, UrlMappingInfo info, String method) { boolean hasUriPatterns = !uriPatterns.isEmpty() boolean isExcluded = this.isExcluded(uri, info) @@ -75,7 +79,7 @@ class UrlMappingMatcher implements Matcher { Boolean matched = CACHED_MATCHES.get(infoCode) if (matched != null) return matched - if (doesMatchInternal(info)) { + if (doesMatchInternal(info, method)) { if (Environment.current == Environment.PRODUCTION) { CACHED_MATCHES.put(infoCode, Boolean.TRUE) } @@ -100,12 +104,12 @@ class UrlMappingMatcher implements Matcher { false } - protected boolean doesMatchInternal(UrlMappingInfo info) { + protected boolean doesMatchInternal(UrlMappingInfo info, String method) { (info != null && ((info.controllerName ?: '') ==~ controllerRegex) && ((info.actionName ?: '') ==~ actionRegex) && ((info.namespace ?: '') ==~ namespaceRegex) && - ((info.httpMethod ?: '') ==~ methodRegex)) + ((method ?: info.httpMethod ?: '') ==~ methodRegex)) } @Override diff --git a/grails-plugin-interceptors/src/test/groovy/grails/artefact/InterceptorSpec.groovy b/grails-plugin-interceptors/src/test/groovy/grails/artefact/InterceptorSpec.groovy index ade0d1cd19a..b877765b33a 100644 --- a/grails-plugin-interceptors/src/test/groovy/grails/artefact/InterceptorSpec.groovy +++ b/grails-plugin-interceptors/src/test/groovy/grails/artefact/InterceptorSpec.groovy @@ -21,6 +21,9 @@ import org.grails.web.mapping.DefaultUrlMappingInfo import org.grails.web.mapping.ForwardUrlMappingInfo import org.grails.web.mapping.mvc.UrlMappingsHandlerMapping import org.grails.web.servlet.mvc.GrailsWebRequest +import org.springframework.mock.web.MockHttpServletRequest +import org.springframework.mock.web.MockHttpServletResponse +import org.springframework.mock.web.MockServletContext import org.springframework.web.context.request.RequestContextHolder import spock.lang.Specification @@ -156,6 +159,25 @@ class InterceptorSpec extends Specification { then:"We don't match" i.doesMatch() } + + void "Test match with http method"() { + given:"A test interceptor" + def i = new TestMethodInterceptor() + def webRequest = GrailsWebMockUtil.bindMockWebRequest(new MockServletContext(), new MockHttpServletRequest(httpMethod, ""), new MockHttpServletResponse()) + def request = webRequest.request + + when:"The http method of the current request is ${httpMethod}" + request.setAttribute(UrlMappingsHandlerMapping.MATCHED_REQUEST, new ForwardUrlMappingInfo(controllerName: "test", action: "save")) + + then: "We match: ${shouldMatch}" + i.doesMatch() == shouldMatch + + where: + httpMethod | shouldMatch + 'POST' | true + 'GET' | false + } + void clearMatch(i, HttpServletRequest request) { request.removeAttribute(i.getClass().name + InterceptorArtefactHandler.MATCH_SUFFIX) } @@ -197,4 +219,10 @@ class Test4Interceptor implements Interceptor { matchAll() .excludes(controller:"foo", action:"bar") } -} \ No newline at end of file +} + +class TestMethodInterceptor implements Interceptor { + TestMethodInterceptor() { + match(method: 'POST') + } +}