Fix #5979 by allowing a configurable etag separator. (#5980)

* Fix #5979 by allowing a configurable etag separator.

Fix #5979 by allowing a configurable etag separator

* updates from review

* Updates from review

Signed-off-by: Greg Wilkins <gregw@webtide.com>
This commit is contained in:
Greg Wilkins 2021-02-17 22:19:23 +01:00 committed by GitHub
parent 70d6724d93
commit a8b4927427
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 30 additions and 14 deletions

View File

@ -18,8 +18,21 @@
package org.eclipse.jetty.http;
import java.util.Objects;
import org.eclipse.jetty.util.StringUtil;
public class CompressedContentFormat
{
/**
* The separator within an etag used to indicate a compressed variant. By default the separator is "--"
* So etag for compressed resource that normally has an etag of <code>W/"28c772d6"</code>
* is <code>W/"28c772d6--gzip"</code>. The separator may be changed by the
* "org.eclipse.jetty.http.CompressedContentFormat.ETAG_SEPARATOR" System property. If changed, it should be changed to a string
* that will not be found in a normal etag or at least is very unlikely to be a substring of a normal etag.
*/
public static final String ETAG_SEPARATOR = System.getProperty(CompressedContentFormat.class.getName() + ".ETAG_SEPARATOR", "--");
public static final CompressedContentFormat GZIP = new CompressedContentFormat("gzip", ".gz");
public static final CompressedContentFormat BR = new CompressedContentFormat("br", ".br");
public static final CompressedContentFormat[] NONE = new CompressedContentFormat[0];
@ -32,11 +45,11 @@ public class CompressedContentFormat
public CompressedContentFormat(String encoding, String extension)
{
_encoding = encoding;
_extension = extension;
_etag = "--" + encoding;
_encoding = StringUtil.asciiToLowerCase(encoding);
_extension = StringUtil.asciiToLowerCase(extension);
_etag = ETAG_SEPARATOR + _encoding;
_etagQuote = _etag + "\"";
_contentEncoding = new PreEncodedHttpField(HttpHeader.CONTENT_ENCODING, encoding);
_contentEncoding = new PreEncodedHttpField(HttpHeader.CONTENT_ENCODING, _encoding);
}
@Override
@ -45,12 +58,13 @@ public class CompressedContentFormat
if (!(o instanceof CompressedContentFormat))
return false;
CompressedContentFormat ccf = (CompressedContentFormat)o;
if (_encoding == null && ccf._encoding != null)
return false;
if (_extension == null && ccf._extension != null)
return false;
return Objects.equals(_encoding, ccf._encoding) && Objects.equals(_extension, ccf._extension);
}
return _encoding.equalsIgnoreCase(ccf._encoding) && _extension.equalsIgnoreCase(ccf._extension);
@Override
public int hashCode()
{
return Objects.hash(_encoding, _extension);
}
public static boolean tagEquals(String etag, String tag)
@ -58,9 +72,9 @@ public class CompressedContentFormat
if (etag.equals(tag))
return true;
int dashdash = tag.indexOf("--");
if (dashdash > 0 && dashdash == etag.length() - 1)
return etag.regionMatches(0, tag, 0, dashdash);
int separator = tag.lastIndexOf(ETAG_SEPARATOR);
if (separator > 0 && separator == etag.length() - 1)
return etag.regionMatches(0, tag, 0, separator);
return false;
}
}

View File

@ -123,6 +123,7 @@ import org.eclipse.jetty.util.log.Logger;
* If a ETag is present in the Response headers, and GzipHandler is compressing the
* contents, it will add the {@code --gzip} suffix before the Response headers are committed
* and sent to the User Agent.
* Note that the suffix used is determined by {@link CompressedContentFormat#ETAG_SEPARATOR}
* </p>
* <p>
* This implementation relies on an Jetty internal {@link org.eclipse.jetty.server.HttpOutput.Interceptor}

View File

@ -44,6 +44,7 @@ import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.CompressedContentFormat;
import org.eclipse.jetty.http.HttpTester;
import org.eclipse.jetty.server.HttpOutput;
import org.eclipse.jetty.server.LocalConnector;
@ -87,7 +88,7 @@ public class GzipHandlerTest
private static final String __micro = __content.substring(0, 10);
private static final String __contentETag = String.format("W/\"%x\"", __content.hashCode());
private static final String __contentETagGzip = String.format("W/\"%x--gzip\"", __content.hashCode());
private static final String __contentETagGzip = String.format("W/\"%x" + CompressedContentFormat.GZIP._etag + "\"", __content.hashCode());
private static final String __icontent = "BEFORE" + __content + "AFTER";
private Server _server;
@ -591,7 +592,7 @@ public class GzipHandlerTest
request.setURI("/ctx/content");
request.setVersion("HTTP/1.0");
request.setHeader("Host", "tester");
request.setHeader("If-Match", "WrongEtag--gzip");
request.setHeader("If-Match", "WrongEtag" + CompressedContentFormat.GZIP._etag);
request.setHeader("accept-encoding", "gzip");
response = HttpTester.parseResponse(_connector.getResponse(request.generate()));