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:
Ali Beyad 2016-01-11 17:04:20 -05:00
parent b29c416b7c
commit 42134cca4d
4 changed files with 26 additions and 2 deletions

View File

@ -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);

View File

@ -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();
} }

View File

@ -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"));
}
}
} }

View File

@ -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));