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

This commit is contained in:
Jan Bartel 2020-06-01 14:47:07 +02:00
commit 42155e889b
7 changed files with 109 additions and 19 deletions

View File

@ -304,11 +304,11 @@ public class HpackEncoder
String encoding = null; String encoding = null;
// Is there an entry for the field? // Is there an index entry for the field?
Entry entry = _context.get(field); Entry entry = _context.get(field);
if (entry != null) if (entry != null)
{ {
// Known field entry, so encode it as indexed // This is a known indexed field, send as static or dynamic indexed.
if (entry.isStatic()) if (entry.isStatic())
{ {
buffer.put(((StaticEntry)entry).getEncodedField()); buffer.put(((StaticEntry)entry).getEncodedField());
@ -326,10 +326,10 @@ public class HpackEncoder
} }
else else
{ {
// Unknown field entry, so we will have to send literally. // Unknown field entry, so we will have to send literally, but perhaps add an index.
final boolean indexed; final boolean indexed;
// But do we know it's name? // Do we know its name?
HttpHeader header = field.getHeader(); HttpHeader header = field.getHeader();
// Select encoding strategy // Select encoding strategy
@ -347,12 +347,11 @@ public class HpackEncoder
if (_debug) if (_debug)
encoding = indexed ? "PreEncodedIdx" : "PreEncoded"; encoding = indexed ? "PreEncodedIdx" : "PreEncoded";
} }
// has the custom header name been seen before? else if (name == null && fieldSize < _context.getMaxDynamicTableSize())
else if (name == null)
{ {
// unknown name and value, so let's index this just in case it is // unknown name and value that will fit in dynamic table, so let's index
// the first time we have seen a custom name or a custom field. // this just in case it is the first time we have seen a custom name or a
// unless the name is changing, this is worthwhile // custom field. Unless the name is once only, this is worthwhile
indexed = true; indexed = true;
encodeName(buffer, (byte)0x40, 6, field.getName(), null); encodeName(buffer, (byte)0x40, 6, field.getName(), null);
encodeValue(buffer, true, field.getValue()); encodeValue(buffer, true, field.getValue());
@ -361,7 +360,7 @@ public class HpackEncoder
} }
else else
{ {
// known custom name, but unknown value. // Known name, but different value.
// This is probably a custom field with changing value, so don't index. // This is probably a custom field with changing value, so don't index.
indexed = false; indexed = false;
encodeName(buffer, (byte)0x00, 4, field.getName(), null); encodeName(buffer, (byte)0x00, 4, field.getName(), null);
@ -400,9 +399,9 @@ public class HpackEncoder
(huffman ? "HuffV" : "LitV") + (huffman ? "HuffV" : "LitV") +
(neverIndex ? "!!Idx" : "!Idx"); (neverIndex ? "!!Idx" : "!Idx");
} }
else if (fieldSize >= _context.getMaxDynamicTableSize() || header == HttpHeader.CONTENT_LENGTH && field.getValue().length() > 2) else if (fieldSize >= _context.getMaxDynamicTableSize() || header == HttpHeader.CONTENT_LENGTH && !"0".equals(field.getValue()))
{ {
// Non indexed if field too large or a content length for 3 digits or more // The field is too large or a non zero content length, so do not index.
indexed = false; indexed = false;
encodeName(buffer, (byte)0x00, 4, header.asString(), name); encodeName(buffer, (byte)0x00, 4, header.asString(), name);
encodeValue(buffer, true, field.getValue()); encodeValue(buffer, true, field.getValue());

View File

@ -22,6 +22,7 @@ import java.nio.ByteBuffer;
import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.http.MetaData; import org.eclipse.jetty.http.MetaData;
import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.BufferUtil;
@ -145,6 +146,54 @@ public class HpackEncoderTest
assertEquals(5, encoder.getHpackContext().size()); assertEquals(5, encoder.getHpackContext().size());
} }
@Test
public void testLargeFieldsNotIndexed()
{
HpackEncoder encoder = new HpackEncoder(38 * 5);
HpackContext ctx = encoder.getHpackContext();
ByteBuffer buffer = BufferUtil.allocate(4096);
// Index little fields
int pos = BufferUtil.flipToFill(buffer);
encoder.encode(buffer, new HttpField("Name", "Value"));
BufferUtil.flipToFlush(buffer, pos);
int dynamicTableSize = ctx.getDynamicTableSize();
assertThat(dynamicTableSize, Matchers.greaterThan(0));
// Do not index big field
StringBuilder largeName = new StringBuilder("largeName-");
String filler = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
while (largeName.length() < ctx.getMaxDynamicTableSize())
largeName.append(filler, 0, Math.min(filler.length(), ctx.getMaxDynamicTableSize() - largeName.length()));
pos = BufferUtil.flipToFill(buffer);
encoder.encode(buffer, new HttpField(largeName.toString(), "Value"));
BufferUtil.flipToFlush(buffer, pos);
assertThat(ctx.getDynamicTableSize(), Matchers.is(dynamicTableSize));
}
@Test
public void testIndexContentLength()
{
HpackEncoder encoder = new HpackEncoder(38 * 5);
HpackContext ctx = encoder.getHpackContext();
ByteBuffer buffer = BufferUtil.allocate(4096);
// Index zero content length
int pos = BufferUtil.flipToFill(buffer);
encoder.encode(buffer, new HttpField(HttpHeader.CONTENT_LENGTH, "0"));
BufferUtil.flipToFlush(buffer, pos);
int dynamicTableSize = ctx.getDynamicTableSize();
assertThat(dynamicTableSize, Matchers.greaterThan(0));
// Do not index non zero content length
pos = BufferUtil.flipToFill(buffer);
encoder.encode(buffer, new HttpField(HttpHeader.CONTENT_LENGTH, "42"));
BufferUtil.flipToFlush(buffer, pos);
assertThat(ctx.getDynamicTableSize(), Matchers.is(dynamicTableSize));
}
@Test @Test
public void testNeverIndexSetCookie() throws Exception public void testNeverIndexSetCookie() throws Exception
{ {

View File

@ -34,21 +34,31 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
*/ */
public class FooContextListener implements ServletContextListener public class FooContextListener implements ServletContextListener
{ {
static int ___initialized;
static int __destroyed;
@Override @Override
public void contextInitialized(ServletContextEvent sce) public void contextInitialized(ServletContextEvent sce)
{ {
++___initialized;
ServletRegistration defaultRego = sce.getServletContext().getServletRegistration("default"); ServletRegistration defaultRego = sce.getServletContext().getServletRegistration("default");
Collection<String> mappings = defaultRego.getMappings(); Collection<String> mappings = defaultRego.getMappings();
assertThat("/", is(in(mappings))); assertThat("/", is(in(mappings)));
Set<String> otherMappings = sce.getServletContext().getServletRegistration("foo").addMapping("/"); ServletRegistration rego = sce.getServletContext().getServletRegistration("foo");
assertTrue(otherMappings.isEmpty()); if (rego != null)
Collection<String> fooMappings = sce.getServletContext().getServletRegistration("foo").getMappings(); {
assertThat("/", is(in(fooMappings))); Set<String> otherMappings = rego.addMapping("/");
assertTrue(otherMappings.isEmpty());
Collection<String> fooMappings = rego.getMappings();
assertThat("/", is(in(fooMappings)));
}
} }
@Override @Override
public void contextDestroyed(ServletContextEvent sce) public void contextDestroyed(ServletContextEvent sce)
{ {
++__destroyed;
} }
} }

View File

@ -79,7 +79,7 @@ public class TestQuickStart
fooHolder.setName("foo"); fooHolder.setName("foo");
quickstart.getServletHandler().addServlet(fooHolder); quickstart.getServletHandler().addServlet(fooHolder);
ListenerHolder lholder = new ListenerHolder(); ListenerHolder lholder = new ListenerHolder();
lholder.setListener(new FooContextListener()); lholder.setClassName("org.eclipse.jetty.quickstart.FooContextListener");
quickstart.getServletHandler().addListener(lholder); quickstart.getServletHandler().addListener(lholder);
server.setHandler(quickstart); server.setHandler(quickstart);
server.setDryRun(true); server.setDryRun(true);
@ -177,4 +177,30 @@ public class TestQuickStart
assertEquals("ascii", webapp.getDefaultRequestCharacterEncoding()); assertEquals("ascii", webapp.getDefaultRequestCharacterEncoding());
assertEquals("utf-16", webapp.getDefaultResponseCharacterEncoding()); assertEquals("utf-16", webapp.getDefaultResponseCharacterEncoding());
} }
@Test
public void testListenersNotCalledInPreConfigure() throws Exception
{
File quickstartXml = new File(webInf, "quickstart-web.xml");
assertFalse(quickstartXml.exists());
Server server = new Server();
WebAppContext quickstart = new WebAppContext();
quickstart.addConfiguration(new QuickStartConfiguration());
quickstart.setAttribute(QuickStartConfiguration.MODE, QuickStartConfiguration.Mode.GENERATE);
quickstart.setAttribute(QuickStartConfiguration.ORIGIN_ATTRIBUTE, "origin");
//add a listener directly to the ContextHandler so it is there when we start -
//if you add them to the ServletHandler (like StandardDescriptorProcessor does)
//then they are not added to the ContextHandler in a pre-generate.
quickstart.addEventListener(new FooContextListener());
quickstart.setResourceBase(testDir.getAbsolutePath());
server.setHandler(quickstart);
server.setDryRun(true);
server.start();
assertTrue(quickstartXml.exists());
assertEquals(0, FooContextListener.___initialized);
}
} }

View File

@ -956,6 +956,9 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
protected void callContextInitialized(ServletContextListener l, ServletContextEvent e) protected void callContextInitialized(ServletContextListener l, ServletContextEvent e)
{ {
if (getServer().isDryRun())
return;
if (LOG.isDebugEnabled()) if (LOG.isDebugEnabled())
LOG.debug("contextInitialized: {}->{}", e, l); LOG.debug("contextInitialized: {}->{}", e, l);
l.contextInitialized(e); l.contextInitialized(e);
@ -963,6 +966,9 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
protected void callContextDestroyed(ServletContextListener l, ServletContextEvent e) protected void callContextDestroyed(ServletContextListener l, ServletContextEvent e)
{ {
if (getServer().isDryRun())
return;
if (LOG.isDebugEnabled()) if (LOG.isDebugEnabled())
LOG.debug("contextDestroyed: {}->{}", e, l); LOG.debug("contextDestroyed: {}->{}", e, l);
l.contextDestroyed(e); l.contextDestroyed(e);

View File

@ -1287,7 +1287,7 @@
<execution> <execution>
<id>attach-sources</id> <id>attach-sources</id>
<goals> <goals>
<goal>jar</goal> <goal>jar-no-fork</goal>
</goals> </goals>
</execution> </execution>
</executions> </executions>

View File

@ -167,7 +167,7 @@ if proceedyn "Are you sure you want to release using above? (y/N)" n; then
# This is equivalent to 'mvn release:perform' # This is equivalent to 'mvn release:perform'
if proceedyn "Build/Deploy from tag $TAG_NAME? (Y/n)" y; then if proceedyn "Build/Deploy from tag $TAG_NAME? (Y/n)" y; then
git checkout $TAG_NAME git checkout $TAG_NAME
mvn clean package source:jar javadoc:jar gpg:sign javadoc:aggregate-jar deploy \ mvn clean package javadoc:aggregate-jar deploy \
-Peclipse-release $DEPLOY_OPTS -Peclipse-release $DEPLOY_OPTS
reportMavenTestFailures reportMavenTestFailures
git checkout $GIT_BRANCH_ID git checkout $GIT_BRANCH_ID