Trying to use Volley lib as a network wrapper for my android application. I have a connection up and running, but the problem is that every time there is multiple "Set-Cookie" headers in the response Volley uses Map that cannot have duplicate keys, and will only store the last Set-cookie header and overwrite the rest.
Is there a workaround for this issue?
Is there another lib to use?
I tried overiding classes to fix this but when I had to edit NetworkResponse, I was descending too far down the rabbithole. So I decided to just edit Volley directly to grab all response headers in an array and not a Map.
My fork is on GitHub and I included an example usage activity.
I made changes to NetworkResponse.java, BasicNetwork.java and HurlStack.java as detailed in this commit.
Then to use in your actual apps 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);
}
It's a dirty little hack but seems to work well for me at the moment.
The first thing you need is to modify BasicNetwork.convertHeaders method to make it support multiple map values. Here is example of 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;
}
Next thing you need is to modify DiskBasedCache.writeStringStringMap and DiskBasedCache.readStringStringMap methods. They should support multiple values. Here are modified methods along with 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 last thing is HttpHeaderParser class. You should make its parseCacheHeaders method support multiple values. Use the following helper method for this:
public static String getHeaderValue(List<String> list) {
if ((list == null) || list.isEmpty()) return null;
return list.get(0);
}
And the latest thing to modify is a bunch of places to replace
Map<String, String>
to
Map<String, List<String>>
Use your IDE to do this.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With