Skip to content

Commit

Permalink
477278 Refactored DefaultServlet for cached Gzip & Etags
Browse files Browse the repository at this point in the history
Refactored the DefaultServlet to better handle static gzipped files with etags in the cache.
Required a simplification of always having a HttpContent rather than the prior situation of
having either a Resource or a HttpContent.  So introduced a HttpContent.Factory, of which
the ResourceCache is the normal implementation, but there is also now a ResourceContentFactory
that creates content when there is no cache.

The Gzip resource is now associated with the normal resource, so less lookups are needed.
This also give scope for caching dynamic gzipping in the future.

The GzipHttpContent class has been introduced to send content with the headers of the
uncompress, but content of the compressed resource.
  • Loading branch information
gregw committed Sep 17, 2015
1 parent 03a601f commit 2d88fdf
Show file tree
Hide file tree
Showing 13 changed files with 747 additions and 252 deletions.
177 changes: 177 additions & 0 deletions jetty-http/src/main/java/org/eclipse/jetty/http/GzipHttpContent.java
@@ -0,0 +1,177 @@
//
// ========================================================================
// Copyright (c) 1995-2015 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//

package org.eclipse.jetty.http;

import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.channels.ReadableByteChannel;
import org.eclipse.jetty.http.MimeTypes.Type;

import org.eclipse.jetty.util.resource.Resource;

/* ------------------------------------------------------------ */
public class GzipHttpContent implements HttpContent
{
private final HttpContent _content;
private final HttpContent _contentGz;
public final static String ETAG_GZIP="--gzip";
public final static PreEncodedHttpField CONTENT_ENCODING_GZIP=new PreEncodedHttpField(HttpHeader.CONTENT_ENCODING,"gzip");

public GzipHttpContent(HttpContent content, HttpContent contentGz)
{
_content=content;
_contentGz=contentGz;
}

@Override
public int hashCode()
{
return _content.hashCode();
}

@Override
public boolean equals(Object obj)
{
return _content.equals(obj);
}

@Override
public Resource getResource()
{
return _content.getResource();
}

@Override
public HttpField getETag()
{
return new HttpField(HttpHeader.ETAG,getETagValue());
}

@Override
public String getETagValue()
{
return _content.getResource().getWeakETag(ETAG_GZIP);
}

@Override
public HttpField getLastModified()
{
return _content.getLastModified();
}

@Override
public String getLastModifiedValue()
{
return _content.getLastModifiedValue();
}

@Override
public HttpField getContentType()
{
return _content.getContentType();
}

@Override
public String getContentTypeValue()
{
return _content.getContentTypeValue();
}

@Override
public HttpField getContentEncoding()
{
return CONTENT_ENCODING_GZIP;
}

@Override
public String getContentEncodingValue()
{
return CONTENT_ENCODING_GZIP.getValue();
}

@Override
public String getCharacterEncoding()
{
return _content.getCharacterEncoding();
}

@Override
public Type getMimeType()
{
return _content.getMimeType();
}

@Override
public void release()
{
_content.release();
}

@Override
public ByteBuffer getIndirectBuffer()
{
return _contentGz.getIndirectBuffer();
}

@Override
public ByteBuffer getDirectBuffer()
{
return _contentGz.getDirectBuffer();
}

@Override
public HttpField getContentLength()
{
return _contentGz.getContentLength();
}

@Override
public long getContentLengthValue()
{
return _contentGz.getContentLengthValue();
}

@Override
public InputStream getInputStream() throws IOException
{
return _contentGz.getInputStream();
}

@Override
public ReadableByteChannel getReadableByteChannel() throws IOException
{
return _contentGz.getReadableByteChannel();
}

@Override
public String toString()
{
return String.format("GzipHttpContent@%x{r=%s|%s,lm=%s|%s,ct=%s}",hashCode(),
_content.getResource(),_contentGz.getResource(),
_content.getResource().lastModified(),_contentGz.getResource().lastModified(),
getContentType());
}

@Override
public HttpContent getGzipContent()
{
return null;
}
}
10 changes: 10 additions & 0 deletions jetty-http/src/main/java/org/eclipse/jetty/http/HttpContent.java
Expand Up @@ -44,6 +44,9 @@ public interface HttpContent
String getCharacterEncoding();
Type getMimeType();

HttpField getContentEncoding();
String getContentEncodingValue();

HttpField getContentLength();
long getContentLengthValue();

Expand All @@ -60,4 +63,11 @@ public interface HttpContent
ReadableByteChannel getReadableByteChannel() throws IOException;
void release();

HttpContent getGzipContent();


public interface Factory
{
HttpContent getContent(String path) throws IOException;
}
}
Expand Up @@ -39,33 +39,28 @@ public class ResourceHttpContent implements HttpContent
final Resource _resource;
final String _contentType;
final int _maxBuffer;
final String _etag;
HttpContent _gzip;
String _etag;

/* ------------------------------------------------------------ */
public ResourceHttpContent(final Resource resource, final String contentType)
{
this(resource,contentType,-1,false);
this(resource,contentType,-1,null);
}

/* ------------------------------------------------------------ */
public ResourceHttpContent(final Resource resource, final String contentType, int maxBuffer)
{
this(resource,contentType,maxBuffer,false);
this(resource,contentType,maxBuffer,null);
}

/* ------------------------------------------------------------ */
public ResourceHttpContent(final Resource resource, final String contentType, boolean etag)
{
this(resource,contentType,-1,etag);
}


/* ------------------------------------------------------------ */
public ResourceHttpContent(final Resource resource, final String contentType, int maxBuffer, boolean etag)
public ResourceHttpContent(final Resource resource, final String contentType, int maxBuffer, HttpContent gzip)
{
_resource=resource;
_contentType=contentType;
_maxBuffer=maxBuffer;
_etag=etag?resource.getWeakETag():null;
_gzip=gzip;
}

/* ------------------------------------------------------------ */
Expand All @@ -82,6 +77,20 @@ public HttpField getContentType()
return _contentType==null?null:new HttpField(HttpHeader.CONTENT_TYPE,_contentType);
}

/* ------------------------------------------------------------ */
@Override
public HttpField getContentEncoding()
{
return null;
}

/* ------------------------------------------------------------ */
@Override
public String getContentEncodingValue()
{
return null;
}

/* ------------------------------------------------------------ */
@Override
public String getCharacterEncoding()
Expand Down Expand Up @@ -132,14 +141,14 @@ public ByteBuffer getDirectBuffer()
@Override
public HttpField getETag()
{
return _etag==null?null:new HttpField(HttpHeader.ETAG,_etag);
return new HttpField(HttpHeader.ETAG,getETagValue());
}

/* ------------------------------------------------------------ */
@Override
public String getETagValue()
{
return _etag;
return _resource.getWeakETag();
}

/* ------------------------------------------------------------ */
Expand Down Expand Up @@ -205,6 +214,14 @@ public void release()
@Override
public String toString()
{
return String.format("%s@%x{r=%s}",this.getClass().getSimpleName(),hashCode(),_resource);
return String.format("%s@%x{r=%s,gz=%b}",this.getClass().getSimpleName(),hashCode(),_resource,_gzip!=null);
}

/* ------------------------------------------------------------ */
@Override
public HttpContent getGzipContent()
{
return _gzip==null?null:new GzipHttpContent(this,_gzip);
}

}

0 comments on commit 2d88fdf

Please sign in to comment.