Response wrong status code for some situation for openAPI (#11864)

* fix:Response wrong status code for some situation for openAPI

* fix:Response wrong status code for some situation for openAPI for PrometheusApiExceptionHandler

* fix:PrometheusApiExceptionHandler status modify

* fix:add unit test

* fix:modify the unit test description

* fix:the code style modify

* fix:the UT modify
This commit is contained in:
publicize-y 2024-04-01 14:11:16 +08:00 committed by GitHub
parent 6461aeb719
commit 2df335d57e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 448 additions and 1 deletions

View File

@ -119,6 +119,11 @@
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-datasource-plugin</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test-autoconfigure</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>

View File

@ -17,6 +17,7 @@
package com.alibaba.nacos.config.server.exception;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;
import com.alibaba.nacos.common.utils.ExceptionUtil;
import com.alibaba.nacos.config.server.monitor.MetricsMonitor;
import com.alibaba.nacos.persistence.monitor.DatasourceMetrics;
@ -47,6 +48,17 @@ public class GlobalExceptionHandler {
return ResponseEntity.status(400).body(ExceptionUtil.getAllExceptionMsg(ex));
}
/**
* For NacosRuntimeException.
*
* @throws com.alibaba.nacos.api.exception.runtime.NacosRuntimeException NacosRuntimeException.
*/
@ExceptionHandler(NacosRuntimeException.class)
public ResponseEntity<String> handleNacosRunTimeException(NacosRuntimeException ex) throws IOException {
MetricsMonitor.getNacosException().increment();
return ResponseEntity.status(ex.getErrCode()).body(ExceptionUtil.getAllExceptionMsg(ex));
}
/**
* For NacosException.
*
@ -57,7 +69,7 @@ public class GlobalExceptionHandler {
MetricsMonitor.getNacosException().increment();
return ResponseEntity.status(ex.getErrCode()).body(ExceptionUtil.getAllExceptionMsg(ex));
}
/**
* For DataAccessException.
*

View File

@ -0,0 +1,75 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.config.server.exception;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;
import com.alibaba.nacos.config.server.controller.v2.HistoryControllerV2;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
@RunWith(SpringRunner.class)
@WebMvcTest(GlobalExceptionHandlerTest.class)
public class GlobalExceptionHandlerTest {
private MockMvc mockMvc;
@Autowired
private WebApplicationContext context;
@MockBean
private HistoryControllerV2 historyControllerV2;
@Before
public void before() {
mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
}
@Test
public void testNacosRunTimeExceptionHandler() throws Exception {
// 设置HistoryControllerV2的行为使其抛出NacosRuntimeException并被GlobalExceptionHandler捕获处理
when(historyControllerV2.getConfigsByTenant("test"))
.thenThrow(new NacosRuntimeException(NacosException.INVALID_PARAM))
.thenThrow(new NacosRuntimeException(NacosException.SERVER_ERROR))
.thenThrow(new NacosRuntimeException(503));
// 执行请求并验证响应码
ResultActions resultActions = mockMvc.perform(get("/v2/cs/history/configs").param("namespaceId", "test"));
resultActions.andExpect(MockMvcResultMatchers.status().is(NacosException.INVALID_PARAM));
// 执行请求并验证响应码
ResultActions resultActions1 = mockMvc.perform(get("/v2/cs/history/configs").param("namespaceId", "test"));
resultActions1.andExpect(MockMvcResultMatchers.status().is(NacosException.SERVER_ERROR));
// 执行请求并验证响应码
ResultActions resultActions2 = mockMvc.perform(get("/v2/cs/history/configs").param("namespaceId", "test"));
resultActions2.andExpect(MockMvcResultMatchers.status().is(503));
}
}

View File

@ -73,6 +73,11 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test-autoconfigure</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>

View File

@ -16,6 +16,7 @@
package com.alibaba.nacos.console.exception;
import com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;
import com.alibaba.nacos.plugin.auth.exception.AccessException;
import com.alibaba.nacos.common.model.RestResultUtils;
import com.alibaba.nacos.common.utils.ExceptionUtil;
@ -51,6 +52,12 @@ public class ConsoleExceptionHandler {
private ResponseEntity<String> handleIllegalArgumentException(IllegalArgumentException e) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(ExceptionUtil.getAllExceptionMsg(e));
}
@ExceptionHandler(NacosRuntimeException.class)
private ResponseEntity<String> handleNacosRuntimeException(NacosRuntimeException e) {
LOGGER.error("got exception. {}", e.getMessage());
return ResponseEntity.status(e.getErrCode()).body(ExceptionUtil.getAllExceptionMsg(e));
}
@ExceptionHandler(Exception.class)
private ResponseEntity<Object> handleException(HttpServletRequest request, Exception e) {

View File

@ -19,6 +19,7 @@ package com.alibaba.nacos.console.exception;
import com.alibaba.nacos.api.annotation.NacosApi;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.exception.api.NacosApiException;
import com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;
import com.alibaba.nacos.api.model.v2.ErrorCode;
import com.alibaba.nacos.api.model.v2.Result;
import com.alibaba.nacos.common.utils.ExceptionUtil;
@ -65,6 +66,12 @@ public class NacosApiExceptionHandler {
LOGGER.error("got exception. {}", e.getErrMsg());
return ResponseEntity.status(e.getErrCode()).body(Result.failure(ErrorCode.SERVER_ERROR, e.getErrMsg()));
}
@ExceptionHandler(NacosRuntimeException.class)
public ResponseEntity<Result<String>> handleNacosRuntimeException(NacosRuntimeException e) {
LOGGER.error("got exception. {} {}", e.getMessage(), ExceptionUtil.getAllExceptionMsg(e));
return ResponseEntity.status(e.getErrCode()).body(Result.failure(ErrorCode.SERVER_ERROR, e.getMessage()));
}
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(HttpMessageNotReadableException.class)

View File

@ -0,0 +1,73 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.console.exception;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;
import com.alibaba.nacos.console.controller.v2.HealthControllerV2;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
@RunWith(SpringRunner.class)
@WebMvcTest(ConsoleExceptionHandlerTest.class)
public class ConsoleExceptionHandlerTest {
private MockMvc mockMvc;
@Autowired
private WebApplicationContext context;
@MockBean
private HealthControllerV2 healthControllerV2;
@Before
public void before() {
mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
}
@Test
public void testNacosRunTimeExceptionHandler() throws Exception {
// 设置HealthControllerV2的行为使其抛出NacosRuntimeException并被ConsoleExceptionHandler捕获处理
when(healthControllerV2.liveness())
.thenThrow(new NacosRuntimeException(NacosException.INVALID_PARAM))
.thenThrow(new NacosRuntimeException(NacosException.SERVER_ERROR))
.thenThrow(new NacosRuntimeException(503));
// 执行请求并验证响应码
ResultActions resultActions = mockMvc.perform(get("/v2/console/health/liveness"));
resultActions.andExpect(MockMvcResultMatchers.status().is(NacosException.INVALID_PARAM));
// 执行请求并验证响应码
ResultActions resultActions1 = mockMvc.perform(get("/v2/console/health/liveness"));
resultActions1.andExpect(MockMvcResultMatchers.status().is(NacosException.SERVER_ERROR));
// 执行请求并验证响应码
ResultActions resultActions2 = mockMvc.perform(get("/v2/console/health/liveness"));
resultActions2.andExpect(MockMvcResultMatchers.status().is(503));
}
}

View File

@ -0,0 +1,74 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.console.exception;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;
import com.alibaba.nacos.console.controller.v2.NamespaceControllerV2;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
@RunWith(SpringRunner.class)
@WebMvcTest(NacosApiExceptionHandler.class)
public class NacosApiExceptionHandlerTest {
private MockMvc mockMvc;
@Autowired
private WebApplicationContext context;
@MockBean
private NamespaceControllerV2 namespaceControllerV2;
@Before
public void before() {
mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
}
@Test
public void testNacosRunTimeExceptionHandler() throws Exception {
// 设置NamespaceControllerV2的行为使其抛出NacosRuntimeException并被NacosApiExceptionHandler捕获处理
when(namespaceControllerV2.createNamespace(any()))
.thenThrow(new NacosRuntimeException(NacosException.INVALID_PARAM))
.thenThrow(new NacosRuntimeException(NacosException.SERVER_ERROR))
.thenThrow(new NacosRuntimeException(503));
// 执行请求并验证响应码
ResultActions resultActions = mockMvc.perform(post("/v2/console/namespace"));
resultActions.andExpect(MockMvcResultMatchers.status().is(NacosException.INVALID_PARAM));
// 执行请求并验证响应码
ResultActions resultActions1 = mockMvc.perform(post("/v2/console/namespace"));
resultActions1.andExpect(MockMvcResultMatchers.status().is(NacosException.SERVER_ERROR));
// 执行请求并验证响应码
ResultActions resultActions2 = mockMvc.perform(post("/v2/console/namespace"));
resultActions2.andExpect(MockMvcResultMatchers.status().is(503));
}
}

View File

@ -17,6 +17,7 @@
package com.alibaba.nacos.naming.exception;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;
import com.alibaba.nacos.common.utils.ExceptionUtil;
import com.alibaba.nacos.naming.misc.Loggers;
import org.springframework.http.HttpStatus;
@ -44,6 +45,18 @@ public class ResponseExceptionHandler {
Loggers.SRV_LOG.error("got exception. {}", e.getErrMsg(), ExceptionUtil.getAllExceptionMsg(e));
return ResponseEntity.status(e.getErrCode()).body(e.getMessage());
}
/**
* Handle {@link com.alibaba.nacos.api.exception.runtime.NacosRuntimeException}.
*
* @param e NacosException
* @return ResponseEntity
*/
@ExceptionHandler(NacosRuntimeException.class)
public ResponseEntity<String> handleNacosRuntimeException(NacosRuntimeException e) {
Loggers.SRV_LOG.error("got exception. {}", e.getMessage(), ExceptionUtil.getAllExceptionMsg(e));
return ResponseEntity.status(e.getErrCode()).body(e.getMessage());
}
/**
* Handle {@link IllegalArgumentException}.

View File

@ -0,0 +1,90 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.naming.exception;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;
import com.alibaba.nacos.naming.controllers.v2.InstanceControllerV2;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
@RunWith(SpringRunner.class)
@WebAppConfiguration
@ContextConfiguration(classes = {ResponseExceptionHandler.class})
public class ResponseExceptionHandlerTest {
private MockMvc mockMvc;
@Autowired
private WebApplicationContext context;
@MockBean
private InstanceControllerV2 instanceControllerV2;
@Before
public void before() {
mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
}
@Test
public void testNacosRunTimeExceptionHandler() throws Exception {
// 设置InstanceControllerV2的行为使其抛出NacosRuntimeException并被ResponseExceptionHandler捕获处理
when(instanceControllerV2.register(any()))
.thenThrow(new NacosRuntimeException(NacosException.INVALID_PARAM))
.thenThrow(new NacosRuntimeException(NacosException.SERVER_ERROR))
.thenThrow(new NacosRuntimeException(503));
// 执行请求并验证响应码
ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.post("/v2/ns/instance")
.param("namespaceId", "public").param("groupName", "G")
.param("serviceName", "s").param("ip", "192.168.0.1")
.param("port", "8080").param("ephemeral", "true"));
resultActions.andExpect(MockMvcResultMatchers.status().is(NacosException.INVALID_PARAM));
// 执行请求并验证响应码
ResultActions resultActions1 = mockMvc.perform(post("/v2/ns/instance")
.param("namespaceId", "public").param("groupName", "G")
.param("serviceName", "s").param("ip", "192.168.0.1")
.param("port", "8080")
.param("ephemeral", "true"));
resultActions1.andExpect(MockMvcResultMatchers.status().is(NacosException.SERVER_ERROR));
// 执行请求并验证响应码
ResultActions resultActions2 = mockMvc.perform(post("/v2/ns/instance")
.param("namespaceId", "public").param("groupName", "G")
.param("serviceName", "s").param("ip", "192.168.0.1")
.param("port", "8080")
.param("ephemeral", "true"));
resultActions2.andExpect(MockMvcResultMatchers.status().is(503));
}
}

View File

@ -43,6 +43,11 @@
<groupId>${project.groupId}</groupId>
<artifactId>nacos-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test-autoconfigure</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

View File

@ -17,6 +17,7 @@
package com.alibaba.nacos.prometheus.exception;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;
import com.alibaba.nacos.api.model.v2.Result;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -45,5 +46,11 @@ public class PrometheusApiExceptionHandler {
LOGGER.error("got exception. {}", e.getErrMsg());
return ResponseEntity.internalServerError().body(Result.failure(e.getErrMsg()));
}
@ExceptionHandler(NacosRuntimeException.class)
public ResponseEntity<Result<String>> handleNacosRuntimeException(NacosRuntimeException e) {
LOGGER.error("got exception. {}", e.getMessage());
return ResponseEntity.status(e.getErrCode()).body(Result.failure(e.getMessage()));
}
}

View File

@ -0,0 +1,74 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.prometheus.controller.exception;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;
import com.alibaba.nacos.prometheus.controller.PrometheusController;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
@RunWith(SpringRunner.class)
@WebMvcTest(PrometheusApiExceptionHandlerTest.class)
public class PrometheusApiExceptionHandlerTest {
private MockMvc mockMvc;
@Autowired
private WebApplicationContext context;
@MockBean
private PrometheusController prometheusController;
@Before
public void before() {
mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
}
@Test
public void testNacosRunTimeExceptionHandler() throws Exception {
// 设置PrometheusController的行为使其抛出NacosRuntimeException并被PrometheusApiExceptionHandler捕获处理
when(prometheusController.metric())
.thenThrow(new NacosRuntimeException(NacosException.INVALID_PARAM))
.thenThrow(new NacosRuntimeException(NacosException.SERVER_ERROR))
.thenThrow(new NacosRuntimeException(503));
// 执行请求并验证响应码
ResultActions resultActions = mockMvc.perform(get("/prometheus"));
resultActions.andExpect(MockMvcResultMatchers.status().is(NacosException.INVALID_PARAM));
// 执行请求并验证响应码
ResultActions resultActions1 = mockMvc.perform(get("/prometheus"));
resultActions1.andExpect(MockMvcResultMatchers.status().is(NacosException.SERVER_ERROR));
// 执行请求并验证响应码
ResultActions resultActions2 = mockMvc.perform(get("/prometheus"));
resultActions2.andExpect(MockMvcResultMatchers.status().is(503));
}
}