tomcat-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From r...@apache.org
Subject cvs commit: jakarta-tomcat-connectors/http11/src/java/org/apache/coyote/http11/filters GzipOutputFilter.java
Date Wed, 18 Dec 2002 20:36:58 GMT
remm        2002/12/18 12:36:58

  Modified:    http11/src/java/org/apache/coyote/http11 Constants.java
                        Http11Processor.java Http11Protocol.java
  Added:       http11/src/java/org/apache/coyote/http11/filters
                        GzipOutputFilter.java
  Log:
  - Add support for gzip content encoding.
  - I believe some broken user agents must be excluded.
  
  Revision  Changes    Path
  1.13      +6 -0      jakarta-tomcat-connectors/http11/src/java/org/apache/coyote/http11/Constants.java
  
  Index: Constants.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-connectors/http11/src/java/org/apache/coyote/http11/Constants.java,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- Constants.java	24 Nov 2002 22:00:04 -0000	1.12
  +++ Constants.java	18 Dec 2002 20:36:58 -0000	1.13
  @@ -199,6 +199,12 @@
   
   
       /**
  +     * GZIP filters (input and output).
  +     */
  +    public static final int GZIP_FILTER = 3;
  +
  +
  +    /**
        * HTTP/1.0.
        */
       public static final String HTTP_10 = "HTTP/1.0";
  
  
  
  1.48      +86 -0     jakarta-tomcat-connectors/http11/src/java/org/apache/coyote/http11/Http11Processor.java
  
  Index: Http11Processor.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-connectors/http11/src/java/org/apache/coyote/http11/Http11Processor.java,v
  retrieving revision 1.47
  retrieving revision 1.48
  diff -u -r1.47 -r1.48
  --- Http11Processor.java	28 Nov 2002 15:15:02 -0000	1.47
  +++ Http11Processor.java	18 Dec 2002 20:36:58 -0000	1.48
  @@ -86,6 +86,8 @@
   
   import org.apache.coyote.http11.filters.ChunkedInputFilter;
   import org.apache.coyote.http11.filters.ChunkedOutputFilter;
  +//import org.apache.coyote.http11.filters.GzipInputFilter;
  +import org.apache.coyote.http11.filters.GzipOutputFilter;
   import org.apache.coyote.http11.filters.IdentityInputFilter;
   import org.apache.coyote.http11.filters.IdentityOutputFilter;
   import org.apache.coyote.http11.filters.VoidInputFilter;
  @@ -223,32 +225,76 @@
        */
       protected Socket socket;
   
  +
       /**
        * Remote Address associated with the current connection.
        */
       protected String remoteAddr = null;
   
  +
       /**
        * Remote Host associated with the current connection.
        */
       protected String remoteHost = null;
   
  +
       /**
        * Maximum timeout on uploads.
        */
       protected int timeout = 300000;   // 5 minutes as in Apache HTTPD server
   
  +
       /**
        * Flag to disable setting a different time-out on uploads.
        */
       protected boolean disableUploadTimeout = false;
   
  +
  +    /**
  +     * Allowed compression level.
  +     */
  +    protected int compressionLevel = 0;
  +
  +
       /**
        * Host name (used to avoid useless B2C conversion on the host name).
        */
       protected char[] hostNameC = new char[0];
   
   
  +    // ------------------------------------------------------------- Properties
  +
  +
  +    /**
  +     * Return compression level.
  +     */
  +    public String getCompression() {
  +        switch (compressionLevel) {
  +        case 0:
  +            return "off";
  +        case 1:
  +            return "on";
  +        case 2:
  +            return "force";
  +        }
  +        return "off";
  +    }
  +
  +
  +    /**
  +     * Set compression level.
  +     */
  +    public void setCompression(String compression) {
  +        if (compression.equals("on")) {
  +            this.compressionLevel = 1;
  +        } else if (compression.equals("force")) {
  +            this.compressionLevel = 2;
  +        } else {
  +            this.compressionLevel = 0;
  +        }
  +    }
  +
  +
       // --------------------------------------------------------- Public Methods
   
   
  @@ -350,6 +396,7 @@
       public void setDisableUploadTimeout(boolean isDisabled) {
           disableUploadTimeout = isDisabled;
       }
  +
       /**
        * Get the flag that controls upload time-outs.
        */
  @@ -363,6 +410,7 @@
       public void setTimeout( int timeouts ) {
           timeout = timeouts ;
       }
  +
       /**
        * Get the upload timeout.
        */
  @@ -918,6 +966,34 @@
               contentDelimitation = true;
           }
   
  +        // Check for compression
  +        boolean useCompression = false;
  +        if (entityBody && (compressionLevel > 0)) {
  +            // Check accept-encoding
  +            // FIXME: write a comma parser; also reuse 
  +            // for transfer-encoding parsing
  +            MessageBytes acceptEncodingMB = 
  +                request.getMimeHeaders().getValue("accept-encoding");
  +            if ((acceptEncodingMB != null) 
  +                && (acceptEncodingMB.indexOf("gzip") != -1)) {
  +                // Check content-type
  +                if (compressionLevel == 1) {
  +                    int contentLength = response.getContentLength();
  +                    // FIXME: Make the value configurable
  +                    if ((contentLength == -1) || (contentLength > 2048)) {
  +                        useCompression = 
  +                            response.getContentType().startsWith("text/");
  +                    }
  +                } else {
  +                    useCompression = true;
  +                }
  +                // Change content-length to -1 to force chunking
  +                if (useCompression) {
  +                    response.setContentLength(-1);
  +                }
  +            }
  +        }
  +
           MimeHeaders headers = response.getMimeHeaders();
           if (!entityBody) {
               response.setContentLength(-1);
  @@ -949,6 +1025,12 @@
               }
           }
   
  +        if (useCompression) {
  +            outputBuffer.addActiveFilter(outputFilters[Constants.GZIP_FILTER]);
  +            // FIXME: Make content-encoding generation dynamic
  +            response.setHeader("Content-Encoding", "gzip");
  +        }
  +
           // Add date header
           if (! response.containsHeader("Date"))
             response.addHeader("Date", FastHttpDateFormat.getCurrentDate());
  @@ -999,6 +1081,10 @@
           // Create and add the void filters.
           inputBuffer.addFilter(new VoidInputFilter());
           outputBuffer.addFilter(new VoidOutputFilter());
  +
  +        // Create and add the chunked filters.
  +        //inputBuffer.addFilter(new GzipInputFilter());
  +        outputBuffer.addFilter(new GzipOutputFilter());
   
       }
   
  
  
  
  1.18      +6 -0      jakarta-tomcat-connectors/http11/src/java/org/apache/coyote/http11/Http11Protocol.java
  
  Index: Http11Protocol.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-connectors/http11/src/java/org/apache/coyote/http11/Http11Protocol.java,v
  retrieving revision 1.17
  retrieving revision 1.18
  diff -u -r1.17 -r1.18
  --- Http11Protocol.java	26 Nov 2002 03:32:50 -0000	1.17
  +++ Http11Protocol.java	18 Dec 2002 20:36:58 -0000	1.18
  @@ -186,6 +186,7 @@
       private String reportedname;
       private int socketCloseDelay=-1;
       private boolean disableUploadTimeout = false;
  +    private String compression = "off";
   
       // -------------------- Pool setup --------------------
   
  @@ -251,6 +252,10 @@
           disableUploadTimeout = isDisabled;
       }
   
  +    public void setCompression(String valueS) {
  +        compression = valueS;
  +    }
  +
       public void setSoLinger( int i ) {
   	ep.setSoLinger( i );
           setAttribute("soLinger", "" + i);
  @@ -352,6 +357,7 @@
               processor.setMaxKeepAliveRequests( proto.maxKeepAliveRequests );
               processor.setTimeout( proto.timeout );
               processor.setDisableUploadTimeout( proto.disableUploadTimeout );
  +            processor.setCompression( proto.compression );
   
               //thData[0]=adapter;
               thData[1]=processor;
  
  
  
  1.1                  jakarta-tomcat-connectors/http11/src/java/org/apache/coyote/http11/filters/GzipOutputFilter.java
  
  Index: GzipOutputFilter.java
  ===================================================================
  /*
   * ====================================================================
   * 
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:  
   *       "This product includes software developed by the 
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */ 
  
  package org.apache.coyote.http11.filters;
  
  import java.io.IOException;
  import java.io.OutputStream;
  import java.util.zip.GZIPOutputStream;
  
  import org.apache.tomcat.util.buf.ByteChunk;
  
  import org.apache.coyote.OutputBuffer;
  import org.apache.coyote.Response;
  import org.apache.coyote.http11.OutputFilter;
  
  /**
   * Gzip output filter.
   * 
   * @author Remy Maucherat
   */
  public class GzipOutputFilter implements OutputFilter {
  
  
      // -------------------------------------------------------------- Constants
  
  
      protected static final String ENCODING_NAME = "gzip";
      protected static final ByteChunk ENCODING = new ByteChunk();
  
  
      // ----------------------------------------------------- Static Initializer
  
  
      static {
          ENCODING.setBytes(ENCODING_NAME.getBytes(), 0, ENCODING_NAME.length());
      }
  
  
      // ----------------------------------------------------- Instance Variables
  
  
      /**
       * Next buffer in the pipeline.
       */
      protected OutputBuffer buffer;
  
  
      /**
       * Compression output stream.
       */
      protected GZIPOutputStream compressionStream = null;
  
  
      /**
       * Fake internal output stream.
       */
      protected OutputStream fakeOutputStream = new FakeOutputStream();
  
  
      // --------------------------------------------------- OutputBuffer Methods
  
  
      /**
       * Write some bytes.
       * 
       * @return number of bytes written by the filter
       */
      public int doWrite(ByteChunk chunk, Response res)
          throws IOException {
          if (compressionStream == null) {
              compressionStream = new GZIPOutputStream(fakeOutputStream);
          }
          compressionStream.write(chunk.getBytes(), chunk.getStart(), 
                                  chunk.getLength());
          return chunk.getLength();
      }
  
  
      // --------------------------------------------------- OutputFilter Methods
  
  
      /**
       * Some filters need additional parameters from the response. All the 
       * necessary reading can occur in that method, as this method is called
       * after the response header processing is complete.
       */
      public void setResponse(Response response) {
      }
  
  
      /**
       * Set the next buffer in the filter pipeline.
       */
      public void setBuffer(OutputBuffer buffer) {
          this.buffer = buffer;
      }
  
  
      /**
       * End the current request. It is acceptable to write extra bytes using
       * buffer.doWrite during the execution of this method.
       */
      public long end()
          throws IOException {
          if (compressionStream == null) {
              compressionStream = new GZIPOutputStream(fakeOutputStream);
          }
          compressionStream.finish();
          return ((OutputFilter) buffer).end();
      }
  
  
      /**
       * Make the filter ready to process the next request.
       */
      public void recycle() {
          // Set compression stream to null
          compressionStream = null;
      }
  
  
      /**
       * Return the name of the associated encoding; Here, the value is 
       * "identity".
       */
      public ByteChunk getEncodingName() {
          return ENCODING;
      }
  
  
      // ------------------------------------------- FakeOutputStream Inner Class
  
  
      protected class FakeOutputStream
          extends OutputStream {
          protected ByteChunk outputChunk = new ByteChunk();
          public void write(int b) {
              // Shouldn't get called
              System.out.println("FIXME");
          }
          public void write(byte[] b, int off, int len)
              throws IOException {
              outputChunk.setBytes(b, off, len);
              buffer.doWrite(outputChunk, null);
          }
          public void flush() throws IOException {}
          public void close() throws IOException {}
      }
  
  
  }
  
  
  

--
To unsubscribe, e-mail:   <mailto:tomcat-dev-unsubscribe@jakarta.apache.org>
For additional commands, e-mail: <mailto:tomcat-dev-help@jakarta.apache.org>


Mime
View raw message