Updated HttpClient tutorial to 4.3 APIs (fundamentals, conn mgmt and state mgmt chapters)
git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk@1513603 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
64ca74933b
commit
5e2c01472d
|
@ -49,14 +49,9 @@ public final class CookieSpecs {
|
|||
public static final String NETSCAPE = "netscape";
|
||||
|
||||
/**
|
||||
* The RFC 2109 compliant policy.
|
||||
* The RFC 2965 compliant policy (standard).
|
||||
*/
|
||||
public static final String RFC_2109 = "rfc2109";
|
||||
|
||||
/**
|
||||
* The RFC 2965 compliant policy.
|
||||
*/
|
||||
public static final String RFC_2965 = "rfc2965";
|
||||
public static final String STANDARD = "standard";
|
||||
|
||||
/**
|
||||
* The default 'best match' policy.
|
||||
|
|
|
@ -690,11 +690,12 @@ public class HttpClientBuilder {
|
|||
if (cookieSpecRegistry == null) {
|
||||
cookieSpecRegistry = RegistryBuilder.<CookieSpecProvider>create()
|
||||
.register(CookieSpecs.BEST_MATCH, new BestMatchSpecFactory())
|
||||
.register(CookieSpecs.STANDARD, new RFC2965SpecFactory())
|
||||
.register(CookieSpecs.BROWSER_COMPATIBILITY, new BrowserCompatSpecFactory())
|
||||
.register(CookieSpecs.NETSCAPE, new NetscapeDraftSpecFactory())
|
||||
.register(CookieSpecs.RFC_2109, new RFC2109SpecFactory())
|
||||
.register(CookieSpecs.RFC_2965, new RFC2965SpecFactory())
|
||||
.register(CookieSpecs.IGNORE_COOKIES, new IgnoreSpecFactory())
|
||||
.register("rfc2109", new RFC2109SpecFactory())
|
||||
.register("rfc2965", new RFC2965SpecFactory())
|
||||
.build();
|
||||
}
|
||||
|
||||
|
|
|
@ -51,6 +51,10 @@ public class DefaultProxyRoutePlanner extends DefaultRoutePlanner {
|
|||
this.proxy = Args.notNull(proxy, "Proxy host");
|
||||
}
|
||||
|
||||
public DefaultProxyRoutePlanner(final HttpHost proxy) {
|
||||
this(proxy, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected HttpHost determineProxy(
|
||||
final HttpHost target,
|
||||
|
|
|
@ -65,6 +65,10 @@ public class SystemDefaultRoutePlanner extends DefaultRoutePlanner {
|
|||
this.proxySelector = proxySelector != null ? proxySelector : ProxySelector.getDefault();
|
||||
}
|
||||
|
||||
public SystemDefaultRoutePlanner(final ProxySelector proxySelector) {
|
||||
this(null, proxySelector);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected HttpHost determineProxy(
|
||||
final HttpHost target,
|
||||
|
|
|
@ -75,7 +75,7 @@ public class TestRequestConfig {
|
|||
.setRelativeRedirectsAllowed(false)
|
||||
.setCircularRedirectsAllowed(true)
|
||||
.setMaxRedirects(100)
|
||||
.setCookieSpec(CookieSpecs.RFC_2965)
|
||||
.setCookieSpec(CookieSpecs.STANDARD)
|
||||
.setLocalAddress(InetAddress.getLocalHost())
|
||||
.setProxy(new HttpHost("someproxy"))
|
||||
.setTargetPreferredAuthSchemes(Arrays.asList(AuthSchemes.NTLM))
|
||||
|
@ -92,7 +92,7 @@ public class TestRequestConfig {
|
|||
Assert.assertEquals(false, config.isRelativeRedirectsAllowed());
|
||||
Assert.assertEquals(true, config.isCircularRedirectsAllowed());
|
||||
Assert.assertEquals(100, config.getMaxRedirects());
|
||||
Assert.assertEquals(CookieSpecs.RFC_2965, config.getCookieSpec());
|
||||
Assert.assertEquals(CookieSpecs.STANDARD, config.getCookieSpec());
|
||||
Assert.assertEquals(InetAddress.getLocalHost(), config.getLocalAddress());
|
||||
Assert.assertEquals(new HttpHost("someproxy"), config.getProxy());
|
||||
Assert.assertEquals(Arrays.asList(AuthSchemes.NTLM), config.getTargetPreferredAuthSchemes());
|
||||
|
|
|
@ -52,7 +52,6 @@ import org.apache.http.impl.cookie.BrowserCompatSpec;
|
|||
import org.apache.http.impl.cookie.BrowserCompatSpecFactory;
|
||||
import org.apache.http.impl.cookie.IgnoreSpecFactory;
|
||||
import org.apache.http.impl.cookie.NetscapeDraftSpecFactory;
|
||||
import org.apache.http.impl.cookie.RFC2109SpecFactory;
|
||||
import org.apache.http.impl.cookie.RFC2965SpecFactory;
|
||||
import org.apache.http.message.BasicHttpRequest;
|
||||
import org.junit.Assert;
|
||||
|
@ -82,10 +81,9 @@ public class TestRequestAddCookies {
|
|||
|
||||
this.cookieSpecRegistry = RegistryBuilder.<CookieSpecProvider>create()
|
||||
.register(CookieSpecs.BEST_MATCH, new BestMatchSpecFactory())
|
||||
.register(CookieSpecs.STANDARD, new RFC2965SpecFactory())
|
||||
.register(CookieSpecs.BROWSER_COMPATIBILITY, new BrowserCompatSpecFactory())
|
||||
.register(CookieSpecs.NETSCAPE, new NetscapeDraftSpecFactory())
|
||||
.register(CookieSpecs.RFC_2109, new RFC2109SpecFactory())
|
||||
.register(CookieSpecs.RFC_2965, new RFC2965SpecFactory())
|
||||
.register(CookieSpecs.IGNORE_COOKIES, new IgnoreSpecFactory())
|
||||
.build();
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -34,17 +34,13 @@
|
|||
interface that defines the contract described above. </para>
|
||||
<para>Here is an example of request execution process in its simplest form:</para>
|
||||
<programlisting><![CDATA[
|
||||
HttpClient httpclient = new DefaultHttpClient();
|
||||
CloseableHttpClient httpclient = HttpClients.createDefault();
|
||||
HttpGet httpget = new HttpGet("http://localhost/");
|
||||
HttpResponse response = httpclient.execute(httpget);
|
||||
HttpEntity entity = response.getEntity();
|
||||
if (entity != null) {
|
||||
InputStream instream = entity.getContent();
|
||||
CloseableHttpResponse response = httpclient.execute(httpget);
|
||||
try {
|
||||
// do something useful
|
||||
|
||||
} finally {
|
||||
instream.close();
|
||||
}
|
||||
response.close();
|
||||
}
|
||||
]]></programlisting>
|
||||
<section>
|
||||
|
@ -69,13 +65,15 @@ HttpGet httpget = new HttpGet(
|
|||
<para>HttpClient provides <classname>URIBuilder</classname> utility class to simplify
|
||||
creation and modification of request URIs.</para>
|
||||
<programlisting><![CDATA[
|
||||
URIBuilder builder = new URIBuilder();
|
||||
builder.setScheme("http").setHost("www.google.com").setPath("/search")
|
||||
URI uri = new URIBuilder()
|
||||
.setScheme("http")
|
||||
.setHost("www.google.com")
|
||||
.setPath("/search")
|
||||
.setParameter("q", "httpclient")
|
||||
.setParameter("btnG", "Google Search")
|
||||
.setParameter("aq", "f")
|
||||
.setParameter("oq", "");
|
||||
URI uri = builder.build();
|
||||
.setParameter("oq", "")
|
||||
.build();
|
||||
HttpGet httpget = new HttpGet(uri);
|
||||
System.out.println(httpget.getURI());
|
||||
]]></programlisting>
|
||||
|
@ -282,10 +280,12 @@ important message
|
|||
</section>
|
||||
<section>
|
||||
<title>Ensuring release of low level resources</title>
|
||||
<para> In order to ensure proper release of system resources one must close the content
|
||||
stream associated with the entity.</para>
|
||||
<para> In order to ensure proper release of system resources one must close either
|
||||
the content stream associated with the entity or the response itself</para>
|
||||
<programlisting><![CDATA[
|
||||
HttpResponse response;
|
||||
CloseableHttpClient httpclient = <...>
|
||||
CloseableHttpResponse response = httpclient.execute(httpget);
|
||||
try {
|
||||
HttpEntity entity = response.getEntity();
|
||||
if (entity != null) {
|
||||
InputStream instream = entity.getContent();
|
||||
|
@ -295,7 +295,14 @@ if (entity != null) {
|
|||
instream.close();
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
response.close();
|
||||
}
|
||||
]]></programlisting>
|
||||
<para>The difference between closing the content stream and closing the response
|
||||
is that the former will attempt to keep the underlying connection alive
|
||||
by consuming the entity content while the latter immediately shuts down
|
||||
and discards the connection.</para>
|
||||
<para>Please note that the <methodname>HttpEntity#writeTo(OutputStream)</methodname>
|
||||
method is also required to ensure proper release of system resources once the
|
||||
entity has been fully written out. If this method obtains an instance of
|
||||
|
@ -309,19 +316,20 @@ if (entity != null) {
|
|||
<para>There can be situations, however, when only a small portion of the entire response
|
||||
content needs to be retrieved and the performance penalty for consuming the
|
||||
remaining content and making the connection reusable is too high, in which case
|
||||
one can simply
|
||||
terminate the request by calling <methodname>HttpUriRequest#abort()</methodname>
|
||||
method.</para>
|
||||
one can terminate the content stream by closing the response.</para>
|
||||
<programlisting><![CDATA[
|
||||
HttpGet httpget = new HttpGet("http://localhost/");
|
||||
HttpResponse response = httpclient.execute(httpget);
|
||||
CloseableHttpClient httpclient = <...>
|
||||
CloseableHttpResponse response = httpclient.execute(httpget);
|
||||
try {
|
||||
HttpEntity entity = response.getEntity();
|
||||
if (entity != null) {
|
||||
InputStream instream = entity.getContent();
|
||||
int byteOne = instream.read();
|
||||
int byteTwo = instream.read();
|
||||
// Do not need the rest
|
||||
httpget.abort();
|
||||
}
|
||||
} finally {
|
||||
response.close();
|
||||
}
|
||||
]]></programlisting>
|
||||
<para>The connection will not be reused, but all level resources held by it will be
|
||||
|
@ -340,8 +348,9 @@ if (entity != null) {
|
|||
strongly discouraged unless the response entities originate from a trusted HTTP
|
||||
server and are known to be of limited length.</para>
|
||||
<programlisting><![CDATA[
|
||||
HttpGet httpget = new HttpGet("http://localhost/");
|
||||
HttpResponse response = httpclient.execute(httpget);
|
||||
CloseableHttpClient httpclient = <...>
|
||||
CloseableHttpResponse response = httpclient.execute(httpget);
|
||||
try {
|
||||
HttpEntity entity = response.getEntity();
|
||||
if (entity != null) {
|
||||
long len = entity.getContentLength();
|
||||
|
@ -351,6 +360,9 @@ if (entity != null) {
|
|||
// Stream content out
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
response.close();
|
||||
}
|
||||
]]></programlisting>
|
||||
<para>In some situations it may be necessary to be able to read entity content more than
|
||||
once. In this case entity content must be buffered in some way, either in memory or
|
||||
|
@ -359,8 +371,7 @@ if (entity != null) {
|
|||
the original entity to be read into a in-memory buffer. In all other ways the entity
|
||||
wrapper will be have the original one.</para>
|
||||
<programlisting><![CDATA[
|
||||
HttpGet httpget = new HttpGet("http://localhost/");
|
||||
HttpResponse response = httpclient.execute(httpget);
|
||||
CloseableHttpResponse response = <...>
|
||||
HttpEntity entity = response.getEntity();
|
||||
if (entity != null) {
|
||||
entity = new BufferedHttpEntity(entity);
|
||||
|
@ -401,7 +412,7 @@ httppost.setEntity(entity);
|
|||
List<NameValuePair> formparams = new ArrayList<NameValuePair>();
|
||||
formparams.add(new BasicNameValuePair("param1", "value1"));
|
||||
formparams.add(new BasicNameValuePair("param2", "value2"));
|
||||
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formparams, "UTF-8");
|
||||
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formparams, Consts.UTF_8);
|
||||
HttpPost httppost = new HttpPost("http://localhost/handler.do");
|
||||
httppost.setEntity(entity);
|
||||
]]></programlisting>
|
||||
|
@ -423,7 +434,7 @@ param1=value1¶m2=value2
|
|||
HTTP/1.0.</para>
|
||||
<programlisting><![CDATA[
|
||||
StringEntity entity = new StringEntity("important message",
|
||||
"text/plain; charset=\"UTF-8\"");
|
||||
ContentType.create("plain/text", Consts.UTF_8));
|
||||
entity.setChunked(true);
|
||||
HttpPost httppost = new HttpPost("http://localhost/acrtion.do");
|
||||
httppost.setEntity(entity);
|
||||
|
@ -441,22 +452,32 @@ httppost.setEntity(entity);
|
|||
take care of ensuring release of the connection back to the connection manager
|
||||
regardless whether the request execution succeeds or causes an exception.</para>
|
||||
<programlisting><![CDATA[
|
||||
HttpClient httpclient = new DefaultHttpClient();
|
||||
HttpGet httpget = new HttpGet("http://localhost/");
|
||||
HttpClient httpclient = <...>
|
||||
HttpRequest request = <...>
|
||||
|
||||
ResponseHandler<byte[]> handler = new ResponseHandler<byte[]>() {
|
||||
public byte[] handleResponse(
|
||||
HttpResponse response) throws ClientProtocolException, IOException {
|
||||
ResponseHandler<MyJsonObject> rh = new ResponseHandler<MyJsonObject>() {
|
||||
|
||||
@Override
|
||||
public JsonObject handleResponse(
|
||||
final HttpResponse response) throws IOException {
|
||||
StatusLine statusLine = response.getStatusLine();
|
||||
HttpEntity entity = response.getEntity();
|
||||
if (entity != null) {
|
||||
return EntityUtils.toByteArray(entity);
|
||||
} else {
|
||||
return null;
|
||||
if (statusLine.getStatusCode() >= 300) {
|
||||
throw new HttpResponseException(
|
||||
statusLine.getStatusCode(),
|
||||
statusLine.getReasonPhrase());
|
||||
}
|
||||
if (entity == null) {
|
||||
throw new ClientProtocolException("Response contains no content");
|
||||
}
|
||||
Gson gson = new GsonBuilder().create();
|
||||
ContentType contentType = ContentType.getOrDefault(entity);
|
||||
Charset charset = contentType.getCharset();
|
||||
Reader reader = new InputStreamReader(entity.getContent(), charset);
|
||||
return gson.fromJson(reader, MyJsonObject.class);
|
||||
}
|
||||
};
|
||||
|
||||
byte[] response = httpclient.execute(httpget, handler);
|
||||
MyJsonObject myjson = client.execute(request, rh);
|
||||
]]></programlisting>
|
||||
</section>
|
||||
</section>
|
||||
|
@ -476,81 +497,45 @@ byte[] response = httpclient.execute(httpget, handler);
|
|||
<para><interfacename>HttpContext</interfacename> can contain arbitrary objects and
|
||||
therefore may be unsafe to share between multiple threads. It is recommended that
|
||||
each thread of execution maintains its own context.</para>
|
||||
<para>In the course of HTTP request execution HttpClient adds the following attributes to
|
||||
the execution context:</para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<formalpara>
|
||||
<title><constant>ExecutionContext.HTTP_CONNECTION</constant>='http.connection':</title>
|
||||
<para><interfacename>HttpConnection</interfacename> instance representing the
|
||||
actual connection to the target server.</para>
|
||||
</formalpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<formalpara>
|
||||
<title><constant>ExecutionContext.HTTP_TARGET_HOST</constant>='http.target_host':</title>
|
||||
<para><classname>HttpHost</classname> instance representing the connection
|
||||
target.</para>
|
||||
</formalpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<formalpara>
|
||||
<title><constant>ExecutionContext.HTTP_PROXY_HOST</constant>='http.proxy_host':</title>
|
||||
<para><classname>HttpHost</classname> instance representing the connection
|
||||
proxy, if used</para>
|
||||
</formalpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<formalpara>
|
||||
<title><constant>ExecutionContext.HTTP_REQUEST</constant>='http.request':</title>
|
||||
<para><interfacename>HttpRequest</interfacename> instance representing the
|
||||
actual HTTP request.
|
||||
The final HttpRequest object in the execution context always represents
|
||||
the state of the message _exactly_ as it was sent to the target server.
|
||||
Per default HTTP/1.0 and HTTP/1.1 use relative request URIs.
|
||||
However if the request is sent via a proxy in a non-tunneling mode then
|
||||
the URI will be absolute.</para>
|
||||
</formalpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<formalpara>
|
||||
<title><constant>ExecutionContext.HTTP_RESPONSE</constant>='http.response':</title>
|
||||
<para><interfacename>HttpResponse</interfacename> instance representing the
|
||||
actual HTTP response.</para>
|
||||
</formalpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<formalpara>
|
||||
<title><constant>ExecutionContext.HTTP_REQ_SENT</constant>='http.request_sent':</title>
|
||||
<para><classname>java.lang.Boolean</classname> object representing the flag
|
||||
indicating whether the actual request has been fully transmitted to the
|
||||
connection target.</para>
|
||||
</formalpara>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
<para>For instance, in order to determine the final redirect target, one can examine the
|
||||
value of the <literal>http.target_host</literal> attribute after the request
|
||||
execution:</para>
|
||||
<para>One can use <classname>HttpClientContext</classname> adaptor class to simplify
|
||||
interractions with the context state.</para>
|
||||
<programlisting><![CDATA[
|
||||
DefaultHttpClient httpclient = new DefaultHttpClient();
|
||||
|
||||
HttpContext localContext = new BasicHttpContext();
|
||||
HttpGet httpget = new HttpGet("http://www.google.com/");
|
||||
|
||||
HttpResponse response = httpclient.execute(httpget, localContext);
|
||||
|
||||
HttpHost target = (HttpHost) localContext.getAttribute(
|
||||
ExecutionContext.HTTP_TARGET_HOST);
|
||||
|
||||
System.out.println("Final target: " + target);
|
||||
|
||||
HttpEntity entity = response.getEntity();
|
||||
EntityUtils.consume(entity);
|
||||
}
|
||||
HttpContext context = <...>
|
||||
HttpClientContext clientContext = HttpClientContext.adapt(context);
|
||||
HttpHost target = clientContext.getTargetHost();
|
||||
HttpRequest request = clientContext.getRequest();
|
||||
HttpResponse response = clientContext.getResponse();
|
||||
]]></programlisting>
|
||||
<para>stdout ></para>
|
||||
<para>Multiple request sequences that represent a logically related session should be
|
||||
executed with the same <interfacename>HttpContext</interfacename> instance to ensure
|
||||
automatic propagation of conversation context and state information between
|
||||
requests.</para>
|
||||
<para>In the following example the request configuration set by the initial request will be
|
||||
kept in the execution context and get propagatd to the consecutive requests sharing
|
||||
the same context.</para>
|
||||
<programlisting><![CDATA[
|
||||
Final target: http://www.google.ch
|
||||
CloseableHttpClient httpclient = <...>
|
||||
|
||||
RequestConfig requestConfig = RequestConfig.custom()
|
||||
.setSocketTimeout(1000)
|
||||
.setConnectTimeout(1000)
|
||||
.build();
|
||||
|
||||
HttpGet httpget1 = new HttpGet("http://localhost/1");
|
||||
httpget1.setConfig(requestConfig);
|
||||
CloseableHttpResponse response1 = httpclient.execute(httpget1, context);
|
||||
try {
|
||||
HttpEntity entity1 = response1.getEntity();
|
||||
} finally {
|
||||
response1.close();
|
||||
}
|
||||
HttpGet httpget2 = new HttpGet("http://localhost/2");
|
||||
CloseableHttpResponse response2 = httpclient.execute(httpget2, context);
|
||||
try {
|
||||
HttpEntity entity2 = response2.getEntity();
|
||||
} finally {
|
||||
response2.close();
|
||||
}
|
||||
]]></programlisting>
|
||||
</section>
|
||||
<section>
|
||||
|
@ -628,8 +613,6 @@ Final target: http://www.google.ch
|
|||
implementation of the <interfacename>HttpRequestRetryHandler</interfacename>
|
||||
interface.</para>
|
||||
<programlisting><![CDATA[
|
||||
DefaultHttpClient httpclient = new DefaultHttpClient();
|
||||
|
||||
HttpRequestRetryHandler myRetryHandler = new HttpRequestRetryHandler() {
|
||||
|
||||
public boolean retryRequest(
|
||||
|
@ -648,7 +631,7 @@ HttpRequestRetryHandler myRetryHandler = new HttpRequestRetryHandler() {
|
|||
// Unknown host
|
||||
return false;
|
||||
}
|
||||
if (exception instanceof ConnectException) {
|
||||
if (exception instanceof ConnectTimeoutException) {
|
||||
// Connection refused
|
||||
return false;
|
||||
}
|
||||
|
@ -656,8 +639,8 @@ HttpRequestRetryHandler myRetryHandler = new HttpRequestRetryHandler() {
|
|||
// SSL handshake exception
|
||||
return false;
|
||||
}
|
||||
HttpRequest request = (HttpRequest) context.getAttribute(
|
||||
ExecutionContext.HTTP_REQUEST);
|
||||
HttpClientContext clientContext = HttpClientContext.adapt(context);
|
||||
HttpRequest request = clientContext.getRequest();
|
||||
boolean idempotent = !(request instanceof HttpEntityEnclosingRequest);
|
||||
if (idempotent) {
|
||||
// Retry if the request is considered idempotent
|
||||
|
@ -667,8 +650,9 @@ HttpRequestRetryHandler myRetryHandler = new HttpRequestRetryHandler() {
|
|||
}
|
||||
|
||||
};
|
||||
|
||||
httpclient.setHttpRequestRetryHandler(myRetryHandler);
|
||||
CloseableHttpClient httpclient = HttpClients.custom()
|
||||
.setRetryHandler(myRetryHandler)
|
||||
.build();
|
||||
]]></programlisting>
|
||||
</section>
|
||||
</section>
|
||||
|
@ -708,15 +692,8 @@ httpclient.setHttpRequestRetryHandler(myRetryHandler);
|
|||
<para>This is an example of how local context can be used to persist a processing state
|
||||
between consecutive requests:</para>
|
||||
<programlisting><![CDATA[
|
||||
DefaultHttpClient httpclient = new DefaultHttpClient();
|
||||
|
||||
HttpContext localContext = new BasicHttpContext();
|
||||
|
||||
AtomicInteger count = new AtomicInteger(1);
|
||||
|
||||
localContext.setAttribute("count", count);
|
||||
|
||||
httpclient.addRequestInterceptor(new HttpRequestInterceptor() {
|
||||
CloseableHttpClient httpclient = HttpClients.custom()
|
||||
.addInterceptorLast(new HttpRequestInterceptor() {
|
||||
|
||||
public void process(
|
||||
final HttpRequest request,
|
||||
|
@ -725,210 +702,22 @@ httpclient.addRequestInterceptor(new HttpRequestInterceptor() {
|
|||
request.addHeader("Count", Integer.toString(count.getAndIncrement()));
|
||||
}
|
||||
|
||||
});
|
||||
})
|
||||
.build();
|
||||
|
||||
AtomicInteger count = new AtomicInteger(1);
|
||||
HttpClientContext localContext = HttpClientContext.create();
|
||||
localContext.setAttribute("count", count);
|
||||
|
||||
HttpGet httpget = new HttpGet("http://localhost/");
|
||||
for (int i = 0; i < 10; i++) {
|
||||
HttpResponse response = httpclient.execute(httpget, localContext);
|
||||
|
||||
CloseableHttpResponse response = httpclient.execute(httpget, localContext);
|
||||
try {
|
||||
HttpEntity entity = response.getEntity();
|
||||
EntityUtils.consume(entity);
|
||||
} finally {
|
||||
response.close();
|
||||
}
|
||||
}
|
||||
]]></programlisting>
|
||||
</section>
|
||||
<section>
|
||||
<title>HTTP parameters</title>
|
||||
<para>The HttpParams interface represents a collection of immutable values that define a runtime
|
||||
behavior of a component. In many ways <interfacename>HttpParams</interfacename> is
|
||||
similar to <interfacename>HttpContext</interfacename>. The main distinction between the
|
||||
two lies in their use at runtime. Both interfaces represent a collection of objects that
|
||||
are organized as a map of keys to object values, but serve distinct purposes:</para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para><interfacename>HttpParams</interfacename> is intended to contain simple
|
||||
objects: integers, doubles, strings, collections and objects that remain
|
||||
immutable at runtime.</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<interfacename>HttpParams</interfacename> is expected to be used in the 'write
|
||||
once - ready many' mode. <interfacename>HttpContext</interfacename> is intended
|
||||
to contain complex objects that are very likely to mutate in the course of HTTP
|
||||
message processing. </para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>The purpose of <interfacename>HttpParams</interfacename> is to define a
|
||||
behavior of other components. Usually each complex component has its own
|
||||
<interfacename>HttpParams</interfacename> object. The purpose of
|
||||
<interfacename>HttpContext</interfacename> is to represent an execution
|
||||
state of an HTTP process. Usually the same execution context is shared among
|
||||
many collaborating objects.</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
<section>
|
||||
<title>Parameter hierarchies</title>
|
||||
<para>In the course of HTTP request execution <interfacename>HttpParams</interfacename>
|
||||
of the <interfacename>HttpRequest</interfacename> object are linked together with
|
||||
<interfacename>HttpParams</interfacename> of the
|
||||
<interfacename>HttpClient</interfacename> instance used to execute the request.
|
||||
This enables parameters set at the HTTP request level to take precedence over
|
||||
<interfacename>HttpParams</interfacename> set at the HTTP client level. The
|
||||
recommended practice is to set common parameters shared by all HTTP requests at the
|
||||
HTTP client level and selectively override specific parameters at the HTTP request
|
||||
level.</para>
|
||||
<programlisting><![CDATA[
|
||||
DefaultHttpClient httpclient = new DefaultHttpClient();
|
||||
httpclient.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION,
|
||||
HttpVersion.HTTP_1_0); // Default to HTTP 1.0
|
||||
httpclient.getParams().setParameter(CoreProtocolPNames.HTTP_CONTENT_CHARSET,
|
||||
"UTF-8");
|
||||
|
||||
HttpGet httpget = new HttpGet("http://www.google.com/");
|
||||
httpget.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION,
|
||||
HttpVersion.HTTP_1_1); // Use HTTP 1.1 for this request only
|
||||
httpget.getParams().setParameter(CoreProtocolPNames.USE_EXPECT_CONTINUE,
|
||||
Boolean.FALSE);
|
||||
|
||||
httpclient.addRequestInterceptor(new HttpRequestInterceptor() {
|
||||
|
||||
public void process(
|
||||
final HttpRequest request,
|
||||
final HttpContext context) throws HttpException, IOException {
|
||||
System.out.println(request.getParams().getParameter(
|
||||
CoreProtocolPNames.PROTOCOL_VERSION));
|
||||
System.out.println(request.getParams().getParameter(
|
||||
CoreProtocolPNames.HTTP_CONTENT_CHARSET));
|
||||
System.out.println(request.getParams().getParameter(
|
||||
CoreProtocolPNames.USE_EXPECT_CONTINUE));
|
||||
System.out.println(request.getParams().getParameter(
|
||||
CoreProtocolPNames.STRICT_TRANSFER_ENCODING));
|
||||
}
|
||||
|
||||
});
|
||||
]]></programlisting>
|
||||
<para>stdout ></para>
|
||||
<programlisting><![CDATA[
|
||||
HTTP/1.1
|
||||
UTF-8
|
||||
false
|
||||
null
|
||||
]]></programlisting>
|
||||
</section>
|
||||
<section>
|
||||
<title>HTTP parameters beans</title>
|
||||
<para>The <interfacename>HttpParams</interfacename> interface allows for a great deal of
|
||||
flexibility in handling configuration of components. Most importantly, new
|
||||
parameters can be introduced without affecting binary compatibility with older
|
||||
versions. However, <interfacename>HttpParams</interfacename> also has a certain
|
||||
disadvantage compared to regular Java beans:
|
||||
<interfacename>HttpParams</interfacename> cannot be assembled using a DI
|
||||
framework. To mitigate the limitation, HttpClient includes a number of bean classes
|
||||
that can used in order to initialize <interfacename>HttpParams</interfacename>
|
||||
objects using standard Java bean conventions.</para>
|
||||
<programlisting><![CDATA[
|
||||
HttpParams params = new BasicHttpParams();
|
||||
HttpProtocolParamBean paramsBean = new HttpProtocolParamBean(params);
|
||||
paramsBean.setVersion(HttpVersion.HTTP_1_1);
|
||||
paramsBean.setContentCharset("UTF-8");
|
||||
paramsBean.setUseExpectContinue(true);
|
||||
|
||||
System.out.println(params.getParameter(
|
||||
CoreProtocolPNames.PROTOCOL_VERSION));
|
||||
System.out.println(params.getParameter(
|
||||
CoreProtocolPNames.HTTP_CONTENT_CHARSET));
|
||||
System.out.println(params.getParameter(
|
||||
CoreProtocolPNames.USE_EXPECT_CONTINUE));
|
||||
System.out.println(params.getParameter(
|
||||
CoreProtocolPNames.USER_AGENT));
|
||||
]]></programlisting>
|
||||
<para>stdout ></para>
|
||||
<programlisting><![CDATA[
|
||||
HTTP/1.1
|
||||
UTF-8
|
||||
false
|
||||
null
|
||||
]]></programlisting>
|
||||
</section>
|
||||
</section>
|
||||
<section>
|
||||
<title>HTTP request execution parameters</title>
|
||||
<para>These are parameters that can impact the process of request execution:</para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<formalpara>
|
||||
<title><constant>CoreProtocolPNames.PROTOCOL_VERSION</constant>='http.protocol.version':</title>
|
||||
<para>defines HTTP protocol version used if not set explicitly on the request
|
||||
object. This parameter expects a value of type
|
||||
<interfacename>ProtocolVersion</interfacename>. If this parameter is not
|
||||
set HTTP/1.1 will be used.</para>
|
||||
</formalpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<formalpara>
|
||||
<title><constant>CoreProtocolPNames.HTTP_ELEMENT_CHARSET</constant>='http.protocol.element-charset':</title>
|
||||
<para>defines the charset to be used for encoding HTTP protocol elements. This
|
||||
parameter expects a value of type <classname>java.lang.String</classname>.
|
||||
If this parameter is not set <literal>US-ASCII</literal> will be
|
||||
used.</para>
|
||||
</formalpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<formalpara>
|
||||
<title><constant>CoreProtocolPNames.HTTP_CONTENT_CHARSET</constant>='http.protocol.content-charset':</title>
|
||||
<para>defines the charset to be used per default for content body coding. This
|
||||
parameter expects a value of type <classname>java.lang.String</classname>.
|
||||
If this parameter is not set <literal>ISO-8859-1</literal> will be
|
||||
used.</para>
|
||||
</formalpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<formalpara>
|
||||
<title><constant>CoreProtocolPNames.USER_AGENT</constant>='http.useragent':</title>
|
||||
<para>defines the content of the <literal>User-Agent</literal> header. This
|
||||
parameter expects a value of type <classname>java.lang.String</classname>.
|
||||
If this parameter is not set, HttpClient will automatically generate a value
|
||||
for it.</para>
|
||||
</formalpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<formalpara>
|
||||
<title><constant>CoreProtocolPNames.STRICT_TRANSFER_ENCODING</constant>='http.protocol.strict-transfer-encoding':</title>
|
||||
<para>defines whether responses with an invalid
|
||||
<literal>Transfer-Encoding</literal> header should be rejected. This
|
||||
parameter expects a value of type <classname>java.lang.Boolean</classname>.
|
||||
If this parameter is not set, invalid <literal>Transfer-Encoding</literal>
|
||||
values will be ignored.</para>
|
||||
</formalpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<formalpara>
|
||||
<title><constant>CoreProtocolPNames.USE_EXPECT_CONTINUE</constant>='http.protocol.expect-continue':</title>
|
||||
<para>activates the <literal>Expect: 100-Continue</literal> handshake for the entity
|
||||
enclosing methods. The purpose of the <literal>Expect:
|
||||
100-Continue</literal> handshake is to allow the client that is sending
|
||||
a request message with a request body to determine if the origin server is
|
||||
willing to accept the request (based on the request headers) before the
|
||||
client sends the request body. The use of the <literal>Expect:
|
||||
100-continue</literal> handshake can result in a noticeable performance
|
||||
improvement for entity enclosing requests (such as <literal>POST</literal>
|
||||
and <literal>PUT</literal>) that require the target server's authentication.
|
||||
The <literal>Expect: 100-continue</literal> handshake should be used with
|
||||
caution, as it may cause problems with HTTP servers and proxies that do not
|
||||
support HTTP/1.1 protocol. This parameter expects a value of type
|
||||
<classname>java.lang.Boolean</classname>. If this parameter is not set,
|
||||
HttpClient will not attempt to use the handshake.</para>
|
||||
</formalpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<formalpara>
|
||||
<title><constant>CoreProtocolPNames.WAIT_FOR_CONTINUE</constant>='http.protocol.wait-for-continue':</title>
|
||||
<para>defines the maximum period of time in milliseconds the client should spend
|
||||
waiting for a <literal>100-continue</literal> response. This parameter
|
||||
expects a value of type <classname>java.lang.Integer</classname>. If this
|
||||
parameter is not set HttpClient will wait 3 seconds for a confirmation
|
||||
before resuming the transmission of the request body.</para>
|
||||
</formalpara>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</section>
|
||||
</chapter>
|
||||
|
|
|
@ -70,9 +70,9 @@
|
|||
<para>
|
||||
HttpClient is NOT a browser. It is a client side HTTP transport library.
|
||||
HttpClient's purpose is to transmit and receive HTTP messages. HttpClient will not
|
||||
attempt to cache content, execute javascript embedded in HTML pages, try to guess
|
||||
content type, or reformat request / redirect location URIs, or other functionality
|
||||
unrelated to the HTTP transport.
|
||||
attempt to process content, execute javascript embedded in HTML pages, try to guess
|
||||
content type, if not explicitly set, or reformat request / redirect location URIs,
|
||||
or other functionality unrelated to the HTTP transport.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
|
|
|
@ -133,15 +133,8 @@ stdCookie.setAttribute(ClientCookie.PORT_ATTR, "80,8080");
|
|||
</listitem>
|
||||
<listitem>
|
||||
<formalpara>
|
||||
<title>RFC 2109:</title>
|
||||
<para>Older version of the official HTTP state management specification
|
||||
superseded by RFC 2965.</para>
|
||||
</formalpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<formalpara>
|
||||
<title>RFC 2965:</title>
|
||||
<para>The official HTTP state management specification.</para>
|
||||
<title>Standard:</title>
|
||||
<para>RFC 2965 HTTP state management specification.</para>
|
||||
</formalpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
|
@ -171,123 +164,37 @@ stdCookie.setAttribute(ClientCookie.PORT_ATTR, "80,8080");
|
|||
HttpClient pick up an appropriate compliance level at runtime based on the execution
|
||||
context.</para>
|
||||
</section>
|
||||
<section>
|
||||
<title>HTTP cookie and state management parameters</title>
|
||||
<para>These are parameters that be used to customize HTTP state management and the behaviour of
|
||||
individual cookie specifications:</para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<formalpara>
|
||||
<title><constant>CookieSpecPNames.DATE_PATTERNS</constant>='http.protocol.cookie-datepatterns':</title>
|
||||
<para>defines valid date patterns to be used for parsing non-standard
|
||||
<literal>expires</literal> attribute. Only required for compatibility
|
||||
with non-compliant servers that still use <literal>expires</literal> defined
|
||||
in the Netscape draft instead of the standard <literal>max-age</literal>
|
||||
attribute. This parameter expects a value of type
|
||||
<interfacename>java.util.Collection</interfacename>. The collection
|
||||
elements must be of type <classname>java.lang.String</classname> compatible
|
||||
with the syntax of <classname>java.text.SimpleDateFormat</classname>. If
|
||||
this parameter is not set the choice of a default value is
|
||||
<interfacename>CookieSpec</interfacename> implementation specific.</para>
|
||||
</formalpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<formalpara>
|
||||
<title><constant>CookieSpecPNames.SINGLE_COOKIE_HEADER</constant>='http.protocol.single-cookie-header':</title>
|
||||
<para>defines whether cookies should be forced into a single
|
||||
<literal>Cookie</literal> request header. Otherwise, each cookie is
|
||||
formatted as a separate <literal>Cookie</literal> header. This parameter
|
||||
expects a value of type <classname>java.lang.Boolean</classname>. If this
|
||||
parameter is not set, the choice of a default value is CookieSpec
|
||||
implementation specific. Please note this parameter applies to strict cookie
|
||||
specifications (RFC 2109 and RFC 2965) only. Browser compatibility and
|
||||
netscape draft policies will always put all cookies into one request
|
||||
header.</para>
|
||||
</formalpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<formalpara>
|
||||
<title><constant>ClientPNames.COOKIE_POLICY</constant>='http.protocol.cookie-policy':</title>
|
||||
<para>defines the name of a cookie specification to be used for HTTP state
|
||||
management. This parameter expects a value of type
|
||||
<classname>java.lang.String</classname>. If this parameter is not set,
|
||||
valid date patterns are <interfacename>CookieSpec</interfacename>
|
||||
implementation specific.</para>
|
||||
</formalpara>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</section>
|
||||
<section>
|
||||
<title>Cookie specification registry</title>
|
||||
<para>HttpClient maintains a registry of available cookie specifications using
|
||||
the <classname>CookieSpecRegistry</classname> class. The following specifications are
|
||||
registered per default:</para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<formalpara>
|
||||
<title>compatibility:</title>
|
||||
<para> Browser compatibility (lenient policy).</para>
|
||||
</formalpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<formalpara>
|
||||
<title>netscape:</title>
|
||||
<para>Netscape draft.</para>
|
||||
</formalpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<formalpara>
|
||||
<title>rfc2109:</title>
|
||||
<para>RFC 2109 (outdated strict policy).</para>
|
||||
</formalpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<formalpara>
|
||||
<title>rfc2965:</title>
|
||||
<para>RFC 2965 (standard conformant strict policy).</para>
|
||||
</formalpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<formalpara>
|
||||
<title>best-match:</title>
|
||||
<para>Best match meta-policy.</para>
|
||||
</formalpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<formalpara>
|
||||
<title>ignoreCookies:</title>
|
||||
<para>All cookies are ignored.</para>
|
||||
</formalpara>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</section>
|
||||
<section>
|
||||
<title>Choosing cookie policy</title>
|
||||
<para>Cookie policy can be set at the HTTP client and overridden on the HTTP request level
|
||||
if required.</para>
|
||||
<programlisting><![CDATA[
|
||||
HttpClient httpclient = new DefaultHttpClient();
|
||||
// force strict cookie policy per default
|
||||
httpclient.getParams().setParameter(
|
||||
ClientPNames.COOKIE_POLICY, CookiePolicy.RFC_2965);
|
||||
|
||||
HttpGet httpget = new HttpGet("http://www.broken-server.com/");
|
||||
// Override the default policy for this request
|
||||
httpget.getParams().setParameter(
|
||||
ClientPNames.COOKIE_POLICY, CookiePolicy.BROWSER_COMPATIBILITY);
|
||||
RequestConfig globalConfig = RequestConfig.custom()
|
||||
.setCookieSpec(CookieSpecs.BEST_MATCH)
|
||||
.build();
|
||||
CloseableHttpClient httpclient = HttpClients.custom()
|
||||
.setDefaultRequestConfig(globalConfig)
|
||||
.build();
|
||||
RequestConfig localConfig = RequestConfig.copy(globalConfig)
|
||||
.setCookieSpec(CookieSpecs.BROWSER_COMPATIBILITY)
|
||||
.build();
|
||||
HttpGet httpGet = new HttpGet("/");
|
||||
httpGet.setConfig(localConfig);
|
||||
]]></programlisting>
|
||||
</section>
|
||||
<section>
|
||||
<title>Custom cookie policy</title>
|
||||
<para>In order to implement a custom cookie policy one should create a custom implementation
|
||||
of the <interfacename>CookieSpec</interfacename> interface, create a
|
||||
<interfacename>CookieSpecFactory</interfacename> implementation to create and
|
||||
<interfacename>CookieSpecProvider</interfacename> implementation to create and
|
||||
initialize instances of the custom specification and register the factory with
|
||||
HttpClient. Once the custom specification has been registered, it can be activated the
|
||||
same way as a standard cookie specification.</para>
|
||||
<programlisting><![CDATA[
|
||||
CookieSpecFactory csf = new CookieSpecFactory() {
|
||||
public CookieSpec newInstance(HttpParams params) {
|
||||
CookieSpecProvider easySpecProvider = new CookieSpecProvider() {
|
||||
|
||||
public CookieSpec create(HttpContext context) {
|
||||
|
||||
return new BrowserCompatSpec() {
|
||||
@Override
|
||||
public void validate(Cookie cookie, CookieOrigin origin)
|
||||
|
@ -296,12 +203,22 @@ CookieSpecFactory csf = new CookieSpecFactory() {
|
|||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
DefaultHttpClient httpclient = new DefaultHttpClient();
|
||||
httpclient.getCookieSpecs().register("easy", csf);
|
||||
httpclient.getParams().setParameter(
|
||||
ClientPNames.COOKIE_POLICY, "easy");
|
||||
};
|
||||
Registry<CookieSpecProvider> cookieSpecReg = RegistryBuilder.<CookieSpecProvider>create()
|
||||
.register(CookieSpecs.BEST_MATCH, new BestMatchSpecFactory())
|
||||
.register(CookieSpecs.BROWSER_COMPATIBILITY, new BrowserCompatSpecFactory())
|
||||
.register("easy", easySpecProvider)
|
||||
.build();
|
||||
|
||||
RequestConfig requestConfig = RequestConfig.custom()
|
||||
.setCookieSpec("easy")
|
||||
.build();
|
||||
|
||||
CloseableHttpClient httpclient = HttpClients.custom()
|
||||
.setDefaultCookieSpecRegistry(cookieSpecReg)
|
||||
.setDefaultRequestConfig(requestConfig)
|
||||
.build();
|
||||
]]></programlisting>
|
||||
</section>
|
||||
<section>
|
||||
|
@ -315,9 +232,8 @@ httpclient.getParams().setParameter(
|
|||
get garbage collected. Users can provide more complex implementations if
|
||||
necessary.</para>
|
||||
<programlisting><![CDATA[
|
||||
DefaultHttpClient httpclient = new DefaultHttpClient();
|
||||
// Create a local instance of cookie store
|
||||
CookieStore cookieStore = new MyCookieStore();
|
||||
CookieStore cookieStore = new BasicCookieStore();
|
||||
// Populate cookies if needed
|
||||
BasicClientCookie cookie = new BasicClientCookie("name", "value");
|
||||
cookie.setVersion(0);
|
||||
|
@ -325,7 +241,9 @@ cookie.setDomain(".mycompany.com");
|
|||
cookie.setPath("/");
|
||||
cookieStore.addCookie(cookie);
|
||||
// Set the store
|
||||
httpclient.setCookieStore(cookieStore);
|
||||
CloseableHttpClient httpclient = HttpClients.custom()
|
||||
.setDefaultCookieStore(cookieStore)
|
||||
.build();
|
||||
]]></programlisting>
|
||||
</section>
|
||||
<section>
|
||||
|
@ -335,7 +253,6 @@ httpclient.setCookieStore(cookieStore);
|
|||
<itemizedlist>
|
||||
<listitem>
|
||||
<formalpara>
|
||||
<title><constant>ClientContext.COOKIESPEC_REGISTRY</constant>='http.cookiespec-registry':</title>
|
||||
<para><classname>CookieSpecRegistry</classname> instance representing the actual
|
||||
cookie specification registry. The value of this attribute set in the local
|
||||
context takes precedence over the default one.</para>
|
||||
|
@ -343,21 +260,18 @@ httpclient.setCookieStore(cookieStore);
|
|||
</listitem>
|
||||
<listitem>
|
||||
<formalpara>
|
||||
<title><constant>ClientContext.COOKIE_SPEC</constant>='http.cookie-spec':</title>
|
||||
<para><interfacename>CookieSpec</interfacename> instance representing the actual
|
||||
cookie specification.</para>
|
||||
</formalpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<formalpara>
|
||||
<title><constant>ClientContext.COOKIE_ORIGIN</constant>='http.cookie-origin':</title>
|
||||
<para><classname>CookieOrigin</classname> instance representing the actual
|
||||
details of the origin server.</para>
|
||||
</formalpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<formalpara>
|
||||
<title><constant>ClientContext.COOKIE_STORE</constant>='http.cookie-store':</title>
|
||||
<para><interfacename>CookieStore</interfacename> instance representing the actual
|
||||
cookie store. The value of this attribute set in the local context takes
|
||||
precedence over the default one.</para>
|
||||
|
@ -366,38 +280,26 @@ httpclient.setCookieStore(cookieStore);
|
|||
</itemizedlist>
|
||||
<para>The local <interfacename>HttpContext</interfacename> object can be used to customize
|
||||
the HTTP state management context prior to request execution, or to examine its state after
|
||||
the request has been executed:</para>
|
||||
the request has been executed. One can also use separate execution contexts in order
|
||||
to implement per user (or per thread) state management. A cookie specification registry
|
||||
and cookie store defined in the local context will take precedence over the default
|
||||
ones set at the HTTP client level</para>
|
||||
<programlisting><![CDATA[
|
||||
HttpClient httpclient = new DefaultHttpClient();
|
||||
HttpContext localContext = new BasicHttpContext();
|
||||
HttpGet httpget = new HttpGet("http://localhost:8080/");
|
||||
HttpResponse response = httpclient.execute(httpget, localContext);
|
||||
CloseableHttpClient httpclient = <...>
|
||||
|
||||
CookieOrigin cookieOrigin = (CookieOrigin) localContext.getAttribute(
|
||||
ClientContext.COOKIE_ORIGIN);
|
||||
System.out.println("Cookie origin: " + cookieOrigin);
|
||||
CookieSpec cookieSpec = (CookieSpec) localContext.getAttribute(
|
||||
ClientContext.COOKIE_SPEC);
|
||||
System.out.println("Cookie spec used: " + cookieSpec);
|
||||
]]></programlisting>
|
||||
</section>
|
||||
<section>
|
||||
<title>Per user / thread state management</title>
|
||||
<para>One can use an individual local execution context in order to implement per user (or
|
||||
per thread) state management. A cookie specification registry and cookie store defined in
|
||||
the local context will take precedence over the default ones set at the HTTP client
|
||||
level.</para>
|
||||
<programlisting><![CDATA[
|
||||
HttpClient httpclient = new DefaultHttpClient();
|
||||
// Create a local instance of cookie store
|
||||
CookieStore cookieStore = new BasicCookieStore();
|
||||
// Create local HTTP context
|
||||
HttpContext localContext = new BasicHttpContext();
|
||||
// Bind custom cookie store to the local context
|
||||
localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
|
||||
HttpGet httpget = new HttpGet("http://www.google.com/");
|
||||
// Pass local context as a parameter
|
||||
HttpResponse response = httpclient.execute(httpget, localContext);
|
||||
Registry<CookieSpecProvider> cookieSpecReg = <...>
|
||||
CookieStore cookieStore = <...>
|
||||
|
||||
HttpClientContext context = HttpClientContext.create();
|
||||
context.setCookieSpecRegistry(cookieSpecReg);
|
||||
context.setCookieStore(cookieStore);
|
||||
HttpGet httpget = new HttpGet("http://localhost/1");
|
||||
CloseableHttpResponse response1 = httpclient.execute(httpget, context);
|
||||
<...>
|
||||
// Cookie origin details
|
||||
CookieOrigin cookieOrigin = context.getCookieOrigin();
|
||||
// Cookie spec used
|
||||
CookieSpec cookieSpec = context.getCookieSpec();
|
||||
]]></programlisting>
|
||||
</section>
|
||||
</chapter>
|
||||
|
|
Loading…
Reference in New Issue