2010-08-11 33 views
5

HttpURLConnection只支持GET,POST和HEAD之類的東西 - 但沒有REPORT/PROPFIND。我要實現一個CalDAV-客戶端,但沒有這些操作(如果我想使用它們,我會得到一個ProtocolException),我必須使用auth等編寫/提供一個完整的大型HTTP庫。Java的HttpURLConnection不支持REPORT/PROPFIND - 我該怎麼辦?

「Overkill」。

如何使用PROPFIND和REPORT發送請求?

回答

3

你可能會想爲這個尋找一個WebDAV庫,而不是HTTP庫。

也許看看Apache Jackrabbit

+0

+1的鏈接兔崽子,雖然你發送的鏈接是在服務器端。這可能更直接相關:http://jackrabbit.apache.org/api/1.3/org/apache/jackrabbit/webdav/client/methods/package-summary.html – Bruno 2010-08-11 15:23:26

2

您可以嘗試使用另一個HTTP庫,例如Apache HTTP client並擴展它的HttpRequestBase(例如,請參閱HttpGetHttpPost)。

或者,您可以直接使用WebDAV客戶端庫。

0

考慮使用Caldav4j

它支持:基於

  • 易產生報告的要求
  • 的HttpClient 3.0
  • Android應用
  • 目前遷移到兔崽子
3

我在WebDav for 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); 

      } 
    } 
+1

很好的答案!但是,在我的情況下,httpURLConnection有一個委託,答案不起作用。因此我通過反射提取httpURLConnection對象的委託字段。委託字段也是HttpURLConnection的(sub sub)子類。我通過methodField = parentClass.getSuperclass()。getSuperclass()。getDeclaredField(「method」);來爲你的過程應用這個委託連接。這很好。謝謝! – KNaito 2015-01-04 03:44:31

+0

我嘗試了上面的解決方案,並因爲「http方法不允許」而出錯。你能否給我提供一些指示。我也看到httpURLConnection有一個委託,但是當我嘗試評論的解決方案時,我得到noSuchMethod錯誤。 – Dhamayanthi 2017-08-10 07:19:05

+0

@KNaito能否請你幫我解決這個問題,我使用的是JDK 1.7,並直接使用HttpURLConnection的 – Dhamayanthi 2017-08-22 12:04:51

3

要麼你可以使用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(); 
+0

的問題請不要[複製/粘貼](http://stackoverflow.com/a/35490228/189134 )多個問題的答案相同。而是定製個別問題的答案,並解釋他們如何解決特定問題。 – Andy 2016-02-19 03:57:59

+0

當然!感謝您的留言! – 2016-02-19 16:05:50

0
private static void setRequestMethod(HttpURLConnection conn, String method) throws Throwable { 
    try { 
     conn.setRequestMethod(method); 
    } catch (ProtocolException e) { 
     Class<?> c = conn.getClass(); 
     Field methodField = null; 
     Field delegateField = null; 
     try { 
      delegateField = c.getDeclaredField("delegate"); 
     } catch (NoSuchFieldException nsfe) { 

     } 
     while (c != null && methodField == null) { 
      try { 
       methodField = c.getDeclaredField("method"); 
      } catch (NoSuchFieldException nsfe) { 

      } 
      if (methodField == null) { 
       c = c.getSuperclass(); 
      } 
     } 
     if (methodField != null) { 
      methodField.setAccessible(true); 
      methodField.set(conn, method); 
     } 

     if (delegateField != null) { 
      delegateField.setAccessible(true); 
      HttpURLConnection delegate = (HttpURLConnection) delegateField.get(conn); 
      setRequestMethod(delegate, method); 
     } 
    } 
}