HttpURLConnection в Java не поддерживает REPORT/PROPFIND — что мне делать?

HttpURLConnection поддерживает только такие вещи, как GET, POST и HEAD, но не REPORT/PROPFIND. Я собираюсь реализовать CalDAV-Client, но без этих операций (если я хочу их использовать, я получаю исключение ProtocolException), мне нужно написать/доставить полную и огромную HTTP-библиотеку с авторизацией и так далее.

«Перебор».

Как отправлять запросы с помощью PROPFIND и REPORT?


person mutter erde    schedule 11.08.2010    source источник


Ответы (5)


У меня была аналогичная проблема с методом WebDav для PROPFIND.

Проблема решена путем реализации этого решения: https://java.net/jira/browse/JERSEY-639

    try {
            httpURLConnection.setRequestMethod(method);
        } catch (final ProtocolException pe) {
            try {
                final Class<?> httpURLConnectionClass = httpURLConnection
                        .getClass();
                final Class<?> parentClass = httpURLConnectionClass
                        .getSuperclass();
                final Field methodField;
                // If the implementation class is an HTTPS URL Connection, we
                // need to go up one level higher in the heirarchy to modify the
                // 'method' field.
                if (parentClass == HttpsURLConnection.class) {
                    methodField = parentClass.getSuperclass().getDeclaredField(
                            "method");
                } else {
                    methodField = parentClass.getDeclaredField("method");
                }
                methodField.setAccessible(true);
                methodField.set(httpURLConnection, method);
            } catch (final Exception e) {
                throw new RuntimeException(e);

            }
     }
person roko    schedule 26.08.2014
comment
Хороший ответ! Однако в моем случае у httpURLConnection есть делегат, и ответ не работает. Поэтому я извлекаю поле делегата объекта httpURLConnection с помощью рефлексии. Поле делегата также является (подпод) подклассом HttpURLConnection. Я применяю вашу процедуру для этого соединения делегата с помощью methodField = parentClass.getSuperclass().getSuperclass().getDeclaredField(method);. Это хорошо работает. Спасибо! - person KNaito; 04.01.2015
comment
Я попробовал вышеуказанное решение и получил ошибку, так как метод http не разрешен. Не могли бы вы дать какой-либо указатель на это. Я также вижу, что у httpURLConnection есть делегат, но когда я попробовал прокомментированное решение, я получаю ошибку noSuchMethod. - person Coder; 10.08.2017
comment
@KNaito, не могли бы вы помочь мне решить эту проблему, я использую JDK 1.7 и напрямую использую HttpUrlConnection - person Coder; 22.08.2017
comment
Я использую следующие коды: ``` if (parentClass == HttpsURLConnection.class) { methodField = parentClass.getSuperclass().getDeclaredField(method); } else if (parentClass == HttpURLConnection.class) { methodField = parentClass.getDeclaredField (метод); } else { methodField = parentClass.getSuperclass().getSuperclass().getDeclaredField(метод); } methodField.setAccessible(true); methodField.set(httpURLConnection, метод); ``` @Dhamayanthi - person KNaito; 23.08.2017
comment
Причина, по которой вы получаете ошибку noSuchMethod, заключается в том, что ваш класс (parentClass) не является ни HttpsURLConnection.class, ни HttpURLConnection.class, а классом-потомком. Поэтому вам следует вернуться к HttpURLConnectionc.class, используя метод getSuperclass(). - person KNaito; 23.08.2017
comment
мой объект conn также имеет делегата (sun.net.www.protocol.https.DelegateHttpsURLConnection), и я пытаюсь извлечь делегата, как вы упомянули в своем первом комментарии, но не знаю, как установить метод для этого делегата. Я предполагаю, что делаю что-то не так, когда извлекаю удаление, и если (parentClass == HttpsURLConnection.class) верно для меня. Не могли бы вы поделиться своим полным методом, который делает это, как указано в ответе. кстати, я пытаюсь реализовать метод PATCH, и когда я попытался в соответствии с ответом, я получил HttpMethodNotFound @KNaito - person Coder; 23.08.2017
comment
Извините, здесь нет места для полного кода. Я думаю, есть две вещи. Во-первых, как получить parentClass. мой код `` Поле delegateField; delegateField = connection.getClass().getDeclaredField(делегат); делегатПоле.setAccessible (истина); HttpURLConnection delegateConnection = (HttpURLConnection) delegateField.get(соединение); конечный класс‹?› httpURLConnectionClass = delegateConnection.getClass(); конечный класс‹?› parentClass = httpURLConnectionClass.getSuperclass(); ``` @Dhamayanthi - person KNaito; 24.08.2017
comment
Другое дело, что HttpsURLConnection/HttpsURLConnection в выражении if являются javax.net.ssl.Https.URLConnection/java.net.HttpURLConnection. Обратите внимание, что класс java.net.HttpURLConnection имеет защищенное поле method. - person KNaito; 24.08.2017
comment
Спасибо @KNaito, ваша последняя подсказка помогла мне определить проблему, это была проблема с java.net.HttpURLConnection. - person Coder; 20.09.2017

Вы, вероятно, захотите найти для этого библиотеку WebDAV, а не библиотеку HTTP.

Можете взглянуть на Apache Jackrabbit.

person Dean J    schedule 11.08.2010
comment
+1 за ссылку на Jackrabbit, хотя ссылка, которую вы отправили, предназначена для серверной части. Это может иметь более прямое отношение: jackrabbit.apache.org/api/1.3/org/apache/jackrabbit/webdav/ - person Bruno; 11.08.2010
comment
Битые ссылки здесь - person IgniteCoders; 02.10.2020

Либо вы можете использовать https://github.com/square/okhttp

Пример кода

    // using OkHttp
    public class PropFindExample {        
    private final OkHttpClient client = new OkHttpClient();
    String run(String url) throws IOException {
        String credential = Credentials.basic(userName, password);
        // body
        String body = "<d:propfind xmlns:d=\"DAV:\" xmlns:cs=\"http://calendarserver.org/ns/\">\n" +
                "  <d:prop>\n" +
                "     <d:displayname />\n" +
                "     <d:getetag />\n" +
                "  </d:prop>\n" +
                "</d:propfind>";
        Request request = new Request.Builder()
                .url(url)
                .method("PROPFIND", RequestBody.create(MediaType.parse(body), body))
                .header("DEPTH", "1")
                .header("Authorization", credential)
                .header("Content-Type", "text/xml")
                .build();

        Response response = client.newCall(request).execute();
        return response.body().string();
    }
 }

Или поиграйте с сокетами

Пример кода

String host = "example.com";
int port = 443;
String path = "/placeholder";
String userName = "username";
String password = "password";

SSLSocketFactory ssf = (SSLSocketFactory) SSLSocketFactory.getDefault();
Socket socket = ssf.createSocket(host, port);
PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())));

// xml data to be sent in body
String xmlData = "<?xml version=\"1.0\"?> <d:propfind xmlns:d=\"DAV:\" xmlns:cs=\"http://calendarserver.org/ns/\"> <d:prop> <d:displayname /> <d:getetag /> </d:prop> </d:propfind>";
// append headers
out.println("PROPFIND path HTTP/1.1");
out.println("Host: "+host);
String userCredentials = username+":"+password;
String basicAuth = "Basic " + new String(Base64.encode(userCredentials.getBytes(), Base64.DEFAULT));
String authorization = "Authorization: " + basicAuth;
out.println(authorization.trim());
out.println("Content-Length: "+ xmlData.length());
out.println("Content-Type: text/xml");
out.println("Depth: 1");
out.println();
// append body
out.println(xmlData);
out.flush();

// get response
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String inputLine;

System.out.println("--------------------------------------------------------");
System.out.println("---------------Printing response--------------------------");
System.out.println("--------------------------------------------------------");
while ((inputLine = in.readLine()) != null) {
    System.out.println(inputLine);
}

in.close();
person Puneet Arora    schedule 18.02.2016
comment
Пожалуйста, не копировать/вставлять один и тот же ответ на несколько вопросов. Вместо этого настройте ответ на отдельные вопросы и объясните, как они решают эту конкретную проблему. - person Andy♦; 19.02.2016
comment
Конечно! Спасибо за твое сообщение! - person Puneet Arora; 19.02.2016

Вы можете попробовать использовать другую библиотеку HTTP, например HTTP-клиент Apache, и расширить его HttpRequestBase (см. HttpGet и HttpPost например).

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

person Bruno    schedule 11.08.2010

Рассмотрите возможность использования Caldav4j.

Он поддерживает:

  • простая генерация запросов отчетов
  • на основе httpclient 3.0
  • приложение для андроид
  • в настоящее время переходит на jackrabbit
person Roberto Polli    schedule 28.02.2011