All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.papsign.ktor.openapigen.interop.StatusPages.kt Maven / Gradle / Ivy

package com.papsign.ktor.openapigen.interop

import com.papsign.ktor.openapigen.APIException.Companion.apiException
import com.papsign.ktor.openapigen.OpenAPIGen
import com.papsign.ktor.openapigen.modules.registerModule
import com.papsign.ktor.openapigen.route.ThrowsInfo
import io.ktor.http.HttpStatusCode
import io.ktor.server.plugins.statuspages.StatusPagesConfig
import io.ktor.server.response.respond

/**
 * Wraps [StatusPages.Configuration] to enable OpenAPI configuration for exception handling.
 * ```
 *  val api = install(OpenAPIGen)  { ... }
 *  ...
 *  // StatusPage interop, can also define exceptions per-route
 *  install(StatusPages) {
 *      withAPI(api) {
 *          exception(HttpStatusCode.BadRequest) {
 *              it.printStackTrace()
 *              Error("mapping.json", it.localizedMessage)
 *          }
 *          exception(HttpStatusCode.BadRequest) {
 *              it.printStackTrace()
 *              Error(it.id, it.localizedMessage)
 *          }
 *      }
 *  }
 * ```
 *
 * @param api the installed instance of [OpenAPIGen] in the [io.ktor.application.Application]
 * @param cfg the block that loads the configuration, see [OpenAPIGenStatusPagesInterop]
 */
inline fun StatusPagesConfig.withAPI(api: OpenAPIGen, crossinline cfg: OpenAPIGenStatusPagesInterop.() -> Unit = {}) {
    OpenAPIGenStatusPagesInterop(api, this).cfg()
}

/**
 * Wrapper for Status pages that handles exceptions and generates documentation in OpenAPI.
 * This is useful for default error pages.
 */
class OpenAPIGenStatusPagesInterop(val api: OpenAPIGen, val statusCfg: StatusPagesConfig) {

    /**
     * Registers a handler for exception type [TThrowable] and returns a [status] page
     */
    inline fun  exception(status: HttpStatusCode) {
        val ex = apiException(status)
        api.globalModuleProvider.registerModule(ThrowsInfo(listOf(ex)))
        statusCfg.exception { call, _ ->
            call.respond(status)
        }
    }

    /**
     * Registers a handler for exception type [TThrowable] and returns a [status] page that includes a response body
     * of type [TResponse].
     *
     * @param example An example of the response body
     * @param gen handler for [TThrowable] that should return an instance of [TResponse]
     */
    inline fun  exception(
        status: HttpStatusCode,
        example: TResponse? = null,
        noinline gen: (TThrowable) -> TResponse
    ) {
        val ex = apiException(status, example, gen)
        api.globalModuleProvider.registerModule(ThrowsInfo(listOf(ex)))
        statusCfg.exception { call, cause ->
            val ret = gen(cause)
            if (ret != null) {
                call.respond(status, ret)
            } else {
                call.respond(status)
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy