or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

client-configuration.mdcookie-management.mdforms-and-uploads.mdhttp-caching.mdhttp-requests.mdindex.mdplugin-system.mdresponse-handling.mdserver-sent-events.mdwebsockets.md

response-handling.mddocs/

0

# Response Handling

1

2

Comprehensive HTTP response processing including body extraction, status handling, streaming support, and type-safe response parsing.

3

4

## Capabilities

5

6

### Response Body Extraction

7

8

Extract response bodies in various formats with type safety and charset handling.

9

10

```kotlin { .api }

11

/**

12

* Get response body as text with optional charset

13

* @param charset Character encoding (default: UTF-8)

14

* @returns Response body as String

15

*/

16

suspend fun HttpResponse.bodyAsText(charset: Charset = Charsets.UTF_8): String

17

18

/**

19

* Get response body as ByteReadChannel for streaming

20

* @returns ByteReadChannel for reading response data

21

*/

22

suspend fun HttpResponse.bodyAsChannel(): ByteReadChannel

23

24

/**

25

* Get response body as ByteArray

26

* @returns Complete response body as byte array

27

*/

28

suspend fun HttpResponse.readBytes(): ByteArray

29

30

/**

31

* Get typed response body using content negotiation

32

* @returns Deserialized response body of type T

33

*/

34

suspend inline fun <reified T> HttpResponse.body(): T

35

36

/**

37

* Get typed response body with explicit TypeInfo

38

* @param typeInfo Type information for deserialization

39

* @returns Deserialized response body

40

*/

41

suspend fun <T> HttpResponse.body(typeInfo: TypeInfo): T

42

```

43

44

**Usage Examples:**

45

46

```kotlin

47

val client = HttpClient()

48

49

// Get response as text

50

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

51

val jsonText = response.bodyAsText()

52

53

// Get response as bytes

54

val imageResponse = client.get("https://example.com/image.jpg")

55

val imageBytes = imageResponse.readBytes()

56

57

// Get typed response (requires content negotiation plugin)

58

val usersResponse = client.get("https://api.example.com/users")

59

val users: List<User> = usersResponse.body()

60

61

// Streaming response

62

val largeFileResponse = client.get("https://example.com/largefile.zip")

63

val channel = largeFileResponse.bodyAsChannel()

64

while (!channel.isClosedForRead) {

65

val chunk = channel.readBuffer()

66

// Process chunk

67

}

68

```

69

70

### HttpResponse Interface

71

72

Core response interface providing access to status, headers, and metadata.

73

74

```kotlin { .api }

75

/**

76

* HTTP response representation

77

*/

78

interface HttpResponse {

79

/** HTTP status code and message */

80

val status: HttpStatusCode

81

82

/** Response headers */

83

val headers: Headers

84

85

/** Associated HTTP call */

86

val call: HttpClientCall

87

88

/** HTTP protocol version */

89

val version: HttpProtocolVersion

90

91

/** Request timestamp */

92

val requestTime: GMTDate

93

94

/** Response timestamp */

95

val responseTime: GMTDate

96

97

/** Response content */

98

val content: ByteReadChannel

99

}

100

101

/**

102

* Default implementation of HttpResponse

103

*/

104

class DefaultHttpResponse(

105

override val call: HttpClientCall,

106

override val status: HttpStatusCode,

107

override val version: HttpProtocolVersion,

108

override val requestTime: GMTDate,

109

override val responseTime: GMTDate,

110

override val content: ByteReadChannel,

111

override val headers: Headers

112

) : HttpResponse

113

```

114

115

**Usage Examples:**

116

117

```kotlin

118

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

119

120

// Check status

121

when (response.status.value) {

122

in 200..299 -> println("Success: ${response.status}")

123

in 400..499 -> println("Client error: ${response.status}")

124

in 500..599 -> println("Server error: ${response.status}")

125

}

126

127

// Access headers

128

val contentType = response.headers["Content-Type"]

129

val contentLength = response.headers["Content-Length"]?.toLong()

130

131

// Check protocol version

132

if (response.version == HttpProtocolVersion.HTTP_2_0) {

133

println("Using HTTP/2")

134

}

135

136

// Check timing

137

val duration = response.responseTime - response.requestTime

138

println("Request took ${duration}ms")

139

```

140

141

### HttpStatement Class

142

143

Prepared HTTP statement for lazy execution and advanced response handling.

144

145

```kotlin { .api }

146

/**

147

* Prepared HTTP statement ready for execution

148

*/

149

class HttpStatement {

150

/** The prepared request builder */

151

val builder: HttpRequestBuilder

152

153

/** The client that will execute this statement */

154

val client: HttpClient

155

156

/**

157

* Execute the statement and return the response

158

* @returns HttpResponse

159

*/

160

suspend fun execute(): HttpResponse

161

162

/**

163

* Execute the statement with custom response handling

164

* @param block Response processing block

165

* @returns Result of the processing block

166

*/

167

suspend fun <T> execute(block: suspend (HttpResponse) -> T): T

168

}

169

```

170

171

**Usage Examples:**

172

173

```kotlin

174

// Prepare statement

175

val statement = client.prepareGet("https://api.example.com/users")

176

177

// Execute multiple times

178

val response1 = statement.execute()

179

val response2 = statement.execute()

180

181

// Execute with custom handling

182

val userCount = statement.execute { response ->

183

val users: List<User> = response.body()

184

users.size

185

}

186

187

// Execute with resource management

188

val result = statement.execute { response ->

189

response.bodyAsChannel().use { channel ->

190

// Process streaming data

191

var totalBytes = 0L

192

while (!channel.isClosedForRead) {

193

val buffer = channel.readBuffer()

194

totalBytes += buffer.remaining

195

}

196

totalBytes

197

}

198

}

199

```

200

201

### Response Pipeline Processing

202

203

Access to response processing pipeline for advanced scenarios.

204

205

```kotlin { .api }

206

/**

207

* Response processing pipeline

208

*/

209

class HttpResponsePipeline {

210

/** Receive phase for initial response processing */

211

val Receive: PipelinePhase

212

213

/** Parse phase for content transformation */

214

val Parse: PipelinePhase

215

216

/** Transform phase for final processing */

217

val Transform: PipelinePhase

218

219

/**

220

* Execute the pipeline with response data

221

* @param context Pipeline context

222

* @param subject Initial subject

223

* @returns Processed result

224

*/

225

suspend fun execute(context: HttpResponseContainer, subject: Any): Any

226

}

227

228

/**

229

* Response container for pipeline processing

230

*/

231

data class HttpResponseContainer(

232

val expectedType: TypeInfo,

233

val response: HttpResponse

234

)

235

```

236

237

### Content Type and Encoding

238

239

Functions for handling content types and character encodings.

240

241

```kotlin { .api }

242

/**

243

* Get content type from response headers

244

* @returns ContentType object or null

245

*/

246

fun HttpResponse.contentType(): ContentType?

247

248

/**

249

* Get charset from content type header

250

* @returns Charset object or default

251

*/

252

fun HttpResponse.charset(): Charset

253

254

/**

255

* Check if response has specific content type

256

* @param contentType Expected content type

257

* @returns True if content type matches

258

*/

259

fun HttpResponse.contentType(contentType: ContentType): Boolean

260

```

261

262

**Usage Examples:**

263

264

```kotlin

265

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

266

267

// Check content type

268

val contentType = response.contentType()

269

when {

270

contentType?.match(ContentType.Application.Json) == true -> {

271

val jsonData = response.bodyAsText()

272

// Process JSON

273

}

274

contentType?.match(ContentType.Text.Html) == true -> {

275

val htmlContent = response.bodyAsText()

276

// Process HTML

277

}

278

contentType?.match(ContentType.Application.OctetStream) == true -> {

279

val binaryData = response.readBytes()

280

// Process binary data

281

}

282

}

283

284

// Handle charset

285

val charset = response.charset()

286

val text = response.bodyAsText(charset)

287

```

288

289

### Response Validation

290

291

Response validation and error handling utilities.

292

293

```kotlin { .api }

294

/**

295

* Check if response is successful (2xx status code)

296

* @returns True if status code is 2xx

297

*/

298

fun HttpResponse.isSuccessful(): Boolean

299

300

/**

301

* Throw exception if response is not successful

302

* @throws ResponseException for non-2xx status codes

303

*/

304

suspend fun HttpResponse.ensureSuccess()

305

306

/**

307

* Get response body as text only if successful, null otherwise

308

* @returns Response body text or null

309

*/

310

suspend fun HttpResponse.bodyAsTextOrNull(): String?

311

```

312

313

**Usage Examples:**

314

315

```kotlin

316

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

317

318

// Check success

319

if (response.isSuccessful()) {

320

val data = response.bodyAsText()

321

// Process successful response

322

} else {

323

println("Request failed with status: ${response.status}")

324

}

325

326

// Ensure success (throws exception if not successful)

327

try {

328

response.ensureSuccess()

329

val data = response.bodyAsText()

330

} catch (e: ResponseException) {

331

println("Request failed: ${e.message}")

332

}

333

334

// Safe body extraction

335

val safeData = response.bodyAsTextOrNull()

336

if (safeData != null) {

337

// Process data

338

}

339

```

340

341

## Types

342

343

### Response Types

344

345

```kotlin { .api }

346

/**

347

* HTTP status code representation

348

*/

349

data class HttpStatusCode(

350

val value: Int,

351

val description: String

352

) {

353

companion object {

354

// 2xx Success

355

val OK: HttpStatusCode

356

val Created: HttpStatusCode

357

val Accepted: HttpStatusCode

358

val NoContent: HttpStatusCode

359

360

// 3xx Redirection

361

val MovedPermanently: HttpStatusCode

362

val Found: HttpStatusCode

363

val NotModified: HttpStatusCode

364

365

// 4xx Client Error

366

val BadRequest: HttpStatusCode

367

val Unauthorized: HttpStatusCode

368

val Forbidden: HttpStatusCode

369

val NotFound: HttpStatusCode

370

371

// 5xx Server Error

372

val InternalServerError: HttpStatusCode

373

val BadGateway: HttpStatusCode

374

val ServiceUnavailable: HttpStatusCode

375

}

376

}

377

378

/**

379

* HTTP protocol version

380

*/

381

enum class HttpProtocolVersion(val name: String, val major: Int, val minor: Int) {

382

HTTP_1_0("HTTP/1.0", 1, 0),

383

HTTP_1_1("HTTP/1.1", 1, 1),

384

HTTP_2_0("HTTP/2.0", 2, 0),

385

SPDY_3("SPDY/3.1", 3, 1),

386

QUIC("QUIC", 1, 0)

387

}

388

389

/**

390

* GMT date representation for timestamps

391

*/

392

data class GMTDate(

393

val timestamp: Long,

394

val seconds: Int,

395

val minutes: Int,

396

val hours: Int,

397

val dayOfMonth: Int,

398

val month: Month,

399

val year: Int,

400

val dayOfWeek: DayOfWeek,

401

val dayOfYear: Int

402

) {

403

companion object {

404

fun start(): GMTDate

405

fun parse(date: String): GMTDate

406

}

407

}

408

```

409

410

### Content Types

411

412

```kotlin { .api }

413

/**

414

* Content type representation

415

*/

416

data class ContentType(

417

val contentType: String,

418

val contentSubtype: String,

419

val parameters: List<HeaderValueParam> = emptyList()

420

) {

421

companion object {

422

object Application {

423

val Json: ContentType

424

val Xml: ContentType

425

val OctetStream: ContentType

426

val FormUrlEncoded: ContentType

427

val Pdf: ContentType

428

}

429

430

object Text {

431

val Plain: ContentType

432

val Html: ContentType

433

val CSS: ContentType

434

val JavaScript: ContentType

435

}

436

437

object Image {

438

val JPEG: ContentType

439

val PNG: ContentType

440

val GIF: ContentType

441

val SVG: ContentType

442

}

443

444

object Audio {

445

val MPEG: ContentType

446

val OGG: ContentType

447

}

448

449

object Video {

450

val MPEG: ContentType

451

val MP4: ContentType

452

}

453

}

454

455

fun match(pattern: ContentType): Boolean

456

fun match(contentType: String): Boolean

457

fun withParameter(name: String, value: String): ContentType

458

}

459

460

/**

461

* Character set enumeration

462

*/

463

object Charsets {

464

val UTF_8: Charset

465

val UTF_16: Charset

466

val ISO_8859_1: Charset

467

val US_ASCII: Charset

468

}

469

```

470

471

### Exception Types

472

473

```kotlin { .api }

474

/**

475

* Base exception for HTTP response errors

476

*/

477

open class ResponseException(

478

response: HttpResponse,

479

cachedResponseText: String

480

) : Exception(cachedResponseText) {

481

val response: HttpResponse

482

}

483

484

/**

485

* Exception for client errors (4xx status codes)

486

*/

487

class ClientRequestException(

488

response: HttpResponse,

489

cachedResponseText: String

490

) : ResponseException(response, cachedResponseText)

491

492

/**

493

* Exception for server errors (5xx status codes)

494

*/

495

class ServerResponseException(

496

response: HttpResponse,

497

cachedResponseText: String

498

) : ResponseException(response, cachedResponseText)

499

500

/**

501

* Exception for redirect errors

502

*/

503

class RedirectResponseException(

504

response: HttpResponse,

505

cachedResponseText: String

506

) : ResponseException(response, cachedResponseText)

507

```