Merge remote-tracking branch 'origin/jetty-9.4.x' into jetty-10.0.x

Signed-off-by: gregw <gregw@webtide.com>
This commit is contained in:
gregw 2021-02-18 17:44:46 +01:00
commit bb5fefdaeb
12 changed files with 409 additions and 51 deletions

View File

@ -15,6 +15,7 @@ package org.eclipse.jetty.http;
import java.util.Objects;
import org.eclipse.jetty.util.QuotedStringTokenizer;
import org.eclipse.jetty.util.StringUtil;
public class CompressedContentFormat
@ -32,18 +33,18 @@ public class CompressedContentFormat
public static final CompressedContentFormat BR = new CompressedContentFormat("br", ".br");
public static final CompressedContentFormat[] NONE = new CompressedContentFormat[0];
public final String _encoding;
public final String _extension;
public final String _etag;
public final String _etagQuote;
public final PreEncodedHttpField _contentEncoding;
private final String _encoding;
private final String _extension;
private final String _etagSuffix;
private final String _etagSuffixQuote;
private final PreEncodedHttpField _contentEncoding;
public CompressedContentFormat(String encoding, String extension)
{
_encoding = StringUtil.asciiToLowerCase(encoding);
_extension = StringUtil.asciiToLowerCase(extension);
_etag = ETAG_SEPARATOR + _encoding;
_etagQuote = _etag + "\"";
_etagSuffix = StringUtil.isEmpty(ETAG_SEPARATOR) ? "" : (ETAG_SEPARATOR + _encoding);
_etagSuffixQuote = _etagSuffix + "\"";
_contentEncoding = new PreEncodedHttpField(HttpHeader.CONTENT_ENCODING, _encoding);
}
@ -56,20 +57,104 @@ public class CompressedContentFormat
return Objects.equals(_encoding, ccf._encoding) && Objects.equals(_extension, ccf._extension);
}
public String getEncoding()
{
return _encoding;
}
public String getExtension()
{
return _extension;
}
public String getEtagSuffix()
{
return _etagSuffix;
}
public HttpField getContentEncoding()
{
return _contentEncoding;
}
/** Get an etag with suffix that represents this compressed type.
* @param etag An etag
* @return An etag with compression suffix, or the etag itself if no suffix is configured.
*/
public String etag(String etag)
{
if (StringUtil.isEmpty(ETAG_SEPARATOR))
return etag;
int end = etag.length() - 1;
if (etag.charAt(end) == '"')
return etag.substring(0, end) + _etagSuffixQuote;
return etag + _etagSuffix;
}
@Override
public int hashCode()
{
return Objects.hash(_encoding, _extension);
}
public static boolean tagEquals(String etag, String tag)
/** Check etags for equality, accounting for quoting and compression suffixes.
* @param etag An etag without a compression suffix
* @param etagWithSuffix An etag optionally with a compression suffix.
* @return True if the tags are equal.
*/
public static boolean tagEquals(String etag, String etagWithSuffix)
{
if (etag.equals(tag))
// Handle simple equality
if (etag.equals(etagWithSuffix))
return true;
int separator = tag.lastIndexOf(ETAG_SEPARATOR);
if (separator > 0 && separator == etag.length() - 1)
return etag.regionMatches(0, tag, 0, separator);
return false;
// If no separator defined, then simple equality is only possible positive
if (StringUtil.isEmpty(ETAG_SEPARATOR))
return false;
// Are both tags quoted?
boolean etagQuoted = etag.endsWith("\"");
boolean etagSuffixQuoted = etagWithSuffix.endsWith("\"");
// Look for a separator
int separator = etagWithSuffix.lastIndexOf(ETAG_SEPARATOR);
// If both tags are quoted the same (the norm) then any difference must be the suffix
if (etagQuoted == etagSuffixQuoted)
return separator > 0 && etag.regionMatches(0, etagWithSuffix, 0, separator);
// If either tag is weak then we can't match because weak tags must be quoted
if (etagWithSuffix.startsWith("W/") || etag.startsWith("W/"))
return false;
// compare unquoted strong etags
etag = etagQuoted ? QuotedStringTokenizer.unquote(etag) : etag;
etagWithSuffix = etagSuffixQuoted ? QuotedStringTokenizer.unquote(etagWithSuffix) : etagWithSuffix;
separator = etagWithSuffix.lastIndexOf(ETAG_SEPARATOR);
if (separator > 0)
return etag.regionMatches(0, etagWithSuffix, 0, separator);
return Objects.equals(etag, etagWithSuffix);
}
public String stripSuffixes(String etagsList)
{
if (StringUtil.isEmpty(ETAG_SEPARATOR))
return etagsList;
// This is a poor implementation that ignores list and tag structure
while (true)
{
int i = etagsList.lastIndexOf(_etagSuffix);
if (i < 0)
return etagsList;
etagsList = etagsList.substring(0, i) + etagsList.substring(i + _etagSuffix.length());
}
}
@Override
public String toString()
{
return _encoding;
}
}

View File

@ -66,7 +66,7 @@ public class PrecompressedHttpContent implements HttpContent
@Override
public String getETagValue()
{
return _content.getResource().getWeakETag(_format._etag);
return _content.getResource().getWeakETag(_format.getEtagSuffix());
}
@Override
@ -96,13 +96,13 @@ public class PrecompressedHttpContent implements HttpContent
@Override
public HttpField getContentEncoding()
{
return _format._contentEncoding;
return _format.getContentEncoding();
}
@Override
public String getContentEncodingValue()
{
return _format._contentEncoding.getValue();
return _format.getContentEncoding().getValue();
}
@Override
@ -162,7 +162,9 @@ public class PrecompressedHttpContent implements HttpContent
@Override
public String toString()
{
return String.format("PrecompressedHttpContent@%x{e=%s,r=%s|%s,lm=%s|%s,ct=%s}", hashCode(), _format._encoding,
return String.format("%s@%x{e=%s,r=%s|%s,lm=%s|%s,ct=%s}",
this.getClass().getSimpleName(), hashCode(),
_format,
_content.getResource(), _precompressedContent.getResource(),
_content.getResource().lastModified(), _precompressedContent.getResource().lastModified(),
getContentType());

View File

@ -30,6 +30,8 @@ import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import static org.eclipse.jetty.http.CompressedContentFormat.BR;
import static org.eclipse.jetty.http.CompressedContentFormat.GZIP;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.junit.jupiter.api.Assertions.assertEquals;
@ -75,9 +77,25 @@ public class GZIPContentDecoderTest
{
assertTrue(CompressedContentFormat.tagEquals("tag", "tag"));
assertTrue(CompressedContentFormat.tagEquals("\"tag\"", "\"tag\""));
assertTrue(CompressedContentFormat.tagEquals("\"tag\"", "\"tag--gzip\""));
assertFalse(CompressedContentFormat.tagEquals("Zag", "Xag--gzip"));
assertTrue(CompressedContentFormat.tagEquals("\"tag\"", "\"tag" + GZIP.getEtagSuffix() + "\""));
assertTrue(CompressedContentFormat.tagEquals("\"tag\"", "\"tag" + BR.getEtagSuffix() + "\""));
assertTrue(CompressedContentFormat.tagEquals("W/\"1234567\"", "W/\"1234567\""));
assertTrue(CompressedContentFormat.tagEquals("W/\"1234567\"", "W/\"1234567" + GZIP.getEtagSuffix() + "\""));
assertFalse(CompressedContentFormat.tagEquals("Zag", "Xag" + GZIP.getEtagSuffix()));
assertFalse(CompressedContentFormat.tagEquals("xtag", "tag"));
assertFalse(CompressedContentFormat.tagEquals("W/\"1234567\"", "W/\"1234111\""));
assertFalse(CompressedContentFormat.tagEquals("W/\"1234567\"", "W/\"1234111" + GZIP.getEtagSuffix() + "\""));
assertTrue(CompressedContentFormat.tagEquals("12345", "\"12345\""));
assertTrue(CompressedContentFormat.tagEquals("\"12345\"", "12345"));
assertTrue(CompressedContentFormat.tagEquals("12345", "\"12345" + GZIP.getEtagSuffix() + "\""));
assertTrue(CompressedContentFormat.tagEquals("\"12345\"", "12345" + GZIP.getEtagSuffix()));
assertThat(GZIP.stripSuffixes("12345"), is("12345"));
assertThat(GZIP.stripSuffixes("12345, 666" + GZIP.getEtagSuffix()), is("12345, 666"));
assertThat(GZIP.stripSuffixes("12345, 666" + GZIP.getEtagSuffix() + ",W/\"9999" + GZIP.getEtagSuffix() + "\""),
is("12345, 666,W/\"9999\""));
}
@Test

View File

@ -0,0 +1,73 @@
//
// ========================================================================
// Copyright (c) 1995-2021 Mort Bay Consulting Pty Ltd and others.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.rewrite.handler;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.Request;
public class ForceRequestHeaderValueRule extends Rule
{
private String headerName;
private String forcedValue;
public String getHeaderName()
{
return headerName;
}
public void setHeaderName(String headerName)
{
this.headerName = headerName;
}
public String getForcedValue()
{
return forcedValue;
}
public void setForcedValue(String forcedValue)
{
this.forcedValue = forcedValue;
}
@Override
public String matchAndApply(String target, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws IOException
{
String existingValue = httpServletRequest.getHeader(headerName);
if (existingValue == null)
{
// no hit, skip this rule.
return null;
}
if (existingValue.equals(forcedValue))
{
// already what we expect, skip this rule.
return null;
}
Request baseRequest = Request.getBaseRequest(httpServletRequest);
baseRequest.getHttpFields().remove(headerName);
baseRequest.getHttpFields().add(headerName, forcedValue);
return target;
}
}

View File

@ -0,0 +1,187 @@
//
// ========================================================================
// Copyright (c) 1995-2021 Mort Bay Consulting Pty Ltd and others.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.rewrite.handler;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.Collections;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.HttpTester;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.LocalConnector;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.server.handler.HandlerList;
import org.eclipse.jetty.util.component.LifeCycle;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.not;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class ForceRequestHeaderValueRuleTest
{
private Server server;
private LocalConnector connector;
private ForceRequestHeaderValueRule rule;
@BeforeEach
public void setup() throws Exception
{
server = new Server();
connector = new LocalConnector(server);
server.addConnector(connector);
HandlerList handlers = new HandlerList();
RewriteHandler rewriteHandler = new RewriteHandler();
rule = new ForceRequestHeaderValueRule();
rewriteHandler.addRule(rule);
Handler handler = new AbstractHandler()
{
@Override
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
response.setContentType("text/plain");
response.setCharacterEncoding("utf-8");
OutputStream stream = response.getOutputStream();
OutputStreamWriter out = new OutputStreamWriter(stream);
out.append("Echo\n");
for (String headerName : Collections.list(request.getHeaderNames()))
{
// Combine all values for header into single output on response body
out.append("Request Header[").append(headerName).append("]: [")
.append(request.getHeader(headerName)).append("]\n");
}
out.flush();
baseRequest.setHandled(true);
}
};
handlers.addHandler(rewriteHandler);
handlers.addHandler(handler);
server.setHandler(handlers);
server.start();
}
@AfterEach
public void teardown()
{
LifeCycle.stop(server);
}
@Test
public void testNormalRequest() throws Exception
{
rule.setHeaderName("Accept");
rule.setForcedValue("*/*");
StringBuilder request = new StringBuilder();
request.append("GET /echo/foo HTTP/1.1\r\n");
request.append("Host: local\r\n");
request.append("Connection: closed\r\n");
request.append("\r\n");
HttpTester.Response response = HttpTester.parseResponse(connector.getResponse(request.toString()));
assertEquals(200, response.getStatus());
assertThat(response.getContent(), not(containsString("[Accept]")));
assertThat(response.getContent(), containsString("[Host]: [local]"));
assertThat(response.getContent(), containsString("[Connection]: [closed]"));
}
@Test
public void testOneAcceptHeaderRequest() throws Exception
{
rule.setHeaderName("Accept");
rule.setForcedValue("*/*");
StringBuilder request = new StringBuilder();
request.append("GET /echo/foo HTTP/1.1\r\n");
request.append("Host: local\r\n");
request.append("Accept: */*\r\n");
request.append("Connection: closed\r\n");
request.append("\r\n");
String rawResponse = connector.getResponse(request.toString());
HttpTester.Response response = HttpTester.parseResponse(rawResponse);
assertEquals(200, response.getStatus());
assertThat(response.getContent(), containsString("[Accept]: [*/*]"));
assertThat(response.getContent(), containsString("[Host]: [local]"));
assertThat(response.getContent(), containsString("[Connection]: [closed]"));
}
@Test
public void testThreeAcceptHeadersRequest() throws Exception
{
rule.setHeaderName("Accept");
rule.setForcedValue("*/*");
StringBuilder request = new StringBuilder();
request.append("GET /echo/foo HTTP/1.1\r\n");
request.append("Host: local\r\n");
request.append("Accept: images/jpeg\r\n");
request.append("Accept: text/plain\r\n");
request.append("Accept: */*\r\n");
request.append("Connection: closed\r\n");
request.append("\r\n");
String rawResponse = connector.getResponse(request.toString());
HttpTester.Response response = HttpTester.parseResponse(rawResponse);
assertEquals(200, response.getStatus());
assertThat(response.getContent(), containsString("[Accept]: [*/*]"));
assertThat(response.getContent(), containsString("[Host]: [local]"));
assertThat(response.getContent(), containsString("[Connection]: [closed]"));
}
@Test
public void testInterleavedAcceptHeadersRequest() throws Exception
{
rule.setHeaderName("Accept");
rule.setForcedValue("*/*");
StringBuilder request = new StringBuilder();
request.append("GET /echo/foo HTTP/1.1\r\n");
request.append("Host: local\r\n");
request.append("Accept: images/jpeg\r\n"); // not value intended to be forced
request.append("Accept-Encoding: gzip;q=1.0, identity; q=0.5, *;q=0\r\n");
request.append("accept: text/plain\r\n"); // interleaved with other headers shouldn't matter
request.append("Accept-Charset: iso-8859-5, unicode-1-1;q=0.8\r\n");
request.append("ACCEPT: */*\r\n"); // case shouldn't matter
request.append("Connection: closed\r\n");
request.append("\r\n");
String rawResponse = connector.getResponse(request.toString());
HttpTester.Response response = HttpTester.parseResponse(rawResponse);
assertEquals(200, response.getStatus());
assertThat(response.getContent(), containsString("[Accept]: [*/*]"));
assertThat(response.getContent(), containsString("[Accept-Charset]: [iso-8859-5, unicode-1-1;q=0.8]"));
assertThat(response.getContent(), containsString("[Accept-Encoding]: [gzip;q=1.0, identity; q=0.5, *;q=0]"));
assertThat(response.getContent(), containsString("[Host]: [local]"));
assertThat(response.getContent(), containsString("[Connection]: [closed]"));
}
}

View File

@ -224,7 +224,7 @@ public class CachedContentFactory implements HttpContent.ContentFactory
Map<CompressedContentFormat, CachedHttpContent> precompresssedContents = new HashMap<>(_precompressedFormats.length);
for (CompressedContentFormat format : _precompressedFormats)
{
String compressedPathInContext = pathInContext + format._extension;
String compressedPathInContext = pathInContext + format.getExtension();
CachedHttpContent compressedContent = _cache.get(compressedPathInContext);
if (compressedContent == null || compressedContent.isValid())
{
@ -269,7 +269,7 @@ public class CachedContentFactory implements HttpContent.ContentFactory
Map<CompressedContentFormat, HttpContent> compressedContents = new HashMap<>();
for (CompressedContentFormat format : _precompressedFormats)
{
String compressedPathInContext = pathInContext + format._extension;
String compressedPathInContext = pathInContext + format.getExtension();
CachedHttpContent compressedContent = _cache.get(compressedPathInContext);
if (compressedContent != null && compressedContent.isValid() && compressedContent.getResource().lastModified() >= resource.lastModified())
compressedContents.put(format, compressedContent);
@ -682,7 +682,7 @@ public class CachedContentFactory implements HttpContent.ContentFactory
_content = content;
_precompressedContent = precompressedContent;
_etag = (CachedContentFactory.this._etags) ? new PreEncodedHttpField(HttpHeader.ETAG, _content.getResource().getWeakETag(format._etag)) : null;
_etag = (CachedContentFactory.this._etags) ? new PreEncodedHttpField(HttpHeader.ETAG, _content.getResource().getWeakETag(format.getEtagSuffix())) : null;
}
public boolean isValid()

View File

@ -85,7 +85,7 @@ public class ResourceContentFactory implements ContentFactory
Map<CompressedContentFormat, HttpContent> compressedContents = new HashMap<>(_precompressedFormats.length);
for (CompressedContentFormat format : _precompressedFormats)
{
String compressedPathInContext = pathInContext + format._extension;
String compressedPathInContext = pathInContext + format.getExtension();
Resource compressedResource = _factory.getResource(compressedPathInContext);
if (compressedResource != null && compressedResource.exists() && compressedResource.lastModified() >= resource.lastModified() &&
compressedResource.length() < resource.length())

View File

@ -138,7 +138,7 @@ public class ResourceService
public void setPrecompressedFormats(CompressedContentFormat[] precompressedFormats)
{
_precompressedFormats = precompressedFormats;
_preferredEncodingOrder = stream(_precompressedFormats).map(f -> f._encoding).toArray(String[]::new);
_preferredEncodingOrder = stream(_precompressedFormats).map(f -> f.getEncoding()).toArray(String[]::new);
}
public void setEncodingCacheSize(int encodingCacheSize)
@ -279,7 +279,7 @@ public class ResourceService
if (LOG.isDebugEnabled())
LOG.debug("precompressed={}", precompressedContent);
content = precompressedContent;
response.setHeader(HttpHeader.CONTENT_ENCODING.asString(), precompressedContentEncoding._encoding);
response.setHeader(HttpHeader.CONTENT_ENCODING.asString(), precompressedContentEncoding.getEncoding());
}
}
@ -352,7 +352,7 @@ public class ResourceService
{
for (CompressedContentFormat format : availableFormats)
{
if (format._encoding.equals(encoding))
if (format.getEncoding().equals(encoding))
return format;
}
@ -526,9 +526,9 @@ public class ResourceService
if (etag != null)
{
QuotedCSV quoted = new QuotedCSV(true, ifm);
for (String tag : quoted)
for (String etagWithSuffix : quoted)
{
if (CompressedContentFormat.tagEquals(etag, tag))
if (CompressedContentFormat.tagEquals(etag, etagWithSuffix))
{
match = true;
break;

View File

@ -31,7 +31,6 @@ import org.eclipse.jetty.http.CompressedContentFormat;
import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpHeaderValue;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.MimeTypes;
import org.eclipse.jetty.http.PreEncodedHttpField;
@ -150,13 +149,13 @@ import org.slf4j.LoggerFactory;
public class GzipHandler extends HandlerWrapper implements GzipFactory
{
public static final EnumSet<HttpHeader> ETAG_HEADERS = EnumSet.of(HttpHeader.IF_MATCH, HttpHeader.IF_NONE_MATCH);
public static final String GZIP_HANDLER_ETAGS = "o.e.j.s.h.gzip.GzipHandler.etag";
public static final String GZIP = "gzip";
public static final String DEFLATE = "deflate";
public static final int DEFAULT_MIN_GZIP_SIZE = 32;
public static final int BREAK_EVEN_GZIP_SIZE = 23;
private static final Logger LOG = LoggerFactory.getLogger(GzipHandler.class);
private static final HttpField X_CE_GZIP = new PreEncodedHttpField("X-Content-Encoding", "gzip");
private static final HttpField TE_CHUNKED = new PreEncodedHttpField(HttpHeader.TRANSFER_ENCODING, HttpHeaderValue.CHUNKED.asString());
private static final Pattern COMMA_GZIP = Pattern.compile(".*, *gzip");
private InflaterPool _inflaterPool;
@ -600,23 +599,17 @@ public class GzipHandler extends HandlerWrapper implements GzipFactory
case IF_MATCH:
case IF_NONE_MATCH:
{
String etag = field.getValue();
int i = etag.indexOf(CompressedContentFormat.GZIP._etagQuote);
if (i <= 0 || alreadyGzipped)
String etags = field.getValue();
String etagsNoSuffix = CompressedContentFormat.GZIP.stripSuffixes(etags);
if (etagsNoSuffix.equals(etags))
newFields.add(field);
else
{
baseRequest.setAttribute("o.e.j.s.h.gzip.GzipHandler.etag", etag);
while (i >= 0)
{
etag = etag.substring(0, i) + etag.substring(i + CompressedContentFormat.GZIP._etag.length());
i = etag.indexOf(CompressedContentFormat.GZIP._etagQuote, i);
}
newFields.add(new HttpField(field.getHeader(), etag));
newFields.add(new HttpField(field.getHeader(), etagsNoSuffix));
baseRequest.setAttribute(GZIP_HANDLER_ETAGS, etags);
}
break;
}
case CONTENT_LENGTH:
newFields.add(inflated ? new HttpField("X-Content-Length", field.getValue()) : field);
break;

View File

@ -22,6 +22,7 @@ import java.util.zip.Deflater;
import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.http.MimeTypes;
import org.eclipse.jetty.http.PreEncodedHttpField;
import org.eclipse.jetty.server.HttpChannel;
@ -139,9 +140,9 @@ public class GzipHttpOutputInterceptor implements HttpOutput.Interceptor
LOG.debug("{} exclude by status {}", this, sc);
noCompression();
if (sc == 304)
if (sc == HttpStatus.NOT_MODIFIED_304)
{
String requestEtags = (String)_channel.getRequest().getAttribute("o.e.j.s.h.gzip.GzipHandler.etag");
String requestEtags = (String)_channel.getRequest().getAttribute(GzipHandler.GZIP_HANDLER_ETAGS);
String responseEtag = response.getHttpFields().get(HttpHeader.ETAG);
if (requestEtags != null && responseEtag != null)
{
@ -200,7 +201,7 @@ public class GzipHttpOutputInterceptor implements HttpOutput.Interceptor
return;
}
fields.put(GZIP._contentEncoding);
fields.put(GZIP.getContentEncoding());
_crc.reset();
// Adjust headers
@ -228,8 +229,7 @@ public class GzipHttpOutputInterceptor implements HttpOutput.Interceptor
private String etagGzip(String etag)
{
int end = etag.length() - 1;
return (etag.charAt(end) == '"') ? etag.substring(0, end) + GZIP._etag + '"' : etag + GZIP._etag;
return GZIP.etag(etag);
}
public void noCompression()

View File

@ -83,7 +83,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" + CompressedContentFormat.GZIP._etag + "\"", __content.hashCode());
private static final String __contentETagGzip = String.format("W/\"%x" + CompressedContentFormat.GZIP.getEtagSuffix() + "\"", __content.hashCode());
private static final String __icontent = "BEFORE" + __content + "AFTER";
private Server _server;
@ -586,7 +586,7 @@ public class GzipHandlerTest
request.setURI("/ctx/content");
request.setVersion("HTTP/1.0");
request.setHeader("Host", "tester");
request.setHeader("If-Match", "WrongEtag" + CompressedContentFormat.GZIP._etag);
request.setHeader("If-Match", "WrongEtag" + CompressedContentFormat.GZIP.getEtagSuffix());
request.setHeader("accept-encoding", "gzip");
response = HttpTester.parseResponse(_connector.getResponse(request.generate()));

View File

@ -118,7 +118,7 @@ public class GzipDefaultServletTest extends AbstractGzipTest
// Response Content-Encoding check
assertThat("Response[Content-Encoding]", response.get("Content-Encoding"), containsString("gzip"));
assertThat("Response[ETag]", response.get("ETag"), startsWith("W/"));
assertThat("Response[ETag]", response.get("ETag"), containsString(CompressedContentFormat.GZIP._etag));
assertThat("Response[ETag]", response.get("ETag"), containsString(CompressedContentFormat.GZIP.getEtagSuffix()));
assertThat("Response[Content-Length]", response.get("Content-Length"), is(nullValue()));
// A HEAD request should have similar headers, but no body
@ -320,7 +320,7 @@ public class GzipDefaultServletTest extends AbstractGzipTest
// Response Content-Encoding check
assertThat("Response[Content-Encoding]", response.get("Content-Encoding"), containsString("gzip"));
assertThat("Response[ETag]", response.get("ETag"), startsWith("W/"));
assertThat("Response[ETag]", response.get("ETag"), containsString(CompressedContentFormat.GZIP._etag));
assertThat("Response[ETag]", response.get("ETag"), containsString(CompressedContentFormat.GZIP.getEtagSuffix()));
assertThat("Response[Vary]", response.get("Vary"), containsString("Accept-Encoding"));
// Response Content checks
@ -439,7 +439,7 @@ public class GzipDefaultServletTest extends AbstractGzipTest
// Response Content-Encoding check
assertThat("Response[Content-Encoding]", response.get("Content-Encoding"), not(containsString("gzip")));
assertThat("Response[ETag]", response.get("ETag"), startsWith("W/"));
assertThat("Response[ETag]", response.get("ETag"), not(containsString(CompressedContentFormat.GZIP._etag)));
assertThat("Response[ETag]", response.get("ETag"), not(containsString(CompressedContentFormat.GZIP.getEtagSuffix())));
// Response Content checks
UncompressedMetadata metadata = parseResponseContent(response);