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.client.protocol;
28  
29  import java.io.IOException;
30  import java.util.Locale;
31  
32  import org.apache.http.Header;
33  import org.apache.http.HeaderElement;
34  import org.apache.http.HttpEntity;
35  import org.apache.http.HttpException;
36  import org.apache.http.HttpResponse;
37  import org.apache.http.HttpResponseInterceptor;
38  import org.apache.http.annotation.Immutable;
39  import org.apache.http.client.entity.DeflateDecompressingEntity;
40  import org.apache.http.client.entity.GzipDecompressingEntity;
41  import org.apache.http.protocol.HttpContext;
42  
43  /**
44   * {@link HttpResponseInterceptor} responsible for processing Content-Encoding
45   * responses.
46   * <p>
47   * Instances of this class are stateless and immutable, therefore threadsafe.
48   *
49   * @since 4.1
50   *
51   */
52  @Immutable
53  public class ResponseContentEncoding implements HttpResponseInterceptor {
54  
55      public static final String UNCOMPRESSED = "http.client.response.uncompressed";
56  
57      /**
58       * Handles the following {@code Content-Encoding}s by
59       * using the appropriate decompressor to wrap the response Entity:
60       * <ul>
61       * <li>gzip - see {@link GzipDecompressingEntity}</li>
62       * <li>deflate - see {@link DeflateDecompressingEntity}</li>
63       * <li>identity - no action needed</li>
64       * </ul>
65       *
66       * @param response the response which contains the entity
67       * @param  context not currently used
68       *
69       * @throws HttpException if the {@code Content-Encoding} is none of the above
70       */
71      public void process(
72              final HttpResponse response,
73              final HttpContext context) throws HttpException, IOException {
74          final HttpEntity entity = response.getEntity();
75  
76          // entity can be null in case of 304 Not Modified, 204 No Content or similar
77          // check for zero length entity.
78          if (entity != null && entity.getContentLength() != 0) {
79              final Header ceheader = entity.getContentEncoding();
80              if (ceheader != null) {
81                  final HeaderElement[] codecs = ceheader.getElements();
82                  boolean uncompressed = false;
83                  for (final HeaderElement codec : codecs) {
84                      final String codecname = codec.getName().toLowerCase(Locale.ENGLISH);
85                      if ("gzip".equals(codecname) || "x-gzip".equals(codecname)) {
86                          response.setEntity(new GzipDecompressingEntity(response.getEntity()));
87                          uncompressed = true;
88                          break;
89                      } else if ("deflate".equals(codecname)) {
90                          response.setEntity(new DeflateDecompressingEntity(response.getEntity()));
91                          uncompressed = true;
92                          break;
93                      } else if ("identity".equals(codecname)) {
94  
95                          /* Don't need to transform the content - no-op */
96                          return;
97                      } else {
98                          throw new HttpException("Unsupported Content-Coding: " + codec.getName());
99                      }
100                 }
101                 if (uncompressed) {
102                     response.removeHeaders("Content-Length");
103                     response.removeHeaders("Content-Encoding");
104                     response.removeHeaders("Content-MD5");
105                 }
106             }
107         }
108     }
109 
110 }