Patches are best provided on JIRA; there's a checkbox that shows you have granted the rights to the patch & code to the Apache Software Foundation. Thanks!
On Tue, Feb 21, 2012 at 12:28 PM, Paul Stanton <p...@mapshed.com.au> wrote: > Here's my implementation: > > // Copyright 2006, 2008, 2009, 2010, 2011 The Apache Software Foundation > // > // Licensed under the Apache License, Version 2.0 (the "License"); > // you may not use this file except in compliance with the License. > // You may obtain a copy of the License at > // > // http://www.apache.org/licenses/LICENSE-2.0 > // > // Unless required by applicable law or agreed to in writing, software > // distributed under the License is distributed on an "AS IS" BASIS, > // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. > // See the License for the specific language governing permissions and > // limitations under the License. > > package org.apache.tapestry5.internal.services; > > import java.io.IOException; > import java.util.Collections; > import java.util.Comparator; > import java.util.List; > import java.util.Map; > > import javax.servlet.http.HttpServletResponse; > > import org.apache.tapestry5.SymbolConstants; > import org.apache.tapestry5.ioc.annotations.Symbol; > import org.apache.tapestry5.ioc.annotations.UsesMappedConfiguration; > import org.apache.tapestry5.ioc.internal.util.CollectionFactory; > import org.apache.tapestry5.services.ClasspathAssetAliasManager; > import org.apache.tapestry5.services.Dispatcher; > import org.apache.tapestry5.services.Request; > import org.apache.tapestry5.services.Response; > import org.apache.tapestry5.services.assets.AssetRequestHandler; > > /** > * 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. > * > * @see ResourceStreamer > * @see ClasspathAssetAliasManager > * @see AssetRequestHandler > */ > // PATCHED incorrect APPLICATION_VERSION 302 temporary redirect to current > APPLICATION_VERSION > > // PATCH + > @SuppressWarnings("all") > @UsesMappedConfiguration(AssetRequestHandler.class) > public class AssetDispatcher implements Dispatcher > { > /** > * Keyed on extended path name, which includes the pathPrefix first and a > trailing slash. > */ > private final Map<String, AssetRequestHandler> pathToHandler = > CollectionFactory.newMap(); > > /** > * List of path prefixes in the pathToHandler, sorted be descending > length. > */ > private final List<String> assetPaths = CollectionFactory.newList(); > > private final String pathPrefix; > > // PATCH + > private final String pathPrefixPattern; > > public AssetDispatcher(Map<String, AssetRequestHandler> configuration, > > @Symbol(SymbolConstants.APPLICATION_VERSION) String applicationVersion, > > @Symbol(SymbolConstants.APPLICATION_FOLDER) String applicationFolder, > > @Symbol(SymbolConstants.ASSET_PATH_PREFIX) String assetPathPrefix) > { > String folder = applicationFolder.equals("") ? "" : "/" + > applicationFolder; > > this.pathPrefix = folder + assetPathPrefix + applicationVersion + > "/"; > > // PATCH + > this.pathPrefixPattern = "^" + folder + assetPathPrefix + > "[^/]{1,}/(.*)$"; > > for (String path : configuration.keySet()) > { > String extendedPath = this.pathPrefix + path + "/"; > > pathToHandler.put(extendedPath, configuration.get(path)); > > assetPaths.add(extendedPath); > } > > // Sort by descending length > > Collections.sort(assetPaths, new Comparator<String>() > { > public int compare(String o1, String o2) > { > return o2.length() - o1.length(); > } > }); > } > > public boolean dispatch(Request request, Response response) throws > IOException > { > String path = request.getPath(); > > // 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)) > { > // PATCH + > if (path.matches(pathPrefixPattern)) > { > // send 302 temporary redirect to the version this server is > using > String newPath = request.getContextPath() + > path.replaceAll(pathPrefixPattern, pathPrefix + "$1"); > response.setHeader("Location", newPath); > response.sendError(HttpServletResponse.SC_MOVED_TEMPORARILY, > newPath); > return true; > } > return false; > } > > for (String extendedPath : assetPaths) > { > > if (path.startsWith(extendedPath)) > { > AssetRequestHandler handler = > pathToHandler.get(extendedPath); > > String extraPath = path.substring(extendedPath.length()); > > boolean handled = handler.handleAssetRequest(request, > response, extraPath); > > if (handled) > { > return true; > } > } > } > > response.sendError(HttpServletResponse.SC_NOT_FOUND, path); > > return true; > > } > } > > > On 22/02/2012 6:05 AM, Howard Lewis Ship wrote: >> >> I suspect the 302 redirect may be the correct solution, and Tapestry >> could support this pretty reasonably. >> >> The perfect solution would involve the following: >> - The version number if replaced with the SHA1 hash of the resource's >> (uncompressed) content >> - All CSS is dynamically rewritten to convert relative references into >> full paths including the correct SHA1 hash >> >> I wonder if the 302 redirect could act as a way to avoid rewriting the >> CSS? >> >> On Sun, Feb 19, 2012 at 7:57 PM, Paul Stanton<p...@mapshed.com.au> wrote: >>> >>> Hi Cezary, >>> >>> I think I have the same need as you. >>> >>> We use load balanced servers, and when upgrading we upgrade one at a time >>> so >>> that there is always a server running. >>> >>> But the side effect is that the upgraded server can receive requests for >>> the >>> old assets, and we don't want to fail in this case. >>> >>> In the past (5.1) I monkey-patched AssetResourceLocatorImpl to allow<= >>> version number requests. >>> >>> However in migrating to 5.3 I would like a better solution, and the >>> implementation is different now anyway. >>> >>> I like the idea of the 302 redirect. >>> >>> How did you end up solving this? Is it possible to just contribute your >>> own >>> AssetDispatcher instead of just replacing the class? >>> >>> Thanks, Paul. >>> >>> >>> On 24/03/2011 10:09 AM, Cezary Biernacki wrote: >>>>> >>>>> >>>>> Perhaps the AssetDispatcher could check the requested version number >>>>> and >>>>> if >>>>> it doesn't match the app version, send a 302 redirect to the "correct" >>>>> URL? >>>>> /assets/1.3/ctx/script.js --> /assets/1.2/ctx/script.js >>>>> >>>>> Or perhaps it should only deliver the asset if the requested version os >>>>> older than or equal to the app version? >>>>> Determining "older" and "newer" would however assume people name their >>>>> application versions in a certain way. >>>> >>>> >>>> It is exactly what I did in my application. I have overridden >>>> AssetsDispatcher service with my copy based on original one, that >>>> differs >>>> only in handling missing resources: if resource actually exists but just >>>> version numbers differ, my dispatcher just sends redirect response with >>>> a >>>> correct path. >>>> >>>> As a side note, I observed in that - at least in my case - typically a >>>> favicon was a typical asset requested with wrong version number, >>>> probably >>>> from bookmarks. >>>> >>>> Regards, >>>> Cezary >>>> >>> --------------------------------------------------------------------- >>> To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org >>> For additional commands, e-mail: users-h...@tapestry.apache.org >>> >> >> > > --------------------------------------------------------------------- > To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org > For additional commands, e-mail: users-h...@tapestry.apache.org > -- Howard M. Lewis Ship Creator of Apache Tapestry The source for Tapestry training, mentoring and support. Contact me to learn how I can get you up and productive in Tapestry fast! (971) 678-5210 http://howardlewisship.com --------------------------------------------------------------------- To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org