You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Hi, I'm not sure why the rewrite function here simply won't execute.
/**
* Gateway filter that enriches the /user-info endpoint response with session timing information.
*
* Process flow:
* 1. Intercepts responses from the /user-info endpoint
* 2. Attempts to retrieve session creation time from Redis session hash
* 3. If successful, adds session timing information to the JSON response:
* - sessionCreatedAt: When the session was created
* - sessionExpiresAt: When the session will expire (xx mins after creation)
*
* Error handling:
* - If Redis access fails: Logs error and continues without session timing info
* - If session key not found: Continues without session timing info
* - Non-user-info endpoints: Passes through unmodified
*
* The filter maintains the original response integrity even when Redis operations fail,
* ensuring the user-info endpoint remains functional with or without the additional
* session timing data.
*
* @property redisTemplate For accessing Redis session data
* @property sessionProperties Configuration for Redis session namespacing
* @property serverProperties Server configuration including endpoint prefixes
* @property modifyResponseBodyFilterFactory Factory for response body modification
*/
@Component
internal class SessionInfoResponseFilter(
private val redisTemplate: ReactiveRedisTemplate<String, Any>,
private val sessionProperties: SessionProperties,
private val serverProperties: ServerProperties,
private val modifyResponseBodyFilterFactory: ModifyResponseBodyGatewayFilterFactory
) : AbstractGatewayFilterFactory<SessionInfoResponseFilter.Config>() {
/** Configuration class for the session info response filter */
class Config
private val logger = LoggerFactory.getLogger(SessionInfoResponseFilter::class.java)
/**
* Applies the filter to add session timing information to /me responses.
*
* @param config Filter configuration (unused in this implementation)
* @return GatewayFilter that enriches /user-info responses with session data
*/
override fun apply(config: Config): GatewayFilter = GatewayFilter { exchange, chain ->
// only modify /user-info endpoint responses
if (exchange.request.path.value() != "${serverProperties.resourceServerPrefix}/me") {
logger.debug("request did not match me endpoint")
chain.filter(exchange)
} else {
chain.filter(exchange).then(
exchange.session.flatMap { session ->
logger.debug("request did match me endpoint")
val sessionId = session.id
val sessionKey = "${sessionProperties.redis?.sessionNamespace}:sessions:$sessionId"
redisTemplate.opsForHash<String, Any>()
.get(sessionKey, "creationTime")
.doOnNext { creationTime ->
logger.debug("3. Found creation time in Redis: {}", creationTime)
}
.flatMap { creationTime ->
val created = Instant.ofEpochMilli(creationTime.toString().toLong())
logger.debug("4. Converted to Instant: {}", created)
// Define the RewriteFunction separately
val rewriteFunction = RewriteFunction<String, String> { _, originalResponse ->
logger.debug("Entering RewriteFunction with body: {}", originalResponse)
if (originalResponse.isNullOrEmpty()) {
logger.warn("Response body is empty or null")
return@RewriteFunction Mono.just(originalResponse)
}
return@RewriteFunction try {
val jsonNode = JSONUtilities.objectMapper.readTree(originalResponse)
logger.debug("Parsed JSON node: {}", jsonNode)
(jsonNode as ObjectNode).apply {
put("sessionCreatedAt", created.toString())
put("sessionExpiresAt", created.plusSeconds(sessionProperties.timeout.toLong()).toString())
}
val modifiedResponse = JSONUtilities.objectMapper.writeValueAsString(jsonNode)
logger.debug("Modified response body: {}", modifiedResponse)
Mono.just(modifiedResponse)
} catch (ex: Exception) {
logger.error("Failed to process response body", ex)
Mono.error(ex)
}
}
val modifyConfig = ModifyResponseBodyGatewayFilterFactory.Config().apply {
logger.debug("Setting up rewrite function")
setInClass(String::class.java)
setOutClass(String::class.java)
setRewriteFunction(String::class.java, String::class.java, rewriteFunction)
}
// Apply modification filter first, then the chain
modifyResponseBodyFilterFactory.apply(modifyConfig).filter(exchange, chain)
}
.onErrorResume { error ->
// log the Redis error but allow the chain to continue
logger.error("Failed to get session timing from Redis", error)
Mono.empty()
}
}
)
}
}
}
In the logs all I can see is:
2025-01-15T21:21:43.302Z DEBUG 35283 --- [BFFApplication] [ctor-http-nio-4] c.v.b.r.s.SessionInfoResponseFilter : request did match userinfo endpoint
2025-01-15T21:21:43.316Z DEBUG 35283 --- [BFFApplication] [xecutorLoop-3-5] c.v.b.r.s.SessionInfoResponseFilter : 3. Found creation time in Redis: 1736971305338
2025-01-15T21:21:43.317Z DEBUG 35283 --- [BFFApplication] [xecutorLoop-3-5] c.v.b.r.s.SessionInfoResponseFilter : 4. Converted to Instant: 2025-01-15T20:01:45.338Z
2025-01-15T21:21:43.317Z DEBUG 35283 --- [BFFApplication] [xecutorLoop-3-5] c.v.b.r.s.SessionInfoResponseFilter : Setting up rewrite function
I've spent 3 hours going over the internet trying to find a solution, but am getting stuck.
Would appreciate if anyone could help
The text was updated successfully, but these errors were encountered:
Hi, I'm not sure why the rewrite function here simply won't execute.
In the logs all I can see is:
I've spent 3 hours going over the internet trying to find a solution, but am getting stuck.
Would appreciate if anyone could help
The text was updated successfully, but these errors were encountered: