| <?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="httpagent"> |
| <title>HTTP client service</title> |
| <section> |
| <title>HttpClient facade</title> |
| <para><interfacename>HttpClient</interfacename> interface represents the most essential |
| contract for HTTP request execution. It imposes no restrictions or particular details on |
| the request execution process and leaves the specifics of connection management, state |
| management, authentication and redirect handling up to individual implementations. This |
| should make it easier to decorate the interface with additional functionality such as |
| response content caching.</para> |
| <para><classname>DefaultHttpClient</classname> is the default implementation of the |
| <interfacename>HttpClient</interfacename> interface. This class acts as a facade to |
| a number of special purpose handler or strategy interface implementations responsible |
| for handling of a particular aspect of the HTTP protocol such as redirect or |
| authentication handling or making decision about connection persistence and keep alive |
| duration. This enables the users to selectively replace default implementation of those |
| aspects with custom, application specific ones.</para> |
| <programlisting><![CDATA[ |
| DefaultHttpClient httpclient = new DefaultHttpClient(); |
| |
| httpclient.setKeepAliveStrategy(new DefaultConnectionKeepAliveStrategy() { |
| |
| @Override |
| public long getKeepAliveDuration( |
| HttpResponse response, |
| HttpContext context) { |
| long keepAlive = super.getKeepAliveDuration(response, context); |
| if (keepAlive == -1) { |
| // Keep connections alive 5 seconds if a keep-alive value |
| // has not be explicitly set by the server |
| keepAlive = 5000; |
| } |
| return keepAlive; |
| } |
| |
| }); |
| ]]></programlisting> |
| <para><classname>DefaultHttpClient</classname> also maintains a list of protocol |
| interceptors intended for processing outgoing requests and incoming responses and |
| provides methods for managing those interceptors. New protocol interceptors can be |
| introduced to the protocol processor chain or removed from it if needed. Internally |
| protocol interceptors are stored in a simple <classname>java.util.ArrayList</classname>. |
| They are executed in the same natural order as they are added to the list.</para> |
| <programlisting><![CDATA[ |
| DefaultHttpClient httpclient = new DefaultHttpClient(); |
| httpclient.removeRequestInterceptorByClass(RequestUserAgent.class); |
| httpclient.addRequestInterceptor(new HttpRequestInterceptor() { |
| |
| public void process( |
| HttpRequest request, HttpContext context) |
| throws HttpException, IOException { |
| request.setHeader(HTTP.USER_AGENT, "My-own-client"); |
| } |
| |
| }); |
| ]]></programlisting> |
| <para><classname>DefaultHttpClient</classname> is thread safe. It is recommended that the |
| same instance of this class is reused for multiple request executions. When an instance |
| of <classname>DefaultHttpClient</classname> is no longer needed and is about to go out |
| of scope the connection manager associated with it must be shut down by calling the |
| <methodname>ClientConnectionManager#shutdown()</methodname> method.</para> |
| <programlisting><![CDATA[ |
| HttpClient httpclient = new DefaultHttpClient(); |
| // Do something useful |
| httpclient.getConnectionManager().shutdown(); |
| ]]></programlisting> |
| </section> |
| <section> |
| <title>HttpClient parameters</title> |
| <para>These are parameters that be used to customize the behaviour of the default HttpClient |
| implementation:</para> |
| <itemizedlist> |
| <listitem> |
| <formalpara> |
| <title><constant>ClientPNames.HANDLE_REDIRECTS</constant>='http.protocol.handle-redirects':</title> |
| <para>defines whether redirects should be handled automatically. This parameter |
| expects a value of type <classname>java.lang.Boolean</classname>. If this |
| parameter is not set HttpClient will handle redirects automatically.</para> |
| </formalpara> |
| </listitem> |
| <listitem> |
| <formalpara> |
| <title><constant>ClientPNames.REJECT_RELATIVE_REDIRECT</constant>='http.protocol.reject-relative-redirect':</title> |
| <para>defines whether relative redirects should be rejected. HTTP specification |
| requires the location value be an absolute URI. This parameter expects a |
| value of type <classname>java.lang.Boolean</classname>. If this parameter is |
| not set relative redirects will be allowed.</para> |
| </formalpara> |
| </listitem> |
| <listitem> |
| <formalpara> |
| <title><constant>ClientPNames.MAX_REDIRECTS</constant>='http.protocol.max-redirects':</title> |
| <para>defines the maximum number of redirects to be followed. The limit on |
| number of redirects is intended to prevent infinite loops caused by broken |
| server side scripts. This parameter expects a value of type |
| <classname>java.lang.Integer</classname>. If this parameter is not set |
| no more than 100 redirects will be allowed.</para> |
| </formalpara> |
| </listitem> |
| <listitem> |
| <formalpara> |
| <title><constant>ClientPNames.ALLOW_CIRCULAR_REDIRECTS</constant>='http.protocol.allow-circular-redirects':</title> |
| <para>defines whether circular redirects (redirects to the same location) should |
| be allowed. The HTTP spec is not sufficiently clear whether circular |
| redirects are permitted, therefore optionally they can be enabled. This |
| parameter expects a value of type <classname>java.lang.Boolean</classname>. |
| If this parameter is not set circular redirects will be disallowed.</para> |
| </formalpara> |
| </listitem> |
| <listitem> |
| <formalpara> |
| <title><constant>ClientPNames.CONNECTION_MANAGER_FACTORY_CLASS_NAME</constant>='http.connection-manager.factory-class-name':</title> |
| <para>defines the class name of the default |
| <interfacename>ClientConnectionManager</interfacename> implementation. |
| This parameter expects a value of type |
| <classname>java.lang.String</classname>. If this parameter is not set |
| <classname>SingleClientConnManager</classname> will be used per |
| default.</para> |
| </formalpara> |
| </listitem> |
| <listitem> |
| <formalpara> |
| <title><constant>ClientPNames.VIRTUAL_HOST</constant>='http.virtual-host':</title> |
| <para>defines the virtual host settings to be used in the <literal>Host</literal> |
| header instead of the physical host. This parameter expects a value of |
| type <classname>HttpHost</classname>. The HttpHost port does not have to |
| be specified as it will be derived from the target. |
| If this parameter is not set, the name or |
| IP address (and port if required) of the target host will be used.</para> |
| </formalpara> |
| </listitem> |
| <listitem> |
| <formalpara> |
| <title><constant>ClientPNames.DEFAULT_HEADERS</constant>='http.default-headers':</title> |
| <para>defines the request headers to be sent per default with each request. This |
| parameter expects a value of type |
| <interfacename>java.util.Collection</interfacename> containing |
| <interfacename>Header</interfacename> objects.</para> |
| </formalpara> |
| </listitem> |
| <listitem> |
| <formalpara> |
| <title><constant>ClientPNames.DEFAULT_HOST</constant>='http.default-host':</title> |
| <para>defines the default host. The default value will be used if the target |
| host is not explicitly specified in the request URI (relative URIs). This |
| parameter expects a value of type <classname>HttpHost</classname>.</para> |
| </formalpara> |
| </listitem> |
| </itemizedlist> |
| </section> |
| <section> |
| <title>Automatic redirect handling</title> |
| <para>HttpClient handles all types of redirects automatically, except those explicitly |
| prohibited by the HTTP specification as requiring user intervention. <literal>See |
| Other</literal> (status code 303) redirects on <literal>POST</literal> and |
| <literal>PUT</literal> requests are converted to <literal>GET</literal> requests as |
| required by the HTTP specification.</para> |
| </section> |
| <section> |
| <title>HTTP client and execution context</title> |
| <para>The <classname>DefaultHttpClient</classname> treats HTTP requests as immutable objects |
| that are never supposed to change in the course of request execution. Instead, it |
| creates a private mutable copy of the original request object, whose properties can be |
| updated depending on the execution context. Therefore the final request properties such |
| as the target host and request URI can be determined by examining the content of the |
| local HTTP context after the request has been executed.</para> |
| <para>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> |
| <programlisting><![CDATA[ |
| DefaultHttpClient httpclient = new DefaultHttpClient(); |
| |
| HttpContext localContext = new BasicHttpContext(); |
| HttpGet httpget = new HttpGet("http://localhost:8080/"); |
| HttpResponse response = httpclient.execute(httpget, localContext); |
| HttpHost target = (HttpHost) localContext.getAttribute( |
| ExecutionContext.HTTP_TARGET_HOST); |
| HttpUriRequest req = (HttpUriRequest) localContext.getAttribute( |
| ExecutionContext.HTTP_REQUEST); |
| |
| System.out.println("Target host: " + target); |
| System.out.println("Final request URI: " + req.getURI()); // relative URI (no proxy used) |
| System.out.println("Final request method: " + req.getMethod()); |
| ]]></programlisting> |
| </section> |
| <section> |
| <title>Compressed response content</title> |
| <para> |
| The <classname>ContentEncodingHttpClient</classname> is a simple sub-class of |
| <classname>DefaultHttpClient</classname> which adds support indicating to servers that it will |
| support <literal>gzip</literal> and <literal>deflate</literal> compressed responses. It does |
| this via the existing published APIs of <link linkend="protocol_interceptors">HTTP Protocol |
| Interceptors </link>. Depending on the type of response (text will compress well versus |
| images, which are typically already well-compressed), this can speed up responses due to the |
| smaller amount of network traffic involved, along with saving bandwidth, which can be |
| important in mobile environments. The <classname>RequestAcceptEncoding</classname> |
| and <classname>ResponseContentEncoding</classname> interceptors used as also part of the |
| published API and can be used by other <interfacename>DefaultHttpClient</interfacename> |
| implementations. These provide transparent handling of <literal>gzip</literal> and |
| <literal>deflate</literal> encoding, so it will not be apparent to clients that this |
| processing has happened. |
| </para> |
| <programlisting><![CDATA[ |
| ContentEncodingHttpClient httpclient = new ContentEncodingHttpClient(); |
| HttpGet httpget = new HttpGet("http://www.yahoo.com/"); |
| HttpResponse response = httpclient.execute(httpget); |
| |
| Header h = rsp.getFirstHeader("Content-Encoding"); |
| if (h != null) { |
| System.out.println("----------------------------------------"); |
| System.out.println("Response is " + h.getValue() + " encoded"); |
| System.out.println("----------------------------------------"); |
| } |
| ]]></programlisting> |
| <para> |
| One can also add the <classname>RequestAcceptEncoding</classname> and |
| <classname>ResponseContentEncoding</classname> interceptors to an instance of the |
| <classname>DefaultHttpClient</classname>, if desired. |
| </para> |
| <programlisting><![CDATA[ |
| DefaultHttpClient httpclient = new DefaultHttpClient(); |
| httpclient.addRequestInterceptor(new RequestAcceptEncoding()); |
| httpclient.addResponseInterceptor(new ResponseContentEncoding()); |
| ]]></programlisting> |
| </section> |
| </chapter> |