diff --git a/src/main/java/com/uid2/shared/attest/UidCoreClient.java b/src/main/java/com/uid2/shared/attest/UidCoreClient.java index 75b4574b..4f090739 100644 --- a/src/main/java/com/uid2/shared/attest/UidCoreClient.java +++ b/src/main/java/com/uid2/shared/attest/UidCoreClient.java @@ -89,8 +89,12 @@ private InputStream internalDownload(String path) throws CloudStorageException { inputStream = getWithAttest(path); } return inputStream; + } catch (CloudStorageException e) { + throw e; } catch (Exception e) { - throw new CloudStorageException("download error: " + e.getMessage(), e); + throw new CloudStorageException( + "E12: Data Download Failure - exception: " + e.getClass().getSimpleName() + + ". Please visit UID2 guides for troubleshooting", e); } } @@ -108,7 +112,9 @@ private InputStream getWithAttest(String path) throws IOException, AttestationRe HttpResponse httpResponse; httpResponse = sendHttpRequest(path, attestationToken); if (httpResponse.statusCode() != 200) { - throw new CloudStorageException(String.format("Non-success response from core on request to %s. Status code: %d", path, httpResponse.statusCode())); + throw new CloudStorageException(String.format( + "E12: Data Download Failure - HTTP response code %d. Please visit UID2 guides for troubleshooting", + httpResponse.statusCode())); } return Utils.convertHttpResponseToInputStream(httpResponse); } diff --git a/src/main/java/com/uid2/shared/cloud/URLStorageWithMetadata.java b/src/main/java/com/uid2/shared/cloud/URLStorageWithMetadata.java index ed6c00db..65ed15e3 100644 --- a/src/main/java/com/uid2/shared/cloud/URLStorageWithMetadata.java +++ b/src/main/java/com/uid2/shared/cloud/URLStorageWithMetadata.java @@ -48,8 +48,8 @@ public InputStream download(String cloudPath) throws CloudStorageException { if (responseCode >= 200 && responseCode < 300) { return httpConn.getInputStream(); } else { - throw new CloudStorageException("Cannot download required files, HTTP response code " + responseCode - + ", please visit UID2 guides for more details"); + throw new CloudStorageException("E12: Data Download Failure - HTTP response code " + responseCode + + ". Please visit UID2 guides for troubleshooting"); } } catch (CloudStorageException e) { @@ -58,8 +58,8 @@ public InputStream download(String cloudPath) throws CloudStorageException { } catch (Throwable t) { // Do not log the original exception as it may contain sensitive information such as the pre-signed URL - throw new CloudStorageException("Cannot download required files, exception: " + t.getClass().getSimpleName() + - ", please visit UID2 guides for more details"); + throw new CloudStorageException("E12: Data Download Failure - exception: " + t.getClass().getSimpleName() + + ". Please visit UID2 guides for troubleshooting"); } } diff --git a/src/main/java/com/uid2/shared/vertx/CloudSyncVerticle.java b/src/main/java/com/uid2/shared/vertx/CloudSyncVerticle.java index a06f4213..fa195ed8 100644 --- a/src/main/java/com/uid2/shared/vertx/CloudSyncVerticle.java +++ b/src/main/java/com/uid2/shared/vertx/CloudSyncVerticle.java @@ -400,8 +400,13 @@ private void cloudDownloadBlocking(String s3Path) throws Exception { downloadFailureTimer.record(java.time.Duration.ofMillis(cloudDownloadTimeMs)); // Be careful as the s3Path may contain the pre-signed S3 token, so do not log the whole path - LOGGER.error("download error: " + ex.getClass().getSimpleName()); - throw new CloudStorageException("Download failed"); + LOGGER.error("Cloud storage download error, exception type: " + ex.getClass().getSimpleName()); + + if (ex instanceof CloudStorageException) { + throw (CloudStorageException) ex; + } + throw new CloudStorageException("Failed to download file from cloud storage, exception: " + + ex.getClass().getSimpleName() + ", please check network connectivity and service availability"); } } diff --git a/src/test/java/com/uid2/shared/attest/UidCoreClientTest.java b/src/test/java/com/uid2/shared/attest/UidCoreClientTest.java index e55849fa..c870cdc6 100644 --- a/src/test/java/com/uid2/shared/attest/UidCoreClientTest.java +++ b/src/test/java/com/uid2/shared/attest/UidCoreClientTest.java @@ -72,7 +72,7 @@ public void Download_AttestInternalFail_ExceptionThrown() throws IOException, At CloudStorageException result = assertThrows(CloudStorageException.class, () -> { uidCoreClient.download("https://download"); }); - String expectedExceptionMessage = "download error: AttestationResponseCode: AttestationFailure, test failure"; + String expectedExceptionMessage = "E12: Data Download Failure - exception: AttestationResponseHandlerException. Please visit UID2 guides for troubleshooting"; assertEquals(expectedExceptionMessage, result.getMessage()); } @@ -100,4 +100,93 @@ void getJwtReturnsCoreToken() { when(mockAttestationResponseHandler.getCoreJWT()).thenReturn("coreJWT"); Assertions.assertEquals("coreJWT", this.uidCoreClient.getJWT()); } + + @Test + public void Download_Http403Error_LogsStatusCodeAndEndpoint() throws IOException, AttestationResponseHandlerException { + HttpResponse mockHttpResponse = mock(HttpResponse.class); + when(mockHttpResponse.statusCode()).thenReturn(403); + when(mockHttpClient.get(eq("https://core-prod.uidapi.com/sites/refresh"), any(HashMap.class))).thenReturn(mockHttpResponse); + + CloudStorageException result = assertThrows(CloudStorageException.class, () -> { + uidCoreClient.download("https://core-prod.uidapi.com/sites/refresh"); + }); + + assertAll( + () -> assertTrue(result.getMessage().contains("E12: Data Download Failure"), + "Should contain E12 error code"), + () -> assertTrue(result.getMessage().contains("HTTP response code 403"), + "Should contain HTTP status code 403"), + () -> assertTrue(result.getMessage().contains("Please visit UID2 guides for troubleshooting"), + "Should reference documentation") + ); + } + + @Test + public void Download_Http404Error_LogsStatusCode() throws IOException, AttestationResponseHandlerException { + HttpResponse mockHttpResponse = mock(HttpResponse.class); + when(mockHttpResponse.statusCode()).thenReturn(404); + when(mockHttpClient.get(eq("https://core-prod.uidapi.com/keys/refresh"), any(HashMap.class))).thenReturn(mockHttpResponse); + + CloudStorageException result = assertThrows(CloudStorageException.class, () -> { + uidCoreClient.download("https://core-prod.uidapi.com/keys/refresh"); + }); + + assertAll( + () -> assertTrue(result.getMessage().contains("HTTP response code 404"), + "Should contain HTTP status code 404"), + () -> assertTrue(result.getMessage().contains("E12: Data Download Failure"), + "Should contain E12 error code") + ); + } + + @Test + public void Download_Http500Error_LogsStatusCode() throws IOException, AttestationResponseHandlerException { + HttpResponse mockHttpResponse = mock(HttpResponse.class); + when(mockHttpResponse.statusCode()).thenReturn(500); + when(mockHttpClient.get(eq("https://core-prod.uidapi.com/salts/refresh"), any(HashMap.class))).thenReturn(mockHttpResponse); + + CloudStorageException result = assertThrows(CloudStorageException.class, () -> { + uidCoreClient.download("https://core-prod.uidapi.com/salts/refresh"); + }); + + assertAll( + () -> assertTrue(result.getMessage().contains("E12: Data Download Failure"), + "Should contain E12 error code"), + () -> assertTrue(result.getMessage().contains("HTTP response code 500"), + "Should contain HTTP status code 500") + ); + } + + @Test + public void Download_Http503Error_LogsStatusCode() throws IOException, AttestationResponseHandlerException { + HttpResponse mockHttpResponse = mock(HttpResponse.class); + when(mockHttpResponse.statusCode()).thenReturn(503); + when(mockHttpClient.get(eq("https://core-integ.uidapi.com/clients/refresh"), any(HashMap.class))).thenReturn(mockHttpResponse); + + CloudStorageException result = assertThrows(CloudStorageException.class, () -> { + uidCoreClient.download("https://core-integ.uidapi.com/clients/refresh"); + }); + + assertTrue(result.getMessage().contains("HTTP response code 503"), + "Should contain HTTP status code 503"); + } + + @Test + public void Download_NetworkError_LogsExceptionType() throws IOException, AttestationResponseHandlerException { + IOException networkException = new IOException("Connection timeout"); + when(mockHttpClient.get(anyString(), any(HashMap.class))).thenThrow(networkException); + + CloudStorageException result = assertThrows(CloudStorageException.class, () -> { + uidCoreClient.download("https://core-prod.uidapi.com/sites/refresh"); + }); + + assertAll( + () -> assertTrue(result.getMessage().contains("E12: Data Download Failure"), + "Should contain E12 error code"), + () -> assertTrue(result.getMessage().contains("exception: IOException"), + "Should log exception type"), + () -> assertTrue(result.getMessage().contains("Please visit UID2 guides for troubleshooting"), + "Should reference documentation") + ); + } }