You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ozone.apache.org by si...@apache.org on 2026/10/11 01:42:32 UTC
(ozone) branch master updated: HDDS-16379. Recon returns 500 NPE instead of proxying error when metrics endpoint responds with a non-enum status code (#11197)
This is an automated email from the ASF dual-hosted git repository.
smengcl pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ozone.git
The following commit(s) were added to refs/heads/master by this push:
new 6818707698c HDDS-16379. Recon returns 500 NPE instead of proxying error when metrics endpoint responds with a non-enum status code (#11197)
6818707698c is described below
commit 6818707698c0d151ef51f64f2286d13b8b3ab329
Author: Henry Chen <he...@apache.org>
AuthorDate: Sun Oct 11 09:42:26 2026 +0800
HDDS-16379. Recon returns 500 NPE instead of proxying error when metrics endpoint responds with a non-enum status code (#11197)
---
.../ozone/recon/api/MetricsProxyEndpoint.java | 7 +++-
.../recon/spi/impl/JmxServiceProviderImpl.java | 3 +-
.../spi/impl/PrometheusServiceProviderImpl.java | 3 +-
.../hadoop/ozone/recon/api/TestEndpoints.java | 48 ++++++++++++++++++++++
4 files changed, 55 insertions(+), 6 deletions(-)
diff --git a/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/api/MetricsProxyEndpoint.java b/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/api/MetricsProxyEndpoint.java
index 82fd0f801f9..efc08f6ee0e 100644
--- a/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/api/MetricsProxyEndpoint.java
+++ b/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/api/MetricsProxyEndpoint.java
@@ -71,13 +71,16 @@ public void getMetricsResponse(
HttpURLConnection connection = metricsServiceProvider.getMetricsResponse(
api, uriInfo.getRequestUri().getQuery());
InputStream inputStream;
- if (Response.Status.fromStatusCode(connection.getResponseCode())
- .getFamily() == Response.Status.Family.SUCCESSFUL) {
+ if (Response.Status.Family.familyOf(connection.getResponseCode()) == Response.Status.Family.SUCCESSFUL) {
inputStream = connection.getInputStream();
} else {
// Throw a bad gateway error if HttpResponseCode is not 2xx
httpServletResponse.setStatus(HttpServletResponse.SC_BAD_GATEWAY);
inputStream = connection.getErrorStream();
+ if (inputStream == null) {
+ // The metrics endpoint sent no error body
+ return;
+ }
}
try (
OutputStream outputStream =
diff --git a/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/spi/impl/JmxServiceProviderImpl.java b/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/spi/impl/JmxServiceProviderImpl.java
index d3de292945b..8497b3a0ad2 100644
--- a/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/spi/impl/JmxServiceProviderImpl.java
+++ b/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/spi/impl/JmxServiceProviderImpl.java
@@ -110,8 +110,7 @@ private List<Map<String, Object>> getMetrics(String api, String queryString)
return SecurityUtil.doAsLoginUser(() -> {
HttpURLConnection urlConnection =
getMetricsResponse(api, queryString);
- if (Response.Status.fromStatusCode(urlConnection.getResponseCode())
- .getFamily() == Response.Status.Family.SUCCESSFUL) {
+ if (Response.Status.Family.familyOf(urlConnection.getResponseCode()) == Response.Status.Family.SUCCESSFUL) {
try (InputStream inputStream = urlConnection.getInputStream()) {
Map<String, Object> jsonMap = JsonUtils.getDefaultMapper().readValue(inputStream, Map.class);
Object beansObj = jsonMap.get("beans");
diff --git a/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/spi/impl/PrometheusServiceProviderImpl.java b/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/spi/impl/PrometheusServiceProviderImpl.java
index 0a784c50c90..ee200e02e44 100644
--- a/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/spi/impl/PrometheusServiceProviderImpl.java
+++ b/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/spi/impl/PrometheusServiceProviderImpl.java
@@ -126,8 +126,7 @@ private List<Metric> getMetrics(String api, String queryString)
HttpURLConnection urlConnection =
getMetricsResponse(api, queryString);
List<Metric> metrics = null;
- if (Response.Status.fromStatusCode(urlConnection.getResponseCode())
- .getFamily() == Response.Status.Family.SUCCESSFUL) {
+ if (Response.Status.Family.familyOf(urlConnection.getResponseCode()) == Response.Status.Family.SUCCESSFUL) {
InputStream inputStream = urlConnection.getInputStream();
ObjectMapper mapper = new ObjectMapper();
Map<String, Object> jsonMap = mapper.readValue(inputStream, Map.class);
diff --git a/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/api/TestEndpoints.java b/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/api/TestEndpoints.java
index a8a8cab6403..afb3f4b56e1 100644
--- a/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/api/TestEndpoints.java
+++ b/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/api/TestEndpoints.java
@@ -17,6 +17,7 @@
package org.apache.hadoop.ozone.recon.api;
+import static java.nio.charset.StandardCharsets.UTF_8;
import static org.apache.hadoop.hdds.protocol.MockDatanodeDetails.randomDatanodeDetails;
import static org.apache.hadoop.ozone.container.upgrade.UpgradeUtils.defaultVersionProto;
import static org.apache.hadoop.ozone.recon.OMMetadataManagerTestUtils.getRandomPipeline;
@@ -43,6 +44,7 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
@@ -803,6 +805,52 @@ public void testGetMetricsResponse() throws Exception {
verify(outputStreamMock).write(fileBytes, 0, fileBytes.length);
}
+ @Test
+ public void testGetMetricsResponseWithNonEnumStatusCode() throws Exception {
+ HttpServletResponse responseMock = mock(HttpServletResponse.class);
+ ServletOutputStream outputStreamMock = mock(ServletOutputStream.class);
+ when(responseMock.getOutputStream()).thenReturn(outputStreamMock);
+ UriInfo uriInfoMock = mock(UriInfo.class);
+ URI uriMock = mock(URI.class);
+ when(uriMock.getQuery()).thenReturn("");
+ when(uriInfoMock.getRequestUri()).thenReturn(uriMock);
+
+ // 422 has no Response.Status enum constant; the error body must still be proxied back.
+ byte[] errorBody = "{\"status\":\"error\",\"errorType\":\"bad_data\"}".getBytes(UTF_8);
+ HttpURLConnection urlConnectionMock = mock(HttpURLConnection.class);
+ when(urlConnectionMock.getResponseCode()).thenReturn(422);
+ when(urlConnectionMock.getErrorStream())
+ .thenReturn(new ByteArrayInputStream(errorBody));
+ when(reconUtilsMock.makeHttpCall(any(URLConnectionFactory.class),
+ anyString(), anyBoolean())).thenReturn(urlConnectionMock);
+
+ metricsProxyEndpoint.getMetricsResponse(PROMETHEUS_INSTANT_QUERY_API,
+ uriInfoMock, responseMock);
+
+ verify(responseMock).setStatus(HttpServletResponse.SC_BAD_GATEWAY);
+ verify(outputStreamMock).write(errorBody, 0, errorBody.length);
+ }
+
+ @Test
+ public void testGetMetricsResponseWithNullErrorStream() throws Exception {
+ HttpServletResponse responseMock = mock(HttpServletResponse.class);
+ UriInfo uriInfoMock = mock(UriInfo.class);
+ URI uriMock = mock(URI.class);
+ when(uriMock.getQuery()).thenReturn("");
+ when(uriInfoMock.getRequestUri()).thenReturn(uriMock);
+
+ HttpURLConnection urlConnectionMock = mock(HttpURLConnection.class);
+ when(urlConnectionMock.getResponseCode()).thenReturn(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
+ when(urlConnectionMock.getErrorStream()).thenReturn(null);
+ when(reconUtilsMock.makeHttpCall(any(URLConnectionFactory.class),
+ anyString(), anyBoolean())).thenReturn(urlConnectionMock);
+
+ assertDoesNotThrow(() -> metricsProxyEndpoint.getMetricsResponse(PROMETHEUS_INSTANT_QUERY_API,
+ uriInfoMock, responseMock));
+
+ verify(responseMock).setStatus(HttpServletResponse.SC_BAD_GATEWAY);
+ }
+
@Test
public void testGetClusterState() throws Exception {
Response response = clusterStateEndpoint.getClusterState();
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@ozone.apache.org
For additional commands, e-mail: commits-help@ozone.apache.org