-
Notifications
You must be signed in to change notification settings - Fork 983
Replace the old InputStreamFactory registries with the new Decoder / Encoder pipeline #660
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
Replace the old InputStreamFactory registries with the new Decoder / Encoder pipeline #660
Conversation
| * {@link org.apache.hc.core5.http.io.entity.HttpEntityWrapper} responsible for | ||
| * handling br Content Coded responses. | ||
| * | ||
| * @deprecated Use Decoder API |
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 think it best to use '@link' in '@deprecated' comments. It makes it much easier to follow the bouncing ball 😉
| /** | ||
| * Factory for decorated {@link InputStream}s. | ||
| * | ||
| * @deprecated |
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 comment with an '@link' is missing, which happens in many places in the PR.
| * @since 5.6 | ||
| */ | ||
| @FunctionalInterface | ||
| public interface Encoder { |
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 could reuse or extend UnaryOperator instead of inventing our own.
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.
Prefer a dedicated Encoder over UnaryOperator – the name conveys intent and leaves room for HTTP-specific defaults later. Keeps symmetry with Decoder and avoids leaking java.util.function into the public API.
| /** | ||
| * Custom decoders keyed by {@link ContentCoding}. | ||
| * | ||
| * @since 5.6 |
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 don't need '@SInCE' tags for private code.
3915567 to
d0ed410
Compare
|
Added a terse Javadoc note that points users to the new Decoder/Encoder API. |
| * @since 5.6 | ||
| */ | ||
| @FunctionalInterface | ||
| public interface Decoder { |
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.
@arturobernalg Should not Decoder be working the same was as Encoder and unwrap HttpEntity?
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.
@ok2c Decoder only swaps the input stream—DecompressingEntity already wraps the HttpEntity—so returning an InputStream keeps the API minimal and avoids duplicating header-handling logic.
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.
@arturobernalg to me it is more important for the API to be logically consistent than saving a few lines of header handling code that will likely get optimized out by the compiler. In my opinion The Encoder / Decoder interfaces should work either with InputStream / OutputStream or with HttpEntity, but not with a mix. Feel free to leave it as is and merge the change-set but I will likely try to normalize the APIs later.
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.
@ok2c please do another pass.
| /** | ||
| * Returns the {@link Codec} (or {@code null}). | ||
| */ | ||
| public static Codec codec(final ContentCoding coding) { |
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.
@arturobernalg Here we have a scope violation: a public method exposing a package private class. Either make the method package private or make the class public. It is internal anyway.
| * @since 5.6 | ||
| */ | ||
| @FunctionalInterface | ||
| public interface Decoder { |
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.
@arturobernalg to me it is more important for the API to be logically consistent than saving a few lines of header handling code that will likely get optimized out by the compiler. In my opinion The Encoder / Decoder interfaces should work either with InputStream / OutputStream or with HttpEntity, but not with a mix. Feel free to leave it as is and merge the change-set but I will likely try to normalize the APIs later.
| * @throws IOException if the decoding entity cannot be created or an | ||
| * underlying I/O error occurs | ||
| */ | ||
| HttpEntity wrap(HttpEntity src) throws IOException; |
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.
@arturobernalg I think this method does not need to throw IOException. At least it does not appear to be thrown anywhere in the existing code.
I also agree with @garydgregory here. I think we could just use standard Function here, but this is a matter of taste so I will not object.
Looks good otherwise.
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.
HI @ok2c please do another pass. Now I'm using java functions instead.
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.
HI @ok2c please do another pass. Now I'm using java functions instead.
@arturobernalg Oh, man. I meant something different. I think IOFunction was fine. It makes sense to have a function that throws IOException. What I meant the Decoder and Encoder could be just UnaryOperator or Function as suggested by @garydgregory
c591d1e to
24ac6ca
Compare
ok2c
left a comment
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.
@arturobernalg I would prefer to have IOFunction restored and Encoder and Decoder replaced but this is more of a matter of taste. You can keep them if you strongly prefer it
8c31bf1 to
474c669
Compare
@ok2c i just
HI @ok2c i just implement the |
|
If I hear no complaints or no feedback within 1 day I will merge the PR as is. |
|
|
||
| import java.io.IOException; | ||
|
|
||
| import org.conscrypt.Internal; |
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.
This is the wrong @Internal import. You want org.apache.hc.core5.annotation.Internal.
| return decoder.apply(super.getContent()); | ||
| } | ||
|
|
||
| InputStream local = cached; |
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.
Do we actually need DCL here? writeTo isn't thread-safe or idempotent, so under what scenarios do we expect getContent() to be called from multiple threads?
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.
DCL is a cheap guard against accidental multi-thread reuse of the same entity instance, ensuring we don’t create two competing decoder streams.
d1a6b23 to
2987731
Compare
…Encoder pipeline. Adds ContentCodecRegistry, rewrites DecompressingEntity, updates HttpClient internals and tests, deprecates legacy helpers, and keeps backward compatibility.
…ic Encoder/Decoder API, introduce IOFunction and ContentCodecRegistry, update DecompressingEntity and all tests accordingly.
2987731 to
d4cc112
Compare
| private Lookup<AuthSchemeFactory> authSchemeRegistry; | ||
| private Lookup<CookieSpecFactory> cookieSpecRegistry; | ||
| @Deprecated | ||
| private LinkedHashMap<String, InputStreamFactory> contentDecoderMap; |
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.
@arturobernalg I found an issue with this change-set that is easily fixable.
At the moment the contentDecoderMap variable is essentially write-only. There is a non-deprecated setter for it but it is not being read anywhere. That is wrong.
What needs to be done is this: contentDecoderMap must be removed, the #setContentDecoderRegistry setter must be changed to populate contentDecoder through an adaptor (see DefaultHttpClientConnectionOperator for an example ) and the #setContentDecoderRegistry must be deprecated.
contentDecoder also sounds like a rather bad choice of a name for what is essentially a map of objects
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.
On it
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.
@arturobernalg I found an issue with this change-set that is easily fixable.
At the moment the
contentDecoderMapvariable is essentially write-only. There is a non-deprecated setter for it but it is not being read anywhere. That is wrong.What needs to be done is this:
contentDecoderMapmust be removed, the#setContentDecoderRegistrysetter must be changed to populatecontentDecoderthrough an adaptor (seeDefaultHttpClientConnectionOperatorfor an example ) and the#setContentDecoderRegistrymust be deprecated.
contentDecoderalso sounds like a rather bad choice of a name for what is essentially a map of objects
This change swaps out the legacy compression infrastructure for the new decoder / encoder model introduced in 5.6. The codebase now routes all (de)compression through
ContentCodecRegistry, uses functional interfaces instead ofInputStreamFactory, and updates tests and docs accordingly while preserving existing public classes as deprecated shims. Everything builds and the full test suite passes.