-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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
fix for bug: https://github.com/opensearch-project/OpenSearch/issues/… #3665
Conversation
✅ Gradle Check success 469c5b664114d866540dd80deb03235b4739e328 |
Signed-off-by: Jitendra Kumar <jkjitend@amazon.com>
✅ Gradle Check success fdfd6c3021294b7f3858d5a2da71d534f89f9853 |
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.
LGTM, the licensing header update is a must, everything else is up to you
Do we need to do similar/related work in https://github.com/opensearch-project/opensearch-java?
* KIND, either express or implied. See the License for the | ||
* specific language governing permissions and limitations | ||
* under the License. | ||
*/ |
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 new code and doesn't require a license to ElasticSearch, just the SPDX header.
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.
ack will update in next commit
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 need to do similar/related work in https://github.com/opensearch-project/opensearch-java?
from dependency it's also using opensearch-rest-client
https://github.com/opensearch-project/opensearch-java/blob/main/java-client/build.gradle.kts#L131
so it's only require version change
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 check if there's anything else to do, I am not sure.
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 only see dependency not much change required in opensearch-java
apart from it.
client/rest/src/main/java/org/opensearch/client/RestClient.java
Outdated
Show resolved
Hide resolved
client/rest/src/main/java/org/opensearch/client/RestClient.java
Outdated
Show resolved
Hide resolved
client/rest/src/main/java/org/opensearch/client/RestClient.java
Outdated
Show resolved
Hide resolved
client/rest/src/main/java/org/opensearch/client/RestClient.java
Outdated
Show resolved
Hide resolved
client/rest/src/main/java/org/opensearch/client/RestClient.java
Outdated
Show resolved
Hide resolved
@jiten1551 Reading https://stackoverflow.com/questions/5280633/gzip-compression-of-chunked-encoding-response compressed/gzipped content can be sent chunked as well. Are we preventing that with this change? |
|
Signed-off-by: Jitendra Kumar <jkjitend@amazon.com>
try (InputStream is = getContent()) { | ||
size = is.readAllBytes().length; | ||
} catch (IOException ex) { | ||
size = -1L; |
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 other places where we return -1
when we cannot figure out the content length. I would expect an exception, not a negative number causing all kinds of wonderful problems of doing x.size() + content.getContentLength()
.
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 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.
yes that why I think @reta said to return -1.
I don't see any other place where we're doing x.size + content.getContentLength();
or returning -1
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.
It's fine. The interface would have been "unsigned long" if it was meant to be otherwise.
client/rest/src/test/java/org/opensearch/client/RestClientCompressionTests.java
Outdated
Show resolved
Hide resolved
@jiten1551 Meta question. Is this the right fix? We say "a gzip compressing entity doesn't work with chunked encoding with sigv4" - is that a limitation of sigv4? Feels like we're making a change that works around a problem that should be fixed elsewhere. Thus, naively, looking at this code change I'd expect a test that uses sigv4, but fails without this change, so I understand what is being fixed and don't break it in the future. |
we've already tested above change with sigv4 AuthN/AuthZ Opensearch cluster in AWS. not sure this a limitation of sigv4 or not. |
@reta WDYT of my concerns? |
Signed-off-by: Jitendra Kumar <jkjitend@amazon.com>
@dblock 💯 share your concerns, I am trying to find out what causes the signature validation to fail with chunked request (is it AWS [1] specific), but have strong feeling we should not disable chunked transfer by default (this change essentially). [1] https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-streaming.html |
I googled it. Reading https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-streaming.html it says to either (a) explicitly specify the total content length (object length in bytes plus metadata in each chunk), or (b) specify the Transfer-Encoding HTTP header, omitting content length. @jiten1551 have you tried either? It sounds like the code was doing (b), but still didn't work? |
It seems to be 100% sigv4-related (as you mentioned in the issue), but I think we should have considered proper support for chunked + sigv4. Alternatively, we could introduce favor of CompressingEntity without chunking, so users could opt-in for it if necessary but not make it a default. |
existing code is doing (b) that still fails we already tried that but as per https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-streaming.html just tried both (a) and (b) with |
could you please post the code/repro for this somewhere? |
here is the code for repro: https://github.com/jiten1551/Java-Client/tree/master |
@jiten1551 Take a look at kumjiten/Java-Client#1. I set |
Hi @dblock it didn't worked with your changes in Apache Interceptor please see kumjiten/Java-Client#1 |
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 first obvious problem here is that chunkedEnabled
only works for a compressed entity as implemented, setting it to true with compressionEnabled=false
has no effect. Chunked transfer encoding is something supported for non-compressed entities too AFAIK, so this looks misleading. I think you have to implement chunked for non-compressed entities too.
I think the isChunked
and getContentLength
parts are no longer needed I believe as the original Sigv4 problem would be solved by just setting chunked
to false
. But correct me if I'm wrong.
We also need tests that are clearly chunked vs. non-chunked.
@@ -131,6 +131,7 @@ public class RestClient implements Closeable { | |||
private volatile NodeTuple<List<Node>> nodeTuple; | |||
private final WarningsHandler warningsHandler; | |||
private final boolean compressionEnabled; | |||
private final boolean chunkedEnabled; |
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 this should be called chunkedTransferEncodingEnabled
. I know it's a mouthful, but it's the name of the HTTP feature.
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.
ack will update in next commit
@Override | ||
public boolean isChunked() { | ||
return false; | ||
} |
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 no longer always the case. A compressing entity can be both chunked or not chunked.
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.
yes but we require that flag to tell it's a chunked or not and set correct headers
} | ||
|
||
return size; | ||
} |
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 way to get the size of the compressed entity directly without reading all the bytes?
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.
didn't see any method that can gives us that info directly
@dblock I check current implementation of rest-client we see it's using content-length not transfer encoding for non-compressed request.
@dblock no it's will not work only setting chunked to false it will require content-length and incorrect length will fail in server side see https://github.com/apache/httpcomponents-core/blob/master/httpcore5/src/main/java/org/apache/hc/core5/http/protocol/RequestContent.java#L115
@dblock the tests we added with non-chunked and existing tests already using chunked |
Signed-off-by: Jitendra Kumar <jkjitend@amazon.com>
@jiten1551 Thanks for the update and for hanging in here, this look a lot better!
|
@dblock we'll not take chunkedTransferEncoding into picture for now for uncompressed and document that it's not supported, if we through an exception that it's not supported that will break the current behaviour and require modifying existing tests but more important users will have now start getting exception that it's not supported.
@dblock ack will update it.
where it's checking out 2.x branch which didn't have rest client interface change |
Signed-off-by: Jitendra Kumar <jkjitend@amazon.com>
@dblock I tried to add chunk support for non-compressed request but after my change some tests are failing
|
Gradle Check (Jenkins) Run Completed with:
|
I am not more familiar with this code than you are, what have you tried so far to fix this? |
@jiten1551 We do want this feature. Are you still working on this? |
@dblock busy with other tasks actively not working on this one |
As is this PR disables chunked transfer encoding for all compressed requests. However, chunking works just fine, except when used with Sigv4 because we don't know how to generate a correct sigv4 signed payload in that case in the request interceptor. This library knows nothing about Sigv4, so I think we want to only add an option so that the user can do |
|
Finished in #3864 |
Description
Overriding isChunked method from GzipCompressingEntity to false as it didn't worked with SIGV4 AuthN/AuthZ,
to preserve data Overriding getContentLength from GzipCompressingEntity to return content length of gzip entity
which will be added in http header.
Issues Resolved
#3640
Check List
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
For more information on following Developer Certificate of Origin and signing off your commits, please check here.