Trying to make a PATCH call to a web service results in the error, java.net.ProtocolException: Invalid HTTP method: PATCH
.
public class PatchTest {
public static void main(String[] args) throws Exception {
HttpURLConnection httpUrlConnection = (HttpURLConnection) new URL("https://api.url.com").openConnection();
httpUrlConnection.setRequestMethod("PATCH");
}
}
I am aware that this is a known issue with Httpurlconnection.setrequestmethod
as discussed in HttpURLConnection Invalid HTTP method: PATCH. First, I tried the X-HTTP-Method-Override
workaround, but the service still thinks I am making a POST call.
public class PatchTest {
public static void main(String[] args) throws Exception {
HttpURLConnection httpUrlConnection = (HttpURLConnection) new URL("https://api.url.com").openConnection();
httpUrlConnection.setRequestProperty("Content-Type", "application/json");
httpUrlConnection.setDoOutput(true);
httpUrlConnection.setRequestProperty("X-HTTP-Method-Override", "PATCH");
httpUrlConnection.setRequestMethod("POST");
httpUrlConnection.getResponseCode();
InputStreamReader inputStreamReader = new InputStreamReader(httpUrlConnection.getErrorStream());
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
System.out.println(bufferedReader.readLine());
}
}
Response: {"code":"405","message":"Request method 'POST' not supported"}
Next, I tried using the reflection method, and this worked fine before trying to send a request payload.
public class PatchTest {
public static void main(String[] args) throws Exception {
allowMethods("PATCH");
HttpURLConnection httpUrlConnection = (HttpURLConnection) new URL("https://api.url.com").openConnection();
httpUrlConnection.setRequestProperty("Content-Type", "application/json");
httpUrlConnection.setDoOutput(true);
System.out.println("Response code: " + httpUrlConnection.getResponseCode());
InputStreamReader inputStreamReader = new InputStreamReader(httpUrlConnection.getInputStream());
System.out.println(new BufferedReader(inputStreamReader).readLine());
}
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);
}
}
}
Response code: 200
{"somekey":"somevalue"}
However, when I try to user Writer
to set the request payload, I get a 405 error.
public static void main(String[] args) throws Exception {
allowMethods("PATCH");
HttpURLConnection httpUrlConnection = (HttpURLConnection) new URL("https://api.url.com").openConnection();
httpUrlConnection.setRequestProperty("Content-Type", "application/json");
httpUrlConnection.setDoOutput(true);
Writer writer = new BufferedWriter(new OutputStreamWriter(httpUrlConnection.getOutputStream()));
writer.write("{}");
writer.close();
InputStreamReader inputStreamReader = new InputStreamReader(httpUrlConnection.getInputStream());
System.out.println(new BufferedReader(inputStreamReader).readLine());
}
Exception in thread "main" java.io.IOException: Server returned HTTP response code: 405 for URL: https://api.url.com
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(Unknown Source)
at PatchTest.main(PatchTest.java:32)
Is there some change I need to make to allowMethods
to get past the 405 error, or is there something else I am missing?