Fixes an issue where, if the content type of the request body could not be
determined, the UpdateRequest would still try to parse the content instead of throwing the standard ElasticsearchParseException. This manifests when passing illegal JSON in the request body that does not begin with a '{'. By trying to parse the content from an unknown request body content type, the UpdateRequest was throwing a null pointer exception. This has been fixed to throw an ElasticsearchParseException, to be consistent with the behavior of all other requests in the face of undecipherable request content types. Closes #15822
This commit is contained in:
parent
b29c416b7c
commit
42134cca4d
|
@ -639,8 +639,7 @@ public class UpdateRequest extends InstanceShardOperationRequest<UpdateRequest>
|
||||||
ScriptParameterParser scriptParameterParser = new ScriptParameterParser();
|
ScriptParameterParser scriptParameterParser = new ScriptParameterParser();
|
||||||
Map<String, Object> scriptParams = null;
|
Map<String, Object> scriptParams = null;
|
||||||
Script script = null;
|
Script script = null;
|
||||||
XContentType xContentType = XContentFactory.xContentType(source);
|
try (XContentParser parser = XContentFactory.xContent(source).createParser(source)) {
|
||||||
try (XContentParser parser = XContentFactory.xContent(xContentType).createParser(source)) {
|
|
||||||
XContentParser.Token token = parser.nextToken();
|
XContentParser.Token token = parser.nextToken();
|
||||||
if (token == null) {
|
if (token == null) {
|
||||||
return this;
|
return this;
|
||||||
|
@ -657,10 +656,12 @@ public class UpdateRequest extends InstanceShardOperationRequest<UpdateRequest>
|
||||||
} else if ("scripted_upsert".equals(currentFieldName)) {
|
} else if ("scripted_upsert".equals(currentFieldName)) {
|
||||||
scriptedUpsert = parser.booleanValue();
|
scriptedUpsert = parser.booleanValue();
|
||||||
} else if ("upsert".equals(currentFieldName)) {
|
} else if ("upsert".equals(currentFieldName)) {
|
||||||
|
XContentType xContentType = XContentFactory.xContentType(source);
|
||||||
XContentBuilder builder = XContentFactory.contentBuilder(xContentType);
|
XContentBuilder builder = XContentFactory.contentBuilder(xContentType);
|
||||||
builder.copyCurrentStructure(parser);
|
builder.copyCurrentStructure(parser);
|
||||||
safeUpsertRequest().source(builder);
|
safeUpsertRequest().source(builder);
|
||||||
} else if ("doc".equals(currentFieldName)) {
|
} else if ("doc".equals(currentFieldName)) {
|
||||||
|
XContentType xContentType = XContentFactory.xContentType(source);
|
||||||
XContentBuilder docBuilder = XContentFactory.contentBuilder(xContentType);
|
XContentBuilder docBuilder = XContentFactory.contentBuilder(xContentType);
|
||||||
docBuilder.copyCurrentStructure(parser);
|
docBuilder.copyCurrentStructure(parser);
|
||||||
safeDoc().source(docBuilder);
|
safeDoc().source(docBuilder);
|
||||||
|
|
|
@ -133,6 +133,9 @@ public class XContentFactory {
|
||||||
* Returns the {@link org.elasticsearch.common.xcontent.XContent} for the provided content type.
|
* Returns the {@link org.elasticsearch.common.xcontent.XContent} for the provided content type.
|
||||||
*/
|
*/
|
||||||
public static XContent xContent(XContentType type) {
|
public static XContent xContent(XContentType type) {
|
||||||
|
if (type == null) {
|
||||||
|
throw new IllegalArgumentException("Cannot get xcontent for unknown type");
|
||||||
|
}
|
||||||
return type.xContent();
|
return type.xContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
package org.elasticsearch.action.update;
|
package org.elasticsearch.action.update;
|
||||||
|
|
||||||
|
import org.elasticsearch.ElasticsearchParseException;
|
||||||
import org.elasticsearch.Version;
|
import org.elasticsearch.Version;
|
||||||
import org.elasticsearch.action.index.IndexRequest;
|
import org.elasticsearch.action.index.IndexRequest;
|
||||||
import org.elasticsearch.common.io.stream.Streamable;
|
import org.elasticsearch.common.io.stream.Streamable;
|
||||||
|
@ -166,4 +167,15 @@ public class UpdateRequestTests extends ESTestCase {
|
||||||
indexAction = (IndexRequest) action;
|
indexAction = (IndexRequest) action;
|
||||||
assertThat(indexAction.ttl(), is(providedTTLValue));
|
assertThat(indexAction.ttl(), is(providedTTLValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Related to issue #15822
|
||||||
|
public void testInvalidBodyThrowsParseException() throws Exception {
|
||||||
|
UpdateRequest request = new UpdateRequest("test", "type", "1");
|
||||||
|
try {
|
||||||
|
request.source(new byte[] { (byte) '"' });
|
||||||
|
fail("Should have thrown a ElasticsearchParseException");
|
||||||
|
} catch (ElasticsearchParseException e) {
|
||||||
|
assertThat(e.getMessage(), equalTo("Failed to derive xcontent"));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,6 +97,14 @@ public class XContentFactoryTests extends ESTestCase {
|
||||||
assertNull(XContentFactory.xContentType(is));
|
assertNull(XContentFactory.xContentType(is));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testInvalidStream() throws Exception {
|
||||||
|
byte[] bytes = new byte[] { (byte) '"' };
|
||||||
|
assertNull(XContentFactory.xContentType(bytes));
|
||||||
|
|
||||||
|
bytes = new byte[] { (byte) 'x' };
|
||||||
|
assertNull(XContentFactory.xContentType(bytes));
|
||||||
|
}
|
||||||
|
|
||||||
public void testJsonFromBytesOptionallyPrecededByUtf8Bom() throws Exception {
|
public void testJsonFromBytesOptionallyPrecededByUtf8Bom() throws Exception {
|
||||||
byte[] bytes = new byte[] {(byte) '{', (byte) '}'};
|
byte[] bytes = new byte[] {(byte) '{', (byte) '}'};
|
||||||
assertThat(XContentFactory.xContentType(bytes), equalTo(XContentType.JSON));
|
assertThat(XContentFactory.xContentType(bytes), equalTo(XContentType.JSON));
|
||||||
|
|
Loading…
Reference in New Issue