diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/ProducibleOperationArgumentResolver.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/ProducibleOperationArgumentResolver.java index 6e9b639a2f88..75a76f787aff 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/ProducibleOperationArgumentResolver.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/ProducibleOperationArgumentResolver.java @@ -65,7 +65,7 @@ private Enum> resolveProducible(Class> 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 @@ private Enum> mostRecent(Enum> e return (candidateOrdinal > existingOrdinal) ? candidate : existing; } - private Enum> forMimeType(List>> values, String mimeType) { - if ("*/*".equals(mimeType)) { + private Enum> forMimeType(List>> values, MimeType mimeType) { + if (mimeType.isWildcardType() && mimeType.isWildcardSubtype()) { return getDefaultValue(values); } - return forMimeType(values, MimeTypeUtils.parseMimeType(mimeType)); - } - - private Enum> forMimeType(List>> values, MimeType mimeType) { for (Enum> candidate : values) { if (mimeType.isCompatibleWith(((Producible) candidate).getProducedMimeType())) { return candidate; diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/export/prometheus/PrometheusScrapeEndpointIntegrationTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/export/prometheus/PrometheusScrapeEndpointIntegrationTests.java index dbce312303bb..1265d82106ff 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/export/prometheus/PrometheusScrapeEndpointIntegrationTests.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/export/prometheus/PrometheusScrapeEndpointIntegrationTests.java @@ -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);