-
Notifications
You must be signed in to change notification settings - Fork 58
Kotless HTTP API
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 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.
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!"
}
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).
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")
}
}
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")
}
}
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 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