Problem description
Recently took over a forum nature of the application, because the traffic is small, network requests frequently, so choose to use volley for refactoring. Because the default volley only reads a cookie, and the item uses 4 cookies, the user login section first uses the original httpclient to save the user's login cookie information.
Refactoring to get and send content part of the refactoring basically can be completed, only the cookie problem, the Internet to find a lot of information, found that many are one-sided, in fact, said the wrong.
Methods found online (does not solve the problem)
Sometimes the server will return multiple Set-cookie values, and volley default only to take the first, if there is a demand, it is necessary to modify volley code, Hurlstack (Sdk_int>9 will walk here) performrequest inside, The default parsing header mode is as follows, multiple values only need to get Header.getvalue (). Get (1) and so on, the specific requirements can be modified by themselves.
new BasicHeader(header.getKey(), header.getValue().get(0));response.addHeader(h);
Above is the online search method, in fact, only said the first step, there is a need to pay attention to the place. But the idea of solving the problem is right:
1. Rewrite or inherit one HurlStack and performRequest() add the cookie to response in the method.
2. Define a model that contains the contents of the request return and a list of cookies.
3. Rewrite a return object is the request of our model above, and in the request parseNetworkResponse method, put the obtained cookie into the model.
There is a little extra attention here, which is not explained in the above method:
In our HurlStack performRequest return is a HttpResponse (header is a list), our cookie is also added to its headers inside. There is no problem at the moment. But the response returned here also undergoes a conversion, because the Request class protected abstract Response<T> parseNetworkResponse(NetworkResponse paramNetworkResponse); parameter is one NetworkResponse , the headers is one Map<String, String> , so this requires that our multiple cookie key cannot be Set-Cookie . Because the cookie in the above code header.getKey() is generally Set-Cookie .
Here are some of the source code:
HurlStack.class
public HttpResponse performrequest (Request<?> Request, map<string, string> additionalheaders) throws IOException, Authfailureerror {... Basichttpresponse response = new basichttpresponse (responsestatus); Response.setentity (Entityfromconnection (connection)); for (Map.entry<string, List<string>> header:connection.getHeaderFields (). EntrySet ()) {if (Header.getkey ()! = null ) {Head Er h = new basicheader ((String) Header.getkey (), (String) ((List) Header.getvalue ()) . Get (0 )); Response.AddHeader (h); }} return response; }
BasicNetwork.class
privatestaticconvertHeaders(Header[] headers) { new HashMap(); for (int0; i < headers.length; i++) { result.put(headers[i].getName(), headers[i].getValue()); } return result; }
My way out.
Key code:
MyHurlStack.class
PublicHttpResponseperformrequest(Request<?> Request, map<string, string> additionalheaders)throwsIOException, authfailureerror {String url = request.geturl (); HashMap map =NewHashMap (); Map.putall (Request.getheaders ()); Map.putall (additionalheaders);if( This. murlrewriter! =NULL) {String Parsedurl = This. Murlrewriter.rewriteurl (URL);if(Parsedurl = =NULL) {Throw NewIOException ("URL blocked by rewriter:"+ URL); } URL = parsedurl; } URL PARSEDURL1 =NewURL (URL); HttpURLConnection connection = This. OpenConnection (PARSEDURL1, request); Iterator responsecode = Map.keyset (). Iterator (); while(Responsecode.hasnext ()) {String protocolversion = (string) responsecode.next (); Connection.addrequestproperty (ProtocolVersion, (String) Map.get (protocolversion)); } setconnectionparametersforrequest (connection, request); ProtocolVersion ProtocolVersion1 =NewProtocolVersion ("HTTP",1,1);intResponseCode1 = Connection.getresponsecode ();if(ResponseCode1 = =-1) {Throw NewIOException ("Could not retrieve response code from HttpURLConnection."); }Else{Basicstatusline ResponseStatus =NewBasicstatusline (ProtocolVersion1, Connection.getresponsecode (), Connection.getresponsemessage ()); Basichttpresponse response =NewBasichttpresponse (ResponseStatus); Response.setentity (Entityfromconnection (connection)); for(Object o:connection.getheaderfields (). EntrySet ()) {Entry Header = (Entry) o;if(Header.getkey ()! =NULL) {//If it is a Cookie, save it as name = Set-cookie + serial number to ensure that key is different if(Header.getkey (). Equals ("Set-cookie") {List headerlist = (list) header.getvalue (); for(inti =0; I < headerlist.size (); i++) {Basicheader h =NewBasicheader (String) header.getkey () + I, (string) headerlist.get (i)); Response.AddHeader (h); } }Else{List headerlist = (list) header.getvalue (); for(Object aheaderlist:headerlist) {Basicheader h =NewBasicheader (String) Header.getkey (), (string) aheaderlist); Response.AddHeader (h); } } } }returnResponse } }
MyRequest.class
//Use regular expressions to extract the substring of the cookie content from the header of the reponse Private Static FinalPattern pattern = Pattern.compile ("set-cookie\\d*");@Override protectedResponse<myresponse>Parsenetworkresponse(Networkresponse networkresponse) {Try{Myresponse response =NewMyresponse (); String jsonstring =NewString (Networkresponse.data, Httpheaderparser.parsecharset (networkresponse.headers)); Response.setjsonstring (jsonstring);//Get All Cookieslist<cookie> cookies =NewArraylist<> (); for(String Key:networkResponse.headers.keySet ()) {Matcher Matcher = Pattern.matcher (key);if(Matcher.find ()) {cookiefromresponse = NetworkResponse.headers.get (key); Cookiefromresponse = cookiefromresponse.substring (0, Cookiefromresponse.indexof (";")); String keyvalue[] = Cookiefromresponse.split ("=", -1); Cookie cookie =NewBasicclientcookie (keyvalue[0], keyvalue[1]); Cookies.add (cookie); }} response.setcookies (cookies);returnResponse.success (Response, Httpheaderparser.parsecacheheaders (Networkresponse)); }Catch(Unsupportedencodingexception e) {returnResponse.error (NewParseError (e)); } }
MyResponse.class
Public class myresponse{ Private StaticString TAG ="Myresponse";Private intStatus =0;PrivateString jsonstring ="";Privatelist<cookie> cookies =NewArraylist<> (); Public int GetStatus() {returnStatus } Public void SetStatus(intStatus) { This. Status = Status; } PublicStringgetjsonstring() {returnjsonstring; } Public void setjsonstring(String jsonstring) { This. jsonstring = jsonstring; } PublicList<cookie>getcookies() {returnCookies } Public void setcookies(List<cookie> Cookies) { This. cookies = cookies; }}
VolleyHelper.class
publicstaticvoidinit(Context context) { new MyHurlStack()); }
Postscript
At the beginning of the online method just changed the contents of the hurlstack inside, and finally can only get a cookie, here is generally thought to be the reason for the map. Finally find source discovery is really the reason, and then use a stupid method to solve the problem. So according to the source code to analyze and solve the problem is very necessary.
This method just according to our current situation solves the problem, should not solve all the situation, here is just to provide a solution to the idea, if you have a better solution, please leave a message, discuss together.
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.
Use volley to get multiple cookies