Multiplatform Ktor schema declaration¶
Describe your Ktor API in code shared between the client and the server.
When creating fullstack projects, using both Ktor as a client and a server, we need to make sure we are calling the same endpoints on both sides, with the same expected DTOs, expect the same failures, etc.
Using Kotlin Multiplatform and KotlinX.Serialization, we can easily share DTOs—but the structure of the API isn't as easy to share.
Declaring a schema¶
Spine is a library to declare a schema of our API in pure Kotlin. Once it is declared, we can use it identically on the client and server sides.
First, declare a dependency on dev.opensavvy.spine:api.
We define that:
-
a <strong>resource</strong>is an imaginary data collection, -
an <strong>endpoint</strong>is a single operation that acts on a given resource.
We can declare the structure of our API like this:
// Declare our root endpoint: /v1
object Api : RootResource("v1") {
// Declare a nested resource: /v1/users
object Users : StaticResource<Api>("/users", parent = Api) {
// GET /v1/users
// which returns a list of UserDto
val list by get()
.response<List<UserDto>>()
// Declare a nested resource: /v1/users/{user}
object User : DynamicResource<Users>("user", parent = Users) {
// GET /v1/users/{user}
// which returns a UserDto
val get by get()
.response<UserDto>()
// POST /v1/users/{user}
// which accepts a UserCreationDto and returns a UserDto
val create by post()
.request<UserCreationDto>()
.response<UserDto>()
// PUT /v1/users/{user}/friend
val addFriend by put("friend")
// DELETE /v1/users/{user}/friend
val removeFriend by delete("friend")
}
}
}
We can then refer to any endpoint easily. For example, Api.Users.User.removeFriend is the DELETE /v1/users/{user}/friend endpoint.
Learn more¶
Resources describe a grouping of endpoints under a single URL:
-
RootResourceis the root of a URL. -
StaticResourceis a hard-coded segment in a URL, for example/usersor/posts. -
DynamicResourceis a wildcard segment in a URL, which could be replaced by a user's ID, for example.
Endpoints describe a specific HTTP method along with its expected input and output types, parameters, etc.
-
AnyEndpointallows introspecting information about an endpoint. -
AnyEndpoint.Builderallows declaring information about an endpoint. -
Parametersrepresent query parameters.
To learn how to use the APIs on the client or on the server, see the documentation of the client and server modules.