Функциональный маршрутизатор Spring WebFlux интерфейс OpenAPI

#spring-webflux #swagger-ui #openapi #springdoc #springdoc-openapi-ui

Вопрос:

Я хотел бы создать спецификацию пользовательского интерфейса OpenAPI, используя функциональный маршрутизатор Spring WebFlux на Kotlin. Spring Boot v. 2.5.2, springdoc-openapi v. 1.5.9. Вот мой класс маршрутизатора:

 @Configuration
class UserServiceRouter {

    @Bean
    @RouterOperations(
        RouterOperation(
            path = "/user/{id}",
            method = [RequestMethod.GET],
            beanClass = UserService::class,
            beanMethod = "getUserCredentialsById",
        operation = Operation(
            parameters = [Parameter(
                style = ParameterStyle.SIMPLE,
                explode = Explode.FALSE,
                `in` = ParameterIn.PATH
            )]
        )
        ),
        RouterOperation(
            path = "/user/profile/{id}",
            method = [RequestMethod.GET],
            beanClass = UserService::class,
            beanMethod = "getUserProfileById",
        operation = Operation(
            parameters = [Parameter(
                style = ParameterStyle.SIMPLE,
                explode = Explode.FALSE,
                `in` = ParameterIn.PATH
            )]
        )
    )
    fun userRoute(userServiceHandler: UserServiceHandler) = coRouter {
        ("/user").nest {
            GET("/{id}", userServiceHandler::getUserCredentialsById)
            GET("/profile/{id}", userServiceHandler::getUserById)
        }
    }
}
 

Я хочу создать запрос GET, такой как

 http://localhost:8080/user/1
 

где 1-идентификатор моего желаемого пользователя.

Но мой пользовательский интерфейс OpenAPI все еще пытается создать запрос с параметром GET

 http://localhost:8080/user/{id}?id=1
 

что, очевидно, приводит к ошибке 400.
Было бы неплохо знать, как мои операции @Router должны быть соответствующим образом настроены.

Ответ №1:

Правильная конфигурация для переменных пути выглядит так (для краткости я оставил здесь только один запрос GET):

 @Bean
@RouterOperations(
    RouterOperation(
        path = "/user/{id}",
        method = arrayOf(RequestMethod.GET),
        beanClass = UserService::class,
        beanMethod = "getUserCredentialsById",
        operation = Operation(
            operationId =  "getUserCredentialsById",
            method = "GET",
            parameters = [
                Parameter(
                    name = "id",
                    `in` = ParameterIn.PATH,
                    style = ParameterStyle.SIMPLE,
                    explode = Explode.FALSE,
                    required = true
                )]
        )
    )
)
fun userRoute(userServiceHandler: UserServiceHandler) = coRouter {
    path("/user")
        .nest {
            GET("/{id}", userServiceHandler::getUserCredentialsById)
        }
}
 

Смотрите спецификации здесь.
Важные моменты:

  • Идентификатор операции является обязательным
  • Значение по умолчанию в Operation parameters[] «параметры запроса» вместо «параметры пути» мы должны явно указать имя параметра ( name = "id" ), чтобы переопределить поведение по умолчанию.
  • Как указано в вопросе, ParameterIn.PATH также является обязательным.