Manually set a cookie in default cookiestore and using it in okhttp requests
Asked Answered
T

1

5

In my android application, I am migrating to okhttp and need to setup the PHPSESSID manually for logged-in users in the default cookieStore, so that they don't get logged out. I am manually setting the cookie using the following code.

((CookieManager)client.getCookieHandler()).getCookieStore().add(new URI("http://www.example.com"), new HttpCookie("PHPSESSID", getPhpSessionID()));

The cookie seems to be set cause I can get the cookie back using this code

((CookieManager)client.getCookieHandler()).getCookieStore().get(new URI("http://www.example.com"));

However, when I am executing the client call using

Request request = new Request.Builder().url("http://www.example.com/getdata.php").build(); 
client.newCall(request).execute();

The cookies are not being sent in the request (verified this network call using android proxy).

Whats the correct way to set such a cookie so that okhttp client uses that cookie?

Tricia answered 23/9, 2014 at 20:58 Comment(1)
I have the exact same issue, and the answer doesn't help me. Did you get the result?Angular
D
7

There seem to be a difference between the CookieHandler's put implementation of the CookieManager and the CookieStore's add method.

By default if you use the put from the CookieManager it will add the domain and the path to the HttpCookie created internally by the implementation. This will not happen if you use the CookieStore's add method directly as you're the one responsible for creating the HttpCookie.

As it turns out OkHttp uses the get from the implementation which in your case will be CookieManager and not the CookieStore directly. That get will also use the path to match the cookie which in your case will be missing.

If you don't provide the expected default path of "/" to your HttpCookie your cookie will not be found.

You should then modify your HttpCookie like so

HttpCookie cookie = new HttpCookie("PHPSESSID", getPhpSessionID());
cookie.setPath("/");
cookie.setVersion(0);
cookie.setDomain("www.example.com");
((CookieManager)client.getCookieHandler()).getCookieStore().add(new URI("http://www.example.com"), cookie);

Or to allow your solution to be more adaptable in the chance that you change CookieHandler implementation you could use the interface only instead of getting access to the CookieStore

You would accomplish this like so

List<String> values = new ArrayList<>(Arrays.asList("PHPSESSID=" + "your_session_id_here"));
Map<String, List<String>> cookies = new HashMap<>();
cookies.put("Set-Cookie", values);
client.getCookieHandler().put(new URI("http://www.example.com"), cookies);
Drank answered 24/9, 2014 at 19:28 Comment(6)
Great. Your 2nd solution worked. However the 1st one didnt. okhttp still refused to set the cookie when sending network requests in this case.Tricia
Well I'm glad at least one of them worked. I'm curious why the 1st didn't do anything for you.Drank
In your first solution, by removing "http://" from the domain and adding cookie.setDomain("www.example.com"); Instead of the usual cookie, Cookie: PHPSESSID=fq01rjn8f8jgotrf7egvcf7mu4 The value that was set was this Cookie: $Version="1"; PHPSESSID="fq01rjn8f8jgotrf7egvcf7mu4";$Path="/";$Domain="www.example.com". The server php file was not able to identify this cookie as a valid sessionid cookie.Tricia
@Tricia try setting setVersion(0) on your HttpCookie when creating it. I think it's defaulting to version 1 and that might be the root cause of this.Drank
That did it perfectly. Removing http:// and using setDomain('www.example.com') and setVersion(0), The network request are being sent as expected. Thanks.Tricia
Unfortunately I can't send cookies using both of your methods. I don't know what might be wrong. I found out that client.getCookieHandler() returns null, thus I check it first and create a new CookieManager before using your code.Angular

© 2022 - 2024 — McMap. All rights reserved.