Issue
I want to add some custom auth headers to my request, when the dev-mode
is activated. This should make the developement easier for me, since I don't have to add them on my self manually.
What I have found is the method annotation ServerRequestFilter which intercepts an ongoing request before hitting the controller level. The annotated function provides ContainerRequestContext
argument where I can add my headers easily.
Now the problem: To know the custom headers value, I have to make an external rest call (I'm using the RestClient for that) to an API. Since I'm using the reactive library I get the exception org.jboss.resteasy.reactive.common.core.BlockingNotAllowedException
because of this call.
Since I'm using Kotlin, i tried to mark my method as suspendable. But this lead to a build error Method 'preCall$suspendImpl of class 'com.kaz.request.service.RequestInterceptor' cannot be static as it is annotated with '@org.jboss.resteasy.reactive.server.ServerRequestFilter'
Here my code:
@ApplicationScoped
class RequestInterceptor @Inject constructor(val authService: AuthService) {
@ServerRequestFilter
suspend fun preCall(requestContext: ContainerRequestContext) {
validateIdTokenHeader(requestContext)
}
private suspend fun validateIdTokenHeader(requestContext: ContainerRequestContext) {
val isTokenHeaderAbsent = requestContext.getHeaderString(Headers.X_ID_TOKEN) == null
val isDevModeEnabled = LaunchMode.current() == LaunchMode.DEVELOPMENT
if (isTokenHeaderAbsent && !isDevModeEnabled) {
throw AuthExceptions.ID_TOKEN_IS_ABSENT
} else {
injectDevUserIdToken(requestContext)
}
}
private suspend fun injectDevUserIdToken(requestContext: ContainerRequestContext) {
// This call is making the request and block
val idToken = authService.getIdToken("someHash")
requestContext.headers.putSingle(Headers.X_ID_TOKEN, idToken)
}
}
What I also tried to do is using Mutiny
in my RestClient. I subscribed to the Uni and added the header when the result was available. But then I had the problem, that my controller/endpoint was already called before the header could be added to the request.
An endpoint could look like this:
@Path("hello/{id}")
@GET
suspend fun get(
//This header is what I want to add automatically, when dev mode is active.
@RestHeader(Headers.X_ID_TOKEN) idToken: UserIdToken,
@RestPath id: UUID,
@Context httpRequest: HttpServerRequest
): Response {
val request = RequestDTO(id, excludeFields, idToken.userId)
val envelope = service.findById(request)
return ResponseBuilder.build(httpRequest, envelope)
}
Solution
Sometimes it makes sense not just to read the online documentation page but also the inline comments of the according class.
ServerRequestFilter.java
says:
The return type of the method must be either be of type void, Response, RestResponse, Optional<Response>, Optional<RestResponse>, Uni<Void>, Uni<Response> or Uni<RestResponse>.
...
Uni<Void> should be used when filtering needs to perform a
non-blocking operation but the filter cannot abort processing. Note
that Uni<Void> can easily be produced using: Uni.createFrom().nullItem()
So the entrypoint function has to return an Uni as well, not just the RestClient. Changing it like the following will be enough
@ServerRequestFilter
fun preCall(requestContext: ContainerRequestContext) : Uni<Void> {
//Here I return a Uni<Void> back using Uni.createFrom().nullItem()
return validateIdTokenHeader(requestContext)
}
Answered By - Ahmet K
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.