| <?xml version="1.0" encoding="UTF-8"?> |
| <!DOCTYPE preface PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" |
| "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd"> |
| <!-- |
| ==================================================================== |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, |
| software distributed under the License is distributed on an |
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| KIND, either express or implied. See the License for the |
| specific language governing permissions and limitations |
| under the License. |
| ==================================================================== |
| --> |
| <chapter id="statemgmt"> |
| <title>HTTP state management</title> |
| <para>Originally HTTP was designed as a stateless, request / response oriented protocol that |
| made no special provisions for stateful sessions spanning across several logically related |
| request / response exchanges. As HTTP protocol grew in popularity and adoption more and more |
| systems began to use it for applications it was never intended for, for instance as a |
| transport for e-commerce applications. Thus, the support for state management became a |
| necessity.</para> |
| <para>Netscape Communications, at that time a leading developer of web client and server |
| software, implemented support for HTTP state management in their products based on a |
| proprietary specification. Later, Netscape tried to standardise the mechanism by publishing |
| a specification draft. Those efforts contributed to the formal specification defined through |
| the RFC standard track. However, state management in a significant number of applications is |
| still largely based on the Netscape draft and is incompatible with the official |
| specification. All major developers of web browsers felt compelled to retain compatibility |
| with those applications greatly contributing to the fragmentation of standards |
| compliance.</para> |
| <section> |
| <title>HTTP cookies</title> |
| <para>An HTTP cookie is a token or short packet of state information that the HTTP agent and the |
| target server can exchange to maintain a session. Netscape engineers used to refer to it |
| as a "magic cookie" and the name stuck.</para> |
| <para>HttpClient uses the <interfacename>Cookie</interfacename> interface to represent an |
| abstract cookie token. In its simplest form an HTTP cookie is merely a name / value pair. |
| Usually an HTTP cookie also contains a number of attributes such a domain for which is |
| valid, a path that specifies the subset of URLs on the origin server to which this |
| cookie applies, and the maximum period of time for which the cookie is valid.</para> |
| <para>The <interfacename>SetCookie</interfacename> interface represents a |
| <literal>Set-Cookie</literal> response header sent by the origin server to the HTTP |
| agent in order to maintain a conversational state.</para> |
| <para>The <interfacename>ClientCookie</interfacename> interface extends <interfacename> |
| Cookie</interfacename> interface with additional client specific functionality such |
| as the ability to retrieve original cookie attributes exactly as they were specified |
| by the origin server. This is important for generating the <literal>Cookie</literal> |
| header because some cookie specifications require that the <literal>Cookie</literal> |
| header should include certain attributes only if they were specified in the |
| <literal>Set-Cookie</literal> header.</para> |
| <para>Here is an example of creating a client-side cookie object:</para> |
| <programlisting><![CDATA[ |
| BasicClientCookie cookie = new BasicClientCookie("name", "value"); |
| // Set effective domain and path attributes |
| cookie.setDomain(".mycompany.com"); |
| cookie.setPath("/"); |
| // Set attributes exactly as sent by the server |
| cookie.setAttribute(ClientCookie.PATH_ATTR, "/"); |
| cookie.setAttribute(ClientCookie.DOMAIN_ATTR, ".mycompany.com"); |
| ]]></programlisting> |
| </section> |
| <section> |
| <title>Cookie specifications</title> |
| <para>The <interfacename>CookieSpec</interfacename> interface represents a cookie management |
| specification. The cookie management specification is expected to enforce:</para> |
| <itemizedlist> |
| <listitem> |
| <para>rules of parsing <literal>Set-Cookie</literal> headers.</para> |
| </listitem> |
| <listitem> |
| <para>rules of validation of parsed cookies.</para> |
| </listitem> |
| <listitem> |
| <para>formatting of <literal>Cookie</literal> header for a given host, port and path |
| of origin.</para> |
| </listitem> |
| </itemizedlist> |
| <para>HttpClient ships with several <interfacename>CookieSpec</interfacename> |
| implementations:</para> |
| <itemizedlist> |
| <listitem> |
| <formalpara> |
| <title>Standard strict:</title> |
| <para>State management policy compliant with the syntax and semantics of |
| the well-behaved profile defined by RFC 6265, section 4.</para> |
| </formalpara> |
| </listitem> |
| <listitem> |
| <formalpara> |
| <title>Standard:</title> |
| <para>State management policy compliant with a more relaxed profile defined |
| by RFC 6265, section 4 intended for interoperability with existing servers |
| that do not conform to the well behaved profile.</para> |
| </formalpara> |
| </listitem> |
| <listitem> |
| <formalpara> |
| <title>Netscape draft (obsolete):</title> |
| <para>This policy conforms to the original draft specification published |
| by Netscape Communications. It should be avoided unless absolutely necessary |
| for compatibility with legacy code.</para> |
| </formalpara> |
| </listitem> |
| <listitem> |
| <formalpara> |
| <title>RFC 2965 (obsolete):</title> |
| <para>State management policy compliant with the obsolete state management |
| specification defined by RFC 2965. Please do not use in new applications. |
| </para> |
| </formalpara> |
| </listitem> |
| <listitem> |
| <formalpara> |
| <title>RFC 2109 (obsolete):</title> |
| <para>State management policy compliant with the obsolete state management |
| specification defined by RFC 2109. Please do not use in new applications. |
| </para> |
| </formalpara> |
| </listitem> |
| <listitem> |
| <formalpara> |
| <title>Browser compatibility (obsolete):</title> |
| <para>This policy strives to closely mimic the (mis)behavior of older versions |
| of browser applications such as Microsoft Internet Explorer and Mozilla |
| FireFox. Please do not use in new applications.</para> |
| </formalpara> |
| </listitem> |
| <listitem> |
| <formalpara> |
| <title>Default:</title> |
| <para>Default cookie policy is a synthetic policy that picks up either RFC 2965, |
| RFC 2109 or Netscape draft compliant implementation based on properties of |
| cookies sent with the HTTP response (such as version attribute, |
| now obsolete). This policy will be deprecated in favor of the |
| standard (RFC 6265 compliant) implementation in the next minor release |
| of HttpClient.</para> |
| </formalpara> |
| </listitem> |
| <listitem> |
| <formalpara> |
| <title>Ignore cookies:</title> |
| <para>All cookies are ignored.</para> |
| </formalpara> |
| </listitem> |
| </itemizedlist> |
| <para>It is strongly recommended to use either <literal>Standard</literal> or |
| <literal>Standard strict</literal> policy in new applications. Obsolete specifications |
| should be used for compatibility with legacy systems only. Support for obsolete |
| specifications will be removed in the next major release of HttpClient. |
| </para> |
| </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[ |
| RequestConfig globalConfig = RequestConfig.custom() |
| .setCookieSpec(CookieSpecs.DEFAULT) |
| .build(); |
| CloseableHttpClient httpclient = HttpClients.custom() |
| .setDefaultRequestConfig(globalConfig) |
| .build(); |
| RequestConfig localConfig = RequestConfig.copy(globalConfig) |
| .setCookieSpec(CookieSpecs.STANDARD_STRICT) |
| .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>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[ |
| PublicSuffixMatcher publicSuffixMatcher = PublicSuffixMatcherLoader.getDefault(); |
| |
| Registry<CookieSpecProvider> r = RegistryBuilder.<CookieSpecProvider>create() |
| .register(CookieSpecs.DEFAULT, |
| new DefaultCookieSpecProvider(publicSuffixMatcher)) |
| .register(CookieSpecs.STANDARD, |
| new RFC6265CookieSpecProvider(publicSuffixMatcher)) |
| .register("easy", new EasySpecProvider()) |
| .build(); |
| |
| RequestConfig requestConfig = RequestConfig.custom() |
| .setCookieSpec("easy") |
| .build(); |
| |
| CloseableHttpClient httpclient = HttpClients.custom() |
| .setDefaultCookieSpecRegistry(r) |
| .setDefaultRequestConfig(requestConfig) |
| .build(); |
| ]]></programlisting> |
| </section> |
| <section> |
| <title>Cookie persistence</title> |
| <para>HttpClient can work with any physical representation of a persistent cookie store that |
| implements the <interfacename>CookieStore</interfacename> interface. The default |
| <interfacename>CookieStore</interfacename> implementation called |
| <classname>BasicCookieStore</classname> is a simple implementation backed by a |
| <classname>java.util.ArrayList</classname>. Cookies stored in an |
| <classname>BasicClientCookie</classname> object are lost when the container object |
| get garbage collected. Users can provide more complex implementations if |
| necessary.</para> |
| <programlisting><![CDATA[ |
| // Create a local instance of cookie store |
| CookieStore cookieStore = new BasicCookieStore(); |
| // Populate cookies if needed |
| BasicClientCookie cookie = new BasicClientCookie("name", "value"); |
| cookie.setDomain(".mycompany.com"); |
| cookie.setPath("/"); |
| cookieStore.addCookie(cookie); |
| // Set the store |
| CloseableHttpClient httpclient = HttpClients.custom() |
| .setDefaultCookieStore(cookieStore) |
| .build(); |
| ]]></programlisting> |
| </section> |
| <section> |
| <title>HTTP state management and execution context</title> |
| <para>In the course of HTTP request execution HttpClient adds the following state management |
| related objects to the execution context:</para> |
| <itemizedlist> |
| <listitem> |
| <formalpara> |
| <para><interfacename>Lookup</interfacename> instance representing the actual |
| cookie specification registry. The value of this attribute set in the local |
| context takes precedence over the default one.</para> |
| </formalpara> |
| </listitem> |
| <listitem> |
| <formalpara> |
| <para><interfacename>CookieSpec</interfacename> instance representing the actual |
| cookie specification.</para> |
| </formalpara> |
| </listitem> |
| <listitem> |
| <formalpara> |
| <para><classname>CookieOrigin</classname> instance representing the actual |
| details of the origin server.</para> |
| </formalpara> |
| </listitem> |
| <listitem> |
| <formalpara> |
| <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> |
| </formalpara> |
| </listitem> |
| </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. 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[ |
| CloseableHttpClient httpclient = <...> |
| |
| Lookup<CookieSpecProvider> cookieSpecReg = <...> |
| CookieStore cookieStore = <...> |
| |
| HttpClientContext context = HttpClientContext.create(); |
| context.setCookieSpecRegistry(cookieSpecReg); |
| context.setCookieStore(cookieStore); |
| HttpGet httpget = new HttpGet("http://somehost/"); |
| CloseableHttpResponse response1 = httpclient.execute(httpget, context); |
| <...> |
| // Cookie origin details |
| CookieOrigin cookieOrigin = context.getCookieOrigin(); |
| // Cookie spec used |
| CookieSpec cookieSpec = context.getCookieSpec(); |
| ]]></programlisting> |
| </section> |
| </chapter> |