diff options
Diffstat (limited to 'src/main/kotlin/util')
| -rw-r--r-- | src/main/kotlin/util/Base64Util.kt | 20 | ||||
| -rw-r--r-- | src/main/kotlin/util/net/HttpUtil.kt | 85 |
2 files changed, 98 insertions, 7 deletions
diff --git a/src/main/kotlin/util/Base64Util.kt b/src/main/kotlin/util/Base64Util.kt index c39c601..0b7b3ea 100644 --- a/src/main/kotlin/util/Base64Util.kt +++ b/src/main/kotlin/util/Base64Util.kt @@ -1,17 +1,23 @@ - package moe.nea.firmament.util import java.util.Base64 object Base64Util { fun decodeString(str: String): String { + return decodeBytes(str).decodeToString() + } + + fun decodeBytes(str: String): ByteArray { return Base64.getDecoder().decode(str.padToValidBase64()) - .decodeToString() } - fun String.padToValidBase64(): String { - val align = this.length % 4 - if (align == 0) return this - return this + "=".repeat(4 - align) - } + fun String.padToValidBase64(): String { + val align = this.length % 4 + if (align == 0) return this + return this + "=".repeat(4 - align) + } + + fun encodeToString(bytes: ByteArray): String { + return Base64.getEncoder().encodeToString(bytes) + } } 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}") + ) + } +} |
