From 295a77fdae4ebcde6285ab4a2e6746b07c73b47a Mon Sep 17 00:00:00 2001 From: brianwyka Date: Mon, 19 Jul 2021 08:15:23 -0700 Subject: [PATCH 1/3] content-http: ContentHttpValidated progress --- .../file/http/ContentHttpValidated.java | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/http/ContentHttpValidated.java diff --git a/enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/http/ContentHttpValidated.java b/enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/http/ContentHttpValidated.java new file mode 100644 index 0000000..2fd40fe --- /dev/null +++ b/enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/http/ContentHttpValidated.java @@ -0,0 +1,77 @@ +package com.optum.sourcehawk.enforcer.file.http; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.optum.sourcehawk.enforcer.EnforcerResult; +import com.optum.sourcehawk.enforcer.file.AbstractFileEnforcer; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.NonNull; +import lombok.val; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.stream.Collectors; + +/** + * A file enforcer which makes an HTTP request to the configured URL + * to validate the file contents + * + * @author brianwyka + */ +@Builder(builderClassName = "Builder") +@JsonDeserialize(builder = ContentHttpValidated.Builder.class) +@AllArgsConstructor(staticName = "validated") +public class ContentHttpValidated extends AbstractFileEnforcer { + + private static final int DEFAULT_BUFFER_SIZE = 8192; + private static final String HTTP_RESPONSE_ERROR_MESSAGE_TEMPLATE = "Validation failed with HTTP response code [%d] and message [%s]"; + + /** + * The URL in which to make a POST request, to validate the file contents + */ + private final String url; + + /** + * The amount of time allowed to connect to URL before timing out + */ + private final int connectTimeout; + + /** + * The amount of time allowed to read response from URL before timing out + */ + private final int readTimeout; + + /** {@inheritDoc} */ + @Override + protected EnforcerResult enforceInternal(final @NonNull InputStream actualFileInputStream) throws IOException { + val httpUrlConnection = (HttpURLConnection) new URL(url).openConnection(); + httpUrlConnection.setDoOutput(true); + httpUrlConnection.setRequestMethod("POST"); + httpUrlConnection.setRequestProperty("Content-Type", "text/plain"); + httpUrlConnection.setRequestProperty("Accept", "text/plain"); + httpUrlConnection.setConnectTimeout(connectTimeout == 0 ? 500 : connectTimeout); + httpUrlConnection.setReadTimeout(readTimeout == 0 ? 500 : readTimeout); + try (val outputStream = httpUrlConnection.getOutputStream()) { + val buffer = new byte[DEFAULT_BUFFER_SIZE]; + int read; + while ((read = actualFileInputStream.read(buffer, 0, DEFAULT_BUFFER_SIZE)) >= 0) { + outputStream.write(buffer, 0, read); + } + } + val responseCode = httpUrlConnection.getResponseCode(); + if (responseCode >= 200 && responseCode < 300) { + return EnforcerResult.passed(); + } + try (val errorStream = httpUrlConnection.getErrorStream(); + val bufferedReader = new BufferedReader(new InputStreamReader(errorStream))) { + val responseMessage = bufferedReader.lines() + .collect(Collectors.joining()); + return EnforcerResult.failed(String.format(HTTP_RESPONSE_ERROR_MESSAGE_TEMPLATE, responseCode, responseMessage)); + } + } + +} From b7812cc51c80d5bc5d110f8ec66eee3f44c67685 Mon Sep 17 00:00:00 2001 From: brianwyka Date: Mon, 19 Jul 2021 08:22:49 -0700 Subject: [PATCH 2/3] content-http: Add error handling distinction to ContentHttpvalidated --- .../enforcer/file/http/ContentHttpValidated.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/http/ContentHttpValidated.java b/enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/http/ContentHttpValidated.java index 2fd40fe..f4f002c 100644 --- a/enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/http/ContentHttpValidated.java +++ b/enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/http/ContentHttpValidated.java @@ -28,7 +28,8 @@ public class ContentHttpValidated extends AbstractFileEnforcer { private static final int DEFAULT_BUFFER_SIZE = 8192; - private static final String HTTP_RESPONSE_ERROR_MESSAGE_TEMPLATE = "Validation failed with HTTP response code [%d] and message [%s]"; + private static final String HTTP_RESPONSE_VALIDATION_MESSAGE_TEMPLATE = "Validation failed with reason: %s"; + private static final String HTTP_RESPONSE_ERROR_MESSAGE_TEMPLATE = "HTTP [%s] error performing validation: %s"; /** * The URL in which to make a POST request, to validate the file contents @@ -62,15 +63,19 @@ protected EnforcerResult enforceInternal(final @NonNull InputStream actualFileIn outputStream.write(buffer, 0, read); } } - val responseCode = httpUrlConnection.getResponseCode(); - if (responseCode >= 200 && responseCode < 300) { + val responseCode = String.valueOf(httpUrlConnection.getResponseCode()); + if (responseCode.startsWith("2")) { return EnforcerResult.passed(); } try (val errorStream = httpUrlConnection.getErrorStream(); val bufferedReader = new BufferedReader(new InputStreamReader(errorStream))) { val responseMessage = bufferedReader.lines() .collect(Collectors.joining()); - return EnforcerResult.failed(String.format(HTTP_RESPONSE_ERROR_MESSAGE_TEMPLATE, responseCode, responseMessage)); + if (responseCode.startsWith("4")) { + return EnforcerResult.failed(String.format(HTTP_RESPONSE_VALIDATION_MESSAGE_TEMPLATE, responseMessage)); + } else { + return EnforcerResult.failed(String.format(HTTP_RESPONSE_ERROR_MESSAGE_TEMPLATE, responseCode, responseMessage)); + } } } From 554b7bbe0f2607f74f7b2ac0077c2ca6cd1fd947 Mon Sep 17 00:00:00 2001 From: Brian Wyka Date: Sun, 23 Jan 2022 19:18:48 -0500 Subject: [PATCH 3/3] content-http: http-validate: Make request properties configurable --- .../file/http/ContentHttpValidated.java | 43 ++++++++++++++----- 1 file changed, 32 insertions(+), 11 deletions(-) diff --git a/enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/http/ContentHttpValidated.java b/enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/http/ContentHttpValidated.java index f4f002c..4f13cef 100644 --- a/enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/http/ContentHttpValidated.java +++ b/enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/http/ContentHttpValidated.java @@ -5,6 +5,7 @@ import com.optum.sourcehawk.enforcer.file.AbstractFileEnforcer; import lombok.AllArgsConstructor; import lombok.Builder; +import lombok.Builder.Default; import lombok.NonNull; import lombok.val; @@ -39,23 +40,43 @@ public class ContentHttpValidated extends AbstractFileEnforcer { /** * The amount of time allowed to connect to URL before timing out */ - private final int connectTimeout; + @Default + private final int connectTimeout = 500; /** - * The amount of time allowed to read response from URL before timing out + * The amount of time allowed to read the response from URL before timing out */ - private final int readTimeout; + @Default + private final int readTimeout = 500; + /** + * The amount of time allowed to read the response from URL before timing out + */ + @Default + private final String method = "POST"; + + /** + * The amount of time allowed to read the response from URL before timing out + */ + @Default + private final String contentTypeHeader = "text/plain"; + + /** + * The amount of time allowed to read the response from URL before timing out + */ + @Default + private final String acceptHeader = "text/plain"; + /** {@inheritDoc} */ @Override protected EnforcerResult enforceInternal(final @NonNull InputStream actualFileInputStream) throws IOException { val httpUrlConnection = (HttpURLConnection) new URL(url).openConnection(); httpUrlConnection.setDoOutput(true); - httpUrlConnection.setRequestMethod("POST"); - httpUrlConnection.setRequestProperty("Content-Type", "text/plain"); - httpUrlConnection.setRequestProperty("Accept", "text/plain"); - httpUrlConnection.setConnectTimeout(connectTimeout == 0 ? 500 : connectTimeout); - httpUrlConnection.setReadTimeout(readTimeout == 0 ? 500 : readTimeout); + httpUrlConnection.setRequestMethod(method); + httpUrlConnection.setRequestProperty("Content-Type", contentTypeHeader); + httpUrlConnection.setRequestProperty("Accept", acceptHeader); + httpUrlConnection.setConnectTimeout(connectTimeout); + httpUrlConnection.setReadTimeout(readTimeout); try (val outputStream = httpUrlConnection.getOutputStream()) { val buffer = new byte[DEFAULT_BUFFER_SIZE]; int read; @@ -63,15 +84,15 @@ protected EnforcerResult enforceInternal(final @NonNull InputStream actualFileIn outputStream.write(buffer, 0, read); } } - val responseCode = String.valueOf(httpUrlConnection.getResponseCode()); - if (responseCode.startsWith("2")) { + val responseCode = httpUrlConnection.getResponseCode(); + if (responseCode >= 200 && responseCode < 300) { return EnforcerResult.passed(); } try (val errorStream = httpUrlConnection.getErrorStream(); val bufferedReader = new BufferedReader(new InputStreamReader(errorStream))) { val responseMessage = bufferedReader.lines() .collect(Collectors.joining()); - if (responseCode.startsWith("4")) { + if (responseCode >= 400 && responseCode < 500) { return EnforcerResult.failed(String.format(HTTP_RESPONSE_VALIDATION_MESSAGE_TEMPLATE, responseMessage)); } else { return EnforcerResult.failed(String.format(HTTP_RESPONSE_ERROR_MESSAGE_TEMPLATE, responseCode, responseMessage));