Skip to content
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

Forbid direct usage of ContentType.create() methods #26457

Merged
merged 2 commits into from
Sep 6, 2017

Conversation

tlrx
Copy link
Member

@tlrx tlrx commented Aug 31, 2017

It's easy to create a wrong Content-Type header when converting a XContentType to a Apache HTTP ContentType instance.

We sometimes did it in the high level client, where we use

ContentType.create(XContentType.JSON.mediaType())

instead of

ContentType.create(XContentType.JSON.mediaTypeWithoutParameters())

But the create(String) method expects a valid MIME type to be passed, and not a value that includes something else like a charset parameter. With XContentType.JSON, the first one builds a Content-Type: application/json; charset=UTF-8 header and the second a Content-Type: application/json. There are both accepted by Elasticsearch because charsets are silently ignored (see #22769). But a new check was added in Apache HTTP Core version 4.4.6 (see #26438 (comment)) and that will just throw IAE. Some users already ran into this issue.

So this pull request forbids the direct usages of ContentType.create() methods in favor of a Request.createContentType(XContentType) method that does the right thing.

Copy link
Member

@cbuescher cbuescher left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, I left one question about the use of the null-Charset argument, maybe you can comment or change that.

*/
@SuppressForbidden(reason = "Only allowed place to convert a XContentType to a ContentType")
static ContentType createContentType(final XContentType xContentType) {
return ContentType.create(xContentType.mediaTypeWithoutParameters(), (Charset) null);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason why you didn't use UTF8 here? Glossing over #22769 I thought we might make this a requirement at some point in the future, but maybe I got that wrong.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't want to force a charset because Elasticsearch exposes many ways to set the source of, let's say, an IndexRequest. It can be a Map converted by Jackson as UTF-8 bytes, but it can also be raw bytes too... And Elasticsearch will rely on Jackson auto-detect encoding to parse this correctly.

I think there are many things to dig here and in the meanwhile setting a null charset allows to keep the current behavior.

@@ -139,8 +141,8 @@ static Request bulk(BulkRequest bulkRequest) throws IOException {
bulkContentType = XContentType.JSON;
}

byte separator = bulkContentType.xContent().streamSeparator();
ContentType requestContentType = ContentType.create(bulkContentType.mediaType());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As a side note, I wonder how useful XContentType.mediaType() still is, except for JSON it redirects to mediaTypeWithoutParameters(). Maybe worth investigating if we can get rid of it in another issue.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree - I'm currently looking at this.

Copy link
Member

@cbuescher cbuescher Aug 31, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would mix it with this PR though.

@tlrx tlrx merged commit ad355f3 into elastic:master Sep 6, 2017
tlrx added a commit that referenced this pull request Sep 6, 2017
It's easy to create a wrong Content-Type header when converting a 
XContentType to a Apache HTTP ContentType instance.

This commit the direct usages of ContentType.create() methods in favor of a Request.createContentType(XContentType) method that does the right thing.

Closes #26438
tlrx added a commit that referenced this pull request Sep 6, 2017
It's easy to create a wrong Content-Type header when converting a 
XContentType to a Apache HTTP ContentType instance.

This commit the direct usages of ContentType.create() methods in favor of a Request.createContentType(XContentType) method that does the right thing.

Closes #26438
tlrx added a commit that referenced this pull request Sep 6, 2017
It's easy to create a wrong Content-Type header when converting a
XContentType to a Apache HTTP ContentType instance.

This commit the direct usages of ContentType.create() methods in favor
of a Request.createContentType(XContentType) method that does the right thing.

Closes #26438
@tlrx tlrx deleted the rest-high-level-content-type branch September 6, 2017 08:22
@tlrx
Copy link
Member Author

tlrx commented Sep 6, 2017

Thanks @cbuescher !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants