最近系統需要使用 Netty4,所以把衝突的 Netty3 拆掉,然後就出現了例外。
pom.xml
<dependency>
<groupId>com.ning</groupId>
<artifactId>async-http-client</artifactId>
<version>1.9.40</version>
<exclusions>
<exclusion>
<groupId>io.netty</groupId>
<artifactId>netty</artifactId>
</exclusion>
</exclusions>
</dependency>
client
Request request = new RequestBuilder("POST")
.setUrl(url)
.setBody(body)
.setHeader("Content-Type", contentType)
.setRequestTimeout(timeout)
.build();
Future&lg4;Response> future = client.executeRequest(request);
console log
[AsyncHttpClient-Callback] DEBUG c.n.h.c.p.jdk.JDKAsyncHttpProvider - Invalid HTTP method: PATCH
java.net.ProtocolException: Invalid HTTP method: PATCH
at java.net.HttpURLConnection.setRequestMethod(HttpURLConnection.java:440)
at sun.net.www.protocol.http.HttpURLConnection.setRequestMethod(HttpURLConnection.java:553)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.setRequestMethod(HttpsURLConnectionImpl.java:388)
at com.ning.http.client.providers.jdk.JDKAsyncHttpProvider$AsyncHttpUrlConnection.configure(JDKAsyncHttpProvider.java:530)
at com.ning.http.client.providers.jdk.JDKAsyncHttpProvider$AsyncHttpUrlConnection.call(JDKAsyncHttpProvider.java:227)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
可以看到 com.ning:async-http-client 原本是走 Netty3,拿掉之後改走 HttpURLConnection 才是出現例外的主因。 找到的解法有幾個:
- 使用 head X-HTTP-Method-Override:測試不可行。
- 複寫 HttpURLConnection.methods:測試不可行,payload 帶不過去。
- 尋找已解決的 JDK (待確認)
- 改用新版 org.asynchttpclient:async-http-client;因為底層用的是 Netty4。
- 改用其他 http client。
雖然 Jersey 也會發生相同問題,但是修改之後可以正常使用。
webTarget.property(HttpUrlConnectorProvider.SET_METHOD_WORKAROUND, true);
Response response = webTarget.path(url)
.request(MediaType.APPLICATION_JSON)
.method("PATCH", Entity.json(payload.toString()));
參考資料: