The "consumes" condition compares MediaType parameters
Closes gh-9257
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -16,8 +16,11 @@
|
||||
|
||||
package org.springframework.web.reactive.result.condition;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.server.NotAcceptableStatusException;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
@@ -78,6 +81,18 @@ abstract class AbstractMediaTypeExpression implements Comparable<AbstractMediaTy
|
||||
protected abstract boolean matchMediaType(ServerWebExchange exchange)
|
||||
throws NotAcceptableStatusException, UnsupportedMediaTypeStatusException;
|
||||
|
||||
protected boolean matchParameters(MediaType contentType) {
|
||||
for (Map.Entry<String, String> entry : getMediaType().getParameters().entrySet()) {
|
||||
if (StringUtils.hasText(entry.getValue())) {
|
||||
String value = contentType.getParameter(entry.getKey());
|
||||
if (StringUtils.hasText(value) && !entry.getValue().equals(value)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(AbstractMediaTypeExpression other) {
|
||||
MediaType mediaType1 = this.getMediaType();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -274,7 +274,7 @@ public final class ConsumesRequestCondition extends AbstractRequestCondition<Con
|
||||
try {
|
||||
MediaType contentType = exchange.getRequest().getHeaders().getContentType();
|
||||
contentType = (contentType != null ? contentType : MediaType.APPLICATION_OCTET_STREAM);
|
||||
return getMediaType().includes(contentType);
|
||||
return (getMediaType().includes(contentType) && matchParameters(contentType));
|
||||
}
|
||||
catch (InvalidMediaTypeException ex) {
|
||||
throw new UnsupportedMediaTypeStatusException("Can't parse Content-Type [" +
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -27,7 +27,6 @@ import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.MimeType;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.accept.ContentNegotiationManager;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.cors.reactive.CorsUtils;
|
||||
@@ -361,17 +360,6 @@ public final class ProducesRequestCondition extends AbstractRequestCondition<Pro
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean matchParameters(MediaType acceptedMediaType) {
|
||||
for (String name : getMediaType().getParameters().keySet()) {
|
||||
String s1 = getMediaType().getParameter(name);
|
||||
String s2 = acceptedMediaType.getParameter(name);
|
||||
if (StringUtils.hasText(s1) && StringUtils.hasText(s2) && !s1.equalsIgnoreCase(s2)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -35,7 +35,7 @@ import static org.assertj.core.api.Assertions.fail;
|
||||
public class ConsumesRequestConditionTests {
|
||||
|
||||
@Test
|
||||
public void consumesMatch() throws Exception {
|
||||
public void consumesMatch() {
|
||||
MockServerWebExchange exchange = postExchange("text/plain");
|
||||
ConsumesRequestCondition condition = new ConsumesRequestCondition("text/plain");
|
||||
|
||||
@@ -43,7 +43,7 @@ public class ConsumesRequestConditionTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void negatedConsumesMatch() throws Exception {
|
||||
public void negatedConsumesMatch() {
|
||||
MockServerWebExchange exchange = postExchange("text/plain");
|
||||
ConsumesRequestCondition condition = new ConsumesRequestCondition("!text/plain");
|
||||
|
||||
@@ -51,13 +51,13 @@ public class ConsumesRequestConditionTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getConsumableMediaTypesNegatedExpression() throws Exception {
|
||||
public void getConsumableMediaTypesNegatedExpression() {
|
||||
ConsumesRequestCondition condition = new ConsumesRequestCondition("!application/xml");
|
||||
assertThat(condition.getConsumableMediaTypes()).isEqualTo(Collections.emptySet());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void consumesWildcardMatch() throws Exception {
|
||||
public void consumesWildcardMatch() {
|
||||
MockServerWebExchange exchange = postExchange("text/plain");
|
||||
ConsumesRequestCondition condition = new ConsumesRequestCondition("text/*");
|
||||
|
||||
@@ -65,7 +65,7 @@ public class ConsumesRequestConditionTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void consumesMultipleMatch() throws Exception {
|
||||
public void consumesMultipleMatch() {
|
||||
MockServerWebExchange exchange = postExchange("text/plain");
|
||||
ConsumesRequestCondition condition = new ConsumesRequestCondition("text/plain", "application/xml");
|
||||
|
||||
@@ -73,15 +73,35 @@ public class ConsumesRequestConditionTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void consumesSingleNoMatch() throws Exception {
|
||||
public void consumesSingleNoMatch() {
|
||||
MockServerWebExchange exchange = postExchange("application/xml");
|
||||
ConsumesRequestCondition condition = new ConsumesRequestCondition("text/plain");
|
||||
|
||||
assertThat(condition.getMatchingCondition(exchange)).isNull();
|
||||
}
|
||||
|
||||
@Test // gh-28024
|
||||
public void matchWithParameters() {
|
||||
String base = "application/hal+json";
|
||||
ConsumesRequestCondition condition = new ConsumesRequestCondition(base + ";profile=\"a\"");
|
||||
MockServerWebExchange exchange = postExchange(base + ";profile=\"a\"");
|
||||
assertThat(condition.getMatchingCondition(exchange)).isNotNull();
|
||||
|
||||
condition = new ConsumesRequestCondition(base + ";profile=\"a\"");
|
||||
exchange = postExchange(base + ";profile=\"b\"");
|
||||
assertThat(condition.getMatchingCondition(exchange)).isNull();
|
||||
|
||||
condition = new ConsumesRequestCondition(base + ";profile=\"a\"");
|
||||
exchange = postExchange(base);
|
||||
assertThat(condition.getMatchingCondition(exchange)).isNotNull();
|
||||
|
||||
condition = new ConsumesRequestCondition(base);
|
||||
exchange = postExchange(base + ";profile=\"a\"");
|
||||
assertThat(condition.getMatchingCondition(exchange)).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void consumesParseError() throws Exception {
|
||||
public void consumesParseError() {
|
||||
MockServerWebExchange exchange = postExchange("01");
|
||||
ConsumesRequestCondition condition = new ConsumesRequestCondition("text/plain");
|
||||
|
||||
@@ -89,7 +109,7 @@ public class ConsumesRequestConditionTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void consumesParseErrorWithNegation() throws Exception {
|
||||
public void consumesParseErrorWithNegation() {
|
||||
MockServerWebExchange exchange = postExchange("01");
|
||||
ConsumesRequestCondition condition = new ConsumesRequestCondition("!text/plain");
|
||||
|
||||
@@ -115,7 +135,7 @@ public class ConsumesRequestConditionTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compareToSingle() throws Exception {
|
||||
public void compareToSingle() {
|
||||
MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/"));
|
||||
|
||||
ConsumesRequestCondition condition1 = new ConsumesRequestCondition("text/plain");
|
||||
@@ -129,7 +149,7 @@ public class ConsumesRequestConditionTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compareToMultiple() throws Exception {
|
||||
public void compareToMultiple() {
|
||||
MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/"));
|
||||
|
||||
ConsumesRequestCondition condition1 = new ConsumesRequestCondition("*/*", "text/plain");
|
||||
@@ -153,7 +173,7 @@ public class ConsumesRequestConditionTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void combineWithDefault() throws Exception {
|
||||
public void combineWithDefault() {
|
||||
ConsumesRequestCondition condition1 = new ConsumesRequestCondition("text/plain");
|
||||
ConsumesRequestCondition condition2 = new ConsumesRequestCondition();
|
||||
|
||||
@@ -162,7 +182,7 @@ public class ConsumesRequestConditionTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseConsumesAndHeaders() throws Exception {
|
||||
public void parseConsumesAndHeaders() {
|
||||
String[] consumes = new String[] {"text/plain"};
|
||||
String[] headers = new String[]{"foo=bar", "content-type=application/xml,application/pdf"};
|
||||
ConsumesRequestCondition condition = new ConsumesRequestCondition(consumes, headers);
|
||||
@@ -171,7 +191,7 @@ public class ConsumesRequestConditionTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getMatchingCondition() throws Exception {
|
||||
public void getMatchingCondition() {
|
||||
MockServerWebExchange exchange = postExchange("text/plain");
|
||||
ConsumesRequestCondition condition = new ConsumesRequestCondition("text/plain", "application/xml");
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -89,19 +89,19 @@ public class ProducesRequestConditionTests {
|
||||
String base = "application/atom+xml";
|
||||
ProducesRequestCondition condition = new ProducesRequestCondition(base + ";type=feed");
|
||||
MockServerWebExchange exchange = MockServerWebExchange.from(get("/").header("Accept", base + ";type=feed"));
|
||||
assertThat(condition.getMatchingCondition(exchange)).as("Declared parameter value must match if present in request").isNotNull();
|
||||
assertThat(condition.getMatchingCondition(exchange)).isNotNull();
|
||||
|
||||
condition = new ProducesRequestCondition(base + ";type=feed");
|
||||
exchange = MockServerWebExchange.from(get("/").header("Accept", base + ";type=entry"));
|
||||
assertThat(condition.getMatchingCondition(exchange)).as("Declared parameter value must match if present in request").isNull();
|
||||
assertThat(condition.getMatchingCondition(exchange)).isNull();
|
||||
|
||||
condition = new ProducesRequestCondition(base + ";type=feed");
|
||||
exchange = MockServerWebExchange.from(get("/").header("Accept", base));
|
||||
assertThat(condition.getMatchingCondition(exchange)).as("Declared parameter has no impact if not present in request").isNotNull();
|
||||
assertThat(condition.getMatchingCondition(exchange)).isNotNull();
|
||||
|
||||
condition = new ProducesRequestCondition(base);
|
||||
exchange = MockServerWebExchange.from(get("/").header("Accept", base + ";type=feed"));
|
||||
assertThat(condition.getMatchingCondition(exchange)).as("No impact from other parameters in request").isNotNull();
|
||||
assertThat(condition.getMatchingCondition(exchange)).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user