0

I am sending a POST request using the volley library on android. Once I get the json response the server is sending back a cookie in the headers. I can see the cookie when I check the network traffic using the profiler in android studio.

I need to be able to get the cookie from the header and assign it to a variable so that I can pass it to the next activity.

I have looked at Using cookies with Android volley library and how to get cookies from volley response

They are both several years old and I was unable to get them to work. I am not sure if it is because they use a GET request and mine is a POST request.

Is there a simple way to get the cookie from the server response?

This is the code that I currently have in place, all is well except for grabbing the cookie.

 JsonObjectRequest postRequest = new JsonObjectRequest(Request.Method.POST, cartUrl, jsonParams,
            new Response.Listener<JSONObject>() {
                @Override
                public void onResponse(JSONObject response) {

                    //Obviously this will not work becuase .getCookie() requires a url as a parameter
                    //There must be a method something like this to capture the response and get the cookie.
                    String chocolateChip = CookieManager.getInstance().getCookie(response);

                    startActivity(postIntent);

                }
            }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {

        }
    });

    postRequestQue.add(postRequest);

}
codeKracken
  • 127
  • 14

3 Answers3

1

Did you check this answer in the same question? It is an accepted answer and shows the implementation required to capture cookies from the response and later send them by adding cookies in subsequent requests.

Also, please check the following screenshot. I have taken it from this link. Cookies

EDITED: I understand the issue. Can you please try this answer. The following link explains the usage of cookies for HttpURLConnection https://developer.android.com/reference/java/net/HttpURLConnection#sessions-with-cookies

CookieManager cookieManager = new CookieManager();
CookieHandler.setDefault(cookieManager);

You can also try adding the following arguments to CookieManager constructor to accept all cookies:

CookieHandler.setDefault(new CookieManager(null, CookiePolicy.ACCEPT_ALL));
Mohit Ajwani
  • 1,328
  • 12
  • 24
  • I appreciate you looking into this however none of those methods work. AbstractHttpClient is a class that I do not have or do not know how to get and HttpClientStack is deprecated. Most of the answers that I can find are several years old from year 2013 or older sometimes. I can not seem to find any up to date information. – codeKracken Feb 17 '19 at 16:22
  • Hey @codeKracken, I have updated my answer. Please let me know if this helps. – Mohit Ajwani Feb 18 '19 at 10:19
  • @ Mohit Ajwani I appreciate your help however, these are not working at all. This seems to get close String rawCookies = responseHeaders.get("Set-Cookie"); But for some reason is not capturing the correct cookie. – codeKracken Feb 20 '19 at 17:25
1

Output: (URL: https://www.secureserver.net/api/v1/cart/508688?redirect=false)

Note: Please try with a privateLabelId as the following output is a result of an HTTP 400 request

{
  "error": {
    "statusCode": 400,
    "name": "invalid-product",
    "message": "Bad Request. Invalid {productId} in {items}"
  }
}

Headers

com.example.test E/MainActivity: Name Access-Control-Allow-Credentials Value true
com.example.test E/MainActivity: Name Cache-Control Value max-age=0, no-cache, no-store
com.example.test E/MainActivity: Name Connection Value close
com.example.test E/MainActivity: Name Content-Length Value 109
com.example.test E/MainActivity: Name Content-Type Value application/json; charset=utf-8
com.example.test E/MainActivity: Name Date Value Thu, 21 Feb 2019 06:09:34 GMT
com.example.test E/MainActivity: Name Expires Value Thu, 21 Feb 2019 06:09:34 GMT
com.example.test E/MainActivity: Name P3P Value CP="IDC DSP COR LAW CUR ADM DEV TAI PSA PSD IVA IVD HIS OUR SAM PUB LEG UNI COM NAV STA"
com.example.test E/MainActivity: Name Pragma Value no-cache
com.example.test E/MainActivity: Name Server Value nginx
com.example.test E/MainActivity: Name Vary Value Origin, Accept-Encoding
com.example.test E/MainActivity: Name X-Android-Received-Millis Value 1550729374476
com.example.test E/MainActivity: Name X-Android-Response-Source Value NETWORK 400
com.example.test E/MainActivity: Name X-Android-Selected-Protocol Value http/1.1
com.example.test E/MainActivity: Name X-Android-Sent-Millis Value 1550729373659
com.example.test E/MainActivity: Name X-ARC Value 102
com.example.test E/MainActivity: Name X-Content-Type-Options Value nosniff
com.example.test E/MainActivity: Name X-Download-Options Value noopen
com.example.test E/MainActivity: Name X-Frame-Options Value DENY
com.example.test E/MainActivity: Name X-XSS-Protection Value 1; mode=block

class VolleyJsonRequest

import android.util.Log;
import android.support.annotation.Nullable;

import com.android.volley.Header;
import com.android.volley.NetworkResponse;
import com.android.volley.ParseError;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.HttpHeaderParser;
import com.android.volley.toolbox.JsonRequest;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;

class VolleyJsonRequest {
    private ResponseListener listener;
    private int method;
    private String url;
    private List<Header> headers = new ArrayList<>();
    private JSONObject body;
    private int statusCode;

    private static final String TAG = VolleyJsonRequest.class.getSimpleName();

    public VolleyJsonRequest(int method, String url, JSONObject body, ResponseListener listener) {
        this.listener = listener;
        this.method = method;
        this.url = url;
        this.body = body;

    }

    public Request get() {
        return new Request(method, url, body.toString(), responseListener, errorListener);
    }

    Response.Listener<String> responseListener = new Response.Listener<String>() {
        @Override
        public void onResponse(String response) {
            deliverResult(response);
        }
    };

    Response.ErrorListener errorListener = new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            statusCode = error.networkResponse.statusCode;
            headers.addAll(error.networkResponse.allHeaders);
            String json;
            try {
                json = new String(
                        error.networkResponse.data,
                        HttpHeaderParser.parseCharset(error.networkResponse.headers));
                deliverResult(json);
            } catch (
                    UnsupportedEncodingException e) {
                Log.e(TAG, Log.getStackTraceString(e));
            }
        }
    };


    private void deliverResult(String response) {
        try {
            Object object = new JSONTokener(response).nextValue();
            if (object instanceof JSONObject) {
                listener.onResponse(statusCode, headers, (JSONObject) object, null);
            } else {
                listener.onResponse(statusCode, headers, null, (JSONArray) object);
            }
        } catch (JSONException e) {
            Log.e(TAG, Log.getStackTraceString(e));
        }
    }


    class Request extends JsonRequest {

        public Request(int method, String url, @Nullable String requestBody, Response.Listener listener, @Nullable Response.ErrorListener errorListener) {
            super(method, url, requestBody, listener, errorListener);
        }

        @Override
        protected Response parseNetworkResponse(NetworkResponse response) {
            headers.addAll(response.allHeaders);
            statusCode = response.statusCode;
            String string;
            try {
                string = new String(
                        response.data,
                        HttpHeaderParser.parseCharset(response.headers));
            } catch (
                    UnsupportedEncodingException e) {
                return Response.error(new ParseError(e));
            }

            return Response.success(
                    string,
                    HttpHeaderParser.parseCacheHeaders(response));

        }
    }

    public interface ResponseListener {
        void onResponse(int statusCode, List<Header> headers, JSONObject object, JSONArray array);
    }

}

Test:

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;

import com.android.volley.Header;
import com.android.volley.NetworkResponse;
import com.android.volley.ParseError;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.HttpHeaderParser;
import com.android.volley.toolbox.JsonRequest;
import com.android.volley.toolbox.Volley;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.UnsupportedEncodingException;
import java.util.List;

public class MainActivity extends AppCompatActivity implements VolleyJsonRequest.ResponseListener {

    private static final String TAG = MainActivity.class.getSimpleName();
    private RequestQueue queue;

    String requestBody = "{\n" +
            "  \"items\": [\n" +
            "    {\n" +
            "      \"id\": \"string\",\n" +
            "      \"domain\": \"string\"\n" +
            "    }\n" +
            "  ],\n" +
            "  \"skipCrossSell\": true\n" +
            "}";
    String url = "https://www.secureserver.net/api/v1/cart/508688?redirect=false";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        queue = Volley.newRequestQueue(this);
        testOne();
        testTwo();
    }

    private void testOne(){
        JsonRequest request = new JsonRequest(Request.Method.POST, url, requestBody, new Response.Listener() {
            @Override
            public void onResponse(Object response) {
                Log.e(TAG,"Response " + response.toString());
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {

                try {
                    String response = new String(
                            error.networkResponse.data,
                            HttpHeaderParser.parseCharset(error.networkResponse.headers));

                    Log.e(TAG,error.networkResponse.allHeaders.toString());
                    Log.e(TAG,response);

                } catch (UnsupportedEncodingException e) {
                    Log.e(TAG,e.getMessage());
                }
            }
        }) {
            @Override
            protected Response parseNetworkResponse(NetworkResponse response) {
                try {


                    List<Header> headers = response.allHeaders;
                    for(Header header: headers){
                        Log.e(TAG,"Name " + header.getName() + " Value " + header.getValue());
                    }

                    String json = new String(
                            response.data,
                            HttpHeaderParser.parseCharset(response.headers));
                    return Response.success(
                            new JSONObject(json),
                            HttpHeaderParser.parseCacheHeaders(response));
                } catch (UnsupportedEncodingException e) {
                    return Response.error(new ParseError(e));
                } catch (JSONException e) {
                    return Response.error(new ParseError(e));
                }
            }
        };

        queue.add(request);
    }

    private  void testTwo(){

        VolleyJsonRequest jsonRequest = null;
        try {
            jsonRequest = new VolleyJsonRequest(Request.Method.POST,url, new JSONObject(requestBody),this);
            queue.add(jsonRequest.get());
        } catch (JSONException e) {
            e.printStackTrace();
        }


    }

    @Override
    public void onResponse(int statusCode, List<Header> headers, JSONObject object, JSONArray array) {


        Log.e(TAG,"-------------------------------");

        for(Header header: headers){
            Log.e(TAG,"Name " + header.getName() + " Value " + header.getValue());
        }


        if (object != null){
            // handle your json object
        }else if (array != null){
            // handle your json array
        }
    }
}

I tried two ways i.e. testOne and testTwo. both are working fine. testOne is pretty straight forward for testTwo i've created a VolleyJsonRequest class. You don't need this class if you are using the testOne method. this class is created just for the comfort/ease to use a common class structure in your project. This class encapsulate actual request and provides a custom interface via which you get the response. it has two special variables i.e. object and array. one of these will be null in case of a valid json response. which variable will be null depends upon the response sent by Server.

Sahil Manchanda
  • 9,812
  • 4
  • 39
  • 89
  • You are a boss! Finally after weeks of experimenting and searching this finally works. – codeKracken Feb 21 '19 at 22:30
  • I do have one more question though if you have a simple solution. I am trying to get the Set-Cookie name that starts with ShopperID. Right now I am using String chocolateChip = string.valueOf(headers.get(11));String trimedCookie = chocolateChip.substring(29, chocolateChip.length()-1); Seems there should be a simpler method. – codeKracken Feb 21 '19 at 22:31
  • I used your testone() method by the way. Thanks again I really appreciate the help you have provided. – codeKracken Feb 21 '19 at 22:32
  • @codeKracken, see if that helps String s = headers.get(11).getValue().split("textyouwanttoskip")[1]; – Sahil Manchanda Feb 22 '19 at 04:15
  • Thank you that is very helpful. I am very grateful for all the help you have provided. – codeKracken Feb 22 '19 at 19:27
0

Try this -

            @Override
            public String getBodyContentType() {
                return "application/json";
            }

            @Override
                protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
                    // since we don't know which of the two underlying network vehicles
                    // will Volley use, we have to handle and store session cookies manually
                    Log.i("response",response.headers.toString());
                    Map<String, String> responseHeaders = response.headers;
                    String rawCookies = responseHeaders.get("Set-Cookie");
                    Log.i("cookies",rawCookies);
                    prefLogin.setSessionId(rawCookies); // save your cookies using shared prefernece
                    return super.parseNetworkResponse(response);
                }
codeKracken
  • 127
  • 14
Asteroid
  • 718
  • 7
  • 21
  • Thanks this is getting close but it returns I/cookies: currency=USD; Domain=secureserver.net; Path=/; Expires=Wed, 19 Feb 2020 00:24:38 GMT and does not return the full cookie, most importantly I am trying to capture the cookie ShopperId508688=somerandomestringgoeshere; – codeKracken Feb 19 '19 at 00:27
  • Thank you for the suggestion but the rawCookies is coming back without the actual cookie from the header. – codeKracken Feb 20 '19 at 17:23