-
Notifications
You must be signed in to change notification settings - Fork 4
/
KtorUtils.kt
57 lines (52 loc) · 2.19 KB
/
KtorUtils.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
package alerts
import arrow.core.Either
import arrow.fx.coroutines.ExitCase
import arrow.fx.coroutines.Resource
import arrow.fx.coroutines.ResourceScope
import io.ktor.http.ContentType
import io.ktor.http.HttpStatusCode
import io.ktor.http.content.OutgoingContent
import io.ktor.http.content.TextContent
import io.ktor.server.application.Application
import io.ktor.server.application.ApplicationCall
import io.ktor.server.application.call
import io.ktor.server.engine.ApplicationEngine
import io.ktor.server.engine.ApplicationEngineFactory
import io.ktor.server.engine.embeddedServer
import io.ktor.server.response.respond
import io.ktor.util.pipeline.PipelineContext
import kotlin.time.Duration
import kotlin.time.Duration.Companion.seconds
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.cancel
import kotlinx.coroutines.delay
import kotlinx.coroutines.job
import kotlin.coroutines.CoroutineContext
/**
* Utility to create a [CoroutineScope] as a [Resource].
* It calls the correct [cancel] overload depending on the [ExitCase].
*/
suspend fun ResourceScope.coroutineScope(context: CoroutineContext): CoroutineScope =
install({ CoroutineScope(context) }, { scope, exitCase ->
when (exitCase) {
ExitCase.Completed -> scope.cancel()
is ExitCase.Cancelled -> scope.cancel(exitCase.exception)
is ExitCase.Failure -> scope.cancel("Resource failed, so cancelling associated scope", exitCase.failure)
}
scope.coroutineContext.job.join()
})
/** Small utility to turn HttpStatusCode into OutgoingContent. */
fun statusCode(statusCode: HttpStatusCode) = object : OutgoingContent.NoContent() {
override val status: HttpStatusCode = statusCode
}
fun badRequest(content: String, contentType: ContentType = ContentType.Text.Plain) =
TextContent(content, contentType, HttpStatusCode.BadRequest)
/** Small utility functions that allows to conveniently respond an `Either` where `Left == OutgoingContent`. */
context(PipelineContext<Unit, ApplicationCall>)
suspend inline fun <reified A : Any> Either<OutgoingContent, A>.respond(
code: HttpStatusCode = HttpStatusCode.OK,
): Unit =
when (this) {
is Either.Left -> call.respond(value)
is Either.Right -> call.respond(code, value)
}