Skip to content
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

Merged
merged 5 commits into from Oct 18, 2023
Merged

Conversation

tjbanghart
Copy link
Member

@tjbanghart tjbanghart commented Oct 13, 2023

πŸ‘‹πŸ‘‹ Thank you for contributing to Looker sdk-codegen (⚑️🍣)

  • πŸ‘† Make sure your pull request title follows Pull Request Title Guidelines from our Contribution guide
  • πŸ‘‰ Don't forget to replace these instructions with your ✨awesome✨ description of what this change actually does. Additionally, it's great to include context on how it works and why the change was needed.
  • πŸ‘‡ Edit "Developer Checklist" to reflect items relevant to this PR (and try to make sure to check everything off before asking for review)

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:

  • Make sure to open an issue as a bug/issue before writing your code! That way we can discuss the change, evaluate designs, and agree on the general idea
  • Ensure the tests and linter pass
  • Appropriate docs were updated (if necessary)

Fixes #1380 πŸ¦•

@tjbanghart tjbanghart force-pushed the tjbanghart/google-java-http branch 2 times, most recently from 3157dc4 to 58c10e0 Compare October 14, 2023 17:59
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"
Copy link
Member Author

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.
Copy link
Member Author

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.

Copy link
Contributor

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.

Copy link
Member Author

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.

Copy link
Contributor

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.

@jkaster
Copy link
Contributor

jkaster commented Oct 14, 2023 via email

@tjbanghart
Copy link
Member Author

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.

@tjbanghart tjbanghart requested review from jkaster and removed request for jkaster October 14, 2023 20:12
@tjbanghart
Copy link
Member Author

Okay, passing smoke tests but one issue with warnings about invalid cookies. I left a comment on the TODO

// 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 =
Copy link
Member Author

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?

Copy link
Contributor

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.

jkaster
jkaster previously approved these changes Oct 17, 2023
Copy link
Contributor

@jkaster jkaster left a 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 {
Copy link
Contributor

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 {
Copy link
Contributor

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. */
Copy link
Contributor

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?

@tjbanghart tjbanghart merged commit 5407e63 into main Oct 18, 2023
11 checks passed
@tjbanghart tjbanghart deleted the tjbanghart/google-java-http branch October 18, 2023 02:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Kotlin: Allow pluggable HTTP clients
2 participants