[Refactor] XContentType to parse Accept or Content-Type headers (#3077)

Refactors XContentType.fromMediaTypeOrFormat to fromMediaType so Accept headers
and Content-Type headers can be parsed separately. This helps in reusing the
same parse logic in for REST Versioning API support.

Signed-off-by: Nicholas Walter Knize <nknize@apache.org>
This commit is contained in:
Nick Knize 2022-04-28 09:58:26 -05:00 committed by GitHub
parent da8077de44
commit d86c88fe59
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 391 additions and 97 deletions

View File

@ -2073,7 +2073,7 @@ public class RestHighLevelClient implements Closeable {
if (entity.getContentType() == null) {
throw new IllegalStateException("OpenSearch didn't return the [Content-Type] header, unable to parse response body");
}
XContentType xContentType = XContentType.fromMediaTypeOrFormat(entity.getContentType().getValue());
XContentType xContentType = XContentType.fromMediaType(entity.getContentType().getValue());
if (xContentType == null) {
throw new IllegalStateException("Unsupported Content-Type: " + entity.getContentType().getValue());
}

View File

@ -806,7 +806,7 @@ public class RequestConvertersTests extends OpenSearchTestCase {
UpdateRequest parsedUpdateRequest = new UpdateRequest();
XContentType entityContentType = XContentType.fromMediaTypeOrFormat(entity.getContentType().getValue());
XContentType entityContentType = XContentType.fromMediaType(entity.getContentType().getValue());
try (XContentParser parser = createParser(entityContentType.xContent(), entity.getContent())) {
parsedUpdateRequest.fromXContent(parser);
}

View File

@ -0,0 +1,65 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* The OpenSearch Contributors require contributions made to
* this file be licensed under the Apache-2.0 license or a
* compatible open source license.
*/
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/*
* Modifications Copyright OpenSearch Contributors. See
* GitHub history for details.
*/
package org.opensearch.common.xcontent;
/**
* Abstracts a <a href="http://en.wikipedia.org/wiki/Internet_media_type">Media Type</a> and a format parameter.
* Media types are used as values on Content-Type and Accept headers
* format is an URL parameter, specifies response media type.
*/
public interface MediaType {
/**
* Returns a type part of a MediaType
* i.e. application for application/json
*/
String type();
/**
* Returns a subtype part of a MediaType.
* i.e. json for application/json
*/
String subtype();
/**
* Returns a corresponding format for a MediaType. i.e. json for application/json media type
* Can differ from the MediaType's subtype i.e plain/text has a subtype of text but format is txt
*/
String format();
/**
* returns a string representation of a media type.
*/
default String typeWithSubtype() {
return type() + "/" + subtype();
}
}

View File

@ -0,0 +1,135 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* The OpenSearch Contributors require contributions made to
* this file be licensed under the Apache-2.0 license or a
* compatible open source license.
*/
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/*
* Modifications Copyright OpenSearch Contributors. See
* GitHub history for details.
*/
package org.opensearch.common.xcontent;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
public class MediaTypeParser<T extends MediaType> {
private final Map<String, T> formatToMediaType;
private final Map<String, T> typeWithSubtypeToMediaType;
public MediaTypeParser(T[] acceptedMediaTypes) {
this(acceptedMediaTypes, Map.of());
}
public MediaTypeParser(T[] acceptedMediaTypes, Map<String, T> additionalMediaTypes) {
final int size = acceptedMediaTypes.length + additionalMediaTypes.size();
Map<String, T> formatMap = new HashMap<>(size);
Map<String, T> typeMap = new HashMap<>(size);
for (T mediaType : acceptedMediaTypes) {
typeMap.put(mediaType.typeWithSubtype(), mediaType);
formatMap.put(mediaType.format(), mediaType);
}
for (Map.Entry<String, T> entry : additionalMediaTypes.entrySet()) {
String typeWithSubtype = entry.getKey();
T mediaType = entry.getValue();
typeMap.put(typeWithSubtype.toLowerCase(Locale.ROOT), mediaType);
formatMap.put(mediaType.format(), mediaType);
}
this.formatToMediaType = Map.copyOf(formatMap);
this.typeWithSubtypeToMediaType = Map.copyOf(typeMap);
}
public T fromMediaType(String mediaType) {
ParsedMediaType parsedMediaType = parseMediaType(mediaType);
return parsedMediaType != null ? parsedMediaType.getMediaType() : null;
}
public T fromFormat(String format) {
if (format == null) {
return null;
}
return formatToMediaType.get(format.toLowerCase(Locale.ROOT));
}
/**
* parsing media type that follows https://tools.ietf.org/html/rfc7231#section-3.1.1.1
* @param headerValue a header value from Accept or Content-Type
* @return a parsed media-type
*/
public ParsedMediaType parseMediaType(String headerValue) {
if (headerValue != null) {
String[] split = headerValue.toLowerCase(Locale.ROOT).split(";");
String[] typeSubtype = split[0].trim().split("/");
if (typeSubtype.length == 2) {
String type = typeSubtype[0];
String subtype = typeSubtype[1];
T xContentType = typeWithSubtypeToMediaType.get(type + "/" + subtype);
if (xContentType != null) {
Map<String, String> parameters = new HashMap<>();
for (int i = 1; i < split.length; i++) {
// spaces are allowed between parameters, but not between '=' sign
String[] keyValueParam = split[i].trim().split("=");
if (keyValueParam.length != 2 || hasSpaces(keyValueParam[0]) || hasSpaces(keyValueParam[1])) {
return null;
}
parameters.put(keyValueParam[0], keyValueParam[1]);
}
return new ParsedMediaType(xContentType, parameters);
}
}
}
return null;
}
private boolean hasSpaces(String s) {
return s.trim().equals(s) == false;
}
/**
* A media type object that contains all the information provided on a Content-Type or Accept header
*/
public class ParsedMediaType {
private final Map<String, String> parameters;
private final T mediaType;
public ParsedMediaType(T mediaType, Map<String, String> parameters) {
this.parameters = parameters;
this.mediaType = mediaType;
}
public T getMediaType() {
return mediaType;
}
public Map<String, String> getParameters() {
return parameters;
}
}
}

View File

@ -38,12 +38,12 @@ import org.opensearch.common.xcontent.smile.SmileXContent;
import org.opensearch.common.xcontent.yaml.YamlXContent;
import java.util.Locale;
import java.util.Objects;
import java.util.Map;
/**
* The content type of {@link org.opensearch.common.xcontent.XContent}.
*/
public enum XContentType {
public enum XContentType implements MediaType {
/**
* A JSON based content type.
@ -60,7 +60,7 @@ public enum XContentType {
}
@Override
public String shortName() {
public String subtype() {
return "json";
}
@ -79,7 +79,7 @@ public enum XContentType {
}
@Override
public String shortName() {
public String subtype() {
return "smile";
}
@ -98,7 +98,7 @@ public enum XContentType {
}
@Override
public String shortName() {
public String subtype() {
return "yaml";
}
@ -117,7 +117,7 @@ public enum XContentType {
}
@Override
public String shortName() {
public String subtype() {
return "cbor";
}
@ -127,34 +127,42 @@ public enum XContentType {
}
};
/** a parser of media types */
private static final MediaTypeParser<XContentType> MEDIA_TYPE_PARSER = new MediaTypeParser<>(
XContentType.values(),
Map.of("application/*", JSON, "application/x-ndjson", JSON)
);
/** gets the {@link MediaTypeParser} singleton for use outside class */
@SuppressWarnings("rawtypes")
public static MediaTypeParser getMediaTypeParser() {
return MEDIA_TYPE_PARSER;
}
/**
* Accepts either a format string, which is equivalent to {@link XContentType#shortName()} or a media type that optionally has
* parameters and attempts to match the value to an {@link XContentType}. The comparisons are done in lower case format and this method
* also supports a wildcard accept for {@code application/*}. This method can be used to parse the {@code Accept} HTTP header or a
* format query string parameter. This method will return {@code null} if no match is found
* Accepts a format string, which is most of the time is equivalent to {@link XContentType#subtype()}
* and attempts to match the value to an {@link XContentType}.
* The comparisons are done in lower case format.
* This method will return {@code null} if no match is found
*/
public static XContentType fromMediaTypeOrFormat(String mediaType) {
if (mediaType == null) {
return null;
}
public static XContentType fromFormat(String mediaType) {
return MEDIA_TYPE_PARSER.fromFormat(mediaType);
}
mediaType = removeVersionInMediaType(mediaType);
for (XContentType type : values()) {
if (isSameMediaTypeOrFormatAs(mediaType, type)) {
return type;
}
}
final String lowercaseMediaType = mediaType.toLowerCase(Locale.ROOT);
if (lowercaseMediaType.startsWith("application/*")) {
return JSON;
}
return null;
/**
* 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 can optionally has parameters.
* This method is suitable for parsing of the {@code Content-Type} and {@code Accept} HTTP headers.
* This method will return {@code null} if no match is found
*/
public static XContentType fromMediaType(String mediaTypeHeaderValue) {
mediaTypeHeaderValue = removeVersionInMediaType(mediaTypeHeaderValue);
return MEDIA_TYPE_PARSER.fromMediaType(mediaTypeHeaderValue);
}
/**
* Clients compatible with ES 7.x might start sending media types with versioned media type
* in a form of application/vnd.opensearch+json;compatible-with=7.
* 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.
@ -162,38 +170,12 @@ public enum XContentType {
* @return a media type string without
*/
private static String removeVersionInMediaType(String mediaType) {
if (mediaType.contains("vnd.opensearch")) {
if (mediaType != null && (mediaType = mediaType.toLowerCase(Locale.ROOT)).contains("vnd.opensearch")) {
return mediaType.replaceAll("vnd.opensearch\\+", "").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}
* HTTP header. This method will return {@code null} if no match is found
*/
public static XContentType fromMediaType(String mediaType) {
final String lowercaseMediaType = Objects.requireNonNull(mediaType, "mediaType cannot be null").toLowerCase(Locale.ROOT);
for (XContentType type : values()) {
if (type.mediaTypeWithoutParameters().equals(lowercaseMediaType)) {
return type;
}
}
// we also support newline delimited JSON: http://specs.okfnlabs.org/ndjson/
if (lowercaseMediaType.toLowerCase(Locale.ROOT).equals("application/x-ndjson")) {
return XContentType.JSON;
}
return null;
}
private static boolean isSameMediaTypeOrFormatAs(String stringType, XContentType type) {
return type.mediaTypeWithoutParameters().equalsIgnoreCase(stringType)
|| stringType.toLowerCase(Locale.ROOT).startsWith(type.mediaTypeWithoutParameters().toLowerCase(Locale.ROOT) + ";")
|| type.shortName().equalsIgnoreCase(stringType);
}
private int index;
XContentType(int index) {
@ -208,10 +190,17 @@ public enum XContentType {
return mediaTypeWithoutParameters();
}
public abstract String shortName();
public abstract XContent xContent();
public abstract String mediaTypeWithoutParameters();
@Override
public String type() {
return "application";
}
@Override
public String format() {
return subtype();
}
}

View File

@ -0,0 +1,84 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* The OpenSearch Contributors require contributions made to
* this file be licensed under the Apache-2.0 license or a
* compatible open source license.
*/
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/*
* Modifications Copyright OpenSearch Contributors. See
* GitHub history for details.
*/
package org.opensearch.common.xcontent;
import org.opensearch.test.OpenSearchTestCase;
import java.util.Collections;
import java.util.Map;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.nullValue;
public class MediaTypeParserTests extends OpenSearchTestCase {
@SuppressWarnings("unchecked")
MediaTypeParser<XContentType> mediaTypeParser = XContentType.getMediaTypeParser();
public void testJsonWithParameters() throws Exception {
String mediaType = "application/json";
assertThat(mediaTypeParser.parseMediaType(mediaType).getParameters(), equalTo(Collections.emptyMap()));
assertThat(mediaTypeParser.parseMediaType(mediaType + ";").getParameters(), equalTo(Collections.emptyMap()));
assertThat(mediaTypeParser.parseMediaType(mediaType + "; charset=UTF-8").getParameters(), equalTo(Map.of("charset", "utf-8")));
assertThat(
mediaTypeParser.parseMediaType(mediaType + "; custom=123;charset=UTF-8").getParameters(),
equalTo(Map.of("charset", "utf-8", "custom", "123"))
);
}
public void testWhiteSpaceInTypeSubtype() {
String mediaType = " application/json ";
assertThat(mediaTypeParser.parseMediaType(mediaType).getMediaType(), equalTo(XContentType.JSON));
assertThat(
mediaTypeParser.parseMediaType(mediaType + "; custom=123; charset=UTF-8").getParameters(),
equalTo(Map.of("charset", "utf-8", "custom", "123"))
);
assertThat(
mediaTypeParser.parseMediaType(mediaType + "; custom=123;\n charset=UTF-8").getParameters(),
equalTo(Map.of("charset", "utf-8", "custom", "123"))
);
mediaType = " application / json ";
assertThat(mediaTypeParser.parseMediaType(mediaType), is(nullValue()));
}
public void testInvalidParameters() {
String mediaType = "application/json";
assertThat(mediaTypeParser.parseMediaType(mediaType + "; keyvalueNoEqualsSign"), is(nullValue()));
assertThat(mediaTypeParser.parseMediaType(mediaType + "; key = value"), is(nullValue()));
assertThat(mediaTypeParser.parseMediaType(mediaType + "; key="), is(nullValue()));
}
}

View File

@ -58,6 +58,7 @@ public abstract class AbstractRestChannel implements RestChannel {
private final String filterPath;
private final boolean pretty;
private final boolean human;
private final String acceptHeader;
private BytesStreamOutput bytesOut;
@ -71,7 +72,8 @@ public abstract class AbstractRestChannel implements RestChannel {
protected AbstractRestChannel(RestRequest request, boolean detailedErrorsEnabled) {
this.request = request;
this.detailedErrorsEnabled = detailedErrorsEnabled;
this.format = request.param("format", request.header("Accept"));
this.format = request.param("format");
this.acceptHeader = request.header("Accept");
this.filterPath = request.param("filter_path", null);
this.pretty = request.paramAsBoolean("pretty", false);
this.human = request.paramAsBoolean("human", false);
@ -112,7 +114,11 @@ public abstract class AbstractRestChannel implements RestChannel {
boolean useFiltering
) throws IOException {
if (responseContentType == null) {
responseContentType = XContentType.fromMediaTypeOrFormat(format);
// TODO should format vs acceptHeader always be the same, do we allow overriding?
responseContentType = XContentType.fromFormat(format);
if (responseContentType == null) {
responseContentType = XContentType.fromMediaType(acceptHeader);
}
}
// try to determine the response content type from the media type or the format query string parameter, with the format parameter
// taking precedence over the Accept header

View File

@ -64,13 +64,20 @@ public class RestTable {
public static RestResponse buildResponse(Table table, RestChannel channel) throws Exception {
RestRequest request = channel.request();
XContentType xContentType = XContentType.fromMediaTypeOrFormat(request.param("format", request.header("Accept")));
XContentType xContentType = getXContentType(request);
if (xContentType != null) {
return buildXContentBuilder(table, channel);
}
return buildTextPlainResponse(table, channel);
}
private static XContentType getXContentType(RestRequest request) {
if (request.hasParam("format")) {
return XContentType.fromFormat(request.param("format"));
}
return XContentType.fromMediaType(request.header("Accept"));
}
public static RestResponse buildXContentBuilder(Table table, RestChannel channel) throws Exception {
RestRequest request = channel.request();
XContentBuilder builder = channel.newBuilder();

View File

@ -43,72 +43,80 @@ public class XContentTypeTests extends OpenSearchTestCase {
public void testFromJson() throws Exception {
String mediaType = "application/json";
XContentType expectedXContentType = XContentType.JSON;
assertThat(XContentType.fromMediaTypeOrFormat(mediaType), equalTo(expectedXContentType));
assertThat(XContentType.fromMediaTypeOrFormat(mediaType + ";"), equalTo(expectedXContentType));
assertThat(XContentType.fromMediaTypeOrFormat(mediaType + "; charset=UTF-8"), equalTo(expectedXContentType));
assertThat(XContentType.fromMediaType(mediaType), equalTo(expectedXContentType));
assertThat(XContentType.fromMediaType(mediaType + ";"), equalTo(expectedXContentType));
assertThat(XContentType.fromMediaType(mediaType + "; charset=UTF-8"), equalTo(expectedXContentType));
}
public void testFromNdJson() throws Exception {
String mediaType = "application/x-ndjson";
XContentType expectedXContentType = XContentType.JSON;
assertThat(XContentType.fromMediaType(mediaType), equalTo(expectedXContentType));
assertThat(XContentType.fromMediaType(mediaType + ";"), equalTo(expectedXContentType));
assertThat(XContentType.fromMediaType(mediaType + "; charset=UTF-8"), equalTo(expectedXContentType));
}
public void testFromJsonUppercase() throws Exception {
String mediaType = "application/json".toUpperCase(Locale.ROOT);
XContentType expectedXContentType = XContentType.JSON;
assertThat(XContentType.fromMediaTypeOrFormat(mediaType), equalTo(expectedXContentType));
assertThat(XContentType.fromMediaTypeOrFormat(mediaType + ";"), equalTo(expectedXContentType));
assertThat(XContentType.fromMediaTypeOrFormat(mediaType + "; charset=UTF-8"), equalTo(expectedXContentType));
assertThat(XContentType.fromMediaType(mediaType), equalTo(expectedXContentType));
assertThat(XContentType.fromMediaType(mediaType + ";"), equalTo(expectedXContentType));
assertThat(XContentType.fromMediaType(mediaType + "; charset=UTF-8"), equalTo(expectedXContentType));
}
public void testFromYaml() throws Exception {
String mediaType = "application/yaml";
XContentType expectedXContentType = XContentType.YAML;
assertThat(XContentType.fromMediaTypeOrFormat(mediaType), equalTo(expectedXContentType));
assertThat(XContentType.fromMediaTypeOrFormat(mediaType + ";"), equalTo(expectedXContentType));
assertThat(XContentType.fromMediaTypeOrFormat(mediaType + "; charset=UTF-8"), equalTo(expectedXContentType));
assertThat(XContentType.fromMediaType(mediaType), equalTo(expectedXContentType));
assertThat(XContentType.fromMediaType(mediaType + ";"), equalTo(expectedXContentType));
assertThat(XContentType.fromMediaType(mediaType + "; charset=UTF-8"), equalTo(expectedXContentType));
}
public void testFromSmile() throws Exception {
String mediaType = "application/smile";
XContentType expectedXContentType = XContentType.SMILE;
assertThat(XContentType.fromMediaTypeOrFormat(mediaType), equalTo(expectedXContentType));
assertThat(XContentType.fromMediaTypeOrFormat(mediaType + ";"), equalTo(expectedXContentType));
assertThat(XContentType.fromMediaType(mediaType), equalTo(expectedXContentType));
assertThat(XContentType.fromMediaType(mediaType + ";"), equalTo(expectedXContentType));
}
public void testFromCbor() throws Exception {
String mediaType = "application/cbor";
XContentType expectedXContentType = XContentType.CBOR;
assertThat(XContentType.fromMediaTypeOrFormat(mediaType), equalTo(expectedXContentType));
assertThat(XContentType.fromMediaTypeOrFormat(mediaType + ";"), equalTo(expectedXContentType));
assertThat(XContentType.fromMediaType(mediaType), equalTo(expectedXContentType));
assertThat(XContentType.fromMediaType(mediaType + ";"), equalTo(expectedXContentType));
}
public void testFromWildcard() throws Exception {
String mediaType = "application/*";
XContentType expectedXContentType = XContentType.JSON;
assertThat(XContentType.fromMediaTypeOrFormat(mediaType), equalTo(expectedXContentType));
assertThat(XContentType.fromMediaTypeOrFormat(mediaType + ";"), equalTo(expectedXContentType));
assertThat(XContentType.fromMediaType(mediaType), equalTo(expectedXContentType));
assertThat(XContentType.fromMediaType(mediaType + ";"), equalTo(expectedXContentType));
}
public void testFromWildcardUppercase() throws Exception {
String mediaType = "APPLICATION/*";
XContentType expectedXContentType = XContentType.JSON;
assertThat(XContentType.fromMediaTypeOrFormat(mediaType), equalTo(expectedXContentType));
assertThat(XContentType.fromMediaTypeOrFormat(mediaType + ";"), equalTo(expectedXContentType));
assertThat(XContentType.fromMediaType(mediaType), equalTo(expectedXContentType));
assertThat(XContentType.fromMediaType(mediaType + ";"), equalTo(expectedXContentType));
}
public void testFromRubbish() throws Exception {
assertThat(XContentType.fromMediaTypeOrFormat(null), nullValue());
assertThat(XContentType.fromMediaTypeOrFormat(""), nullValue());
assertThat(XContentType.fromMediaTypeOrFormat("text/plain"), nullValue());
assertThat(XContentType.fromMediaTypeOrFormat("gobbly;goop"), nullValue());
assertThat(XContentType.fromMediaType(null), nullValue());
assertThat(XContentType.fromMediaType(""), nullValue());
assertThat(XContentType.fromMediaType("text/plain"), nullValue());
assertThat(XContentType.fromMediaType("gobbly;goop"), nullValue());
}
public void testVersionedMediaType() throws Exception {
assertThat(XContentType.fromMediaTypeOrFormat("application/vnd.opensearch+json;compatible-with=7"), equalTo(XContentType.JSON));
assertThat(XContentType.fromMediaTypeOrFormat("application/vnd.opensearch+yaml;compatible-with=7"), equalTo(XContentType.YAML));
assertThat(XContentType.fromMediaTypeOrFormat("application/vnd.opensearch+cbor;compatible-with=7"), equalTo(XContentType.CBOR));
assertThat(XContentType.fromMediaTypeOrFormat("application/vnd.opensearch+smile;compatible-with=7"), equalTo(XContentType.SMILE));
assertThat(XContentType.fromMediaType("application/vnd.opensearch+json;compatible-with=7"), equalTo(XContentType.JSON));
assertThat(XContentType.fromMediaType("application/vnd.opensearch+yaml;compatible-with=7"), equalTo(XContentType.YAML));
assertThat(XContentType.fromMediaType("application/vnd.opensearch+cbor;compatible-with=7"), equalTo(XContentType.CBOR));
assertThat(XContentType.fromMediaType("application/vnd.opensearch+smile;compatible-with=7"), equalTo(XContentType.SMILE));
assertThat(XContentType.fromMediaTypeOrFormat("application/vnd.opensearch+json ;compatible-with=7"), equalTo(XContentType.JSON));
assertThat(
XContentType.fromMediaTypeOrFormat("application/vnd.opensearch+json ;compatible-with=7;charset=utf-8"),
equalTo(XContentType.JSON)
);
assertThat(XContentType.fromMediaType("application/vnd.opensearch+json ;compatible-with=7"), equalTo(XContentType.JSON));
String mthv = "application/vnd.opensearch+json ;compatible-with=7;charset=utf-8";
assertThat(XContentType.fromMediaType(mthv), equalTo(XContentType.JSON));
assertThat(XContentType.fromMediaType(mthv.toUpperCase(Locale.ROOT)), equalTo(XContentType.JSON));
}
}

View File

@ -325,7 +325,7 @@ public class BytesRestResponseTests extends OpenSearchTestCase {
final XContentType xContentType = randomFrom(XContentType.values());
Map<String, String> params = Collections.singletonMap("format", xContentType.mediaType());
Map<String, String> params = Collections.singletonMap("format", xContentType.format());
RestRequest request = new FakeRestRequest.Builder(xContentRegistry()).withParams(params).build();
RestChannel channel = detailed ? new DetailedExceptionRestChannel(request) : new SimpleExceptionRestChannel(request);

View File

@ -136,7 +136,7 @@ public abstract class OpenSearchRestTestCase extends OpenSearchTestCase {
* Convert the entity from a {@link Response} into a map of maps.
*/
public static Map<String, Object> entityAsMap(Response response) throws IOException {
XContentType xContentType = XContentType.fromMediaTypeOrFormat(response.getEntity().getContentType().getValue());
XContentType xContentType = XContentType.fromMediaType(response.getEntity().getContentType().getValue());
// EMPTY and THROW are fine here because `.map` doesn't use named x content or deprecation
try (
XContentParser parser = xContentType.xContent()
@ -154,7 +154,7 @@ public abstract class OpenSearchRestTestCase extends OpenSearchTestCase {
* Convert the entity from a {@link Response} into a list of maps.
*/
public static List<Object> entityAsList(Response response) throws IOException {
XContentType xContentType = XContentType.fromMediaTypeOrFormat(response.getEntity().getContentType().getValue());
XContentType xContentType = XContentType.fromMediaType(response.getEntity().getContentType().getValue());
// EMPTY and THROW are fine here because `.map` doesn't use named x content or deprecation
try (
XContentParser parser = xContentType.xContent()
@ -1082,7 +1082,7 @@ public abstract class OpenSearchRestTestCase extends OpenSearchTestCase {
}
protected static Map<String, Object> responseAsMap(Response response) throws IOException {
XContentType entityContentType = XContentType.fromMediaTypeOrFormat(response.getEntity().getContentType().getValue());
XContentType entityContentType = XContentType.fromMediaType(response.getEntity().getContentType().getValue());
Map<String, Object> responseEntity = XContentHelper.convertToMap(
entityContentType.xContent(),
response.getEntity().getContent(),

View File

@ -66,7 +66,7 @@ public class ClientYamlTestResponse {
this.response = response;
if (response.getEntity() != null) {
String contentType = response.getHeader("Content-Type");
this.bodyContentType = XContentType.fromMediaTypeOrFormat(contentType);
this.bodyContentType = XContentType.fromMediaType(contentType);
try {
byte[] bytes = EntityUtils.toByteArray(response.getEntity());
// skip parsing if we got text back (e.g. if we called _cat apis)

View File

@ -57,7 +57,7 @@ public class ObjectPath {
public static ObjectPath createFromResponse(Response response) throws IOException {
byte[] bytes = EntityUtils.toByteArray(response.getEntity());
String contentType = response.getHeader("Content-Type");
XContentType xContentType = XContentType.fromMediaTypeOrFormat(contentType);
XContentType xContentType = XContentType.fromMediaType(contentType);
return ObjectPath.createFromXContent(xContentType.xContent(), new BytesArray(bytes));
}