Merge branch 'master' into jetty-9.4.x-Feature
This commit is contained in:
commit
22d2b251e9
35
VERSION.txt
35
VERSION.txt
|
@ -1,5 +1,40 @@
|
|||
jetty-9.4.0-SNAPSHOT
|
||||
|
||||
jetty-9.3.9.M1 - 11 April 2016
|
||||
+ 481 Event response.success notified without waiting for content callback for
|
||||
HTTP/2 transport
|
||||
+ 490 serverClasses set from jetty-web.xml
|
||||
+ 491 Do not assume gzip acceptable for HTTP/2
|
||||
+ 503 Wrong request-per-connection counting in MultiplexHttpDestination in
|
||||
case of failures
|
||||
+ 504 HTTP/2 client transport cannot send request after idle timeout
|
||||
|
||||
jetty-9.3.9.M0 - 05 April 2016
|
||||
+ 184 Empty Realm for BasicAuthentication
|
||||
+ 371 update apache jsp to 8.0.27
|
||||
+ 418 Add osgi capability for endpoint configurator
|
||||
+ 424 Jetty impl. of Websocket ServerEndpointConfig.Configurator lifecycle out
|
||||
of spec
|
||||
+ 427 Squelch intentional exceptions seen during websocket testing
|
||||
+ 434 RequestTest stack traces
|
||||
+ 435 adjust debug log message
|
||||
+ 437 Avoid NPE on receiving empty message though MessageHandler.Partial
|
||||
+ 438 File and Path Resources with control characters should be rejected
|
||||
+ 446 jetty-quickstart path normalization uses improper paths on Windows
|
||||
+ 448 RFC2616 Compliance Mode should track and report RFC7230 violations
|
||||
+ 450 Client AuthenticationProtocolHandler sends request failures to response
|
||||
failure listener
|
||||
+ 451 RFC2616 Compliance mode should support empty headers
|
||||
+ 453 Change logging of setting session maxInactiveInterval to DEBUG from WARN
|
||||
+ 454 DoSFilter does not send an error status code when closing a connection,
|
||||
because of timeout
|
||||
+ 458 Improve Quality list handling
|
||||
+ 467 Compact // rule
|
||||
+ 469 Update to Apache Jasper 8.0.33
|
||||
+ 470 AsyncContextState NPE if called after reset
|
||||
+ 472 Use LongAdder for statistics
|
||||
+ 476 HttpClient should not send absolute-form target with non HttpProxy
|
||||
|
||||
jetty-9.3.8.v20160314 - 14 March 2016
|
||||
+ 107 ResourceHandler range support testcase
|
||||
+ 124 Don't produce text/html if the request doesn't accept it
|
||||
|
|
|
@ -146,17 +146,16 @@ public class HttpConnectionOverHTTP extends AbstractConnection implements Connec
|
|||
{
|
||||
if (closed.compareAndSet(false, true))
|
||||
{
|
||||
// First close then abort, to be sure that the connection cannot be reused
|
||||
// from an onFailure() handler or by blocking code waiting for completion.
|
||||
getHttpDestination().close(this);
|
||||
|
||||
abort(failure);
|
||||
|
||||
getEndPoint().shutdownOutput();
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Shutdown {}", this);
|
||||
getEndPoint().close();
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Closed {}", this);
|
||||
|
||||
abort(failure);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -32,9 +32,11 @@ import org.junit.After;
|
|||
import org.junit.Assert;
|
||||
import org.junit.Assume;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
@Ignore
|
||||
public class ExternalSiteTest
|
||||
{
|
||||
@Rule
|
||||
|
|
|
@ -223,17 +223,16 @@ public class HttpConnectionOverFCGI extends AbstractConnection implements Connec
|
|||
{
|
||||
if (closed.compareAndSet(false, true))
|
||||
{
|
||||
// First close then abort, to be sure that the connection cannot be reused
|
||||
// from an onFailure() handler or by blocking code waiting for completion.
|
||||
getHttpDestination().close(this);
|
||||
|
||||
abort(failure);
|
||||
|
||||
getEndPoint().shutdownOutput();
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Shutdown {}", this);
|
||||
getEndPoint().close();
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Closed {}", this);
|
||||
|
||||
abort(failure);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ package org.eclipse.jetty.http2.client.http;
|
|||
|
||||
import java.nio.channels.AsynchronousCloseException;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
|
@ -77,6 +78,15 @@ public class HttpConnectionOverHTTP2 extends HttpConnection implements Sweeper.S
|
|||
getHttpDestination().release(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onIdleTimeout(long idleTimeout)
|
||||
{
|
||||
boolean close = super.onIdleTimeout(idleTimeout);
|
||||
if (close)
|
||||
close(new TimeoutException("idle_timeout"));
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isClosed()
|
||||
{
|
||||
return closed.get();
|
||||
|
@ -92,11 +102,11 @@ public class HttpConnectionOverHTTP2 extends HttpConnection implements Sweeper.S
|
|||
{
|
||||
if (closed.compareAndSet(false, true))
|
||||
{
|
||||
// First close then abort, to be sure that the connection cannot be reused
|
||||
// from an onFailure() handler or by blocking code waiting for completion.
|
||||
getHttpDestination().close(this);
|
||||
session.close(ErrorCode.NO_ERROR.code, failure.getMessage(), Callback.NOOP);
|
||||
|
||||
abort(failure);
|
||||
|
||||
session.close(ErrorCode.NO_ERROR.code, failure.getMessage(), Callback.NOOP);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ import org.eclipse.jetty.http2.frames.ResetFrame;
|
|||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
import org.eclipse.jetty.util.CompletableCallback;
|
||||
|
||||
public class HttpReceiverOverHTTP2 extends HttpReceiver implements Stream.Listener
|
||||
{
|
||||
|
@ -110,26 +111,40 @@ public class HttpReceiverOverHTTP2 extends HttpReceiver implements Stream.Listen
|
|||
copy.put(original);
|
||||
BufferUtil.flipToFlush(copy, 0);
|
||||
|
||||
Callback delegate = new Callback.Nested(callback)
|
||||
CompletableCallback delegate = new CompletableCallback()
|
||||
{
|
||||
@Override
|
||||
public void succeeded()
|
||||
{
|
||||
byteBufferPool.release(copy);
|
||||
callback.succeeded();
|
||||
super.succeeded();
|
||||
if (frame.isEndStream())
|
||||
responseSuccess(exchange);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void failed(Throwable x)
|
||||
{
|
||||
byteBufferPool.release(copy);
|
||||
callback.failed(x);
|
||||
super.failed(x);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resume()
|
||||
{
|
||||
if (frame.isEndStream())
|
||||
responseSuccess(exchange);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void abort(Throwable failure)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
responseContent(exchange, copy, delegate);
|
||||
if (!delegate.tryComplete())
|
||||
delegate.resume();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -313,6 +313,83 @@ public class HttpClientTransportOverHTTP2Test extends AbstractTest
|
|||
Assert.assertEquals(HttpStatus.OK_200, response.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConnectionIdleTimeoutSendsResetFrame() throws Exception
|
||||
{
|
||||
long idleTimeout = 1000;
|
||||
|
||||
CountDownLatch resetLatch = new CountDownLatch(1);
|
||||
start(new ServerSessionListener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public Stream.Listener onNewStream(Stream stream, HeadersFrame frame)
|
||||
{
|
||||
return new Stream.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onReset(Stream stream, ResetFrame frame)
|
||||
{
|
||||
resetLatch.countDown();
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
client.stop();
|
||||
client.setIdleTimeout(idleTimeout);
|
||||
client.start();
|
||||
|
||||
try
|
||||
{
|
||||
client.newRequest("localhost", connector.getLocalPort())
|
||||
// Make sure the connection idle times out, not the stream.
|
||||
.idleTimeout(2 * idleTimeout, TimeUnit.MILLISECONDS)
|
||||
.send();
|
||||
Assert.fail();
|
||||
}
|
||||
catch (ExecutionException e)
|
||||
{
|
||||
// Expected.
|
||||
}
|
||||
|
||||
Assert.assertTrue(resetLatch.await(5, TimeUnit.SECONDS));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRequestIdleTimeoutSendsResetFrame() throws Exception
|
||||
{
|
||||
CountDownLatch resetLatch = new CountDownLatch(1);
|
||||
start(new ServerSessionListener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public Stream.Listener onNewStream(Stream stream, HeadersFrame frame)
|
||||
{
|
||||
return new Stream.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onReset(Stream stream, ResetFrame frame)
|
||||
{
|
||||
resetLatch.countDown();
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
try
|
||||
{
|
||||
long idleTimeout = 1000;
|
||||
client.newRequest("localhost", connector.getLocalPort())
|
||||
.idleTimeout(idleTimeout, TimeUnit.MILLISECONDS)
|
||||
.send();
|
||||
Assert.fail();
|
||||
}
|
||||
catch (ExecutionException e)
|
||||
{
|
||||
// Expected.
|
||||
}
|
||||
|
||||
Assert.assertTrue(resetLatch.await(5, TimeUnit.SECONDS));
|
||||
}
|
||||
|
||||
@Ignore
|
||||
@Test
|
||||
public void testExternalServer() throws Exception
|
||||
|
|
|
@ -18,8 +18,6 @@
|
|||
|
||||
package org.eclipse.jetty.start;
|
||||
|
||||
import static org.eclipse.jetty.start.UsageException.ERR_BAD_ARG;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
|
@ -34,6 +32,8 @@ import java.util.regex.Pattern;
|
|||
|
||||
import org.eclipse.jetty.start.Props.Prop;
|
||||
|
||||
import static org.eclipse.jetty.start.UsageException.ERR_BAD_ARG;
|
||||
|
||||
/**
|
||||
* Management of Properties.
|
||||
* <p>
|
||||
|
@ -227,8 +227,6 @@ public final class Props implements Iterable<Prop>
|
|||
throw new PropsException(err.toString());
|
||||
}
|
||||
|
||||
seenStack.push(property);
|
||||
|
||||
// find property name
|
||||
expanded.append(str.subSequence(offset,mat.start()));
|
||||
// get property value
|
||||
|
@ -241,7 +239,9 @@ public final class Props implements Iterable<Prop>
|
|||
else
|
||||
{
|
||||
// recursively expand
|
||||
seenStack.push(property);
|
||||
value = expand(value,seenStack);
|
||||
seenStack.pop();
|
||||
expanded.append(value);
|
||||
}
|
||||
// update offset
|
||||
|
|
|
@ -18,15 +18,18 @@
|
|||
|
||||
package org.eclipse.jetty.start;
|
||||
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.fail;
|
||||
import org.eclipse.jetty.start.Props.Prop;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import org.eclipse.jetty.start.Props.Prop;
|
||||
import org.junit.Test;
|
||||
|
||||
public class PropsTest
|
||||
{
|
||||
private static final String FROM_TEST = "(test)";
|
||||
|
@ -121,6 +124,17 @@ public class PropsTest
|
|||
assertThat(props.expand("server-id=corporate-${id}"),is("server-id=corporate-jetty-9.1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpandDouble()
|
||||
{
|
||||
Props props = new Props();
|
||||
props.setProperty("bar","apple",FROM_TEST);
|
||||
props.setProperty("foo","foo/${bar}/${bar}-xx",FROM_TEST);
|
||||
|
||||
// Should expand
|
||||
assertThat(props.expand("foo/${bar}/${bar}-xx"),is("foo/apple/apple-xx"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpandLoop()
|
||||
{
|
||||
|
|
|
@ -52,8 +52,11 @@ public class HttpClientIdleTimeoutTest extends AbstractTest
|
|||
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||
{
|
||||
baseRequest.setHandled(true);
|
||||
AsyncContext asyncContext = request.startAsync();
|
||||
asyncContext.setTimeout(0);
|
||||
if (target.equals("/timeout"))
|
||||
{
|
||||
AsyncContext asyncContext = request.startAsync();
|
||||
asyncContext.setTimeout(0);
|
||||
}
|
||||
}
|
||||
});
|
||||
client.stop();
|
||||
|
@ -61,13 +64,19 @@ public class HttpClientIdleTimeoutTest extends AbstractTest
|
|||
client.start();
|
||||
|
||||
final CountDownLatch latch = new CountDownLatch(1);
|
||||
client.newRequest(newURI()).send(result ->
|
||||
{
|
||||
if (result.isFailed())
|
||||
latch.countDown();
|
||||
});
|
||||
client.newRequest(newURI())
|
||||
.path("/timeout")
|
||||
.send(result ->
|
||||
{
|
||||
if (result.isFailed())
|
||||
latch.countDown();
|
||||
});
|
||||
|
||||
Assert.assertTrue(latch.await(2 * idleTimeout, TimeUnit.MILLISECONDS));
|
||||
|
||||
// Verify that after the timeout we can make another request.
|
||||
ContentResponse response = client.newRequest(newURI()).send();
|
||||
Assert.assertEquals(HttpStatus.OK_200, response.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -79,13 +88,17 @@ public class HttpClientIdleTimeoutTest extends AbstractTest
|
|||
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||
{
|
||||
baseRequest.setHandled(true);
|
||||
AsyncContext asyncContext = request.startAsync();
|
||||
asyncContext.setTimeout(0);
|
||||
if (target.equals("/timeout"))
|
||||
{
|
||||
AsyncContext asyncContext = request.startAsync();
|
||||
asyncContext.setTimeout(0);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
final CountDownLatch latch = new CountDownLatch(1);
|
||||
client.newRequest(newURI())
|
||||
.path("/timeout")
|
||||
.idleTimeout(idleTimeout, TimeUnit.MILLISECONDS)
|
||||
.send(result ->
|
||||
{
|
||||
|
@ -94,10 +107,41 @@ public class HttpClientIdleTimeoutTest extends AbstractTest
|
|||
});
|
||||
|
||||
Assert.assertTrue(latch.await(2 * idleTimeout, TimeUnit.MILLISECONDS));
|
||||
|
||||
// Verify that after the timeout we can make another request.
|
||||
ContentResponse response = client.newRequest(newURI()).send();
|
||||
Assert.assertEquals(HttpStatus.OK_200, response.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testServerIdleTimeout() throws Exception
|
||||
public void testIdleClientIdleTimeout() throws Exception
|
||||
{
|
||||
start(new AbstractHandler()
|
||||
{
|
||||
@Override
|
||||
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||
{
|
||||
baseRequest.setHandled(true);
|
||||
}
|
||||
});
|
||||
client.stop();
|
||||
client.setIdleTimeout(idleTimeout);
|
||||
client.start();
|
||||
|
||||
// Make a first request to open a connection.
|
||||
ContentResponse response = client.newRequest(newURI()).send();
|
||||
Assert.assertEquals(HttpStatus.OK_200, response.getStatus());
|
||||
|
||||
// Let the connection idle timeout.
|
||||
Thread.sleep(2 * idleTimeout);
|
||||
|
||||
// Verify that after the timeout we can make another request.
|
||||
response = client.newRequest(newURI()).send();
|
||||
Assert.assertEquals(HttpStatus.OK_200, response.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIdleServerIdleTimeout() throws Exception
|
||||
{
|
||||
start(new AbstractHandler()
|
||||
{
|
||||
|
|
|
@ -408,6 +408,8 @@ public class HttpClientTest extends AbstractTest
|
|||
|
||||
InputStream input = listener.getInputStream();
|
||||
Assert.assertEquals(content, IO.toString(input));
|
||||
|
||||
Assert.assertTrue(latch.await(5, TimeUnit.SECONDS));
|
||||
}
|
||||
|
||||
private void sleep(long time) throws IOException
|
||||
|
|
Loading…
Reference in New Issue