You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by hl...@apache.org on 2013/04/02 15:01:37 UTC
[3/5] git commit: Add ETag support
Add ETag support
Project: http://git-wip-us.apache.org/repos/asf/tapestry-5/repo
Commit: http://git-wip-us.apache.org/repos/asf/tapestry-5/commit/97b0d4fb
Tree: http://git-wip-us.apache.org/repos/asf/tapestry-5/tree/97b0d4fb
Diff: http://git-wip-us.apache.org/repos/asf/tapestry-5/diff/97b0d4fb
Branch: refs/heads/master
Commit: 97b0d4fba108295858dfd9b53deb14004530dade
Parents: 398f6bd
Author: Howard M. Lewis Ship <hl...@apache.org>
Authored: Tue Apr 2 05:51:26 2013 -0700
Committer: Howard M. Lewis Ship <hl...@apache.org>
Committed: Tue Apr 2 06:01:18 2013 -0700
----------------------------------------------------------------------
.../internal/services/ResourceStreamerImpl.java | 21 ++++++++
.../services/assets/StackAssetRequestHandler.java | 40 ++++++++------
.../services/javascript/ModuleDispatcher.java | 4 +-
3 files changed, 47 insertions(+), 18 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/97b0d4fb/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ResourceStreamerImpl.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ResourceStreamerImpl.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ResourceStreamerImpl.java
index c4a6464..8daec39 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ResourceStreamerImpl.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ResourceStreamerImpl.java
@@ -125,14 +125,35 @@ public class ResourceStreamerImpl implements ResourceStreamer
}
}
+ // ETag should be surrounded with quotes.
+ String token = "\"" + streamable.getChecksum() + "\"";
+
+ // Even when sending a 304, we want the ETag associated with the request.
+ // In most cases (except JavaScript modules), the checksum is also embedded into the URL.
+ // However, E-Tags are also useful for enabling caching inside intermediate servers, CDNs, etc.
+ response.setHeader("ETag", token);
+
+ // If the client can send the correct ETag token, then its cache already contains the correct
+ // content.
+
+ String providedToken = request.getHeader("If-None-Match");
+
+ if (providedToken != null && providedToken.equals(token)) {
+ response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
+ return;
+ }
+
// Prevent the upstream code from compressing when we don't want to.
response.disableCompression();
response.setDateHeader("Last-Modified", lastModified);
+
if (productionMode)
{
+ // Starting in 5.4, this is a lot less necessary; any change to a Resource will result
+ // in a new asset URL with the changed checksum incorporated into the URL.
response.setDateHeader("Expires", lastModified + InternalConstants.TEN_YEARS);
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/97b0d4fb/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/StackAssetRequestHandler.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/StackAssetRequestHandler.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/StackAssetRequestHandler.java
index 31c6b08..39f1e31 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/StackAssetRequestHandler.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/StackAssetRequestHandler.java
@@ -14,19 +14,16 @@
package org.apache.tapestry5.internal.services.assets;
-import org.apache.tapestry5.SymbolConstants;
import org.apache.tapestry5.internal.services.ResourceStreamer;
+import org.apache.tapestry5.ioc.IOOperation;
import org.apache.tapestry5.ioc.OperationTracker;
-import org.apache.tapestry5.ioc.annotations.Symbol;
import org.apache.tapestry5.services.LocalizationSetter;
import org.apache.tapestry5.services.Request;
import org.apache.tapestry5.services.Response;
import org.apache.tapestry5.services.ResponseCompressionAnalyzer;
import org.apache.tapestry5.services.assets.AssetRequestHandler;
-import org.apache.tapestry5.services.assets.ResourceMinimizer;
import org.apache.tapestry5.services.assets.StreamableResource;
-import org.apache.tapestry5.services.assets.StreamableResourceSource;
-import org.apache.tapestry5.services.javascript.JavaScriptStackSource;
+import org.slf4j.Logger;
import java.io.IOException;
import java.util.regex.Matcher;
@@ -34,6 +31,8 @@ import java.util.regex.Pattern;
public class StackAssetRequestHandler implements AssetRequestHandler
{
+ private final Logger logger;
+
private final LocalizationSetter localizationSetter;
private final ResponseCompressionAnalyzer compressionAnalyzer;
@@ -49,12 +48,13 @@ public class StackAssetRequestHandler implements AssetRequestHandler
private final JavaScriptStackAssembler javaScriptStackAssembler;
- public StackAssetRequestHandler(LocalizationSetter localizationSetter,
+ public StackAssetRequestHandler(Logger logger, LocalizationSetter localizationSetter,
ResponseCompressionAnalyzer compressionAnalyzer,
ResourceStreamer resourceStreamer,
OperationTracker tracker,
JavaScriptStackAssembler javaScriptStackAssembler)
{
+ this.logger = logger;
this.localizationSetter = localizationSetter;
this.compressionAnalyzer = compressionAnalyzer;
this.resourceStreamer = resourceStreamer;
@@ -64,22 +64,25 @@ public class StackAssetRequestHandler implements AssetRequestHandler
public boolean handleAssetRequest(Request request, Response response, final String extraPath) throws IOException
{
- tracker.perform(String.format("Streaming asset stack %s", extraPath),
- new org.apache.tapestry5.ioc.IOOperation<Void>()
+ return tracker.perform(String.format("Streaming asset stack %s", extraPath),
+ new IOOperation<Boolean>()
{
- public Void perform() throws IOException
+ public Boolean perform() throws IOException
{
boolean compress = compressionAnalyzer.isGZipSupported();
StreamableResource resource = getResource(extraPath, compress);
+ if (resource == null)
+ {
+ return false;
+ }
+
resourceStreamer.streamResource(resource);
- return null;
+ return true;
}
});
-
- return true;
}
private StreamableResource getResource(String extraPath, boolean compressed) throws IOException
@@ -88,11 +91,12 @@ public class StackAssetRequestHandler implements AssetRequestHandler
if (!matcher.matches())
{
- throw new RuntimeException("Invalid path for a stack asset request.");
- }
+ logger.warn(String.format("Unable to parse '%s' as an asset stack path", extraPath));
- // TODO: Extract the stack's aggregate checksum as well
+ return null;
+ }
+ String checksum = matcher.group(1);
String localeName = matcher.group(2);
String stackName = matcher.group(3);
@@ -101,8 +105,10 @@ public class StackAssetRequestHandler implements AssetRequestHandler
localizationSetter.setNonPersistentLocaleFromLocaleName(localeName);
- // TODO: Verify request checksum against actual
+ StreamableResource resource = javaScriptStackAssembler.assembleJavaScriptResourceForStack(stackName, compressed);
- return javaScriptStackAssembler.assembleJavaScriptResourceForStack(stackName, compressed);
+ return checksum.equals(resource.getChecksum())
+ ? resource
+ : null;
}
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/97b0d4fb/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/javascript/ModuleDispatcher.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/javascript/ModuleDispatcher.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/javascript/ModuleDispatcher.java
index b81dd0f..284e23c 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/javascript/ModuleDispatcher.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/javascript/ModuleDispatcher.java
@@ -69,7 +69,9 @@ public class ModuleDispatcher implements Dispatcher
String extraPath = requestPath.substring(prefix.length());
// Ensure request ends with '.js'. That's the extension tacked on by RequireJS because it expects there
- // to be a hierarchy of static JavaScript files here.
+ // to be a hierarchy of static JavaScript files here. In reality, we may be cross-compiling CoffeeScript to
+ // JavaScript, or generating modules on-the-fly, or exposing arbitrary Resources from somewhere on the classpath
+ // as a module.
int dotx = extraPath.lastIndexOf('.');