Skip to content

Commit 5407e63

Browse files
authored
Kotlin: allow pluggable HTTP clients (#1381)
* Replace ktor with Google Java HTTP client * Remove ktor and clean up methods * Disable cookie management for Apache transport
1 parent dca6f4e commit 5407e63

File tree

11 files changed

+276
-183
lines changed

11 files changed

+276
-183
lines changed

kotlin/build.gradle

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ defaultTasks 'jar'
1515

1616
repositories {
1717
mavenCentral()
18-
maven { url "https://dl.bintray.com/kotlin/ktor" }
1918
maven { url "https://dl.bintray.com/kotlin/kotlinx" }
2019
maven { url "https://jitpack.io" }
2120
}
@@ -32,10 +31,10 @@ dependencies {
3231
implementation "io.github.cdimascio:dotenv-kotlin:6.2.2"
3332
implementation "org.ini4j:ini4j:0.5.4"
3433

35-
implementation "io.ktor:ktor-client:$ktorVersion"
36-
implementation "io.ktor:ktor-client-okhttp:$ktorVersion"
37-
implementation "io.ktor:ktor-client-json:$ktorVersion"
38-
implementation "io.ktor:ktor-client-gson:$ktorVersion"
34+
implementation "com.google.http-client:google-http-client:$googleHttpVersion"
35+
implementation "com.google.http-client:google-http-client-apache-v2:$googleHttpVersion"
36+
implementation "com.google.http-client:google-http-client-gson:$googleHttpVersion"
37+
3938

4039
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.0-RC'
4140
implementation 'com.google.code.gson:gson:2.8.5'

kotlin/gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
kotlinVersion=1.7.10
2-
ktorVersion=1.6.7
2+
googleHttpVersion=1.43.3

kotlin/src/main/com/looker/rtl/APIMethods.kt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,27 +41,27 @@ open class APIMethods(val authSession: AuthSession) {
4141
}
4242
}
4343

44-
inline fun <reified T> get(path: String, queryParams: Values = mapOf(), body: Any? = null): SDKResponse {
44+
inline fun <reified T : Any> get(path: String, queryParams: Values = mapOf(), body: Any? = null): SDKResponse {
4545
return authSession.transport.request<T>(HttpMethod.GET, path, queryParams, body, authRequest)
4646
}
4747

48-
inline fun <reified T> head(path: String, queryParams: Values = mapOf(), body: Any? = null): SDKResponse {
48+
inline fun <reified T : Any> head(path: String, queryParams: Values = mapOf(), body: Any? = null): SDKResponse {
4949
return authSession.transport.request<T>(HttpMethod.HEAD, path, queryParams, body, authRequest)
5050
}
5151

52-
inline fun <reified T> delete(path: String, queryParams: Values = mapOf(), body: Any? = null): SDKResponse {
52+
inline fun <reified T : Any> delete(path: String, queryParams: Values = mapOf(), body: Any? = null): SDKResponse {
5353
return authSession.transport.request<T>(HttpMethod.DELETE, path, queryParams, body, authRequest)
5454
}
5555

56-
inline fun <reified T> post(path: String, queryParams: Values = mapOf(), body: Any? = null): SDKResponse {
56+
inline fun <reified T : Any> post(path: String, queryParams: Values = mapOf(), body: Any? = null): SDKResponse {
5757
return authSession.transport.request<T>(HttpMethod.POST, path, queryParams, body, authRequest)
5858
}
5959

60-
inline fun <reified T> put(path: String, queryParams: Values = mapOf(), body: Any? = null): SDKResponse {
60+
inline fun <reified T : Any> put(path: String, queryParams: Values = mapOf(), body: Any? = null): SDKResponse {
6161
return authSession.transport.request<T>(HttpMethod.PUT, path, queryParams, body, authRequest)
6262
}
6363

64-
inline fun <reified T> patch(path: String, queryParams: Values = mapOf(), body: Any? = null): SDKResponse {
64+
inline fun <reified T : Any> patch(path: String, queryParams: Values = mapOf(), body: Any? = null): SDKResponse {
6565
return authSession.transport.request<T>(HttpMethod.PATCH, path, queryParams, body, authRequest)
6666
}
6767

kotlin/src/main/com/looker/rtl/AuthSession.kt

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,7 @@
2424

2525
package com.looker.rtl
2626

27-
import io.ktor.client.request.forms.*
28-
import io.ktor.http.*
27+
import com.google.api.client.http.UrlEncodedContent
2928

3029
open class AuthSession(
3130
open val apiSettings: ConfigurationProvider,
@@ -144,12 +143,11 @@ open class AuthSession(
144143
unQuote(System.getProperty("${apiSettings.environmentPrefix}_CLIENT_ID") ?: config[client_id])
145144
val clientSecret =
146145
unQuote(System.getProperty("${apiSettings.environmentPrefix}_CLIENT_SECRET") ?: config[client_secret])
147-
val body = FormDataContent(
148-
Parameters.build {
149-
append(client_id, clientId)
150-
append(client_secret, clientSecret)
151-
}
146+
val params = mapOf(
147+
client_id to clientId,
148+
client_secret to clientSecret
152149
)
150+
val body = UrlEncodedContent(params)
153151
val token = ok<AuthToken>(
154152
transport.request<AuthToken>(
155153
HttpMethod.POST,

kotlin/src/main/com/looker/rtl/Constants.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ val BinaryMatch = Regex(MATCH_MODE_BINARY, RegexOption.IGNORE_CASE)
4242

4343
const val DEFAULT_TIMEOUT = 120
4444
const val DEFAULT_API_VERSION = "4.0" // Kotlin requires at least API 4.0
45+
const val DEFAULT_HTTP_TRANSPORT = "apache"
4546

4647
typealias Values = Map<String, Any?>
4748

kotlin/src/main/com/looker/rtl/ErrorDoc.kt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ class ErrorDocItem(var url: String)
3030
/** Structure of the error code document index */
3131
typealias ErrorCodeIndex = HashMap<String, ErrorDocItem>
3232

33-
interface IErrorDocLink {
33+
interface IErrorDocLink {
3434
/** base redirector url */
3535
var redirector: String
3636
/** api version of the error link */
@@ -39,9 +39,9 @@ typealias ErrorCodeIndex = HashMap<String, ErrorDocItem>
3939
var statusCode: String
4040
/** REST API Path */
4141
var apiPath: String
42-
}
42+
}
4343

44-
interface IErrorDoc {
44+
interface IErrorDoc {
4545
/** Index of all known error codes. Call load() to populate it */
4646
var index: ErrorCodeIndex?
4747

@@ -103,10 +103,10 @@ typealias ErrorCodeIndex = HashMap<String, ErrorDocItem>
103103
* @param errorMdUrl url for the error document
104104
*/
105105
fun methodName(errorMdUrl: String): String
106-
}
106+
}
107107

108108
/** Class to process Looker API error payloads and retrieve error documentation */
109-
class ErrorDoc(val sdk: APIMethods, val cdnUrl: String = ErrorCodesUrl): IErrorDoc {
109+
class ErrorDoc(val sdk: APIMethods, val cdnUrl: String = ErrorCodesUrl) : IErrorDoc {
110110
companion object {
111111
/** Location of the public CDN for Looker API Error codes */
112112
const val ErrorCodesUrl = "https://static-a.cdn.looker.app/errorcodes/"
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package com.looker.rtl
2+
3+
import com.google.api.client.util.ObjectParser
4+
import com.google.gson.Gson
5+
import com.google.gson.stream.JsonReader
6+
import java.io.InputStream
7+
import java.io.InputStreamReader
8+
import java.io.Reader
9+
import java.lang.reflect.Type
10+
import java.nio.charset.Charset
11+
12+
/** Custom GSON based parser for deserialization. */
13+
class GsonObjectParser : ObjectParser {
14+
override fun <T : Any?> parseAndClose(
15+
inputStream: InputStream?,
16+
charset: Charset?,
17+
clazz: Class<T>?,
18+
): T {
19+
return doParseAndClose(InputStreamReader(inputStream, charset), clazz)
20+
}
21+
22+
override fun parseAndClose(inputStream: InputStream?, charset: Charset?, type: Type?): Any {
23+
return doParseAndClose(InputStreamReader(inputStream, charset), type)
24+
}
25+
26+
override fun <T : Any?> parseAndClose(reader: Reader?, clazz: Class<T>?): T {
27+
return doParseAndClose(reader, clazz)
28+
}
29+
30+
override fun parseAndClose(reader: Reader?, type: Type?): Any {
31+
return doParseAndClose(reader, type)
32+
}
33+
34+
private fun <T : Any?> doParseAndClose(reader: Reader?, type: Type?): T {
35+
val jsonReader = JsonReader(reader)
36+
jsonReader.use {
37+
return GSON.fromJson(reader, type)
38+
}
39+
}
40+
41+
companion object {
42+
/** [Gson] instance used for serializing Kotlin data classes and deserializing responses */
43+
val GSON: Gson = Gson().newBuilder()
44+
.registerTypeAdapter(AuthToken::class.java, AuthTokenAdapter())
45+
.create()
46+
}
47+
}

0 commit comments

Comments
 (0)