diff --git a/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/convert/request/target/PresignedUrlTarget.java b/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/convert/request/target/PresignedUrlTarget.java new file mode 100644 index 00000000..569f83d8 --- /dev/null +++ b/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/convert/request/target/PresignedUrlTarget.java @@ -0,0 +1,37 @@ +package ai.docling.serve.api.convert.request.target; + +import com.fasterxml.jackson.annotation.JsonInclude; + +/** + * Target for delivering the converted document via server-managed presigned URLs. + * + *
This is a concrete implementation of {@link Target}, where the {@code Kind} is set to + * {@link Kind#PRESIGNED_URL}. The docling-serve instance uploads each output artifact to its + * own configured object storage bucket and returns time-limited presigned GET URLs in the + * response. Clients supply no storage credentials; the server's operator manages them via + * the {@code DOCLING_SERVE_ARTIFACT_STORAGE_*} settings. + * + *
Available in docling-serve {@code v1.22.0} and later. Requires the server to have + * {@code DOCLING_SERVE_ARTIFACT_STORAGE_ENABLED=true}; otherwise the request is rejected + * at admission. Responses for this target deserialise as + * {@code PreSignedUrlConvertDocumentResponse}. + * + *
Uses JSON serialization annotations to include only non-empty fields in the output. + * + *
This class overrides {@link Object#toString()} for a string representation of the instance. + */ +@JsonInclude(JsonInclude.Include.NON_EMPTY) +@tools.jackson.databind.annotation.JsonDeserialize(builder = PresignedUrlTarget.Builder.class) +@lombok.extern.jackson.Jacksonized +@lombok.Builder(toBuilder = true) +@lombok.Getter +@lombok.ToString +public final class PresignedUrlTarget extends Target { + + /** + * Builder for creating {@link PresignedUrlTarget} instances. + * Generated by Lombok's {@code @Builder} annotation. + */ + @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/convert/request/target/Target.java b/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/convert/request/target/Target.java index bfdb5b28..7f2b0fa1 100644 --- a/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/convert/request/target/Target.java +++ b/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/convert/request/target/Target.java @@ -10,9 +10,11 @@ * Represents an abstract target for defining where and how the converted document should be delivered. * *
The {@link Target} class is a sealed type that is extended by specific concrete implementations: - * {@link InBodyTarget}, {@link PutTarget}, {@link S3Target}, and {@link ZipTarget}. These implementations specify different - * delivery methods, such as including the document in the response body, sending it to a specified URI, or - * zipping it for inclusion in the response. + * {@link InBodyTarget}, {@link PutTarget}, {@link S3Target}, {@link ZipTarget}, and + * {@link PresignedUrlTarget}. These implementations specify different delivery methods, such as + * including the document in the response body, sending it to a specified URI, zipping it for + * inclusion in the response, or returning server-managed presigned URLs that point at the + * docling-serve operator's object storage. */ @JsonInclude(JsonInclude.Include.NON_EMPTY) @JsonTypeInfo( @@ -24,15 +26,17 @@ @Type(value = InBodyTarget.class, name = "inbody"), @Type(value = PutTarget.class, name = "put"), @Type(value = ZipTarget.class, name = "zip"), - @Type(value = S3Target.class, name = "s3") + @Type(value = S3Target.class, name = "s3"), + @Type(value = PresignedUrlTarget.class, name = "presigned_url") }) @lombok.Getter @lombok.ToString -public abstract sealed class Target permits InBodyTarget, PutTarget, S3Target, ZipTarget { +public abstract sealed class Target permits InBodyTarget, PresignedUrlTarget, PutTarget, S3Target, ZipTarget { enum Kind { @JsonProperty("inbody") INBODY, @JsonProperty("put") PUT, @JsonProperty("zip") ZIP, - @JsonProperty("s3") S3 + @JsonProperty("s3") S3, + @JsonProperty("presigned_url") PRESIGNED_URL } } diff --git a/docling-serve/docling-serve-api/src/test/java/ai/docling/serve/api/convert/request/target/PresignedUrlTargetTests.java b/docling-serve/docling-serve-api/src/test/java/ai/docling/serve/api/convert/request/target/PresignedUrlTargetTests.java new file mode 100644 index 00000000..c6302b4e --- /dev/null +++ b/docling-serve/docling-serve-api/src/test/java/ai/docling/serve/api/convert/request/target/PresignedUrlTargetTests.java @@ -0,0 +1,34 @@ +package ai.docling.serve.api.convert.request.target; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; + +/** + * Unit tests for {@link PresignedUrlTarget}. + */ +class PresignedUrlTargetTests { + + @Test + void whenBuiltThenInstanceCreated() { + PresignedUrlTarget target = PresignedUrlTarget.builder().build(); + + assertThat(target).isNotNull(); + } + + @Test + void whenBuiltThenIsTargetSubtype() { + PresignedUrlTarget target = PresignedUrlTarget.builder().build(); + + assertThat(target).isInstanceOf(Target.class); + } + + @Test + void whenToBuilderInvokedThenEqualInstanceProduced() { + PresignedUrlTarget target = PresignedUrlTarget.builder().build(); + + PresignedUrlTarget roundtripped = target.toBuilder().build(); + + assertThat(roundtripped).usingRecursiveComparison().isEqualTo(target); + } +}