54

Using OkHttp by Square https://github.com/square/okhttp, how can I:

  1. Retrieve a cookie returned from the server
  2. Store the cookie for upcoming requests
  3. Use the stored cookie in subsequent requests
  4. Update the cookie returned by the subsequent request

Ideally the cookie would be stored, resent and updated automatically with every request.

Daniel
  • 541
  • 1
  • 5
  • 3

3 Answers3

75

For OkHttp3, a simple accept-all, non-persistent CookieJar implementation can be as follows:

OkHttpClient client = new OkHttpClient.Builder()
    .cookieJar(new CookieJar() {
        private final HashMap<HttpUrl, List<Cookie>> cookieStore = new HashMap<>();

        @Override
        public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
            cookieStore.put(url, cookies);
        }

        @Override
        public List<Cookie> loadForRequest(HttpUrl url) {
            List<Cookie> cookies = cookieStore.get(url);
            return cookies != null ? cookies : new ArrayList<Cookie>();
        }
    })
    .build();

Or if you prefer to use java.net.CookieManager, include okhttp-urlconnection in your project, which contains JavaNetCookieJar, a wrapper class that delegates to java.net.CookieHandler:

dependencies {
    compile "com.squareup.okhttp3:okhttp:3.0.0"
    compile "com.squareup.okhttp3:okhttp-urlconnection:3.0.0"
}

CookieManager cookieManager = new CookieManager();
cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
OkHttpClient client = new OkHttpClient.Builder()
    .cookieJar(new JavaNetCookieJar(cookieManager))
    .build();
hidro
  • 12,333
  • 6
  • 53
  • 53
  • So automatically saves and nothing I have to do? After restarting works? – Kamil Nękanowicz Jan 14 '16 at 12:32
  • 1
    No the example is for non-persistent cookie jar. For persistent solution, you can implement your own, e.g. http://stackoverflow.com/a/25462286/836540, and wrap it with JavaNetCookieJar. – hidro Jan 14 '16 at 14:23
  • 22
    Btw, url is a 'FULL URL' to server and it will only send cookies when making the request to exact same URL. You might want to replace `cookieStore.put(url, cookies);` to `cookieStore.put(url.host(), cookies);` For loadForRequest, `coookieStore.get(url.host());`. AND Replace `HashMap>` to `HashMap` – Eddie Feb 18 '16 at 00:19
  • @hidro how do i construct Cookies? – Michael A Mar 02 '16 at 09:52
  • Using `Cookie.Builder`? https://github.com/square/okhttp/blob/master/okhttp/src/main/java/okhttp3/Cookie.java#L451 – hidro Mar 02 '16 at 09:59
  • Adding codes below helped me. Thanks! CookieManager cookieManager = new CookieManager(); cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL); OkHttpClient client = new OkHttpClient.Builder() .cookieJar(new JavaNetCookieJar(cookieManager)) .build(); – Can Uludağ Apr 06 '16 at 13:14
  • FYI : In the near Future, they plan to remove the okhttp-urlconnection module. https://github.com/square/okhttp/blob/master/CHANGELOG.md – Tobliug Apr 12 '16 at 19:10
  • Using just the HttpUrl limits the cookie to just that url - and isn't really particular helpful. It should just be the domain name as the key - and then it works as intended. – slott Apr 26 '16 at 14:59
  • 7
    This is wrong. `saveFromResponse` **replaces** the list instead of **merging** them. It means that setting any cookie erases all cookies set in previous requests. – Agent_L Nov 30 '16 at 16:28
  • I agree with @Agent_L. This replaces all cookies each time new cookies arrive. This means if you login, receive an auth cookie in response, then make another request that returns a different cookie in the response, the auth cookie will get overwritten and you will no longer be logged in. – Cypress Frankenfeld Jun 26 '17 at 15:55
  • @Agent_L and how do I merge the cookies ? – Maxim Toyberman Jul 04 '18 at 12:41
  • @MaximToyberman You'd want something that looks like this `private final HashMap> cookieStore = new HashMap<>(); @Override public void saveFromResponse(HttpUrl url, List cookies) { if(cookieStore.containsKey(url.host())) { cookieStore.get(url.host()).addAll(cookies); } else { cookieStore.put(url.host(), cookies); } }` – Mikael Mengistu Sep 26 '18 at 22:41
  • Still not able to get the response. There is some session issue showing in server.But since it runs in web and iOS as well as i have no other option just to check my code. – Priyanka Singhal Mar 15 '19 at 06:10
  • Can't figure out why the session did't work with `CookieJar` implementation. `CookieManager` works like a charm. – Kimi Chiu Jun 30 '20 at 09:57
36

For OkHttp 3 (or maybe newer)

See hidro's answer

For OkHttp 2.x (or maybe older)

You can pass a CookieHandler to your OkHttpClient instance. You can use the CookieManager implementation from java.net or you could implement your own if you want. Choose the policy that works best for your needs.

OkHttpClient client = new OkHttpClient();
CookieManager cookieManager = new CookieManager();
cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
client.setCookieHandler(cookieManager);

OkHttp will save cookies received from Responses into the CookieHandler and read from it when sending requests. It will do so for matching request/response URIs.

Top-Master
  • 7,611
  • 5
  • 39
  • 71
Miguel
  • 19,793
  • 8
  • 56
  • 46
9

I needed to share the default Cookie Jar (CookieManager.getInstance()) so this seemed to work ok for me.

return new CookieJar() {

        @Override
        public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
            CookieManager cookieManager = CookieManager.getInstance();

            for (Cookie cookie : cookies) {
                cookieManager.setCookie(url.toString(), cookie.toString());
            }
        }

        @Override
        public List<Cookie> loadForRequest(HttpUrl url) {
            CookieManager cookieManager = CookieManager.getInstance();
            List<Cookie> cookies = new ArrayList<>();
            if (cookieManager.getCookie(url.toString()) != null) {
                String[] splitCookies = cookieManager.getCookie(url.toString()).split("[,;]");
                for (int i=0; i<splitCookies.length; i++) {
                    cookies.add(Cookie.parse(url, splitCookies[i].trim()));
                }
            }
            return cookies;
        }
    };
hmac
  • 267
  • 3
  • 9
  • Thanks It works really fine. Great job. Simple Solution, Thanks !! – KZoNE Aug 17 '17 at 04:58
  • hii @hmac your this approach works for me. Can you guide me how to clear the cookie when user logout? – Rozina May 24 '18 at 06:53
  • I solved the issue of clear cookies. Here is the link might helped someone https://stackoverflow.com/a/50505170/8159810 – Rozina May 24 '18 at 09:03