mirror of
https://gitee.com/dromara/hutool.git
synced 2025-04-05 17:37:59 +08:00
fix http
This commit is contained in:
parent
1c13d73010
commit
63a8c5766d
@ -9,6 +9,8 @@
|
||||
* 【core 】 XmlUtil支持可选是否输出omit xml declaration(pr#732@Github)
|
||||
* 【core 】 车牌号校验兼容新能源车牌(pr#92@Gitee)
|
||||
* 【core 】 在NetUtil中新增ping功能(pr#91@Gitee)
|
||||
* 【core 】 DateUtil.offset不支持ERA,增加异常提示(issue#I18KD5@Gitee)
|
||||
* 【http 】 改进HttpUtil访问HTTPS接口性能问题,SSL证书使用单例(issue#I18AL1@Gitee)
|
||||
|
||||
### Bug修复
|
||||
* 【core 】 修复isExpired的bug(issue#733@Gtihub)
|
||||
|
@ -268,6 +268,10 @@ public class DateTime extends Date {
|
||||
* @return 如果此对象为可变对象,返回自身,否则返回新对象
|
||||
*/
|
||||
public DateTime offset(DateField datePart, int offset) {
|
||||
if(DateField.ERA == datePart){
|
||||
throw new IllegalArgumentException("ERA is not support offset!");
|
||||
}
|
||||
|
||||
final Calendar cal = toCalendar();
|
||||
//noinspection MagicConstant
|
||||
cal.add(datePart.getValue(), offset);
|
||||
|
@ -645,6 +645,7 @@ public class DateUtilTest {
|
||||
DateTime startDate = DateUtil.parse("2019-12-01 17:02:30");
|
||||
DateTime endDate = DateUtil.parse("2019-12-02 17:02:30");
|
||||
int length = 3;
|
||||
//noinspection deprecation
|
||||
boolean expired = DateUtil.isExpired(startDate, DateField.DAY_OF_YEAR, length, endDate);
|
||||
Assert.assertTrue(expired);
|
||||
}
|
||||
|
@ -1,5 +1,16 @@
|
||||
package cn.hutool.http;
|
||||
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.core.util.URLUtil;
|
||||
import cn.hutool.http.ssl.AndroidSupportSSLFactory;
|
||||
import cn.hutool.http.ssl.DefaultSSLInfo;
|
||||
import cn.hutool.http.ssl.SSLSocketFactoryBuilder;
|
||||
|
||||
import javax.net.ssl.HostnameVerifier;
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
@ -16,17 +27,6 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import javax.net.ssl.HostnameVerifier;
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.core.util.URLUtil;
|
||||
import cn.hutool.http.ssl.AndroidSupportSSLFactory;
|
||||
import cn.hutool.http.ssl.SSLSocketFactoryBuilder;
|
||||
import cn.hutool.http.ssl.TrustAnyHostnameVerifier;
|
||||
|
||||
/**
|
||||
* http连接对象,对HttpURLConnection的包装
|
||||
*
|
||||
@ -262,20 +262,8 @@ public class HttpConnection {
|
||||
// Https请求
|
||||
final HttpsURLConnection httpsConn = (HttpsURLConnection) conn;
|
||||
// 验证域
|
||||
httpsConn.setHostnameVerifier(null != hostnameVerifier ? hostnameVerifier : new TrustAnyHostnameVerifier());
|
||||
if (null == ssf) {
|
||||
try {
|
||||
if (StrUtil.equalsIgnoreCase("dalvik", System.getProperty("java.vm.name"))) {
|
||||
// 兼容android低版本SSL连接
|
||||
ssf = new AndroidSupportSSLFactory();
|
||||
} else {
|
||||
ssf = SSLSocketFactoryBuilder.create().build();
|
||||
}
|
||||
} catch (KeyManagementException | NoSuchAlgorithmException e) {
|
||||
throw new HttpException(e);
|
||||
}
|
||||
}
|
||||
httpsConn.setSSLSocketFactory(ssf);
|
||||
httpsConn.setHostnameVerifier(ObjectUtil.defaultIfNull(hostnameVerifier, DefaultSSLInfo.TRUST_ANY_HOSTNAME_VERIFIER));
|
||||
httpsConn.setSSLSocketFactory(ObjectUtil.defaultIfNull(ssf, DefaultSSLInfo.DEFAULT_SSF));
|
||||
}
|
||||
|
||||
return this;
|
||||
|
@ -857,12 +857,11 @@ public class HttpRequest extends HttpBase<HttpRequest> {
|
||||
* @see #setSSLSocketFactory(SSLSocketFactory)
|
||||
*/
|
||||
public HttpRequest setSSLProtocol(String protocol) {
|
||||
if (null == this.ssf) {
|
||||
try {
|
||||
this.ssf = SSLSocketFactoryBuilder.create().setProtocol(protocol).build();
|
||||
} catch (Exception e) {
|
||||
throw new HttpException(e);
|
||||
}
|
||||
Assert.notBlank(protocol, "protocol must be not blank!");
|
||||
try {
|
||||
this.ssf = SSLSocketFactoryBuilder.create().setProtocol(protocol).build();
|
||||
} catch (Exception e) {
|
||||
throw new HttpException(e);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
@ -930,13 +929,13 @@ public class HttpRequest extends HttpBase<HttpRequest> {
|
||||
this.url = HttpUtil.encodeParams(this.url, this.charset);
|
||||
}
|
||||
// 初始化 connection
|
||||
initConnecton();
|
||||
initConnection();
|
||||
|
||||
// 发送请求
|
||||
send();
|
||||
|
||||
// 手动实现重定向
|
||||
HttpResponse httpResponse = sendRedirectIfPosible();
|
||||
HttpResponse httpResponse = sendRedirectIfPossible();
|
||||
|
||||
// 获取响应
|
||||
if (null == httpResponse) {
|
||||
@ -966,7 +965,7 @@ public class HttpRequest extends HttpBase<HttpRequest> {
|
||||
/**
|
||||
* 初始化网络连接
|
||||
*/
|
||||
private void initConnecton() {
|
||||
private void initConnection() {
|
||||
if (null != this.httpConnection) {
|
||||
// 执行下次请求时自动关闭上次请求(常用于转发)
|
||||
this.httpConnection.disconnectQuietly();
|
||||
@ -1018,7 +1017,7 @@ public class HttpRequest extends HttpBase<HttpRequest> {
|
||||
*
|
||||
* @return {@link HttpResponse},无转发返回 <code>null</code>
|
||||
*/
|
||||
private HttpResponse sendRedirectIfPosible() {
|
||||
private HttpResponse sendRedirectIfPossible() {
|
||||
if (this.maxRedirectCount < 1) {
|
||||
// 不重定向
|
||||
return null;
|
||||
|
@ -1,5 +1,7 @@
|
||||
package cn.hutool.http.ssl;
|
||||
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Socket;
|
||||
@ -13,7 +15,6 @@ import javax.net.ssl.SSLSocketFactory;
|
||||
* 自定义支持协议类型的SSLSocketFactory
|
||||
*
|
||||
* @author looly
|
||||
*
|
||||
*/
|
||||
public class CustomProtocolsSSLFactory extends SSLSocketFactory {
|
||||
|
||||
@ -45,45 +46,42 @@ public class CustomProtocolsSSLFactory extends SSLSocketFactory {
|
||||
|
||||
@Override
|
||||
public Socket createSocket() throws IOException {
|
||||
SSLSocket sslSocket = (SSLSocket) base.createSocket();
|
||||
final SSLSocket sslSocket = (SSLSocket) base.createSocket();
|
||||
resetProtocols(sslSocket);
|
||||
return sslSocket;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SSLSocket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
|
||||
SSLSocket socket = (SSLSocket) base.createSocket(s, host, port, autoClose);
|
||||
final SSLSocket socket = (SSLSocket) base.createSocket(s, host, port, autoClose);
|
||||
resetProtocols(socket);
|
||||
return socket;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(String host, int port) throws IOException {
|
||||
SSLSocket socket = (SSLSocket) base.createSocket(host, port);
|
||||
final SSLSocket socket = (SSLSocket) base.createSocket(host, port);
|
||||
resetProtocols(socket);
|
||||
return socket;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException {
|
||||
|
||||
SSLSocket socket = (SSLSocket) base.createSocket(host, port, localHost, localPort);
|
||||
final SSLSocket socket = (SSLSocket) base.createSocket(host, port, localHost, localPort);
|
||||
resetProtocols(socket);
|
||||
return socket;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(InetAddress host, int port) throws IOException {
|
||||
|
||||
SSLSocket socket = (SSLSocket) base.createSocket(host, port);
|
||||
final SSLSocket socket = (SSLSocket) base.createSocket(host, port);
|
||||
resetProtocols(socket);
|
||||
return socket;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
|
||||
|
||||
SSLSocket socket = (SSLSocket) base.createSocket(address, port, localAddress, localPort);
|
||||
final SSLSocket socket = (SSLSocket) base.createSocket(address, port, localAddress, localPort);
|
||||
resetProtocols(socket);
|
||||
return socket;
|
||||
}
|
||||
@ -94,7 +92,9 @@ public class CustomProtocolsSSLFactory extends SSLSocketFactory {
|
||||
* @param socket SSLSocket
|
||||
*/
|
||||
private void resetProtocols(SSLSocket socket) {
|
||||
socket.setEnabledProtocols(protocols);
|
||||
if(ArrayUtil.isNotEmpty(this.protocols)){
|
||||
socket.setEnabledProtocols(this.protocols);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package cn.hutool.http.ssl;
|
||||
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
/**
|
||||
* 默认的SSLSocketFactory
|
||||
*
|
||||
* @author Looly
|
||||
* @since 5.1.2
|
||||
*/
|
||||
public class DefaultSSLFactory extends CustomProtocolsSSLFactory {
|
||||
|
||||
public DefaultSSLFactory() throws KeyManagementException, NoSuchAlgorithmException {
|
||||
super();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package cn.hutool.http.ssl;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.http.HttpException;
|
||||
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
/**
|
||||
* 默认的SSL配置,当用户未设置相关信息时,使用默认设置,默认设置为单例模式。
|
||||
*
|
||||
* @author looly
|
||||
* @since 5.1.2
|
||||
*/
|
||||
public class DefaultSSLInfo {
|
||||
/**
|
||||
* 默认信任全部的域名校验器
|
||||
*/
|
||||
public static final TrustAnyHostnameVerifier TRUST_ANY_HOSTNAME_VERIFIER;
|
||||
/**
|
||||
* 默认的SSLSocketFactory,区分安卓
|
||||
*/
|
||||
public static final SSLSocketFactory DEFAULT_SSF;
|
||||
|
||||
static {
|
||||
TRUST_ANY_HOSTNAME_VERIFIER = new TrustAnyHostnameVerifier();
|
||||
|
||||
try {
|
||||
if (StrUtil.equalsIgnoreCase("dalvik", System.getProperty("java.vm.name"))) {
|
||||
// 兼容android低版本SSL连接
|
||||
DEFAULT_SSF = new AndroidSupportSSLFactory();
|
||||
} else {
|
||||
DEFAULT_SSF = new DefaultSSLFactory();
|
||||
}
|
||||
} catch (KeyManagementException | NoSuchAlgorithmException e) {
|
||||
throw new HttpException(e);
|
||||
}
|
||||
}
|
||||
}
|
@ -7,8 +7,8 @@ import javax.net.ssl.X509TrustManager;
|
||||
|
||||
/**
|
||||
* 证书管理
|
||||
* @author Looly
|
||||
*
|
||||
* @author Looly
|
||||
*/
|
||||
public class DefaultTrustManager implements X509TrustManager {
|
||||
|
||||
@ -18,10 +18,10 @@ public class DefaultTrustManager implements X509TrustManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
|
||||
public void checkClientTrusted(X509Certificate[] chain, String authType) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
|
||||
public void checkServerTrusted(X509Certificate[] chain, String authType) {
|
||||
}
|
||||
}
|
||||
|
28
hutool-http/src/test/java/cn/hutool/http/test/HttpsTest.java
Normal file
28
hutool-http/src/test/java/cn/hutool/http/test/HttpsTest.java
Normal file
@ -0,0 +1,28 @@
|
||||
package cn.hutool.http.test;
|
||||
|
||||
import cn.hutool.core.lang.Console;
|
||||
import cn.hutool.core.thread.ThreadUtil;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class HttpsTest {
|
||||
|
||||
/**
|
||||
* 测试单例的SSLSocketFactory是否有线程安全问题
|
||||
*/
|
||||
@Test
|
||||
@Ignore
|
||||
public void getTest() {
|
||||
final AtomicInteger count = new AtomicInteger();
|
||||
for(int i =0; i < 100; i++){
|
||||
ThreadUtil.execute(()->{
|
||||
final String s = HttpUtil.get("https://www.baidu.com/");
|
||||
Console.log(count.incrementAndGet());
|
||||
});
|
||||
}
|
||||
ThreadUtil.sync(this);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user