The "consumes" condition compares MediaType parameters

Closes gh-9257
This commit is contained in:
rstoyanchev
2022-05-11 14:54:00 +01:00
parent 4b0531b4aa
commit f0e23b66f3
11 changed files with 112 additions and 60 deletions

View File

@@ -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.servlet.mvc.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;
/**
@@ -78,6 +81,18 @@ abstract class AbstractMediaTypeExpression implements MediaTypeExpression, Compa
}
}
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 boolean equals(@Nullable Object other) {
if (this == other) {

View File

@@ -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.
@@ -285,7 +285,7 @@ public final class ConsumesRequestCondition extends AbstractRequestCondition<Con
}
public final boolean match(MediaType contentType) {
boolean match = getMediaType().includes(contentType);
boolean match = (getMediaType().includes(contentType) && matchParameters(contentType));
return !isNegated() == match;
}
}

View File

@@ -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.
@@ -29,7 +29,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.HttpMediaTypeException;
import org.springframework.web.HttpMediaTypeNotAcceptableException;
import org.springframework.web.accept.ContentNegotiationManager;
@@ -373,17 +372,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;
}
}
}

View File

@@ -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.
@@ -88,6 +88,27 @@ public class ConsumesRequestConditionTests {
assertThat(condition.getMatchingCondition(request)).isNull();
}
@Test // gh-28024
public void matchWithParameters() {
String base = "application/hal+json";
ConsumesRequestCondition condition = new ConsumesRequestCondition(base + ";profile=\"a\"");
MockHttpServletRequest request = new MockHttpServletRequest();
request.setContentType(base + ";profile=\"a\"");
assertThat(condition.getMatchingCondition(request)).isNotNull();
condition = new ConsumesRequestCondition(base + ";profile=\"a\"");
request.setContentType(base + ";profile=\"b\"");
assertThat(condition.getMatchingCondition(request)).isNull();
condition = new ConsumesRequestCondition(base + ";profile=\"a\"");
request.setContentType(base);
assertThat(condition.getMatchingCondition(request)).isNotNull();
condition = new ConsumesRequestCondition(base);
request.setContentType(base + ";profile=\"a\"");
assertThat(condition.getMatchingCondition(request)).isNotNull();
}
@Test
public void consumesParseError() {
ConsumesRequestCondition condition = new ConsumesRequestCondition("text/plain");

View File

@@ -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.
@@ -99,19 +99,19 @@ public class ProducesRequestConditionTests {
String base = "application/atom+xml";
ProducesRequestCondition condition = new ProducesRequestCondition(base + ";type=feed");
HttpServletRequest request = createRequest(base + ";type=entry");
assertThat(condition.getMatchingCondition(request)).as("Declared parameter value must match if present in request").isNull();
assertThat(condition.getMatchingCondition(request)).isNull();
condition = new ProducesRequestCondition(base + ";type=feed");
request = createRequest(base + ";type=feed");
assertThat(condition.getMatchingCondition(request)).as("Declared parameter value must match if present in request").isNotNull();
assertThat(condition.getMatchingCondition(request)).isNotNull();
condition = new ProducesRequestCondition(base + ";type=feed");
request = createRequest(base);
assertThat(condition.getMatchingCondition(request)).as("Declared parameter has no impact if not present in request").isNotNull();
assertThat(condition.getMatchingCondition(request)).isNotNull();
condition = new ProducesRequestCondition(base);
request = createRequest(base + ";type=feed");
assertThat(condition.getMatchingCondition(request)).as("No impact from other parameters in request").isNotNull();
assertThat(condition.getMatchingCondition(request)).isNotNull();
}
@Test