Modify AssetDispatcher to handle two path prefixes: normal and compressed
Project: http://git-wip-us.apache.org/repos/asf/tapestry-5/repo Commit: http://git-wip-us.apache.org/repos/asf/tapestry-5/commit/aa465fcd Tree: http://git-wip-us.apache.org/repos/asf/tapestry-5/tree/aa465fcd Diff: http://git-wip-us.apache.org/repos/asf/tapestry-5/diff/aa465fcd Branch: refs/heads/master Commit: aa465fcd3b4b735da9682f377e43553110303494 Parents: 6fd011e Author: Howard M. Lewis Ship <[email protected]> Authored: Sat Apr 13 08:25:00 2013 -0700 Committer: Howard M. Lewis Ship <[email protected]> Committed: Mon Apr 15 22:11:18 2013 +0100 ---------------------------------------------------------------------- .../src/main/java/org/apache/tapestry5/Asset.java | 5 ++ .../java/org/apache/tapestry5/SymbolConstants.java | 12 +++- .../internal/services/AssetDispatcher.java | 50 +++++++++++---- .../tapestry5/services/assets/AssetsModule.java | 1 + 4 files changed, 55 insertions(+), 13 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/aa465fcd/tapestry-core/src/main/java/org/apache/tapestry5/Asset.java ---------------------------------------------------------------------- diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/Asset.java b/tapestry-core/src/main/java/org/apache/tapestry5/Asset.java index b2c76ac..a7a9f25 100644 --- a/tapestry-core/src/main/java/org/apache/tapestry5/Asset.java +++ b/tapestry-core/src/main/java/org/apache/tapestry5/Asset.java @@ -40,8 +40,13 @@ public interface Asset * <p/>Note that starting in Tapestry 5.4, it is expected that Asset instances recognize * when the underlying Resource's content has changed, and update the clientURL to reflect the new content's * checksum. This wasn't an issue in earlier releases where the clientURL incorporated a version number. + * <p/> + * Finally, starting in 5.4, this value will often be <em>variant</em>: the exact URL returned will depend on + * whether the underlying resource content is compressable, whether the current {@link org.apache.tapestry5.services.Request} + * supports compression. * * @see org.apache.tapestry5.services.AssetSource + * @see org.apache.tapestry5.services.AssetPathConverter */ String toClientURL(); http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/aa465fcd/tapestry-core/src/main/java/org/apache/tapestry5/SymbolConstants.java ---------------------------------------------------------------------- diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/SymbolConstants.java b/tapestry-core/src/main/java/org/apache/tapestry5/SymbolConstants.java index 0d671c4..8f16694 100644 --- a/tapestry-core/src/main/java/org/apache/tapestry5/SymbolConstants.java +++ b/tapestry-core/src/main/java/org/apache/tapestry5/SymbolConstants.java @@ -330,11 +330,21 @@ public class SymbolConstants /** * Prefix to be used for all resource paths, used to recognize which requests are for assets. This value * is appended to the context path and the (optional {@linkplain #APPLICATION_FOLDER application folder}. - * Its default is "assets". It may contain slashes, but should not begin or end with one. + * Its default is "assets". It may contain slashes, but should not begin or end with one. This is the prefix + * for uncompressed assets. */ public static final String ASSET_PATH_PREFIX = "tapestry.asset-path-prefix"; /** + * As with {@link #ASSET_PATH_PREFIX} but for compressed versions of assets. At render time, it is determined + * whether each asset is compressable (for example, image file formats are already compressed). A path for + * either {@link #ASSET_PATH_PREFIX} or this prefix is selected at render time. Defaults to the asset path prefix suffixed with ".gz". + * + * @since 5.4 + */ + public static final String COMPRESSED_ASSET_PATH_PREFIX = "tapestry.compressed-asset-path-prefix"; + + /** * The Asset path to the copy of Require JS to include in rendered pages. Any page that makes use of any JavaScript will * automatically import this library (as well as the core JavaScript stack). * http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/aa465fcd/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AssetDispatcher.java ---------------------------------------------------------------------- diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AssetDispatcher.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AssetDispatcher.java index 4f8e8a7..2ab1a68 100644 --- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AssetDispatcher.java +++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AssetDispatcher.java @@ -30,8 +30,10 @@ import java.util.List; import java.util.Map; /** - * Recognizes requests where the path begins with "/asset/" and delivers the content therein as a bytestream. Also - * handles requests that are simply polling for a change to the file. + * Recognizes requests where the path begins with "/asset/" (actually, as defined by the + * {@link SymbolConstants#ASSET_PATH_PREFIX} symbol), and delivers the content therein as a bytestream. Also + * handles requests that are simply polling for a change to the file (including checking the ETag in the + * request against {@linkplain org.apache.tapestry5.services.assets.StreamableResource#getChecksum() the asset's checksum}. * * @see ResourceStreamer * @see ClasspathAssetAliasManager @@ -51,26 +53,27 @@ public class AssetDispatcher implements Dispatcher */ private final List<String> assetPaths = CollectionFactory.newList(); - private final String pathPrefix; + private final String uncompressedPathPrefix, compressedPathPrefix; public AssetDispatcher(Map<String, AssetRequestHandler> configuration, PathConstructor pathConstructor, @Symbol(SymbolConstants.ASSET_PATH_PREFIX) - String assetPathPrefix) + String uncompressedPrefix, + + @Symbol(SymbolConstants.COMPRESSED_ASSET_PATH_PREFIX) + String compressedPrefix) { - pathPrefix = pathConstructor.constructDispatchPath(assetPathPrefix, ""); + uncompressedPathPrefix = pathConstructor.constructDispatchPath(uncompressedPrefix, ""); + compressedPathPrefix = pathConstructor.constructDispatchPath(compressedPrefix, ""); for (String path : configuration.keySet()) { - String extendedPath = path.length() == 0 - ? pathPrefix - : pathPrefix + path + "/"; - - pathToHandler.put(extendedPath, configuration.get(path)); + AssetRequestHandler handler = configuration.get(path); - assetPaths.add(extendedPath); + addPath(uncompressedPathPrefix, path, handler); + addPath(compressedPathPrefix, path, handler); } // Sort by descending length @@ -84,6 +87,29 @@ public class AssetDispatcher implements Dispatcher }); } + private void addPath(String prefix, String path, AssetRequestHandler handler) + { + String extendedPath = buildPath(prefix, path); + + pathToHandler.put(extendedPath, handler); + + assetPaths.add(extendedPath); + } + + private String buildPath(String prefix, String path) + { + // TODO: Not sure when path would be length 0! + return path.length() == 0 + ? prefix + : prefix + path + "/"; + } + + private boolean matchesEitherPrefix(String path) + { + return path.startsWith(compressedPathPrefix) || + path.startsWith(uncompressedPathPrefix); + } + public boolean dispatch(Request request, Response response) throws IOException { String path = request.getPath(); @@ -91,7 +117,7 @@ public class AssetDispatcher implements Dispatcher // Remember that the request path does not include the context path, so we can simply start // looking for the asset path prefix right off the bat. - if (!path.startsWith(pathPrefix)) + if (!matchesEitherPrefix(path)) { return false; } http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/aa465fcd/tapestry-core/src/main/java/org/apache/tapestry5/services/assets/AssetsModule.java ---------------------------------------------------------------------- diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/services/assets/AssetsModule.java b/tapestry-core/src/main/java/org/apache/tapestry5/services/assets/AssetsModule.java index ad954c0..797e464 100644 --- a/tapestry-core/src/main/java/org/apache/tapestry5/services/assets/AssetsModule.java +++ b/tapestry-core/src/main/java/org/apache/tapestry5/services/assets/AssetsModule.java @@ -76,6 +76,7 @@ public class AssetsModule configuration.add(SymbolConstants.ASSET_URL_FULL_QUALIFIED, false); configuration.add(SymbolConstants.ASSET_PATH_PREFIX, "assets"); + configuration.add(SymbolConstants.COMPRESSED_ASSET_PATH_PREFIX, "${tapestry.asset-path-prefix}.gz"); } // The use of decorators is to allow third-parties to get their own extensions
