summaryrefslogtreecommitdiff
path: root/core/src/main/java/org/elasticsearch/common/xcontent/XContentType.java
diff options
context:
space:
mode:
authorJay Modi <jaymode@users.noreply.github.com>2017-02-02 14:07:13 -0500
committerGitHub <noreply@github.com>2017-02-02 14:07:13 -0500
commit7520a107bee67099338813728147d2aee25ed240 (patch)
tree22828e74c5aa601c185c36c7463665fbfeaa4c51 /core/src/main/java/org/elasticsearch/common/xcontent/XContentType.java
parentb41d5747f0bd67dad05c8168312ba456bcdaebda (diff)
Optionally require a valid content type for all rest requests with content (#22691)
This change adds a strict mode for xcontent parsing on the rest layer. The strict mode will be off by default for 5.x and in a separate commit will be enabled by default for 6.0. The strict mode, which can be enabled by setting `http.content_type.required: true` in 5.x, will require that all incoming rest requests have a valid and supported content type header before the request is dispatched. In the non-strict mode, the Content-Type header will be inspected and if it is not present or not valid, we will continue with auto detection of content like we have done previously. The content type header is parsed to the matching XContentType value with the only exception being for plain text requests. This value is then passed on with the content bytes so that we can reduce the number of places where we need to auto-detect the content type. As part of this, many transport requests and builders were updated to provide methods that accepted the XContentType along with the bytes and the methods that would rely on auto-detection have been deprecated. In the non-strict mode, deprecation warnings are issued whenever a request with body doesn't provide the Content-Type header. See #19388
Diffstat (limited to 'core/src/main/java/org/elasticsearch/common/xcontent/XContentType.java')
-rw-r--r--core/src/main/java/org/elasticsearch/common/xcontent/XContentType.java36
1 files changed, 29 insertions, 7 deletions
diff --git a/core/src/main/java/org/elasticsearch/common/xcontent/XContentType.java b/core/src/main/java/org/elasticsearch/common/xcontent/XContentType.java
index ddd736e0d0..8e3c298270 100644
--- a/core/src/main/java/org/elasticsearch/common/xcontent/XContentType.java
+++ b/core/src/main/java/org/elasticsearch/common/xcontent/XContentType.java
@@ -29,6 +29,7 @@ import org.elasticsearch.common.xcontent.yaml.YamlXContent;
import java.io.IOException;
import java.util.Locale;
+import java.util.Objects;
/**
* The content type of {@link org.elasticsearch.common.xcontent.XContent}.
@@ -40,7 +41,7 @@ public enum XContentType implements Writeable {
*/
JSON(0) {
@Override
- protected String mediaTypeWithoutParameters() {
+ public String mediaTypeWithoutParameters() {
return "application/json";
}
@@ -64,7 +65,7 @@ public enum XContentType implements Writeable {
*/
SMILE(1) {
@Override
- protected String mediaTypeWithoutParameters() {
+ public String mediaTypeWithoutParameters() {
return "application/smile";
}
@@ -83,7 +84,7 @@ public enum XContentType implements Writeable {
*/
YAML(2) {
@Override
- protected String mediaTypeWithoutParameters() {
+ public String mediaTypeWithoutParameters() {
return "application/yaml";
}
@@ -102,7 +103,7 @@ public enum XContentType implements Writeable {
*/
CBOR(3) {
@Override
- protected String mediaTypeWithoutParameters() {
+ public String mediaTypeWithoutParameters() {
return "application/cbor";
}
@@ -117,12 +118,18 @@ public enum XContentType implements Writeable {
}
};
+ /**
+ * 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
+ */
public static XContentType fromMediaTypeOrFormat(String mediaType) {
if (mediaType == null) {
return null;
}
for (XContentType type : values()) {
- if (isSameMediaTypeAs(mediaType, type)) {
+ if (isSameMediaTypeOrFormatAs(mediaType, type)) {
return type;
}
}
@@ -133,7 +140,22 @@ public enum XContentType implements Writeable {
return null;
}
- private static boolean isSameMediaTypeAs(String stringType, XContentType type) {
+ /**
+ * 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;
+ }
+ }
+ 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);
@@ -157,7 +179,7 @@ public enum XContentType implements Writeable {
public abstract XContent xContent();
- protected abstract String mediaTypeWithoutParameters();
+ public abstract String mediaTypeWithoutParameters();
public static XContentType readFrom(StreamInput in) throws IOException {
int index = in.readVInt();