diff --git a/hutool-http/src/main/java/cn/hutool/http/HttpConnection.java b/hutool-http/src/main/java/cn/hutool/http/HttpConnection.java
index 6d6b13285..44114a3ed 100644
--- a/hutool-http/src/main/java/cn/hutool/http/HttpConnection.java
+++ b/hutool-http/src/main/java/cn/hutool/http/HttpConnection.java
@@ -13,8 +13,6 @@ 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;
@@ -122,7 +120,7 @@ public class HttpConnection {
// 增加PATCH方法支持
if (Method.PATCH.equals(method)) {
- allowPatch();
+ HttpGlobalConfig.allowPatch();
}
}
@@ -546,23 +544,5 @@ public class HttpConnection {
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
-}
\ No newline at end of file
+}
diff --git a/hutool-http/src/main/java/cn/hutool/http/HttpGlobalConfig.java b/hutool-http/src/main/java/cn/hutool/http/HttpGlobalConfig.java
index 3ed3605f4..93a70070b 100755
--- a/hutool-http/src/main/java/cn/hutool/http/HttpGlobalConfig.java
+++ b/hutool-http/src/main/java/cn/hutool/http/HttpGlobalConfig.java
@@ -1,13 +1,17 @@
package cn.hutool.http;
-import java.io.Serializable;
-import java.net.CookieManager;
-
+import cn.hutool.core.util.ReflectUtil;
import cn.hutool.http.cookie.GlobalCookieManager;
+import java.io.Serializable;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.net.CookieManager;
+import java.net.HttpURLConnection;
+
/**
* HTTP 全局参数配置
- *
+ *
* @author Looly
* @since 4.6.2
*/
@@ -15,10 +19,11 @@ public class HttpGlobalConfig implements Serializable {
private static final long serialVersionUID = 1L;
protected static int timeout = -1;
+ private static boolean isAllowPatch = false;
/**
* 获取全局默认的超时时长
- *
+ *
* @return 全局默认的超时时长
*/
public static int getTimeout() {
@@ -27,16 +32,16 @@ public class HttpGlobalConfig implements Serializable {
/**
* 设置默认的连接和读取超时时长
- *
+ *
* @param customTimeout 超时时长
*/
- public static void setTimeout(int customTimeout) {
+ synchronized public static void setTimeout(int customTimeout) {
timeout = customTimeout;
}
-
+
/**
* 获取Cookie管理器,用于自定义Cookie管理
- *
+ *
* @return {@link CookieManager}
* @since 4.1.0
* @see GlobalCookieManager#getCookieManager()
@@ -47,7 +52,7 @@ public class HttpGlobalConfig implements Serializable {
/**
* 自定义{@link CookieManager}
- *
+ *
* @param customCookieManager 自定义的{@link CookieManager}
* @since 4.5.14
* @see GlobalCookieManager#setCookieManager(CookieManager)
@@ -55,14 +60,37 @@ public class HttpGlobalConfig implements Serializable {
public static void setCookieManager(CookieManager customCookieManager) {
GlobalCookieManager.setCookieManager(customCookieManager);
}
-
+
/**
* 关闭Cookie
- *
+ *
* @since 4.1.9
* @see GlobalCookieManager#setCookieManager(CookieManager)
*/
public static void closeCookie() {
GlobalCookieManager.setCookieManager(null);
}
+
+ /**
+ * 增加支持的METHOD方法
+ * 此方法通过注入方式修改{@link HttpURLConnection}中的methods静态属性,增加PATCH方法
+ * see: https://stackoverflow.com/questions/25163131/httpurlconnection-invalid-http-method-patch
+ *
+ * @since 5.7.4
+ */
+ synchronized public static void allowPatch() {
+ if(isAllowPatch){
+ return;
+ }
+ 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);
+ isAllowPatch = true;
+ }
+ }
}
diff --git a/hutool-http/src/main/java/cn/hutool/http/HttpInputStream.java b/hutool-http/src/main/java/cn/hutool/http/HttpInputStream.java
index d59fa5edf..9dc6b0205 100644
--- a/hutool-http/src/main/java/cn/hutool/http/HttpInputStream.java
+++ b/hutool-http/src/main/java/cn/hutool/http/HttpInputStream.java
@@ -12,7 +12,7 @@ import java.util.zip.InflaterInputStream;
/**
* HTTP输入流,此流用于包装Http请求响应内容的流,用于解析各种压缩、分段的响应流内容
- *
+ *
* @author Looly
*
*/
@@ -23,7 +23,7 @@ public class HttpInputStream extends InputStream {
/**
* 构造
- *
+ *
* @param response 响应对象
*/
public HttpInputStream(HttpResponse response) {
@@ -34,37 +34,38 @@ public class HttpInputStream extends InputStream {
public int read() throws IOException {
return this.in.read();
}
-
+
+ @SuppressWarnings("NullableProblems")
@Override
public int read(byte[] b, int off, int len) throws IOException {
return this.in.read(b, off, len);
}
-
+
@Override
public long skip(long n) throws IOException {
return this.in.skip(n);
}
-
+
@Override
public int available() throws IOException {
return this.in.available();
}
-
+
@Override
public void close() throws IOException {
this.in.close();
}
-
+
@Override
public synchronized void mark(int readlimit) {
this.in.mark(readlimit);
}
-
+
@Override
public synchronized void reset() throws IOException {
this.in.reset();
}
-
+
@Override
public boolean markSupported() {
return this.in.markSupported();
@@ -72,7 +73,7 @@ public class HttpInputStream extends InputStream {
/**
* 初始化流
- *
+ *
* @param response 响应对象
*/
private void init(HttpResponse response) {
@@ -84,13 +85,13 @@ public class HttpInputStream extends InputStream {
}
// 服务器无返回内容,忽略之
}
-
+
// 在一些情况下,返回的流为null,此时提供状态码说明
if (null == this.in) {
this.in = new ByteArrayInputStream(StrUtil.format("Error request, response status: {}", response.status).getBytes());
return;
}
-
+
if (response.isGzip() && false == (response.in instanceof GZIPInputStream)) {
// Accept-Encoding: gzip
try {