-
Notifications
You must be signed in to change notification settings - Fork 24.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
Fixed NPEs caused by requests without content. #23497
Conversation
Since this is a community submitted pull request, a Jenkins build has not been kicked off automatically. Can an Elastic organization member please verify the contents of this patch and then kick off a build manually? |
@jaymode Do you mind taking a look at this? I noticed you made some changes recently related to content type in #23146. I'm not sure this is the best solution; seems like there should be better way to reject requests at a higher level when there is no content (but it's required). Thanks! Also I did not add tests for the missing content scenarios. Should this be tested with the REST tests or Java integration tests? |
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 left one comment, but it applies throughout the change. Additionally, I think that REST tests need to be added for all of these changes.
if(request.hasContent()) { | ||
bulkRequest.add(request.content(), defaultIndex, defaultType, defaultRouting, defaultFields, | ||
defaultFetchSourceContext, defaultPipeline, null, allowExplicitIndex, request.getXContentType()); | ||
} | ||
|
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 don't understand this change? I think that we should still blow up here, just not with an NPE? This comment applies elsewhere in this pull request.
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 followed the pattern used in a few other places. e.g. RestCreateIndexAction#L44-L46.
Instead of failing in RestHandler.prepareRequest
a validation exception will be thrown from ActionRequest.validate()
if request content is missing but required.
Would an approach similar to RestDeleteByQueryAction.java#L51-L53 be better for cases when request content is required?
I agree. This change may get larger but it would be great to have a general purpose way to do this. Thinking out loud:
I think all of these options have flaws, but hopefully this helps generate some other ideas about how to handle this. |
@jaymode I like your first suggestion:
If content is required this method will be called like it was before this PR and throw an exception if content is missing. Let me know if that sounds good to you and I'll revert the changes in this PR and update the While I was looking at the code I noticed
Should the requests that use this method fail earlier (while parsing) as well? |
@qwerty4030 I apologize for the delay here.
This sounds good to me.
I think we should probably try to get rid of this behavior and just rely on the behavior you described above (throw exception if content is missing). |
1ceb605
to
9ba0fcc
Compare
@jaymode Pushed new changes. I had to create a new I was unable to add REST tests because the internal test runner validates the request using the api spec, which requires a body for these requests. Should I look into adding some kind of override or try adding integration/unit tests instread? Thanks! |
This sounds like a good scenario for an |
@jasontedor Looks like I spoke too soon. I discovered that you can do a
Would you prefer that? Another idea I had was to somehow use the REST API spec to automatically test all requests that require a body. |
The REST tests (the YAML-based ones) are preferred because then the other language clients benefit from them too.
I'd rather that we not get fancy here, there are other consumers of the REST tests. |
@jasontedor Pushed updates to the REST tests and cleaned up some |
@@ -300,10 +300,16 @@ public BulkRequest add(BytesReference data, @Nullable String defaultIndex, @Null | |||
if (token == null) { | |||
continue; | |||
} | |||
assert token == XContentParser.Token.START_OBJECT; | |||
if(token != XContentParser.Token.START_OBJECT) { |
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.
Please use a space between the if
and (
. Also, I think it would be good to use XContentParserUtils#ensureExpectedToken
or XContentParserUtils#ensureFieldName
// Move to FIELD_NAME, that's the action | ||
token = parser.nextToken(); | ||
assert token == XContentParser.Token.FIELD_NAME; | ||
if(token != XContentParser.Token.FIELD_NAME) { |
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 would be good to use XContentParserUtils#ensureExpectedToken
or XContentParserUtils#ensureFieldName
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 tried to use these methods but the ParsingException
they throw has the wrong line number due to BulkRequest#add
creating a new XContentParser
for each action.
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 potential fix it to catch the ParsingException
and rethrow a new ParsingException
with the correct line number.
* @return content of the request body or throw an exception if the body or content type is missing | ||
*/ | ||
public final BytesReference requiredContent() { | ||
if(hasContent() == 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.
space between if
and (
} | ||
return new Tuple<>(xContentType, bytes); | ||
if (source == null || typeParam == null) { | ||
throw new IllegalStateException("source and source_content_type param required"); |
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.
Change "param required" to "parameters are required"
IOUtils.close(searchRequestParser); | ||
} | ||
}); | ||
XContentParser parser = restRequest.contentOrSourceParamParser(); |
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.
use a try-with resources for the parser value
} | ||
}); | ||
XContentParser parser = restRequest.contentOrSourceParamParser(); | ||
parser = extractRequestSpecificFieldsAndReturnSearchCompatibleParser(parser, bodyConsumers); |
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.
use a different variable
@jaymode Pushed changes to address all your comments except the one about using |
@jasontedor @jaymode Hey guys, are there any other changes you would like me to make? Thanks. |
This branch is not up to date with master, can you merge it in and resolve conflicts? Also @jaymode is on vacation this week, and we are going to need his eyes on this next week before it can be pulled. |
Sounds good. I'll merge master a bit later this week to catch any future conflicts. |
@@ -83,6 +83,9 @@ protected void parseInternalRequest(Request internal, RestRequest restRequest, | |||
*/ | |||
private XContentParser extractRequestSpecificFields(RestRequest restRequest, | |||
Map<String, Consumer<Object>> bodyConsumers) throws IOException { | |||
if(restRequest.hasContentOrSourceParam() == 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.
Jumped the gun on cleaning up this class: turns out that update_by_query
allows an empty body so we need to make sure this method does not throw an exception if the request body or source param is missing.
Merged master and disabled the new REST tests for BWC tests. |
@jaymode Let me know when you'll have time to take another look. Thanks. |
Merged latest master to resolve conflicts and ran |
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.
left two style comments, but otherwise I think this is ready to get in after fixing those and merging master again. @jasontedor do you want to take another look as well?
return parser; | ||
private XContentParser extractRequestSpecificFields(RestRequest restRequest, | ||
Map<String, Consumer<Object>> bodyConsumers) throws IOException { | ||
if(restRequest.hasContentOrSourceParam() == 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.
can you add a space between the if
and (
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.
done in 08d1749
String emptyObject = "{}\r\n"; | ||
StringBuilder bulk = new StringBuilder(); | ||
int emptyLine; | ||
if(randomBoolean()) { |
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.
space between if
and (
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.
done in 08d1749
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.
Pushed 4ad47d2 for 5.x |
@jaymode Thanks for the review. Question: do we need to do something different for backport REST tests because they should pass for latest 5.X, but not for versions <= 5.4? |
@qwerty4030 I took care of it during the backport by changing the skip version to |
This updates the missing body tests to run against versions >= 5.5.0 after backporting the change to the 5.x branch. See #23497
* master: Add support for clear scroll to high level REST client (elastic#25038) Tiny correction in inner-hits.asciidoc (elastic#25066) Added release notes for 6.0.0-alpha2 Expand index expressions against indices only when managing aliases (elastic#23997) Collapse inner hits rest test should not skip 5.x Settings: Fix secure settings by prefix (elastic#25064) add `exclude_keys` option to KeyValueProcessor (elastic#24876) Test: update missing body tests to run against versions >= 5.5.0 Track EWMA[1] of task execution time in search threadpool executor Removes an invalid assert in resizing big arrays which does not always hold (resizing can result in a smaller size than the current size, while the assert attempted to verify the new size is always greater than the current). Fixed NPEs caused by requests without content. (elastic#23497) Plugins can register pre-configured char filters (elastic#25000) Build: Allow preserving shared dir (elastic#24962) Tests: Make secure settings available from settings builder for tests (elastic#25037)
* master: (1210 commits) Add support for clear scroll to high level REST client (elastic#25038) Tiny correction in inner-hits.asciidoc (elastic#25066) Added release notes for 6.0.0-alpha2 Expand index expressions against indices only when managing aliases (elastic#23997) Collapse inner hits rest test should not skip 5.x Settings: Fix secure settings by prefix (elastic#25064) add `exclude_keys` option to KeyValueProcessor (elastic#24876) Test: update missing body tests to run against versions >= 5.5.0 Track EWMA[1] of task execution time in search threadpool executor Removes an invalid assert in resizing big arrays which does not always hold (resizing can result in a smaller size than the current size, while the assert attempted to verify the new size is always greater than the current). Fixed NPEs caused by requests without content. (elastic#23497) Plugins can register pre-configured char filters (elastic#25000) Build: Allow preserving shared dir (elastic#24962) Tests: Make secure settings available from settings builder for tests (elastic#25037) [TEST] Skip wildcard expansion test due to breaking change Test that gradle and Java version types match (elastic#24943) Include duplicate jar when jarhell check fails Change ScriptContexts to use needs instead of uses$. (elastic#25036) Change `has_child`, `has_parent` queries and `childen` aggregation to work with the new join field type and at the same time maintaining support for the `_parent` meta field type. Remove comma-separated feature parsing for GetIndicesAction ...
* master: (619 commits) Add support for clear scroll to high level REST client (elastic#25038) Tiny correction in inner-hits.asciidoc (elastic#25066) Added release notes for 6.0.0-alpha2 Expand index expressions against indices only when managing aliases (elastic#23997) Collapse inner hits rest test should not skip 5.x Settings: Fix secure settings by prefix (elastic#25064) add `exclude_keys` option to KeyValueProcessor (elastic#24876) Test: update missing body tests to run against versions >= 5.5.0 Track EWMA[1] of task execution time in search threadpool executor Removes an invalid assert in resizing big arrays which does not always hold (resizing can result in a smaller size than the current size, while the assert attempted to verify the new size is always greater than the current). Fixed NPEs caused by requests without content. (elastic#23497) Plugins can register pre-configured char filters (elastic#25000) Build: Allow preserving shared dir (elastic#24962) Tests: Make secure settings available from settings builder for tests (elastic#25037) [TEST] Skip wildcard expansion test due to breaking change Test that gradle and Java version types match (elastic#24943) Include duplicate jar when jarhell check fails Change ScriptContexts to use needs instead of uses$. (elastic#25036) Change `has_child`, `has_parent` queries and `childen` aggregation to work with the new join field type and at the same time maintaining support for the `_parent` meta field type. Remove comma-separated feature parsing for GetIndicesAction ...
Raw requests are supported only by the java yaml test runner and were introduced to test docs snippets. Some yaml tests ended up using them (see elastic#23497) which causes failures for other language clients. This commit migrates those yaml tests to Java tests that send requests through the Java low-level REST client, and also moves the ability to send raw requests to a special client that's only available when testing docs snippets. Closes elastic#25694
Raw requests are supported only by the java yaml test runner and were introduced to test docs snippets. Some yaml tests ended up using them (see #23497) which causes failures for other language clients. This commit migrates those yaml tests to Java tests that send requests through the Java low-level REST client, and also moves the ability to send raw requests to a special client that's only available when testing docs snippets. Closes #25694
Raw requests are supported only by the java yaml test runner and were introduced to test docs snippets. Some yaml tests ended up using them (see #23497) which causes failures for other language clients. This commit migrates those yaml tests to Java tests that send requests through the Java low-level REST client, and also moves the ability to send raw requests to a special client that's only available when testing docs snippets. Closes #25694
Raw requests are supported only by the java yaml test runner and were introduced to test docs snippets. Some yaml tests ended up using them (see #23497) which causes failures for other language clients. This commit migrates those yaml tests to Java tests that send requests through the Java low-level REST client, and also moves the ability to send raw requests to a special client that's only available when testing docs snippets. Closes #25694
Raw requests are supported only by the java yaml test runner and were introduced to test docs snippets. Some yaml tests ended up using them (see #23497) which causes failures for other language clients. This commit migrates those yaml tests to Java tests that send requests through the Java low-level REST client, and also moves the ability to send raw requests to a special client that's only available when testing docs snippets. Closes #25694
Raw requests are supported only by the java yaml test runner and were introduced to test docs snippets. Some yaml tests ended up using them (see #23497) which causes failures for other language clients. This commit migrates those yaml tests to Java tests that send requests through the Java low-level REST client, and also moves the ability to send raw requests to a special client that's only available when testing docs snippets. Closes #25694
Fixed NPEs caused by requests without content.
REST handlers that require a body will throw an an
ElasticsearchParseException
"request body required".REST handlers that require a body OR source param will throw an
ElasticsearchParseException
"request body or source parameter is required".Replaced asserts in
BulkRequest
parsing code with a more descriptiveIllegalArgumentException
if the line contains an empty object.Before this fix all the following requests threw confusing exceptions:
After this fix, requests that require a body will throw this exception:
After this fix, requests require a body or
source
param:Fixed confusing
_bulk
response:Closes #24701