or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

application.mdconfig.mdengine.mdindex.mdplugins.mdrequest.mdresponse.mdrouting.md

routing.mddocs/

0

# Routing and HTTP Method Handling

1

2

URL routing system with DSL for defining routes, handling different HTTP methods, extracting path parameters, and organizing complex routing hierarchies with middleware support.

3

4

## Capabilities

5

6

### Route Definition

7

8

Core routing classes for building routing trees and handling HTTP requests with path matching and parameter extraction.

9

10

```kotlin { .api }

11

/**

12

* Represents a route in the routing tree

13

*/

14

class Route(

15

val parent: Route?,

16

val selector: RouteSelector,

17

val developmentMode: Boolean = false,

18

val environment: ApplicationEnvironment

19

) : ApplicationCallPipeline() {

20

/** Child routes */

21

val children: List<Route>

22

/** Route handlers */

23

val handlers: List<PipelineInterceptor<Unit, ApplicationCall>>

24

25

/** Create child route with selector */

26

fun createChild(selector: RouteSelector): Route

27

/** Install handler for this route */

28

fun handle(body: PipelineInterceptor<Unit, ApplicationCall>)

29

}

30

31

/**

32

* Root routing node

33

*/

34

class Routing(

35

private val application: Application

36

) : Route(parent = null, selector = RootRouteSelector, environment = application.environment)

37

38

/**

39

* DSL builder for constructing routing trees

40

*/

41

class RoutingBuilder : Route

42

```

43

44

### HTTP Method Handlers

45

46

DSL functions for handling different HTTP methods with path patterns and request processing.

47

48

```kotlin { .api }

49

/**

50

* Handle GET requests

51

* @param path - URL path pattern (supports parameters like {id})

52

* @param body - Request handler function

53

*/

54

fun Route.get(path: String, body: RoutingHandler): Route

55

fun Route.get(body: RoutingHandler): Route

56

57

/**

58

* Handle POST requests

59

* @param path - URL path pattern

60

* @param body - Request handler function

61

*/

62

fun Route.post(path: String, body: RoutingHandler): Route

63

fun Route.post(body: RoutingHandler): Route

64

65

/**

66

* Handle PUT requests

67

* @param path - URL path pattern

68

* @param body - Request handler function

69

*/

70

fun Route.put(path: String, body: RoutingHandler): Route

71

fun Route.put(body: RoutingHandler): Route

72

73

/**

74

* Handle DELETE requests

75

* @param path - URL path pattern

76

* @param body - Request handler function

77

*/

78

fun Route.delete(path: String, body: RoutingHandler): Route

79

fun Route.delete(body: RoutingHandler): Route

80

81

/**

82

* Handle PATCH requests

83

* @param path - URL path pattern

84

* @param body - Request handler function

85

*/

86

fun Route.patch(path: String, body: RoutingHandler): Route

87

fun Route.patch(body: RoutingHandler): Route

88

89

/**

90

* Handle HEAD requests

91

* @param path - URL path pattern

92

* @param body - Request handler function

93

*/

94

fun Route.head(path: String, body: RoutingHandler): Route

95

fun Route.head(body: RoutingHandler): Route

96

97

/**

98

* Handle OPTIONS requests

99

* @param path - URL path pattern

100

* @param body - Request handler function

101

*/

102

fun Route.options(path: String, body: RoutingHandler): Route

103

fun Route.options(body: RoutingHandler): Route

104

105

/**

106

* Handle requests for specific HTTP method

107

* @param method - HTTP method to handle

108

* @param path - URL path pattern

109

* @param body - Request handler function

110

*/

111

fun Route.method(method: HttpMethod, path: String, body: RoutingHandler): Route

112

fun Route.method(method: HttpMethod, body: RoutingHandler): Route

113

114

/**

115

* Type alias for routing handler functions

116

*/

117

typealias RoutingHandler = suspend RoutingContext.() -> Unit

118

119

/**

120

* Context for routing handlers

121

*/

122

class RoutingContext(

123

val call: RoutingCall

124

)

125

```

126

127

### Route Building and Nesting

128

129

Functions for creating nested routes and organizing routing hierarchies with shared middleware and path prefixes.

130

131

```kotlin { .api }

132

/**

133

* Create nested routes with path prefix

134

* @param path - Path prefix for nested routes

135

* @param build - Function to configure nested routes

136

*/

137

fun Route.route(path: String, build: Route.() -> Unit): Route

138

139

/**

140

* Install and configure routing for application

141

* @param configuration - Function to configure routing tree

142

*/

143

fun Application.routing(configuration: Routing.() -> Unit): Routing

144

145

/**

146

* Create route group without path prefix

147

* @param build - Function to configure route group

148

*/

149

fun Route.route(build: Route.() -> Unit): Route

150

```

151

152

### Route Selectors

153

154

Classes for matching routes based on different criteria including HTTP methods, path segments, and parameters.

155

156

```kotlin { .api }

157

/**

158

* Base class for route selection criteria

159

*/

160

abstract class RouteSelector {

161

/** Evaluate selector against current request */

162

abstract fun evaluate(context: RoutingResolveContext, segmentIndex: Int): RouteSelectorEvaluation

163

/** Build string representation */

164

abstract fun toString(): String

165

}

166

167

/**

168

* Selector for HTTP methods

169

*/

170

data class HttpMethodRouteSelector(val method: HttpMethod) : RouteSelector

171

172

/**

173

* Selector for exact path segments

174

*/

175

data class PathSegmentRouteSelector(val value: String, val optional: Boolean = false) : RouteSelector

176

177

/**

178

* Selector for path parameters (e.g., {id})

179

*/

180

data class ParameterRouteSelector(val name: String, val optional: Boolean = false) : RouteSelector

181

182

/**

183

* Selector for wildcard path segments

184

*/

185

data class WildcardRouteSelector(val name: String) : RouteSelector

186

187

/**

188

* Selector for trailing path segments

189

*/

190

object TailcardRouteSelector : RouteSelector

191

192

/**

193

* Root route selector

194

*/

195

object RootRouteSelector : RouteSelector

196

```

197

198

### Route Resolution

199

200

System for resolving incoming requests to appropriate route handlers with parameter extraction.

201

202

```kotlin { .api }

203

/**

204

* Context for route resolution

205

*/

206

class RoutingResolveContext(

207

val routing: Route,

208

val call: ApplicationCall,

209

val parameters: MutableMap<String, String> = mutableMapOf()

210

) {

211

/** Segments from request path */

212

val segments: List<String>

213

/** Current segment index during resolution */

214

var segmentIndex: Int

215

}

216

217

/**

218

* Result of route resolution

219

*/

220

sealed class RoutingResolveResult {

221

/** Successful route resolution */

222

class Success(val route: Route, val parameters: Map<String, String>) : RoutingResolveResult()

223

/** Route not found */

224

object Failure : RoutingResolveResult()

225

}

226

227

/**

228

* Evaluation result for route selector

229

*/

230

sealed class RouteSelectorEvaluation {

231

/** Selector matches */

232

object Success : RouteSelectorEvaluation()

233

/** Selector doesn't match */

234

object Failure : RouteSelectorEvaluation()

235

/** Selector matches with consumed segments */

236

class SuccessWithConsume(val segmentCount: Int) : RouteSelectorEvaluation()

237

}

238

```

239

240

### Route Middleware

241

242

Support for middleware that applies to specific routes or route groups with proper scoping.

243

244

```kotlin { .api }

245

/**

246

* Install interceptor for route and all child routes

247

* @param phase - Pipeline phase to install interceptor

248

* @param block - Interceptor function

249

*/

250

fun Route.intercept(phase: PipelinePhase, block: PipelineInterceptor<Unit, ApplicationCall>)

251

252

/**

253

* Install route-scoped plugin

254

* @param plugin - Plugin to install

255

* @param configuration - Plugin configuration

256

*/

257

fun <TConfiguration : Any> Route.install(

258

plugin: RouteScopedPlugin<TConfiguration, *>,

259

configuration: TConfiguration.() -> Unit = {}

260

)

261

```

262

263

### Parameter Extraction

264

265

Utilities for extracting and converting path parameters from matched routes.

266

267

```kotlin { .api }

268

/**

269

* Parameter collection for route parameters

270

*/

271

interface Parameters {

272

/** Get parameter value by name */

273

operator fun get(name: String): String?

274

/** Get all values for parameter name */

275

fun getAll(name: String): List<String>?

276

/** Get all parameter names */

277

fun names(): Set<String>

278

/** Check if parameter exists */

279

fun contains(name: String): Boolean

280

/** Check if parameter has specific value */

281

fun contains(name: String, value: String): Boolean

282

}

283

284

/** Access route parameters from application call */

285

val ApplicationCall.parameters: Parameters

286

287

/** Utility functions for parameter conversion */

288

fun Parameters.getOrFail(name: String): String =

289

get(name) ?: throw ParameterConversionException(name, "String", "Parameter $name not found")

290

291

fun Parameters.getInt(name: String): Int? = get(name)?.toIntOrNull()

292

fun Parameters.getIntOrFail(name: String): Int =

293

getInt(name) ?: throw ParameterConversionException(name, "Int", "Cannot convert to Int")

294

295

fun Parameters.getLong(name: String): Long? = get(name)?.toLongOrNull()

296

fun Parameters.getLongOrFail(name: String): Long =

297

getLong(name) ?: throw ParameterConversionException(name, "Long", "Cannot convert to Long")

298

299

fun Parameters.getBoolean(name: String): Boolean? = get(name)?.toBooleanStrictOrNull()

300

fun Parameters.getBooleanOrFail(name: String): Boolean =

301

getBoolean(name) ?: throw ParameterConversionException(name, "Boolean", "Cannot convert to Boolean")

302

```

303

304

**Usage Examples:**

305

306

```kotlin

307

import io.ktor.server.application.*

308

import io.ktor.server.response.*

309

import io.ktor.server.routing.*

310

import io.ktor.server.request.*

311

312

// Basic routing with HTTP methods

313

fun Application.basicRouting() {

314

routing {

315

get("/") {

316

call.respondText("Welcome!")

317

}

318

319

post("/users") {

320

val user = call.receive<User>()

321

// Create user

322

call.respond(HttpStatusCode.Created)

323

}

324

325

get("/health") {

326

call.respondText("OK")

327

}

328

}

329

}

330

331

// Path parameters and nested routes

332

fun Application.parameterRouting() {

333

routing {

334

route("/api/v1") {

335

route("/users") {

336

get {

337

// GET /api/v1/users - list all users

338

call.respondText("All users")

339

}

340

341

get("/{id}") {

342

val userId = call.parameters["id"]?.toIntOrNull()

343

?: throw BadRequestException("Invalid user ID")

344

// GET /api/v1/users/123

345

call.respondText("User $userId")

346

}

347

348

put("/{id}") {

349

val userId = call.parameters.getIntOrFail("id")

350

val user = call.receive<User>()

351

// PUT /api/v1/users/123 - update user

352

call.respond(user)

353

}

354

355

delete("/{id}") {

356

val userId = call.parameters.getIntOrFail("id")

357

// DELETE /api/v1/users/123

358

call.respond(HttpStatusCode.NoContent)

359

}

360

361

// Nested resource routes

362

route("/{userId}/posts") {

363

get {

364

val userId = call.parameters.getIntOrFail("userId")

365

// GET /api/v1/users/123/posts

366

call.respondText("Posts for user $userId")

367

}

368

369

post {

370

val userId = call.parameters.getIntOrFail("userId")

371

val post = call.receive<Post>()

372

// POST /api/v1/users/123/posts

373

call.respond(HttpStatusCode.Created, post)

374

}

375

}

376

}

377

}

378

}

379

}

380

381

// Wildcard and optional parameters

382

fun Application.wildcardRouting() {

383

routing {

384

// Wildcard parameter captures single segment

385

get("/files/{filename}") {

386

val filename = call.parameters["filename"]!!

387

call.respondText("Requested file: $filename")

388

}

389

390

// Tailcard captures remaining path segments

391

get("/static/{...}") {

392

val path = call.request.uri.removePrefix("/static/")

393

// Serve static files

394

call.respondText("Static path: $path")

395

}

396

397

// Optional parameters with defaults

398

get("/search") {

399

val query = call.request.queryParameters["q"] ?: ""

400

val page = call.request.queryParameters.getInt("page") ?: 1

401

val limit = call.request.queryParameters.getInt("limit") ?: 10

402

403

call.respondText("Search: $query, Page: $page, Limit: $limit")

404

}

405

}

406

}

407

408

// Route middleware and interceptors

409

fun Application.middlewareRouting() {

410

routing {

411

// Global interceptor for all routes

412

intercept(ApplicationCallPipeline.Setup) {

413

call.response.headers.append("X-Server", "Ktor")

414

}

415

416

route("/admin") {

417

// Authentication middleware for admin routes

418

intercept(ApplicationCallPipeline.Plugins) {

419

val token = call.request.headers["Authorization"]

420

if (token?.startsWith("Bearer ") != true) {

421

call.respond(HttpStatusCode.Unauthorized)

422

return@intercept finish()

423

}

424

// Validate token

425

}

426

427

get("/dashboard") {

428

call.respondText("Admin Dashboard")

429

}

430

431

get("/users") {

432

call.respondText("Admin Users")

433

}

434

}

435

436

route("/api") {

437

// CORS middleware for API routes

438

intercept(ApplicationCallPipeline.Setup) {

439

call.response.headers.append("Access-Control-Allow-Origin", "*")

440

}

441

442

get("/data") {

443

call.respond(mapOf("message" to "API data"))

444

}

445

}

446

}

447

}

448

449

data class User(val id: Int, val name: String, val email: String)

450

data class Post(val id: Int, val title: String, val content: String)

451

```