Skip to content

Commit 59653d8

Browse files
committed
refactor: streamline OkHttpClient creation and SSL configuration handling
1 parent f8a98c5 commit 59653d8

5 files changed

Lines changed: 111 additions & 43 deletions

File tree

easy-postman-app/src/main/java/com/laker/postman/service/http/HttpService.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,17 @@ private static Request buildRequestByType(PreparedRequest req) {
119119
*/
120120
private static OkHttpClient buildCustomClient(PreparedRequest req) {
121121
String baseUri = extractBaseUri(req.url);
122-
OkHttpClient baseClient = OkHttpClientManager.getClient(baseUri, req.followRedirects);
123-
return buildDynamicClient(baseClient, req, req.requestTimeoutMs, shouldIsolateConnectionPool(req));
122+
boolean isolateSslConfiguration = shouldIsolateConnectionPool(req);
123+
OkHttpClient baseClient = isolateSslConfiguration
124+
// When request-level SSL mode differs from the cached global client,
125+
// rebuild the base client in the target mode instead of inheriting SSL state.
126+
? OkHttpClientManager.createClientForSslMode(
127+
baseUri,
128+
req.followRedirects,
129+
resolveSslVerificationMode(req)
130+
)
131+
: OkHttpClientManager.getClient(baseUri, req.followRedirects);
132+
return buildDynamicClient(baseClient, req, req.requestTimeoutMs, false);
124133
}
125134

126135
private static void applyRequestSettings(OkHttpClient.Builder builder,

easy-postman-app/src/main/java/com/laker/postman/service/http/okhttp/OkHttpClientManager.java

Lines changed: 41 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -145,41 +145,20 @@ public static OkHttpClient getClient(String baseUri, boolean followRedirects) {
145145
String proxyKey = getProxyConfigKey(baseUri);
146146
String key = baseUri + "|" + followRedirects + "|" + proxyKey;
147147

148-
return clientMap.computeIfAbsent(key, k -> {
149-
// 配置 Dispatcher 并发参数
150-
Dispatcher dispatcher = new Dispatcher();
151-
dispatcher.setMaxRequests(maxRequests);
152-
dispatcher.setMaxRequestsPerHost(maxRequestsPerHost);
153-
154-
OkHttpClient.Builder builder = new OkHttpClient.Builder()
155-
// 连接超时
156-
.connectTimeout(0, TimeUnit.MILLISECONDS)
157-
// 读超时
158-
.readTimeout(0, TimeUnit.MILLISECONDS)
159-
// 写超时
160-
.writeTimeout(0, TimeUnit.MILLISECONDS)
161-
// 配置 Dispatcher
162-
.dispatcher(dispatcher)
163-
// 连接池配置
164-
.connectionPool(new ConnectionPool(maxIdleConnections, keepAliveDuration, TimeUnit.SECONDS))
165-
// 失败自动重试
166-
.retryOnConnectionFailure(true)
167-
// 是否自动跟随重定向
168-
.followRedirects(followRedirects)
169-
.cache(null)
170-
.pingInterval(30, TimeUnit.SECONDS);
171-
172-
// 使用全局 JavaNetCookieJar
173-
builder.cookieJar(GLOBAL_COOKIE_JAR);
174-
175-
// 配置网络代理
176-
configureProxy(builder, baseUri);
177-
178-
// 配置SSL设置
179-
configureSSLSettings(builder, baseUri);
180-
181-
return builder.build();
182-
});
148+
return clientMap.computeIfAbsent(key, k -> createClient(
149+
baseUri,
150+
followRedirects,
151+
resolveSslVerificationMode(baseUri)
152+
));
153+
}
154+
155+
/**
156+
* 创建一个不参与缓存的客户端,用于请求级 SSL 模式覆盖。
157+
*/
158+
public static OkHttpClient createClientForSslMode(String baseUri,
159+
boolean followRedirects,
160+
SSLConfigurationUtil.SSLVerificationMode sslMode) {
161+
return createClient(baseUri, followRedirects, sslMode);
183162
}
184163

185164
/**
@@ -270,13 +249,38 @@ private static void configureProxyAuthenticator(OkHttpClient.Builder builder) {
270249
/**
271250
* 配置SSL设置(统一处理所有HTTPS连接的SSL配置)
272251
*/
273-
private static void configureSSLSettings(OkHttpClient.Builder builder, String baseUri) {
252+
private static OkHttpClient createClient(String baseUri,
253+
boolean followRedirects,
254+
SSLConfigurationUtil.SSLVerificationMode sslMode) {
255+
Dispatcher dispatcher = new Dispatcher();
256+
dispatcher.setMaxRequests(maxRequests);
257+
dispatcher.setMaxRequestsPerHost(maxRequestsPerHost);
258+
259+
OkHttpClient.Builder builder = new OkHttpClient.Builder()
260+
.connectTimeout(0, TimeUnit.MILLISECONDS)
261+
.readTimeout(0, TimeUnit.MILLISECONDS)
262+
.writeTimeout(0, TimeUnit.MILLISECONDS)
263+
.dispatcher(dispatcher)
264+
.connectionPool(new ConnectionPool(maxIdleConnections, keepAliveDuration, TimeUnit.SECONDS))
265+
.retryOnConnectionFailure(true)
266+
.followRedirects(followRedirects)
267+
.cache(null)
268+
.pingInterval(30, TimeUnit.SECONDS);
269+
270+
builder.cookieJar(GLOBAL_COOKIE_JAR);
271+
configureProxy(builder, baseUri);
272+
configureSSLSettings(builder, baseUri, sslMode);
273+
return builder.build();
274+
}
275+
276+
private static void configureSSLSettings(OkHttpClient.Builder builder,
277+
String baseUri,
278+
SSLConfigurationUtil.SSLVerificationMode mode) {
274279
URI uri = tryParseUri(baseUri, "SSL configuration");
275280
if (uri == null || !isSecureScheme(uri.getScheme())) {
276281
return;
277282
}
278283

279-
SSLConfigurationUtil.SSLVerificationMode mode = resolveSslVerificationMode(baseUri);
280284
if (mode == SSLConfigurationUtil.SSLVerificationMode.LENIENT) {
281285
log.warn("SSL verification disabled by user settings");
282286
}

easy-postman-app/src/main/java/com/laker/postman/service/http/ssl/SSLConfigurationUtil.java

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
import okhttp3.OkHttpClient;
1212

1313
import javax.net.ssl.*;
14-
import javax.net.ssl.HttpsURLConnection;
1514
import java.security.KeyStore;
1615
import java.security.cert.CertificateException;
1716
import java.security.cert.X509Certificate;
@@ -96,14 +95,14 @@ public static void configureSSL(OkHttpClient.Builder builder, SSLVerificationMod
9695
public static void configureSSL(OkHttpClient.Builder builder, SSLVerificationMode mode,
9796
String host, int port) {
9897
try {
99-
builder.hostnameVerifier(createHostnameVerifier(mode));
100-
10198
// 查找并加载匹配的客户端证书
10299
KeyManager[] keyManagers = loadClientCertificate(host, port);
103100

104101
// 配置 TrustManager
105102
X509TrustManager trustManager = configureTrustManager(mode, keyManagers);
106103

104+
applyHostnameVerifier(builder, mode);
105+
107106
// 严格模式且没有客户端证书:使用默认配置
108107
if (trustManager == null) {
109108
return;
@@ -318,7 +317,14 @@ private static HostnameVerifier createHostnameVerifier(SSLVerificationMode mode)
318317
} else if (mode == SSLVerificationMode.LENIENT) {
319318
return new LenientHostnameVerifier();
320319
}
321-
return HttpsURLConnection.getDefaultHostnameVerifier();
320+
return new OkHttpClient().hostnameVerifier();
321+
}
322+
323+
private static void applyHostnameVerifier(OkHttpClient.Builder builder, SSLVerificationMode mode) {
324+
if (builder == null) {
325+
return;
326+
}
327+
builder.hostnameVerifier(createHostnameVerifier(mode));
322328
}
323329

324330
/**

easy-postman-app/src/test/java/com/laker/postman/service/http/HttpServiceTest.java

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import java.util.Properties;
1616

1717
import static org.testng.Assert.assertSame;
18+
import static org.testng.Assert.assertEquals;
1819
import static org.testng.Assert.assertFalse;
1920
import static org.testng.Assert.assertTrue;
2021

@@ -140,6 +141,51 @@ public void connectFailed(URI uri, java.net.SocketAddress sa, java.io.IOExceptio
140141
}
141142
}
142143

144+
@Test
145+
public void strictRequestShouldNotReuseLenientSslComponents() throws Exception {
146+
Properties props = getSettingsProperties();
147+
Properties backup = new Properties();
148+
backup.putAll(props);
149+
150+
try {
151+
props.clear();
152+
props.setProperty("proxy_enabled", "false");
153+
props.setProperty("ssl_verification_enabled", "false");
154+
props.setProperty("proxy_ssl_verification_disabled", "false");
155+
OkHttpClientManager.clearClientCache();
156+
157+
PreparedRequest request = new PreparedRequest();
158+
request.url = "https://api.example.com/data";
159+
request.followRedirects = true;
160+
request.sslVerificationEnabled = true;
161+
162+
OkHttpClient lenientBaseClient = OkHttpClientManager.getClient("https://api.example.com", true);
163+
OkHttpClient strictClient = invokeBuildCustomClient(request);
164+
OkHttpClient strictDefaultClient = new OkHttpClient();
165+
166+
assertEquals(
167+
strictClient.hostnameVerifier().getClass().getName(),
168+
strictDefaultClient.hostnameVerifier().getClass().getName()
169+
);
170+
assertEquals(
171+
strictClient.sslSocketFactory().getClass().getName(),
172+
strictDefaultClient.sslSocketFactory().getClass().getName()
173+
);
174+
assertFalse(
175+
strictClient.hostnameVerifier().getClass().getName()
176+
.equals(lenientBaseClient.hostnameVerifier().getClass().getName())
177+
);
178+
assertFalse(
179+
strictClient.sslSocketFactory().getClass().getName()
180+
.equals(lenientBaseClient.sslSocketFactory().getClass().getName())
181+
);
182+
} finally {
183+
props.clear();
184+
props.putAll(backup);
185+
OkHttpClientManager.clearClientCache();
186+
}
187+
}
188+
143189
private static Properties getSettingsProperties() throws Exception {
144190
Field propsField = SettingManager.class.getDeclaredField("props");
145191
propsField.setAccessible(true);

easy-postman-app/src/test/java/com/laker/postman/service/http/ssl/SSLConfigurationUtilTest.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import java.security.cert.X509Certificate;
1414
import java.util.Arrays;
1515

16+
import static org.testng.Assert.assertEquals;
1617
import static org.testng.Assert.assertNotNull;
1718
import static org.testng.Assert.assertNotSame;
1819
import static org.testng.Assert.assertTrue;
@@ -52,11 +53,13 @@ public void shouldRestoreDefaultHostnameVerifierInStrictMode() {
5253
HostnameVerifier lenientVerifier = (hostname, session) -> true;
5354
OkHttpClient.Builder builder = new OkHttpClient.Builder()
5455
.hostnameVerifier(lenientVerifier);
56+
String expectedVerifierClass = new OkHttpClient().hostnameVerifier().getClass().getName();
5557

5658
SSLConfigurationUtil.configureSSL(builder, SSLConfigurationUtil.SSLVerificationMode.STRICT, null, 0);
5759

5860
OkHttpClient client = builder.build();
5961
assertNotSame(client.hostnameVerifier(), lenientVerifier);
62+
assertEquals(client.hostnameVerifier().getClass().getName(), expectedVerifierClass);
6063
}
6164

6265
private static X509TrustManager getDefaultTrustManager() throws Exception {

0 commit comments

Comments
 (0)