Грааль 3.1.16 Перехватчики не фильтруются по методу - PullRequest
0 голосов
/ 31 октября 2018

Я пытаюсь использовать перехватчики Grails для соответствия конкретным URI, имеющим определенные методы HTTP. Аргумент метода метода match, тем не менее, игнорируется, несмотря на то, что я обновил версию Grails с 3.1.1 до 3.1.16, где эта проблема должна быть исправлена ​​.

Упрощенная версия моего кода будет:

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

}

Как я могу убедиться, что перехватчик соответствует uris только для заданных методов HTTP?

1 Ответ

0 голосов
/ 27 июля 2019

Это невозможно по умолчанию в 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, и использовать его вместо обычного в вашем Перехватчике:

// 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
}
...