Skip to content

Commit 7718936

Browse files
committed
Recognize wildcards in media types with a suffix
The "includes" and "isCompatibleWith" methods of MediaType take into account media types with suffices (e.g. application/soap+xml) including wildcards with suffices (e.g. application/*+xml). However before this change, the isWildcardSubtype() method returned true only for subtype "*". Now a media type such as application/*+xml is also recognized as having a wildcard subtype. Issue: SPR-9841
1 parent 2638dd5 commit 7718936

File tree

3 files changed

+32
-2
lines changed

3 files changed

+32
-2
lines changed

spring-web/src/main/java/org/springframework/http/MediaType.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -413,11 +413,12 @@ public String getSubtype() {
413413
}
414414

415415
/**
416-
* Indicates whether the {@linkplain #getSubtype() subtype} is the wildcard character <code>&#42;</code> or not.
416+
* Indicates whether the {@linkplain #getSubtype() subtype} is the wildcard character <code>&#42;</code>
417+
* or the wildcard character followed by a sufiix (e.g. <code>&#42;+xml</code>), or not.
417418
* @return whether the subtype is <code>&#42;</code>
418419
*/
419420
public boolean isWildcardSubtype() {
420-
return WILDCARD_TYPE.equals(subtype);
421+
return WILDCARD_TYPE.equals(subtype) || subtype.startsWith("*+");
421422
}
422423

423424
/**

spring-web/src/test/java/org/springframework/http/MediaTypeTests.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,7 @@ public void specificityComparator() throws Exception {
313313
MediaType audio07 = new MediaType("audio", "*", 0.7);
314314
MediaType audioBasicLevel = new MediaType("audio", "basic", Collections.singletonMap("level", "1"));
315315
MediaType textHtml = new MediaType("text", "html");
316+
MediaType allXml = new MediaType("application", "*+xml");
316317
MediaType all = MediaType.ALL;
317318

318319
Comparator<MediaType> comp = MediaType.SPECIFICITY_COMPARATOR;
@@ -328,9 +329,11 @@ public void specificityComparator() throws Exception {
328329
assertTrue("Invalid comparison result", comp.compare(audioBasic, audio) < 0);
329330
assertTrue("Invalid comparison result", comp.compare(audioBasic, all) < 0);
330331
assertTrue("Invalid comparison result", comp.compare(audio, all) < 0);
332+
assertTrue("Invalid comparison result", comp.compare(MediaType.APPLICATION_XHTML_XML, allXml) < 0);
331333

332334
// unspecific to specific
333335
assertTrue("Invalid comparison result", comp.compare(audio, audioBasic) > 0);
336+
assertTrue("Invalid comparison result", comp.compare(allXml, MediaType.APPLICATION_XHTML_XML) > 0);
334337
assertTrue("Invalid comparison result", comp.compare(all, audioBasic) > 0);
335338
assertTrue("Invalid comparison result", comp.compare(all, audio) > 0);
336339

@@ -414,6 +417,7 @@ public void qualityComparator() throws Exception {
414417
MediaType audio07 = new MediaType("audio", "*", 0.7);
415418
MediaType audioBasicLevel = new MediaType("audio", "basic", Collections.singletonMap("level", "1"));
416419
MediaType textHtml = new MediaType("text", "html");
420+
MediaType allXml = new MediaType("application", "*+xml");
417421
MediaType all = MediaType.ALL;
418422

419423
Comparator<MediaType> comp = MediaType.QUALITY_VALUE_COMPARATOR;
@@ -429,11 +433,13 @@ public void qualityComparator() throws Exception {
429433
assertTrue("Invalid comparison result", comp.compare(audioBasic, audio) < 0);
430434
assertTrue("Invalid comparison result", comp.compare(audioBasic, all) < 0);
431435
assertTrue("Invalid comparison result", comp.compare(audio, all) < 0);
436+
assertTrue("Invalid comparison result", comp.compare(MediaType.APPLICATION_XHTML_XML, allXml) < 0);
432437

433438
// unspecific to specific
434439
assertTrue("Invalid comparison result", comp.compare(audio, audioBasic) > 0);
435440
assertTrue("Invalid comparison result", comp.compare(all, audioBasic) > 0);
436441
assertTrue("Invalid comparison result", comp.compare(all, audio) > 0);
442+
assertTrue("Invalid comparison result", comp.compare(allXml, MediaType.APPLICATION_XHTML_XML) > 0);
437443

438444
// qualifiers
439445
assertTrue("Invalid comparison result", comp.compare(audio, audio07) < 0);

spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestResponseBodyMethodProcessorMockTests.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,28 @@ public void handleReturnValueNotAcceptableProduces() throws Exception {
279279
processor.handleReturnValue("Foo", returnTypeStringProduces, mavContainer, webRequest);
280280
}
281281

282+
// SPR-9841
283+
284+
@Test
285+
public void handleReturnValueMediaTypeSuffix() throws Exception {
286+
String body = "Foo";
287+
MediaType accepted = MediaType.APPLICATION_XHTML_XML;
288+
List<MediaType> supported = Collections.singletonList(MediaType.valueOf("application/*+xml"));
289+
290+
servletRequest.addHeader("Accept", accepted);
291+
292+
expect(messageConverter.canWrite(String.class, null)).andReturn(true);
293+
expect(messageConverter.getSupportedMediaTypes()).andReturn(supported);
294+
expect(messageConverter.canWrite(String.class, accepted)).andReturn(true);
295+
messageConverter.write(eq(body), eq(accepted), isA(HttpOutputMessage.class));
296+
replay(messageConverter);
297+
298+
processor.handleReturnValue(body, returnTypeStringProduces, mavContainer, webRequest);
299+
300+
assertTrue(mavContainer.isRequestHandled());
301+
verify(messageConverter);
302+
}
303+
282304
// SPR-9160
283305

284306
@Test
@@ -308,6 +330,7 @@ public void handleReturnValueString() throws Exception {
308330
assertEquals("Foo", servletResponse.getContentAsString());
309331
}
310332

333+
311334
@ResponseBody
312335
public String handle1(@RequestBody String s, int i) {
313336
return s;

0 commit comments

Comments
 (0)