2013-09-25 77 views
19

嘗試使用Volley lib作爲我的android應用程序的網絡包裝。我有一個連接並正在運行,但問題是每次在響應中有多個「Set-Cookie」標題時,Volley使用的Map不能有重複的鍵,並且只會存儲最後一個Set-cookie標題並覆蓋其餘。Android Volley,重複Set-Cookie被覆蓋

是否有解決此問題的方法?

是否有另一個使用的lib?

+2

只要注意到這一點,這對Google來說是荒謬的。很明顯,這個庫是用於非常輕量級的東西。 – georgiecasey

+0

它不是Android Volley的問題。它是Web服務器的一個問題。 Set-Cookie不能是多個。 http://stackoverflow.com/questions/11533867/set-cookie-header-with-multiple-cookies –

+0

http://stackoverflow.com/a/25388897/2819864是最快的解決方案 – RominaV

回答

16

我嘗試了過度類來解決這個問題,但是當我不得不編輯NetworkResponse時,我的下拉距離太遠了。所以我決定直接編輯Volley來獲取數組中的所有響應頭,而不是Map。

我的叉子在GitHub,我包括一個example usage activity

我對NetworkResponse.java,BasicNetwork.java和HurlStack.java進行了更改,詳見this commit

然後在您的實際應用使用你做這樣的事情

protected Response<String> parseNetworkResponse(NetworkResponse response) { 
      // we must override this to get headers. and with the fix, we should get all headers including duplicate names 
      // in an array of apache headers called apacheHeaders. everything else about volley is the same 
      for (int i = 0; i < response.apacheHeaders.length; i++) { 
       String key = response.apacheHeaders[i].getName(); 
       String value = response.apacheHeaders[i].getValue(); 
       Log.d("VOLLEY_HEADERFIX",key + " - " +value); 
      } 

      return super.parseNetworkResponse(response); 
     } 

這是一個骯髒的小技巧,但似乎爲我的時刻很好地工作。

+1

我很驚訝這還沒有在官方發佈。你知道爲什麼嗎? –

1

您可以覆蓋Network排球類。查看BasicNetwork的performRequest和convertHeaders方法可能會有所幫助。然後,將您的網絡實現傳遞給RequestQueue的構造器,如下所示:

new RequestQueue(new NoCache(),new YourOwnNetwork());

+0

嗨@Kazuki,你可以把並舉例說明?我用perfomRequest創建了自己的Network(CustomNetwork)接口。然後我修改它的實現,但我不能在新的RequestQueue(...)中傳遞CustomNetwork。你可以幫幫我嗎? –

3

您需要的第一件事是修改BasicNetwork.convertHeaders方法使其支持多個地圖值。下面是例子,改裝方法:

protected static Map<String, List<String>> convertHeaders(Header[] headers) { 
    Map<String, List<String>> result = new TreeMap<String, List<String>>(String.CASE_INSENSITIVE_ORDER); 
    for (int i = 0; i < headers.length; i++) { 
     Header header = headers[i]; 
     List<String> list = result.get(header.getName()); 
     if (list == null) { 
      list = new ArrayList<String>(1); 
      list.add(header.getValue()); 
      result.put(header.getName(), list); 
     } 
     else list.add(header.getValue()); 

    } 
    return result; 
} 

你需要接下來的事情就是修改DiskBasedCache.writeStringStringMapDiskBasedCache.readStringStringMap方法。他們應該支持多種價值。以下是改進方法與輔助方法一起:

static void writeStringStringMap(Map<String, List<String>> map, OutputStream os) throws IOException { 
    if (map != null) { 
     writeInt(os, map.size()); 
     for (Map.Entry<String, List<String>> entry : map.entrySet()) { 
      writeString(os, entry.getKey()); 
      writeString(os, joinStringsList(entry.getValue())); 
     } 
    } else { 
     writeInt(os, 0); 
    } 
} 

static Map<String, List<String>> readStringStringMap(InputStream is) throws IOException { 
    int size = readInt(is); 
    Map<String, List<String>> result = (size == 0) 
      ? Collections.<String, List<String>>emptyMap() 
      : new HashMap<String, List<String>>(size); 
    for (int i = 0; i < size; i++) { 
     String key = readString(is).intern(); 
     String value = readString(is).intern(); 
     result.put(key, parseNullStringsList(value)); 
    } 
    return result; 
} 

static List<String> parseNullStringsList(String str) { 
    String[] strs = str.split("\0"); 
    return Arrays.asList(strs); 
} 

static String joinStringsList(List<String> list) { 
    StringBuilder ret = new StringBuilder(); 
    boolean first = true; 
    for (String str : list) { 
     if (first) first = false; 
     else ret.append("\0"); 
     ret.append(str); 
    } 
    return ret.toString(); 
} 

而最後一件事是HttpHeaderParser類。您應該使其parseCacheHeaders方法支持多個值。使用此以下的輔助方法:

public static String getHeaderValue(List<String> list) { 
    if ((list == null) || list.isEmpty()) return null; 
    return list.get(0); 
} 

並修改最新的東西是一堆的地方,以取代

Map<String, String> 

Map<String, List<String>> 

使用您的IDE來做到這一點。

+0

Hi @ ruslan-yanchyshyn,你可以把完整的代碼看看這個例子嗎?我試圖按照你的步驟,但是當我嘗試重寫BasicNetwork時,我有很多依賴關係。你可以幫幫我嗎? –

0

問題相當古老,但如果幫助某人。在最新的排球中你有:

protected Response<String> parseNetworkResponse(NetworkResponse response) 
{ 
    List<Header> headers = response.allHeaders; 

    String sessionId = null; 

    for (Header header : headers) 
    { 
     // header.getName(); 
     // header.getValue(); 
    } 

    return super.parseNetworkResponse(response); 
}