diff --git a/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/DoclingServeApi.java b/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/DoclingServeApi.java index 67d76fd..d6c8eb9 100644 --- a/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/DoclingServeApi.java +++ b/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/DoclingServeApi.java @@ -1,5 +1,7 @@ package ai.docling.serve.api; +import org.jspecify.annotations.Nullable; + /** * Docling Serve API interface. */ @@ -23,6 +25,19 @@ public interface DoclingServeApi * @param the type of the concrete builder implementation. */ interface DoclingApiBuilder> { + /** + * Sets the API key for authenticating requests made by the client being built. + * + * The provided API key will be used as a credential to authorize and authenticate + * API requests. This method updates the configuration of the builder with the specified + * API key and ensures that the API client includes it in its requests as required for + * secure access to the API. + * + * @param apiKey the API key to be used for authenticating API requests + * @return {@code this} builder instance for fluent API usage + */ + B apiKey(@Nullable String apiKey); + /** * Enables logging of requests for the API client being built. This can be useful for * debugging or monitoring the behavior of requests made to the API. diff --git a/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/auth/AuthenticatedRequest.java b/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/auth/AuthenticatedRequest.java deleted file mode 100644 index 6928d29..0000000 --- a/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/auth/AuthenticatedRequest.java +++ /dev/null @@ -1,28 +0,0 @@ -package ai.docling.serve.api.auth; - -/** - * Represents a request that requires authentication for secure access to resources. - * - * Implementations of this interface define a contract for providing authentication - * details associated with the request. This is used to ensure authorized interaction - * with APIs or protected services. - * - * Methods: - * - {@code getAuthentication()}: Retrieves the {@link Authentication} details - * required to authorize the request. - */ -public interface AuthenticatedRequest { - /** - * Retrieves the authentication details associated with the request. - * - * This method provides the {@link Authentication} object required to authorize - * interaction with secure resources or APIs. Implementations should ensure - * the returned object contains the necessary credentials for successful - * authentication. - * - * @return an {@link Authentication} instance containing the authentication - * details required for the request, or {@code null} if authentication - * is not applicable. - */ - Authentication getAuthentication(); -} diff --git a/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/auth/Authentication.java b/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/auth/Authentication.java deleted file mode 100644 index 4dc4c17..0000000 --- a/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/auth/Authentication.java +++ /dev/null @@ -1,31 +0,0 @@ -package ai.docling.serve.api.auth; - -import org.jspecify.annotations.Nullable; - -/** - * Represents authentication details required for secure API usage. - * - * The {@code Authentication} class encapsulates the necessary credentials - * for accessing restricted resources, such as an API key. It is designed - * to be immutable and thread-safe. - * - * This class uses Lombok annotations to provide a builder pattern, generate - * a getter for its fields, and produce a string representation. - * - * Features: - * - {@code apiKey}: Optional API key to authorize requests. - */ -@lombok.Builder(toBuilder = true) -@lombok.Getter -@lombok.ToString -public class Authentication { - /** - * Represents an optional API key used to authenticate requests to a secure service. - * - * This field is nullable, indicating that the API key may not always be provided - * or required, depending on the specific use case or configuration of the client. - * When present, the API key is used to authorize access to restricted resources. - */ - @Nullable - private String apiKey; -} diff --git a/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/auth/package-info.java b/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/auth/package-info.java deleted file mode 100644 index a4c33c0..0000000 --- a/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/auth/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -@NullMarked -package ai.docling.serve.api.auth; - -import org.jspecify.annotations.NullMarked; diff --git a/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/chunk/request/HierarchicalChunkDocumentRequest.java b/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/chunk/request/HierarchicalChunkDocumentRequest.java index a3f99f0..159be6f 100644 --- a/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/chunk/request/HierarchicalChunkDocumentRequest.java +++ b/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/chunk/request/HierarchicalChunkDocumentRequest.java @@ -4,14 +4,11 @@ import org.jspecify.annotations.Nullable; -import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonSetter; import com.fasterxml.jackson.annotation.Nulls; -import ai.docling.serve.api.auth.AuthenticatedRequest; -import ai.docling.serve.api.auth.Authentication; import ai.docling.serve.api.chunk.request.options.HierarchicalChunkerOptions; import ai.docling.serve.api.convert.request.options.ConvertDocumentOptions; import ai.docling.serve.api.convert.request.source.Source; @@ -27,7 +24,7 @@ @lombok.Builder(toBuilder = true) @lombok.Getter @lombok.ToString -public class HierarchicalChunkDocumentRequest implements AuthenticatedRequest { +public class HierarchicalChunkDocumentRequest { @JsonProperty("sources") @JsonSetter(nulls = Nulls.AS_EMPTY) @@ -51,11 +48,6 @@ public class HierarchicalChunkDocumentRequest implements AuthenticatedRequest { @lombok.Builder.Default private HierarchicalChunkerOptions chunkingOptions = HierarchicalChunkerOptions.builder().build(); - @JsonIgnore - @lombok.NonNull - @lombok.Builder.Default - private Authentication authentication = Authentication.builder().build(); - @tools.jackson.databind.annotation.JsonPOJOBuilder(withPrefix = "") public static class Builder { } diff --git a/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/chunk/request/HybridChunkDocumentRequest.java b/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/chunk/request/HybridChunkDocumentRequest.java index d55b626..6e76b8d 100644 --- a/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/chunk/request/HybridChunkDocumentRequest.java +++ b/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/chunk/request/HybridChunkDocumentRequest.java @@ -4,14 +4,11 @@ import org.jspecify.annotations.Nullable; -import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonSetter; import com.fasterxml.jackson.annotation.Nulls; -import ai.docling.serve.api.auth.AuthenticatedRequest; -import ai.docling.serve.api.auth.Authentication; import ai.docling.serve.api.chunk.request.options.HybridChunkerOptions; import ai.docling.serve.api.convert.request.options.ConvertDocumentOptions; import ai.docling.serve.api.convert.request.source.Source; @@ -27,7 +24,7 @@ @lombok.Builder(toBuilder = true) @lombok.Getter @lombok.ToString -public class HybridChunkDocumentRequest implements AuthenticatedRequest { +public class HybridChunkDocumentRequest { @JsonProperty("sources") @JsonSetter(nulls = Nulls.AS_EMPTY) @@ -51,11 +48,6 @@ public class HybridChunkDocumentRequest implements AuthenticatedRequest { @lombok.Builder.Default private HybridChunkerOptions chunkingOptions = HybridChunkerOptions.builder().build(); - @JsonIgnore - @lombok.NonNull - @lombok.Builder.Default - private Authentication authentication = Authentication.builder().build(); - @tools.jackson.databind.annotation.JsonPOJOBuilder(withPrefix = "") public static class Builder { } diff --git a/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/clear/request/ClearConvertersRequest.java b/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/clear/request/ClearConvertersRequest.java index a9e9a6e..e19f050 100644 --- a/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/clear/request/ClearConvertersRequest.java +++ b/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/clear/request/ClearConvertersRequest.java @@ -1,10 +1,5 @@ package ai.docling.serve.api.clear.request; -import com.fasterxml.jackson.annotation.JsonIgnore; - -import ai.docling.serve.api.auth.AuthenticatedRequest; -import ai.docling.serve.api.auth.Authentication; - /** * Represents a request to clear or reset configured converters using the Docling Serve API. * @@ -22,9 +17,5 @@ @lombok.Builder(toBuilder = true) @lombok.Getter @lombok.ToString -public class ClearConvertersRequest implements AuthenticatedRequest { - @JsonIgnore - @lombok.NonNull - @lombok.Builder.Default - private Authentication authentication = Authentication.builder().build(); +public class ClearConvertersRequest { } diff --git a/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/clear/request/ClearResultsRequest.java b/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/clear/request/ClearResultsRequest.java index 881dfd9..b75fac8 100644 --- a/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/clear/request/ClearResultsRequest.java +++ b/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/clear/request/ClearResultsRequest.java @@ -2,11 +2,6 @@ import java.time.Duration; -import com.fasterxml.jackson.annotation.JsonIgnore; - -import ai.docling.serve.api.auth.AuthenticatedRequest; -import ai.docling.serve.api.auth.Authentication; - /** * Represents a request to clear stale data via the Docling Serve Clear API. * This class provides a mechanism to specify a threshold duration, after which data @@ -22,7 +17,7 @@ @lombok.Builder(toBuilder = true) @lombok.Getter @lombok.ToString -public class ClearResultsRequest implements AuthenticatedRequest { +public class ClearResultsRequest { /** * Represents the default duration used as a threshold for clearing stale results * or data in the Docling Serve Clear API. Results older than this duration @@ -35,9 +30,4 @@ public class ClearResultsRequest implements AuthenticatedRequest { @lombok.NonNull @lombok.Builder.Default private Duration olderThen = DEFAULT_OLDER_THAN; - - @JsonIgnore - @lombok.NonNull - @lombok.Builder.Default - private Authentication authentication = Authentication.builder().build(); } diff --git a/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/convert/request/ConvertDocumentRequest.java b/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/convert/request/ConvertDocumentRequest.java index e41ab91..bcfea23 100644 --- a/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/convert/request/ConvertDocumentRequest.java +++ b/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/convert/request/ConvertDocumentRequest.java @@ -4,14 +4,11 @@ import org.jspecify.annotations.Nullable; -import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonSetter; import com.fasterxml.jackson.annotation.Nulls; -import ai.docling.serve.api.auth.AuthenticatedRequest; -import ai.docling.serve.api.auth.Authentication; import ai.docling.serve.api.convert.request.options.ConvertDocumentOptions; import ai.docling.serve.api.convert.request.source.Source; import ai.docling.serve.api.convert.request.target.Target; @@ -30,7 +27,7 @@ @lombok.Builder(toBuilder = true) @lombok.Getter @lombok.ToString -public class ConvertDocumentRequest implements AuthenticatedRequest { +public class ConvertDocumentRequest { @JsonProperty("sources") @JsonSetter(nulls = Nulls.AS_EMPTY) @lombok.Singular @@ -45,11 +42,6 @@ public class ConvertDocumentRequest implements AuthenticatedRequest { @Nullable private Target target; - @JsonIgnore - @lombok.NonNull - @lombok.Builder.Default - private Authentication authentication = Authentication.builder().build(); - @tools.jackson.databind.annotation.JsonPOJOBuilder(withPrefix = "") public static class Builder { } } diff --git a/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/task/request/TaskResultRequest.java b/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/task/request/TaskResultRequest.java index 414fa21..f413c3e 100644 --- a/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/task/request/TaskResultRequest.java +++ b/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/task/request/TaskResultRequest.java @@ -1,10 +1,5 @@ package ai.docling.serve.api.task.request; -import com.fasterxml.jackson.annotation.JsonIgnore; - -import ai.docling.serve.api.auth.AuthenticatedRequest; -import ai.docling.serve.api.auth.Authentication; - /** * Represents a request to retrieve the result of a task. * @@ -20,12 +15,7 @@ @lombok.Builder(toBuilder = true) @lombok.Getter @lombok.ToString -public class TaskResultRequest implements AuthenticatedRequest { +public class TaskResultRequest { @lombok.NonNull private String taskId; - - @JsonIgnore - @lombok.NonNull - @lombok.Builder.Default - private Authentication authentication = Authentication.builder().build(); } diff --git a/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/task/request/TaskStatusPollRequest.java b/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/task/request/TaskStatusPollRequest.java index 134ecf7..c6d7156 100644 --- a/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/task/request/TaskStatusPollRequest.java +++ b/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/task/request/TaskStatusPollRequest.java @@ -2,11 +2,6 @@ import java.time.Duration; -import com.fasterxml.jackson.annotation.JsonIgnore; - -import ai.docling.serve.api.auth.AuthenticatedRequest; -import ai.docling.serve.api.auth.Authentication; - /** * Represents a request for polling the status of a task. * @@ -27,7 +22,7 @@ @lombok.Builder(toBuilder = true) @lombok.Getter @lombok.ToString -public class TaskStatusPollRequest implements AuthenticatedRequest { +public class TaskStatusPollRequest { /** * The default wait time between status polling attempts for a task. *

@@ -44,9 +39,4 @@ public class TaskStatusPollRequest implements AuthenticatedRequest { @lombok.NonNull @lombok.Builder.Default private Duration waitTime = DEFAULT_STATUS_POLL_WAIT_TIME; - - @JsonIgnore - @lombok.NonNull - @lombok.Builder.Default - private Authentication authentication = Authentication.builder().build(); } diff --git a/docling-serve/docling-serve-api/src/main/java/module-info.java b/docling-serve/docling-serve-api/src/main/java/module-info.java index 455e531..eb58960 100644 --- a/docling-serve/docling-serve-api/src/main/java/module-info.java +++ b/docling-serve/docling-serve-api/src/main/java/module-info.java @@ -14,9 +14,6 @@ exports ai.docling.serve.api.health; exports ai.docling.serve.api.util; - // Auth - exports ai.docling.serve.api.auth; - // Chunking API exports ai.docling.serve.api.chunk.request; exports ai.docling.serve.api.chunk.request.options; diff --git a/docling-serve/docling-serve-api/src/test/java/ai/docling/serve/api/auth/AuthenticationTests.java b/docling-serve/docling-serve-api/src/test/java/ai/docling/serve/api/auth/AuthenticationTests.java deleted file mode 100644 index 98e6b00..0000000 --- a/docling-serve/docling-serve-api/src/test/java/ai/docling/serve/api/auth/AuthenticationTests.java +++ /dev/null @@ -1,23 +0,0 @@ -package ai.docling.serve.api.auth; - -import static org.assertj.core.api.Assertions.assertThat; - -import org.junit.jupiter.api.Test; - -class AuthenticationTests { - @Test - void nothingSpecified() { - assertThat(Authentication.builder().build()) - .isNotNull() - .extracting(Authentication::getApiKey) - .isNull(); - } - - @Test - void keySpecified() { - assertThat(Authentication.builder().apiKey("key").build()) - .isNotNull() - .extracting(Authentication::getApiKey) - .isEqualTo("key"); - } -} diff --git a/docling-serve/docling-serve-api/src/test/java/ai/docling/serve/api/chunk/request/HierarchicalChunkDocumentRequestTests.java b/docling-serve/docling-serve-api/src/test/java/ai/docling/serve/api/chunk/request/HierarchicalChunkDocumentRequestTests.java index af45343..bdadb09 100644 --- a/docling-serve/docling-serve-api/src/test/java/ai/docling/serve/api/chunk/request/HierarchicalChunkDocumentRequestTests.java +++ b/docling-serve/docling-serve-api/src/test/java/ai/docling/serve/api/chunk/request/HierarchicalChunkDocumentRequestTests.java @@ -10,7 +10,6 @@ import org.junit.jupiter.api.Test; -import ai.docling.serve.api.auth.Authentication; import ai.docling.serve.api.chunk.request.options.HierarchicalChunkerOptions; import ai.docling.serve.api.convert.request.options.ConvertDocumentOptions; import ai.docling.serve.api.convert.request.source.FileSource; @@ -41,10 +40,6 @@ void buildWithHttpSourcesAsList() { .build(); assertThat(request.getSources()).hasSize(1); assertThat(request.getSources().get(0)).isInstanceOf(HttpSource.class); - assertThat(request.getAuthentication()) - .isNotNull() - .extracting(Authentication::getApiKey) - .isNull(); } @Test @@ -59,11 +54,6 @@ void buildWithHttpSourcesAsVarargs() { assertThat(request.getSources()) .hasSize(2) .allSatisfy(source -> assertThat(source).isInstanceOf(HttpSource.class)); - - assertThat(request.getAuthentication()) - .isNotNull() - .extracting(Authentication::getApiKey) - .isNull(); } @Test @@ -75,11 +65,6 @@ void buildWithFileSourcesAsList() { assertThat(request.getSources()) .hasSize(1) .allSatisfy(source -> assertThat(source).isInstanceOf(FileSource.class)); - - assertThat(request.getAuthentication()) - .isNotNull() - .extracting(Authentication::getApiKey) - .isNull(); } @Test @@ -95,11 +80,6 @@ void buildWithFileSourcesAsVarargs() { assertThat(request.getSources()) .hasSize(2) .allSatisfy(source -> assertThat(source).isInstanceOf(FileSource.class)); - - assertThat(request.getAuthentication()) - .isNotNull() - .extracting(Authentication::getApiKey) - .isNull(); } @Test @@ -125,11 +105,6 @@ void hierarchicalChunkDocumentRequestIsImmutable() { .asInstanceOf(type(FileSource.class)) .extracting(FileSource::getFilename, FileSource::getBase64String) .containsExactly("test.txt", "dGVzdCBjb250ZW50"); - - assertThat(request.getAuthentication()) - .isNotNull() - .extracting(Authentication::getApiKey) - .isNull(); } @Test @@ -140,10 +115,6 @@ void buildWithIncludeConvertedDoc() { .build(); assertThat(request.isIncludeConvertedDoc()).isTrue(); - assertThat(request.getAuthentication()) - .isNotNull() - .extracting(Authentication::getApiKey) - .isNull(); } @Test @@ -164,11 +135,6 @@ void buildWithChunkingOptions() { assertThat(options.isUseMarkdownTables()).isTrue(); assertThat(options.isIncludeRawText()).isFalse(); }); - - assertThat(request.getAuthentication()) - .isNotNull() - .extracting(Authentication::getApiKey) - .isNull(); } @Test @@ -191,10 +157,6 @@ void buildWithAllFields() { assertThat(request.getTarget()).isNotNull(); assertThat(request.isIncludeConvertedDoc()).isTrue(); assertThat(request.getChunkingOptions()).isNotNull(); - assertThat(request.getAuthentication()) - .isNotNull() - .extracting(Authentication::getApiKey) - .isNull(); } @Test @@ -207,21 +169,5 @@ void buildWithDefaultOptions() { assertThat(request.isIncludeConvertedDoc()).isFalse(); assertThat(request.getChunkingOptions()).isNotNull(); assertThat(request.getTarget()).isNull(); - assertThat(request.getAuthentication()) - .isNotNull() - .extracting(Authentication::getApiKey) - .isNull(); - } - - @Test - void buildWithAuth() { - var request = HierarchicalChunkDocumentRequest.builder() - .authentication(Authentication.builder().apiKey("key").build()) - .build(); - - assertThat(request.getAuthentication()) - .isNotNull() - .extracting(Authentication::getApiKey) - .isEqualTo("key"); } } diff --git a/docling-serve/docling-serve-api/src/test/java/ai/docling/serve/api/chunk/request/HybridChunkDocumentRequestTests.java b/docling-serve/docling-serve-api/src/test/java/ai/docling/serve/api/chunk/request/HybridChunkDocumentRequestTests.java index 392af4c..c39e739 100644 --- a/docling-serve/docling-serve-api/src/test/java/ai/docling/serve/api/chunk/request/HybridChunkDocumentRequestTests.java +++ b/docling-serve/docling-serve-api/src/test/java/ai/docling/serve/api/chunk/request/HybridChunkDocumentRequestTests.java @@ -10,7 +10,6 @@ import org.junit.jupiter.api.Test; -import ai.docling.serve.api.auth.Authentication; import ai.docling.serve.api.chunk.request.options.HybridChunkerOptions; import ai.docling.serve.api.convert.request.options.ConvertDocumentOptions; import ai.docling.serve.api.convert.request.source.FileSource; @@ -41,10 +40,6 @@ void buildWithHttpSourcesAsList() { .build(); assertThat(request.getSources()).hasSize(1); assertThat(request.getSources().get(0)).isInstanceOf(HttpSource.class); - assertThat(request.getAuthentication()) - .isNotNull() - .extracting(Authentication::getApiKey) - .isNull(); } @Test @@ -59,11 +54,6 @@ void buildWithHttpSourcesAsVarargs() { assertThat(request.getSources()) .hasSize(2) .allSatisfy(source -> assertThat(source).isInstanceOf(HttpSource.class)); - - assertThat(request.getAuthentication()) - .isNotNull() - .extracting(Authentication::getApiKey) - .isNull(); } @Test @@ -75,11 +65,6 @@ void buildWithFileSourcesAsList() { assertThat(request.getSources()) .hasSize(1) .allSatisfy(source -> assertThat(source).isInstanceOf(FileSource.class)); - - assertThat(request.getAuthentication()) - .isNotNull() - .extracting(Authentication::getApiKey) - .isNull(); } @Test @@ -95,11 +80,6 @@ void buildWithFileSourcesAsVarargs() { assertThat(request.getSources()) .hasSize(2) .allSatisfy(source -> assertThat(source).isInstanceOf(FileSource.class)); - - assertThat(request.getAuthentication()) - .isNotNull() - .extracting(Authentication::getApiKey) - .isNull(); } @Test @@ -125,11 +105,6 @@ void hybridChunkDocumentRequestIsImmutable() { .asInstanceOf(type(FileSource.class)) .extracting(FileSource::getFilename, FileSource::getBase64String) .containsExactly("test.txt", "dGVzdCBjb250ZW50"); - - assertThat(request.getAuthentication()) - .isNotNull() - .extracting(Authentication::getApiKey) - .isNull(); } @Test @@ -140,10 +115,6 @@ void buildWithIncludeConvertedDoc() { .build(); assertThat(request.isIncludeConvertedDoc()).isTrue(); - assertThat(request.getAuthentication()) - .isNotNull() - .extracting(Authentication::getApiKey) - .isNull(); } @Test @@ -170,11 +141,6 @@ void buildWithChunkingOptions() { assertThat(options.isIncludeRawText()).isFalse(); assertThat(options.getMergePeers()).isTrue(); }); - - assertThat(request.getAuthentication()) - .isNotNull() - .extracting(Authentication::getApiKey) - .isNull(); } @Test @@ -196,10 +162,6 @@ void buildWithAllFields() { assertThat(request.getTarget()).isNotNull(); assertThat(request.isIncludeConvertedDoc()).isTrue(); assertThat(request.getChunkingOptions()).isNotNull(); - assertThat(request.getAuthentication()) - .isNotNull() - .extracting(Authentication::getApiKey) - .isNull(); } @Test @@ -212,21 +174,5 @@ void buildWithDefaultOptions() { assertThat(request.isIncludeConvertedDoc()).isFalse(); assertThat(request.getChunkingOptions()).isNotNull(); assertThat(request.getTarget()).isNull(); - assertThat(request.getAuthentication()) - .isNotNull() - .extracting(Authentication::getApiKey) - .isNull(); - } - - @Test - void buildWithAuth() { - var request = HybridChunkDocumentRequest.builder() - .authentication(Authentication.builder().apiKey("key").build()) - .build(); - - assertThat(request.getAuthentication()) - .isNotNull() - .extracting(Authentication::getApiKey) - .isEqualTo("key"); } } diff --git a/docling-serve/docling-serve-api/src/test/java/ai/docling/serve/api/clear/request/ClearConvertersRequestTests.java b/docling-serve/docling-serve-api/src/test/java/ai/docling/serve/api/clear/request/ClearConvertersRequestTests.java deleted file mode 100644 index 9d0039e..0000000 --- a/docling-serve/docling-serve-api/src/test/java/ai/docling/serve/api/clear/request/ClearConvertersRequestTests.java +++ /dev/null @@ -1,29 +0,0 @@ -package ai.docling.serve.api.clear.request; - -import static org.assertj.core.api.Assertions.assertThat; - -import org.junit.jupiter.api.Test; - -import ai.docling.serve.api.auth.Authentication; - -class ClearConvertersRequestTests { - @Test - void noAuthSpecified() { - assertThat(ClearConvertersRequest.builder().build()) - .isNotNull() - .extracting(ClearConvertersRequest::getAuthentication) - .isNotNull() - .extracting(Authentication::getApiKey) - .isNull(); - } - - @Test - void authSpecified() { - assertThat(ClearConvertersRequest.builder().authentication(Authentication.builder().apiKey("key").build()).build()) - .isNotNull() - .extracting(ClearConvertersRequest::getAuthentication) - .isNotNull() - .extracting(Authentication::getApiKey) - .isEqualTo("key"); - } -} diff --git a/docling-serve/docling-serve-api/src/test/java/ai/docling/serve/api/clear/request/ClearResultsRequestTests.java b/docling-serve/docling-serve-api/src/test/java/ai/docling/serve/api/clear/request/ClearResultsRequestTests.java index bef64d7..7053f18 100644 --- a/docling-serve/docling-serve-api/src/test/java/ai/docling/serve/api/clear/request/ClearResultsRequestTests.java +++ b/docling-serve/docling-serve-api/src/test/java/ai/docling/serve/api/clear/request/ClearResultsRequestTests.java @@ -6,8 +6,6 @@ import org.assertj.core.api.InstanceOfAssertFactories; import org.junit.jupiter.api.Test; -import ai.docling.serve.api.auth.Authentication; - class ClearResultsRequestTests { @Test void nullOlderThen() { @@ -25,22 +23,5 @@ void defaultOlderThen() { .extracting(ClearResultsRequest::getOlderThen) .asInstanceOf(InstanceOfAssertFactories.DURATION) .isEqualByComparingTo(ClearResultsRequest.DEFAULT_OLDER_THAN); - - assertThat(request.getAuthentication()) - .isNotNull() - .extracting(Authentication::getApiKey) - .isNull(); - } - - @Test - void buildWithAuth() { - var request = ClearResultsRequest.builder() - .authentication(Authentication.builder().apiKey("key").build()) - .build(); - - assertThat(request.getAuthentication()) - .isNotNull() - .extracting(Authentication::getApiKey) - .isEqualTo("key"); } } diff --git a/docling-serve/docling-serve-api/src/test/java/ai/docling/serve/api/task/request/TaskResultRequestTests.java b/docling-serve/docling-serve-api/src/test/java/ai/docling/serve/api/task/request/TaskResultRequestTests.java index bbb6799..e548790 100644 --- a/docling-serve/docling-serve-api/src/test/java/ai/docling/serve/api/task/request/TaskResultRequestTests.java +++ b/docling-serve/docling-serve-api/src/test/java/ai/docling/serve/api/task/request/TaskResultRequestTests.java @@ -5,8 +5,6 @@ import org.junit.jupiter.api.Test; -import ai.docling.serve.api.auth.Authentication; - class TaskResultRequestTests { @Test void nullTaskId() { @@ -23,26 +21,9 @@ void noTaskId() { } @Test - void buildWithoutAuth() { + void build() { var request = TaskResultRequest.builder().taskId("1").build(); assertThat(request.getTaskId()).isEqualTo("1"); - assertThat(request.getAuthentication()) - .isNotNull() - .extracting(Authentication::getApiKey) - .isNull(); - } - - @Test - void buildWithAuth() { - var request = TaskResultRequest.builder() - .taskId("1") - .authentication(Authentication.builder().apiKey("key").build()) - .build(); - - assertThat(request.getAuthentication()) - .isNotNull() - .extracting(Authentication::getApiKey) - .isEqualTo("key"); } } diff --git a/docling-serve/docling-serve-api/src/test/java/ai/docling/serve/api/task/request/TaskStatusPollRequestTests.java b/docling-serve/docling-serve-api/src/test/java/ai/docling/serve/api/task/request/TaskStatusPollRequestTests.java index a8e10b7..9a1af1c 100644 --- a/docling-serve/docling-serve-api/src/test/java/ai/docling/serve/api/task/request/TaskStatusPollRequestTests.java +++ b/docling-serve/docling-serve-api/src/test/java/ai/docling/serve/api/task/request/TaskStatusPollRequestTests.java @@ -6,8 +6,6 @@ import org.assertj.core.api.InstanceOfAssertFactories; import org.junit.jupiter.api.Test; -import ai.docling.serve.api.auth.Authentication; - class TaskStatusPollRequestTests { @Test void nullTaskId() { @@ -38,34 +36,12 @@ void defaultWaitTime() { .extracting(TaskStatusPollRequest::getWaitTime) .asInstanceOf(InstanceOfAssertFactories.DURATION) .isEqualByComparingTo(TaskStatusPollRequest.DEFAULT_STATUS_POLL_WAIT_TIME); - - assertThat(request.getAuthentication()) - .isNotNull() - .extracting(Authentication::getApiKey) - .isNull(); } @Test - void buildWithoutAuth() { + void build() { var request = TaskStatusPollRequest.builder().taskId("1").build(); assertThat(request.getTaskId()).isEqualTo("1"); - assertThat(request.getAuthentication()) - .isNotNull() - .extracting(Authentication::getApiKey) - .isNull(); - } - - @Test - void buildWithAuth() { - var request = TaskStatusPollRequest.builder() - .taskId("1") - .authentication(Authentication.builder().apiKey("key").build()) - .build(); - - assertThat(request.getAuthentication()) - .isNotNull() - .extracting(Authentication::getApiKey) - .isEqualTo("key"); } } diff --git a/docling-serve/docling-serve-client/src/main/java/ai/docling/serve/client/DoclingServeClient.java b/docling-serve/docling-serve-client/src/main/java/ai/docling/serve/client/DoclingServeClient.java index ede14e6..843b633 100644 --- a/docling-serve/docling-serve-client/src/main/java/ai/docling/serve/client/DoclingServeClient.java +++ b/docling-serve/docling-serve-client/src/main/java/ai/docling/serve/client/DoclingServeClient.java @@ -28,8 +28,6 @@ import ai.docling.serve.api.DoclingServeConvertApi; import ai.docling.serve.api.DoclingServeHealthApi; import ai.docling.serve.api.DoclingServeTaskApi; -import ai.docling.serve.api.auth.AuthenticatedRequest; -import ai.docling.serve.api.auth.Authentication; import ai.docling.serve.api.chunk.request.HierarchicalChunkDocumentRequest; import ai.docling.serve.api.chunk.request.HybridChunkDocumentRequest; import ai.docling.serve.api.chunk.response.ChunkDocumentResponse; @@ -42,11 +40,13 @@ import ai.docling.serve.api.task.request.TaskResultRequest; import ai.docling.serve.api.task.request.TaskStatusPollRequest; import ai.docling.serve.api.task.response.TaskStatusPollResponse; +import ai.docling.serve.api.util.Utils; import ai.docling.serve.client.operations.ChunkOperations; import ai.docling.serve.client.operations.ClearOperations; import ai.docling.serve.client.operations.ConvertOperations; import ai.docling.serve.client.operations.HealthOperations; import ai.docling.serve.client.operations.HttpOperations; +import ai.docling.serve.client.operations.RequestContext; import ai.docling.serve.client.operations.TaskOperations; /** @@ -74,7 +74,8 @@ public abstract class DoclingServeClient extends HttpOperations implements Docli private final boolean logRequests; private final boolean logResponses; private final boolean prettyPrintJson; - + private final @Nullable String apiKey; + private final HealthOperations healthOps = new HealthOperations(this); private final ConvertOperations convertOps = new ConvertOperations(this); private final ChunkOperations chunkOps = new ChunkOperations(this); @@ -95,6 +96,7 @@ protected DoclingServeClient(DoclingServeClientBuilder builder) { this.logRequests = builder.logRequests; this.logResponses = builder.logResponses; this.prettyPrintJson = builder.prettyPrintJson; + this.apiKey = builder.apiKey; } /** @@ -190,37 +192,32 @@ protected T execute(HttpRequest request, Class expectedValueType) { } @Override - protected O executePost(String uri, I request, Class expectedReturnType) { - var httpRequest = createRequestBuilder(uri, request) + protected O executePost(RequestContext requestContext) { + var httpRequest = createRequestBuilder(requestContext) .header("Content-Type", "application/json") - .POST(new LoggingBodyPublisher<>(request)) + .POST(new LoggingBodyPublisher<>(requestContext.getRequest())) .build(); - return execute(httpRequest, expectedReturnType); + return execute(httpRequest, requestContext.getResponseType()); } @Override - protected O executeGet(String uri, I request, Class expectedReturnType) { - var httpRequest = createRequestBuilder(uri, request) + protected O executeGet(RequestContext requestContext) { + var httpRequest = createRequestBuilder(requestContext) .GET() .build(); - return execute(httpRequest, expectedReturnType); + return execute(httpRequest, requestContext.getResponseType()); } - protected HttpRequest.Builder createRequestBuilder(String uri, @Nullable I request) { + protected HttpRequest.Builder createRequestBuilder(RequestContext requestContext) { var requestBuilder = HttpRequest.newBuilder() - .uri(baseUrl.resolve(uri)) - .header("Accept", "application/json"); - - // Handle the authentication - Optional.ofNullable(request) - .filter(AuthenticatedRequest.class::isInstance) - .map(AuthenticatedRequest.class::cast) - .map(AuthenticatedRequest::getAuthentication) - .map(Authentication::getApiKey) - .map(String::trim) - .ifPresent(apiKey -> requestBuilder.header(API_KEY_HEADER_NAME, apiKey)); + .uri(this.baseUrl.resolve(requestContext.getUri())) + .header("Accept", "application/json"); + + if (Utils.isNotNullOrBlank(this.apiKey)) { + requestBuilder.header(API_KEY_HEADER_NAME, this.apiKey); + } return requestBuilder; } @@ -292,9 +289,15 @@ private class LoggingBodyPublisher implements BodyPublisher { private final BodyPublisher delegate; private final String stringContent; - private LoggingBodyPublisher(T content) { - this.stringContent = writeValueAsString(content); - this.delegate = BodyPublishers.ofString(this.stringContent); + private LoggingBodyPublisher(@Nullable T content) { + if (content == null) { + this.stringContent = ""; + this.delegate = BodyPublishers.noBody(); + } + else { + this.stringContent = writeValueAsString(content); + this.delegate = BodyPublishers.ofString(this.stringContent); + } } @Override @@ -329,6 +332,7 @@ public abstract static class DoclingServeClientBuilder RequestContext createRequestContext(String uri, I request) { + return RequestContext.builder() + .request(request) + .responseType(ChunkDocumentResponse.class) + .uri(uri) + .build(); } } diff --git a/docling-serve/docling-serve-client/src/main/java/ai/docling/serve/client/operations/ClearOperations.java b/docling-serve/docling-serve-client/src/main/java/ai/docling/serve/client/operations/ClearOperations.java index b291ea0..70a93ad 100644 --- a/docling-serve/docling-serve-client/src/main/java/ai/docling/serve/client/operations/ClearOperations.java +++ b/docling-serve/docling-serve-client/src/main/java/ai/docling/serve/client/operations/ClearOperations.java @@ -30,7 +30,7 @@ public ClearOperations(HttpOperations httpOperations) { * including details such as the status of the operation. */ public ClearResponse clearConverters(ClearConvertersRequest request) { - return this.httpOperations.executeGet("/v1/clear/converters", request, ClearResponse.class); + return this.httpOperations.executeGet(createRequestContext("/v1/clear/converters", request)); } /** @@ -44,7 +44,14 @@ public ClearResponse clearConverters(ClearConvertersRequest request) { */ public ClearResponse clearResults(ClearResultsRequest request) { ValidationUtils.ensureNotNull(request, "request"); + return this.httpOperations.executeGet(createRequestContext("/v1/clear/results?older_then=%d".formatted(request.getOlderThen().toSeconds()), request)); + } - return this.httpOperations.executeGet("/v1/clear/results?older_then=%d".formatted(request.getOlderThen().toSeconds()), request, ClearResponse.class); + private RequestContext createRequestContext(String uri, I request) { + return RequestContext.builder() + .request(request) + .responseType(ClearResponse.class) + .uri(uri) + .build(); } } diff --git a/docling-serve/docling-serve-client/src/main/java/ai/docling/serve/client/operations/ConvertOperations.java b/docling-serve/docling-serve-client/src/main/java/ai/docling/serve/client/operations/ConvertOperations.java index 54c95dd..87e1839 100644 --- a/docling-serve/docling-serve-client/src/main/java/ai/docling/serve/client/operations/ConvertOperations.java +++ b/docling-serve/docling-serve-client/src/main/java/ai/docling/serve/client/operations/ConvertOperations.java @@ -24,6 +24,14 @@ public ConvertOperations(HttpOperations httpOperations) { */ public ConvertDocumentResponse convertSource(ConvertDocumentRequest request) { ValidationUtils.ensureNotNull(request, "request"); - return this.httpOperations.executePost("/v1/convert/source", request, ConvertDocumentResponse.class); + return this.httpOperations.executePost(createRequestContext("/v1/convert/source", request)); + } + + private RequestContext createRequestContext(String uri, I request) { + return RequestContext.builder() + .request(request) + .responseType(ConvertDocumentResponse.class) + .uri(uri) + .build(); } } diff --git a/docling-serve/docling-serve-client/src/main/java/ai/docling/serve/client/operations/HealthOperations.java b/docling-serve/docling-serve-client/src/main/java/ai/docling/serve/client/operations/HealthOperations.java index 2c3c528..851a438 100644 --- a/docling-serve/docling-serve-client/src/main/java/ai/docling/serve/client/operations/HealthOperations.java +++ b/docling-serve/docling-serve-client/src/main/java/ai/docling/serve/client/operations/HealthOperations.java @@ -20,6 +20,13 @@ public HealthOperations(HttpOperations httpOperations) { * @return a {@link HealthCheckResponse} object containing the health status of the API. */ public HealthCheckResponse health() { - return this.httpOperations.executeGet("/health", HealthCheckResponse.class); + return this.httpOperations.executeGet(createRequestContext("/health")); + } + + private RequestContext createRequestContext(String uri) { + return RequestContext.builder() + .responseType(HealthCheckResponse.class) + .uri(uri) + .build(); } } diff --git a/docling-serve/docling-serve-client/src/main/java/ai/docling/serve/client/operations/HttpOperations.java b/docling-serve/docling-serve-client/src/main/java/ai/docling/serve/client/operations/HttpOperations.java index 49bb04c..0c846ac 100644 --- a/docling-serve/docling-serve-client/src/main/java/ai/docling/serve/client/operations/HttpOperations.java +++ b/docling-serve/docling-serve-client/src/main/java/ai/docling/serve/client/operations/HttpOperations.java @@ -14,42 +14,26 @@ public abstract class HttpOperations { public static final String API_KEY_HEADER_NAME = "X-Api-Key"; /** - * Executes an HTTP GET request to the specified URI and deserializes the response into the given type. + * Executes an HTTP GET request using the details specified in the provided {@code RequestContext}. * - * @param Parameter type for the request - * @param the expected return type for the deserialized response. - * @param uri the URI to send the GET request to. - * @param request parameters for the request - * @param expectedReturnType the class representing the type to which the response should be deserialized. - * @return an instance of the specified type containing the deserialized response data. + * @param the type of the request payload + * @param the type of the response object + * @param requestContext the context containing details such as the URI, request payload, + * and expected response type of the GET operation + * @return an instance of the response type {@code O}, which represents the deserialized response data */ - protected abstract O executeGet(String uri, I request, Class expectedReturnType); + protected abstract O executeGet(RequestContext requestContext); /** - * Executes an HTTP GET request to the specified URI and deserializes - * the response into the given type. + * Executes an HTTP POST request using the details provided in the {@code RequestContext}. + * This method is designed to be implemented by subclasses and facilitates sending POST requests + * with a specified request payload and receiving a deserialized response. * - * @param the expected return type for the deserialized response. - * @param uri the URI to send the GET request to. Must not be null. - * @param expectedReturnType the class representing the type to which - * the response should be deserialized. Must not be null. - * @return an instance of the specified type containing the deserialized - * response data. + * @param the type of the request payload + * @param the type of the response object + * @param requestContext the context containing details such as the URI, request payload, and + * expected response type of the POST operation + * @return an instance of the response type {@code O}, which represents the deserialized response data */ - protected O executeGet(String uri, Class expectedReturnType) { - return executeGet(uri, null, expectedReturnType); - } - - /** - * Executes an HTTP POST request to the specified URI with the given request payload and deserializes - * the response into the specified return type. - * - * @param Parameter type for the request - * @param the expected return type for the deserialized response. - * @param uri the URI to send the POST request to. - * @param request parameters for the request - * @param expectedReturnType the class representing the type to which the response should be deserialized. - * @return an instance of the specified type containing the deserialized response data. - */ - protected abstract O executePost(String uri, I request, Class expectedReturnType); + protected abstract O executePost(RequestContext requestContext); } diff --git a/docling-serve/docling-serve-client/src/main/java/ai/docling/serve/client/operations/RequestContext.java b/docling-serve/docling-serve-client/src/main/java/ai/docling/serve/client/operations/RequestContext.java new file mode 100644 index 0000000..05af3b9 --- /dev/null +++ b/docling-serve/docling-serve-client/src/main/java/ai/docling/serve/client/operations/RequestContext.java @@ -0,0 +1,130 @@ +package ai.docling.serve.client.operations; + +import org.jspecify.annotations.Nullable; + +import ai.docling.serve.api.util.ValidationUtils; + +public class RequestContext { + private final String uri; + private final I request; + private final Class responseType; + + private RequestContext(Builder builder) { + this.uri = ValidationUtils.ensureNotBlank(builder.uri, "uri"); + this.request = builder.request; + this.responseType = ValidationUtils.ensureNotNull(builder.responseType, "responseType"); + } + + /** + * Returns the URI for the request. + * + * @return the URI string + */ + public String getUri() { + return uri; + } + + /** + * Returns the request object. + * + * @return the request object of type I + */ + @Nullable + public I getRequest() { + return request; + } + + /** + * Returns the response type class. + * + * @return the Class object representing the response type O + */ + public Class getResponseType() { + return responseType; + } + + /** + * Creates a new Builder instance for constructing a RequestContext. + * + * @param the request type + * @param the response type + * @return a new Builder instance + */ + public static Builder builder() { + return new Builder<>(); + } + + /** + * Creates a new Builder instance initialized with the values from this RequestContext. + * + * @return a new Builder instance with values copied from this RequestContext + */ + public Builder toBuilder() { + return new Builder<>(this); + } + + public static class Builder { + private String uri; + private @Nullable I request; + private Class responseType; + + /** + * Creates a new empty Builder instance. + */ + public Builder() { + } + + /** + * Creates a new Builder instance initialized with values from the given RequestContext. + * + * @param context the RequestContext to copy values from + */ + public Builder(RequestContext context) { + this.uri = context.uri; + this.request = context.request; + this.responseType = context.responseType; + } + + /** + * Sets the URI for the request. + * + * @param uri the URI string + * @return this Builder instance for method chaining + */ + public Builder uri(String uri) { + this.uri = uri; + return this; + } + + /** + * Sets the request object. + * + * @param request the request object of type I + * @return this Builder instance for method chaining + */ + public Builder request(@Nullable I request) { + this.request = request; + return this; + } + + /** + * Sets the response type class. + * + * @param responseType the Class object representing the response type O + * @return this Builder instance for method chaining + */ + public Builder responseType(Class responseType) { + this.responseType = responseType; + return this; + } + + /** + * Builds and returns a new RequestContext instance with the configured values. + * + * @return a new RequestContext instance + */ + public RequestContext build() { + return new RequestContext<>(this); + } + } +} diff --git a/docling-serve/docling-serve-client/src/main/java/ai/docling/serve/client/operations/TaskOperations.java b/docling-serve/docling-serve-client/src/main/java/ai/docling/serve/client/operations/TaskOperations.java index a60c1bc..898957e 100644 --- a/docling-serve/docling-serve-client/src/main/java/ai/docling/serve/client/operations/TaskOperations.java +++ b/docling-serve/docling-serve-client/src/main/java/ai/docling/serve/client/operations/TaskOperations.java @@ -37,12 +37,11 @@ public TaskOperations(HttpOperations httpOperations) { public TaskStatusPollResponse pollTaskStatus(TaskStatusPollRequest request) { ValidationUtils.ensureNotNull(request, "request"); - return this.httpOperations.executeGet( + return this.httpOperations.executeGet(createRequestContext( "/v1/status/poll/%s?wait=%d".formatted( request.getTaskId(), - request.getWaitTime().toSeconds() - ), - TaskStatusPollResponse.class + request.getWaitTime().toSeconds()), + TaskStatusPollResponse.class) ); } @@ -61,7 +60,7 @@ public TaskStatusPollResponse pollTaskStatus(TaskStatusPollRequest request) { */ public ConvertDocumentResponse convertTaskResult(TaskResultRequest request) { ValidationUtils.ensureNotNull(request, "request"); - return this.httpOperations.executeGet("/v1/result/%s".formatted(request.getTaskId()), request, ConvertDocumentResponse.class); + return this.httpOperations.executeGet(createRequestContext("/v1/result/%s".formatted(request.getTaskId()), ConvertDocumentResponse.class)); } /** @@ -79,6 +78,13 @@ public ConvertDocumentResponse convertTaskResult(TaskResultRequest request) { */ public ChunkDocumentResponse chunkTaskResult(TaskResultRequest request) { ValidationUtils.ensureNotNull(request, "request"); - return this.httpOperations.executeGet("/v1/result/%s".formatted(request.getTaskId()), request, ChunkDocumentResponse.class); + return this.httpOperations.executeGet(createRequestContext("/v1/result/%s".formatted(request.getTaskId()), ChunkDocumentResponse.class)); + } + + private RequestContext createRequestContext(String uri, Class responseType) { + return RequestContext.builder() + .responseType(responseType) + .uri(uri) + .build(); } } diff --git a/docling-serve/docling-serve-client/src/test/java/ai/docling/serve/client/AbstractDoclingServeClientTests.java b/docling-serve/docling-serve-client/src/test/java/ai/docling/serve/client/AbstractDoclingServeClientTests.java index 1f63b36..9ef3776 100644 --- a/docling-serve/docling-serve-client/src/test/java/ai/docling/serve/client/AbstractDoclingServeClientTests.java +++ b/docling-serve/docling-serve-client/src/test/java/ai/docling/serve/client/AbstractDoclingServeClientTests.java @@ -95,7 +95,11 @@ public void testFailed(ExtensionContext context, @Nullable Throwable cause) { doclingContainer.start(); } - protected abstract DoclingServeApi getDoclingClient(); + protected abstract DoclingServeApi getDoclingClient(boolean requiresAuth); + + protected DoclingServeApi getDoclingClient() { + return getDoclingClient(true); + } private T readValue(String json, Class valueType) { return ((DoclingServeClient) getDoclingClient()).readValue(json, valueType); @@ -308,7 +312,7 @@ public void subscribe(Subscriber subscriber) { class HealthTests { @Test void shouldSuccessfullyCallHealthEndpoint() { - HealthCheckResponse response = getDoclingClient().health(); + HealthCheckResponse response = getDoclingClient(false).health(); assertThat(response) .isNotNull() diff --git a/docling-serve/docling-serve-client/src/test/java/ai/docling/serve/client/DoclingServeJackson2ClientTests.java b/docling-serve/docling-serve-client/src/test/java/ai/docling/serve/client/DoclingServeJackson2ClientTests.java index a84ebaf..833ab53 100644 --- a/docling-serve/docling-serve-client/src/test/java/ai/docling/serve/client/DoclingServeJackson2ClientTests.java +++ b/docling-serve/docling-serve-client/src/test/java/ai/docling/serve/client/DoclingServeJackson2ClientTests.java @@ -9,19 +9,22 @@ */ class DoclingServeJackson2ClientTests extends AbstractDoclingServeClientTests { private static DoclingServeApi doclingClient; + private static DoclingServeApi authDoclingClient; @BeforeAll static void setUp() { - doclingClient = DoclingServeJackson2Client.builder() - .baseUrl(doclingContainer.getApiUrl()) + var builder = DoclingServeJackson2Client.builder() .logRequests() .logResponses() .prettyPrint() - .build(); + .baseUrl(doclingContainer.getApiUrl()); + + doclingClient = builder.build(); + authDoclingClient = builder.apiKey("key").build(); } @Override - protected DoclingServeApi getDoclingClient() { - return doclingClient; + protected DoclingServeApi getDoclingClient(boolean requiresAuth) { + return requiresAuth ? authDoclingClient : doclingClient; } } diff --git a/docling-serve/docling-serve-client/src/test/java/ai/docling/serve/client/DoclingServeJackson3ClientTests.java b/docling-serve/docling-serve-client/src/test/java/ai/docling/serve/client/DoclingServeJackson3ClientTests.java index 97bc9f9..8ef39f2 100644 --- a/docling-serve/docling-serve-client/src/test/java/ai/docling/serve/client/DoclingServeJackson3ClientTests.java +++ b/docling-serve/docling-serve-client/src/test/java/ai/docling/serve/client/DoclingServeJackson3ClientTests.java @@ -9,19 +9,22 @@ */ class DoclingServeJackson3ClientTests extends AbstractDoclingServeClientTests { private static DoclingServeApi doclingClient; + private static DoclingServeApi authDoclingClient; @BeforeAll static void setUp() { - doclingClient = DoclingServeJackson3Client.builder() + var builder = DoclingServeJackson3Client.builder() .logRequests() .logResponses() .prettyPrint() - .baseUrl(doclingContainer.getApiUrl()) - .build(); + .baseUrl(doclingContainer.getApiUrl()); + + doclingClient = builder.build(); + authDoclingClient = builder.apiKey("key").build(); } @Override - protected DoclingServeApi getDoclingClient() { - return doclingClient; + protected DoclingServeApi getDoclingClient(boolean requiresAuth) { + return requiresAuth ? authDoclingClient : doclingClient; } } diff --git a/docling-testcontainers/src/test/java/ai/docling/testcontainers/serve/DoclingServeContainerAvailableTests.java b/docling-testcontainers/src/test/java/ai/docling/testcontainers/serve/DoclingServeContainerAvailableTests.java index 2d8ae2b..560ff63 100644 --- a/docling-testcontainers/src/test/java/ai/docling/testcontainers/serve/DoclingServeContainerAvailableTests.java +++ b/docling-testcontainers/src/test/java/ai/docling/testcontainers/serve/DoclingServeContainerAvailableTests.java @@ -3,14 +3,10 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import java.io.IOException; -import java.net.http.HttpResponse; - import org.junit.jupiter.api.Test; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; -import ai.docling.serve.api.auth.Authentication; import ai.docling.serve.api.clear.request.ClearResultsRequest; import ai.docling.serve.api.clear.response.ClearResponse; import ai.docling.serve.api.health.HealthCheckResponse; @@ -67,7 +63,7 @@ void containerNoUI() { } @Test - void containerAvailable() throws IOException, InterruptedException { + void containerAvailable() { var client = DoclingServeClientBuilderFactory.newBuilder() .baseUrl(this.noUiDoclingContainer.getApiUrl()) .build(); @@ -106,11 +102,10 @@ void containerWithoutApiKeyClientWith() { .logRequests() .logResponses() .prettyPrint() + .apiKey(DEFAULT_API_KEY) .build(); - var auth = Authentication.builder().apiKey(DEFAULT_API_KEY).build(); - - assertThat(client.clearResults(ClearResultsRequest.builder().authentication(auth).build())) + assertThat(client.clearResults(ClearResultsRequest.builder().build())) .isNotNull() .extracting(ClearResponse::getStatus) .isEqualTo("ok"); @@ -123,26 +118,12 @@ void containerWithApiKeyClientWith() { .logRequests() .logResponses() .prettyPrint() + .apiKey(DEFAULT_API_KEY) .build(); - var auth = Authentication.builder().apiKey(DEFAULT_API_KEY).build(); - - assertThat(client.clearResults(ClearResultsRequest.builder().authentication(auth).build())) + assertThat(client.clearResults(ClearResultsRequest.builder().build())) .isNotNull() .extracting(ClearResponse::getStatus) .isEqualTo("ok"); } - - private static HttpResponse.BodyHandler jsonBodyHandler(Class type) { - return responseInfo -> HttpResponse.BodySubscribers.mapping( - HttpResponse.BodySubscribers.ofByteArray(), - bytes -> { - try { - return JSON_MAPPER.readValue(bytes, type); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - ); - } }