kav*_*i77 64 java httpurlconnection
当我尝试使用非标准的HTTP方法,如PATCH和URLConnection:
HttpURLConnection conn = (HttpURLConnection) new URL("http://example.com").openConnection();
conn.setRequestMethod("PATCH");
Run Code Online (Sandbox Code Playgroud)
我得到一个例外:
java.net.ProtocolException: Invalid HTTP method: PATCH
at java.net.HttpURLConnection.setRequestMethod(HttpURLConnection.java:440)
Run Code Online (Sandbox Code Playgroud)
使用像Jersey这样的更高级别的API会产生相同的错误.是否有解决方法来发出PATCH HTTP请求?
sag*_*gar 44
是的,有解决方法.使用
X-HTTP-方法,覆盖
.此标头可用于POST请求中"伪造"其他HTTP方法.只需将X-HTTP-Method-Override标头的值设置为您想要实际执行的HTTP方法即可.所以使用以下代码.
conn.setRequestProperty("X-HTTP-Method-Override", "PATCH");
conn.setRequestMethod("POST");
Run Code Online (Sandbox Code Playgroud)
oku*_*ane 32
有很多好的答案,所以这是我的:
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.Set;
public class SupportPatch {
public static void main(String... args) throws IOException {
allowMethods("PATCH");
HttpURLConnection conn = (HttpURLConnection) new URL("http://example.com").openConnection();
conn.setRequestMethod("PATCH");
}
private static void allowMethods(String... methods) {
try {
Field methodsField = HttpURLConnection.class.getDeclaredField("methods");
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(methodsField, methodsField.getModifiers() & ~Modifier.FINAL);
methodsField.setAccessible(true);
String[] oldMethods = (String[]) methodsField.get(null);
Set<String> methodsSet = new LinkedHashSet<>(Arrays.asList(oldMethods));
methodsSet.addAll(Arrays.asList(methods));
String[] newMethods = methodsSet.toArray(new String[0]);
methodsField.set(null/*static field*/, newMethods);
} catch (NoSuchFieldException | IllegalAccessException e) {
throw new IllegalStateException(e);
}
}
}
Run Code Online (Sandbox Code Playgroud)
它也使用反射,但不是黑客攻击每个连接对象,而是黑客攻击HttpURLConnection#方法静态字段,它在内部检查中使用.
kav*_*i77 29
OpenJDK中有一个不会修复的错误:https://bugs.openjdk.java.net/browse/JDK-7016595
但是,使用Apache Http-Components Client 4.2+,这是可能的.它具有自定义网络实现,因此可以使用非标准HTTP方法,如PATCH.它甚至还有一个支持补丁方法的HttpPatch类.
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPatch httpPatch = new HttpPatch(new URI("http://example.com"));
CloseableHttpResponse response = httpClient.execute(httpPatch);
Run Code Online (Sandbox Code Playgroud)
Maven坐标:
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.2+</version>
</dependency>
Run Code Online (Sandbox Code Playgroud)
sim*_*005 15
在 java 11+ 中,您可以使用 HttpRequest 类来执行您想要的操作:
import java.net.http.HttpRequest;
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(uri))
.method("PATCH", HttpRequest.BodyPublishers.ofString(message))
.header("Content-Type", "text/xml")
.build();
Run Code Online (Sandbox Code Playgroud)
如果您在 Oracle 的 JRE 上使用 a ,则本文和相关帖子中所述的反射不起作用HttpsURLConnection,因为sun.net.www.protocol.https.HttpsURLConnectionImpl使用的是method来自java.net.HttpURLConnection其DelegateHttpsURLConnection!
所以一个完整的工作解决方案是:
private void setRequestMethod(final HttpURLConnection c, final String value) {
try {
final Object target;
if (c instanceof HttpsURLConnectionImpl) {
final Field delegate = HttpsURLConnectionImpl.class.getDeclaredField("delegate");
delegate.setAccessible(true);
target = delegate.get(c);
} else {
target = c;
}
final Field f = HttpURLConnection.class.getDeclaredField("method");
f.setAccessible(true);
f.set(target, value);
} catch (IllegalAccessException | NoSuchFieldException ex) {
throw new AssertionError(ex);
}
}
Run Code Online (Sandbox Code Playgroud)
如果项目在Spring / Gradle上;以下解决方案将进行锻炼。
对于build.gradle,添加以下依赖项;
compile('org.apache.httpcomponents:httpclient:4.5.2')
Run Code Online (Sandbox Code Playgroud)
并在com.company.project中的@SpringBootApplication类中定义以下bean;
@Bean
public RestTemplate restTemplate() {
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
requestFactory.setReadTimeout(600000);
requestFactory.setConnectTimeout(600000);
return new RestTemplate(requestFactory);
}
Run Code Online (Sandbox Code Playgroud)
该解决方案为我工作。
| 归档时间: |
|
| 查看次数: |
49824 次 |
| 最近记录: |