or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

builtin-plugins.mdcaching.mdcookies.mdengine-configuration.mdforms.mdhttp-client.mdindex.mdplugin-system.mdrequest-building.mdresponse-handling.mdresponse-observation.mdutilities.mdwebsockets.md

cookies.mddocs/

0

# Cookies Support

1

2

The Ktor HTTP Client Core provides comprehensive cookie management functionality through the `HttpCookies` plugin. This allows automatic handling of HTTP cookies across requests with configurable storage backends and support for custom cookie storage implementations.

3

4

## Core Cookie API

5

6

### HttpCookies Plugin

7

8

The main plugin for cookie management that automatically handles cookie storage and retrieval.

9

10

```kotlin { .api }

11

object HttpCookies : HttpClientPlugin<HttpCookies.Config, HttpCookies> {

12

class Config {

13

var storage: CookiesStorage = AcceptAllCookiesStorage()

14

15

fun default()

16

fun storage(storage: CookiesStorage)

17

}

18

}

19

```

20

21

### CookiesStorage Interface

22

23

Base interface for implementing custom cookie storage backends.

24

25

```kotlin { .api }

26

interface CookiesStorage {

27

suspend fun get(requestUrl: Url): List<Cookie>

28

suspend fun addCookie(requestUrl: Url, cookie: Cookie)

29

fun close()

30

}

31

```

32

33

## Built-in Storage Implementations

34

35

### AcceptAllCookiesStorage

36

37

Default storage implementation that accepts and stores all cookies with in-memory storage.

38

39

```kotlin { .api }

40

class AcceptAllCookiesStorage : CookiesStorage {

41

override suspend fun get(requestUrl: Url): List<Cookie>

42

override suspend fun addCookie(requestUrl: Url, cookie: Cookie)

43

override fun close()

44

}

45

```

46

47

### ConstantCookiesStorage

48

49

Read-only storage implementation that provides a fixed set of cookies for all requests.

50

51

```kotlin { .api }

52

class ConstantCookiesStorage(

53

private val cookies: List<Cookie>

54

) : CookiesStorage {

55

constructor(vararg cookies: Cookie)

56

57

override suspend fun get(requestUrl: Url): List<Cookie>

58

override suspend fun addCookie(requestUrl: Url, cookie: Cookie)

59

override fun close()

60

}

61

```

62

63

## Cookie Data Types

64

65

### Cookie Class

66

67

Represents an HTTP cookie with all its attributes.

68

69

```kotlin { .api }

70

data class Cookie(

71

val name: String,

72

val value: String,

73

val encoding: CookieEncoding = CookieEncoding.URI_ENCODING,

74

val maxAge: Int = 0,

75

val expires: GMTDate? = null,

76

val domain: String? = null,

77

val path: String? = null,

78

val secure: Boolean = false,

79

val httpOnly: Boolean = false,

80

val extensions: Map<String, String?> = emptyMap()

81

) {

82

fun copy(

83

name: String = this.name,

84

value: String = this.value,

85

encoding: CookieEncoding = this.encoding,

86

maxAge: Int = this.maxAge,

87

expires: GMTDate? = this.expires,

88

domain: String? = this.domain,

89

path: String? = this.path,

90

secure: Boolean = this.secure,

91

httpOnly: Boolean = this.httpOnly,

92

extensions: Map<String, String?> = this.extensions

93

): Cookie

94

}

95

96

enum class CookieEncoding {

97

URI_ENCODING,

98

DQUOTES,

99

RAW

100

}

101

```

102

103

## Basic Usage

104

105

### Simple Cookie Handling

106

107

```kotlin

108

val client = HttpClient {

109

install(HttpCookies)

110

}

111

112

// First request - server sets cookies

113

val loginResponse = client.post("https://example.com/login") {

114

setBody("username=john&password=secret")

115

contentType(ContentType.Application.FormUrlEncoded)

116

}

117

118

// Subsequent requests automatically include cookies

119

val profileResponse = client.get("https://example.com/profile")

120

// Cookies from login are automatically sent

121

122

client.close()

123

```

124

125

### Custom Storage Configuration

126

127

```kotlin

128

val client = HttpClient {

129

install(HttpCookies) {

130

storage = AcceptAllCookiesStorage()

131

}

132

}

133

134

// Or with constant cookies

135

val client2 = HttpClient {

136

install(HttpCookies) {

137

storage = ConstantCookiesStorage(

138

Cookie("session_id", "abc123"),

139

Cookie("user_pref", "dark_mode")

140

)

141

}

142

}

143

```

144

145

### Manual Cookie Management

146

147

```kotlin

148

val cookieStorage = AcceptAllCookiesStorage()

149

150

val client = HttpClient {

151

install(HttpCookies) {

152

storage = cookieStorage

153

}

154

}

155

156

// Add cookies manually

157

cookieStorage.addCookie(

158

Url("https://example.com"),

159

Cookie(

160

name = "auth_token",

161

value = "bearer_xyz789",

162

domain = "example.com",

163

path = "/api",

164

secure = true,

165

httpOnly = true,

166

maxAge = 3600 // 1 hour

167

)

168

)

169

170

// Cookies will be included in matching requests

171

val response = client.get("https://example.com/api/data")

172

```

173

174

## Advanced Cookie Features

175

176

### Cookie Attributes

177

178

```kotlin

179

val secureCookie = Cookie(

180

name = "secure_session",

181

value = "encrypted_data",

182

domain = ".example.com", // Available to all subdomains

183

path = "/secure", // Only for /secure paths

184

secure = true, // HTTPS only

185

httpOnly = true, // No JavaScript access

186

maxAge = 7200, // 2 hours lifetime

187

extensions = mapOf(

188

"SameSite" to "Strict" // CSRF protection

189

)

190

)

191

```

192

193

### Domain and Path Matching

194

195

Cookies are automatically filtered based on domain and path matching rules:

196

197

```kotlin

198

val client = HttpClient {

199

install(HttpCookies) {

200

storage = AcceptAllCookiesStorage()

201

}

202

}

203

204

// Set cookies with different scopes

205

client.get("https://api.example.com/login") // May set cookies for .example.com

206

client.get("https://app.example.com/dashboard") // Gets cookies for .example.com

207

client.get("https://other.com/data") // No cookies from example.com

208

```

209

210

### Cookie Encoding

211

212

```kotlin

213

val encodedCookie = Cookie(

214

name = "special_chars",

215

value = "hello world & more!",

216

encoding = CookieEncoding.URI_ENCODING // URL-encodes special characters

217

)

218

219

val quotedCookie = Cookie(

220

name = "quoted_value",

221

value = "contains spaces",

222

encoding = CookieEncoding.DQUOTES // Wraps in double quotes

223

)

224

225

val rawCookie = Cookie(

226

name = "raw_value",

227

value = "no-encoding-needed",

228

encoding = CookieEncoding.RAW // No encoding applied

229

)

230

```

231

232

## Custom Storage Implementation

233

234

### Thread-Safe Cookie Storage

235

236

```kotlin

237

class ThreadSafeCookieStorage : CookiesStorage {

238

private val cookies = mutableMapOf<String, MutableList<Cookie>>()

239

private val mutex = Mutex()

240

241

override suspend fun get(requestUrl: Url): List<Cookie> = mutex.withLock {

242

val host = requestUrl.host

243

return cookies[host]?.filter { cookie ->

244

// Apply domain and path matching logic

245

matchesDomain(cookie.domain, host) &&

246

matchesPath(cookie.path, requestUrl.encodedPath)

247

} ?: emptyList()

248

}

249

250

override suspend fun addCookie(requestUrl: Url, cookie: Cookie) = mutex.withLock {

251

val host = requestUrl.host

252

cookies.getOrPut(host) { mutableListOf() }.add(cookie)

253

}

254

255

override fun close() {

256

// Cleanup resources

257

}

258

259

private fun matchesDomain(cookieDomain: String?, requestHost: String): Boolean {

260

// Implement domain matching rules

261

return cookieDomain == null || requestHost.endsWith(cookieDomain)

262

}

263

264

private fun matchesPath(cookiePath: String?, requestPath: String): Boolean {

265

// Implement path matching rules

266

return cookiePath == null || requestPath.startsWith(cookiePath)

267

}

268

}

269

```

270

271

### Persistent Cookie Storage

272

273

```kotlin

274

class FileCookieStorage(private val file: File) : CookiesStorage {

275

private val cookies = mutableMapOf<String, MutableList<Cookie>>()

276

277

init {

278

loadCookies()

279

}

280

281

override suspend fun get(requestUrl: Url): List<Cookie> {

282

return cookies[requestUrl.host] ?: emptyList()

283

}

284

285

override suspend fun addCookie(requestUrl: Url, cookie: Cookie) {

286

cookies.getOrPut(requestUrl.host) { mutableListOf() }.add(cookie)

287

saveCookies()

288

}

289

290

override fun close() {

291

saveCookies()

292

}

293

294

private fun loadCookies() {

295

if (file.exists()) {

296

// Load cookies from file (implementation dependent)

297

}

298

}

299

300

private fun saveCookies() {

301

// Save cookies to file (implementation dependent)

302

}

303

}

304

```

305

306

## Cookie Security

307

308

### Secure Cookie Practices

309

310

```kotlin

311

val client = HttpClient {

312

install(HttpCookies) {

313

storage = AcceptAllCookiesStorage()

314

}

315

}

316

317

// Always use secure cookies for sensitive data

318

val secureCookie = Cookie(

319

name = "auth_session",

320

value = "encrypted_token",

321

secure = true, // Only send over HTTPS

322

httpOnly = true, // Prevent XSS attacks

323

extensions = mapOf(

324

"SameSite" to "Strict" // Prevent CSRF attacks

325

)

326

)

327

```

328

329

### Cookie Filtering

330

331

```kotlin

332

class FilteringCookieStorage(

333

private val delegate: CookiesStorage,

334

private val allowedDomains: Set<String>

335

) : CookiesStorage {

336

337

override suspend fun get(requestUrl: Url): List<Cookie> {

338

return if (requestUrl.host in allowedDomains) {

339

delegate.get(requestUrl)

340

} else {

341

emptyList()

342

}

343

}

344

345

override suspend fun addCookie(requestUrl: Url, cookie: Cookie) {

346

if (requestUrl.host in allowedDomains) {

347

delegate.addCookie(requestUrl, cookie)

348

}

349

}

350

351

override fun close() = delegate.close()

352

}

353

354

val client = HttpClient {

355

install(HttpCookies) {

356

storage = FilteringCookieStorage(

357

AcceptAllCookiesStorage(),

358

setOf("api.example.com", "secure.example.com")

359

)

360

}

361

}

362

```

363

364

## Cookie Inspection and Debugging

365

366

### Accessing Cookie Storage

367

368

```kotlin

369

val cookieStorage = AcceptAllCookiesStorage()

370

371

val client = HttpClient {

372

install(HttpCookies) {

373

storage = cookieStorage

374

}

375

}

376

377

// Make requests that set cookies

378

client.get("https://example.com/login")

379

380

// Inspect stored cookies

381

val storedCookies = cookieStorage.get(Url("https://example.com"))

382

println("Stored cookies: ${storedCookies.joinToString { "${it.name}=${it.value}" }}")

383

```

384

385

### Request Cookie Inspection

386

387

```kotlin

388

val client = HttpClient {

389

install(HttpCookies)

390

391

install(HttpSend) {

392

intercept { request ->

393

// Log cookies being sent

394

val cookieHeader = request.headers["Cookie"]

395

println("Sending cookies: $cookieHeader")

396

397

execute(request)

398

}

399

}

400

}

401

```

402

403

## Best Practices

404

405

1. **Use secure cookies**: Always set `secure` and `httpOnly` flags for sensitive cookies

406

2. **Implement proper storage**: Use persistent storage for long-lived applications

407

3. **Handle cookie expiration**: Check and clean up expired cookies regularly

408

4. **Domain validation**: Validate cookie domains to prevent security issues

409

5. **Thread safety**: Ensure custom storage implementations are thread-safe

410

6. **Memory management**: Be mindful of memory usage in long-running applications with many cookies

411

7. **CSRF protection**: Use SameSite attribute for additional security

412

8. **Cookie size limits**: Be aware of cookie size limitations (typically 4KB per cookie)