add EngineRequestBuilder

This commit is contained in:
Looly 2024-12-12 18:28:21 +08:00
parent b15d6458f3
commit fb6302f1a2
11 changed files with 413 additions and 222 deletions

View File

@ -0,0 +1,36 @@
/*
* 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.engine;
import org.dromara.hutool.http.client.Request;
/**
* 引擎的请求对象构建器<br
* 用于将{@link Request}转换为引擎对应的请求对象
*
* @param <T> 引擎请求对象类型
*/
public interface EngineRequestBuilder<T> {
/**
* 构建引擎请求对象
*
* @param message 请求对象
* @return 引擎请求对象
*/
T build(Request message);
}

View File

@ -23,15 +23,16 @@ 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;
import org.apache.http.impl.client.*;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.impl.conn.SystemDefaultRoutePlanner;
import org.apache.http.message.BasicHeader;
import org.dromara.hutool.core.io.IoUtil;
import org.dromara.hutool.core.lang.Assert;
import org.dromara.hutool.core.net.url.UrlBuilder;
import org.dromara.hutool.core.util.ObjUtil;
import org.dromara.hutool.http.GlobalHeaders;
import org.dromara.hutool.http.HttpException;
@ -39,10 +40,8 @@ import org.dromara.hutool.http.client.ApacheHttpClientConfig;
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.cookie.InMemoryCookieStore;
import org.dromara.hutool.http.client.engine.AbstractClientEngine;
import org.dromara.hutool.http.meta.HeaderName;
import org.dromara.hutool.http.proxy.ProxyInfo;
import org.dromara.hutool.http.ssl.SSLInfo;
@ -77,10 +76,9 @@ public class HttpClient4Engine extends AbstractClientEngine {
public Response send(final Request message) {
initEngine();
final HttpUriRequest request = buildRequest(message);
final HttpUriRequest request = HttpUriRequestBuilder.INSTANCE.build(message);
final CloseableHttpResponse response;
try {
//return this.engine.execute(request, response -> new HttpClient4Response(response, message));
response = this.engine.execute(request);
} catch (final IOException e) {
throw new HttpException(e);
@ -124,7 +122,7 @@ public class HttpClient4Engine extends AbstractClientEngine {
clientBuilder.setConnectionManager(buildConnectionManager(config));
// 实例级别默认请求配置
clientBuilder.setDefaultRequestConfig(buildRequestConfig(config));
clientBuilder.setDefaultRequestConfig(buildDefaultRequestConfig(config));
// 缓存
if (config.isDisableCache()) {
@ -146,40 +144,6 @@ public class HttpClient4Engine extends AbstractClientEngine {
this.engine = clientBuilder.build();
}
/**
* 构建请求体
*
* @param message {@link Request}
* @return {@link HttpUriRequest}
*/
private static HttpUriRequest buildRequest(final Request message) {
final UrlBuilder url = message.handledUrl();
Assert.notNull(url, "Request URL must be not null!");
final RequestBuilder requestBuilder = RequestBuilder
.create(message.method().name())
.setUri(url.toURI());
// 自定义单次请求配置
requestBuilder.setConfig(buildRequestConfig(message));
// 填充自定义头
message.headers().forEach((k, v1) -> v1.forEach((v2) -> requestBuilder.addHeader(k, v2)));
// 填充自定义消息体
final HttpBody body = message.handledBody();
if (null != body) {
requestBuilder.setEntity(new HttpClient4BodyEntity(
// 用户自定义的内容类型
message.header(HeaderName.CONTENT_TYPE),
message.contentEncoding(),
message.isChunked(),
body));
}
return requestBuilder.build();
}
/**
* 获取默认头列表
*
@ -229,31 +193,13 @@ public class HttpClient4Engine extends AbstractClientEngine {
return manager;
}
/**
* 构建请求配置包括重定向
*
* @param request 请求
* @return {@link RequestConfig}
*/
private static RequestConfig buildRequestConfig(final Request request) {
final RequestConfig.Builder requestConfigBuilder = RequestConfig.custom();
final int maxRedirects = request.maxRedirects();
if (maxRedirects > 0) {
requestConfigBuilder.setMaxRedirects(maxRedirects);
} else {
requestConfigBuilder.setRedirectsEnabled(false);
}
return requestConfigBuilder.build();
}
/**
* 构建请求配置包括连接请求超时和响应读取超时
*
* @param config {@link ClientConfig}
* @return {@link RequestConfig}
*/
private static RequestConfig buildRequestConfig(final ClientConfig config) {
private static RequestConfig buildDefaultRequestConfig(final ClientConfig config) {
// 请求配置
final RequestConfig.Builder requestConfigBuilder = RequestConfig.custom();

View File

@ -0,0 +1,88 @@
/*
* 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.engine.httpclient4;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.methods.RequestBuilder;
import org.dromara.hutool.core.lang.Assert;
import org.dromara.hutool.core.net.url.UrlBuilder;
import org.dromara.hutool.http.client.Request;
import org.dromara.hutool.http.client.body.HttpBody;
import org.dromara.hutool.http.client.engine.EngineRequestBuilder;
import org.dromara.hutool.http.meta.HeaderName;
/**
* HttpClient4请求构建器
*
* @author Looly
* @since 6.0.0
*/
public class HttpUriRequestBuilder implements EngineRequestBuilder<HttpUriRequest> {
/**
* 单例
*/
public static final HttpUriRequestBuilder INSTANCE = new HttpUriRequestBuilder();
@Override
public HttpUriRequest build(final Request message) {
final UrlBuilder url = message.handledUrl();
Assert.notNull(url, "Request URL must be not null!");
final RequestBuilder requestBuilder = RequestBuilder
.create(message.method().name())
.setUri(url.toURI());
// 自定义单次请求配置
requestBuilder.setConfig(buildRequestConfig(message));
// 填充自定义头
message.headers().forEach((k, v1) -> v1.forEach((v2) -> requestBuilder.addHeader(k, v2)));
// 填充自定义消息体
final HttpBody body = message.handledBody();
if (null != body) {
requestBuilder.setEntity(new HttpClient4BodyEntity(
// 用户自定义的内容类型
message.header(HeaderName.CONTENT_TYPE),
message.contentEncoding(),
message.isChunked(),
body));
}
return requestBuilder.build();
}
/**
* 构建请求配置包括重定向
*
* @param request 请求
* @return {@link RequestConfig}
*/
private static RequestConfig buildRequestConfig(final Request request) {
final RequestConfig.Builder requestConfigBuilder = RequestConfig.custom();
final int maxRedirects = request.maxRedirects();
if (maxRedirects > 0) {
requestConfigBuilder.setMaxRedirects(maxRedirects);
} else {
requestConfigBuilder.setRedirectsEnabled(false);
}
return requestConfigBuilder.build();
}
}

View File

@ -0,0 +1,104 @@
/*
* 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.engine.httpclient5;
import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase;
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.core5.http.ClassicHttpRequest;
import org.apache.hc.core5.http.Header;
import org.apache.hc.core5.http.message.BasicHeader;
import org.dromara.hutool.core.lang.Assert;
import org.dromara.hutool.core.net.url.UrlBuilder;
import org.dromara.hutool.http.client.Request;
import org.dromara.hutool.http.client.body.HttpBody;
import org.dromara.hutool.http.client.engine.EngineRequestBuilder;
import org.dromara.hutool.http.meta.HeaderName;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* HttpClient5请求构建器
*
* @author Looly
* @since 6.0.0
*/
public class ClassicHttpRequestBuilder implements EngineRequestBuilder<ClassicHttpRequest> {
/**
* 单例
*/
public static ClassicHttpRequestBuilder INSTANCE = new ClassicHttpRequestBuilder();
@Override
public ClassicHttpRequest build(final Request message) {
final UrlBuilder url = message.handledUrl();
Assert.notNull(url, "Request URL must be not null!");
final HttpUriRequestBase request = new HttpUriRequestBase(message.method().name(), url.toURI());
// 自定义单次请求配置
request.setConfig(buildRequestConfig(message));
// 填充自定义头
request.setHeaders(toHeaderList(message.headers()).toArray(new Header[0]));
// 填充自定义消息体
final HttpBody body = message.handledBody();
if (null != body) {
request.setEntity(new HttpClient5BodyEntity(
// 用户自定义的内容类型
message.header(HeaderName.CONTENT_TYPE),
message.contentEncoding(),
message.isChunked(),
body));
}
return request;
}
/**
* 获取默认头列表
*
* @return 默认头列表
*/
private static List<Header> toHeaderList(final Map<String, ? extends Collection<String>> headersMap) {
final List<Header> result = new ArrayList<>();
headersMap.forEach((k, v1) -> v1.forEach((v2) -> result.add(new BasicHeader(k, v2))));
return result;
}
/**
* 构建请求配置包括重定向配置
*
* @param request 请求
* @return {@link RequestConfig}
*/
private static RequestConfig buildRequestConfig(final Request request) {
final RequestConfig.Builder requestConfigBuilder = RequestConfig.custom();
final int maxRedirects = request.maxRedirects();
if (maxRedirects > 0) {
requestConfigBuilder.setMaxRedirects(maxRedirects);
} else {
requestConfigBuilder.setRedirectsEnabled(false);
}
return requestConfigBuilder.build();
}
}

View File

@ -18,7 +18,6 @@ package org.dromara.hutool.http.client.engine.httpclient5;
import org.apache.hc.client5.http.auth.AuthScope;
import org.apache.hc.client5.http.auth.UsernamePasswordCredentials;
import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase;
import org.apache.hc.client5.http.config.ConnectionConfig;
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider;
@ -34,7 +33,6 @@ import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.message.BasicHeader;
import org.dromara.hutool.core.io.IoUtil;
import org.dromara.hutool.core.lang.Assert;
import org.dromara.hutool.core.net.url.UrlBuilder;
import org.dromara.hutool.core.util.ObjUtil;
import org.dromara.hutool.http.GlobalHeaders;
import org.dromara.hutool.http.HttpException;
@ -42,10 +40,8 @@ import org.dromara.hutool.http.client.ApacheHttpClientConfig;
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.cookie.InMemoryCookieStore;
import org.dromara.hutool.http.client.engine.AbstractClientEngine;
import org.dromara.hutool.http.meta.HeaderName;
import org.dromara.hutool.http.proxy.ProxyInfo;
import org.dromara.hutool.http.ssl.SSLInfo;
@ -80,7 +76,7 @@ public class HttpClient5Engine extends AbstractClientEngine {
public Response send(final Request message) {
initEngine();
final ClassicHttpRequest request = buildRequest(message);
final ClassicHttpRequest request = ClassicHttpRequestBuilder.INSTANCE.build(message);
final ClassicHttpResponse response;
try {
//return this.engine.execute(request, (response -> new HttpClient5Response(response, message)));
@ -143,39 +139,6 @@ public class HttpClient5Engine extends AbstractClientEngine {
this.engine = clientBuilder.build();
}
/**
* 构建请求体
*
* @param message {@link Request}
* @return {@link ClassicHttpRequest}
*/
@SuppressWarnings("ConstantConditions")
private static ClassicHttpRequest buildRequest(final Request message) {
final UrlBuilder url = message.handledUrl();
Assert.notNull(url, "Request URL must be not null!");
final HttpUriRequestBase request = new HttpUriRequestBase(message.method().name(), url.toURI());
// 自定义单次请求配置
request.setConfig(buildRequestConfig(message));
// 填充自定义头
request.setHeaders(toHeaderList(message.headers()).toArray(new Header[0]));
// 填充自定义消息体
final HttpBody body = message.handledBody();
if (null != body) {
request.setEntity(new HttpClient5BodyEntity(
// 用户自定义的内容类型
message.header(HeaderName.CONTENT_TYPE),
message.contentEncoding(),
message.isChunked(),
body));
}
return request;
}
/**
* 获取默认头列表
*
@ -234,24 +197,6 @@ public class HttpClient5Engine extends AbstractClientEngine {
return connectionManagerBuilder.build();
}
/**
* 构建请求配置包括重定向配置
*
* @param request 请求
* @return {@link RequestConfig}
*/
private static RequestConfig buildRequestConfig(final Request request) {
final RequestConfig.Builder requestConfigBuilder = RequestConfig.custom();
final int maxRedirects = request.maxRedirects();
if (maxRedirects > 0) {
requestConfigBuilder.setMaxRedirects(maxRedirects);
} else {
requestConfigBuilder.setRedirectsEnabled(false);
}
return requestConfigBuilder.build();
}
/**
* 构建默认请求配置包括连接请求超时和响应读取超时
*

View File

@ -17,22 +17,17 @@
package org.dromara.hutool.http.client.engine.jdk;
import org.dromara.hutool.core.io.IoUtil;
import org.dromara.hutool.core.net.url.UrlUtil;
import org.dromara.hutool.core.util.ObjUtil;
import org.dromara.hutool.http.HttpException;
import org.dromara.hutool.http.client.ClientConfig;
import org.dromara.hutool.http.client.Request;
import org.dromara.hutool.http.client.RequestContext;
import org.dromara.hutool.http.client.body.HttpBody;
import org.dromara.hutool.http.client.cookie.InMemoryCookieStore;
import org.dromara.hutool.http.client.engine.AbstractClientEngine;
import org.dromara.hutool.http.meta.HeaderName;
import org.dromara.hutool.http.meta.HttpStatus;
import org.dromara.hutool.http.meta.Method;
import org.dromara.hutool.http.proxy.ProxyInfo;
import java.io.IOException;
import java.net.Proxy;
import java.net.URL;
/**
* 基于JDK的UrlConnection的Http客户端引擎实现
@ -63,6 +58,7 @@ public class JdkClientEngine extends AbstractClientEngine {
@Override
public JdkHttpResponse send(final Request message) {
initEngine();
return doSend(new RequestContext(message));
}
@ -84,12 +80,24 @@ public class JdkClientEngine extends AbstractClientEngine {
@Override
protected void initEngine() {
this.cookieManager = (null != this.config && this.config.isUseCookieManager()) ? new JdkCookieManager() : new JdkCookieManager(null);
if(null != this.cookieManager){
return;
}
if(null != this.config && this.config.isUseCookieManager()){
this.cookieStore = new InMemoryCookieStore();
this.cookieManager = new JdkCookieManager(this.cookieStore);
}
}
/**
* 发送请求
*
* @param context 请求上下文
* @return 响应对象
*/
private JdkHttpResponse doSend(final RequestContext context) {
final Request message = context.getRequest();
final JdkHttpConnection conn = buildConn(message);
final JdkHttpConnection conn = new JdkRequestBuilder(this.config, this.cookieManager).build(message);
try {
doSend(conn, message);
} catch (final IOException e) {
@ -146,52 +154,4 @@ public class JdkClientEngine extends AbstractClientEngine {
// 非Rest简单GET请求
conn.connect();
}
/**
* 构建{@link JdkHttpConnection}
*
* @param message {@link Request}消息
* @return {@link JdkHttpConnection}
*/
private JdkHttpConnection buildConn(final Request message) {
final ClientConfig config = ObjUtil.defaultIfNull(this.config, ClientConfig::of);
final URL url = message.handledUrl().toURL();
Proxy proxy = null;
final ProxyInfo proxyInfo = config.getProxy();
if (null != proxyInfo) {
proxy = proxyInfo.selectFirst(UrlUtil.toURI(url));
}
final JdkHttpConnection conn = JdkHttpConnection
.of(url, proxy)
.setConnectTimeout(config.getConnectionTimeout())
.setReadTimeout(config.getReadTimeout())
.setMethod(message.method())//
.setSSLInfo(config.getSslInfo())
// 关闭自动重定向手动处理重定向
.setInstanceFollowRedirects(false)
.setDisableCache(config.isDisableCache())
// 覆盖默认Header
.header(message.headers(), true);
if (!message.method().isIgnoreBody()) {
// 在允许发送body的情况下如果用户自定义了Content-Length则使用用户定义的值
final long contentLength = message.contentLength();
if (contentLength > 0) {
// 固定请求长度
conn.setFixedLengthStreamingMode(contentLength);
} else if (message.isChunked()) {
conn.setChunkedStreamingMode(4096);
}
}
// Cookie管理
if (null == message.header(HeaderName.COOKIE) && null != this.cookieManager) {
// 用户没有自定义Cookie则读取Cookie管理器中的信息并附带到请求中
// 不覆盖模式回填Cookie头这样用户定义的Cookie将优先
conn.header(this.cookieManager.loadForRequest(conn), false);
}
return conn;
}
}

View File

@ -19,9 +19,8 @@ package org.dromara.hutool.http.client.engine.jdk;
import org.dromara.hutool.core.io.IORuntimeException;
import org.dromara.hutool.core.map.MapUtil;
import org.dromara.hutool.core.net.url.UrlUtil;
import org.dromara.hutool.http.client.cookie.InMemoryCookieStore;
import org.dromara.hutool.http.client.cookie.CookieStoreSpi;
import java.io.Closeable;
import java.io.IOException;
import java.net.CookieManager;
import java.net.CookiePolicy;
@ -42,15 +41,17 @@ import java.util.Map;
* @author Looly
* @since 6.0.0
*/
public class JdkCookieManager implements Closeable {
public class JdkCookieManager {
private CookieManager cookieManager;
/**
* 构造
*
* @param cookieStore {@link CookieStoreSpi}
*/
public JdkCookieManager() {
this(new CookieManager(new JdkCookieStore(new InMemoryCookieStore()), CookiePolicy.ACCEPT_ALL));
public JdkCookieManager(final CookieStoreSpi cookieStore) {
this(new CookieManager(new JdkCookieStore(cookieStore), CookiePolicy.ACCEPT_ALL));
}
/**
@ -62,20 +63,6 @@ public class JdkCookieManager implements Closeable {
this.cookieManager = raw;
}
/**
* 是否启用Cookie管理
*
* @return 是否启用Cookie管理
*/
public boolean isEnable() {
return null != this.cookieManager;
}
@Override
public void close() {
this.cookieManager = null;
}
/**
* 获取{@link CookieManager}
*

View File

@ -133,7 +133,7 @@ public class JdkHttpResponse implements Response, Closeable {
* @return Cookie列表
*/
public List<HttpCookie> getCookies() {
if (this.cookieManager.isEnable()) {
if (null != this.cookieManager) {
return this.cookieManager.getCookies(this.httpConnection);
}
return HttpCookie.parse(this.header(HeaderName.SET_COOKIE));

View File

@ -0,0 +1,94 @@
/*
* 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.engine.jdk;
import org.dromara.hutool.core.net.url.UrlUtil;
import org.dromara.hutool.core.util.ObjUtil;
import org.dromara.hutool.http.client.ClientConfig;
import org.dromara.hutool.http.client.Request;
import org.dromara.hutool.http.client.engine.EngineRequestBuilder;
import org.dromara.hutool.http.meta.HeaderName;
import org.dromara.hutool.http.proxy.ProxyInfo;
import java.net.Proxy;
import java.net.URL;
/**
* JDK Http请求构建器
*
* @author Looly
* @since 6.0.0
*/
public class JdkRequestBuilder implements EngineRequestBuilder<JdkHttpConnection> {
private final ClientConfig config;
private final JdkCookieManager cookieManager;
/**
* 构造
*
* @param config 客户端配置为null则使用默认配置
* @param cookieManager Cookie管理器
*/
public JdkRequestBuilder(final ClientConfig config, final JdkCookieManager cookieManager) {
this.config = ObjUtil.defaultIfNull(config, ClientConfig::of);
this.cookieManager = cookieManager;
}
@Override
public JdkHttpConnection build(final Request message) {
final ClientConfig config = this.config;
final URL url = message.handledUrl().toURL();
Proxy proxy = null;
final ProxyInfo proxyInfo = config.getProxy();
if (null != proxyInfo) {
proxy = proxyInfo.selectFirst(UrlUtil.toURI(url));
}
final JdkHttpConnection conn = JdkHttpConnection
.of(url, proxy)
.setConnectTimeout(config.getConnectionTimeout())
.setReadTimeout(config.getReadTimeout())
.setMethod(message.method())//
.setSSLInfo(config.getSslInfo())
// 关闭自动重定向手动处理重定向
.setInstanceFollowRedirects(false)
.setDisableCache(config.isDisableCache())
// 覆盖默认Header
.header(message.headers(), true);
if (!message.method().isIgnoreBody()) {
// 在允许发送body的情况下如果用户自定义了Content-Length则使用用户定义的值
final long contentLength = message.contentLength();
if (contentLength > 0) {
// 固定请求长度
conn.setFixedLengthStreamingMode(contentLength);
} else if (message.isChunked()) {
conn.setChunkedStreamingMode(4096);
}
}
// Cookie管理
if (null == message.header(HeaderName.COOKIE) && null != this.cookieManager) {
// 用户没有自定义Cookie则读取Cookie管理器中的信息并附带到请求中
// 不覆盖模式回填Cookie头这样用户定义的Cookie将优先
conn.header(this.cookieManager.loadForRequest(conn), false);
}
return conn;
}
}

View File

@ -17,7 +17,6 @@
package org.dromara.hutool.http.client.engine.okhttp;
import okhttp3.OkHttpClient;
import okhttp3.internal.http.HttpMethod;
import org.dromara.hutool.core.lang.Assert;
import org.dromara.hutool.core.util.ObjUtil;
import org.dromara.hutool.http.HttpException;
@ -25,7 +24,6 @@ import org.dromara.hutool.http.client.ClientConfig;
import org.dromara.hutool.http.client.Request;
import org.dromara.hutool.http.client.RequestContext;
import org.dromara.hutool.http.client.Response;
import org.dromara.hutool.http.client.body.HttpBody;
import org.dromara.hutool.http.client.cookie.InMemoryCookieStore;
import org.dromara.hutool.http.client.engine.AbstractClientEngine;
import org.dromara.hutool.http.meta.HeaderName;
@ -149,9 +147,11 @@ public class OkHttpEngine extends AbstractClientEngine {
*/
private Response doSend(final RequestContext context) {
final Request message = context.getRequest();
final okhttp3.Request request = OkHttpRequestBuilder.INSTANCE.build(message);
final okhttp3.Response response;
try {
response = client.newCall(buildRequest(message)).execute();
response = client.newCall(request).execute();
} catch (final IOException e) {
throw new HttpException(e);
}
@ -178,32 +178,6 @@ public class OkHttpEngine extends AbstractClientEngine {
return new OkHttpResponse(response, message);
}
/**
* 构建请求体
*
* @param message {@link Request}
* @return {@link okhttp3.Request}
*/
private static okhttp3.Request buildRequest(final Request message) {
final okhttp3.Request.Builder builder = new okhttp3.Request.Builder()
.url(message.handledUrl().toURL());
// 填充方法
final String method = message.method().name();
final HttpBody body = message.handledBody();
if (null != body || HttpMethod.requiresRequestBody(method)) {
// okhttp中POST等请求必须提供body否则会抛异常此处传空的OkHttpRequestBody
// 为了兼容支持rest请求在此不区分是否为GET等方法一律按照body是否有值填充兼容
builder.method(method, new OkHttpRequestBody(body));
} else {
builder.method(method, null);
}
// 填充头信息
message.headers().forEach((key, values) -> values.forEach(value -> builder.addHeader(key, value)));
return builder.build();
}
/**
* 设置代理信息
*

View File

@ -0,0 +1,57 @@
/*
* 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.engine.okhttp;
import okhttp3.internal.http.HttpMethod;
import org.dromara.hutool.http.client.Request;
import org.dromara.hutool.http.client.body.HttpBody;
import org.dromara.hutool.http.client.engine.EngineRequestBuilder;
/**
* OkHttp请求构建器
*
* @author Looly
* @since 6.0.0
*/
public class OkHttpRequestBuilder implements EngineRequestBuilder<okhttp3.Request> {
/**
* 单例
*/
public static final OkHttpRequestBuilder INSTANCE = new OkHttpRequestBuilder();
@Override
public okhttp3.Request build(final Request message) {
final okhttp3.Request.Builder builder = new okhttp3.Request.Builder()
.url(message.handledUrl().toURL());
// 填充方法
final String method = message.method().name();
final HttpBody body = message.handledBody();
if (null != body || HttpMethod.requiresRequestBody(method)) {
// okhttp中POST等请求必须提供body否则会抛异常此处传空的OkHttpRequestBody
// 为了兼容支持rest请求在此不区分是否为GET等方法一律按照body是否有值填充兼容
builder.method(method, new OkHttpRequestBody(body));
} else {
builder.method(method, null);
}
// 填充头信息
message.headers().forEach((key, values) -> values.forEach(value -> builder.addHeader(key, value)));
return builder.build();
}
}