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

Add http transport #449

Merged
merged 7 commits into from
Oct 12, 2023
Merged

Add http transport #449

merged 7 commits into from
Oct 12, 2023

Conversation

luqasn
Copy link
Contributor

@luqasn luqasn commented Jun 18, 2021

addresses #370

Implementation based on the original thrift http transport with a few changes:

  • apache http client variant removed
    • it was weird to have multiple different implementations in the same class
    • I did not want to introduce an additional dependency
    • okio is already a dependency, so maybe we want to base the transport on that?
  • tried to make the code a bit more kotlin idiomatic and safer

Even though there are no tests yet I wanted to collect some early feedback, especially on okio vs. HTTPUrlConnection. This needs to live in the jvm variant due to the availability of HTTPUrlConnection.

@codecov-commenter
Copy link

Codecov Report

Merging #449 (af78d7d) into master (e218285) will increase coverage by 0.00%.
The diff coverage is n/a.

Impacted file tree graph

@@            Coverage Diff            @@
##             master     #449   +/-   ##
=========================================
  Coverage     59.52%   59.53%           
  Complexity      796      796           
=========================================
  Files            60       60           
  Lines          5534     5535    +1     
  Branches        876      876           
=========================================
+ Hits           3294     3295    +1     
  Misses         1996     1996           
  Partials        244      244           
Impacted Files Coverage Δ
.../com/microsoft/thrifty/kgen/KotlinCodeGenerator.kt 82.35% <0.00%> (+0.01%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update e218285...af78d7d. Read the comment docs.

Copy link
Collaborator

@benjamin-bader benjamin-bader left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a great start - thanks for picking this up! There are a few things I think we could change to make this fit seamlessly in with the rest of the project; noted inline. Also, I'd really like to see some sort of testing here. OkHttp's MockWebServer could be very handy for this, assuming it's still maintained and available (been a few years since I used it).

*
* @see [THRIFT-970](https://issues.apache.org/jira/browse/THRIFT-970)
*/
open class THttpTransport(url: String) : Transport {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's petty, but let's drop the T prefix. It's just ugly to me and, is out-of-step with the rest of the project, and (perhaps most importantly) doesn't deliver any actual information.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For context, the CompactProtocol class specifically is heavily based on TCompactProtocol but even there, the prefix had to go. TType retains its prefix only because Type is taken, and "T for Thrift" actually makes sense there.

*
* @see [THRIFT-970](https://issues.apache.org/jira/browse/THRIFT-970)
*/
open class THttpTransport(url: String) : Transport {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, a substantive comment - can we please make an expect class in src/commonMain/kotlin/com/microsoft/thrifty/transport for this? Then make this one the actual?

Generally on JVM I favor using OkHttp over HttpURLConnection - it's much easier to use correctly and scalably. Is there a reason, aside from the initial implementation using it, to favor HttpURLConnection?

I suppose the fact that it's built in to the JDK is a point in its favor, along with not wanting to bring in extra dependencies. This is part of why I suggested making a separate module for this guy.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What benefit do we get from making it an expect/actual class? Why can't there just be different types of Transports implemented for different variants? This is a genuine question, I have no experience with Kotlin Multiplatform.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, main reason is OOB-ness. I don't want to add something to the runtime that drags in a bunch of transitive dependencies. For that I would prefer the separate module. But I see nothing wrong with providing a basic HttpTransport with maybe not the best performance that needs no dependencies and is this simple as part of the "core" library.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair point re: "OOB-ness". My concern definitely is around the default easy path. Nothing's easier, dependency-wise, than what's built in. On the other hand, this is an Android library first and foremost, and on Android OkHttp is basically the standard anymore. I'm OK with leaving it out for now.

As far as expect/actual, this is the mechanism that lets us have interfaces in common code but have platform-specific implementations. In the eventual iOS release, we'll definitely want to use an HttpTransport. Having an expect class HttpTransport in common code is a prerequisite.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was trying to understand the benefit of the expect over a plain interface for this usecase. We can already have different implementations of the http transport, they would all just implement Transport.

So if I understand correctly, expect just tells you "whatever platform this is ported to also needs to implement this thing", which to me is mainly useful for the "common" library to be able to call platform specific code without having the user pass an implementation to some constructor explicitly (there is always going to be exactly one implementation, no more, no less).
To me, plain old interface still sounds totally fitting to me for this use case. Consider the case that we add an OkHttpClient in a separate library as well. Would that then work with the expect? Or would this now be a "plain" implementation of Transport? If yes, why treat both implementations differently?

Please excuse all the text, I am mainly trying to wrap my head around Kotlin Multiplatform.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right that we could just have platform-specific types that implement Transport. The thing I think lacks there is that we won't have a single HttpTransport. That seems like a miss to me.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I never addressed you question about the benefit(s) of expect class over an interface. The difference is that an expect class is concrete - one can instantiate one as-is, without needing to consider what other type might implement the interface.

@@ -0,0 +1,6 @@
package com.microsoft.thrifty.transport

class TTransportException : Throwable {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tend to think this exception doesn't buy us anything, and would prefer not to include it. We could use the perfectly-good ProtocolException in its stead.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ProtocolException unfortunately does not have the possibility to pass a cause (doesn't have that constructor implemented), and I really don't like wrapping exceptions in a way that loses information.
But I do agree with you that this does not provide much value, so I will go for just not catching and rethrowing these wrapped.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, SGTM.

@luqasn
Copy link
Contributor Author

luqasn commented Jun 22, 2021

This is a great start - thanks for picking this up! There are a few things I think we could change to make this fit seamlessly in with the rest of the project; noted inline. Also, I'd really like to see some sort of testing here. OkHttp's MockWebServer could be very handy for this, assuming it's still maintained and available (been a few years since I used it).

Yes, I am definitely planning to write tests still!

@juequinterore
Copy link

Hi.

I would like to ask, is there any plan to continue with this work?

@luqasn
Copy link
Contributor Author

luqasn commented Oct 8, 2023

Sorry for the late reply. I picked this up again and have integration tests ready, but there are still issues with the plumbing (extension initialization order).
Will try to finish this ASAP.

@juequinterore
Copy link

juequinterore commented Oct 8, 2023 via email

for spinning up a thrift http server for integration testing. The servlet namespace was renamed from javax.servlet to jakarta.servlet so that's why we need the newer version.
…tion

in order to be able to introduce new, http based server for testing as well.
@luqasn
Copy link
Contributor Author

luqasn commented Oct 9, 2023

Long time no see, @benjamin-bader :)

I finally finished the integration tests I promised, could you have a look? Thanks!

@benjamin-bader
Copy link
Collaborator

Hey, glad to see you @luqasn! The test code is pretty substantial - thanks for digging in to it. I don't know why the tests didn't run earlier, given that you've made PRs here before, but I just had to re-approve running the test suite. It failed the license-header check, which I fixed here.

I'm inclined to take this large PR as-is. Thanks very much for all of your hard work on it, and for coming back to finish it!

I might come back and refactor HttpTransport into an expect/actual type, so that we can use this in iOS (we have some rudimentary iOS support now), but that's somewhere off in the future.

@benjamin-bader benjamin-bader merged commit 436e7f2 into microsoft:master Oct 12, 2023
3 checks passed
@benjamin-bader
Copy link
Collaborator

Also fair warning for anyone following this PR - Microsoft has changed the way they handle publishing permissions to Maven Central, but started the tooling migration before Github support was done. This leaves Thrifty temporarily unable to make releases. I hear that in another month or so, this should be fixed, but in the meantime please be patient.

@luqasn
Copy link
Contributor Author

luqasn commented Oct 12, 2023

Thanks for letting us know, I think after those two years one month more is not gonna bother anyone ;)

Anyone in a pinch could also use jitpack.io to get a "prerelease" version of thrifty-runtime. Brilliant service, though I can't vouch for their security. Be mindful of that.

@luqasn luqasn deleted the httptransport branch October 14, 2023 15:16
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.

4 participants