如何在router.route("/api/*").handler中使用协程? [英] How to use coroutine inside the router.route("/api/*").handler?
问题描述
我正在尝试在路由处理程序lambda中使用协程,如下所示:
I am trying to use coroutine inside the route handler lambda as follows:
private suspend fun createRoutes(router: Router, auth: OAuth2Auth): Unit {
val oauth2 = OAuth2AuthHandler.create(vertx, auth)
val authz = KeycloakAuthorization.create()
router.route().handler(LoggerHandler.create())
router.route("/api/*").handler(oauth2)
router.route("/api/greet").handler {
println(RoleBasedAuthorization.create("ad-admins").match(it.user()))
authz.getAuthorizations(it.user()).await()
}
}
编译器在authz.getAuthorizations(it.user()).await()
上抱怨Suspension functions can be called only within coroutine body
.
我在做什么错了?
The compiler complains on authz.getAuthorizations(it.user()).await()
about Suspension functions can be called only within coroutine body
.
What am I doing wrong?
整个代码:
class MainVerticle : CoroutineVerticle() {
private suspend fun initConfig(): JsonObject {
val yamlConfigOpts = ConfigStoreOptions()
.setFormat("yaml")
.setType("file")
.setConfig(JsonObject().put("path", "config.yaml"))
val configRetrieverOpts = ConfigRetrieverOptions()
.addStore(yamlConfigOpts)
val configRetriever = ConfigRetriever.create(vertx, configRetrieverOpts)
return configRetriever.config.await()
}
private suspend fun createJwtAuth(): OAuth2Auth =
KeycloakAuth.discover(
vertx,
OAuth2Options()
.setFlow(OAuth2FlowType.AUTH_CODE)
.setClientID("svc")
.setClientSecret("9d782e45-67e7-44b1-9b74-864f45f9a18f")
.setSite("https://oic.dev.databaker.io/auth/realms/databaker")
).await()
private suspend fun createRoutes(router: Router, auth: OAuth2Auth): Unit {
val oauth2 = OAuth2AuthHandler.create(vertx, auth)
val authz = KeycloakAuthorization.create()
router.route().handler(LoggerHandler.create())
router.route("/api/*").handler(oauth2)
router.route("/api/greet").handler {
println(RoleBasedAuthorization.create("ad-admins").match(it.user()))
authz.getAuthorizations(it.user()).await()
}
}
private suspend fun server(router: Router): HttpServer {
val server = vertx.createHttpServer()
return server.requestHandler(router)
.listen(8080)
.onSuccess {
println("HTTP server started on port ${it.actualPort()}")
}
.onFailure {
println("Failed to start the server. Reason ${it.message}")
}
.await()
}
override suspend fun start() {
val router = Router.router(vertx)
createRoutes(router, createJwtAuth())
server(router)
}
}
提示:我正在使用 Vertx 4.0.0 RC1
推荐答案
由于未在挂起函数中调用authz.getAuthorizations(it.user()).await()
,因此编译器:从Vert.x Web路由处理程序中调用.
The compiler because authz.getAuthorizations(it.user()).await()
is not invoked in a suspended function: it is invoked from the Vert.x Web route handler.
您必须使用launch
包装您的调用:
You must wrap your invocation with launch
:
router.route("/api/greet").handler {
println(RoleBasedAuthorization.create("ad-admins").match(it.user()))
launch {
authz.getAuthorizations(it.user()).await()
}
}
鉴于此代码是在CoroutineVerticle
中定义的,协程将绑定到verticle上下文(以及在verticle的事件循环中调用的代码).
Given this code is defined in a CoroutineVerticle
, the coroutine will be bound to the verticle context (and the code invoked on the verticle's event loop).
这篇关于如何在router.route("/api/*").handler中使用协程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!