Skip to content

Commit a3526fe

Browse files
authored
Merge 82ad7db into b7ffa74
2 parents b7ffa74 + 82ad7db commit a3526fe

File tree

2 files changed

+134
-107
lines changed

2 files changed

+134
-107
lines changed

dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/utils/HttpUtils.java

Lines changed: 73 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
* See the License for the specific language governing permissions and
1515
* limitations under the License.
1616
*/
17-
1817
package org.apache.dolphinscheduler.common.utils;
1918

2019
import org.apache.dolphinscheduler.common.constants.Constants;
@@ -25,11 +24,10 @@
2524
import org.apache.http.client.config.RequestConfig;
2625
import org.apache.http.client.methods.CloseableHttpResponse;
2726
import org.apache.http.client.methods.HttpGet;
28-
import org.apache.http.config.Registry;
2927
import org.apache.http.config.RegistryBuilder;
3028
import org.apache.http.conn.socket.ConnectionSocketFactory;
3129
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
32-
import org.apache.http.conn.ssl.NoopHostnameVerifier;
30+
import org.apache.http.conn.ssl.DefaultHostnameVerifier;
3331
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
3432
import org.apache.http.impl.client.CloseableHttpClient;
3533
import org.apache.http.impl.client.HttpClientBuilder;
@@ -38,28 +36,63 @@
3836
import org.apache.http.util.EntityUtils;
3937

4038
import java.io.IOException;
41-
import java.security.KeyManagementException;
4239
import java.security.NoSuchAlgorithmException;
43-
import java.security.cert.X509Certificate;
4440
import java.util.Arrays;
45-
import java.util.Objects;
4641

4742
import javax.net.ssl.SSLContext;
48-
import javax.net.ssl.TrustManager;
49-
import javax.net.ssl.X509TrustManager;
5043

5144
import lombok.extern.slf4j.Slf4j;
5245

5346
/**
54-
* http utils
47+
* HTTP utilities class with secure SSL context.
5548
*/
5649
@Slf4j
5750
public class HttpUtils {
5851

52+
private static final PoolingHttpClientConnectionManager cm;
53+
private static final SSLContext ctx;
54+
private static final SSLConnectionSocketFactory socketFactory;
55+
private static final RequestConfig requestConfig;
56+
57+
static {
58+
try {
59+
// Use default SSL context which includes standard certificate validation
60+
ctx = SSLContext.getDefault();
61+
} catch (NoSuchAlgorithmException e) {
62+
log.error("Failed to get default SSLContext", e);
63+
throw new RuntimeException("Failed to get default SSLContext", e);
64+
}
65+
66+
socketFactory = new SSLConnectionSocketFactory(ctx, new DefaultHostnameVerifier());
67+
68+
// Set timeout, request time, socket timeout
69+
requestConfig = RequestConfig.custom()
70+
.setCookieSpec(CookieSpecs.IGNORE_COOKIES)
71+
.setExpectContinueEnabled(Boolean.TRUE)
72+
.setTargetPreferredAuthSchemes(Arrays.asList(AuthSchemes.NTLM, AuthSchemes.DIGEST, AuthSchemes.SPNEGO))
73+
.setProxyPreferredAuthSchemes(Arrays.asList(AuthSchemes.BASIC, AuthSchemes.SPNEGO))
74+
.setConnectTimeout(Constants.HTTP_CONNECT_TIMEOUT)
75+
.setSocketTimeout(Constants.SOCKET_TIMEOUT)
76+
.setConnectionRequestTimeout(Constants.HTTP_CONNECTION_REQUEST_TIMEOUT)
77+
.setRedirectsEnabled(true)
78+
.build();
79+
80+
cm = new PoolingHttpClientConnectionManager(
81+
RegistryBuilder.<ConnectionSocketFactory>create()
82+
.register("http", PlainConnectionSocketFactory.INSTANCE)
83+
.register("https", socketFactory)
84+
.build());
85+
86+
cm.setDefaultMaxPerRoute(60);
87+
cm.setMaxTotal(100);
88+
}
89+
90+
// Private constructor to prevent instantiation
5991
private HttpUtils() {
60-
throw new UnsupportedOperationException("Construct HttpUtils");
92+
throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
6193
}
6294

95+
// Returns a singleton instance of the HTTP client
6396
public static CloseableHttpClient getInstance() {
6497
return HttpClientInstance.httpClient;
6598
}
@@ -69,120 +102,53 @@ private static class HttpClientInstance {
69102
private static final CloseableHttpClient httpClient = getHttpClientBuilder().build();
70103
}
71104

105+
// Builds and returns an HttpClient with the custom configuration
72106
public static HttpClientBuilder getHttpClientBuilder() {
73-
return HttpClients.custom().setConnectionManager(cm).setDefaultRequestConfig(requestConfig);
74-
}
75-
76-
private static PoolingHttpClientConnectionManager cm;
77-
78-
private static SSLContext ctx = null;
79-
80-
private static SSLConnectionSocketFactory socketFactory;
81-
82-
private static RequestConfig requestConfig;
83-
84-
private static Registry<ConnectionSocketFactory> socketFactoryRegistry;
85-
86-
private static X509TrustManager xtm = new X509TrustManager() {
87-
88-
@Override
89-
public void checkClientTrusted(X509Certificate[] chain, String authType) {
90-
}
91-
92-
@Override
93-
public void checkServerTrusted(X509Certificate[] chain, String authType) {
94-
}
95-
96-
@Override
97-
public X509Certificate[] getAcceptedIssuers() {
98-
return null;
99-
}
100-
};
101-
102-
static {
103-
try {
104-
ctx = SSLContext.getInstance(SSLConnectionSocketFactory.TLS);
105-
ctx.init(null, new TrustManager[]{xtm}, null);
106-
} catch (NoSuchAlgorithmException e) {
107-
log.error("SSLContext init with NoSuchAlgorithmException", e);
108-
} catch (KeyManagementException e) {
109-
log.error("SSLContext init with KeyManagementException", e);
110-
}
111-
socketFactory = new SSLConnectionSocketFactory(ctx, NoopHostnameVerifier.INSTANCE);
112-
/** set timeout、request time、socket timeout */
113-
requestConfig = RequestConfig.custom().setCookieSpec(CookieSpecs.IGNORE_COOKIES)
114-
.setExpectContinueEnabled(Boolean.TRUE)
115-
.setTargetPreferredAuthSchemes(Arrays.asList(AuthSchemes.NTLM, AuthSchemes.DIGEST, AuthSchemes.SPNEGO))
116-
.setProxyPreferredAuthSchemes(Arrays.asList(AuthSchemes.BASIC, AuthSchemes.SPNEGO))
117-
.setConnectTimeout(Constants.HTTP_CONNECT_TIMEOUT).setSocketTimeout(Constants.SOCKET_TIMEOUT)
118-
.setConnectionRequestTimeout(Constants.HTTP_CONNECTION_REQUEST_TIMEOUT).setRedirectsEnabled(true)
119-
.build();
120-
socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
121-
.register("http", PlainConnectionSocketFactory.INSTANCE).register("https", socketFactory).build();
122-
cm = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
123-
cm.setDefaultMaxPerRoute(60);
124-
cm.setMaxTotal(100);
125-
107+
return HttpClients.custom()
108+
.setConnectionManager(cm)
109+
.setDefaultRequestConfig(requestConfig);
126110
}
127111

128112
/**
129-
* get http request content
113+
* Executes a GET request and returns the response content as a string.
130114
*
131-
* @param url url
132-
* @return http get request response content
115+
* @param url The URL to send the GET request to
116+
* @return The response content as a string
133117
*/
134118
public static String get(String url) {
135-
CloseableHttpClient httpclient = HttpUtils.getInstance();
136-
137-
HttpGet httpget = new HttpGet(url);
138-
return getResponseContentString(httpget, httpclient);
119+
CloseableHttpClient httpClient = getInstance();
120+
HttpGet httpGet = new HttpGet(url);
121+
return getResponseContentString(httpGet, httpClient);
139122
}
140123

141124
/**
142-
* get http response content
125+
* Gets the response content from an executed HttpGet request.
143126
*
144-
* @param httpget httpget
145-
* @param httpClient httpClient
146-
* @return http get request response content
127+
* @param httpGet The HttpGet request to execute
128+
* @param httpClient The HttpClient to use for the request
129+
* @return The response content as a string
147130
*/
148-
public static String getResponseContentString(HttpGet httpget, CloseableHttpClient httpClient) {
149-
if (Objects.isNull(httpget) || Objects.isNull(httpClient)) {
131+
public static String getResponseContentString(HttpGet httpGet, CloseableHttpClient httpClient) {
132+
if (httpGet == null || httpClient == null) {
150133
log.error("HttpGet or HttpClient parameter is null");
151134
return null;
152135
}
153-
String responseContent = null;
154-
CloseableHttpResponse response = null;
155-
try {
156-
response = httpClient.execute(httpget);
157-
// check response status is 200
158-
if (response.getStatusLine().getStatusCode() == 200) {
159-
HttpEntity entity = response.getEntity();
160-
if (entity != null) {
161-
responseContent = EntityUtils.toString(entity, Constants.UTF_8);
162-
} else {
163-
log.warn("http entity is null");
164-
}
165-
} else {
166-
log.error("http get:{} response status code is not 200!", response.getStatusLine().getStatusCode());
167-
}
168-
} catch (IOException ioe) {
169-
log.error(ioe.getMessage(), ioe);
170-
} finally {
171-
try {
172-
if (response != null) {
173-
EntityUtils.consume(response.getEntity());
174-
response.close();
175-
}
176-
} catch (IOException e) {
177-
log.error(e.getMessage(), e);
178-
}
179-
if (!httpget.isAborted()) {
180-
httpget.releaseConnection();
181-
httpget.abort();
136+
137+
try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
138+
// Check if the response status is 200 (OK)
139+
if (response.getStatusLine().getStatusCode() != 200) {
140+
log.error("HTTP GET request to {} returned status code: {}", httpGet.getURI(),
141+
response.getStatusLine().getStatusCode());
142+
return null;
182143
}
183144

145+
HttpEntity entity = response.getEntity();
146+
return entity != null ? EntityUtils.toString(entity, Constants.UTF_8) : null;
147+
} catch (IOException e) {
148+
log.error("Error executing HTTP GET request", e);
149+
return null;
150+
} finally {
151+
httpGet.releaseConnection();
184152
}
185-
return responseContent;
186153
}
187-
188154
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.dolphinscheduler.common.utils;
18+
19+
import static org.junit.jupiter.api.Assertions.assertNotNull;
20+
import static org.junit.jupiter.api.Assertions.assertNull;
21+
22+
import org.junit.jupiter.api.Test;
23+
24+
public class HttpUtilsTest {
25+
26+
@Test
27+
void testGetRequest() {
28+
// test HTTP URL
29+
String response1 = HttpUtils.get("http://www.bing.com/");
30+
assertNotNull(response1, "Response should not be null for a http URL");
31+
}
32+
33+
/**
34+
* test invalid certification HTTPS URL
35+
*/
36+
@Test
37+
void testGetInvalidRequest() {
38+
// test invalid certification HTTPS URL
39+
String response2 = HttpUtils.get("https://poc.bzzt.net");
40+
assertNull(response2,
41+
"Response should be null for an invalid certification https URL and throw exception in console");
42+
}
43+
44+
/**
45+
* test valid certification HTTPS URL
46+
*/
47+
@Test
48+
void testGetValidRequest() {
49+
String response3 = HttpUtils.get("https://www.google.com/");
50+
assertNotNull(response3, "Response should not be null for a valid certification https URL");
51+
}
52+
53+
/**
54+
* test wrong URL
55+
*/
56+
@Test
57+
void testGetWrongRequest() {
58+
String response4 = HttpUtils.get("/abc/22");
59+
assertNull(response4, "Response should be null for a wrong url");
60+
}
61+
}

0 commit comments

Comments
 (0)