简体   繁体   English

Grails 3.1.16拦截器未过滤方法

[英]Grails 3.1.16 Interceptors not filtering on method

I'm trying to use Grails interceptors to match specific uri having specific HTTP methods. 我正在尝试使用Grails拦截器来匹配具有特定HTTP方法的特定uri。 The method argument of the match method is however ignored, despite the fact that I upgraded my Grails version from 3.1.1 to 3.1.16, where that issue should be fixed . 尽管我将Grails版本从3.1.1升级到了3.1.16,但该问题应该得到解决 ,但match方法的method参数却被忽略了。

An simplified version of my code would be: 我的代码的简化版本是:

@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')
    }
}

With the following interceptor test: 通过以下拦截器测试:

@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
    }

}

How can I ensure that the interceptor match uris only for given HTTP methods? 如何确保拦截器仅针对给定的HTTP方法匹配uri?

It is not possible by default in Grails. 默认情况下,Grails中不可能。

Looking at the code of the UrlMappingMatcher we can see that when we define a matching rule with an uri, the method part is ignored: 查看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
}

You can however create a subclass of UrlMappingMatcher that takes into account the method even when an uri is defined, and use it instead of the regular one in your Interceptor: 但是,您可以创建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
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM