blob: 1b810e3d7ec9aef818a1c042514c1c1cb1f34812 (
plain)
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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
|
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()
.followRedirects(HttpClient.Redirect.NORMAL)
.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}")
)
}
}
|