Improve MIME type subtype suffix handling
Prior to this commit, the subtype suffix of a MIME type (see RFC 6839) was not properly taken into account when checking compatibility between MIME types. For example, `"application/*"` was not considered as compatible with `"application/vnd.io.spring+json"`. This commit adds a new `MimeType#getSubtypeSuffix()` method to easily extract the subtype suffix information. This method is then reused in the `isCompatibleWith` implementation to better handle these cases. Fixes gh-25350
This commit is contained in:
@@ -284,6 +284,19 @@ public class MimeType implements Comparable<MimeType>, Serializable {
|
||||
return this.subtype;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the subtype suffix as defined in RFC 6839.
|
||||
* @since 5.3
|
||||
*/
|
||||
@Nullable
|
||||
public String getSubtypeSuffix() {
|
||||
int suffixIndex = this.subtype.lastIndexOf('+');
|
||||
if (suffixIndex != -1 && this.subtype.length() > suffixIndex) {
|
||||
return this.subtype.substring(suffixIndex + 1);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the character set, as indicated by a {@code charset} parameter, if any.
|
||||
* @return the character set, or {@code null} if not available
|
||||
@@ -377,22 +390,20 @@ public class MimeType implements Comparable<MimeType>, Serializable {
|
||||
if (getSubtype().equals(other.getSubtype())) {
|
||||
return true;
|
||||
}
|
||||
// Wildcard with suffix? e.g. application/*+xml
|
||||
if (isWildcardSubtype() || other.isWildcardSubtype()) {
|
||||
int thisPlusIdx = getSubtype().lastIndexOf('+');
|
||||
int otherPlusIdx = other.getSubtype().lastIndexOf('+');
|
||||
if (thisPlusIdx == -1 && otherPlusIdx == -1) {
|
||||
String thisSuffix = getSubtypeSuffix();
|
||||
String otherSuffix = other.getSubtypeSuffix();
|
||||
if (getSubtype().equals(WILDCARD_TYPE)
|
||||
|| other.getSubtype().equals(WILDCARD_TYPE)) {
|
||||
return true;
|
||||
}
|
||||
else if (thisPlusIdx != -1 && otherPlusIdx != -1) {
|
||||
String thisSubtypeNoSuffix = getSubtype().substring(0, thisPlusIdx);
|
||||
String otherSubtypeNoSuffix = other.getSubtype().substring(0, otherPlusIdx);
|
||||
String thisSubtypeSuffix = getSubtype().substring(thisPlusIdx + 1);
|
||||
String otherSubtypeSuffix = other.getSubtype().substring(otherPlusIdx + 1);
|
||||
if (thisSubtypeSuffix.equals(otherSubtypeSuffix) &&
|
||||
(WILDCARD_TYPE.equals(thisSubtypeNoSuffix) || WILDCARD_TYPE.equals(otherSubtypeNoSuffix))) {
|
||||
return true;
|
||||
}
|
||||
else if (isWildcardSubtype() && thisSuffix != null) {
|
||||
return thisSuffix.equals(other.getSubtype())
|
||||
|| thisSuffix.equals(otherSuffix);
|
||||
}
|
||||
else if (other.isWildcardSubtype() && otherSuffix != null) {
|
||||
return this.getSubtype().equals(otherSuffix)
|
||||
|| otherSuffix.equals(thisSuffix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -320,6 +320,25 @@ class MimeTypeTests {
|
||||
testWithQuotedParameters("foo/bar;param=\"\\,\\\"");
|
||||
}
|
||||
|
||||
@Test
|
||||
void parseSubtypeSuffix() {
|
||||
MimeType type = new MimeType("application", "vdn.something+json");
|
||||
assertThat(type.getSubtypeSuffix()).isEqualTo("json");
|
||||
type = new MimeType("application", "vdn.something");
|
||||
assertThat(type.getSubtypeSuffix()).isNull();
|
||||
type = new MimeType("application", "vdn.something+");
|
||||
assertThat(type.getSubtypeSuffix()).isEqualTo("");
|
||||
type = new MimeType("application", "vdn.some+thing+json");
|
||||
assertThat(type.getSubtypeSuffix()).isEqualTo("json");
|
||||
}
|
||||
|
||||
@Test // gh-25350
|
||||
void wildcardSubtypeCompatibleWithSuffix() {
|
||||
MimeType applicationStar = new MimeType("application", "*");
|
||||
MimeType applicationVndJson = new MimeType("application", "vnd.something+json");
|
||||
assertThat(applicationStar.isCompatibleWith(applicationVndJson)).isTrue();
|
||||
}
|
||||
|
||||
private void testWithQuotedParameters(String... mimeTypes) {
|
||||
String s = String.join(",", mimeTypes);
|
||||
List<MimeType> actual = MimeTypeUtils.parseMimeTypes(s);
|
||||
|
||||
Reference in New Issue
Block a user