user2021938
user2021938

Reputation: 145

Accessing all response headers using volley api in android application

while making connection using HttpClient in android from HttpResponse able to get all possible "set-cookie" header value (JESSIONID and XSCRF-TOKEN).Check below screenshot. HttpResponse header

Now working with android studio with volley api for connection , i am getting only single value of "set-cookie" header (JESSIONID only).See below : Volley response header

I have also check https://groups.google.com/forum/#!topic/volley-users/rNTlV-LORzY. For which have to make change in volley api jar project. But don't know how to edit volley api. If any other solution present kindly guide.

Kindly help to retrieve multiple value of "set-cookie" using volley api.

Upvotes: 1

Views: 912

Answers (2)

Alexey
Alexey

Reputation: 4501

There is workaround for this in:

implementation "com.android.volley:volley:1.1.0"

"NetworkResponse (and Cache.Entry) now includes an "allHeaders" field which is the raw list of all headers returned by the server and thus can include duplicates by name."

Source: https://github.com/google/volley/issues/21

Example:

    private static final String COOKIE_KEY = "Set-Cookie";
    private static final String COOKIE_NAME = "NameOfOneOfTheCookies";

    @Override
    protected Response<String> parseNetworkResponse(NetworkResponse response) {
        handleCookies(response);
        String parsed;
        try {
            parsed = new String(response.data, "utf-8");
        } catch (UnsupportedEncodingException e) {
            parsed = new String(response.data);
        }
        return Response.success(parsed,
                HttpHeaderParser.parseCacheHeaders(response));
    }

    private void handleCookies(NetworkResponse response) {
        for (Header header : response.allHeaders) {
            if (header.getName().equals(COOKIE_KEY) && header.getValue().startsWith(COOKIE_NAME)) {
                getCookies(response);
            }
        }
    }

    private void getCookies(NetworkResponse response) {
        ArrayList<String> cookiesList = new ArrayList<>();
        for (Header header : response.allHeaders) {
            if (header.getName().equals(COOKIE_KEY)) {
                cookiesList.add(header.getValue());
            }
        }
        // TODO Do something with the cookiesList
    }

Upvotes: 1

Sepehr Behroozi
Sepehr Behroozi

Reputation: 1800

Problem:
The problem is inside the Volley unfortunately. I had this problem and after many searches i figured out that there is a method called convertHeaders in BasicNetwork class that handles headers like this:

protected static Map<String, String> convertHeaders(Header[] headers) {
    Map<String, String> result = new TreeMap<String, String>(String.CASE_INSENSITIVE_ORDER);
    for (int i = 0; i < headers.length; i++) {
        result.put(headers[i].getName(), headers[i].getValue());
    }
    return result;
}

You see the result is Map<String, String> which can't contain same keys with different values. so you always have only last cookie.
The standard of cookie setting tells us we should separate cookies with ; for example if you want to contain 2 key-value in a request cookie you should put them like this: Cookies: k1=v1;k2=v2

Solution:
In your case you have two options.

1 - change your code in Server-Side so that the response contains only 1 Set-Cookie separated key-values by ;. example of your response:

Set-Cookie: JESSIONID=qZtQ...;Path=/;HttpOnly;XSRF-TOKEN=6c65...

2 - get Volley source code and change that buggy method and make a fixed .jar again! this option is my favorite cause you didn't touch the response of server

My implementation of this method is:

protected static Map<String, String> convertHeaders(Header[] headers) {
    TreeMap result = new TreeMap(String.CASE_INSENSITIVE_ORDER);

    for(int i = 0; i < headers.length; ++i) {
        String headerName = headers[i].getName();
        if(!result.containsKey(headerName)) {
            result.put(headers[i].getName(), headers[i].getValue());
        } else {
            String value = (String)result.get(headerName);
            String mergedValue = value + ";" + headers[i].getValue();
            result.remove(headerName);
            result.put(headerName, mergedValue);
        }
    }

    return result;
}

Upvotes: 3

Related Questions