I have setup a global filter for all requests that adds user information to the headers. This filter works for all my http requests but doesnt apply them to my websocket requests.
Questions
gateway:
routes:
- id: example
uri: http://localhost:80
predicates:
- Path=/example/**
filters:
- RewritePath=/example/(?<path>.*), /$\{path}
@Component
class CustomGlobalFilter(private val jwtDecoder: ReactiveJwtDecoder) : GlobalFilter {
private val logger = KotlinLogging.logger {}
/**
* Given exchange, extract Authorization header value and modify to retrieve JWT token.
*/
fun extractJwtToken(exchange: ServerWebExchange): String {
return (exchange.request.headers["Authorization"]
?: throw JwtExtractionException("Request does not contain Authorization header"))[0]
.replace("Bearer ", "")
}
/**
* Modify request headers to add `username`.
*/
fun modifyHeaders(exchange: ServerWebExchange): Mono<ServerWebExchange> {
return try {
val jwt = extractJwtToken(exchange)
jwtDecoder
.decode(jwt)
.map {
val username = it.claims["username"] as String
val modRequest = exchange
.request
.mutate()
.header("username", username)
.build()
exchange.mutate()
.request(modRequest)
.build()
}
} catch (e: JwtExtractionException) {
exchange.toMono() // fall back on default exchange
}
}
/**
* Filter all outgoing requests to modify headers.
*/
override fun filter(exchange: ServerWebExchange, chain: GatewayFilterChain): Mono<Void> {
return modifyHeaders(exchange)
.flatMap { chain.filter(it) }
}
}
I was able to fix the routing issue by setting the custom filter order before the WebsocketRoutingFilter
@Component
class CustomGlobalFilter(
private val authFilterUtil: AuthFilterUtil,
) : GlobalFilter, Ordered {
override fun filter(exchange: ServerWebExchange, chain: GatewayFilterChain): Mono<Void> {
return authFilterUtil
.modifyHeaders(exchange)
.flatMap { chain.filter(it) }
}
override fun getOrder(): Int {
return Ordered.HIGHEST_PRECEDENCE
}
}