androidcookieshttp-postandroidhttpclientandroid-cookiemanager

Android is ignoring cookies in my HTTP POST


My app does HTTP POSTS, in general the app works, but I am having trouble with the cookies. My code seems to get the cookies fine, through the HttpClient variable and out, but the results of the POST reveal that my app (as a client), is not remembering anything. (When I use a webbroswer in my pc, it works fine, the cookies remember my name) Also, if the app is restarted, the cookies disappear (...but first things first)

This is my code:

static DefaultHttpClient httpclient;
static HttpPost httppost;
static CookieStore cookiestore;

new Thread(new Runnable() {
        public void run() {

            String URI_FOR_DOMAIN="http://chatbot.t.com/cgi-bin/elbot.cgi";

            httppost = new HttpPost(URI_FOR_DOMAIN);
            try {
                HttpResponse resp = httpclient.execute(httppost);
            } catch (IOException e) {
                e.printStackTrace();
            }

            cookiestore = ((DefaultHttpClient) httpclient).getCookieStore();
            List<Cookie> list = cookiestore.getCookies();
            app.logy("COOKIE STORE 1: " + cookiestore.toString());
            app.logy("COOKIE LIST  1: "+list.toString());
            for (int i=0;i<list.size();i++) {
                Cookie cookie = list.get(i);
                app.logy("COOKIE "+i+": "+cookie.toString());
            }

            HttpContext context = new BasicHttpContext();
            context.setAttribute(  ClientContext.COOKIE_STORE, cookiestore);

            httppost = new HttpPost(url);
            try {
                // Add your data
                List<NameValuePair> nameValuePairs = new ArrayList<>(2);
                nameValuePairs.add(new BasicNameValuePair("ENTRY", userInput));
                nameValuePairs.add(new BasicNameValuePair("IDENT", userIDENT));
                nameValuePairs.add(new BasicNameValuePair("USERLOGID", userLOGID));
                httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));

                // Execute HTTP Post Request
                app.logy("COOKIE STORE 2: "+cookiestore.toString());
                app.logy("COOKIE CONTEXT: " + context.toString());
                HttpResponse response = httpclient.execute(httppost, context);

                cookiestore = ((DefaultHttpClient) httpclient).getCookieStore();
                List<Cookie> list2 = cookiestore.getCookies();
                app.logy("COOKIE STORE 2: " + cookiestore.toString());
                app.logy("COOKIE LIST  2: "+list2.toString());
                for (int i=0;i<list2.size();i++) {
                    Cookie cookie = list2.get(i);
                    app.logy("COOKIE2 i="+i+": "+cookie.toString());
                }

                HttpEntity entity = response.getEntity();
}


                    }
                    app.logy(sb.toString());
                }
                catch (IOException e) { e.printStackTrace(); }
                catch (Exception e) { e.printStackTrace(); }


            } catch (ClientProtocolException e) {
                app.logy("HttpPOST (ClientProtocol) error: "+e);
            } catch (IOException e) {
                app.logy("HttpPOST (I/O) error: "+e);
            }

        }
    }).start();

This are the values that are reflected in the Logcats from the above code. The cookies seem to be there, but HttpResponse response = httpclient.execute(httppost, context); seems to ignore them.

COOKIE STORE 2: [[version: 0][name: cookie_user_name][value: Albert][domain: elbot-e.artificial-solutions.com][path: /][expiry: Thu Oct 08 22:26:54 GMT+02:00 2015]]
COOKIE LIST  2: [[version: 0][name: cookie_user_name][value: Albert][domain: elbot-e.artificial-solutions.com][path: /][expiry: Thu Oct 08 22:26:54 GMT+02:00 2015]]
COOKIE2 i=0: [version: 0][name: cookie_user_name][value: Albert][domain: elbot-e.artificial-solutions.com][path: /][expiry: Thu Oct 08 22:26:54 GMT+02:00 2015]

Solution

  • First off you should be using an AsyncTask for any kind of api calls. Creating separate threads works, but is bad practice and not the android way. Second, in your api call use HttpUrlConnection instead of HTTPPost. It is the new way to do api interactions. Try both those things and see what happens with your cookie problem.

    EDIT by @Josh: It turns out @cj1090 sent me in the right direction with his recommendation, so I will edit his answer to add the implementation and mark it as green. As he recommended, I changed strategy and implemented an AsyncTask based in HttpURLConnection instead of a Thread+HTTPpost solution. The code works perfectly and the cookies are handled internally by the HttpURLConnection object. However, the cookies disappear if the app is destroyed, but that is a topic for another day. Enjoy the code! BASE_URL is a vintage HTML website url, and the user communicates to it by sending a string into params[0]:

      //Call the AsyncTask like this:
    final String BASE_URL = "http://elba.artisol.com/cgi/bot.cgi";
    String fromUserTextbox="hello"
    new elbotHttpTask().execute(url);
    
    
       public class elbotHttpTask extends AsyncTask<String, Void, Integer> {
    
            @Override
            protected Integer doInBackground(String... params) {
                InputStream inputStream = null;
                HttpURLConnection urlConnection = null;
                Integer result = 0;
                try {
                    URL obj = new URL(BASE_URL);
                    HttpURLConnection con = (HttpURLConnection) obj.openConnection();
                    con.setRequestMethod("POST");
                    con.setDoInput(true);
                    con.setDoOutput(true);
                    //con.setRequestProperty("User-Agent", USER_AGENT);
    
                    app.userInput=params[0];
    
                    List<NameValuePair> parameters = new ArrayList<NameValuePair>();
                    parameters.add(new BasicNameValuePair("ENTRY", params[0]));
                    parameters.add(new BasicNameValuePair("IDENT", app.sessionIDENT));
                    parameters.add(new BasicNameValuePair("USERLOGID", app.sessionUSERLOGID));
    
    
                    // For POST only - START
                    app.logy("pp.getQuery(parameters): "+app.getQuery(parameters));
                    OutputStream os = con.getOutputStream();
                    BufferedWriter writer = new BufferedWriter(
                            new OutputStreamWriter(os, "UTF-8"));
                    writer.write(app.getQuery(parameters));
                    writer.flush();
                    writer.close();
                    os.close();
    
                    con.connect();
    
                    int responseCode = con.getResponseCode();
                    System.out.println("POST Response Code :: " + responseCode);
    
                    if (responseCode == HttpURLConnection.HTTP_OK) { //success
                        BufferedReader in = new BufferedReader(new InputStreamReader(
                                con.getInputStream()));
                        String inputLine;
                        StringBuffer response = new StringBuffer();
    
                        while ((inputLine = in.readLine()) != null) {
                            response.append(inputLine);
                        }
                        in.close();
                        consumeHTMLresponse(response.toString());
                        result = 1;
                    } else {
                        System.out.println("POST request not worked");
                        result = 0;
                    }
                } catch (Exception e) {
                    app.logy(e.getLocalizedMessage());
                }
                return result; //"Failed to fetch data!";
            }
    
    
    
            @Override
            protected void onPostExecute(Integer result) {
                if(result == 1){
                    app.logy("onPostEXECUTE SUCCESS");
                }else{
                    app.logy("Failed to fetch data!");
                }
            }
        }