kotlinktor

Setting Cookies before redirect with Ktor


I have the following code:

import io.ktor.serialization.kotlinx.json.*
import io.ktor.server.application.*
import io.ktor.server.engine.*
import io.ktor.server.netty.*
import io.ktor.server.plugins.*
import io.ktor.server.plugins.contentnegotiation.*
import io.ktor.server.response.*
import io.ktor.server.routing.*

fun main() {
    embeddedServer(Netty, 8087) {

        fun isSecureRequest(call: ApplicationCall): Boolean = call.request.origin.scheme == "https"
        install(ContentNegotiation) {
            json()
        }
        routing {
            get("/cookies") {
                val cookies = call.request.cookies.rawCookies
                call.respond(mapOf("cookies" to cookies))
            }

            get("/cookies/set/{name}/{value}") {
                val name = call.parameters["name"] ?: ""
                val value = call.parameters["value"] ?: ""
                val secure = isSecureRequest(call)

                //call.response.cookies.append(Cookie(name, value, secure = secure))
                call.response.cookies.append(name, value, secure = secure)
                call.respondRedirect("/cookies")
            }

            get("/cookies/set") {
                val secure = isSecureRequest(call)
                call.request.queryParameters.entries().forEach { (key, values) ->
                    values.forEach { value ->
                        call.response.cookies.append(key, value, secure = secure)
                    }
                }
                call.respondRedirect("/cookies")
            }
        }
    }.start(wait = true)
}

When following the url: http://localhost:8087/cookies/set?cookieSetFromQuery=hello the cookie is set and I see it in the response.

However, if use the variant with the path parameters: http://localhost:8087/cookies/set/cookieFromPath/hello i do not see the cookie in the response.

Even after going through the debugger I do not understand why is there a difference in behavior.

In both cases, the cookies are set with all.response.cookies.append(name, value, secure = secure) and in both cases a redirect to the /cookies path is made. Why is the variant using the path parameters not working?


Solution

  • The reason must be that the cookie set from the /cookies/set path unlike /cookies/set/cookieFromPath/hello, is within the scope of the /cookies path and therefore browser sends the Cookie header.

    To solve the problem, you can specify the explicit path for the Set-Cookie header:

    call.response.cookies.append(name, value, path = "/cookies", secure = secure)
    

    You can find more information about the Path attribute on MDN.