Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 6 commits into from Feb 17, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -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];
Expand All @@ -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
Expand All @@ -45,22 +58,23 @@ public boolean equals(Object o)
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)
{
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;
}
}
Expand Up @@ -123,6 +123,7 @@
* 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}
Expand Down
Expand Up @@ -44,6 +44,7 @@
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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -591,7 +592,7 @@ public void testDeleteETagGzipHandler() throws Exception
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()));
Expand Down