From eb630e599d5aa02872153a3be8a1e7985824906e Mon Sep 17 00:00:00 2001 From: Przemyslaw Gomulka Date: Fri, 2 Oct 2020 09:17:11 +0200 Subject: [PATCH] Allow passing versioned media types to 7.x server (#63071) 7.x client can pass media type with a version which will return a 7.x version of the api in ES 8. In ES server 7 this media type shoulld be accepted but it serve the same version of the API (7x) relates #61427 --- .../common/xcontent/XContentType.java | 19 +++++++++++++++++++ .../common/xcontent/XContentTypeTests.java | 17 +++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/XContentType.java b/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/XContentType.java index 606284f0462..d058ff76087 100644 --- a/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/XContentType.java +++ b/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/XContentType.java @@ -124,6 +124,8 @@ public enum XContentType { if (mediaType == null) { return null; } + + mediaType = removeVersionInMediaType(mediaType); for (XContentType type : values()) { if (isSameMediaTypeOrFormatAs(mediaType, type)) { return type; @@ -137,6 +139,23 @@ public enum XContentType { return null; } + /** + * Clients compatible with ES 7.x might start sending media types with versioned media type + * in a form of application/vnd.elasticsearch+json;compatible-with=7. + * This has to be removed in order to be used in 7.x server. + * The same client connecting using that media type will be able to communicate with ES 8 thanks to compatible API. + * @param mediaType - a media type used on Content-Type header, might contain versioned media type. + * + * @return a media type string without + */ + private static String removeVersionInMediaType(String mediaType) { + if (mediaType.contains("vnd.elasticsearch")) { + return mediaType.replaceAll("vnd.elasticsearch\\+", "") + .replaceAll("\\s*;\\s*compatible-with=\\d+", ""); + } + return mediaType; + } + /** * Attempts to match the given media type with the known {@link XContentType} values. This match is done in a case-insensitive manner. * The provided media type should not include any parameters. This method is suitable for parsing part of the {@code Content-Type} diff --git a/server/src/test/java/org/elasticsearch/common/xcontent/XContentTypeTests.java b/server/src/test/java/org/elasticsearch/common/xcontent/XContentTypeTests.java index 47a470e2cea..0dc2be69348 100644 --- a/server/src/test/java/org/elasticsearch/common/xcontent/XContentTypeTests.java +++ b/server/src/test/java/org/elasticsearch/common/xcontent/XContentTypeTests.java @@ -26,6 +26,7 @@ import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.nullValue; public class XContentTypeTests extends ESTestCase { + public void testFromJson() throws Exception { String mediaType = "application/json"; XContentType expectedXContentType = XContentType.JSON; @@ -84,4 +85,20 @@ public class XContentTypeTests extends ESTestCase { assertThat(XContentType.fromMediaTypeOrFormat("text/plain"), nullValue()); assertThat(XContentType.fromMediaTypeOrFormat("gobbly;goop"), nullValue()); } + + public void testVersionedMediaType() throws Exception { + assertThat(XContentType.fromMediaTypeOrFormat("application/vnd.elasticsearch+json;compatible-with=7"), + equalTo(XContentType.JSON)); + assertThat(XContentType.fromMediaTypeOrFormat("application/vnd.elasticsearch+yaml;compatible-with=7"), + equalTo(XContentType.YAML)); + assertThat(XContentType.fromMediaTypeOrFormat("application/vnd.elasticsearch+cbor;compatible-with=7"), + equalTo(XContentType.CBOR)); + assertThat(XContentType.fromMediaTypeOrFormat("application/vnd.elasticsearch+smile;compatible-with=7"), + equalTo(XContentType.SMILE)); + + assertThat(XContentType.fromMediaTypeOrFormat("application/vnd.elasticsearch+json ;compatible-with=7"), + equalTo(XContentType.JSON)); + assertThat(XContentType.fromMediaTypeOrFormat("application/vnd.elasticsearch+json ;compatible-with=7;charset=utf-8"), + equalTo(XContentType.JSON)); + } }