From 229e5f0db035df8b34b85375be680cb7c89796f5 Mon Sep 17 00:00:00 2001
From: tomsun28
Date: Fri, 7 Nov 2025 13:51:20 +0800
Subject: [PATCH 1/5] feat: add web reader api
---
.../java/ai/z/openapi/AbstractAiClient.java | 17 ++++
.../openapi/api/web_reader/WebReaderApi.java | 22 +++++
.../service/web_reader/WebReaderRequest.java | 82 +++++++++++++++++++
.../service/web_reader/WebReaderResponse.java | 20 +++++
.../service/web_reader/WebReaderResult.java | 42 ++++++++++
.../service/web_reader/WebReaderService.java | 15 ++++
.../web_reader/WebReaderServiceImpl.java | 27 ++++++
.../web_reader/WebReaderServiceTest.java | 32 ++++++++
.../WebReaderExample.java | 80 ++++++++++++++++++
9 files changed, 337 insertions(+)
create mode 100644 core/src/main/java/ai/z/openapi/api/web_reader/WebReaderApi.java
create mode 100644 core/src/main/java/ai/z/openapi/service/web_reader/WebReaderRequest.java
create mode 100644 core/src/main/java/ai/z/openapi/service/web_reader/WebReaderResponse.java
create mode 100644 core/src/main/java/ai/z/openapi/service/web_reader/WebReaderResult.java
create mode 100644 core/src/main/java/ai/z/openapi/service/web_reader/WebReaderService.java
create mode 100644 core/src/main/java/ai/z/openapi/service/web_reader/WebReaderServiceImpl.java
create mode 100644 core/src/test/java/ai/z/openapi/service/web_reader/WebReaderServiceTest.java
create mode 100644 samples/src/main/ai.z.openapi.samples/WebReaderExample.java
diff --git a/core/src/main/java/ai/z/openapi/AbstractAiClient.java b/core/src/main/java/ai/z/openapi/AbstractAiClient.java
index 7df1add..bc305ae 100644
--- a/core/src/main/java/ai/z/openapi/AbstractAiClient.java
+++ b/core/src/main/java/ai/z/openapi/AbstractAiClient.java
@@ -21,6 +21,8 @@
import ai.z.openapi.service.batches.BatchServiceImpl;
import ai.z.openapi.service.web_search.WebSearchService;
import ai.z.openapi.service.web_search.WebSearchServiceImpl;
+import ai.z.openapi.service.web_reader.WebReaderService;
+import ai.z.openapi.service.web_reader.WebReaderServiceImpl;
import ai.z.openapi.service.videos.VideosService;
import ai.z.openapi.service.videos.VideosServiceImpl;
import ai.z.openapi.service.assistant.AssistantService;
@@ -99,6 +101,9 @@ public abstract class AbstractAiClient extends AbstractClientBaseService {
/** Web search service for internet search capabilities */
private WebSearchService webSearchService;
+ /** Web reader service for parsing web pages */
+ private WebReaderService webReaderService;
+
/** Videos service for video processing */
private VideosService videosService;
@@ -230,6 +235,18 @@ public synchronized WebSearchService webSearch() {
return webSearchService;
}
+ /**
+ * Returns the web reader service for parsing web pages. This service reads and
+ * extracts content, metadata, images, and links from URLs.
+ * @return the WebReaderService instance (lazily initialized)
+ */
+ public synchronized WebReaderService webReader() {
+ if (webReaderService == null) {
+ this.webReaderService = new WebReaderServiceImpl(this);
+ }
+ return webReaderService;
+ }
+
/**
* Returns the videos service for video processing. This service handles video
* analysis, generation, and manipulation.
diff --git a/core/src/main/java/ai/z/openapi/api/web_reader/WebReaderApi.java b/core/src/main/java/ai/z/openapi/api/web_reader/WebReaderApi.java
new file mode 100644
index 0000000..55840c1
--- /dev/null
+++ b/core/src/main/java/ai/z/openapi/api/web_reader/WebReaderApi.java
@@ -0,0 +1,22 @@
+package ai.z.openapi.api.web_reader;
+
+import ai.z.openapi.service.web_reader.WebReaderRequest;
+import ai.z.openapi.service.web_reader.WebReaderResult;
+import io.reactivex.rxjava3.core.Single;
+import retrofit2.http.Body;
+import retrofit2.http.POST;
+
+/**
+ * Web Reader API for reading and parsing web page content.
+ */
+public interface WebReaderApi {
+
+ /**
+ * Read and parse content from a given URL.
+ * @param request reader parameters including url and options
+ * @return parsed content and metadata
+ */
+ @POST("reader")
+ Single reader(@Body WebReaderRequest request);
+
+}
\ No newline at end of file
diff --git a/core/src/main/java/ai/z/openapi/service/web_reader/WebReaderRequest.java b/core/src/main/java/ai/z/openapi/service/web_reader/WebReaderRequest.java
new file mode 100644
index 0000000..32a6f87
--- /dev/null
+++ b/core/src/main/java/ai/z/openapi/service/web_reader/WebReaderRequest.java
@@ -0,0 +1,82 @@
+package ai.z.openapi.service.web_reader;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import ai.z.openapi.core.model.ClientRequest;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.SuperBuilder;
+
+@SuperBuilder
+@NoArgsConstructor
+@AllArgsConstructor
+@Data
+public class WebReaderRequest implements ClientRequest {
+
+ /**
+ * The target URL to read and parse content from.
+ */
+ @JsonProperty("url")
+ private String url;
+
+ /**
+ * Unique request identifier, used for tracing.
+ */
+ @JsonProperty("request_id")
+ private String requestId;
+
+ /**
+ * User ID associated with the request.
+ */
+ @JsonProperty("user_id")
+ private String userId;
+
+ /**
+ * Timeout in seconds for the reader operation.
+ */
+ @JsonProperty("timeout")
+ private Integer timeout;
+
+ /**
+ * Whether to bypass cache when reading.
+ */
+ @JsonProperty("no_cache")
+ private Boolean noCache;
+
+ /**
+ * Return format of the reader output, e.g., markdown or plain.
+ */
+ @JsonProperty("return_format")
+ private String returnFormat;
+
+ /**
+ * Whether to retain image placeholders in the content.
+ */
+ @JsonProperty("retain_images")
+ private Boolean retainImages;
+
+ /**
+ * Whether to disable GitHub-Flavored Markdown processing.
+ */
+ @JsonProperty("no_gfm")
+ private Boolean noGfm;
+
+ /**
+ * Whether to keep image data URLs inline.
+ */
+ @JsonProperty("keep_img_data_url")
+ private Boolean keepImgDataUrl;
+
+ /**
+ * Whether to include images summary in the result.
+ */
+ @JsonProperty("with_images_summary")
+ private Boolean withImagesSummary;
+
+ /**
+ * Whether to include links summary in the result.
+ */
+ @JsonProperty("with_links_summary")
+ private Boolean withLinksSummary;
+
+}
\ No newline at end of file
diff --git a/core/src/main/java/ai/z/openapi/service/web_reader/WebReaderResponse.java b/core/src/main/java/ai/z/openapi/service/web_reader/WebReaderResponse.java
new file mode 100644
index 0000000..aa15fb6
--- /dev/null
+++ b/core/src/main/java/ai/z/openapi/service/web_reader/WebReaderResponse.java
@@ -0,0 +1,20 @@
+package ai.z.openapi.service.web_reader;
+
+import ai.z.openapi.core.model.ClientResponse;
+import ai.z.openapi.service.model.ChatError;
+import lombok.Data;
+
+@Data
+public class WebReaderResponse implements ClientResponse {
+
+ private int code;
+
+ private String msg;
+
+ private boolean success;
+
+ private WebReaderResult data;
+
+ private ChatError error;
+
+}
diff --git a/core/src/main/java/ai/z/openapi/service/web_reader/WebReaderResult.java b/core/src/main/java/ai/z/openapi/service/web_reader/WebReaderResult.java
new file mode 100644
index 0000000..337ebc1
--- /dev/null
+++ b/core/src/main/java/ai/z/openapi/service/web_reader/WebReaderResult.java
@@ -0,0 +1,42 @@
+package ai.z.openapi.service.web_reader;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+
+import java.util.Map;
+
+@Data
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class WebReaderResult {
+
+ @JsonProperty("reader_result")
+ private ReaderData readerResult;
+
+ @Data
+ @JsonIgnoreProperties(ignoreUnknown = true)
+ @JsonInclude(JsonInclude.Include.NON_EMPTY)
+ public static class ReaderData {
+
+ private Map images;
+
+ private Map links;
+
+ private String title;
+
+ private String description;
+
+ private String url;
+
+ private String content;
+
+ private String publishedTime;
+
+ private Map metadata;
+
+ private Map external;
+
+ }
+
+}
diff --git a/core/src/main/java/ai/z/openapi/service/web_reader/WebReaderService.java b/core/src/main/java/ai/z/openapi/service/web_reader/WebReaderService.java
new file mode 100644
index 0000000..d3a8b3f
--- /dev/null
+++ b/core/src/main/java/ai/z/openapi/service/web_reader/WebReaderService.java
@@ -0,0 +1,15 @@
+package ai.z.openapi.service.web_reader;
+
+/**
+ * Web reader service interface
+ */
+public interface WebReaderService {
+
+ /**
+ * Creates a web reader request to parse a URL.
+ * @param request the web reader request
+ * @return WebReaderResponse containing the reader result
+ */
+ WebReaderResponse createWebReader(WebReaderRequest request);
+
+}
\ No newline at end of file
diff --git a/core/src/main/java/ai/z/openapi/service/web_reader/WebReaderServiceImpl.java b/core/src/main/java/ai/z/openapi/service/web_reader/WebReaderServiceImpl.java
new file mode 100644
index 0000000..df34233
--- /dev/null
+++ b/core/src/main/java/ai/z/openapi/service/web_reader/WebReaderServiceImpl.java
@@ -0,0 +1,27 @@
+package ai.z.openapi.service.web_reader;
+
+import ai.z.openapi.AbstractAiClient;
+import ai.z.openapi.api.web_reader.WebReaderApi;
+import ai.z.openapi.utils.RequestSupplier;
+
+/**
+ * Web reader service implementation
+ */
+public class WebReaderServiceImpl implements WebReaderService {
+
+ private final AbstractAiClient zAiClient;
+
+ private final WebReaderApi webReaderApi;
+
+ public WebReaderServiceImpl(AbstractAiClient zAiClient) {
+ this.zAiClient = zAiClient;
+ this.webReaderApi = zAiClient.retrofit().create(WebReaderApi.class);
+ }
+
+ @Override
+ public WebReaderResponse createWebReader(WebReaderRequest request) {
+ RequestSupplier supplier = webReaderApi::reader;
+ return this.zAiClient.executeRequest(request, supplier, WebReaderResponse.class);
+ }
+
+}
\ No newline at end of file
diff --git a/core/src/test/java/ai/z/openapi/service/web_reader/WebReaderServiceTest.java b/core/src/test/java/ai/z/openapi/service/web_reader/WebReaderServiceTest.java
new file mode 100644
index 0000000..79b774b
--- /dev/null
+++ b/core/src/test/java/ai/z/openapi/service/web_reader/WebReaderServiceTest.java
@@ -0,0 +1,32 @@
+package ai.z.openapi.service.web_reader;
+
+import ai.z.openapi.ZaiClient;
+import ai.z.openapi.core.config.ZaiConfig;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+@DisplayName("WebReaderService Tests")
+public class WebReaderServiceTest {
+
+ private WebReaderService webReaderService;
+
+ @BeforeEach
+ void setUp() {
+ ZaiConfig zaiConfig = new ZaiConfig();
+ if (zaiConfig.getApiKey() == null) {
+ zaiConfig.setApiKey("id.test-api-key");
+ }
+ ZaiClient client = new ZaiClient(zaiConfig);
+ webReaderService = client.webReader();
+ }
+
+ @Test
+ @DisplayName("Test WebReaderService Instantiation")
+ void testWebReaderServiceInstantiation() {
+ assertNotNull(webReaderService, "WebReaderService should be instantiated");
+ }
+
+}
\ No newline at end of file
diff --git a/samples/src/main/ai.z.openapi.samples/WebReaderExample.java b/samples/src/main/ai.z.openapi.samples/WebReaderExample.java
new file mode 100644
index 0000000..7f59c56
--- /dev/null
+++ b/samples/src/main/ai.z.openapi.samples/WebReaderExample.java
@@ -0,0 +1,80 @@
+package ai.z.openapi.samples;
+
+import ai.z.openapi.ZaiClient;
+import ai.z.openapi.service.web_reader.WebReaderRequest;
+import ai.z.openapi.service.web_reader.WebReaderResponse;
+import ai.z.openapi.service.web_reader.WebReaderResult;
+
+/**
+ * Web Reader Example
+ * Demonstrates how to use ZaiClient for web page reading and parsing capabilities
+ */
+public class WebReaderExample {
+
+ public static void main(String[] args) {
+ // Create client, recommended to set API Key via environment variable
+ // export ZAI_API_KEY=your.api_key
+ // for Z.ai use the `ZaiClient`, for Zhipu AI use the ZhipuAiClient
+ ZaiClient client = ZaiClient.builder().ofZHIPU().build();
+
+ basicWebReader(client);
+ }
+
+ /**
+ * Example of basic web reader functionality
+ */
+ private static void basicWebReader(ZaiClient client) {
+ System.out.println("\n=== Web Reader Example ===");
+
+ // Create web reader request
+ WebReaderRequest request = WebReaderRequest.builder()
+ .url("https://example.com/")
+ .returnFormat("markdown")
+ .withImagesSummary(Boolean.TRUE)
+ .withLinksSummary(Boolean.TRUE)
+ .build();
+
+ try {
+ // Execute request
+ WebReaderResponse response = client.webReader().createWebReader(request);
+
+ if (response.isSuccess()) {
+ System.out.println("Read successful!");
+
+ WebReaderResult result = response.getData();
+ if (result != null && result.getReaderResult() != null) {
+ WebReaderResult.ReaderData data = result.getReaderResult();
+ System.out.println("Title: " + data.getTitle());
+ System.out.println("URL: " + data.getUrl());
+ System.out.println("Description: " + data.getDescription());
+
+ String content = data.getContent();
+ if (content != null) {
+ String preview = content.length() > 300 ? content.substring(0, 300) + "..." : content;
+ System.out.println("\nContent preview:\n" + preview);
+ }
+
+ if (data.getImages() != null) {
+ System.out.println("\nImages count: " + data.getImages().size());
+ }
+ if (data.getLinks() != null) {
+ System.out.println("Links count: " + data.getLinks().size());
+ }
+ }
+ else {
+ System.out.println("No reader result returned.");
+ }
+ }
+ else {
+ System.err.println("Error: " + response.getMsg());
+ if (response.getError() != null) {
+ System.err.println("Error detail: " + response.getError());
+ }
+ }
+ }
+ catch (Exception e) {
+ System.err.println("Exception occurred: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+}
\ No newline at end of file
From 0066ef19a4cb67b2f5941ccb603e36bfe00aad56 Mon Sep 17 00:00:00 2001
From: tomsun28
Date: Fri, 7 Nov 2025 14:12:25 +0800
Subject: [PATCH 2/5] feat: add web reader api
---
.../service/web_reader/WebReaderRequest.java | 33 +++++++++++++++++++
.../web_reader/WebReaderServiceImpl.java | 4 +++
2 files changed, 37 insertions(+)
diff --git a/core/src/main/java/ai/z/openapi/service/web_reader/WebReaderRequest.java b/core/src/main/java/ai/z/openapi/service/web_reader/WebReaderRequest.java
index 32a6f87..b65ff2e 100644
--- a/core/src/main/java/ai/z/openapi/service/web_reader/WebReaderRequest.java
+++ b/core/src/main/java/ai/z/openapi/service/web_reader/WebReaderRequest.java
@@ -6,6 +6,8 @@
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
+import java.net.URI;
+import java.net.URISyntaxException;
@SuperBuilder
@NoArgsConstructor
@@ -79,4 +81,35 @@ public class WebReaderRequest implements ClientRequest {
@JsonProperty("with_links_summary")
private Boolean withLinksSummary;
+ /**
+ * Validate request fields that require constraints. Ensures {@code url} is non-empty
+ * and a syntactically valid HTTP/HTTPS URL.
+ * @throws IllegalArgumentException if validation fails
+ */
+ public void validate() {
+ if (url == null || url.trim().isEmpty()) {
+ throw new IllegalArgumentException("request url cannot be null or empty");
+ }
+ String normalized = url.trim();
+ try {
+ URI initial = new URI(normalized);
+ URI candidate = initial;
+ String scheme = initial.getScheme();
+ if (scheme == null) {
+ String candidateStr = normalized.startsWith("//") ? ("https:" + normalized) : ("https://" + normalized);
+ candidate = new URI(candidateStr);
+ scheme = candidate.getScheme();
+ }
+ if (!("http".equalsIgnoreCase(scheme) || "https".equalsIgnoreCase(scheme))) {
+ throw new IllegalArgumentException("request url must use http or https");
+ }
+ if (candidate.getHost() == null || candidate.getHost().trim().isEmpty()) {
+ throw new IllegalArgumentException("request url must contain a valid host");
+ }
+ }
+ catch (URISyntaxException ex) {
+ throw new IllegalArgumentException("request url is invalid: " + ex.getMessage());
+ }
+ }
+
}
\ No newline at end of file
diff --git a/core/src/main/java/ai/z/openapi/service/web_reader/WebReaderServiceImpl.java b/core/src/main/java/ai/z/openapi/service/web_reader/WebReaderServiceImpl.java
index df34233..125956a 100644
--- a/core/src/main/java/ai/z/openapi/service/web_reader/WebReaderServiceImpl.java
+++ b/core/src/main/java/ai/z/openapi/service/web_reader/WebReaderServiceImpl.java
@@ -20,6 +20,10 @@ public WebReaderServiceImpl(AbstractAiClient zAiClient) {
@Override
public WebReaderResponse createWebReader(WebReaderRequest request) {
+ if (request == null) {
+ throw new IllegalArgumentException("request cannot be null");
+ }
+ request.validate();
RequestSupplier supplier = webReaderApi::reader;
return this.zAiClient.executeRequest(request, supplier, WebReaderResponse.class);
}
From 6352471ab60e84eea3ea7a14a279b65117ffbc04 Mon Sep 17 00:00:00 2001
From: tomsun28
Date: Mon, 10 Nov 2025 15:00:59 +0800
Subject: [PATCH 3/5] feat: add web reader api
---
samples/src/main/ai.z.openapi.samples/CustomClientExample.java | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/samples/src/main/ai.z.openapi.samples/CustomClientExample.java b/samples/src/main/ai.z.openapi.samples/CustomClientExample.java
index 14d9101..4c459c0 100644
--- a/samples/src/main/ai.z.openapi.samples/CustomClientExample.java
+++ b/samples/src/main/ai.z.openapi.samples/CustomClientExample.java
@@ -34,9 +34,8 @@ public static void main(String[] args) throws Exception {
.baseUrl(Constants.ZHIPU_AI_BASE_URL)
.customHeaders(Collections.emptyMap())
.disableTokenCache(true)
- .requestTimeOut(600)
+ .readTimeout(600)
.timeOutTimeUnit(TimeUnit.SECONDS)
- .connectTimeout(60)
.connectionPoolKeepAliveDuration(10)
.connectionPoolTimeUnit(TimeUnit.SECONDS)
.connectionPoolMaxIdleConnections(20)
From ea0f0d2188749804b3456189f237679b8adc9879 Mon Sep 17 00:00:00 2001
From: tomsun28
Date: Mon, 10 Nov 2025 15:09:25 +0800
Subject: [PATCH 4/5] feat: add web reader api
---
core/src/main/java/ai/z/openapi/AbstractAiClient.java | 2 +-
core/src/main/java/ai/z/openapi/ZhipuAiClient.java | 2 +-
samples/src/main/ai.z.openapi.samples/CustomTimeoutExample.java | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/core/src/main/java/ai/z/openapi/AbstractAiClient.java b/core/src/main/java/ai/z/openapi/AbstractAiClient.java
index bc305ae..66e8261 100644
--- a/core/src/main/java/ai/z/openapi/AbstractAiClient.java
+++ b/core/src/main/java/ai/z/openapi/AbstractAiClient.java
@@ -618,7 +618,7 @@ public B tokenExpire(int expireMillis) {
/**
* Configures network request timeout settings.
- * @param requestTimeOut the overall request timeout
+ * @param requestTimeOut the overall request timeout, 0 is no timeout
* @param connectTimeout the connection timeout
* @param readTimeout the read timeout
* @param writeTimeout the write timeout
diff --git a/core/src/main/java/ai/z/openapi/ZhipuAiClient.java b/core/src/main/java/ai/z/openapi/ZhipuAiClient.java
index 0618d02..1f2b6fc 100644
--- a/core/src/main/java/ai/z/openapi/ZhipuAiClient.java
+++ b/core/src/main/java/ai/z/openapi/ZhipuAiClient.java
@@ -87,7 +87,7 @@ public static Builder builder() {
*
* {@code
* ZhipuAiClient client = new ZhipuAiClient.Builder("your-api-key")
- * .networkConfig(30, 10, 30, 30, TimeUnit.SECONDS)
+ * .networkConfig(0, 10, 30, 30, TimeUnit.SECONDS)
* .connectionPool(10, 5, TimeUnit.MINUTES)
* .enableTokenCache()
* .build();
diff --git a/samples/src/main/ai.z.openapi.samples/CustomTimeoutExample.java b/samples/src/main/ai.z.openapi.samples/CustomTimeoutExample.java
index 5bdfdda..1bed73a 100644
--- a/samples/src/main/ai.z.openapi.samples/CustomTimeoutExample.java
+++ b/samples/src/main/ai.z.openapi.samples/CustomTimeoutExample.java
@@ -25,7 +25,7 @@ public static void main(String[] args) {
// export ZAI_API_KEY=your.api_key
// for Z.ai use the `ZaiClient`, for Zhipu AI use the ZhipuAiClient
ZhipuAiClient client = ZhipuAiClient.builder()
- .networkConfig(30, 10, 30, 30, TimeUnit.SECONDS)
+ .networkConfig(0, 10, 30, 30, TimeUnit.SECONDS)
.build();
// Create chat request
From 0f6aed7b49db79027d498d1b0ad7ed222ad0deb1 Mon Sep 17 00:00:00 2001
From: tomsun28
Date: Mon, 10 Nov 2025 15:30:22 +0800
Subject: [PATCH 5/5] feat: add web reader api
---
.../ai/z/openapi/core/config/ZaiConfig.java | 2 +-
.../service/audio/AudioServiceImpl.java | 6 +++--
.../main/java/ai/z/openapi/utils/OkHttps.java | 23 ++++++++++++++++++-
3 files changed, 27 insertions(+), 4 deletions(-)
diff --git a/core/src/main/java/ai/z/openapi/core/config/ZaiConfig.java b/core/src/main/java/ai/z/openapi/core/config/ZaiConfig.java
index c85c235..bad6fe7 100644
--- a/core/src/main/java/ai/z/openapi/core/config/ZaiConfig.java
+++ b/core/src/main/java/ai/z/openapi/core/config/ZaiConfig.java
@@ -97,7 +97,7 @@ public class ZaiConfig {
/**
* Request timeout in specified time unit. The whole timeout for complete calls, is
- * the okhttp call timeout.
+ * the okhttp call timeout. The 0 value means no timeout.
*/
private Integer requestTimeOut;
diff --git a/core/src/main/java/ai/z/openapi/service/audio/AudioServiceImpl.java b/core/src/main/java/ai/z/openapi/service/audio/AudioServiceImpl.java
index 3c5eb26..f0c0d1e 100644
--- a/core/src/main/java/ai/z/openapi/service/audio/AudioServiceImpl.java
+++ b/core/src/main/java/ai/z/openapi/service/audio/AudioServiceImpl.java
@@ -8,11 +8,12 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import io.reactivex.rxjava3.core.Single;
-import lombok.extern.slf4j.Slf4j;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.InputStream;
@@ -26,9 +27,10 @@
/**
* Audio service implementation
*/
-@Slf4j
public class AudioServiceImpl implements AudioService {
+ private static final Logger log = LoggerFactory.getLogger(AudioServiceImpl.class);
+
protected static final ObjectMapper mapper = MessageDeserializeFactory.defaultObjectMapper();
private final AbstractAiClient zAiClient;
diff --git a/core/src/main/java/ai/z/openapi/utils/OkHttps.java b/core/src/main/java/ai/z/openapi/utils/OkHttps.java
index af2e964..b41db8c 100644
--- a/core/src/main/java/ai/z/openapi/utils/OkHttps.java
+++ b/core/src/main/java/ai/z/openapi/utils/OkHttps.java
@@ -4,6 +4,9 @@
import ai.z.openapi.core.token.HttpRequestInterceptor;
import okhttp3.ConnectionPool;
import okhttp3.OkHttpClient;
+import okhttp3.internal.Util;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.util.concurrent.TimeUnit;
@@ -15,6 +18,8 @@
*/
public final class OkHttps {
+ private static final Logger logger = LoggerFactory.getLogger(OkHttps.class);
+
// The default value is 0 which imposes no timeout.
private static final int DEFAULT_CALL_TIMEOUT_SECONDS = 0;
@@ -60,37 +65,53 @@ public static OkHttpClient create(ZaiConfig config) {
*/
private static void configureTimeouts(OkHttpClient.Builder builder, ZaiConfig config) {
TimeUnit timeUnit = config.getTimeOutTimeUnit();
-
+ int callTimeout;
+ int connectTimeout;
+ int readTimeout;
+ int writeTimeout;
// Configure call timeout
if (config.getRequestTimeOut() != null && config.getRequestTimeOut() > 0) {
builder.callTimeout(config.getRequestTimeOut(), timeUnit);
+ callTimeout = Util.checkDuration("callTimeout", config.getRequestTimeOut(), timeUnit);
}
else {
builder.callTimeout(DEFAULT_CALL_TIMEOUT_SECONDS, TimeUnit.SECONDS);
+ callTimeout = Util.checkDuration("callTimeout", DEFAULT_CALL_TIMEOUT_SECONDS, TimeUnit.SECONDS);
}
// Configure connect timeout
if (config.getConnectTimeout() != null && config.getConnectTimeout() > 0) {
builder.connectTimeout(config.getConnectTimeout(), timeUnit);
+ connectTimeout = Util.checkDuration("connectTimeout", config.getConnectTimeout(), timeUnit);
}
else {
builder.connectTimeout(DEFAULT_CONNECT_TIMEOUT_SECONDS, TimeUnit.SECONDS);
+ connectTimeout = Util.checkDuration("connectTimeout", DEFAULT_CONNECT_TIMEOUT_SECONDS, TimeUnit.SECONDS);
}
// Configure read timeout
if (config.getReadTimeout() != null && config.getReadTimeout() > 0) {
builder.readTimeout(config.getReadTimeout(), timeUnit);
+ readTimeout = Util.checkDuration("readTimeout", config.getReadTimeout(), timeUnit);
}
else {
builder.readTimeout(DEFAULT_READ_TIMEOUT_SECONDS, TimeUnit.SECONDS);
+ readTimeout = Util.checkDuration("readTimeout", DEFAULT_READ_TIMEOUT_SECONDS, TimeUnit.SECONDS);
}
// Configure write timeout
if (config.getWriteTimeout() != null && config.getWriteTimeout() > 0) {
builder.writeTimeout(config.getWriteTimeout(), timeUnit);
+ writeTimeout = Util.checkDuration("writeTimeout", config.getWriteTimeout(), timeUnit);
}
else {
builder.writeTimeout(DEFAULT_WRITE_TIMEOUT_SECONDS, TimeUnit.SECONDS);
+ writeTimeout = Util.checkDuration("writeTimeout", DEFAULT_WRITE_TIMEOUT_SECONDS, TimeUnit.SECONDS);
+ }
+ if (callTimeout != 0 && (callTimeout <= (connectTimeout + readTimeout + writeTimeout))) {
+ logger.error("Wrong Request(Call) timeout configuration");
+ logger.error(
+ "Request(Call) timeout is less than or equal to the sum of connect, read, and write timeouts. This may cause issues with the client.");
}
}