History | Log In     View a printable version of the current page.  
Issue Details (XML | Word | Printable)

Key: XFIRE-444
Type: New Feature New Feature
Status: Closed Closed
Resolution: Fixed
Priority: Minor Minor
Assignee: Dan Diephouse
Reporter: Gum Shoe
Votes: 0
Watchers: 1
Operations

If you were logged in you would be able to see more operations.
XFire

Added optional gzip content encoding support to CommonsHttpMessageSender.

Created: 07/Jun/06 01:10 PM   Updated: 20/Jul/06 08:09 PM
Component/s: Core
Affects Version/s: 1.1, 1.1.1
Fix Version/s: 1.2-RC

Time Tracking:
Not Specified

File Attachments: 1. Java Source File CommonsHttpMessageSender.java (11 kb)



 Description  « Hide
Added optional gzip content encoding support to CommonsHttpMessageSender. To enable set the property CommonsHttpMessageSender.GZIP_ENABLED to Boolean true. When enabled all requests will have the header Accept-Encoding set to 'gzip' and responses with or without Content-Encoding set to 'gzip' will be handled appropriately. Outgoing requests will not be compressed.

The patch:

Index: E:/work/eclipseworkspace/xfire/xfire-core/src/main/org/codehaus/xfire/transport/http/CommonsHttpMessageSender.java
===================================================================
--- E:/work/eclipseworkspace/xfire/xfire-core/src/main/org/codehaus/xfire/transport/http/CommonsHttpMessageSender.java	(revision 1590)
+++ E:/work/eclipseworkspace/xfire/xfire-core/src/main/org/codehaus/xfire/transport/http/CommonsHttpMessageSender.java	(working copy)
@@ -3,9 +3,11 @@
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.zip.GZIPInputStream;
 
 import javax.activation.DataHandler;
 
+import org.apache.commons.httpclient.Header;
 import org.apache.commons.httpclient.HttpClient;
 import org.apache.commons.httpclient.HttpException;
 import org.apache.commons.httpclient.HttpState;
@@ -46,6 +48,8 @@
     private HttpClient client;
 
     private HttpState state;
+    
+    private static final String GZIP = "gzip";
 
     public static final String HTTP_CLIENT_PARAMS = "httpClient.params";
     public static final String USER_AGENT =  
@@ -54,6 +58,7 @@
     public static final String HTTP_PROXY_PORT = "http.proxyPort";
     public static final String HTTP_STATE = "httpClient.httpstate";
     public static final String HTTP_CLIENT = "httpClient";
+    public static final String GZIP_ENABLED = "gzip.enabled";
     
     public CommonsHttpMessageSender(OutMessage message, MessageContext context)
     {
@@ -140,6 +145,14 @@
         {
             postMethod.setRequestHeader("Content-Type", HttpChannel.getSoapMimeType(getMessage()));
         }
+        Object o = context.getContextualProperty(GZIP_ENABLED);
+        if(null != o)
+        {
+	          if(((Boolean)o).booleanValue())
+	          {
+		            postMethod.setRequestHeader("Accept-Encoding", GZIP);
+	          }
+        }
     }
 
     public void send()
@@ -215,7 +228,23 @@
         throws IOException
     {
         String ct = postMethod.getResponseHeader("Content-Type").getValue();
-        InputStream in = postMethod.getResponseBodyAsStream();
+        Header hce = postMethod.getResponseHeader("Content-Encoding");
+        InputStream in = null;
+        if(null != hce)
+        {
+	          if(hce.getValue().equals(GZIP))
+	          {
+		            in = new GZIPInputStream(postMethod.getResponseBodyAsStream());
+	          }
+	          else
+	          {
+		            //better hope this never happens
+	          }
+        }
+        else
+        {
+            in = postMethod.getResponseBodyAsStream();
+        }
         if (ct.toLowerCase().indexOf("multipart/related") != -1)
         {
             Attachments atts = new StreamedAttachments(in, ct);


 All   Comments   Work Log   Change History      Sort Order: Ascending order - Click to sort in descending order
Gum Shoe - 07/Jun/06 01:28 PM
To quickly enable compression on the server side: http://sourceforge.net/projects/pjl-comp-filter

Dan Diephouse - 13/Jun/06 11:03 PM
OK this needs some work before we can put it in. Specifically we need a test case and outgoing GZip support as well.

Also some suggestions. Try something like this instead:
InputStream in = postMethod.getResponseBodyAsStream();
if(null != hce && hce.getValue().equals(GZIP))

{ in = new GZIPInputStream(in); }

If we don't know what it is, we'll just ignore it.


Gum Shoe - 15/Jun/06 10:09 AM
As per the IRC discussion I am making changes that will allow for:
  1. request compression of responses via gzip
  2. compress requests via gzip
  3. both of the above
  4. perform no compression (the default)

At present http://sourceforge.net/projects/pjl-comp-filter does not support request compression but the author has graciously agreed to look at it this weekend.


Gum Shoe - 19/Jun/06 05:01 PM

Dan Diephouse - 19/Jun/06 05:12 PM
reopening...

Gum Shoe - 19/Jun/06 05:16 PM
Sorry about the mess with http://jira.codehaus.org/browse/XFIRE-468; looks like this will be the place for this now. Please not that this patch is now against 1.1.1.

Added optional gzip content encoding support to CommonsHttpMessageSender.
To enable response compression set the property CommonsHttpMessageSender.GZIP_RESPONSE to Boolean true. When enabled all requests will have the header Accept-Encoding set to 'gzip' and responses with or without Content-Encoding set to 'gzip' will be handled appropriately.

To enable request compression set the property CommonsHttpMessageSender.GZIP_REQUEST to Boolean true. When enabled all requests will have the Content-Encoding header set to 'gzip' and the content will be compressed. There is no negotiation with the server to ensure that it supports this.

I tested this with a pre-release of 1.6 http://sourceforge.net/projects/pjl-comp-filter with added request compression support, a formal release is expected within a week or so.

Dan, you mentioned unit tests. Do you see the need to add gzip support to the stand alone server in order to test this?

Index: E:/work/eclipseworkspace/xfire/xfire-core/src/main/org/codehaus/xfire/transport/http/CommonsHttpMessageSender.java
===================================================================
--- E:/work/eclipseworkspace/xfire/xfire-core/src/main/org/codehaus/xfire/transport/http/CommonsHttpMessageSender.java	(revision 1672)
+++ E:/work/eclipseworkspace/xfire/xfire-core/src/main/org/codehaus/xfire/transport/http/CommonsHttpMessageSender.java	(working copy)
@@ -3,9 +3,13 @@
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.GZIPOutputStream;
 
 import javax.activation.DataHandler;
 
+import org.apache.commons.httpclient.Header;
 import org.apache.commons.httpclient.HttpClient;
 import org.apache.commons.httpclient.HttpException;
 import org.apache.commons.httpclient.HttpState;
@@ -19,6 +23,7 @@
 import org.apache.commons.httpclient.params.HttpClientParams;
 import org.codehaus.xfire.MessageContext;
 import org.codehaus.xfire.XFireException;
+import org.codehaus.xfire.XFireRuntimeException;
 import org.codehaus.xfire.attachments.Attachments;
 import org.codehaus.xfire.attachments.JavaMailAttachments;
 import org.codehaus.xfire.attachments.SimpleAttachment;
@@ -45,6 +50,8 @@
     private HttpClient client;
 
     private HttpState state;
+    
+    private static final String GZIP = "gzip";
 
     public static final String HTTP_CLIENT_PARAMS = "httpClient.params";
     public static final String USER_AGENT =  
@@ -53,6 +60,10 @@
     public static final String HTTP_PROXY_PORT = "http.proxyPort";
     public static final String HTTP_STATE = "httpClient.httpstate";
     public static final String HTTP_CLIENT = "httpClient";
+    /** Request GZIP encoded responses. */
+    public static final String GZIP_RESPONSE = "gzip.response";
+    /** GZIP the requests. */
+    public static final String GZIP_REQUEST = "gzip.requests";
 
     private InputStream msgIs;
     
@@ -141,6 +152,22 @@
         {
             postMethod.setRequestHeader("Content-Type", HttpChannel.getSoapMimeType(getMessage(), true));
         }
+        Object o = context.getContextualProperty(GZIP_RESPONSE);
+        if(null != o)
+        {
+	          if(((Boolean)o).booleanValue())
+	          {
+		            postMethod.setRequestHeader("Accept-Encoding", GZIP);
+	          }
+        }
+        o = context.getContextualProperty(GZIP_REQUEST);
+        if(null != o)
+        {
+	          if(((Boolean)o).booleanValue())
+	          {
+		            postMethod.setRequestHeader("Content-Encoding", GZIP);
+	          }
+        }
     }
 
     public void send()
@@ -193,16 +220,34 @@
         OutMessage message = getMessage();
         MessageContext context = getMessageContext();
         ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        
+        OutputStream os = bos;
+        boolean bGZIP = false;
+        Object o = context.getContextualProperty(GZIP_REQUEST);
+        if(null != o)
+        {
+	          if(((Boolean)o).booleanValue())
+	          {
+                bGZIP = true;
+                GZIPOutputStream gzOut = new GZIPOutputStream(bos);
+                os = gzOut;
+	          }
+        }
 
         Attachments atts = message.getAttachments();
         if (atts != null)
         {
-            atts.write(bos);
+            atts.write(os);
         }
         else
         {
-            HttpChannel.writeWithoutAttachments(context, message, bos);
+            HttpChannel.writeWithoutAttachments(context, message, os);
         }
+        if(bGZIP)
+        {
+            ((GZIPOutputStream)os).finish();
+        }
+        os.close();
         
         return new ByteArrayRequestEntity(bos.toByteArray());
     }
@@ -211,7 +256,23 @@
         throws IOException
     {
         String ct = postMethod.getResponseHeader("Content-Type").getValue();
-        InputStream in = postMethod.getResponseBodyAsStream();
+        Header hce = postMethod.getResponseHeader("Content-Encoding");
+        InputStream in = null;
+        if(null != hce)
+        {
+	          if(hce.getValue().equals(GZIP))
+	          {
+		            in = new GZIPInputStream(postMethod.getResponseBodyAsStream());
+	          }
+	          else
+	          {
+              throw new XFireRuntimeException("Response contains Content-Encoding '" + hce.getValue() + "', which is not the requested type of '" + GZIP + "'.");
+	          }
+        }
+        else
+        {
+            in = postMethod.getResponseBodyAsStream();
+        }
         if (ct.toLowerCase().indexOf("multipart/related") != -1)
         {
             Attachments atts = new StreamedAttachments(in, ct);


Gum Shoe - 06/Jul/06 10:22 AM
http://sourceforge.net/projects/pjl-comp-filter 1.6 is now official; with gzip request support.

Gum Shoe - 17/Jul/06 02:20 PM
How to add the filter to web.xml:

<filter>
<filter-name>CompressingFilter</filter-name>
<filter-class>com.planetj.servlet.filter.compression.CompressingFilter</filter-class>
<init-param>
<param-name>debug</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>statsEnabled</param-name>
<param-value>false</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CompressingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>


Gum Shoe - 17/Jul/06 02:36 PM
Example client use:
   Service serviceModel = new ObjectServiceFactory().create(IDataServerService.class);

    // create a proxy for the deployed service
    XFire xfire = XFireFactory.newInstance().getXFire();
    XFireProxyFactory factory = new XFireProxyFactory(xfire);
    try{
      this.client = (IDataServerService)factory.create(serviceModel, url);
    }catch(MalformedURLException e){
      log.error(e);
      throw new DataServerException("could not create client", e);
    }
    Client client = ((XFireProxy)Proxy.getInvocationHandler(this.client)).getClient();
    client.setProperty(CommonsHttpMessageSender.GZIP_RESPONSE, true);
    client.setProperty(CommonsHttpMessageSender.GZIP_REQUEST, true);

Gum Shoe - 17/Jul/06 03:09 PM
Could not provide a diff as am having SVN issues so here is the file; my mods are agains rev 1761.

Dan Diephouse - 20/Jul/06 08:09 PM
This functionality is now in SVN. Thanks.