Skip to content

Kotless HTTP API

Vladislav.Tankov edited this page Jun 13, 2020 · 3 revisions

Kotless DSL provides simple yet powerful DSL to create HTTP-based applications. It includes annotations to create HTTP routes, deploy static files, extensible serialization, HTTP request interceptors, and links API.

Let us take a look at these features one by one.

Dynamic

Dynamic HTTP API of Kotless includes everything related to dynamic processing of HTTP requests. Basically it is everything except for static files located right at S3.

Routes

Kotless supports Get and Post function annotations. Each function annotated with them will create a new HTTP route with appropriate method.

Functions may have parameters. Deserialization of the parameters, for primitive types will be done automatically. Also, you can extend deserialization to support non-primitive types as function parameters.

Serialization of the result will also be done automatically. Nevertheless, it is possible to return data as HttpResponse — in this case no serialization will be performed.

Here is a simple snippet of dynamic Get route:

@Get("/")
fun root(): String {
    return "Hello world!"
}

Context

During the processing of HTTP request KotlessContext.HTTP object is available for user.

Context includes current HTTP request at field request.

Note that a call to request may throw KotlinNullPointerException if this call is performed not in the context of HTTP request processing (basically, not in an HTTP route).

Interceptor

Kotless will pass all HTTP requests through interceptors. Each interceptor is a Kotlin static object implementing interface HttpRequestInterceptor.

In case there is more than one interceptor, Kotless will pass a request to the first of them (ascending order of priority) and will pass as next continuation pipeline of next interceptors.

Here is a simple snippet of the request interceptor, which is checking that the header auth token is valid:

object AuthInterceptor: HttpRequestInterceptor {
    override val priority = 0

    override fun intercept(request: HttpRequest, key: RouteKey, next: (HttpRequest, RouteKey) -> HttpResponse): HttpResponse {
        if (AuthTokens.isValid(request.headers["auth"])) {
            //Pass request to next interceptor or handler, if authentication is valid
            return next(request, key)
        }
        //Redirect to login if authentication is not valid
        return redirect("/login")
    }
}

Serialization

Kotless uses ConversionService implementations to deserialize parameters of the request and serialize them in links. DefaultConversionService supports serialization and deserialization of primitive Kotlin types.

In case you need to support custom types deserialization, you will need to create Kotlin static object implementing interface ConversionService.

Here is a simple snippet that deserializes entities by ID from a database:

object EntityConversionService: ConversionService {
    override fun convertFrom(value: String, type: Type): Any {
        if (type !is Class<*>) throw ConversionException("Type is not supported")
        if (Entity::class.java.isAssignableFrom(type)) {
            return Database.load(value.toLong())
        }
        throw ConversionException("Type is not supported")
    }

    override fun convertTo(value: Any): String {
        if (value is Entity) {
            return value.id
        }
        throw ConversionException("Type is not supported")
    }
}

Links

Kotless provides extension functions to create links (href-s) to Kotless-based routes.

Basically, there are two types of such links — base links, without any parameters, and prepared links with parameters already embedded in a link itself.

Here is a simple snippet creating a base and a prepared link.

@Get("/url")
fun root(str: String) = "body"

val baseLink = API::root.href

val preparedLink = API::root.href("parameter")

Static

Static HTTP API of Kotless is a convenient way of creating HTTP routes that are served via static files.

To create static route you need to use @StaticGet annotation.

Note that this annotation has severe limitations on an annotated object.

The property under annotation must have a value instantiated directly with java.io.File(String) constructor, and the path should be relative to workingDir of Kotless.

Here is a simple snippet of static route creation:

@StaticGet("/file.css", MimeType.CSS)
val exampleCss = File("example.css")

Links API also works for static routes, but only base links can be constructed:

val baseLink = ::exampleCss.href