Исключение при попытке использовать PATCH с Httpurlconnection.setrequestmethod - PullRequest
0 голосов
/ 04 февраля 2020

Попытка сделать вызов PATCH для веб-службы приводит к ошибке, 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");    
    }
}

Я знаю, что это известная проблема с Httpurlconnection.setrequestmethod, как обсуждалось в HttpURLConnection Неверный метод HTTP: PATCH . Сначала я попробовал обходной путь X-HTTP-Method-Override, но служба все еще думает, что я выполняю вызов POST.

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

Ответ: {"code":"405","message":"Request method 'POST' not supported"}

Далее я попытался использовать метод отражения и это работало нормально, прежде чем пытаться отправить полезную нагрузку запроса.

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"}

Однако при попытке пользователя Writer установить полезную нагрузку запроса я получаю ошибку 405.

    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)

Нужно ли внести некоторые изменения в allowMethods, чтобы избежать ошибки 405, или я что-то упускаю?

...