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

kweb.config.KwebConfiguration.kt Maven / Gradle / Ivy

There is a newer version: 1.4.12
Show newest version
package kweb.config

import io.ktor.server.application.*
import io.ktor.http.*
import io.ktor.server.response.*
import kweb.Kweb
import mu.KotlinLogging
import java.time.Duration
import java.util.*

/**
 * A configuration class for Kweb parameterization. Extend this if you have custom needs
 * on how to inject configuration values, otherwise [KwebDefaultConfiguration] is probably
 * good enough for your use case
 *
 * Please note this is not [Kweb.Feature.Configuration], which is a Ktor specific config block
 */
abstract class KwebConfiguration {
    private val logger = KotlinLogging.logger {}

    /**
     * If [Kweb.debug] is enabled, then pages that take longer than [buildpageTimeout]
     * to load will display a warning message
     *
     * See [Duration.parse] for valid formats, e.g PT5S, or PT48H
     */
    abstract val buildpageTimeout: Duration

    /**
     * Enable stats for the client state cache. Small performance penalty per operation,
     * large gains in observability. Consider this in production.
     */
    abstract val clientStateStatsEnabled: Boolean

    /**
     * Clients that last connected more than [clientStateTimeout] will be cleaned
     * up every minute.
     *
     * Don't put this too low, you may end up cleaning semi-active clients, e.g someone
     * who left a page open for a long duration without actions, such as a monitoring page.
     */
    abstract val clientStateTimeout: Duration

    /**
     * Values are initialized eagerly, but objects are not, so be sure to "touch" this class
     * on initialization for failing fast.
     *
     * We can also add some smarter validation here later if needed
     */
    fun validate() {
        logger.debug { "Configuration has been initialized successfully" }
    }


    /**
     * Override this function to handle uncaught exceptions of client callbacks.
     * E.g. if the browser sends a websocket message back to the kweb instance
     * and the message handler throws an uncaught exception, kweb will invoke
     * this exception handler to expose the fact that a message could not be
     * properly handled
     */
    open fun onWebsocketMessageHandlingFailure(ex: Exception){

    }

    /**
     * Override the default robots.txt behavior, which is to return with a 404. Passed a Ktor [ApplicationCall]
     * which may be used to return whatever you wish.
     */
    open suspend fun robotsTxt(call: ApplicationCall) {
        call.response.status(HttpStatusCode.NotFound)
        call.respondText("robots.txt has not been specified)")
    }

    /**
     * Override the default favicon.ico behavior, which is to return with a 404. Passed a Ktor [ApplicationCall]
     * which may be used to return whatever you wish.
     */
    open suspend fun faviconIco(call: ApplicationCall) {
        call.respondText("404 favicon.ico not found", status = HttpStatusCode.NotFound)
    }

    /**
     * Message that is shown to a disconnected client.
     *
     */
    open val clientOfflineToastTextTemplate: String = "Connection to server lost, attempting to reconnect"

    /**
     * By default, Kweb will handle all paths under `/`, but this may not be desirable if you have other
     * Ktor route handlers. This config option allows you to add a prefix to the Kweb route handler,
     * e.g. `/my_kweb_site`, so that only URLs under that path will be handled by Kweb.

     *
     * ```kotlin
     *    cfg.urlPathPrefix = ""
     *    path("/users/{userId}") { } // will be accessible at /users/1234
     *
     *    cfg.urlPathPrefix = "/my_kweb_site"
     *    path("/my_kweb_site/users/{userId}") { } // will be accessible at /my_kweb_site/users/1234
     *
     *    cfg.urlPathPrefix = "/my_kweb_site"
     *    path("/users/{userId}") { } // Will **NOT** be accessible
     * ```
     *
     * The path used for the WebSocket connection (`/kweb_ws`) and static assets (`/kweb_static/`) will be
     * unaffected by this setting.
     */
    open val urlPathPrefix : String = ""

    protected object Accessor {
        private val env = System.getenv()

        /**
         * Gets the value of the given property by searching runtime properties,
         * then env, then uppercase ENV. Each case is only examined if the previous one failed.
         *
         * So, if you provide a [key] value such as "kweb.test", the following will happen
         * - First "kweb.test" will be looked up as a run argument
         * - Then "kweb.test" is looked up in env variables (the JVM is kinda bad at lowercase ENV vars in my experience)
         * - Then "KWEB_TEST" is looked up in env variables
         * - Then null is returned
         */
        fun getProperty(key: String): String? =
            System.getProperty(key, env[key] ?: env[key.uppercase(Locale.getDefault()).replace('.', '_')])
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy