0

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?

Acroyear
  • 1,354
  • 3
  • 22
  • 37
  • Forgot to add `httpUrlConnection.setRequestMethod("PATCH");`. It seems to be working now... – Acroyear Feb 04 '20 at 00:19
  • You may have better luck with the [java.net.http](https://docs.oracle.com/en/java/javase/13/docs/api/java.net.http/java/net/http/package-summary.html) package, if you’re using Java 11 or later. – VGR Feb 04 '20 at 03:13
  • Sadly, I'm stuck with Java 7 for the time being. – Acroyear Feb 04 '20 at 17:31

0 Answers0