public static JsonRpcResponse fromString(String rawResponse) { JsonParser parser = new JsonParser(); JsonObject response = parser.parse(rawResponse).getAsJsonObject(); JsonElement id = response.get("id"); JsonElement errorElement = response.get("error"); int responseStatus = HttpServletResponse.SC_OK; String error; if (! (errorElement instanceof JsonNull)) { if (errorElement instanceof JsonObject) { error = errorElement.toString(); // try parsing it into RpcCallException to get the HttpStatus from there RpcCallException rpcEx = RpcCallException.fromJson(error); if (rpcEx != null) { responseStatus = rpcEx.getCategory().getHttpStatus(); JsonElement resultElement = response.get("result"); return new JsonRpcResponse(id, resultElement == null ? JsonNull.INSTANCE : resultElement, errorElement, responseStatus); } } error = errorElement.getAsString(); if (StringUtils.isNotBlank(error)) { responseStatus = HttpServletResponse.SC_INTERNAL_SERVER_ERROR; } } JsonElement resultElement = response.get("result"); return new JsonRpcResponse(id, resultElement == null ? JsonNull.INSTANCE : resultElement, errorElement, responseStatus); }
if (rawObject instanceof JsonObject) { JsonObject object = (JsonObject) rawObject; Category category = getCategory(object); String message = getMessage(object); RpcCallException retval = new RpcCallException(category, message);
@Test public void testFromJson_ErrorWithoutCategory() { String error = "{\"id\":\"com.sixt.service.foobar\",\"code\":500,\"message\":\"error message\",\"status\":\"Internal Server Error\"}"; RpcCallException ex = RpcCallException.fromJson(error); assertThat(ex.getCategory()).isEqualTo(RpcCallException.Category.InternalServerError); }
@Test public void testFromJson_ErrorWithDetailInsteadOfMessage() { String error = "{\"id\":\"com.sixt.service.foobar\",\"code\":500,\"detail\":\"error message\",\"status\":\"Internal Server Error\"}"; RpcCallException ex = RpcCallException.fromJson(error); assertThat(ex.getCategory()).isEqualTo(RpcCallException.Category.InternalServerError); assertThat(ex.getMessage()).isEqualTo("error message"); }
@Test public void testFromJson_CategoryNotANumber() { String error = "{\"sxerror\":\"1\",\"source\":\"go.micro.client\",\"category\":\"not-a-number\"}"; RpcCallException ex = RpcCallException.fromJson(error); assertThat(ex).isNotNull(); assertThat(ex.getCategory()).isEqualTo(RpcCallException.Category.InternalServerError); // Switch to default Category when }
@Test public void testFromJson_CategoryAsNull() { String error = "{\"sxerror\":\"1\",\"source\":\"go.micro.client\",\"category\":null}"; RpcCallException ex = RpcCallException.fromJson(error); assertThat(ex).isNotNull(); assertThat(ex.getCategory()).isEqualTo(RpcCallException.Category.InternalServerError); // Switch to default Category when }
@Test public void testFromJson_CategoryAsObject() { String error = "{\"sxerror\":\"1\",\"source\":\"go.micro.client\",\"category\":{}}"; RpcCallException ex = RpcCallException.fromJson(error); assertThat(ex).isNotNull(); assertThat(ex.getCategory()).isEqualTo(RpcCallException.Category.InternalServerError); // Switch to default Category when }
@Test public void testFromJson_CategoryAsFloatingPoint() { String error = "{\"sxerror\":\"1\",\"source\":\"go.micro.client\",\"category\":\1.2345}"; RpcCallException ex = RpcCallException.fromJson(error); assertThat(ex).isNotNull(); assertThat(ex.getCategory()).isEqualTo(RpcCallException.Category.InternalServerError); // Switch to default Category when }
@Test public void decodeException_nullContentPassed_InternalServerErrorShouldBeReturned() throws RpcCallException { byte[] content = null; RpcCallException exception = decoder.decodeException(response(content)); assertThat(exception.getCategory()).isEqualTo(InternalServerError); assertThat(exception.getMessage()).isEqualTo("Empty response received"); }
@Test public void decodeException_zeroLengthContentPassed_InternalServerErrorShouldBeReturned() throws RpcCallException { byte[] content = new byte[0]; RpcCallException exception = decoder.decodeException(response(content)); assertThat(exception.getCategory()).isEqualTo(InternalServerError); assertThat(exception.getMessage()).isEqualTo("Empty response received"); }
@Test public void testFromJson_mediumBadData() { String error = "{\"sxerror\":\"1\",\"source\":\"go.micro.client\",\"category\":408,\"code\":\"unexpected_error\",\"message\":\"call timeout: context deadline exceeded\",\"data\":\"'*errors.Error' with error '{\\\"id\\\":\\\"go.micro.client\\\",\\\"code\\\":408,\\\"detail\\\":\\\"call timeout: context deadline exceeded\\\",\\\"status\\\":\\\"Request Timeout\\\"}' cannot be mapped to a known representation. Data: \\u0026errors.Error{Id:\\\"go.micro.client\\\", Code:408, Detail:\\\"call timeout: context deadline exceeded\\\", Status:\\\"Request Timeout\\\"}\",\"retriable\":false}"; RpcCallException ex = RpcCallException.fromJson(error); assertThat(ex).isNotNull(); assertThat(ex.getCategory()).isEqualTo(RpcCallException.Category.InternalServerError); // Switch to default Category when assertThat(ex.getErrorCode()).isEqualTo("unexpected_error"); assertThat(ex.getMessage()).isEqualTo("call timeout: context deadline exceeded"); assertThat(ex.getData()).isNotNull(); assertThat(ex.isRetriable()).isFalse(); }
@Override public Request newRequest(String uri) { Request retval = mock(Request.class); try { if (requestsTimeout || (isFirstRequestTimeout && requests.isEmpty())) { when(retval.send()).thenThrow(new TimeoutException()); } else { when(retval.send()).thenReturn(httpResponse); } if (requestsFail && featureFlag.equals("true")) { when(httpResponse.getStatus()).thenReturn(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); } else if (responseException != null) { when(httpResponse.getStatus()).thenReturn(responseException.getCategory().getHttpStatus()); } else { when(httpResponse.getStatus()).thenReturn(HttpServletResponse.SC_OK); } } catch (Exception e) { e.printStackTrace(); } when(retval.method(anyString())).thenReturn(retval); when(retval.content(any(ContentProvider.class))).thenReturn(retval); when(retval.timeout(anyLong(), any(TimeUnit.class))).thenReturn(retval); requests.add(uri); return retval; }
@Test public void noInstances() { //no service endpoints available int errorCount = 0; try { rpcClient.callSynchronous(FrameworkTest.Foobar.newBuilder().build(), new OrangeContext()); } catch (RpcCallException ex) { errorCount++; assertThat(ex.getCategory()).isEqualTo(RpcCallException.Category.InternalServerError); } assertThat(errorCount).isEqualTo(1); }
@SuppressWarnings("unchecked") private JsonRpcResponse dispatchJsonRpcRequest(JsonRpcRequest rpcRequest, OrangeContext cxt) { JsonRpcResponse jsonResponse = new JsonRpcResponse(rpcRequest.getId(), JsonNull.INSTANCE, JsonNull.INSTANCE, HttpServletResponse.SC_OK); try { ServiceMethodHandler handler = handlers.getMethodHandler(rpcRequest.getMethod()); Message innerRequest = convertJsonToProtobuf(handler, rpcRequest); JsonElement idElement = rpcRequest.getId(); if (idElement == null) { jsonResponse.setId(new JsonPrimitive(-1)); } Message innerResponse = invokeHandlerChain(rpcRequest.getMethod(), handler, innerRequest, cxt); jsonResponse.setResult(ProtobufUtil.protobufToJson(innerResponse)); } catch (RpcCallException rpcEx) { logger.debug("Error processing request", rpcEx); jsonResponse.setError(rpcEx.toJson()); jsonResponse.setStatusCode(rpcEx.getCategory().getHttpStatus()); } catch (Exception ex) { logger.warn("Error processing request", ex); if (ex.getMessage() != null) { jsonResponse.setError(new JsonPrimitive(ex.getMessage())); } jsonResponse.setStatusCode(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); } return jsonResponse; }
public void setResponseException(RpcCallException responseException) { this.responseException = responseException; if (featureFlag.equals("true")) { when(httpResponse.getStatus()).thenReturn(responseException.getCategory().getHttpStatus()); } String response = "{\"error\":" + responseException.toJson() + ",\"result\":{}}"; when(httpResponse.getContentAsString()).thenReturn(response); RpcEnvelope.Response pbResponse = RpcEnvelope.Response.newBuilder(). setError(responseException.toJson().toString()).build(); byte[] responseArray = pbResponse.toByteArray(); byte[] headerLength = Ints.toByteArray(responseArray.length); byte[] bodyLength = Ints.toByteArray(0); byte[] overallPayload = concatAll(headerLength, responseArray, bodyLength); when(httpResponse.getContent()).thenReturn(overallPayload); }
@Test public void allInstancesTimeOut() { //Create 2 servers and have both timeout. Set retries to 1. Send request. //The response from the 2nd should be returned. loadBalancer.addServiceEndpoint(new ServiceEndpoint(executor, "localhost:20001", "dc1", dependencyHealthCheck)); loadBalancer.addServiceEndpoint(new ServiceEndpoint(executor, "localhost:20002", "dc1", dependencyHealthCheck)); rpcClient = clientFactory.newClient(serviceName, "testing", FrameworkTest.Foobar.class). withRetries(1).build(); httpClient.makeRequestsTimeout(); int failureCount = 0; try { rpcClient.callSynchronous(FrameworkTest.Foobar.newBuilder().build(), new OrangeContext()); } catch (RpcCallException ex) { failureCount++; assertThat(ex.getCategory()).isEqualTo(RpcCallException.Category.RequestTimedOut); } assertThat(failureCount).isEqualTo(1); assertThat(httpClient.verifyRequestsProcessed(1, "localhost:20001")).isTrue(); assertThat(httpClient.verifyRequestsProcessed(1, "localhost:20002")).isTrue(); }
@Test public void retriableError() { //Create 2 servers and have both throw an exception that is retriable. //The exception should be thrown locally loadBalancer.addServiceEndpoint(new ServiceEndpoint(executor, "localhost:20001", "dc1", dependencyHealthCheck)); loadBalancer.addServiceEndpoint(new ServiceEndpoint(executor, "localhost:20002", "dc1", dependencyHealthCheck)); rpcClient = clientFactory.newClient(serviceName, "testing", FrameworkTest.Foobar.class). withRetries(1).build(); httpClient.setResponseException(new RpcCallException(RpcCallException.Category. InternalServerError, "test1234").withSource("testing567")); int failureCount = 0; try { rpcClient.callSynchronous(FrameworkTest.Foobar.newBuilder().build(), new OrangeContext()); } catch (RpcCallException ex) { failureCount++; assertThat(ex.getCategory()).isEqualTo(RpcCallException.Category.InternalServerError); assertThat(ex.getMessage()).isEqualTo("test1234"); assertThat(ex.getSource()).isEqualTo("testing567"); } assertThat(failureCount).isEqualTo(1); assertThat(httpClient.verifyRequestsProcessed(2)).isTrue(); }
@Test public void nonRetriableError() { //Create 2 servers and have the first throw an exception that is not retriable. //The exception should be thrown and not retried with the other node loadBalancer.addServiceEndpoint(new ServiceEndpoint(executor, "localhost:20001", "dc1", dependencyHealthCheck)); loadBalancer.addServiceEndpoint(new ServiceEndpoint(executor, "localhost:20002", "dc1", dependencyHealthCheck)); rpcClient = clientFactory.newClient(serviceName, "testing", FrameworkTest.Foobar.class). withRetries(1).build(); httpClient.setResponseException(new RpcCallException(RpcCallException.Category. InsufficientPermissions, "test").withSource("testing")); int failureCount = 0; try { rpcClient.callSynchronous(FrameworkTest.Foobar.newBuilder().build(), new OrangeContext()); } catch (RpcCallException ex) { failureCount++; assertThat(ex.getCategory()).isEqualTo(RpcCallException.Category.InsufficientPermissions); assertThat(ex.getMessage()).isEqualTo("test"); } assertThat(failureCount).isEqualTo(1); assertThat(httpClient.verifyRequestsProcessed(1)).isTrue(); }
context.getRpcOriginMethod()); } catch (RpcCallException rpcEx) { sendErrorResponse(resp, rpcRequest, rpcEx.toString(), rpcEx.getCategory().getHttpStatus()); if (span != null) { Tags.ERROR.set(span, true);