or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

client-configuration.mdcookie-management.mdengine-configuration.mdform-handling.mdhttp-caching.mdindex.mdplugin-system.mdrequest-building.mdresponse-handling.mdwebsocket-support.md

form-handling.mddocs/

0

# Form Handling

1

2

Support for URL-encoded forms and multipart form data with file uploads, providing type-safe form submission capabilities.

3

4

## Capabilities

5

6

### FormDataContent Class

7

8

URL-encoded form content for simple form submissions.

9

10

```kotlin { .api }

11

/**

12

* URL-encoded form content implementation

13

*/

14

class FormDataContent(val formData: Parameters) : OutgoingContent.ByteArrayContent() {

15

/** Form parameters */

16

val formData: Parameters

17

18

/** Content length in bytes */

19

override val contentLength: Long

20

21

/** Content type (application/x-www-form-urlencoded) */

22

override val contentType: ContentType

23

24

/**

25

* Get form data as byte array

26

*/

27

override fun bytes(): ByteArray

28

}

29

```

30

31

**Usage Examples:**

32

33

```kotlin

34

import io.ktor.client.request.forms.*

35

import io.ktor.http.*

36

37

// Create form data

38

val formData = FormDataContent(Parameters.build {

39

append("username", "john_doe")

40

append("password", "secret123")

41

append("remember", "true")

42

})

43

44

// Send form data

45

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

46

setBody(formData)

47

}

48

```

49

50

### MultiPartFormDataContent Class

51

52

Multipart form data content for complex forms with file uploads.

53

54

```kotlin { .api }

55

/**

56

* Multipart form data content implementation

57

*/

58

class MultiPartFormDataContent(

59

parts: List<PartData>,

60

boundary: String,

61

contentType: ContentType = ContentType.MultiPart.FormData.withParameter("boundary", boundary)

62

) : OutgoingContent.WriteChannelContent() {

63

/** Multipart boundary string */

64

val boundary: String

65

66

/** Content type (multipart/form-data) */

67

override val contentType: ContentType

68

69

/** Content length if determinable */

70

override val contentLength: Long?

71

72

/**

73

* Write multipart content to channel

74

*/

75

override suspend fun writeTo(channel: ByteWriteChannel)

76

}

77

```

78

79

### Form Submission Functions

80

81

Convenience functions for submitting forms with various content types.

82

83

```kotlin { .api }

84

/**

85

* Submit URL-encoded form

86

*/

87

suspend fun HttpClient.submitForm(

88

formParameters: Parameters,

89

encodeInQuery: Boolean = false,

90

block: HttpRequestBuilder.() -> Unit = {}

91

): HttpResponse

92

93

/**

94

* Submit URL-encoded form with URL

95

*/

96

suspend fun HttpClient.submitForm(

97

url: String,

98

formParameters: Parameters,

99

encodeInQuery: Boolean = false,

100

block: HttpRequestBuilder.() -> Unit = {}

101

): HttpResponse

102

103

/**

104

* Submit multipart form with binary data

105

*/

106

suspend fun HttpClient.submitFormWithBinaryData(

107

formData: List<PartData>,

108

block: HttpRequestBuilder.() -> Unit = {}

109

): HttpResponse

110

111

/**

112

* Submit multipart form with binary data and URL

113

*/

114

suspend fun HttpClient.submitFormWithBinaryData(

115

url: String,

116

formData: List<PartData>,

117

block: HttpRequestBuilder.() -> Unit = {}

118

): HttpResponse

119

```

120

121

**Usage Examples:**

122

123

```kotlin

124

// Simple form submission

125

val loginParams = Parameters.build {

126

append("username", "alice")

127

append("password", "secret")

128

}

129

130

val loginResponse = client.submitForm(

131

url = "https://api.example.com/login",

132

formParameters = loginParams

133

) {

134

headers["User-Agent"] = "MyApp/1.0"

135

}

136

137

// Form data in query string

138

val searchResponse = client.submitForm(

139

url = "https://api.example.com/search",

140

formParameters = Parameters.build {

141

append("q", "kotlin")

142

append("limit", "10")

143

},

144

encodeInQuery = true // Use GET with query parameters

145

)

146

147

// Multipart form with file upload

148

val uploadData = listOf(

149

PartData.FormItem("title", "My Document"),

150

PartData.FormItem("description", "Important document"),

151

PartData.FileItem(

152

provider = { ByteReadChannel(fileBytes) },

153

dispose = {},

154

partHeaders = headersOf(

155

HttpHeaders.ContentDisposition,

156

"form-data; name=\"file\"; filename=\"document.pdf\""

157

)

158

)

159

)

160

161

val uploadResponse = client.submitFormWithBinaryData(

162

url = "https://api.example.com/upload",

163

formData = uploadData

164

) {

165

headers["Authorization"] = "Bearer $token"

166

}

167

```

168

169

### Prepared Form Functions

170

171

Functions for creating reusable prepared form requests.

172

173

```kotlin { .api }

174

/**

175

* Prepare URL-encoded form submission

176

*/

177

suspend fun HttpClient.prepareForm(

178

formParameters: Parameters,

179

encodeInQuery: Boolean = false,

180

block: HttpRequestBuilder.() -> Unit = {}

181

): HttpStatement

182

183

/**

184

* Prepare URL-encoded form submission with URL

185

*/

186

suspend fun HttpClient.prepareForm(

187

url: String,

188

formParameters: Parameters,

189

encodeInQuery: Boolean = false,

190

block: HttpRequestBuilder.() -> Unit = {}

191

): HttpStatement

192

193

/**

194

* Prepare multipart form submission

195

*/

196

suspend fun HttpClient.prepareFormWithBinaryData(

197

formData: List<PartData>,

198

block: HttpRequestBuilder.() -> Unit = {}

199

): HttpStatement

200

201

/**

202

* Prepare multipart form submission with URL

203

*/

204

suspend fun HttpClient.prepareFormWithBinaryData(

205

url: String,

206

formData: List<PartData>,

207

block: HttpRequestBuilder.() -> Unit = {}

208

): HttpStatement

209

```

210

211

**Usage Examples:**

212

213

```kotlin

214

// Prepare reusable form

215

val loginForm = client.prepareForm(

216

url = "https://api.example.com/login",

217

formParameters = Parameters.build {

218

append("username", "placeholder")

219

append("password", "placeholder")

220

}

221

)

222

223

// Use prepared form multiple times

224

val response1 = loginForm.execute { response ->

225

// Custom response handling

226

response.bodyAsText()

227

}

228

229

val response2 = loginForm.execute()

230

```

231

232

### PartData Classes

233

234

Classes representing different types of form parts in multipart forms.

235

236

```kotlin { .api }

237

/**

238

* Base class for multipart form parts

239

*/

240

sealed class PartData {

241

abstract val headers: Headers

242

abstract val name: String?

243

244

/**

245

* Simple form field

246

*/

247

data class FormItem(

248

override val name: String,

249

val value: String,

250

override val headers: Headers = Headers.Empty

251

) : PartData()

252

253

/**

254

* Binary file part

255

*/

256

data class BinaryItem(

257

override val name: String?,

258

val contentType: ContentType?,

259

override val headers: Headers = Headers.Empty,

260

val provider: () -> ByteReadChannel

261

) : PartData()

262

263

/**

264

* File upload part

265

*/

266

data class FileItem(

267

override val name: String?,

268

val originalFileName: String?,

269

override val headers: Headers = Headers.Empty,

270

val provider: () -> ByteReadChannel,

271

val dispose: () -> Unit = {}

272

) : PartData()

273

274

/**

275

* Binary channel part

276

*/

277

data class BinaryChannelItem(

278

override val name: String?,

279

val contentType: ContentType?,

280

override val headers: Headers = Headers.Empty,

281

val provider: () -> ByteReadChannel

282

) : PartData()

283

}

284

```

285

286

**Usage Examples:**

287

288

```kotlin

289

import io.ktor.http.content.*

290

import io.ktor.utils.io.*

291

import java.io.File

292

293

// Create different types of form parts

294

val formParts = listOf(

295

// Simple text field

296

PartData.FormItem("username", "alice"),

297

298

// File upload from File object (JVM)

299

PartData.FileItem(

300

provider = { file.readChannel() },

301

dispose = {},

302

partHeaders = headersOf(

303

HttpHeaders.ContentDisposition,

304

"form-data; name=\"avatar\"; filename=\"avatar.jpg\""

305

)

306

),

307

308

// Binary data

309

PartData.BinaryItem(

310

name = "data",

311

contentType = ContentType.Application.OctetStream,

312

provider = { ByteReadChannel(binaryData) }

313

),

314

315

// Binary channel

316

PartData.BinaryChannelItem(

317

name = "stream",

318

contentType = ContentType.Text.Plain,

319

provider = { dataChannel }

320

)

321

)

322

323

// Submit multipart form

324

val response = client.submitFormWithBinaryData(

325

url = "https://api.example.com/upload",

326

formData = formParts

327

)

328

```

329

330

### Form Building DSL

331

332

DSL for building form data with type safety.

333

334

```kotlin { .api }

335

/**

336

* Build form parameters using DSL

337

*/

338

fun formParameters(block: ParametersBuilder.() -> Unit): Parameters =

339

ParametersBuilder().apply(block).build()

340

341

/**

342

* Build multipart form data using DSL

343

*/

344

fun multiPartFormData(block: MultiPartFormDataContent.Builder.() -> Unit): MultiPartFormDataContent

345

```

346

347

**Usage Examples:**

348

349

```kotlin

350

// Form parameters DSL

351

val params = formParameters {

352

append("name", "John Doe")

353

append("email", "john@example.com")

354

append("subscribe", "true")

355

appendAll("interests", listOf("kotlin", "web", "mobile"))

356

}

357

358

val response = client.submitForm(

359

url = "https://api.example.com/register",

360

formParameters = params

361

)

362

363

// Multipart form DSL

364

val multipart = multiPartFormData {

365

// Add text fields

366

append("title", "My Upload")

367

append("description", "File description")

368

369

// Add file

370

append("file", fileBytes, Headers.build {

371

append(HttpHeaders.ContentDisposition, "filename=document.pdf")

372

append(HttpHeaders.ContentType, "application/pdf")

373

})

374

}

375

376

val uploadResponse = client.post("https://api.example.com/upload") {

377

setBody(multipart)

378

}

379

```