Complete cookie handling with encoding options, security attributes, parsing/rendering utilities, and support for all standard cookie attributes.
Cookie representation with all standard attributes and security options.
/**
* HTTP cookie representation with all standard attributes
* @param name cookie name
* @param value cookie value
* @param encoding encoding strategy for cookie value
* @param maxAge maximum age in seconds (0 = session cookie)
* @param expires expiration date (null = session cookie)
* @param domain cookie domain scope
* @param path cookie path scope
* @param secure require HTTPS transmission
* @param httpOnly prevent client-side script access
* @param extensions additional custom cookie attributes
*/
data class Cookie(
val name: String,
val value: String,
val encoding: CookieEncoding = CookieEncoding.URI_ENCODING,
val maxAge: Int = 0,
val expires: GMTDate? = null,
val domain: String? = null,
val path: String? = null,
val secure: Boolean = false,
val httpOnly: Boolean = false,
val extensions: Map<String, String?> = emptyMap()
)Encoding options for cookie values to handle special characters.
/**
* Cookie value encoding strategies
*/
enum class CookieEncoding {
/** No encoding - use raw cookie value */
RAW,
/** Double quotes with character escaping */
DQUOTES,
/** URI percent encoding */
URI_ENCODING,
/** Base64 encoding */
BASE64_ENCODING
}Functions for parsing cookie headers from both client and server perspectives.
/**
* Parse Set-Cookie header from server response
* @param cookiesHeader the Set-Cookie header value
* @return Cookie instance with parsed attributes
* @throws IllegalArgumentException if header format is invalid
*/
fun parseServerSetCookieHeader(cookiesHeader: String): Cookie
/**
* Parse Cookie header from client request
* @param cookiesHeader the Cookie header value
* @param skipEscaped whether to skip escaped values during parsing
* @return map of cookie names to values
*/
fun parseClientCookiesHeader(
cookiesHeader: String,
skipEscaped: Boolean = true
): Map<String, String>Functions for formatting cookies into header values for HTTP communication.
/**
* Render cookie as Set-Cookie header value
* @param cookie the cookie to render
* @return formatted Set-Cookie header value
*/
fun renderSetCookieHeader(cookie: Cookie): String
/**
* Render cookie as Cookie header value (name=value only)
* @param cookie the cookie to render
* @return formatted Cookie header value
*/
fun renderCookieHeader(cookie: Cookie): String
/**
* Render Set-Cookie header with all parameters explicitly specified
* @param name cookie name
* @param value cookie value
* @param encoding encoding strategy
* @param maxAge maximum age in seconds
* @param expires expiration date
* @param domain cookie domain
* @param path cookie path
* @param secure secure flag
* @param httpOnly HTTP-only flag
* @param extensions additional attributes
* @param includeEncoding whether to include encoding info
* @return formatted Set-Cookie header value
*/
fun renderSetCookieHeader(
name: String,
value: String,
encoding: CookieEncoding = CookieEncoding.URI_ENCODING,
maxAge: Int = 0,
expires: GMTDate? = null,
domain: String? = null,
path: String? = null,
secure: Boolean = false,
httpOnly: Boolean = false,
extensions: Map<String, String?> = emptyMap(),
includeEncoding: Boolean = true
): StringLow-level functions for encoding and decoding cookie values.
/**
* Encode cookie value using specified encoding
* @param value raw cookie value
* @param encoding encoding strategy to use
* @return encoded cookie value
*/
fun encodeCookieValue(value: String, encoding: CookieEncoding): String
/**
* Decode cookie value using specified encoding
* @param encodedValue encoded cookie value
* @param encoding encoding strategy used
* @return decoded cookie value
*/
fun decodeCookieValue(encodedValue: String, encoding: CookieEncoding): StringUsage Examples:
import io.ktor.http.*
// Create simple session cookie
val sessionCookie = Cookie(
name = "sessionId",
value = "abc123def456",
httpOnly = true,
secure = true
)
// Create persistent cookie with expiration
val rememberMeCookie = Cookie(
name = "rememberMe",
value = "user123",
maxAge = 86400 * 30, // 30 days
domain = ".example.com",
path = "/",
secure = true,
httpOnly = true
)
// Create cookie with custom encoding
val specialValueCookie = Cookie(
name = "data",
value = "special chars & symbols!",
encoding = CookieEncoding.BASE64_ENCODING,
path = "/api"
)
// Cookie with extensions (custom attributes)
val customCookie = Cookie(
name = "preferences",
value = "theme=dark",
extensions = mapOf(
"SameSite" to "Strict",
"Partitioned" to null // attribute without value
)
)
// Render cookies for HTTP headers
val setCookieHeader = renderSetCookieHeader(sessionCookie)
println(setCookieHeader)
// "sessionId=abc123def456; HttpOnly; Secure"
val cookieHeader = renderCookieHeader(sessionCookie)
println(cookieHeader)
// "sessionId=abc123def456"
// Parse Set-Cookie header from server
val setCookieValue = "auth=token123; Max-Age=3600; Domain=.example.com; Path=/; Secure; HttpOnly"
val parsedCookie = parseServerSetCookieHeader(setCookieValue)
println(parsedCookie.name) // "auth"
println(parsedCookie.value) // "token123"
println(parsedCookie.maxAge) // 3600
println(parsedCookie.domain) // ".example.com"
println(parsedCookie.secure) // true
println(parsedCookie.httpOnly) // true
// Parse Cookie header from client
val clientCookieHeader = "auth=token123; sessionId=abc456; preferences=theme%3Ddark"
val parsedCookies = parseClientCookiesHeader(clientCookieHeader)
parsedCookies.forEach { (name, value) ->
println("$name = $value")
}
// auth = token123
// sessionId = abc456
// preferences = theme%3Ddark
// Work with different encodings
val rawValue = "special chars & symbols!"
val uriEncoded = encodeCookieValue(rawValue, CookieEncoding.URI_ENCODING)
println(uriEncoded) // "special%20chars%20%26%20symbols%21"
val base64Encoded = encodeCookieValue(rawValue, CookieEncoding.BASE64_ENCODING)
println(base64Encoded) // "c3BlY2lhbCBjaGFycyAmIHN5bWJvbHMh"
val quotedValue = encodeCookieValue(rawValue, CookieEncoding.DQUOTES)
println(quotedValue) // "\"special chars & symbols!\""
// Decode values back
val decodedUri = decodeCookieValue(uriEncoded, CookieEncoding.URI_ENCODING)
val decodedBase64 = decodeCookieValue(base64Encoded, CookieEncoding.BASE64_ENCODING)
println(decodedUri == rawValue) // true
println(decodedBase64 == rawValue) // true
// Create cookies with different security levels
val insecureCookie = Cookie("debug", "enabled") // Basic cookie
val secureCookie = Cookie(
name = "auth",
value = "secure-token",
secure = true,
httpOnly = true,
maxAge = 3600
) // Secure authentication cookie
val strictCookie = Cookie(
name = "csrf",
value = "csrf-token-123",
secure = true,
httpOnly = true,
path = "/",
extensions = mapOf("SameSite" to "Strict")
) // CSRF protection cookie
// Handle cookie expiration
val expiredCookie = Cookie(
name = "old-session",
value = "",
maxAge = 0 // Expire immediately
)
// Render with custom parameters
val customRendered = renderSetCookieHeader(
name = "custom",
value = "data",
maxAge = 7200,
domain = "subdomain.example.com",
path = "/api/v1",
secure = true,
httpOnly = false,
extensions = mapOf("SameSite" to "Lax")
)
println(customRendered)
// "custom=data; Max-Age=7200; Domain=subdomain.example.com; Path=/api/v1; Secure; SameSite=Lax"
// Error handling for malformed cookies
try {
parseServerSetCookieHeader("malformed cookie header")
} catch (e: IllegalArgumentException) {
println("Failed to parse cookie: ${e.message}")
}/**
* GMT date representation for cookie expiration
* (This type is typically provided by the Ktor date utilities)
*/
// GMTDate is referenced but defined in the date utilities module