Ignore parameters when checking if */* is accepted

Previously the parameters were not ignored so */*;q=0.8 was not
identified as accepting */*. As a result, the most recent producible
content type was returned rather than the default.

This commit updates the argument resolver to ignore parameters.
The default content type is now produced in response to a request
that accepts */*, irrespective of its parameters.

Fixes gh-28446
This commit is contained in:
Andy Wilkinson 2021-10-28 12:22:29 +01:00
parent ce38d592f9
commit b375f9fac0
2 changed files with 17 additions and 8 deletions

View File

@ -65,7 +65,7 @@ public class ProducibleOperationArgumentResolver implements OperationArgumentRes
Enum<? extends Producible<?>> result = null;
for (String accept : accepts) {
for (String mimeType : MimeTypeUtils.tokenize(accept)) {
result = mostRecent(result, forMimeType(values, mimeType));
result = mostRecent(result, forMimeType(values, MimeTypeUtils.parseMimeType(mimeType)));
}
}
return result;
@ -78,14 +78,10 @@ public class ProducibleOperationArgumentResolver implements OperationArgumentRes
return (candidateOrdinal > existingOrdinal) ? candidate : existing;
}
private Enum<? extends Producible<?>> forMimeType(List<Enum<? extends Producible<?>>> values, String mimeType) {
if ("*/*".equals(mimeType)) {
private Enum<? extends Producible<?>> forMimeType(List<Enum<? extends Producible<?>>> values, MimeType mimeType) {
if (mimeType.isWildcardType() && mimeType.isWildcardSubtype()) {
return getDefaultValue(values);
}
return forMimeType(values, MimeTypeUtils.parseMimeType(mimeType));
}
private Enum<? extends Producible<?>> forMimeType(List<Enum<? extends Producible<?>>> values, MimeType mimeType) {
for (Enum<? extends Producible<?>> candidate : values) {
if (mimeType.isCompatibleWith(((Producible<?>) candidate).getProducedMimeType())) {
return candidate;

View File

@ -41,12 +41,25 @@ class PrometheusScrapeEndpointIntegrationTests {
@WebEndpointTest
void scrapeHasContentTypeText004ByDefault(WebTestClient client) {
String expectedContentType = TextFormat.CONTENT_TYPE_004;
assertThat(TextFormat.chooseContentType(null)).isEqualTo(expectedContentType);
client.get().uri("/actuator/prometheus").exchange().expectStatus().isOk().expectHeader()
.contentType(MediaType.parseMediaType(TextFormat.CONTENT_TYPE_004)).expectBody(String.class)
.contentType(MediaType.parseMediaType(expectedContentType)).expectBody(String.class)
.value((body) -> assertThat(body).contains("counter1_total").contains("counter2_total")
.contains("counter3_total"));
}
@WebEndpointTest
void scrapeHasContentTypeText004ByDefaultWhenClientAcceptsWildcardWithParameter(WebTestClient client) {
String expectedContentType = TextFormat.CONTENT_TYPE_004;
String accept = "*/*;q=0.8";
assertThat(TextFormat.chooseContentType(accept)).isEqualTo(expectedContentType);
client.get().uri("/actuator/prometheus").accept(MediaType.parseMediaType(accept)).exchange().expectStatus()
.isOk().expectHeader().contentType(MediaType.parseMediaType(expectedContentType))
.expectBody(String.class).value((body) -> assertThat(body).contains("counter1_total")
.contains("counter2_total").contains("counter3_total"));
}
@WebEndpointTest
void scrapeCanProduceOpenMetrics100(WebTestClient client) {
MediaType openMetrics = MediaType.parseMediaType(TextFormat.CONTENT_TYPE_OPENMETRICS_100);