aboutsummaryrefslogtreecommitdiff
path: root/src/main/kotlin/moe/nea/ledger/utils/network
diff options
context:
space:
mode:
authorLinnea Gräf <nea@nea.moe>2024-12-17 23:07:06 +0100
committerLinnea Gräf <nea@nea.moe>2024-12-17 23:07:06 +0100
commita046b198645811fe1b7db129942505c379aabb03 (patch)
treed97e68b1cf3a272aec5d8dd863b82fb0c9b0dc82 /src/main/kotlin/moe/nea/ledger/utils/network
parenta2f73de90fb9c9d0ea7a5e7e9e6b9e445a8094ee (diff)
downloadLocalTransactionLedger-a046b198645811fe1b7db129942505c379aabb03.tar.gz
LocalTransactionLedger-a046b198645811fe1b7db129942505c379aabb03.tar.bz2
LocalTransactionLedger-a046b198645811fe1b7db129942505c379aabb03.zip
feat: Add name prefetching
Diffstat (limited to 'src/main/kotlin/moe/nea/ledger/utils/network')
-rw-r--r--src/main/kotlin/moe/nea/ledger/utils/network/Request.kt40
-rw-r--r--src/main/kotlin/moe/nea/ledger/utils/network/RequestUtil.kt63
-rw-r--r--src/main/kotlin/moe/nea/ledger/utils/network/Response.kt19
3 files changed, 122 insertions, 0 deletions
diff --git a/src/main/kotlin/moe/nea/ledger/utils/network/Request.kt b/src/main/kotlin/moe/nea/ledger/utils/network/Request.kt
new file mode 100644
index 0000000..ddf2fcc
--- /dev/null
+++ b/src/main/kotlin/moe/nea/ledger/utils/network/Request.kt
@@ -0,0 +1,40 @@
+package moe.nea.ledger.utils.network
+
+import com.google.gson.JsonElement
+import java.net.URL
+
+data class Request(
+ val url: URL,
+ val method: Method,
+ val body: String?,
+ val headers: Map<String, String>,
+) {
+ enum class Method {
+ GET, POST
+ }
+
+ enum class MediaType(val text: String) {
+ JSON("application/json"),
+ TEXT("text/plain"),
+ HTML("text/html"),
+ ANY("*/*"),
+ }
+
+ fun withHeaders(map: Map<String, String>): Request {
+ // TODO: enforce caselessness?
+ return this.copy(headers = headers + map)
+ }
+
+ fun post() = copy(method = Method.POST)
+ fun get() = copy(method = Method.GET)
+
+ fun json(element: JsonElement) = copy(
+ headers = headers + mapOf("content-type" to "application/json"),
+ body = element.toString())
+
+ fun accept(request: MediaType) = withHeaders(mapOf("accept" to request.text))
+
+ fun acceptJson() = accept(MediaType.JSON)
+
+ fun execute(requestUtil: RequestUtil) = requestUtil.executeRequest(this)
+} \ No newline at end of file
diff --git a/src/main/kotlin/moe/nea/ledger/utils/network/RequestUtil.kt b/src/main/kotlin/moe/nea/ledger/utils/network/RequestUtil.kt
new file mode 100644
index 0000000..a49c65a
--- /dev/null
+++ b/src/main/kotlin/moe/nea/ledger/utils/network/RequestUtil.kt
@@ -0,0 +1,63 @@
+package moe.nea.ledger.utils.network
+
+import moe.nea.ledger.utils.ErrorUtil
+import moe.nea.ledger.utils.di.Inject
+import java.net.URL
+import java.net.URLConnection
+import java.security.KeyStore
+import java.util.zip.GZIPInputStream
+import javax.net.ssl.HttpsURLConnection
+import javax.net.ssl.KeyManagerFactory
+import javax.net.ssl.SSLContext
+import javax.net.ssl.TrustManagerFactory
+
+class RequestUtil @Inject constructor(val errorUtil: ErrorUtil) {
+
+ private fun createSSLContext(): SSLContext? = errorUtil.catch {
+ val keyStorePath = RequestUtil::class.java.getResourceAsStream("/ledgerkeystore.jks")
+ ?: error("Could not locate keystore")
+ val keyStore = KeyStore.getInstance("JKS")
+ keyStore.load(keyStorePath, "neuneu".toCharArray())
+ val kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm())
+ val tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm())
+ kmf.init(keyStore, null)
+ tmf.init(keyStore)
+ val ctx = SSLContext.getInstance("TLS")
+ ctx.init(kmf.keyManagers, tmf.trustManagers, null)
+ return@catch ctx
+ }
+
+ val sslContext = createSSLContext()
+
+ fun enhanceConnection(connection: URLConnection) {
+ if (connection is HttpsURLConnection && sslContext != null) {
+ connection.sslSocketFactory = sslContext.socketFactory
+ }
+ }
+
+ fun createRequest(url: String) = createRequest(URL(url))
+ fun createRequest(url: URL) = Request(url, Request.Method.GET, null, mapOf())
+
+ fun executeRequest(request: Request): Response {
+ val connection = request.url.openConnection()
+ enhanceConnection(connection)
+ connection.setRequestProperty("accept-encoding", "gzip")
+ request.headers.forEach { (k, v) ->
+ connection.setRequestProperty(k, v)
+ }
+ if (request.body != null) {
+ connection.getOutputStream().write(request.body.encodeToByteArray())
+ connection.getOutputStream().close()
+ }
+ var stream = connection.getInputStream()
+ if (connection.contentEncoding == "gzip") {
+ stream = GZIPInputStream(stream)
+ }
+ val text = stream.bufferedReader().readText()
+ stream.close()
+ // Do NOT call connection.disconnect() to allow for connection reuse
+ return Response(request, text, connection.headerFields)
+ }
+
+
+} \ No newline at end of file
diff --git a/src/main/kotlin/moe/nea/ledger/utils/network/Response.kt b/src/main/kotlin/moe/nea/ledger/utils/network/Response.kt
new file mode 100644
index 0000000..daae7f7
--- /dev/null
+++ b/src/main/kotlin/moe/nea/ledger/utils/network/Response.kt
@@ -0,0 +1,19 @@
+package moe.nea.ledger.utils.network
+
+import com.google.gson.reflect.TypeToken
+import moe.nea.ledger.Ledger
+
+data class Response(
+ val source: Request,
+ // TODO: allow other body processors, to avoid loading everything as strings
+ val response: String,
+ val headers: Map<String, List<String>>,
+) {
+ fun <T : Any> json(typ: TypeToken<T>): T {
+ return Ledger.gson.fromJson(response, typ.type)
+ }
+
+ fun <T : Any> json(clazz: Class<T>): T {
+ return Ledger.gson.fromJson(response, clazz)
+ }
+} \ No newline at end of file