Status Pages

The feature allows Ktor applications to respond appropriately to any failure state. This feature is installed using the standard application configuration:

There are three main configuration options provided to StatusPages:

  1. exceptions - Configures response based on mapped exception classes

  2. status - Configures response to status code value

  3. statusFile - Configures standard file response from classpath

  1. install(StatusPages) {
  2. exception<Throwable> { cause ->
  3. call.respond(HttpStatusCode.InternalServerError)
  4. }
  5. }

More specific responses can allow for more complex user interactions.

  1. exception<AuthenticationException> { cause ->
  2. call.respond(HttpStatusCode.Unauthorized)
  3. }
  4. exception<AuthorizationException> { cause ->
  5. call.respond(HttpStatusCode.Forbidden)
  6. }

These customizations can work well when paired with custom status code responses, e.g. providing a login page when a user has not authenticated.

Each call is only caught by a single exception handler, the closest exception on the object graph from the thrown exception. When multiple exceptions within the same object hierarchy are handled, only a single one will be executed.

Single handling also implies that recursive call stacks are avoided. For example, this configuration would result in the created IllegalStateException propagating to the client.

  1. install(StatusPages) {
  2. exception<IllegalStateException> { cause ->
  3. throw IllegalStateException("")
  4. }
  5. }

It is important to note that adding the handlers above will “swallow” the exceptions generated by your routes. In order to log the actual errors generated, you can either log the cause manually, or simply re-throw it as shown below:

  1. install(StatusPages) {
  2. exception<Throwable> { cause ->
  3. throw cause
  4. }
  5. }

The configuration provides a custom actions for status responses from within the application. Below is a basic configuration that provides information about the HTTP status code within the response text.

  1. install(StatusPages) {
  2. statusFile(HttpStatusCode.NotFound, HttpStatusCode.Unauthorized, filePattern = "error#.html")
  3. }

This will resolve two resources from the classpath.

  1. On a 404, it will return error404.html.

  2. On a 401, it will return error401.html.

The statusFile configuration replaces any # character with the value of the status code within the list of configured statuses.

When doing redirections by executing call.respondRedirect("/moved/here", permanent = true), the rest of the callee function is executed. So when doing redirections inside guard clauses, you have to return the function.

  1. routing {
  2. get("/") {
  3. if (condition) {
  4. return@get call.respondRedirect("/invalid", permanent = false)
  5. }
  6. call.respondText("Normal response")
  7. }

Other frameworks, use exceptions on redirect, so the normal flow is broken and you can execute redirections in guard clauses or subfunctions without having to worry about returning in all the subfunction chain. You can use the StatusPages feature to simulate this: