Subversion Repositories javautils

Rev

Blame | Last modification | View Log | RSS feed

  1. <html><head>
  2.       <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
  3.    <title>Chapter&nbsp;3.&nbsp;HTTP state management</title><link rel="stylesheet" href="css/hc-tutorial.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.73.2"><link rel="start" href="index.html" title="HttpClient Tutorial"><link rel="up" href="index.html" title="HttpClient Tutorial"><link rel="prev" href="connmgmt.html" title="Chapter&nbsp;2.&nbsp;Connection management"><link rel="next" href="authentication.html" title="Chapter&nbsp;4.&nbsp;HTTP authentication"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div xmlns:fo="http://www.w3.org/1999/XSL/Format" class="banner"><a class="bannerLeft" href="http://www.apache.org/" title="Apache Software Foundation"><img style="border:none;" src="images/asf_logo_wide.gif"></a><a class="bannerRight" href="http://hc.apache.org/httpcomponents-core/" title="Apache HttpComponents Core"><img style="border:none;" src="images/hc_logo.png"></a><div class="clear"></div></div><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Chapter&nbsp;3.&nbsp;HTTP state management</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="connmgmt.html">Prev</a>&nbsp;</td><th width="60%" align="center">&nbsp;</th><td width="20%" align="right">&nbsp;<a accesskey="n" href="authentication.html">Next</a></td></tr></table><hr></div><div class="chapter" lang="en"><div class="titlepage"><div><div><h2 class="title"><a name="statemgmt"></a>Chapter&nbsp;3.&nbsp;HTTP state management</h2></div></div></div>
  4.    
  5.     <p>Originally HTTP was designed as a stateless, request / response oriented protocol that
  6.         made no special provisions for stateful sessions spanning across several logically related
  7.         request / response exchanges. As HTTP protocol grew in popularity and adoption more and more
  8.         systems began to use it for applications it was never intended for, for instance as a
  9.         transport for e-commerce applications. Thus, the support for state management became a
  10.         necessity.</p>
  11.     <p>Netscape Communications, at that time a leading developer of web client and server
  12.         software, implemented support for HTTP state management in their products based on a
  13.         proprietary specification. Later, Netscape tried to standardise the mechanism by publishing
  14.         a specification draft. Those efforts contributed to the formal specification defined through
  15.         the RFC standard track. However, state management in a significant number of applications is
  16.         still largely based on the Netscape draft and is incompatible with the official
  17.         specification. All major developers of web browsers felt compelled to retain compatibility
  18.         with those applications greatly contributing to the fragmentation of standards
  19.         compliance.</p>
  20.     <div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d4e655"></a>3.1.&nbsp;HTTP cookies</h2></div></div></div>
  21.        
  22.         <p>Cookie is a token or short packet of state information that the HTTP agent and the
  23.             target server can exchange to maintain a session. Netscape engineers used to refer to it
  24.             as as a "magic cookie" and the name stuck.</p>
  25.         <p>HttpClient uses <code class="interfacename">Cookie</code> interface to represent an
  26.             abstract cookie token. In its simples form an HTTP cookie is merely a name / value pair.
  27.             Usually an HTTP cookie also contains a number of attributes such as version, a domain
  28.             for which is valid, a path that specifies the subset of URLs on the origin server to
  29.             which this cookie applies, and maximum period of time the cookie is valid for.</p>
  30.         <p><code class="interfacename">SetCookie</code> interface represents a
  31.                 <code class="literal">Set-Cookie</code> response header sent by the origin server to the HTTP
  32.             agent in order to maintain a conversational state.
  33.                 <code class="interfacename">SetCookie2</code> interface extends SetCookie with
  34.                 <code class="literal">Set-Cookie2</code> specific methods.</p>
  35.         <p><code class="interfacename">ClientCookie</code> interface extends
  36.                 <code class="interfacename">Cookie</code> interface with additional client specific
  37.             functionality such ability to retrieve original cookie attributes exactly as they were
  38.             specified by the origin server. This is important for generating the
  39.                 <code class="literal">Cookie</code> header because some cookie specifications require that the
  40.                 <code class="literal">Cookie</code> header should include certain attributes only if they were
  41.             specified in the <code class="literal">Set-Cookie</code> or <code class="literal">Set-Cookie2</code>
  42.             header.</p>
  43.         <div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="d4e672"></a>3.1.1.&nbsp;Cookie versions</h3></div></div></div>
  44.            
  45.             <p>Cookies compatible with Netscape draft specification but non-compliant with the
  46.                 official specification are considered to be of version 0. Standard compliant cookies
  47.                 are expected to have version 1. HttpClient may handle cookies differently depending
  48.                 on the version.</p>
  49.             <p>Here is an example of re-creating a Netscape cookie:</p>
  50.             <pre class="programlisting">
  51. BasicClientCookie netscapeCookie = new BasicClientCookie("name", "value");
  52. netscapeCookie.setVersion(0);
  53. netscapeCookie.setDomain(".mycompany.com");
  54. netscapeCookie.setPath("/");
  55. </pre>
  56.             <p>Here is an example of re-creating a standard cookie. Please note that standard
  57.                 compliant cookie must retain all attributes as sent by the origin server:</p>
  58.             <pre class="programlisting">
  59. BasicClientCookie stdCookie = new BasicClientCookie("name", "value");
  60. stdCookie.setVersion(1);
  61. stdCookie.setDomain(".mycompany.com");
  62. stdCookie.setPath("/");
  63. stdCookie.setSecure(true);
  64. // Set attributes EXACTLY as sent by the server
  65. stdCookie.setAttribute(ClientCookie.VERSION_ATTR, "1");
  66. stdCookie.setAttribute(ClientCookie.DOMAIN_ATTR, ".mycompany.com");
  67. </pre>
  68.             <p>Here is an example of re-creating a <code class="literal">Set-Cookie2</code> compliant
  69.                 cookie. Please note that standard compliant cookie must retain all attributes as
  70.                 sent by the origin server:</p>
  71.             <pre class="programlisting">
  72. BasicClientCookie2 stdCookie = new BasicClientCookie2("name", "value");
  73. stdCookie.setVersion(1);
  74. stdCookie.setDomain(".mycompany.com");
  75. stdCookie.setPorts(new int[] {80,8080});
  76. stdCookie.setPath("/");
  77. stdCookie.setSecure(true);
  78. // Set attributes EXACTLY as sent by the server
  79. stdCookie.setAttribute(ClientCookie.VERSION_ATTR, "1");
  80. stdCookie.setAttribute(ClientCookie.DOMAIN_ATTR, ".mycompany.com");
  81. stdCookie.setAttribute(ClientCookie.PORT_ATTR, "80,8080");
  82. </pre>
  83.         </div>
  84.     </div>
  85.     <div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d4e682"></a>3.2.&nbsp;Cookie specifications</h2></div></div></div>
  86.        
  87.         <p><code class="interfacename">CookieSpec</code> interface represents a cookie management
  88.             specification. Cookie management specification is expected to enforce:</p>
  89.         <div class="itemizedlist"><ul type="disc"><li>
  90.                 <p>rules of parsing <code class="literal">Set-Cookie</code> and optionally
  91.                         <code class="literal">Set-Cookie2</code> headers.</p>
  92.             </li><li>
  93.                 <p>rules of validation of parsed cookies.</p>
  94.             </li><li>
  95.                 <p>formatting of <code class="literal">Cookie</code> header for a given host, port and path
  96.                     of origin.</p>
  97.             </li></ul></div>
  98.         <p>HttpClient ships with several <code class="interfacename">CookieSpec</code>
  99.             implementations:</p>
  100.         <div class="itemizedlist"><ul type="disc"><li>
  101.                 <p>
  102.                     <b>Netscape draft:&nbsp;</b>
  103.                     This specification conforms to the original draft specification published
  104.                         by Netscape Communications. It should be avoided unless absolutely necessary
  105.                         for compatibility with legacy code.
  106.                 </p>
  107.             </li><li>
  108.                 <p>
  109.                     <b>RFC 2109:&nbsp;</b>
  110.                     Older version of the official HTTP state management specification
  111.                         superseded by RFC 2965.
  112.                 </p>
  113.             </li><li>
  114.                 <p>
  115.                     <b>RFC 2965:&nbsp;</b>
  116.                     The official HTTP state management specification.
  117.                 </p>
  118.             </li><li>
  119.                 <p>
  120.                     <b>Browser compatibility:&nbsp;</b>
  121.                     This implementations strives to closely mimic (mis)behavior of common web
  122.                         browser applications such as Microsoft Internet Explorer and Mozilla
  123.                         FireFox.
  124.                 </p>
  125.             </li><li>
  126.                 <p>
  127.                     <b>Best match:&nbsp;</b>
  128.                     'Meta' cookie specification that picks up a cookie policy based on the
  129.                         format of cookies sent with the HTTP response. It basically aggregates all
  130.                         above implementations into one class.
  131.                 </p>
  132.             </li></ul></div>
  133.         <p>It is strongly recommended to use the <code class="literal">Best Match</code> policy and let
  134.             HttpClient pick up an appropriate compliance level at runtime based on the execution
  135.             context.</p>
  136.     </div>
  137.     <div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d4e721"></a>3.3.&nbsp;HTTP cookie and state management parameters</h2></div></div></div>
  138.        
  139.         <p>These are parameters that be used to customize HTTP state management and behaviour of
  140.             individual cookie specifications:</p>
  141.         <div class="itemizedlist"><ul type="disc"><li>
  142.                 <p>
  143.                     <b>'http.protocol.cookie-datepatterns':&nbsp;</b>
  144.                     defines valid date patterns to be used for parsing non-standard
  145.                             <code class="literal">expires</code> attribute. Only required for compatibility
  146.                         with non-compliant servers that still use <code class="literal">expires</code> defined
  147.                         in the Netscape draft instead of the standard <code class="literal">max-age</code>
  148.                         attribute. This parameter expects a value of type
  149.                             <code class="interfacename">java.util.Collection</code>. The collection
  150.                         elements must be of type <code class="classname">java.lang.String</code> compatible
  151.                         with the syntax of <code class="classname">java.text.SimpleDateFormat</code>. If
  152.                         this parameter is not set the choice of a default value is
  153.                             <code class="interfacename">CookieSpec</code> implementation specific.
  154.                         Please note this parameter applies
  155.                 </p>
  156.             </li><li>
  157.                 <p>
  158.                     <b>'http.protocol.single-cookie-header':&nbsp;</b>
  159.                     defines whether cookies should be forced into a single
  160.                             <code class="literal">Cookie</code> request header. Otherwise, each cookie is
  161.                         formatted as a separate <code class="literal">Cookie</code> header. This parameter
  162.                         expects a value of type <code class="classname">java.lang.Boolean</code>. If this
  163.                         parameter is not set the choice of a default value is CookieSpec
  164.                         implementation specific. Please note this parameter applies to strict cookie
  165.                         specifications (RFC 2109 and RFC 2965) only. Browser compatibility and
  166.                         netscape draft policies will always put all cookies into one request
  167.                         header.
  168.                 </p>
  169.             </li><li>
  170.                 <p>
  171.                     <b>'http.protocol.cookie-policy':&nbsp;</b>
  172.                     defines the name of a cookie specification to be used for HTTP state
  173.                         management. This parameter expects a value of type
  174.                             <code class="classname">java.lang.String</code>. If this parameter is not set
  175.                         valid date patterns are <code class="interfacename">CookieSpec</code>
  176.                         implementation specific.
  177.                 </p>
  178.             </li></ul></div>
  179.     </div>
  180.     <div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d4e749"></a>3.4.&nbsp;Cookie specification registry</h2></div></div></div>
  181.        
  182.         <p>HttpClient maintains a registry of available cookie specifications using
  183.                 <code class="classname">CookieSpecRegistry</code> class. The following specifications are
  184.             registered per default:</p>
  185.         <div class="itemizedlist"><ul type="disc"><li>
  186.                 <p>
  187.                     <b>compatibility:&nbsp;</b>
  188.                      Browser compatibility (lenient policy).
  189.                 </p>
  190.             </li><li>
  191.                 <p>
  192.                     <b>netscape:&nbsp;</b>
  193.                     Netscape draft.
  194.                 </p>
  195.             </li><li>
  196.                 <p>
  197.                     <b>rfc2109:&nbsp;</b>
  198.                     RFC 2109 (outdated strict policy).
  199.                 </p>
  200.             </li><li>
  201.                 <p>
  202.                     <b>rfc2965:&nbsp;</b>
  203.                     RFC 2965 (standard conformant strict policy).
  204.                 </p>
  205.             </li><li>
  206.                 <p>
  207.                     <b>best-match:&nbsp;</b>
  208.                     Best match meta-policy.
  209.                 </p>
  210.             </li></ul></div>
  211.     </div>
  212.     <div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d4e774"></a>3.5.&nbsp;Choosing cookie policy</h2></div></div></div>
  213.        
  214.         <p>Cookie policy can be set at the HTTP client and overridden on the HTTP request level
  215.             if required.</p>
  216.         <pre class="programlisting">
  217. HttpClient httpclient = new DefaultHttpClient();
  218. // force strict cookie policy per default
  219. httpclient.getParams().setParameter(
  220.         ClientPNames.COOKIE_POLICY, CookiePolicy.RFC_2965);
  221.  
  222. HttpGet httpget = new HttpGet("http://www.broken-server.com/");
  223. // Override the default policy for this request
  224. httpget.getParams().setParameter(
  225.         ClientPNames.COOKIE_POLICY, CookiePolicy.BROWSER_COMPATIBILITY);
  226. </pre>
  227.     </div>
  228.     <div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d4e778"></a>3.6.&nbsp;Custom cookie policy</h2></div></div></div>
  229.        
  230.         <p>In order to implement a custom cookie policy one should create a custom implementation
  231.             of <code class="interfacename">CookieSpec</code> interface, create a
  232.                 <code class="interfacename">CookieSpecFactory</code> implementation to create and
  233.             initialize instances of the custom specification and register the factory with
  234.             HttpClient. Once the custom specification has been registered, it can be activated the
  235.             same way as the standard cookie specifications.</p>
  236.         <pre class="programlisting">
  237. CookieSpecFactory csf = new CookieSpecFactory() {
  238.     public CookieSpec newInstance(HttpParams params) {
  239.         return new BrowserCompatSpec() {  
  240.             @Override
  241.             public void validate(Cookie cookie, CookieOrigin origin)
  242.             throws MalformedCookieException {
  243.                 // Oh, I am easy
  244.             }          
  245.         };
  246.     }  
  247. };
  248.  
  249. DefaultHttpClient httpclient = new DefaultHttpClient();
  250. httpclient.getCookieSpecs().register("easy", csf);
  251. httpclient.getParams().setParameter(
  252.      ClientPNames.COOKIE_POLICY, "easy");
  253. </pre>
  254.     </div>
  255.     <div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d4e784"></a>3.7.&nbsp;Cookie persistence</h2></div></div></div>
  256.        
  257.         <p>HttpClient can work with any physical representation of a persistent cookie store that
  258.             implements the <code class="interfacename">CookieStore</code> interface. The default
  259.                 <code class="interfacename">CookieStore</code> implementation called
  260.                 <code class="classname">BasicClientCookie</code> is a simple implementation backed by a
  261.                 <code class="classname">java.util.ArrayList</code>. Cookies stored in an
  262.                 <code class="classname">BasicClientCookie</code> object are lost when the container object
  263.             get garbage collected. Users can provide more complex implementations if
  264.             necessary.</p>
  265.         <pre class="programlisting">
  266. DefaultHttpClient httpclient = new DefaultHttpClient();
  267. // Create a local instance of cookie store
  268. CookieStore cookieStore = new MyCookieStore();
  269. // Populate cookies if needed
  270. BasicClientCookie cookie = new BasicClientCookie("name", "value");
  271. cookie.setVersion(0);
  272. cookie.setDomain(".mycompany.com");
  273. cookie.setPath("/");
  274. cookieStore.addCookie(cookie);
  275. // Set the store
  276. httpclient.setCookieStore(cookieStore);
  277. </pre>
  278.     </div>
  279.     <div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d4e793"></a>3.8.&nbsp;HTTP state management and execution context</h2></div></div></div>
  280.        
  281.         <p>In the course of HTTP request execution HttpClient adds the following state management
  282.             related objects to the execution context:</p>
  283.         <div class="itemizedlist"><ul type="disc"><li>
  284.                 <p>
  285.                     <b>'http.cookiespec-registry':&nbsp;</b>
  286.                     <code class="classname">CookieSpecRegistry</code> instance representing the actual
  287.                         cookie specification registry. The value of this attribute set in the local
  288.                         context takes precedence over the default one.
  289.                 </p>
  290.             </li><li>
  291.                 <p>
  292.                     <b>'http.cookie-spec':&nbsp;</b>
  293.                     <code class="interfacename">CookieSpec</code> instance representing the actual
  294.                         cookie specification.
  295.                 </p>
  296.             </li><li>
  297.                 <p>
  298.                     <b>'http.cookie-origin':&nbsp;</b>
  299.                     <code class="classname">CookieOrigin</code> instance representing the actual
  300.                         details of the origin server.
  301.                 </p>
  302.             </li><li>
  303.                 <p>
  304.                     <b>'http.cookie-store':&nbsp;</b>
  305.                     <code class="interfacename">CookieStore</code> instance represents the actual
  306.                         cookie store. The value of this attribute set in the local context takes
  307.                         precedence over the default one.
  308.                 </p>
  309.             </li></ul></div>
  310.         <p>The local <code class="interfacename">HttpContext</code> object can be used to customize
  311.             the HTTP state management context prior to request execution or examine its state after
  312.             the request has been executed:</p>
  313.         <pre class="programlisting">
  314. HttpClient httpclient = new DefaultHttpClient();
  315. HttpContext localContext = new BasicHttpContext();
  316. HttpGet httpget = new HttpGet("http://localhost:8080/");
  317. HttpResponse response = httpclient.execute(httpget, localContext);
  318.  
  319. CookieOrigin cookieOrigin = (CookieOrigin) localContext.getAttribute(
  320.         ClientContext.COOKIE_ORIGIN);
  321. System.out.println("Cookie origin: " + cookieOrigin);
  322. CookieSpec cookieSpec = (CookieSpec) localContext.getAttribute(
  323.         ClientContext.COOKIE_SPEC);
  324. System.out.println("Cookie spec used: " + cookieSpec);
  325. </pre>
  326.     </div>
  327.     <div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d4e820"></a>3.9.&nbsp;Per user / thread state management</h2></div></div></div>
  328.        
  329.         <p>One can use an individual local execution context in order to implement per user (or
  330.             per thread) state management. Cookie specification registry and cookie store defined in
  331.             the local context will take precedence over the default ones set at the HTTP client
  332.             level.</p>
  333.         <pre class="programlisting">
  334. HttpClient httpclient = new DefaultHttpClient();
  335. // Create a local instance of cookie store
  336. CookieStore cookieStore = new BasicCookieStore();
  337. // Create local HTTP context
  338. HttpContext localContext = new BasicHttpContext();
  339. // Bind custom cookie store to the local context
  340. localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
  341. HttpGet httpget = new HttpGet("http://www.google.com/");
  342. // Pass local context as a parameter
  343. HttpResponse response = httpclient.execute(httpget, localContext);
  344. </pre>
  345.     </div>
  346. </div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="connmgmt.html">Prev</a>&nbsp;</td><td width="20%" align="center">&nbsp;</td><td width="40%" align="right">&nbsp;<a accesskey="n" href="authentication.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Chapter&nbsp;2.&nbsp;Connection management&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top">&nbsp;Chapter&nbsp;4.&nbsp;HTTP authentication</td></tr></table></div></body></html>