diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/io/stream/SyncInputStream.java b/hutool-core/src/main/java/org/dromara/hutool/core/io/stream/SyncInputStream.java
index 1b41760c2..c2e8e3e12 100644
--- a/hutool-core/src/main/java/org/dromara/hutool/core/io/stream/SyncInputStream.java
+++ b/hutool-core/src/main/java/org/dromara/hutool/core/io/stream/SyncInputStream.java
@@ -58,7 +58,8 @@ public class SyncInputStream extends FilterInputStream {
}
/**
- * 同步数据到内存
+ * 同步数据到内存,同步后关闭原流
+ *
* @return this
*/
public SyncInputStream sync() {
@@ -76,18 +77,19 @@ public class SyncInputStream extends FilterInputStream {
* @return bytes
*/
public byte[] readBytes() {
- final FastByteArrayOutputStream bytesOut = new FastByteArrayOutputStream(length > 0 ? (int)length : 1024);
+ final FastByteArrayOutputStream bytesOut = new FastByteArrayOutputStream(length > 0 ? (int) length : 1024);
final long length = copyTo(bytesOut, null);
return length > 0 ? bytesOut.toByteArray() : new byte[0];
}
/**
- * 将流的内容拷贝到输出流
- * @param out 输出流
+ * 将流的内容拷贝到输出流,拷贝结束后关闭输入流
+ *
+ * @param out 输出流
* @param streamProgress 进度条
* @return 拷贝长度
*/
- public long copyTo(final OutputStream out, final StreamProgress streamProgress){
+ public long copyTo(final OutputStream out, final StreamProgress streamProgress) {
long copyLength = -1;
try {
copyLength = IoUtil.copy(this.in, out, IoUtil.DEFAULT_BUFFER_SIZE, this.length, streamProgress);
@@ -96,7 +98,7 @@ public class SyncInputStream extends FilterInputStream {
throw e;
}
// 忽略读取流中的EOF错误
- }finally {
+ } finally {
// 读取结束
IoUtil.closeQuietly(in);
}
diff --git a/hutool-http/src/main/java/org/dromara/hutool/http/client/Response.java b/hutool-http/src/main/java/org/dromara/hutool/http/client/Response.java
index 097efacb4..a9545b361 100644
--- a/hutool-http/src/main/java/org/dromara/hutool/http/client/Response.java
+++ b/hutool-http/src/main/java/org/dromara/hutool/http/client/Response.java
@@ -82,13 +82,21 @@ public interface Response extends Closeable {
InputStream bodyStream();
/**
- * 获取响应体,包含服务端返回的内容和Content-Type信息
+ * 同步
+ * 如果为异步状态,则暂时不读取服务器中响应的内容,而是持有Http链接的{@link InputStream}。
+ * 当调用此方法时,异步状态转为同步状态,此时从Http链接流中读取body内容并暂存在内容(内存)中。如果已经是同步状态,则不进行任何操作。
+ *
+ * @return this
+ */
+ Response sync();
+
+ /**
+ * 获取响应体,包含服务端返回的内容和Content-Type信息
+ * 如果为HEAD、CONNECT、TRACE等方法无响应体,则返回{@code null}
*
* @return {@link ResponseBody}
*/
- default ResponseBody body() {
- return new ResponseBody(this, bodyStream(), false, true);
- }
+ ResponseBody body();
/**
* 获取响应主体
@@ -112,7 +120,7 @@ public interface Response extends Closeable {
*/
default byte[] bodyBytes() {
try (final ResponseBody body = body()) {
- return body.getBytes();
+ return null == body ? null : body.getBytes();
} catch (final IOException e) {
throw new IORuntimeException(e);
}
diff --git a/hutool-http/src/main/java/org/dromara/hutool/http/client/body/ResponseBody.java b/hutool-http/src/main/java/org/dromara/hutool/http/client/body/ResponseBody.java
index 974962885..8163f99fe 100644
--- a/hutool-http/src/main/java/org/dromara/hutool/http/client/body/ResponseBody.java
+++ b/hutool-http/src/main/java/org/dromara/hutool/http/client/body/ResponseBody.java
@@ -44,6 +44,16 @@ public class ResponseBody implements HttpBody, Closeable {
*/
private final SyncInputStream bodyStream;
+ /**
+ * 构造,不读取响应体,忽略响应体EOF错误
+ *
+ * @param response 响应体
+ * @param in HTTP主体响应流
+ */
+ public ResponseBody(final Response response, final InputStream in) {
+ this(response, in, true, true);
+ }
+
/**
* 构造
*
diff --git a/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/httpclient4/HttpClient4Engine.java b/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/httpclient4/HttpClient4Engine.java
index eb86f796a..4e724002b 100644
--- a/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/httpclient4/HttpClient4Engine.java
+++ b/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/httpclient4/HttpClient4Engine.java
@@ -21,6 +21,7 @@ import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.config.RequestConfig;
+import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
@@ -75,11 +76,14 @@ public class HttpClient4Engine extends AbstractClientEngine {
initEngine();
final HttpUriRequest request = buildRequest(message);
+ final CloseableHttpResponse response;
try {
- return this.engine.execute(request, response -> new HttpClient4Response(response, message.charset()));
+ //return this.engine.execute(request, response -> new HttpClient4Response(response, message));
+ response = this.engine.execute(request);
} catch (final IOException e) {
throw new HttpException(e);
}
+ return new HttpClient4Response(response, message);
}
@Override
diff --git a/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/httpclient4/HttpClient4Response.java b/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/httpclient4/HttpClient4Response.java
index c3ff0a554..ce2537603 100644
--- a/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/httpclient4/HttpClient4Response.java
+++ b/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/httpclient4/HttpClient4Response.java
@@ -24,13 +24,15 @@ import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.util.EntityUtils;
import org.dromara.hutool.core.array.ArrayUtil;
import org.dromara.hutool.core.io.IORuntimeException;
+import org.dromara.hutool.core.io.IoUtil;
import org.dromara.hutool.core.lang.wrapper.SimpleWrapper;
import org.dromara.hutool.core.util.ObjUtil;
import org.dromara.hutool.http.HttpException;
import org.dromara.hutool.http.HttpUtil;
+import org.dromara.hutool.http.client.Request;
import org.dromara.hutool.http.client.Response;
+import org.dromara.hutool.http.client.body.ResponseBody;
-import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
@@ -52,18 +54,20 @@ public class HttpClient4Response extends SimpleWrapper implements
* 请求时的默认编码
*/
private final Charset requestCharset;
+ private final ResponseBody body;
/**
* 构造
* 通过传入一个请求时的编码,当无法获取响应内容的编码时,默认使用响应时的编码
*
- * @param rawRes {@link HttpResponse}
- * @param requestCharset 请求时的编码
+ * @param rawRes {@link HttpResponse}
+ * @param message 请求消息
*/
- public HttpClient4Response(final HttpResponse rawRes, final Charset requestCharset) {
+ public HttpClient4Response(final HttpResponse rawRes, final Request message) {
super(rawRes);
this.entity = rawRes.getEntity();
- this.requestCharset = requestCharset;
+ this.requestCharset = message.charset();
+ this.body = message.method().isIgnoreBody() ? null : new ResponseBody(this, bodyStream());
}
@@ -112,6 +116,21 @@ public class HttpClient4Response extends SimpleWrapper implements
}
}
+ @Override
+ public HttpClient4Response sync() {
+ final ResponseBody body = this.body;
+ if(null != body){
+ body.sync();
+ }
+ IoUtil.closeIfPossible(this.raw);
+ return this;
+ }
+
+ @Override
+ public ResponseBody body() {
+ return this.body;
+ }
+
@Override
public String bodyStr() throws HttpException {
try {
@@ -124,10 +143,8 @@ public class HttpClient4Response extends SimpleWrapper implements
}
@Override
- public void close() throws IOException {
- if(this.raw instanceof Closeable){
- ((Closeable) this.raw).close();
- }
+ public void close() {
+ IoUtil.closeIfPossible(this.raw);
}
@Override
diff --git a/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/httpclient5/HttpClient5Engine.java b/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/httpclient5/HttpClient5Engine.java
index e91ca3512..cbb735a1a 100644
--- a/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/httpclient5/HttpClient5Engine.java
+++ b/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/httpclient5/HttpClient5Engine.java
@@ -29,6 +29,7 @@ import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder;
import org.apache.hc.core5.http.ClassicHttpRequest;
+import org.apache.hc.core5.http.ClassicHttpResponse;
import org.apache.hc.core5.http.Header;
import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.message.BasicHeader;
@@ -81,11 +82,14 @@ public class HttpClient5Engine extends AbstractClientEngine {
initEngine();
final ClassicHttpRequest request = buildRequest(message);
+ final ClassicHttpResponse response;
try {
- return this.engine.execute(request, (response -> new HttpClient5Response(response, message.charset())));
+ //return this.engine.execute(request, (response -> new HttpClient5Response(response, message)));
+ response = this.engine.executeOpen(null, request, null);
} catch (final IOException e) {
throw new HttpException(e);
}
+ return new HttpClient5Response(response, message);
}
@Override
diff --git a/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/httpclient5/HttpClient5Response.java b/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/httpclient5/HttpClient5Response.java
index 57c002bd5..f21b08a4a 100644
--- a/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/httpclient5/HttpClient5Response.java
+++ b/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/httpclient5/HttpClient5Response.java
@@ -16,28 +16,27 @@
package org.dromara.hutool.http.client.engine.httpclient5;
+import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
+import org.apache.hc.core5.http.ClassicHttpResponse;
+import org.apache.hc.core5.http.Header;
import org.apache.hc.core5.http.HttpEntity;
-import org.dromara.hutool.core.io.IORuntimeException;
+import org.apache.hc.core5.http.ParseException;
+import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.dromara.hutool.core.array.ArrayUtil;
+import org.dromara.hutool.core.io.IORuntimeException;
+import org.dromara.hutool.core.io.IoUtil;
import org.dromara.hutool.core.lang.wrapper.SimpleWrapper;
import org.dromara.hutool.core.util.ObjUtil;
import org.dromara.hutool.http.HttpException;
import org.dromara.hutool.http.HttpUtil;
+import org.dromara.hutool.http.client.Request;
import org.dromara.hutool.http.client.Response;
-import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
-import org.apache.hc.core5.http.ClassicHttpResponse;
-import org.apache.hc.core5.http.Header;
-import org.apache.hc.core5.http.ParseException;
-import org.apache.hc.core5.http.io.entity.EntityUtils;
+import org.dromara.hutool.http.client.body.ResponseBody;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
/**
* HttpClient响应包装
@@ -52,18 +51,20 @@ public class HttpClient5Response extends SimpleWrapper impl
* 请求时的默认编码
*/
private final Charset requestCharset;
+ private final ResponseBody body;
/**
* 构造
* 通过传入一个请求时的编码,当无法获取响应内容的编码时,默认使用响应时的编码
*
- * @param rawRes {@link CloseableHttpResponse}
- * @param requestCharset 请求时的编码
+ * @param rawRes {@link CloseableHttpResponse}
+ * @param message 请求消息
*/
- public HttpClient5Response(final ClassicHttpResponse rawRes, final Charset requestCharset) {
+ public HttpClient5Response(final ClassicHttpResponse rawRes, final Request message) {
super(rawRes);
this.entity = rawRes.getEntity();
- this.requestCharset = requestCharset;
+ this.requestCharset = message.charset();
+ this.body = message.method().isIgnoreBody() ? null : new ResponseBody(this, bodyStream());
}
@@ -112,6 +113,21 @@ public class HttpClient5Response extends SimpleWrapper impl
}
}
+ @Override
+ public HttpClient5Response sync() {
+ final ResponseBody body = this.body;
+ if(null != body){
+ body.sync();
+ }
+ IoUtil.closeQuietly(this.raw);
+ return this;
+ }
+
+ @Override
+ public ResponseBody body() {
+ return this.body;
+ }
+
@Override
public String bodyStr() throws HttpException {
try {
diff --git a/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/jdk/JdkClientEngine.java b/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/jdk/JdkClientEngine.java
index dfed64f97..53626c693 100644
--- a/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/jdk/JdkClientEngine.java
+++ b/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/jdk/JdkClientEngine.java
@@ -26,7 +26,6 @@ import org.dromara.hutool.http.HttpException;
import org.dromara.hutool.http.HttpUtil;
import org.dromara.hutool.http.client.ClientConfig;
import org.dromara.hutool.http.client.Request;
-import org.dromara.hutool.http.client.Response;
import org.dromara.hutool.http.client.body.HttpBody;
import org.dromara.hutool.http.client.engine.AbstractClientEngine;
import org.dromara.hutool.http.meta.HeaderName;
@@ -65,18 +64,7 @@ public class JdkClientEngine extends AbstractClientEngine {
}
@Override
- public Response send(final Request message) {
- return send(message, true);
- }
-
- /**
- * 发送请求
- *
- * @param message 请求消息
- * @param isAsync 是否异步,异步不会立即读取响应内容
- * @return {@link Response}
- */
- public JdkHttpResponse send(final Request message, final boolean isAsync) {
+ public JdkHttpResponse send(final Request message) {
final JdkHttpConnection conn = buildConn(message);
try {
doSend(conn, message);
@@ -86,7 +74,7 @@ public class JdkClientEngine extends AbstractClientEngine {
throw new IORuntimeException(e);
}
- return sendRedirectIfPossible(conn, message, isAsync);
+ return sendRedirectIfPossible(conn, message);
}
@Override
@@ -173,11 +161,10 @@ public class JdkClientEngine extends AbstractClientEngine {
/**
* 调用转发,如果需要转发返回转发结果,否则返回{@code null}
*
- * @param conn {@link JdkHttpConnection}}
- * @param isAsync 最终请求是否异步
+ * @param conn {@link JdkHttpConnection}}
* @return {@link JdkHttpResponse},无转发返回 {@code null}
*/
- private JdkHttpResponse sendRedirectIfPossible(final JdkHttpConnection conn, final Request message, final boolean isAsync) {
+ private JdkHttpResponse sendRedirectIfPossible(final JdkHttpConnection conn, final Request message) {
// 手动实现重定向
if (message.maxRedirects() > 0) {
final int code;
@@ -203,14 +190,14 @@ public class JdkClientEngine extends AbstractClientEngine {
if (conn.redirectCount < message.maxRedirects()) {
conn.redirectCount++;
- return send(message, isAsync);
+ return send(message);
}
}
}
}
// 最终页面
- return new JdkHttpResponse(conn, this.cookieManager, true, message.charset(), isAsync, message.method().isIgnoreBody());
+ return new JdkHttpResponse(conn, this.cookieManager, message);
}
/**
diff --git a/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/jdk/JdkHttpResponse.java b/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/jdk/JdkHttpResponse.java
index 9cdd0d3d0..df341f879 100644
--- a/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/jdk/JdkHttpResponse.java
+++ b/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/jdk/JdkHttpResponse.java
@@ -21,6 +21,7 @@ import org.dromara.hutool.core.io.stream.EmptyInputStream;
import org.dromara.hutool.core.util.ObjUtil;
import org.dromara.hutool.http.HttpException;
import org.dromara.hutool.http.HttpUtil;
+import org.dromara.hutool.http.client.Request;
import org.dromara.hutool.http.client.Response;
import org.dromara.hutool.http.client.body.ResponseBody;
import org.dromara.hutool.http.meta.HeaderName;
@@ -42,6 +43,10 @@ import java.util.Map;
*/
public class JdkHttpResponse implements Response, Closeable {
+ /**
+ * 持有连接对象
+ */
+ protected JdkHttpConnection httpConnection;
/**
* 请求时的默认编码
*/
@@ -50,26 +55,14 @@ public class JdkHttpResponse implements Response, Closeable {
* Cookie管理器
*/
private final JdkCookieManager cookieManager;
- /**
- * 响应内容体,{@code null} 表示无内容
- */
- private ResponseBody body;
/**
* 响应头
*/
private Map> headers;
-
/**
- * 是否忽略响应读取时可能的EOF异常。
- * 在Http协议中,对于Transfer-Encoding: Chunked在正常情况下末尾会写入一个Length为0的的chunk标识完整结束。
- * 如果服务端未遵循这个规范或响应没有正常结束,会报EOF异常,此选项用于是否忽略这个异常。
+ * 响应内容体,{@code null} 表示无内容
*/
- private final boolean ignoreEOFError;
-
- /**
- * 持有连接对象
- */
- protected JdkHttpConnection httpConnection;
+ private ResponseBody body;
/**
* 响应状态码
*/
@@ -80,22 +73,15 @@ public class JdkHttpResponse implements Response, Closeable {
*
* @param httpConnection {@link JdkHttpConnection}
* @param cookieManager Cookie管理器
- * @param ignoreEOFError 是否忽略响应读取时可能的EOF异常
- * @param requestCharset 编码,从请求编码中获取默认编码
- * @param isAsync 是否异步
- * @param isIgnoreBody 是否忽略读取响应体
+ * @param message 请求消息
*/
protected JdkHttpResponse(final JdkHttpConnection httpConnection,
final JdkCookieManager cookieManager,
- final boolean ignoreEOFError,
- final Charset requestCharset,
- final boolean isAsync,
- final boolean isIgnoreBody) {
+ final Request message) {
this.httpConnection = httpConnection;
this.cookieManager = cookieManager;
- this.ignoreEOFError = ignoreEOFError;
- this.requestCharset = requestCharset;
- init(isAsync, isIgnoreBody);
+ this.requestCharset = message.charset();
+ init(message.method().isIgnoreBody());
}
/**
@@ -128,18 +114,13 @@ public class JdkHttpResponse implements Response, Closeable {
return ObjUtil.defaultIfNull(Response.super.charset(), requestCharset);
}
- /**
- * 同步
- * 如果为异步状态,则暂时不读取服务器中响应的内容,而是持有Http链接的{@link InputStream}。
- * 当调用此方法时,异步状态转为同步状态,此时从Http链接流中读取body内容并暂存在内容中。如果已经是同步状态,则不进行任何操作。
- *
- * @return this
- */
+ @Override
public JdkHttpResponse sync() {
if (null != this.body) {
this.body.sync();
}
- close();
+ // 关闭连接
+ this.httpConnection.closeQuietly();
return this;
}
@@ -250,9 +231,10 @@ public class JdkHttpResponse implements Response, Closeable {
* 3、持有Http流,并不关闭流
*
*
+ * @param isIgnoreBody 是否忽略消息体
* @throws HttpException IO异常
*/
- private void init(final boolean isAsync, final boolean isIgnoreBody) throws HttpException {
+ private void init(final boolean isIgnoreBody) throws HttpException {
// 获取响应状态码
try {
this.status = httpConnection.getCode();
@@ -272,13 +254,13 @@ public class JdkHttpResponse implements Response, Closeable {
}
// 存储服务端设置的Cookie信息
- if(null != this.cookieManager){
+ if (null != this.cookieManager) {
this.cookieManager.saveFromResponse(this.httpConnection, this.headers);
}
// 获取响应内容流
if (!isIgnoreBody) {
- this.body = new ResponseBody(this, new JdkHttpInputStream(this), isAsync, this.ignoreEOFError);
+ this.body = new ResponseBody(this, new JdkHttpInputStream(this));
}
}
// ---------------------------------------------------------------- Private method end
diff --git a/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/okhttp/OkHttpEngine.java b/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/okhttp/OkHttpEngine.java
index da84d98fc..3aa5dac82 100644
--- a/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/okhttp/OkHttpEngine.java
+++ b/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/okhttp/OkHttpEngine.java
@@ -71,7 +71,7 @@ public class OkHttpEngine extends AbstractClientEngine {
throw new IORuntimeException(e);
}
- return new OkHttpResponse(response, message.charset());
+ return new OkHttpResponse(response, message);
}
@Override
diff --git a/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/okhttp/OkHttpResponse.java b/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/okhttp/OkHttpResponse.java
index 1ea5ca628..feb553f58 100644
--- a/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/okhttp/OkHttpResponse.java
+++ b/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/okhttp/OkHttpResponse.java
@@ -16,19 +16,20 @@
package org.dromara.hutool.http.client.engine.okhttp;
-import kotlin.Pair;
-import okhttp3.Headers;
-import okhttp3.ResponseBody;
+import org.dromara.hutool.core.io.IoUtil;
import org.dromara.hutool.core.io.stream.EmptyInputStream;
import org.dromara.hutool.core.util.ObjUtil;
import org.dromara.hutool.http.GlobalCompressStreamRegister;
import org.dromara.hutool.http.HttpUtil;
+import org.dromara.hutool.http.client.Request;
import org.dromara.hutool.http.client.Response;
+import org.dromara.hutool.http.client.body.ResponseBody;
import org.dromara.hutool.http.meta.HeaderName;
import java.io.InputStream;
import java.nio.charset.Charset;
-import java.util.*;
+import java.util.List;
+import java.util.Map;
/**
* OkHttp3的{@link okhttp3.Response} 响应包装
@@ -42,14 +43,16 @@ public class OkHttpResponse implements Response {
* 请求时的默认编码
*/
private final Charset requestCharset;
+ private final ResponseBody body;
/**
* @param rawRes {@link okhttp3.Response}
- * @param requestCharset 请求时的默认编码
+ * @param message 请求对象
*/
- public OkHttpResponse(final okhttp3.Response rawRes, final Charset requestCharset) {
+ public OkHttpResponse(final okhttp3.Response rawRes, final Request message) {
this.rawRes = rawRes;
- this.requestCharset = requestCharset;
+ this.requestCharset = message.charset();
+ this.body = message.method().isIgnoreBody() ? null : new ResponseBody(this, bodyStream());
}
@Override
@@ -74,7 +77,7 @@ public class OkHttpResponse implements Response {
@Override
public InputStream bodyStream() {
- final ResponseBody body = rawRes.body();
+ final okhttp3.ResponseBody body = rawRes.body();
if(null == body){
return EmptyInputStream.INSTANCE;
}
@@ -84,10 +87,22 @@ public class OkHttpResponse implements Response {
}
@Override
- public void close() {
- if(null != this.rawRes){
- rawRes.close();
+ public OkHttpResponse sync() {
+ if (null != this.body) {
+ this.body.sync();
}
+ IoUtil.closeQuietly(this.rawRes);
+ return this;
+ }
+
+ @Override
+ public ResponseBody body() {
+ return this.body;
+ }
+
+ @Override
+ public void close() {
+ IoUtil.closeQuietly(this.rawRes);
}
@Override
diff --git a/hutool-http/src/test/java/org/dromara/hutool/http/client/Issue3765Test.java b/hutool-http/src/test/java/org/dromara/hutool/http/client/Issue3765Test.java
new file mode 100644
index 000000000..a8b207704
--- /dev/null
+++ b/hutool-http/src/test/java/org/dromara/hutool/http/client/Issue3765Test.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2024 Hutool Team and hutool.cn
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.dromara.hutool.http.client;
+
+import org.dromara.hutool.http.HttpUtil;
+import org.dromara.hutool.http.client.engine.ClientEngine;
+import org.dromara.hutool.http.client.engine.ClientEngineFactory;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+
+public class Issue3765Test {
+
+ public static void main(String[] args) {
+ HttpUtil.createServer(8888)
+ .setRoot("d:/test/www")
+ .start();
+ }
+ @Test
+ @Disabled
+ void downloadTest() {
+ final String url = "http://localhost:8888/a.mp3";
+ final ClientEngine engine = ClientEngineFactory.createEngine("httpclient4");
+ Request.of(url)
+ .send(engine)
+ .body().write("d:/test/");
+ }
+}