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

io.javalin.router.Endpoint.kt Maven / Gradle / Ivy

There is a newer version: 6.3.0
Show newest version
package io.javalin.router

import io.javalin.http.Context
import io.javalin.http.Handler
import io.javalin.http.HandlerType
import io.javalin.http.NotFoundResponse
import io.javalin.security.Roles
import io.javalin.security.RouteRole

/**
 * Marker interface for endpoint metadata.
 * Requiring this interfaces prevents the user from passing existing classes (such as String) as metadata.
 */
interface EndpointMetadata

/**
 * Represents an HTTP endpoint in the application.
 *
 * @param method The HTTP method of the endpoint
 * @param path The path of the endpoint
 * @param metadata The metadata of the endpoint
 * @param handler The handler of the endpoint
 */
open class Endpoint @JvmOverloads constructor(
    val method: HandlerType,
    val path: String,
    metadata: Set = emptySet(),
    val handler: Handler
) {

    @Deprecated("Use Endpoint builder instead", ReplaceWith("Endpoint.create(method, path)"))
    constructor(
        method: HandlerType,
        path: String,
        vararg roles: RouteRole,
        handler: Handler
    ) : this(
        method = method,
        path = path,
        metadata = setOf(Roles(roles.toSet())),
        handler = handler
    )

    @Deprecated("Use metadata instead", ReplaceWith("getMetadata(Roles.class)"))
    val roles: Set
        get() = metadata(Roles::class.java)?.roles ?: emptySet()

    private val metadata = metadata.associateBy { it::class.java }

    /** Execute the endpoint handler with the given context */
    fun handle(ctx: Context): Context =
        ctx.also { handler.handle(ctx) }

    /** Execute the endpoint handler with the given executor */
    fun handle(executor: EndpointExecutor): Context =
        executor.execute(this)

    @Suppress("UNCHECKED_CAST")
    fun  metadata(key: Class): METADATA? =
        metadata[key] as METADATA?

    companion object {

        class EndpointBuilder internal constructor(val method: HandlerType, val path: String) {

            private val metadata = mutableSetOf()

            fun addMetadata(metadata: EndpointMetadata): EndpointBuilder =
                apply { this.metadata.add(metadata) }

            fun handler(handler: Handler): Endpoint =
                Endpoint(method, path, metadata, handler)

        }

        @Deprecated("Experimental feature")
        @JvmStatic
        fun create(method: HandlerType, path: String): EndpointBuilder = EndpointBuilder(method, path)
    }

}

/**
 * Endpoint executor represents a component that is able to execute an endpoint,
 * such as a router or a mock.
 */
fun interface EndpointExecutor {
    fun execute(endpoint: Endpoint): Context
}

class EndpointNotFound(
    method: HandlerType,
    path: String
) : NotFoundResponse("Endpoint ${method.name} $path not found")




© 2015 - 2025 Weber Informatics LLC | Privacy Policy