可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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?
回答1:
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.
回答2:
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.
回答3:
You can override Network class of volley. Looking at performRequest and convertHeaders methods of BasicNetwork might help. Then, passing your Network implementation to the contructor of RequestQueue like:
new RequestQueue(new NoCache(), new YourOwnNetwork());
回答4:
Question pretty old, but if helps someone. In newest volley you have:
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); }