diff options
| author | Linnea Gräf <nea@nea.moe> | 2025-10-13 22:10:38 +0200 |
|---|---|---|
| committer | Linnea Gräf <nea@nea.moe> | 2025-10-13 22:10:38 +0200 |
| commit | 733f01be8c2ca986e594816e73cb89ee1c8d105d (patch) | |
| tree | 7709f194f714b0bcfdbab0c65ec5aa7b3fe49c14 /src/main/kotlin/util/net/HttpUtil.kt | |
| parent | 05160314e6899ece75779dbd2e5b691ed581c2b9 (diff) | |
| download | Firmament-733f01be8c2ca986e594816e73cb89ee1c8d105d.tar.gz Firmament-733f01be8c2ca986e594816e73cb89ee1c8d105d.tar.bz2 Firmament-733f01be8c2ca986e594816e73cb89ee1c8d105d.zip | |
feat: remove ktor (for a smaller binary)
Diffstat (limited to 'src/main/kotlin/util/net/HttpUtil.kt')
| -rw-r--r-- | src/main/kotlin/util/net/HttpUtil.kt | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/src/main/kotlin/util/net/HttpUtil.kt b/src/main/kotlin/util/net/HttpUtil.kt new file mode 100644 index 0000000..50e0644 --- /dev/null +++ b/src/main/kotlin/util/net/HttpUtil.kt @@ -0,0 +1,85 @@ +package moe.nea.firmament.util.net + +import java.io.InputStream +import java.net.URI +import java.net.URL +import java.net.http.HttpClient +import java.net.http.HttpRequest +import java.net.http.HttpResponse +import java.nio.ByteBuffer +import java.util.concurrent.CompletableFuture +import java.util.concurrent.CompletionStage +import java.util.concurrent.Flow +import kotlinx.serialization.DeserializationStrategy +import kotlinx.serialization.json.decodeFromStream +import kotlinx.serialization.serializer +import moe.nea.firmament.Firmament + +object HttpUtil { + val httpClient = HttpClient.newBuilder() + .build() + + data class Request(val request: HttpRequest.Builder) { + fun <T> execute(bodyHandler: HttpResponse.BodyHandler<T>): CompletableFuture<HttpResponse<T>> { + return httpClient.sendAsync(request.build(), bodyHandler) + } + + fun <T> forBody(bodyHandler: HttpResponse.BodyHandler<T>): CompletableFuture<T> { + return execute(bodyHandler).thenApply { it.body() } + } + + fun forInputStream(): CompletableFuture<InputStream> { + return forBody(HttpResponse.BodyHandlers.ofInputStream()) + } + + inline fun <reified T> forJson(): CompletableFuture<T> { + return forJson(serializer()) + } + + fun <T> forJson(serializer: DeserializationStrategy<T>): CompletableFuture<T> { + return forBody(jsonBodyHandler(serializer)) + } + + fun header(key: String, value: String) { + request.header(key, value) + } + } + + fun <T> jsonBodyHandler(serializer: DeserializationStrategy<T>): HttpResponse.BodyHandler<T> { + val inp = HttpResponse.BodyHandlers.ofInputStream() + return HttpResponse.BodyHandler { + val subscriber = inp.apply(it) + object : HttpResponse.BodySubscriber<T> { + override fun getBody(): CompletionStage<T> { + return subscriber.body.thenApply { Firmament.json.decodeFromStream(serializer, it) } + } + + override fun onSubscribe(subscription: Flow.Subscription?) { + subscriber.onSubscribe(subscription) + } + + override fun onNext(item: List<ByteBuffer?>?) { + subscriber.onNext(item) + } + + override fun onError(throwable: Throwable?) { + subscriber.onError(throwable) + } + + override fun onComplete() { + subscriber.onComplete() + } + } + } + } + + fun request(url: String): Request = request(URI.create(url)) + fun request(url: URL): Request = request(url.toURI()) + fun request(url: URI): Request { + return Request( + HttpRequest.newBuilder(url) + .GET() + .header("user-agent", "Firmament/${Firmament.version}") + ) + } +} |
