我正在尝试使用Grails拦截器来匹配具有特定HTTP方法的特定uri。尽管我将Grails版本从3.1.1升级到了3.1.16, where that issue should be fixed,但是match方法的method参数却被忽略了。
我的代码的简化版本是:
@GrailsCompileStatic
class MyInterceptor {
int order = HIGHEST_PRECEDENCE
MyInterceptor () {
match(uri: '/api/domain/*', method: 'PUT')
match(uri: '/api/domain/*', method: 'DELETE')
match(uri: '/api/domain/*', method: 'POST')
}
}
通过以下拦截器测试:
@TestFor(MyInterceptor)
class MyInterceptorSpec extends Specification {
@Unroll
def "it matches '#method #uri'"() {
when: "A request matches the interceptor"
withRequest(uri: uri, method: method)
then:"The interceptor does match"
interceptor.doesMatch()
where:
uri | method
'/api/domain/1' | 'PUT'
'/api/domain/1' | 'POST'
'/api/domain/1' | 'DELETE'
}
@Unroll
def "it does not match '#method #uri'"() {
when:
withRequest(uri: uri, method: method)
then:
!interceptor.doesMatch()
where:
uri | method
'/api/domain' | 'GET'
'/api/domain/1' | 'GET' // failing test
}
}
如何确保拦截器仅针对给定的HTTP方法匹配uri?
答案 0 :(得分:0)
默认情况下在Grails中是不可能的。
查看UrlMappingMatcher的代码,我们可以看到,当我们使用uri定义匹配规则时,方法部分将被忽略:
@Override
Matcher matches(Map arguments) {
if(arguments.uri) {
uriPatterns << arguments.uri.toString()
}
else {
controllerRegex = regexMatch( arguments, "controller")
actionRegex = regexMatch( arguments, "action")
namespaceRegex = regexMatch( arguments, "namespace")
methodRegex = regexMatch( arguments, "method")
}
return this
}
@Override
Matcher excludes(Map arguments) {
if(arguments.uri) {
uriExcludePatterns << arguments.uri.toString()
}
else {
def exclude = new MapExclude()
exclude.controllerExcludesRegex = regexMatch( arguments, "controller", null)
exclude.actionExcludesRegex = regexMatch( arguments, "action", null)
exclude.namespaceExcludesRegex = regexMatch( arguments, "namespace", null)
exclude.methodExcludesRegex = regexMatch( arguments, "method", null)
excludes << exclude
}
return this
}
但是,您可以创建UrlMappingMatcher的子类,即使在定义了uri时也要考虑该方法,并使用它代替Interceptor中的常规方法:
// in MyInterceptor.groovy
Matcher match(Map arguments) {
// use your own implementation of the UrlMappingMatcher
def matcher = new MethodFilteringUrlMappingMatcher(this)
matcher.matches(arguments)
matchers << matcher
return matcher
}