英文:
Why doesn't @RestCookie detect a Cookie Header set in the ContainerRequestFilter for resteasy-reactive?
问题
Here's the translated code you provided:
我正在迁移我的 Kotlin Quarkus 应用程序,以使用 `quarkus-rest-client` 和 `quarkus-resteasy` 的响应式版本。
基本上,我希望在用户没有在其请求中提供 Cookie 的情况下,创建一个包含 JWT 的 Cookie 并设置在 User-Agent 上,只有在 `ApiResource` 中定义的端点(因此使用自定义的 `@NameBinding`) - 然后,同一 User-Agent 的后续请求会自动获得此 Cookie。
这是我之前的大致代码,使用 Resteasy Classic:
``` kotlin
import org.eclipse.microprofile.rest.client.inject.RestClient
import javax.inject.Inject
import javax.ws.rs.*
import javax.ws.rs.core.*
import javax.ws.rs.container.*
import javax.ws.rs.ext.Provider
val RESOURCE_PATH = "/api"
@NameBinding
@Retention(AnnotationRetention.RUNTIME)
annotation class JwtCookieUpserterBinder
@JwtCookieUpserterBinder
@Provider
class JwtCookieUpserter: ContainerRequestFilter, ContainerResponseFilter {
@Inject
@RestClient
lateinit var jwtService: JwtClient
override fun filter(requestContext: ContainerRequestContext) {
var jwtCookie = requestContext?.cookies?.get("jwt")
if (jwtCookie == null || jwtCookie.value.isNullOrEmpty()) {
val newJwt: String = jwtService.getJwt() // 返回一个字符串
jwtCookie = NewCookie("jwt", newJwt, RESOURCE_PATH, null, null, 600, false)
requestContext?.headers?.add(HttpHeaders.COOKIE, jwtCookie.toString())
requestContext?.setProperty("jwt", jwtCookie)
}
}
override fun filter(requestContext: ContainerRequestContext, responseContext: ContainerResponseContext) {
val jwtCookie = requestContext?.getProperty("jwt")
if (jwtCookie != null) {
responseContext?.headers?.add(HttpHeaders.SET_COOKIE, jwtCookie.toString())
}
}
}
@JwtCookieUpserterBinder
@Path(RESOURCE_PATH)
class ApiResource {
// ...其他资源端点...
// 用于测试的路由
@GET
@Path("/jwt")
@Produces(MediaType.TEXT_PLAIN)
fun getJwt(
@CookieParam("jwt") jwtCookieValue: String?
): Response {
return Response.ok(jwtCookieValue, MediatType.TEXT_PLAIN).build()
}
// ...其他资源端点...
}
上述实现之前是正常工作的。但是,切换到 resteasy-reactive
后,我注意到在 RequestFilter
中设置 Cookie HttpHeader 不再起作用,我不得不在 ApiResource
中的 ContainerRequestContext
属性中提取 Cookie 值。现在,以下是我当前的 Resteasy Reactive 代码:
import javax.enterprise.context.ApplicationScoped
import org.eclipse.microprofile.rest.client.inject.RestClient
import javax.inject.Inject
import javax.ws.rs.*
import javax.ws.rs.core.*
import javax.ws.rs.container.*
import javax.ws.rs.ext.Provider
import org.jboss.resteasy.reactive.*
import org.jboss.resteasy.reactive.server.*
val RESOURCE_PATH = "/api"
@NameBinding
@Retention(AnnotationRetention.RUNTIME)
annotation class JwtCookieUpserterBinder
@ApplicationScoped
@Provider
class JwtCookieUpserter {
@RestClient
lateinit var jwtService: JwtClient
@JwtCookieUpserterBinder
@ServerRequestFilter
fun filterRequest(requestContext: ContainerRequestContext?) {
var jwtCookie = requestContext?.cookies?.get("jwt")
if (jwtCookie == null || jwtCookie.value.isNullOrEmpty()) {
val newJwt: String = jwtService.getJwt() // 返回一个字符串
jwtCookie = NewCookie("jwt", newJwt, RESOURCE_PATH, null, null, 600, false)
// requestContext?.headers?.add(HttpHeaders.COOKIE, jwtCookie.toString()) // 这在 ApiResource 中似乎不再起作用
requestContext?.setProperty("set-jwt", jwtCookie)
}
requestContext?.setProperty("jwt", jwtCookie)
}
@JwtCookieUpserterBinder
@ServerResponseFilter
fun filterResponse(requestContext: ContainerRequestContext, responseContext: ContainerResponseContext) {
val jwtCookie = requestContext?.getProperty("set-jwt")
if (jwtCookie != null) {
responseContext?.headers?.add(HttpHeaders.SET_COOKIE, jwtCookie.toString())
}
}
}
@JwtCookieUpserterBinder
@ApplicationScoped
@Path(RESOURCE_PATH)
class ApiResource {
@Inject
lateinit var requestContext: ContainerRequestContext
// ...其他资源端点...
private fun getJwtCookieValueFromRequestContext(): String {
return (requestContext.getProperty("jwt") as? Cookie)?.value ?: "Not Set"
}
// 用于测试的路由
@GET
@Path("/jwt")
@Produces(MediaType.TEXT_PLAIN)
fun getJwt(
@RestCookie("jwt") jwt: String? // 对于用户代理提供请求中的 Cookie 值,似乎仍然需要这个
): Response {
val jwtCookieValue = getJwtCookieValueFromRequestContext()
return Response.ok(jwtCookieValue, MediatType.TEXT_PLAIN).build()
}
// ...其他资源端点...
}
我不确定这是否是实现我想要的正确方式(将 ContainerRequestFilter
注入到 ApiResource
Bean 中似乎有些奇怪);但我主要好奇为什么 @RestCookie
似乎与 @CookieParam
表现不同。
或者,如果有人对在不添加额外依赖的情况下更好地完成此任务有建议,我也愿意听取建议。
英文:
I'm in the middle of migrating my Kotlin Quarkus Application to use the Reactive versions of quarkus-rest-client
and quarkus-resteasy
.
Basically, I want a Cookie containing a JWT to be created and set on the User-Agent if they did not provide it in their Request to any of the Endpoints defined in ApiResource
only (hence the custom @NameBinding
) - subsequent Requests by the same User-Agent would then give this Cookie automatically.
This was my approximate code before, using Resteasy Classic:
import org.eclipse.microprofile.rest.client.inject.RestClient
import javax.inject.Inject
import javax.ws.rs.*
import javax.ws.rs.core.*
import javax.ws.rs.container.*
import javax.ws.rs.ext.Provider
val RESOURCE_PATH = "/api"
@NameBinding
@Retention(AnnotationRetention.RUNTIME)
annotation class JwtCookieUpserterBinder
@JwtCookieUpserterBinder
@Provider
class JwtCookieUpserter: ContainerRequestFilter, ContainerResponseFilter {
@Inject
@RestClient
lateinit var jwtService: JwtClient
override fun filter(requestContext: ContainerRequestContext) {
var jwtCookie = requestContext?.cookies?.get("jwt")
if (jwtCookie == null || jwtCookie.value.isNullOrEmpty()) {
val newJwt: String = jwtService.getJwt() // returns a String
jwtCookie = NewCookie("jwt", newJwt, RESOURCE_PATH, null, null, 600, false)
requestContext?.headers?.add(HttpHeaders.COOKIE, jwtCookie.toString())
requestContext?.setProperty("jwt", jwtCookie)
}
}
override fun filter(requestContext: ContainerRequestContext, responseContext: ContainerResponseContext) {
val jwtCookie = requestContext?.getProperty("jwt")
if (jwtCookie != null) {
responseContext?.headers?.add(HttpHeaders.SET_COOKIE, jwtCookie.toString())
}
}
}
@JwtCookieUpserterBinder
@Path(RESOURCE_PATH)
class ApiResource {
// ...
// Route meant for Testing
@GET
@Path("/jwt")
@Produces(MediaType.TEXT_PLAIN)
fun getJwt(
@CookieParam("jwt") jwtCookieValue: String?
): Response {
return Response.ok(jwtCookieValue, MediatType.TEXT_PLAIN).build()
}
// ... other Resource Endpoints ...
}
The above implementation was working correctly. After switching to resteasy-reactive
however, I notice that setting the Cookie HttpHeader in the RequestFilter
no longer works, and I ended up having to pull the Cookie value from a property on ContainerRequestContext
within ApiResource
instead. This is my current code now, for Resteasy Reactive:
import javax.enterprise.context.ApplicationScoped
import org.eclipse.microprofile.rest.client.inject.RestClient
import javax.inject.Inject
import javax.ws.rs.*
import javax.ws.rs.core.*
import javax.ws.rs.container.*
import javax.ws.rs.ext.Provider
import org.jboss.resteasy.reactive.*
import org.jboss.resteasy.reactive.server.*
val RESOURCE_PATH = "/api"
@NameBinding
@Retention(AnnotationRetention.RUNTIME)
annotation class JwtCookieUpserterBinder
@ApplicationScoped
@Provider
class JwtCookieUpserter {
@RestClient
lateinit var jwtService: JwtClient
@JwtCookieUpserterBinder
@ServerRequestFilter
fun filterRequest(requestContext: ContainerRequestContext?) {
var jwtCookie = requestContext?.cookies?.get("jwt")
if (jwtCookie == null || jwtCookie.value.isNullOrEmpty()) {
val newJwt: String = jwtService.getJwt() // returns a String
jwtCookie = NewCookie("jwt", newJwt, RESOURCE_PATH, null, null, 600, false)
// requestContext?.headers?.add(HttpHeaders.COOKIE, jwtCookie.toString()) // this no longer seems to have any effect in ApiResource
requestContext?.setProperty("set-jwt", jwtCookie)
}
requestContext?.setProperty("jwt", jwtCookie)
}
@JwtCookieUpserterBinder
@ServerResponseFilter
fun filterResponse(requestContext: ContainerRequestContext, responseContext: ContainerResponseContext) {
val jwtCookie = requestContext?.getProperty("set-jwt")
if (jwtCookie != null) {
responseContext?.headers?.add(HttpHeaders.SET_COOKIE, jwtCookie.toString())
}
}
}
@JwtCookieUpserterBinder
@ApplicationScoped
@Path(RESOURCE_PATH)
class ApiResource {
@Inject
lateinit var requestContext: ContainerRequestContext
// ...
private fun getJwtCookieValueFromRequestContext(): String {
return (requestContext.getProperty("jwt") as? Cookie)?.value ?: "Not Set"
}
// Route meant for Testing
@GET
@Path("/jwt")
@Produces(MediaType.TEXT_PLAIN)
fun getJwt(
@RestCookie("jwt") jwt: String? // This still seems necessary for the Endpoint to take in the User-Agent's Cookie Value if they provide it in the Request
): Response {
val jwtCookieValue = getJwtCookieValueFromRequestContext()
return Response.ok(jwtCookieValue, MediatType.TEXT_PLAIN).build()
}
// ... other Resource Endpoints ...
}
I'm not sure if this is the correct way to accomplish what I want (injecting the ContainerRequestFilter
into the ApiResource
Bean seems weird); but I am primarily curious on why @RestCookie
seems to behave differently than @CookieParam
.
Alternatively, if anyone has suggestions on a better way to accomplish this without adding additional Dependencies, I am open to those as well.
答案1
得分: 1
这实际上是一个bug。但修复将很快可用。
英文:
This is actually a bug. But the fix will be available very soon
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论