Improvements to the Jetty client documentation, cookies section.
Signed-off-by: Simone Bordet <simone.bordet@gmail.com>
This commit is contained in:
parent
9b57fcd8ee
commit
512f31b3af
|
@ -49,6 +49,10 @@
|
|||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.toolchain</groupId>
|
||||
<artifactId>jetty-servlet-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-client</artifactId>
|
||||
|
|
|
@ -17,103 +17,87 @@
|
|||
//
|
||||
|
||||
[[client-http-cookie]]
|
||||
=== Cookies Support
|
||||
=== HttpClient Cookie Support
|
||||
|
||||
Jetty HTTP client supports cookies out of the box.
|
||||
Jetty's `HttpClient` 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}"]
|
||||
[source,java,indent=0]
|
||||
----
|
||||
CookieStore cookieStore = httpClient.getCookieStore();
|
||||
List<HttpCookie> cookies = cookieStore.get(URI.create("http://domain.com/path"));
|
||||
include::../../{doc_code}/embedded/client/http/HTTPClientDocs.java[tag=getCookies]
|
||||
----
|
||||
|
||||
Applications can also programmatically set cookies as if they were returned from a HTTP response:
|
||||
|
||||
[source, java, subs="{sub-order}"]
|
||||
[source,java,indent=0]
|
||||
----
|
||||
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);
|
||||
include::../../{doc_code}/embedded/client/http/HTTPClientDocs.java[tag=setCookie]
|
||||
----
|
||||
|
||||
Cookies may be added only for a particular request:
|
||||
Cookies may be added explicitly only for a particular request:
|
||||
|
||||
[source, java, subs="{sub-order}"]
|
||||
[source,java,indent=0]
|
||||
----
|
||||
ContentResponse response = httpClient.newRequest("http://domain.com/path")
|
||||
.cookie(new HttpCookie("foo", "bar"))
|
||||
.send();
|
||||
include::../../{doc_code}/embedded/client/http/HTTPClientDocs.java[tag=requestCookie]
|
||||
----
|
||||
|
||||
You can remove cookies that you do not want to be sent in future HTTP requests:
|
||||
|
||||
[source, java, subs="{sub-order}"]
|
||||
[source,java,indent=0]
|
||||
----
|
||||
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);
|
||||
include::../../{doc_code}/embedded/client/http/HTTPClientDocs.java[tag=removeCookie]
|
||||
----
|
||||
|
||||
If you want to totally disable cookie handling, you can install a `HttpCookieStore.Empty` instance in this way:
|
||||
If you want to totally disable cookie handling, you can install a
|
||||
`HttpCookieStore.Empty`. This must be done when `HttpClient` is used in a
|
||||
proxy application, in this way:
|
||||
|
||||
[source, java, subs="{sub-order}"]
|
||||
[source,java,indent=0]
|
||||
----
|
||||
httpClient.setCookieStore(new HttpCookieStore.Empty());
|
||||
include::../../{doc_code}/embedded/client/http/HTTPClientDocs.java[tag=emptyCookieStore]
|
||||
----
|
||||
|
||||
You can enable cookie filtering by installing a cookie store that performs the filtering logic in this way:
|
||||
|
||||
[source, java, subs="{sub-order}"]
|
||||
[source,java,indent=0]
|
||||
----
|
||||
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);
|
||||
}
|
||||
}
|
||||
include::../../{doc_code}/embedded/client/http/HTTPClientDocs.java[tag=filteringCookieStore]
|
||||
----
|
||||
|
||||
The example above will retain only cookies that come from the `google.com` domain or sub-domains.
|
||||
|
||||
// TODO: move this section to server-side
|
||||
==== Special Characters in Cookies
|
||||
Jetty is compliant with link:https://tools.ietf.org/html/rfc6265[RFC6265], and as such care must be taken when setting a cookie value that includes special characters such as `;`.
|
||||
|
||||
Previously, Version=1 cookies defined in link:https://tools.ietf.org/html/rfc2109[RFC2109] (and continued in link:https://tools.ietf.org/html/rfc2965[RFC2965]) allowed for special/reserved characters to be enclosed within double quotes when declared in a `Set-Cookie` response header:
|
||||
|
||||
[source, java, subs="{sub-order}"]
|
||||
[source,subs="{sub-order}"]
|
||||
----
|
||||
Set-Cookie: foo="bar;baz";Version=1;Path="/secur"
|
||||
----
|
||||
|
||||
This was added to the HTTP Response header as follows:
|
||||
This was added to the HTTP Response as follows:
|
||||
|
||||
[source, java, subs="{sub-order}"]
|
||||
[source,java,subs="{sub-order}"]
|
||||
----
|
||||
Cookie cookie = new Cookie("foo", "bar;baz");
|
||||
cookie.setPath("/secur");
|
||||
response.addCookie(cookie);
|
||||
protected void service(HttpServletRequest request, HttpServletResponse response)
|
||||
{
|
||||
javax.servlet.http.Cookie cookie = new Cookie("foo", "bar;baz");
|
||||
cookie.setPath("/secur");
|
||||
response.addCookie(cookie);
|
||||
}
|
||||
----
|
||||
|
||||
The introduction of RFC6265 has rendered this approach no longer possible; users are now required to encode cookie values that use these special characters.
|
||||
This can be done utilizing `javax.servlet.http.Cookie` as follows:
|
||||
|
||||
[source, java, subs="{sub-order}"]
|
||||
[source,java,subs="{sub-order}"]
|
||||
----
|
||||
Cookie cookie = new Cookie("foo", URLEncoder.encode("bar;baz", "utf-8"));
|
||||
javax.servlet.http.Cookie cookie = new Cookie("foo", URLEncoder.encode("bar;baz", "UTF-8"));
|
||||
----
|
||||
|
||||
Jetty validates all cookie names and values being added to the `HttpServletResponse` via the `addCookie(Cookie)` method.
|
||||
|
|
|
@ -46,6 +46,18 @@ Out of the box features that you get with the Jetty HTTP client include:
|
|||
[[client-http-start]]
|
||||
==== Starting HttpClient
|
||||
|
||||
The Jetty artifact that provides the main HTTP client implementation is `jetty-client`.
|
||||
The Maven artifact coordinates are the following:
|
||||
|
||||
[source,xml,subs="{sub-order}"]
|
||||
----
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-client</artifactId>
|
||||
<version>{version}</version>
|
||||
</dependency>
|
||||
----
|
||||
|
||||
The main class is named `org.eclipse.jetty.client.HttpClient`.
|
||||
|
||||
You can think of a `HttpClient` instance as a browser instance.
|
||||
|
|
|
@ -22,8 +22,12 @@ import java.io.FileInputStream;
|
|||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.CookieStore;
|
||||
import java.net.HttpCookie;
|
||||
import java.net.URI;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.LongConsumer;
|
||||
|
||||
|
@ -47,6 +51,7 @@ import org.eclipse.jetty.http.HttpStatus;
|
|||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.ClientConnector;
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
import org.eclipse.jetty.util.HttpCookieStore;
|
||||
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
||||
|
||||
import static java.lang.System.Logger.Level.INFO;
|
||||
|
@ -474,4 +479,88 @@ public class HTTPClientDocs
|
|||
request1.send(result -> System.getLogger("forwarder").log(INFO, "Sourcing from server1 complete"));
|
||||
// end::demandedContentListener[]
|
||||
}
|
||||
|
||||
public void getCookies() throws Exception
|
||||
{
|
||||
HttpClient httpClient = new HttpClient();
|
||||
httpClient.start();
|
||||
|
||||
// tag::getCookies[]
|
||||
CookieStore cookieStore = httpClient.getCookieStore();
|
||||
List<HttpCookie> cookies = cookieStore.get(URI.create("http://domain.com/path"));
|
||||
// end::getCookies[]
|
||||
}
|
||||
|
||||
public void setCookie() throws Exception
|
||||
{
|
||||
HttpClient httpClient = new HttpClient();
|
||||
httpClient.start();
|
||||
|
||||
// tag::setCookie[]
|
||||
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);
|
||||
// end::setCookie[]
|
||||
}
|
||||
|
||||
public void requestCookie() throws Exception
|
||||
{
|
||||
HttpClient httpClient = new HttpClient();
|
||||
httpClient.start();
|
||||
|
||||
// tag::requestCookie[]
|
||||
ContentResponse response = httpClient.newRequest("http://domain.com/path")
|
||||
.cookie(new HttpCookie("foo", "bar"))
|
||||
.send();
|
||||
// end::requestCookie[]
|
||||
}
|
||||
|
||||
public void removeCookie() throws Exception
|
||||
{
|
||||
HttpClient httpClient = new HttpClient();
|
||||
httpClient.start();
|
||||
|
||||
// tag::removeCookie[]
|
||||
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);
|
||||
}
|
||||
// end::removeCookie[]
|
||||
}
|
||||
|
||||
public void emptyCookieStore() throws Exception
|
||||
{
|
||||
HttpClient httpClient = new HttpClient();
|
||||
httpClient.start();
|
||||
|
||||
// tag::emptyCookieStore[]
|
||||
httpClient.setCookieStore(new HttpCookieStore.Empty());
|
||||
// end::emptyCookieStore[]
|
||||
}
|
||||
|
||||
public void filteringCookieStore() throws Exception
|
||||
{
|
||||
HttpClient httpClient = new HttpClient();
|
||||
httpClient.start();
|
||||
|
||||
// tag::filteringCookieStore[]
|
||||
class GoogleOnlyCookieStore extends HttpCookieStore
|
||||
{
|
||||
@Override
|
||||
public void add(URI uri, HttpCookie cookie)
|
||||
{
|
||||
if (uri.getHost().endsWith("google.com"))
|
||||
super.add(uri, cookie);
|
||||
}
|
||||
}
|
||||
|
||||
httpClient.setCookieStore(new GoogleOnlyCookieStore());
|
||||
// end::filteringCookieStore[]
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue