Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HttpURLConnection Invalid HTTP method: PATCH

When I try to use a non-standard HTTP Method like PATCH with URLConnection:

    HttpURLConnection conn = (HttpURLConnection) new URL("http://example.com").openConnection();     conn.setRequestMethod("PATCH"); 

I get an exception:

java.net.ProtocolException: Invalid HTTP method: PATCH at java.net.HttpURLConnection.setRequestMethod(HttpURLConnection.java:440) 

Using a higher level API like Jersey generates the same error. Is there a workaround to issue a PATCH HTTP request?

like image 482
kavai77 Avatar asked Aug 06 '14 14:08

kavai77


People also ask

How do I call a PATCH method in Java?

To send a PATCH request to the server, you need to use the HTTP PATCH method and include the request data in the body of the HTTP message. The Content-Type request header must indicate the data type in the body. In this PATCH request example, we send JSON to the ReqBin echo endpoint to update the data on the server.

What is PATCH method?

In computing, the PATCH method is a request method in HTTP for making partial changes to an existing resource. The PATCH method provides an entity containing a list of changes to be applied to the resource requested using the HTTP Uniform Resource Identifier (URI).

What is put and PATCH?

PUT. PATCH. PUT is a method of modifying resource where the client sends data that updates the entire resource . PATCH is a method of modifying resources where the client sends partial data that is to be updated without modifying the entire data.


2 Answers

There are a lot of good answers, so here is mine (not work in jdk12):

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);         }     } } 

It also uses reflection, but instead of hacking into every connection object we're hacking HttpURLConnection#methods static field which is used in the checks internally.

like image 147
okutane Avatar answered Sep 18 '22 19:09

okutane


Yes there is workaround for this. Use

X-HTTP-Method-Override

. This header can be used in a POST request to “fake” other HTTP methods. Simply set the value of the X-HTTP-Method-Override header to the HTTP method you would like to actually perform. So use following code.

conn.setRequestProperty("X-HTTP-Method-Override", "PATCH"); conn.setRequestMethod("POST"); 
like image 38
sagar Avatar answered Sep 19 '22 19:09

sagar