//  ========================================================================
//  Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
//  ========================================================================
//  All rights reserved. This program and the accompanying materials
//  are made available under the terms of the Eclipse Public License v1.0
//  and Apache License v2.0 which accompanies this distribution.
//
//      The Eclipse Public License is available at
//      http://www.eclipse.org/legal/epl-v10.html
//
//      The Apache License v2.0 is available at
//      http://www.opensource.org/licenses/apache2.0.php
//
//  You may elect to redistribute this code under either of these licenses.
//  ========================================================================

[[http-client-cookie]]
=== Cookies Support

Jetty HTTP client supports cookies out of the box.
The `HttpClient` instance receives cookies from HTTP responses and stores them in a `java.net.CookieStore`, a class that is part of the JDK.
When new requests are made, the cookie store is consulted and if there are matching cookies (that is, cookies that are not expired and that match domain and path of the request) then they are added to the requests.

Applications can programmatically access the cookie store to find the cookies that have been set:

[source, java, subs="{sub-order}"]
----
CookieStore cookieStore = httpClient.getCookieStore();
List<HttpCookie> cookies = cookieStore.get(URI.create("http://domain.com/path"));
----

Applications can also programmatically set cookies as if they were returned from a HTTP response:

[source, java, subs="{sub-order}"]
----
CookieStore cookieStore = httpClient.getCookieStore();
HttpCookie cookie = new HttpCookie("foo", "bar");
cookie.setDomain("domain.com");
cookie.setPath("/");
cookie.setMaxAge(TimeUnit.DAYS.toSeconds(1));
cookieStore.add(URI.create("http://domain.com"), cookie);
----

Cookies may be added only for a particular request:

[source, java, subs="{sub-order}"]
----
ContentResponse response = httpClient.newRequest("http://domain.com/path")
        .cookie(new HttpCookie("foo", "bar"))
        .send();
----

You can remove cookies that you do not want to be sent in future HTTP requests:

[source, java, subs="{sub-order}"]
----
CookieStore cookieStore = httpClient.getCookieStore();
URI uri = URI.create("http://domain.com");
List<HttpCookie> cookies = cookieStore.get(uri);
for (HttpCookie cookie : cookies)
    cookieStore.remove(uri, cookie);
----

If you want to totally disable cookie handling, you can install a `HttpCookieStore.Empty` instance in this way:

[source, java, subs="{sub-order}"]
----
httpClient.setCookieStore(new HttpCookieStore.Empty());
----

You can enable cookie filtering by installing a cookie store that performs the filtering logic in this way:

[source, java, subs="{sub-order}"]
----
httpClient.setCookieStore(new GoogleOnlyCookieStore());

public class GoogleOnlyCookieStore extends HttpCookieStore
{
    @Override
    public void add(URI uri, HttpCookie cookie)
    {
        if (uri.getHost().endsWith("google.com"))
            super.add(uri, cookie);
    }
}
----

The example above will retain only cookies that come from the `google.com` domain or sub-domains.
