View Javadoc
1   /*
2    * ====================================================================
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   * ====================================================================
20   *
21   * This software consists of voluntary contributions made by many
22   * individuals on behalf of the Apache Software Foundation.  For more
23   * information on the Apache Software Foundation, please see
24   * <http://www.apache.org/>.
25   *
26   */
27  package org.apache.http.impl.client;
28  
29  import java.io.IOException;
30  import java.net.URI;
31  
32  import org.apache.http.HttpEntity;
33  import org.apache.http.HttpEntityEnclosingRequest;
34  import org.apache.http.HttpException;
35  import org.apache.http.HttpHost;
36  import org.apache.http.HttpRequest;
37  import org.apache.http.HttpRequestInterceptor;
38  import org.apache.http.HttpResponse;
39  import org.apache.http.HttpResponseInterceptor;
40  import org.apache.http.client.ClientProtocolException;
41  import org.apache.http.client.HttpClient;
42  import org.apache.http.client.ResponseHandler;
43  import org.apache.http.client.methods.HttpUriRequest;
44  import org.apache.http.client.protocol.RequestAcceptEncoding;
45  import org.apache.http.client.protocol.ResponseContentEncoding;
46  import org.apache.http.client.utils.URIUtils;
47  import org.apache.http.conn.ClientConnectionManager;
48  import org.apache.http.params.HttpParams;
49  import org.apache.http.protocol.BasicHttpContext;
50  import org.apache.http.protocol.HttpContext;
51  import org.apache.http.util.EntityUtils;
52  
53  /**
54   * <p>Decorator adding support for compressed responses. This class sets
55   * the {@code Accept-Encoding} header on requests to indicate
56   * support for the {@code gzip} and {@code deflate}
57   * compression schemes; it then checks the {@code Content-Encoding}
58   * header on the response to uncompress any compressed response bodies.
59   * The {@link java.io.InputStream} of the entity will contain the uncompressed
60   * content.</p>
61   *
62   * <p><b>N.B.</b> Any upstream clients of this class need to be aware that
63   * this effectively obscures visibility into the length of a server
64   * response body, since the {@code Content-Length} header will
65   * correspond to the compressed entity length received from the server,
66   * but the content length experienced by reading the response body may
67   * be different (hopefully higher!).</p>
68   *
69   * <p>That said, this decorator is compatible with the
70   * {@code CachingHttpClient} in that the two decorators can be added
71   * in either order and still have cacheable responses be cached.</p>
72   *
73   * @since 4.2
74   *
75   * @deprecated (4.3) use {@link HttpClientBuilder}
76   */
77  @Deprecated
78  public class DecompressingHttpClient implements HttpClient {
79  
80      private final HttpClient backend;
81      private final HttpRequestInterceptor acceptEncodingInterceptor;
82      private final HttpResponseInterceptor contentEncodingInterceptor;
83  
84      /**
85       * Constructs a decorator to ask for and handle compressed
86       * entities on the fly.
87       */
88      public DecompressingHttpClient() {
89          this(new DefaultHttpClient());
90      }
91  
92      /**
93       * Constructs a decorator to ask for and handle compressed
94       * entities on the fly.
95       * @param backend the {@link HttpClient} to use for actually
96       *   issuing requests
97       */
98      public DecompressingHttpClient(final HttpClient backend) {
99          this(backend, new RequestAcceptEncoding(), new ResponseContentEncoding());
100     }
101 
102     DecompressingHttpClient(final HttpClient backend,
103             final HttpRequestInterceptor requestInterceptor,
104             final HttpResponseInterceptor responseInterceptor) {
105         this.backend = backend;
106         this.acceptEncodingInterceptor = requestInterceptor;
107         this.contentEncodingInterceptor = responseInterceptor;
108     }
109 
110     @Override
111     public HttpParams getParams() {
112         return backend.getParams();
113     }
114 
115     @Override
116     public ClientConnectionManager getConnectionManager() {
117         return backend.getConnectionManager();
118     }
119 
120     @Override
121     public HttpResponse execute(final HttpUriRequest request) throws IOException,
122             ClientProtocolException {
123         return execute(getHttpHost(request), request, (HttpContext)null);
124     }
125 
126     /**
127      * Gets the HttpClient to issue request.
128      *
129      * @return the HttpClient to issue request
130      */
131     public HttpClient getHttpClient() {
132         return this.backend;
133     }
134 
135     HttpHost getHttpHost(final HttpUriRequest request) {
136         final URI uri = request.getURI();
137         return URIUtils.extractHost(uri);
138     }
139 
140     @Override
141     public HttpResponse execute(final HttpUriRequest request, final HttpContext context)
142             throws IOException, ClientProtocolException {
143         return execute(getHttpHost(request), request, context);
144     }
145 
146     @Override
147     public HttpResponse execute(final HttpHost target, final HttpRequest request)
148             throws IOException, ClientProtocolException {
149         return execute(target, request, (HttpContext)null);
150     }
151 
152     @Override
153     public HttpResponse execute(final HttpHost target, final HttpRequest request,
154             final HttpContext context) throws IOException, ClientProtocolException {
155         try {
156             final HttpContext localContext = context != null ? context : new BasicHttpContext();
157             final HttpRequest wrapped;
158             if (request instanceof HttpEntityEnclosingRequest) {
159                 wrapped = new EntityEnclosingRequestWrapper((HttpEntityEnclosingRequest) request);
160             } else {
161                 wrapped = new RequestWrapper(request);
162             }
163             acceptEncodingInterceptor.process(wrapped, localContext);
164             final HttpResponse response = backend.execute(target, wrapped, localContext);
165             try {
166                 contentEncodingInterceptor.process(response, localContext);
167                 if (Boolean.TRUE.equals(localContext.getAttribute(ResponseContentEncoding.UNCOMPRESSED))) {
168                     response.removeHeaders("Content-Length");
169                     response.removeHeaders("Content-Encoding");
170                     response.removeHeaders("Content-MD5");
171                 }
172                 return response;
173             } catch (final HttpException ex) {
174                 EntityUtils.consume(response.getEntity());
175                 throw ex;
176             } catch (final IOException ex) {
177                 EntityUtils.consume(response.getEntity());
178                 throw ex;
179             } catch (final RuntimeException ex) {
180                 EntityUtils.consume(response.getEntity());
181                 throw ex;
182             }
183         } catch (final HttpException e) {
184             throw new ClientProtocolException(e);
185         }
186     }
187 
188     @Override
189     public <T> T execute(final HttpUriRequest request,
190             final ResponseHandler<? extends T> responseHandler) throws IOException,
191             ClientProtocolException {
192         return execute(getHttpHost(request), request, responseHandler);
193     }
194 
195     @Override
196     public <T> T execute(final HttpUriRequest request,
197             final ResponseHandler<? extends T> responseHandler, final HttpContext context)
198             throws IOException, ClientProtocolException {
199         return execute(getHttpHost(request), request, responseHandler, context);
200     }
201 
202     @Override
203     public <T> T execute(final HttpHost target, final HttpRequest request,
204             final ResponseHandler<? extends T> responseHandler) throws IOException,
205             ClientProtocolException {
206         return execute(target, request, responseHandler, null);
207     }
208 
209     @Override
210     public <T> T execute(final HttpHost target, final HttpRequest request,
211             final ResponseHandler<? extends T> responseHandler, final HttpContext context)
212             throws IOException, ClientProtocolException {
213         final HttpResponse response = execute(target, request, context);
214         try {
215             return responseHandler.handleResponse(response);
216         } finally {
217             final HttpEntity entity = response.getEntity();
218             if (entity != null) {
219                 EntityUtils.consume(entity);
220             }
221         }
222     }
223 
224 }