Issue #1340 Consistent optional use of query string in PushCacheFilter
This commit is contained in:
parent
9f9e1ab190
commit
2219863c11
|
@ -704,7 +704,7 @@ public class PushCacheFilterTest extends AbstractTest
|
|||
{
|
||||
String name = "foo";
|
||||
String value = "bar";
|
||||
final String primaryResource = "/primary.html";
|
||||
final String primaryResource = "/primary.html?"+name + "=" +value;
|
||||
final String secondaryResource = "/secondary.html?" + name + "=" + value;
|
||||
start(new HttpServlet()
|
||||
{
|
||||
|
|
|
@ -73,6 +73,8 @@ import org.eclipse.jetty.util.log.Logger;
|
|||
* secondary resources are pushed to the client, unless the request carries
|
||||
* {@code If-xxx} header that hint that the client has the resources in its
|
||||
* cache.</p>
|
||||
* <p>If the init param useQueryInKey is set, then the query string is used as
|
||||
* as part of the key to identify a resource</p>
|
||||
*/
|
||||
@ManagedObject("Push cache based on the HTTP 'Referer' header")
|
||||
public class PushCacheFilter implements Filter
|
||||
|
@ -85,6 +87,7 @@ public class PushCacheFilter implements Filter
|
|||
private long _associatePeriod = 4000L;
|
||||
private int _maxAssociations = 16;
|
||||
private long _renew = System.nanoTime();
|
||||
private boolean _useQueryInKey;
|
||||
|
||||
@Override
|
||||
public void init(FilterConfig config) throws ServletException
|
||||
|
@ -106,6 +109,8 @@ public class PushCacheFilter implements Filter
|
|||
for (String p : StringUtil.csvSplit(ports))
|
||||
_ports.add(Integer.parseInt(p));
|
||||
|
||||
_useQueryInKey = Boolean.parseBoolean(config.getInitParameter("useQueryInKey"));
|
||||
|
||||
// Expose for JMX.
|
||||
config.getServletContext().setAttribute(config.getFilterName(), this);
|
||||
|
||||
|
@ -161,10 +166,13 @@ public class PushCacheFilter implements Filter
|
|||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("{} {} referrer={} conditional={} synthetic={}", request.getMethod(), request.getRequestURI(), referrer, conditional, isPushRequest(request));
|
||||
|
||||
String path = URIUtil.addPaths(request.getServletPath(), request.getPathInfo());
|
||||
String query = request.getQueryString();
|
||||
if (query != null)
|
||||
path += "?" + query;
|
||||
String key = URIUtil.addPaths(request.getServletPath(), request.getPathInfo());
|
||||
if (_useQueryInKey)
|
||||
{
|
||||
String query = request.getQueryString();
|
||||
if (query != null)
|
||||
key += "?" + query;
|
||||
}
|
||||
if (referrer != null)
|
||||
{
|
||||
HttpURI referrerURI = new HttpURI(referrer);
|
||||
|
@ -180,13 +188,13 @@ public class PushCacheFilter implements Filter
|
|||
{
|
||||
if (HttpMethod.GET.is(request.getMethod()))
|
||||
{
|
||||
String referrerPath = referrerURI.getPath();
|
||||
String referrerPath = _useQueryInKey?referrerURI.getPathQuery():referrerURI.getPath();
|
||||
if (referrerPath == null)
|
||||
referrerPath = "/";
|
||||
if (referrerPath.startsWith(request.getContextPath()))
|
||||
{
|
||||
String referrerPathNoContext = referrerPath.substring(request.getContextPath().length());
|
||||
if (!referrerPathNoContext.equals(path))
|
||||
if (!referrerPathNoContext.equals(key))
|
||||
{
|
||||
PrimaryResource primaryResource = _cache.get(referrerPathNoContext);
|
||||
if (primaryResource != null)
|
||||
|
@ -194,29 +202,29 @@ public class PushCacheFilter implements Filter
|
|||
long primaryTimestamp = primaryResource._timestamp.get();
|
||||
if (primaryTimestamp != 0)
|
||||
{
|
||||
RequestDispatcher dispatcher = request.getServletContext().getRequestDispatcher(path);
|
||||
RequestDispatcher dispatcher = request.getServletContext().getRequestDispatcher(key);
|
||||
if (now - primaryTimestamp < TimeUnit.MILLISECONDS.toNanos(_associatePeriod))
|
||||
{
|
||||
ConcurrentMap<String, RequestDispatcher> associated = primaryResource._associated;
|
||||
// Not strictly concurrent-safe, just best effort to limit associations.
|
||||
if (associated.size() <= _maxAssociations)
|
||||
{
|
||||
if (associated.putIfAbsent(path, dispatcher) == null)
|
||||
if (associated.putIfAbsent(key, dispatcher) == null)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Associated {} to {}", path, referrerPathNoContext);
|
||||
LOG.debug("Associated {} to {}", key, referrerPathNoContext);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Not associated {} to {}, exceeded max associations of {}", path, referrerPathNoContext, _maxAssociations);
|
||||
LOG.debug("Not associated {} to {}, exceeded max associations of {}", key, referrerPathNoContext, _maxAssociations);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Not associated {} to {}, outside associate period of {}ms", path, referrerPathNoContext, _associatePeriod);
|
||||
LOG.debug("Not associated {} to {}, outside associate period of {}ms", key, referrerPathNoContext, _associatePeriod);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -224,7 +232,7 @@ public class PushCacheFilter implements Filter
|
|||
else
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Not associated {} to {}, referring to self", path, referrerPathNoContext);
|
||||
LOG.debug("Not associated {} to {}, referring to self", key, referrerPathNoContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -236,15 +244,15 @@ public class PushCacheFilter implements Filter
|
|||
}
|
||||
}
|
||||
|
||||
PrimaryResource primaryResource = _cache.get(path);
|
||||
PrimaryResource primaryResource = _cache.get(key);
|
||||
if (primaryResource == null)
|
||||
{
|
||||
PrimaryResource r = new PrimaryResource();
|
||||
primaryResource = _cache.putIfAbsent(path, r);
|
||||
primaryResource = _cache.putIfAbsent(key, r);
|
||||
primaryResource = primaryResource == null ? r : primaryResource;
|
||||
primaryResource._timestamp.compareAndSet(0, now);
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Cached primary resource {}", path);
|
||||
LOG.debug("Cached primary resource {}", key);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -253,7 +261,7 @@ public class PushCacheFilter implements Filter
|
|||
{
|
||||
primaryResource._associated.clear();
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Clear associated resources for {}", path);
|
||||
LOG.debug("Clear associated resources for {}", key);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -274,7 +282,7 @@ public class PushCacheFilter implements Filter
|
|||
|
||||
Dispatcher dispatcher = (Dispatcher)entry.getValue();
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Pushing {} for {}", dispatcher, path);
|
||||
LOG.debug("Pushing {} for {}", dispatcher, key);
|
||||
dispatcher.push(request);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue