001 /* 002 * Copyright 2003-2008 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * You are receiving this code free of charge, which represents many hours of 017 * effort from other individuals and corporations. As a responsible member 018 * of the community, you are asked (but not required) to donate any 019 * enhancements or improvements back to the community under a similar open 020 * source license. Thank you. -TMN 021 */ 022 package groovyx.net.http; 023 024 import java.io.IOException; 025 026 import org.apache.http.Header; 027 import org.apache.http.HeaderElement; 028 import org.apache.http.HttpEntity; 029 import org.apache.http.HttpException; 030 import org.apache.http.HttpRequest; 031 import org.apache.http.HttpRequestInterceptor; 032 import org.apache.http.HttpResponse; 033 import org.apache.http.HttpResponseInterceptor; 034 import org.apache.http.protocol.HttpContext; 035 036 /** 037 * Base class for handing content-encoding. 038 * @author <a href='mailto:tnichols@enernoc.com'>Tom Nichols</a> 039 */ 040 public abstract class ContentEncoding { 041 042 public static final String ACCEPT_ENC_HDR = "Accept-Encoding"; 043 public static final String CONTENT_ENC_HDR = "Content-Encoding"; 044 045 protected abstract String getContentEncoding(); 046 protected abstract HttpEntity wrapResponseEntity( HttpEntity raw ); 047 048 public HttpRequestInterceptor getRequestInterceptor() { 049 return new RequestInterceptor(); 050 } 051 052 public HttpResponseInterceptor getResponseInterceptor() { 053 return new ResponseInterceptor(); 054 } 055 056 /** 057 * Enumeration of common content-encodings. 058 */ 059 public static enum Type { 060 GZIP, 061 COMPRESS, 062 DEFLATE; 063 064 /** Prints the value as it should appear in an HTTP header */ 065 @Override public String toString() { 066 return this.name().toLowerCase(); 067 } 068 } 069 070 /** 071 * Request interceptor that adds the correct <code>Accept</code> header 072 * to the outgoing request. 073 * @author <a href='mailto:tnichols@enernoc.com'>Tom Nichols</a> 074 */ 075 protected class RequestInterceptor implements HttpRequestInterceptor { 076 public void process( final HttpRequest req, 077 final HttpContext context ) throws HttpException, IOException { 078 079 // set the Accept-Encoding header: 080 String encoding = getContentEncoding(); 081 if ( !req.containsHeader( ACCEPT_ENC_HDR ) ) 082 req.addHeader( ACCEPT_ENC_HDR, encoding ); 083 084 else { 085 StringBuilder values = new StringBuilder(); 086 for ( Header h : req.getHeaders( ACCEPT_ENC_HDR ) ) 087 values.append( h.getValue() ).append( "," ); 088 089 String encList = (!values.toString().contains( encoding )) ? values 090 .append( encoding ).toString() 091 : values.toString().substring( 0, values.lastIndexOf( "," ) ); 092 093 req.setHeader( ACCEPT_ENC_HDR, encList ); 094 } 095 096 //TODO compress request and add content-encoding header. 097 } 098 } 099 100 /** 101 * Response interceptor that filters the response stream to decode the 102 * compressed content before it is passed on to the parser. 103 * @author <a href='mailto:tnichols@enernoc.com'>Tom Nichols</a> 104 */ 105 protected class ResponseInterceptor implements HttpResponseInterceptor { 106 public void process( final HttpResponse response, final HttpContext context ) 107 throws HttpException, IOException { 108 109 if ( hasEncoding( response, getContentEncoding() ) ) 110 response.setEntity( wrapResponseEntity( response.getEntity() ) ); 111 } 112 113 protected boolean hasEncoding( final HttpResponse response, final String encoding ) { 114 HttpEntity entity = response.getEntity(); 115 if ( entity == null ) return false; 116 Header ceHeader = entity.getContentEncoding(); 117 if ( ceHeader == null ) return false; 118 119 HeaderElement[] codecs = ceHeader.getElements(); 120 for ( int i = 0; i < codecs.length; i++ ) 121 if ( encoding.equalsIgnoreCase( codecs[i].getName() ) ) 122 return true; 123 124 return false; 125 } 126 } 127 }