From a426a7b21e50724a84e6bb7a18f48c9b27e7b66d Mon Sep 17 00:00:00 2001 From: Marco Martinez Date: Fri, 18 Nov 2022 08:08:35 -0700 Subject: [PATCH] Generalized HTTP Network Layer (#80) --- .../lib/drivers/network/HttpNetworkDriver.kt | 12 ++++ .../lib/drivers/network/HttpRequest.kt | 41 ++++++++++++++ .../lib/drivers/network/JdkHttpDriver.kt | 55 +++++++++++++++++++ .../metaplex/lib/drivers/rpc/JdkRpcDriver.kt | 42 +++++--------- 4 files changed, 121 insertions(+), 29 deletions(-) create mode 100644 lib/src/main/java/com/metaplex/lib/drivers/network/HttpNetworkDriver.kt create mode 100644 lib/src/main/java/com/metaplex/lib/drivers/network/HttpRequest.kt create mode 100644 lib/src/main/java/com/metaplex/lib/drivers/network/JdkHttpDriver.kt diff --git a/lib/src/main/java/com/metaplex/lib/drivers/network/HttpNetworkDriver.kt b/lib/src/main/java/com/metaplex/lib/drivers/network/HttpNetworkDriver.kt new file mode 100644 index 0000000..28345f1 --- /dev/null +++ b/lib/src/main/java/com/metaplex/lib/drivers/network/HttpNetworkDriver.kt @@ -0,0 +1,12 @@ +/* + * NetworkDriver + * metaplex-android + * + * Created by Funkatronics on 11/6/2022 + */ + +package com.metaplex.lib.drivers.network + +interface HttpNetworkDriver { + suspend fun makeHttpRequest(request: HttpRequest): String +} \ No newline at end of file diff --git a/lib/src/main/java/com/metaplex/lib/drivers/network/HttpRequest.kt b/lib/src/main/java/com/metaplex/lib/drivers/network/HttpRequest.kt new file mode 100644 index 0000000..e0d07f9 --- /dev/null +++ b/lib/src/main/java/com/metaplex/lib/drivers/network/HttpRequest.kt @@ -0,0 +1,41 @@ +/* + * HttpRequest + * metaplex-android + * + * Created by Funkatronics on 11/6/2022 + */ + +package com.metaplex.lib.drivers.network + +enum class HttpMethod(name: String){ + GET("GET"), + POST("POST"), + HEAD("HEAD"), + OPTIONS("OPTIONS"), + PUT("PUT"), + DELETE("DELETE"), + TRACE("TRACE") +} + +interface HttpRequest { + val url: String + val method: String + val properties: Map + val body: String? +} + +class HttpGetRequest( + override val url: String, + override val properties: Map +) : HttpRequest { + override val method = HttpMethod.GET.name + override val body = null +} + +class HttpPostRequest( + override val url: String, + override val properties: Map, + override val body: String? = null +) : HttpRequest { + override val method = HttpMethod.POST.name +} \ No newline at end of file diff --git a/lib/src/main/java/com/metaplex/lib/drivers/network/JdkHttpDriver.kt b/lib/src/main/java/com/metaplex/lib/drivers/network/JdkHttpDriver.kt new file mode 100644 index 0000000..3034450 --- /dev/null +++ b/lib/src/main/java/com/metaplex/lib/drivers/network/JdkHttpDriver.kt @@ -0,0 +1,55 @@ +/* + * JdkHttpDriver + * metaplex-android + * + * Created by Funkatronics on 11/6/2022 + */ + +package com.metaplex.lib.drivers.network + +import kotlinx.coroutines.suspendCancellableCoroutine +import java.net.HttpURLConnection +import java.net.URL + +/** + * A [HttpNetworkDriver] implementation using the native JDK [HttpURLConnection] + * + * @see HttpNetworkDriver + * @see java.net.HttpURLConnection + * + * @author Funkatronics + */ +class JdkHttpDriver : HttpNetworkDriver { + override suspend fun makeHttpRequest(request: HttpRequest): String = + suspendCancellableCoroutine { continuation -> + + with(URL(request.url).openConnection() as HttpURLConnection) { + // config + requestMethod = request.method + request.properties.forEach { (key, value) -> + setRequestProperty(key, value) + } + + // cancellation + continuation.invokeOnCancellation { disconnect() } + + // send request body + request.body?.run { + doOutput = true + outputStream.write(toByteArray(Charsets.UTF_8)) + outputStream.flush() + outputStream.close() + } + + // read response + val responseString = inputStream.bufferedReader().use { it.readText() } + + // TODO: should check response code and/or errorStream for errors +// println("URL : $url") +// println("Response Code : $responseCode") +// println("input stream : $responseString") + + continuation.resumeWith(Result.success(responseString)) + } + } +} \ No newline at end of file diff --git a/lib/src/main/java/com/metaplex/lib/drivers/rpc/JdkRpcDriver.kt b/lib/src/main/java/com/metaplex/lib/drivers/rpc/JdkRpcDriver.kt index 1aa72d8..1f4c485 100644 --- a/lib/src/main/java/com/metaplex/lib/drivers/rpc/JdkRpcDriver.kt +++ b/lib/src/main/java/com/metaplex/lib/drivers/rpc/JdkRpcDriver.kt @@ -7,7 +7,8 @@ package com.metaplex.lib.drivers.rpc -import kotlinx.coroutines.suspendCancellableCoroutine +import com.metaplex.lib.drivers.network.HttpPostRequest +import com.metaplex.lib.drivers.network.JdkHttpDriver import kotlinx.serialization.KSerializer import kotlinx.serialization.json.Json import java.net.HttpURLConnection @@ -21,7 +22,9 @@ import java.net.URL * * @author Funkatronics */ -class JdkRpcDriver(val url: URL) : JsonRpcDriver { +class JdkRpcDriver(val url: String) : JsonRpcDriver { + + constructor(url: URL) : this(url.toString()) private val json = Json { encodeDefaults = true @@ -29,32 +32,13 @@ class JdkRpcDriver(val url: URL) : JsonRpcDriver { } override suspend fun makeRequest(request: RpcRequest, resultSerializer: KSerializer): RpcResponse = - suspendCancellableCoroutine { continuation -> - - with(url.openConnection() as HttpURLConnection) { - // config - setRequestProperty("Content-Type", "application/json; charset=utf-8") - requestMethod = "POST" - doOutput = true - - // cancellation - continuation.invokeOnCancellation { disconnect() } - - // send request body - outputStream.write(json.encodeToString(RpcRequest.serializer(), request).toByteArray()) - outputStream.close() - - // read response - val responseString = inputStream.bufferedReader().use { it.readText() } - - // TODO: should check response code and/or errorStream for errors -// println("URL : $url") -// println("Response Code : $responseCode") -// println("input stream : $responseString") - - continuation.resumeWith(Result.success( - json.decodeFromString(RpcResponse.serializer(resultSerializer), responseString) - )) + JdkHttpDriver().makeHttpRequest( + HttpPostRequest( + url = url, + properties = mapOf("Content-Type" to "application/json; charset=utf-8"), + body = json.encodeToString(RpcRequest.serializer(), request) + ) + ).run { + json.decodeFromString(RpcResponse.serializer(resultSerializer), this) } - } } \ No newline at end of file