New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Kotlin: allow pluggable HTTP clients #1381
Conversation
3157dc4
to
58c10e0
Compare
implementation "io.ktor:ktor-client:$ktorVersion" | ||
implementation "io.ktor:ktor-client-okhttp:$ktorVersion" | ||
implementation "io.ktor:ktor-client-json:$ktorVersion" | ||
implementation "io.ktor:ktor-client-gson:$ktorVersion" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed for now but can add back if we decide to have a low-level ktor client to make the requests
APACHE("Apache HTTP Client"), | ||
JAVA_NET("Native Java HTTP Client"), | ||
// URL_FETCH("Google App Engine HTTP Client"), TODO: App Engine support? Requires App Engine SDK. | ||
// KTOR("Kotlin based HTTP Client") TODO: Add ktor transport wrapper. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a requirement to use ktor
? If so I can make the wrapper class.
Apache and java.net are fairly standard.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's not a requirement to use ktor
although that appears to be the more "standard" HTTP client for Kotlin. Have you looked at the dependency size impact of the Apache and/or Java HTTP clients? Is Ktor a layer on top of Java HTTP? I haven't looked since we implemented the original SDK.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Prior to this change we were using the OkHttp
engine but ktor
supports several types including Apache: https://ktor.io/docs/http-client-engines.html.
In my understanding ktor
and the Google HTTP Client do similar things in that they abstract "low-level" HTTP request/responses handling. ktor
provides more Kotlin specific features, like coroutines, but I am not sure what else is gained. Both have Android specific transports as well if that is a requirement.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah. I think @brianmadden I talked about coroutines for ktor
and that's why we wanted to use it, based on what he'd done in Krawler. That was a long time ago, though, so I'm not sure at this point.
Did you run the kotlin smoke tests with this change?
β¦On Sat, Oct 14, 2023, 7:02β―PM TJ Banghart ***@***.***> wrote:
***@***.**** commented on this pull request.
------------------------------
In kotlin/src/main/com/looker/rtl/Transport.kt
<#1381 (comment)>
:
> - HEAD(io.ktor.http.HttpMethod.Head)
- // TODO: Using the ktor-client-apache may support TRACE?
+enum class HttpMethod {
+ GET,
+ POST,
+ PUT,
+ DELETE,
+ PATCH,
+ HEAD
+}
+
+enum class HttpTransports(val label: String) {
+ APACHE("Apache HTTP Client"),
+ JAVA_NET("Native Java HTTP Client"),
+ // URL_FETCH("Google App Engine HTTP Client"), TODO: App Engine support? Requires App Engine SDK.
+ // KTOR("Kotlin based HTTP Client") TODO: Add ktor transport wrapper.
Is there a requirement to use ktor? If so I can make the wrapper class.
Apache and java.net are fairly standard.
β
Reply to this email directly, view it on GitHub
<#1381 (review)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ABORGARTFKRED2GVK74252DX7LHSPAVCNFSM6AAAAAA56UT4H2VHI2DSMVQWIX3LMV43YUDVNRWFEZLROVSXG5CSMV3GSZLXHMYTMNZYGI3TENRXGM>
.
You are receiving this because your review was requested.Message ID:
***@***.***>
|
Ah, let me double check that. I ran the unit tests in intellij but should probably use the script. I'll mark as WIP and test it out again. |
Okay, passing smoke tests but one issue with warnings about invalid cookies. I left a comment on the |
// TODO: fix bug upstream that does not pass client context to requests. | ||
// The Netscape `expire` datetime format is not compatible with the "default" and | ||
// will log invalid warnings. | ||
val clientBuilder = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The response cookies we get back from Looker use the Wdy, DD-Mon-YY HH:MM:SS GMT
format for expires
. We should be able to push down the config here to the low-level Apache request but the request does not reference the client context. I believe it is a bug in the Google Java Client.
Note, this doesn't stop requests, but rather logs a confusing error. We still get a correct response back.
Alternatively, we could use disableCookieManagement()
so the low-level client doesn't try to validate cookies. This prevents the warning and we get the desired response. The SDK usually shouldn't care about cookies right? Wouldn't the required auth token header make cookies redundant?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We definitely have responses that would set cookies and those would be needed (the ironically named cookieless embed is one example) but this could be a case of worrying about it when we discover someone needs it. The only concern I have is whether the Looker Android mobile client reads any cookies from Looker, but it probably doesn't? I've not really looked at how cookies are used in non-browser situations and someone could implement a custom payload parser if it really was required as long as we have the hooks available to get the original request.
Do we have a test that verifies a payload with missing "required" fields still gets parsed correctly? Or are you still using GSon for parsing with whichever client? I'll look at the code now that I'm on a bigger screen.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have questions but nothing that blocks approval for this PR
@@ -41,27 +41,27 @@ open class APIMethods(val authSession: AuthSession) { | |||
} | |||
} | |||
|
|||
inline fun <reified T> get(path: String, queryParams: Values = mapOf(), body: Any? = null): SDKResponse { | |||
inline fun <reified T : Any> get(path: String, queryParams: Values = mapOf(), body: Any? = null): SDKResponse { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
was this update required by the new Kotlin version? Just curious because it doesn't look like the Kotlin version got updated.
@@ -30,7 +30,7 @@ class ErrorDocItem(var url: String) | |||
/** Structure of the error code document index */ | |||
typealias ErrorCodeIndex = HashMap<String, ErrorDocItem> | |||
|
|||
interface IErrorDocLink { | |||
interface IErrorDocLink { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks for the reformatting correction. Weird we had leading spaces in the interface declarations.
import java.lang.reflect.Type | ||
import java.nio.charset.Charset | ||
|
||
/** Custom GSON based parser for deserialization. */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you document why this is required now?
140c013
to
ec84830
Compare
ππ Thank you for contributing to Looker sdk-codegen (β‘οΈπ£)
Developer Checklist βΉοΈ
Thank you for opening a Pull Request! Before submitting your PR, there are a few things you can do to make sure it goes smoothly:
Fixes #1380 π¦