Android Volley duplicate Set-Cookie canceled

Trying to use Volley lib as a network shell for my Android application. I have a connection and it works, but the problem is that every time there are multiple "Set-Cookie" headers in the response, Volley uses a Map, which does not have duplicate keys, and will only store the last Set-cookie header and overwrite the rest .

Is there a workaround for this problem?

Is there any other lib to use?

+19
android adt android-volley setcookie
Sep 25 '13 at 7:04 on
source share
3 answers

I tried to override the classes to fix this, but when I had to edit NetworkResponse , I went too far down the tweet. So I decided to just edit Volley directly to capture all the response headers in the array, not in Map.

My fork is on GitHub , and I have included a usage example .

I made changes to NetworkResponse.java, BasicNetwork.java and HurlStack.java as described in this commit .

Then, for use in your real applications, you do something like this

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

This is a dirty little hack, but it seems to work fine for me now.

+16
Oct 30 '13 at 3:56 on
source share

First of all, you need to change the BasicNetwork.convertHeaders method to support multiple map values. Here is an example of a modified method:

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

The next thing you need to do is change the DiskBasedCache.writeStringStringMap and DiskBasedCache.readStringStringMap methods. They must support multiple values. The following are modified methods and helper methods:

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

And the last thing is the HttpHeaderParser class. You must force its parseCacheHeaders method to support multiple values. To do this, use the following helper method:

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

And the last thing to change is a bunch of places to replace

 Map<String, String> 

to

 Map<String, List<String>> 

Use this IDE.

+3
Mar 11 '15 at 10:33
source share

You can override the Network salvo class. Considering the executeRequest and convertHeaders BasicNetwork methods can help. Then, passing the implementation of your network to the contructor RequestQueue, for example:

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

+1
07 Oct '13 at 10:18
source share



All Articles