mirror of https://github.com/dapr/java-sdk.git
Add support for HTTP status code in exception. (#1019)
Signed-off-by: Artur Souza <asouza.pro@gmail.com>
This commit is contained in:
parent
304a85d9ae
commit
e0355ceaee
|
@ -71,7 +71,7 @@ public class DaprHttpClientTest {
|
|||
|
||||
assertThrowsDaprException(
|
||||
"ERR_SOMETHING",
|
||||
"ERR_SOMETHING: error message",
|
||||
"ERR_SOMETHING: error message (HTTP status code: 404)",
|
||||
() -> mono.block());
|
||||
}
|
||||
|
||||
|
|
|
@ -135,7 +135,7 @@ public class MethodInvokeIT extends BaseIT {
|
|||
// TODO(artursouza): change this to INTERNAL once runtime is fixed.
|
||||
assertEquals("UNKNOWN", exception.getErrorCode());
|
||||
assertNotNull(exception.getMessage());
|
||||
assertTrue(exception.getMessage().contains("Internal Server Error"));
|
||||
assertTrue(exception.getMessage().contains("HTTP status code: 500"));
|
||||
assertTrue(new String(exception.getPayload()).contains("Internal Server Error"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -122,7 +122,7 @@ public class PubSubIT extends BaseIT {
|
|||
} else {
|
||||
assertThrowsDaprExceptionWithReason(
|
||||
"ERR_PUBSUB_NOT_FOUND",
|
||||
"ERR_PUBSUB_NOT_FOUND: pubsub unknown pubsub is not found",
|
||||
"ERR_PUBSUB_NOT_FOUND: pubsub unknown pubsub is not found (HTTP status code: 404)",
|
||||
"DAPR_PUBSUB_NOT_FOUND",
|
||||
() -> client.publishEvent("unknown pubsub", "mytopic", "payload").block());
|
||||
}
|
||||
|
|
|
@ -65,7 +65,7 @@ public class HttpStateClientIT extends AbstractStateClientIT {
|
|||
// DaprException is guaranteed in the Dapr SDK but getCause() is null in HTTP while present in GRPC implementation.
|
||||
assertThrowsDaprException(
|
||||
"ERR_STATE_STORE_NOT_FOUND",
|
||||
"ERR_STATE_STORE_NOT_FOUND: state store unknown state store is not found",
|
||||
"ERR_STATE_STORE_NOT_FOUND: state store unknown state store is not found (HTTP status code: 400)",
|
||||
() -> daprClient.getState("unknown state store", new State(stateKey), byte[].class).block());
|
||||
}
|
||||
|
||||
|
@ -78,7 +78,7 @@ public class HttpStateClientIT extends AbstractStateClientIT {
|
|||
// DaprException is guaranteed in the Dapr SDK but getCause() is null in HTTP while present in GRPC implementation.
|
||||
assertThrowsDaprException(
|
||||
"ERR_STATE_STORE_NOT_FOUND",
|
||||
"ERR_STATE_STORE_NOT_FOUND: state store unknown state store is not found",
|
||||
"ERR_STATE_STORE_NOT_FOUND: state store unknown state store is not found (HTTP status code: 400)",
|
||||
() -> daprClient.getBulkState(
|
||||
"unknown state store",
|
||||
Collections.singletonList(stateKey),
|
||||
|
|
|
@ -349,7 +349,8 @@ public class DaprHttp implements AutoCloseable {
|
|||
try {
|
||||
return DAPR_ERROR_DETAILS_OBJECT_MAPPER.readValue(json, DaprError.class);
|
||||
} catch (IOException e) {
|
||||
throw new DaprException("UNKNOWN", new String(json, StandardCharsets.UTF_8), json);
|
||||
// Could not parse DaprError. Return null.
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -384,17 +385,13 @@ public class DaprHttp implements AutoCloseable {
|
|||
try {
|
||||
byte[] payload = getBodyBytesOrEmptyArray(response);
|
||||
DaprError error = parseDaprError(payload);
|
||||
if ((error != null) && (error.getErrorCode() != null)) {
|
||||
if (error.getMessage() != null) {
|
||||
future.completeExceptionally(new DaprException(error, payload));
|
||||
} else {
|
||||
future.completeExceptionally(
|
||||
new DaprException(error.getErrorCode(), "HTTP status code: " + response.code(), payload));
|
||||
}
|
||||
if (error != null) {
|
||||
future.completeExceptionally(new DaprException(error, payload, response.code()));
|
||||
return;
|
||||
}
|
||||
|
||||
future.completeExceptionally(new DaprException("UNKNOWN", "HTTP status code: " + response.code(), payload));
|
||||
future.completeExceptionally(
|
||||
new DaprException("UNKNOWN", "", payload, response.code()));
|
||||
return;
|
||||
} catch (DaprException e) {
|
||||
future.completeExceptionally(e);
|
||||
|
|
|
@ -13,7 +13,9 @@ limitations under the License.
|
|||
|
||||
package io.dapr.exceptions;
|
||||
|
||||
import com.google.rpc.Status;
|
||||
import io.grpc.StatusRuntimeException;
|
||||
import io.grpc.protobuf.StatusProto;
|
||||
import reactor.core.Exceptions;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
@ -30,26 +32,32 @@ public class DaprException extends RuntimeException {
|
|||
/**
|
||||
* Dapr's error code for this exception.
|
||||
*/
|
||||
private String errorCode;
|
||||
private final String errorCode;
|
||||
|
||||
/**
|
||||
* The status details for the error.
|
||||
*/
|
||||
private DaprErrorDetails errorDetails;
|
||||
private final DaprErrorDetails errorDetails;
|
||||
|
||||
/**
|
||||
* Optional payload, if the exception came from a response body.
|
||||
*/
|
||||
private byte[] payload;
|
||||
private final byte[] payload;
|
||||
|
||||
/**
|
||||
* Optional HTTP status code, if error happened for an HTTP call (0 if not set).
|
||||
*/
|
||||
private final int httpStatusCode;
|
||||
|
||||
/**
|
||||
* New exception from a server-side generated error code and message.
|
||||
*
|
||||
* @param daprError Server-side error.
|
||||
* @param payload Payload containing the error.
|
||||
* @param payload Optional payload containing the error.
|
||||
* @param httpStatusCode Optional http Status Code (0 if not set).
|
||||
*/
|
||||
public DaprException(DaprError daprError, byte[] payload) {
|
||||
this(daprError.getErrorCode(), daprError.getMessage(), daprError.getDetails(), payload);
|
||||
public DaprException(DaprError daprError, byte[] payload, int httpStatusCode) {
|
||||
this(daprError.getErrorCode(), daprError.getMessage(), daprError.getDetails(), payload, httpStatusCode);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -77,10 +85,11 @@ public class DaprException extends RuntimeException {
|
|||
*
|
||||
* @param errorCode Client-side error code.
|
||||
* @param message Client-side error message.
|
||||
* @param payload Error's raw payload.
|
||||
* @param payload Optional payload containing the error.
|
||||
* @param httpStatusCode Optional http Status Code (0 if not set).
|
||||
*/
|
||||
public DaprException(String errorCode, String message, byte[] payload) {
|
||||
this(errorCode, message, DaprErrorDetails.EMPTY_INSTANCE, payload);
|
||||
public DaprException(String errorCode, String message, byte[] payload, int httpStatusCode) {
|
||||
this(errorCode, message, DaprErrorDetails.EMPTY_INSTANCE, payload, httpStatusCode);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -89,10 +98,12 @@ public class DaprException extends RuntimeException {
|
|||
* @param errorCode Client-side error code.
|
||||
* @param message Client-side error message.
|
||||
* @param errorDetails Details of the error from runtime.
|
||||
* @param payload Payload containing the error.
|
||||
* @param payload Optional payload containing the error.
|
||||
* @param httpStatusCode Optional http Status Code (0 if not set).
|
||||
*/
|
||||
public DaprException(String errorCode, String message, List<Map<String, Object>> errorDetails, byte[] payload) {
|
||||
this(errorCode, message, new DaprErrorDetails(errorDetails), payload);
|
||||
public DaprException(
|
||||
String errorCode, String message, List<Map<String, Object>> errorDetails, byte[] payload, int httpStatusCode) {
|
||||
this(errorCode, message, new DaprErrorDetails(errorDetails), payload, httpStatusCode);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -101,10 +112,29 @@ public class DaprException extends RuntimeException {
|
|||
* @param errorCode Client-side error code.
|
||||
* @param message Client-side error message.
|
||||
* @param errorDetails Details of the error from runtime.
|
||||
* @param payload Payload containing the error.
|
||||
* @param payload Optional payload containing the error.
|
||||
*/
|
||||
public DaprException(String errorCode, String message, DaprErrorDetails errorDetails, byte[] payload) {
|
||||
super(String.format("%s: %s", errorCode, message));
|
||||
this(errorCode, message, errorDetails, payload, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* New Exception from a client-side generated error code and message.
|
||||
*
|
||||
* @param errorCode Client-side error code.
|
||||
* @param message Client-side error message.
|
||||
* @param errorDetails Details of the error from runtime.
|
||||
* @param payload Optional payload containing the error.
|
||||
* @param httpStatusCode Optional http Status Code (0 if not set).
|
||||
*/
|
||||
public DaprException(
|
||||
String errorCode,
|
||||
String message,
|
||||
DaprErrorDetails errorDetails,
|
||||
byte[] payload,
|
||||
int httpStatusCode) {
|
||||
super(buildErrorMessage(errorCode, httpStatusCode, message));
|
||||
this.httpStatusCode = httpStatusCode;
|
||||
this.errorCode = errorCode;
|
||||
this.errorDetails = errorDetails;
|
||||
this.payload = payload;
|
||||
|
@ -120,8 +150,11 @@ public class DaprException extends RuntimeException {
|
|||
* unknown.)
|
||||
*/
|
||||
public DaprException(String errorCode, String message, Throwable cause) {
|
||||
super(String.format("%s: %s", errorCode, emptyIfNull(message)), cause);
|
||||
super(buildErrorMessage(errorCode, 0, message), cause);
|
||||
this.httpStatusCode = 0;
|
||||
this.errorCode = errorCode;
|
||||
this.errorDetails = DaprErrorDetails.EMPTY_INSTANCE;
|
||||
this.payload = null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -137,7 +170,8 @@ public class DaprException extends RuntimeException {
|
|||
*/
|
||||
public DaprException(
|
||||
String errorCode, String message, Throwable cause, DaprErrorDetails errorDetails, byte[] payload) {
|
||||
super(String.format("%s: %s", errorCode, emptyIfNull(message)), cause);
|
||||
super(buildErrorMessage(errorCode, 0, message), cause);
|
||||
this.httpStatusCode = 0;
|
||||
this.errorCode = errorCode;
|
||||
this.errorDetails = errorDetails == null ? DaprErrorDetails.EMPTY_INSTANCE : errorDetails;
|
||||
this.payload = payload;
|
||||
|
@ -170,6 +204,15 @@ public class DaprException extends RuntimeException {
|
|||
return this.payload == null ? null : this.payload.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the exception's http status code, 0 if not applicable.
|
||||
*
|
||||
* @return Http status code (0 if not applicable).
|
||||
*/
|
||||
public int getHttpStatusCode() {
|
||||
return this.httpStatusCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps an exception into DaprException (if not already DaprException).
|
||||
*
|
||||
|
@ -266,7 +309,7 @@ public class DaprException extends RuntimeException {
|
|||
while (e != null) {
|
||||
if (e instanceof StatusRuntimeException) {
|
||||
StatusRuntimeException statusRuntimeException = (StatusRuntimeException) e;
|
||||
com.google.rpc.Status status = io.grpc.protobuf.StatusProto.fromThrowable(statusRuntimeException);
|
||||
Status status = StatusProto.fromThrowable(statusRuntimeException);
|
||||
|
||||
DaprErrorDetails errorDetails = new DaprErrorDetails(status);
|
||||
|
||||
|
@ -289,11 +332,18 @@ public class DaprException extends RuntimeException {
|
|||
return new DaprException(exception);
|
||||
}
|
||||
|
||||
private static String emptyIfNull(String str) {
|
||||
if (str == null) {
|
||||
return "";
|
||||
private static String buildErrorMessage(String errorCode, int httpStatusCode, String message) {
|
||||
String result = ((errorCode == null) || errorCode.isEmpty()) ? "UNKNOWN: " : errorCode + ": ";
|
||||
if ((message == null) || message.isEmpty()) {
|
||||
if (httpStatusCode > 0) {
|
||||
return result + "HTTP status code: " + httpStatusCode;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
return str;
|
||||
if (httpStatusCode > 0) {
|
||||
return result + message + " (HTTP status code: " + httpStatusCode + ")";
|
||||
}
|
||||
return result + message;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -353,7 +353,8 @@ public class DaprClientHttpTest {
|
|||
});
|
||||
|
||||
assertEquals("MYCODE", exception.getErrorCode());
|
||||
assertEquals("MYCODE: My Message", exception.getMessage());
|
||||
assertEquals("MYCODE: My Message (HTTP status code: 500)", exception.getMessage());
|
||||
assertEquals(500, exception.getHttpStatusCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -387,7 +388,7 @@ public class DaprClientHttpTest {
|
|||
});
|
||||
|
||||
assertEquals("UNKNOWN", exception.getErrorCode());
|
||||
assertEquals("UNKNOWN: { \"anything\": 7 }", exception.getMessage());
|
||||
assertEquals("UNKNOWN: HTTP status code: 500", exception.getMessage());
|
||||
assertEquals("{ \"anything\": 7 }", new String(exception.getPayload()));
|
||||
}
|
||||
|
||||
|
@ -1319,8 +1320,10 @@ public class DaprClientHttpTest {
|
|||
"{\"errorCode\":\"ERR_SECRET_STORE_NOT_FOUND\"," +
|
||||
"\"message\":\"error message\"}", MediaTypes.MEDIATYPE_JSON));
|
||||
|
||||
assertThrowsDaprException("ERR_SECRET_STORE_NOT_FOUND", "ERR_SECRET_STORE_NOT_FOUND: error message", () ->
|
||||
daprClientHttp.getSecret(SECRET_STORE_NAME, "key").block()
|
||||
assertThrowsDaprException(
|
||||
"ERR_SECRET_STORE_NOT_FOUND",
|
||||
"ERR_SECRET_STORE_NOT_FOUND: error message (HTTP status code: 404)",
|
||||
() -> daprClientHttp.getSecret(SECRET_STORE_NAME, "key").block()
|
||||
);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue