Reputation: 363
I'm having problems deleting a cookie set by a Ktor 0.9.0 server side application. Maybe I don't know how to do it the right way, or there's an omission in the Ktor framework.
Cookie creation and deletion is not the problem per se, but in order to delete a cookie I've to use the same path that is stored with the cookie on the client browser. Ktor let me control the path with cookie creation. Here's my configuration:
install(Sessions) {
cookie<MySession>(sessionMarker) {
cookie.duration = cookieDuration
cookie.path = "/myWebapp"
transform(SessionTransportTransformerMessageAuthentication(sessionKey))
}
}
On the login page /myWebapp/page/login
, I create the cookie that is then sent to the client and it travels back and forth for the rest of the requests sent to the web application:
call.sessions.set(MySession([some data class arguments]))
The cookie shows the path /myWebapp
when inspected on the client. The default would be /myWebapp/page
because that's the path of the login page, but the path is taken from the cookie configuration shown above. All is well until now.
Eventually the user wants to log out via a POST request to the login page:
call.sessions.clear<MySession>()
The problem here is that I've not found a way of controlling the cookie's path. Because the login page /myWebapp/page/login
is sending the expired cookie back to the client for another path (its own /myWebapp/page
), the original cookie is not deleted (/myWebapp/page
!= /myWebapp
).
How can I control the cookie's path in Ktor 0.9.0 when trying to delete it?
I know how to work around it: by creating the cookie with the same path from where I'll delete it. But that's not what I want (there're other paths within the web applications like /myWebapp/others
were the cookie should be used). Having the ability to control the cookie's path during creation makes no sense then.
Upvotes: 4
Views: 1581
Reputation: 1550
I think you could try to create your own custom SessionTransportCookie.
If you see deeper in method cookie<MySession>(sessionMarker)
you will find this code:
inline fun <reified S : Any> Sessions.Configuration.cookie(name: String, block: CookieSessionBuilder<S>.() -> Unit): Unit = cookie(name, S::class, block)
inline fun <S : Any> Sessions.Configuration.cookie(name: String, sessionType: KClass<S>, block: CookieSessionBuilder<S>.() -> Unit) {
val builder = CookieSessionBuilder(sessionType).apply(block)
val transport = SessionTransportCookie(name, builder.cookie, builder.transformers)
val tracker = SessionTrackerByValue(sessionType, builder.serializer)
val provider = SessionProvider(name, sessionType, transport, tracker)
register(provider)
}
Important line here is creating session transport cookie by line: SessionTransportCookie(name, builder.cookie, builder.transformers)
Lets look deeper in SessionTransportCookie
:
class SessionTransportCookie(val name: String,
val configuration: CookieConfiguration,
val transformers: List<SessionTransportTransformer>
) : SessionTransport {
override fun receive(call: ApplicationCall): String? {
return transformers.transformRead(call.request.cookies[name])
}
override fun send(call: ApplicationCall, value: String) {
val now = LocalDateTime.now()
val expires = now.plus(configuration.duration)
val maxAge = configuration.duration[ChronoUnit.SECONDS].toInt()
val cookie = Cookie(name,
transformers.transformWrite(value),
configuration.encoding,
maxAge,
expires,
configuration.domain,
configuration.path,
configuration.secure,
configuration.httpOnly,
configuration.extensions
)
call.response.cookies.append(cookie)
}
override fun clear(call: ApplicationCall) {
call.response.cookies.appendExpired(name)
}
}
class CookieConfiguration {
var duration: TemporalAmount = Duration.ofDays(7)
var encoding: CookieEncoding = CookieEncoding.URI_ENCODING
var domain: String? = null
var path: String? = null
var secure: Boolean = false
var httpOnly: Boolean = false
val extensions: MutableMap<String, String?> = mutableMapOf()
}
So, as you see, in this class you have all possibilities to customise your cookies send/clear
logic.
Upvotes: 1