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;6.&nbsp;Advanced topics</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="httpagent.html" title="Chapter&nbsp;5.&nbsp;HTTP client service"></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;6.&nbsp;Advanced topics</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="httpagent.html">Prev</a>&nbsp;</td><th width="60%" align="center">&nbsp;</th><td width="20%" align="right">&nbsp;</td></tr></table><hr></div><div class="chapter" lang="en"><div class="titlepage"><div><div><h2 class="title"><a name="advanced"></a>Chapter&nbsp;6.&nbsp;Advanced topics</h2></div></div></div>
  4.    
  5.     <div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d4e1063"></a>6.1.&nbsp;Custom client connections</h2></div></div></div>
  6.        
  7.         <p>In certain situations it may be necessary to customize the way HTTP messages get
  8.             transmitted across the wire beyond what is possible possible using HTTP parameters in
  9.             order to be able to deal non-standard, non-compliant behaviours. For instance, for web
  10.             crawlers it may be necessary to force HttpClient into accepting malformed response heads
  11.             in order to salvage the content of the messages. </p>
  12.         <p>Usually the process of plugging in a custom message parser or a custom connection
  13.             implementation involves several steps:</p>
  14.         <div class="itemizedlist"><ul type="disc"><li>
  15.                 <p>Provide a custom <code class="interfacename">LineParser</code> /
  16.                         <code class="interfacename">LineFormatter</code> interface implementation.
  17.                     Implement message parsing / formatting logic as required.</p>
  18.                 <pre class="programlisting">
  19. class MyLineParser extends BasicLineParser {
  20.  
  21.     @Override
  22.     public Header parseHeader(
  23.             final CharArrayBuffer buffer) throws ParseException {
  24.         try {
  25.             return super.parseHeader(buffer);
  26.         } catch (ParseException ex) {
  27.             // Suppress ParseException exception
  28.             return new BasicHeader("invalid", buffer.toString());
  29.         }
  30.     }
  31.    
  32. }
  33. </pre>
  34.             </li><li>
  35.                 <p>Provide a custom <code class="interfacename">OperatedClientConnection</code>
  36.                     implementation. Replace default request / response parsers, request / response
  37.                     formatters with custom ones as required. Implement different message writing /
  38.                     reading code if necessary.</p>
  39.                 <pre class="programlisting">
  40. class MyClientConnection extends DefaultClientConnection {
  41.  
  42.     @Override
  43.     protected HttpMessageParser createResponseParser(
  44.             final SessionInputBuffer buffer,
  45.             final HttpResponseFactory responseFactory,
  46.             final HttpParams params) {
  47.         return new DefaultResponseParser(
  48.                 buffer,
  49.                 new MyLineParser(),
  50.                 responseFactory,
  51.                 params);
  52.     }
  53.    
  54. }
  55. </pre>
  56.             </li><li>
  57.                 <p>Provide a custom <code class="interfacename">ClientConnectionOperator</code>
  58.                     interface implementation in order to create connections of new class. Implement
  59.                     different socket initialization code if necessary.</p>
  60.                 <pre class="programlisting">
  61. class MyClientConnectionOperator extends DefaultClientConnectionOperator {
  62.    
  63.     public MyClientConnectionOperator(final SchemeRegistry sr) {
  64.         super(sr);
  65.     }
  66.  
  67.     @Override
  68.     public OperatedClientConnection createConnection() {
  69.         return new MyClientConnection();
  70.     }
  71.    
  72. }
  73. </pre>
  74.             </li><li>
  75.                 <p>Provide a custom <code class="interfacename">ClientConnectionManager</code>
  76.                     interface implementation in order to create connection operator of new
  77.                     class.</p>
  78.                 <pre class="programlisting">
  79. class MyClientConnManager extends SingleClientConnManager {
  80.    
  81.     public MyClientConnManager(
  82.             final HttpParams params,
  83.             final SchemeRegistry sr) {
  84.         super(params, sr);
  85.     }
  86.  
  87.     @Override
  88.     protected ClientConnectionOperator createConnectionOperator(
  89.             final SchemeRegistry sr) {
  90.         return new MyClientConnectionOperator(sr);
  91.     }
  92.    
  93. }
  94. </pre>
  95.             </li></ul></div>
  96.     </div>
  97.     <div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="stateful_conn"></a>6.2.&nbsp;Stateful HTTP connections</h2></div></div></div>
  98.        
  99.         <p>While HTTP specification assumes that session state information is always embedded in
  100.             HTTP messages in the form of HTTP cookies and therefore HTTP connections are always
  101.             stateless, this assumption does not always hold true in real life. There are cases when
  102.             HTTP connections are created with a particular user identity or within a particular
  103.             security context and therefore cannot be shared with other users and can be reused by
  104.             the same user only. Examples of such stateful HTTP connections are
  105.                 <code class="literal">NTLM</code> authenticated connections and SSL connections with client
  106.             certificate authentication.</p>
  107.         <div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="d4e1089"></a>6.2.1.&nbsp;User token handler</h3></div></div></div>
  108.            
  109.             <p>HttpClient relies on <code class="interfacename">UserTokenHandler</code> interface to
  110.                 determine if the given execution context is user specific or not. The token object
  111.                 returned by this handler is expected to uniquely identify the current user if the
  112.                 context is user specific or to be null if the context does not contain any resources
  113.                 or details specific to the current user. The user token will be used to ensure that
  114.                 user specific resources will not be shared with or reused by other users.</p>
  115.             <p>The default implementation of the <code class="interfacename">UserTokenHandler</code>
  116.                 interface uses an instance of Principal class to represent a state object for HTTP
  117.                 connections, if it can be obtained from the given execution context.
  118.                     <code class="classname">DefaultUserTokenHandler</code> will use the user principle of
  119.                 connection based authentication schemes such as <code class="literal">NTLM</code> or that of
  120.                 the SSL session with client authentication turned on. If both are unavailable, null
  121.                 token will be returned.</p>
  122.             <p>Users can provide a custom implementation if the default one does not satisfy
  123.                 their needs:</p>
  124.             <pre class="programlisting">
  125. DefaultHttpClient httpclient = new DefaultHttpClient();
  126. httpclient.setUserTokenHandler(new UserTokenHandler() {
  127.  
  128.     public Object getUserToken(HttpContext context) {
  129.         return context.getAttribute("my-token");
  130.     }
  131.    
  132. });
  133. </pre>
  134.         </div>
  135.         <div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="d4e1099"></a>6.2.2.&nbsp;User token and execution context</h3></div></div></div>
  136.            
  137.             <p>In the course of HTTP request execution HttpClient adds the following user
  138.                 identity related objects to the execution context: </p>
  139.             <div class="itemizedlist"><ul type="disc"><li>
  140.                     <p>
  141.                         <b>'http.user-token':&nbsp;</b>
  142.                         Object instance representing the actual user identity, usually
  143.                             expected to be an instance of <code class="interfacename">Principle</code>
  144.                             interface
  145.                     </p>
  146.                 </li></ul></div>
  147.             <p>One can find out whether or not the connection used to execute the request was
  148.                 stateful by examining the content of the local HTTP context after the request has
  149.                 been executed.</p>
  150.             <pre class="programlisting">
  151. DefaultHttpClient httpclient = new DefaultHttpClient();
  152. HttpContext localContext = new BasicHttpContext();
  153. HttpGet httpget = new HttpGet("http://localhost:8080/");
  154. HttpResponse response = httpclient.execute(httpget, localContext);
  155. HttpEntity entity = response.getEntity();
  156. if (entity != null) {
  157.     entity.consumeContent();
  158. }
  159. Object userToken = localContext.getAttribute(ClientContext.USER_TOKEN);
  160. System.out.println(userToken);
  161. </pre>
  162.             <div class="section" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="d4e1110"></a>6.2.2.1.&nbsp;Persistent stateful connections</h4></div></div></div>
  163.                
  164.                 <p>Please note that persistent connection that carry a state object can be reused
  165.                     only if the same state object is bound to the execution context when requests
  166.                     are executed. So, it is really important to ensure the either same context is
  167.                     reused for execution of subsequent HTTP requests by the same user or the user
  168.                     token is bound to the context prior to request execution.</p>
  169.                 <pre class="programlisting">
  170. DefaultHttpClient httpclient = new DefaultHttpClient();
  171. HttpContext localContext1 = new BasicHttpContext();
  172. HttpGet httpget1 = new HttpGet("http://localhost:8080/");
  173. HttpResponse response1 = httpclient.execute(httpget1, localContext1);
  174. HttpEntity entity1 = response1.getEntity();
  175. if (entity1 != null) {
  176.     entity1.consumeContent();
  177. }
  178. Principal principal = (Principal) localContext1.getAttribute(
  179.         ClientContext.USER_TOKEN);
  180.  
  181. HttpContext localContext2 = new BasicHttpContext();
  182. localContext2.setAttribute(ClientContext.USER_TOKEN, principal);
  183. HttpGet httpget2 = new HttpGet("http://localhost:8080/");
  184. HttpResponse response2 = httpclient.execute(httpget2, localContext2);
  185. HttpEntity entity2 = response2.getEntity();
  186. if (entity2 != null) {
  187.     entity2.consumeContent();
  188. }
  189. </pre>
  190.             </div>
  191.         </div>
  192.  
  193.     </div>
  194.  
  195. </div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="httpagent.html">Prev</a>&nbsp;</td><td width="20%" align="center">&nbsp;</td><td width="40%" align="right">&nbsp;</td></tr><tr><td width="40%" align="left" valign="top">Chapter&nbsp;5.&nbsp;HTTP client service&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top">&nbsp;</td></tr></table></div></body></html>