@@ -2,11 +2,10 @@ package cn.hutool.http;
import cn.hutool.core.map.MapUtil ;
import cn.hutool.core.util.ObjectUtil ;
import cn.hutool.core.util.ReflectUtil ;
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 ;
@@ -14,6 +13,8 @@ import javax.net.ssl.SSLSocketFactory;
import java.io.IOException ;
import java.io.InputStream ;
import java.io.OutputStream ;
import java.lang.reflect.Field ;
import java.lang.reflect.Modifier ;
import java.net.HttpURLConnection ;
import java.net.ProtocolException ;
import java.net.Proxy ;
@@ -21,17 +22,14 @@ import java.net.URL;
import java.net.URLConnection ;
import java.nio.charset.Charset ;
import java.nio.charset.UnsupportedCharsetException ;
import java.security.KeyManagementException ;
import java.security.NoSuchAlgorithmException ;
import java.util.List ;
import java.util.Map ;
import java.util.Map.Entry ;
/**
* http连接对象, 对HttpURLConnection的包装
*
* @author Looly
*
* @author Looly
*/
public class HttpConnection {
@@ -41,9 +39,9 @@ public class HttpConnection {
/**
* 创建HttpConnection
*
*
* @param urlStr URL
* @param proxy 代理,无代理传{@code null}
* @param proxy 代理,无代理传{@code null}
* @return HttpConnection
*/
public static HttpConnection create ( String urlStr , Proxy proxy ) {
@@ -52,8 +50,8 @@ public class HttpConnection {
/**
* 创建HttpConnection
*
* @param url URL
*
* @param url URL
* @param proxy 代理,无代理传{@code null}
* @return HttpConnection
*/
@@ -62,10 +60,11 @@ public class HttpConnection {
}
// --------------------------------------------------------------- Constructor start
/**
* 构造HttpConnection
*
* @param url URL
*
* @param url URL
* @param proxy 代理
*/
public HttpConnection ( URL url , Proxy proxy ) {
@@ -80,7 +79,7 @@ public class HttpConnection {
/**
* 初始化连接相关信息
*
*
* @return HttpConnection
* @since 4.4.1
*/
@@ -98,10 +97,11 @@ public class HttpConnection {
}
// --------------------------------------------------------------- Getters And Setters start
/**
* 获取请求方法,GET/POST
*
* @return 请求方法,GET/POST
*
* @return 请求方法, GET/POST
*/
public Method getMethod ( ) {
return Method . valueOf ( this . conn . getRequestMethod ( ) ) ;
@@ -109,11 +109,23 @@ public class HttpConnection {
/**
* 设置请求方法
*
*
* @param method 请求方法
* @return 自己
*/
public HttpConnection setMethod ( Method method ) {
if ( Method . POST . equals ( method ) //
| | Method . PUT . equals ( method ) //
| | Method . PATCH . equals ( method ) //
| | Method . DELETE . equals ( method ) ) {
this . conn . setUseCaches ( false ) ;
// 增加PATCH方法支持
if ( Method . PATCH . equals ( method ) ) {
allowPatch ( ) ;
}
}
// method
try {
this . conn . setRequestMethod ( method . toString ( ) ) ;
@@ -121,18 +133,12 @@ public class HttpConnection {
throw new HttpException ( e ) ;
}
if ( Method . POST . equals ( method ) //
| | Method . PUT . equals ( method ) //
| | Method . PATCH . equals ( method ) //
| | Method . DELETE . equals ( method ) ) {
this . conn . setUseCaches ( false ) ;
}
return this ;
}
/**
* 获取请求URL
*
*
* @return 请求URL
*/
public URL getUrl ( ) {
@@ -141,7 +147,7 @@ public class HttpConnection {
/**
* 获得代理
*
*
* @return {@link Proxy}
*/
public Proxy getProxy ( ) {
@@ -150,7 +156,7 @@ public class HttpConnection {
/**
* 获取HttpURLConnection对象
*
*
* @return HttpURLConnection
*/
public HttpURLConnection getHttpURLConnection ( ) {
@@ -160,12 +166,13 @@ public class HttpConnection {
// --------------------------------------------------------------- Getters And Setters end
// ---------------------------------------------------------------- Headers start
/**
* 设置请求头<br>
* 当请求头存在时,覆盖之
*
* @param header 头名
* @param value 头值
*
* @param header 头名
* @param value 头值
* @param isOverride 是否覆盖旧值
* @return HttpConnection
*/
@@ -184,9 +191,9 @@ public class HttpConnection {
/**
* 设置请求头<br>
* 当请求头存在时,覆盖之
*
* @param header 头名
* @param value 头值
*
* @param header 头名
* @param value 头值
* @param isOverride 是否覆盖旧值
* @return HttpConnection
*/
@@ -197,8 +204,8 @@ public class HttpConnection {
/**
* 设置请求头<br>
* 不覆盖原有请求头
*
* @param headerMap 请求头
*
* @param headerMap 请求头
* @param isOverride 是否覆盖
* @return this
*/
@@ -217,7 +224,7 @@ public class HttpConnection {
/**
* 获取Http请求头
*
*
* @param name Header名
* @return Http请求头值
*/
@@ -227,7 +234,7 @@ public class HttpConnection {
/**
* 获取Http请求头
*
*
* @param name Header名
* @return Http请求头值
*/
@@ -237,7 +244,7 @@ public class HttpConnection {
/**
* 获取所有Http请求头
*
*
* @return Http请求头Map
*/
public Map < String , List < String > > headers ( ) {
@@ -249,9 +256,9 @@ public class HttpConnection {
/**
* 设置https请求参数<br>
* 有些时候htts请求会出现com.sun.net.ssl.internal.www.protocol.https.HttpsURLConnectionOldImpl的实现, 此为sun内部api, 按照普通http请求处理
*
*
* @param hostnameVerifier 域名验证器, 非https传入null
* @param ssf SSLSocketFactory, 非https传入null
* @param ssf SSLSocketFactory, 非https传入null
* @return this
* @throws HttpException KeyManagementException和NoSuchAlgorithmException异常包装
*/
@@ -271,9 +278,9 @@ public class HttpConnection {
/**
* 关闭缓存
*
*
* @return this
* @see HttpURLConnection#setUseCaches(boolean)
* @see HttpURLConnection#setUseCaches(boolean)
*/
public HttpConnection disableCache ( ) {
this . conn . setUseCaches ( false ) ;
@@ -282,7 +289,7 @@ public class HttpConnection {
/**
* 设置连接超时
*
*
* @param timeout 超时
* @return this
*/
@@ -296,7 +303,7 @@ public class HttpConnection {
/**
* 设置读取超时
*
*
* @param timeout 超时
* @return this
*/
@@ -310,7 +317,7 @@ public class HttpConnection {
/**
* 设置连接和读取的超时时间
*
*
* @param timeout 超时时间
* @return this
*/
@@ -323,7 +330,7 @@ public class HttpConnection {
/**
* 设置Cookie
*
*
* @param cookie Cookie
* @return this
*/
@@ -337,12 +344,12 @@ public class HttpConnection {
/**
* 采用流方式上传数据,无需本地缓存数据。<br>
* HttpUrlConnection默认是将所有数据读到本地缓存, 然后再发送给服务器, 这样上传大文件时就会导致内存溢出。
*
*
* @param blockSize 块大小( bytes数) , 0或小于0表示不设置Chuncked模式
* @return this
*/
public HttpConnection setChunkedStreamingMode ( int blockSize ) {
if ( blockSize > 0 ) {
if ( blockSize > 0 ) {
conn . setChunkedStreamingMode ( blockSize ) ;
}
return this ;
@@ -350,7 +357,7 @@ public class HttpConnection {
/**
* 设置自动HTTP 30X跳转
*
*
* @param isInstanceFollowRedirects 是否自定跳转
* @return this
*/
@@ -361,7 +368,7 @@ public class HttpConnection {
/**
* 连接
*
*
* @return this
* @throws IOException IO异常
*/
@@ -371,10 +378,10 @@ public class HttpConnection {
}
return this ;
}
/**
* 静默断开连接。不抛出异常
*
*
* @return this
* @since 4.6.0
*/
@@ -384,13 +391,13 @@ public class HttpConnection {
} catch ( Throwable e ) {
// ignore
}
return this ;
}
/**
* 断开连接
*
*
* @return this
*/
public HttpConnection disconnect ( ) {
@@ -403,7 +410,7 @@ public class HttpConnection {
/**
* 获得输入流对象<br>
* 输入流对象用于读取数据
*
*
* @return 输入流对象
* @throws IOException IO异常
*/
@@ -416,7 +423,7 @@ public class HttpConnection {
/**
* 当返回错误代码时,获得错误内容流
*
*
* @return 错误内容
*/
public InputStream getErrorStream ( ) {
@@ -428,7 +435,7 @@ public class HttpConnection {
/**
* 获取输出流对象 输出流对象用于发送数据
*
*
* @return OutputStream
* @throws IOException IO异常
*/
@@ -444,7 +451,7 @@ public class HttpConnection {
/**
* 获取响应码
*
*
* @return 响应码
* @throws IOException IO异常
*/
@@ -459,7 +466,7 @@ public class HttpConnection {
* 获得字符集编码<br>
* 从Http连接的头信息中获得字符集<br>
* 从ContentType中获取
*
*
* @return 字符集编码
*/
public String getCharsetName ( ) {
@@ -470,7 +477,7 @@ public class HttpConnection {
* 获取字符集编码<br>
* 从Http连接的头信息中获得字符集<br>
* 从ContentType中获取
*
*
* @return {@link Charset}编码
* @since 3.0.9
*/
@@ -501,10 +508,11 @@ public class HttpConnection {
}
// --------------------------------------------------------------- Private Method start
/**
* 初始化http或https请求参数<br>
* 有些时候https请求会出现com.sun.net.ssl.internal.www.protocol.https.HttpsURLConnectionOldImpl的实现, 此为sun内部api, 按照普通http请求处理
*
*
* @return {@link HttpURLConnection}, https返回{@link HttpsURLConnection}
*/
private HttpURLConnection openHttp ( ) throws IOException {
@@ -519,12 +527,30 @@ public class HttpConnection {
/**
* 建立连接
*
*
* @return {@link URLConnection}
* @throws IOException IO异常
*/
private URLConnection openConnection ( ) throws IOException {
return ( null = = this . proxy ) ? url . openConnection ( ) : url . openConnection ( this . proxy ) ;
}
/**
* 增加支持的METHOD方法
* see: https://stackoverflow.com/questions/25163131/httpurlconnection-invalid-http-method-patch
*
* @since 5.1.6
*/
private static void allowPatch ( ) {
final Field methodsField = ReflectUtil . getField ( HttpURLConnection . class , " methods " ) ;
if ( null ! = methodsField ) {
// 去除final修饰
ReflectUtil . setFieldValue ( methodsField , " modifiers " , methodsField . getModifiers ( ) & ~ Modifier . FINAL ) ;
final String [ ] methods = {
" GET " , " POST " , " HEAD " , " OPTIONS " , " PUT " , " DELETE " , " TRACE " , " PATCH "
} ;
ReflectUtil . setFieldValue ( null , methodsField , methods ) ;
}
}
// --------------------------------------------------------------- Private Method end
}