Merge branch 'SPDY_ff_fixes'

This commit is contained in:
Thomas Becker 2012-11-28 17:44:22 +01:00
commit 33e951d44a
6 changed files with 172 additions and 146 deletions

View File

@ -1060,15 +1060,19 @@ public class StandardSession implements ISession, Parser.Listener, Dumpable
execute(new Runnable()
{
@Override
public void run() { callback.succeeded() ; }
public void run()
{
callback.succeeded();
flush();
}
});
}
@Override
public void call(Callback callback)
{
callback.succeeded();
flush();
}
}

View File

@ -22,6 +22,8 @@ import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpGenerator;
@ -32,10 +34,12 @@ import org.eclipse.jetty.io.EofException;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.HttpTransport;
import org.eclipse.jetty.spdy.StreamException;
import org.eclipse.jetty.spdy.api.ByteBufferDataInfo;
import org.eclipse.jetty.spdy.api.ReplyInfo;
import org.eclipse.jetty.spdy.api.SPDY;
import org.eclipse.jetty.spdy.api.Stream;
import org.eclipse.jetty.spdy.api.StreamStatus;
import org.eclipse.jetty.spdy.api.SynInfo;
import org.eclipse.jetty.util.BlockingCallback;
import org.eclipse.jetty.util.BufferUtil;
@ -56,6 +60,7 @@ public class HttpTransportOverSPDY implements HttpTransport
private final Stream stream;
private final Fields requestHeaders;
private final BlockingCallback streamBlocker = new BlockingCallback();
private final AtomicBoolean committed = new AtomicBoolean();
public HttpTransportOverSPDY(Connector connector, HttpConfiguration configuration, EndPoint endPoint, PushStrategy pushStrategy, Stream stream, Fields requestHeaders)
{
@ -71,9 +76,9 @@ public class HttpTransportOverSPDY implements HttpTransport
public void send(HttpGenerator.ResponseInfo info, ByteBuffer content, boolean lastContent, Callback callback)
{
if (LOG.isDebugEnabled())
LOG.debug("send {} {} {} {} last={}%n",this,stream,info,BufferUtil.toDetailString(content),lastContent);
LOG.debug("send {} {} {} {} last={}",this,stream,info,BufferUtil.toDetailString(content),lastContent);
if (stream.isClosed() || stream.isReset() )
if (stream.isClosed() || stream.isReset())
{
callback.failed(new EofException("stream closed"));
return;
@ -93,6 +98,11 @@ public class HttpTransportOverSPDY implements HttpTransport
if (info!=null)
{
if(!committed.compareAndSet(false, true)){
callback.failed(new StreamException(stream.getId(), StreamStatus.PROTOCOL_ERROR,
"Stream already committed!"));
return;
}
short version = stream.getSession().getVersion();
Fields headers = new Fields();
@ -157,20 +167,16 @@ public class HttpTransportOverSPDY implements HttpTransport
}
@Override
public void send(HttpGenerator.ResponseInfo info, ByteBuffer content, boolean lastContent) throws IOException
public void send(HttpGenerator.ResponseInfo info, ByteBuffer content, boolean lastContent) throws EofException
{
send(info,content,lastContent,streamBlocker);
try
{
streamBlocker.block();
}
catch (IOException e)
catch (InterruptedException | TimeoutException | IOException e)
{
throw e;
}
catch (Exception e)
{
throw new EofException(e);
LOG.debug(e);
}
}

View File

@ -48,6 +48,8 @@ public class ConcurrentStreamsTest extends AbstractHTTPSPDYTest
{
final CountDownLatch slowServerLatch = new CountDownLatch(1);
final CountDownLatch fastServerLatch = new CountDownLatch(1);
final String fastPath = "/fast";
final String slowPath = "/slow";
Session session = startClient(version, startHTTPServer(version, new AbstractHandler()
{
@Override
@ -59,11 +61,11 @@ public class ConcurrentStreamsTest extends AbstractHTTPSPDYTest
request.setHandled(true);
switch (target)
{
case "/slow":
case slowPath:
Assert.assertTrue(fastServerLatch.await(10, TimeUnit.SECONDS));
slowServerLatch.countDown();
break;
case "/fast":
case fastPath:
fastServerLatch.countDown();
break;
default:
@ -79,11 +81,7 @@ public class ConcurrentStreamsTest extends AbstractHTTPSPDYTest
}), null);
// Perform slow request. This will wait on server side until the fast request wakes it up
Fields headers = new Fields();
headers.put(HTTPSPDYHeader.METHOD.name(version), "GET");
headers.put(HTTPSPDYHeader.URI.name(version), "/slow");
headers.put(HTTPSPDYHeader.VERSION.name(version), "HTTP/1.1");
headers.put(HTTPSPDYHeader.HOST.name(version), "localhost:" + connector.getLocalPort());
Fields headers = createHeaders(slowPath);
final CountDownLatch slowClientLatch = new CountDownLatch(1);
session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
{
@ -97,11 +95,7 @@ public class ConcurrentStreamsTest extends AbstractHTTPSPDYTest
});
// Perform the fast request. This will wake up the slow request
headers.clear();
headers.put(HTTPSPDYHeader.METHOD.name(version), "GET");
headers.put(HTTPSPDYHeader.URI.name(version), "/fast");
headers.put(HTTPSPDYHeader.VERSION.name(version), "HTTP/1.1");
headers.put(HTTPSPDYHeader.HOST.name(version), "localhost:" + connector.getLocalPort());
headers = createHeaders(fastPath);
final CountDownLatch fastClientLatch = new CountDownLatch(1);
session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
{
@ -119,4 +113,14 @@ public class ConcurrentStreamsTest extends AbstractHTTPSPDYTest
Assert.assertTrue(fastClientLatch.await(5, TimeUnit.SECONDS));
Assert.assertTrue(slowClientLatch.await(5, TimeUnit.SECONDS));
}
private Fields createHeaders(String path)
{
Fields headers = new Fields();
headers.put(HTTPSPDYHeader.METHOD.name(version), "GET");
headers.put(HTTPSPDYHeader.URI.name(version), path);
headers.put(HTTPSPDYHeader.VERSION.name(version), "HTTP/1.1");
headers.put(HTTPSPDYHeader.HOST.name(version), "localhost:" + connector.getLocalPort());
return headers;
}
}

View File

@ -18,15 +18,18 @@
package org.eclipse.jetty.spdy.server.http;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.http.HttpGenerator;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.spdy.api.ByteBufferDataInfo;
import org.eclipse.jetty.spdy.api.DataInfo;
import org.eclipse.jetty.spdy.api.ReplyInfo;
import org.eclipse.jetty.spdy.api.SPDY;
import org.eclipse.jetty.spdy.api.Session;
@ -45,7 +48,6 @@ import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.anyObject;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@ -79,6 +81,7 @@ public class HttpTransportOverSPDYTest
{
httpTransportOverSPDY = new HttpTransportOverSPDY(connector, httpConfiguration, endPoint, pushStrategy,
stream, new Fields());
when(responseInfo.getStatus()).thenReturn(HttpStatus.OK_200);
when(stream.getSession()).thenReturn(session);
when(session.getVersion()).thenReturn(SPDY.V3);
when(stream.isClosed()).thenReturn(false);
@ -169,7 +172,7 @@ public class HttpTransportOverSPDYTest
ByteBuffer content = null;
boolean lastContent = true;
// when stream.isClosed() is called a 2nd time, the teply has closed the stream already
// when stream.isClosed() is called a 2nd time, the reply has closed the stream already
when(stream.isClosed()).thenReturn(false).thenReturn(true);
httpTransportOverSPDY.send(responseInfo, content, lastContent, callback);
@ -234,6 +237,23 @@ public class HttpTransportOverSPDYTest
assertThat("ByteBuffer length is 4096", dataInfoCaptor.getValue().length(), is(4096));
}
@Test
public void testVerifyThatAStreamIsNotCommittedTwice() throws IOException
{
ByteBuffer content = createRandomByteBuffer();
boolean lastContent = false;
httpTransportOverSPDY.send(responseInfo,content,lastContent, callback);
ArgumentCaptor<ReplyInfo> replyInfoCaptor = ArgumentCaptor.forClass(ReplyInfo.class);
verify(stream, times(1)).reply(replyInfoCaptor.capture());
assertThat("ReplyInfo close is false", replyInfoCaptor.getValue().isClose(), is(false));
httpTransportOverSPDY.send(HttpGenerator.RESPONSE_500_INFO, null,true);
verify(stream, times(0)).data(any(DataInfo.class));
verify(stream, times(1)).data(any(DataInfo.class), anyLong(), any(TimeUnit.class), any(Callback.class));
}
private ByteBuffer createRandomByteBuffer()
{
ByteBuffer content = BufferUtil.allocate(8192);

View File

@ -34,11 +34,13 @@ import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.spdy.api.DataInfo;
import org.eclipse.jetty.spdy.api.ReplyInfo;
import org.eclipse.jetty.spdy.api.RstInfo;
import org.eclipse.jetty.spdy.api.SPDY;
import org.eclipse.jetty.spdy.api.Session;
import org.eclipse.jetty.spdy.api.SessionFrameListener;
import org.eclipse.jetty.spdy.api.Stream;
import org.eclipse.jetty.spdy.api.StreamFrameListener;
import org.eclipse.jetty.spdy.api.StreamStatus;
import org.eclipse.jetty.spdy.api.SynInfo;
import org.eclipse.jetty.spdy.server.NPNServerConnectionFactory;
import org.eclipse.jetty.util.Fields;
@ -51,13 +53,15 @@ import static org.junit.Assert.assertThat;
public class ReferrerPushStrategyTest extends AbstractHTTPSPDYTest
{
private final String mainResource = "/index.html";
private final int referrerPushPeriod = 1000;
private final String mainResource = "/index.html";
private final String cssResource = "/style.css";
private InetSocketAddress serverAddress;
private ReferrerPushStrategy pushStrategy;
private ConnectionFactory defaultFactory;
private Fields mainRequestHeaders;
private Fields associatedCSSRequestHeaders;
private Fields associatedJSRequestHeaders;
public ReferrerPushStrategyTest(short version)
{
@ -83,6 +87,8 @@ public class ReferrerPushStrategyTest extends AbstractHTTPSPDYTest
else
connector.setDefaultProtocol(defaultFactory.getProtocol());
mainRequestHeaders = createHeadersWithoutReferrer(mainResource);
associatedCSSRequestHeaders = createHeaders(cssResource);
associatedJSRequestHeaders = createHeaders("/application.js");
}
@Test
@ -92,6 +98,47 @@ public class ReferrerPushStrategyTest extends AbstractHTTPSPDYTest
run2ndClientRequests(true, true);
}
@Test
public void testClientResetsPushStreams() throws Exception
{
sendMainRequestAndCSSRequest();
final CountDownLatch pushDataLatch = new CountDownLatch(1);
final CountDownLatch pushSynHeadersValid = new CountDownLatch(1);
Session session = startClient(version, serverAddress, new SessionFrameListener.Adapter()
{
@Override
public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
{
validateHeaders(synInfo.getHeaders(), pushSynHeadersValid);
assertThat("Stream is unidirectional", stream.isUnidirectional(), is(true));
assertThat("URI header ends with css", synInfo.getHeaders().get(HTTPSPDYHeader.URI.name(version))
.value().endsWith
("" +
".css"),
is(true));
stream.getSession().rst(new RstInfo(stream.getId(), StreamStatus.REFUSED_STREAM));
return new StreamFrameListener.Adapter()
{
@Override
public void onData(Stream stream, DataInfo dataInfo)
{
dataInfo.consume(dataInfo.length());
pushDataLatch.countDown();
}
};
}
});
// Send main request. That should initiate the push syn's which get reset by the client
sendRequest(session, mainRequestHeaders);
assertThat("No push data is received", pushDataLatch.await(1, TimeUnit.SECONDS), is(false));
assertThat("Push syn headers valid", pushSynHeadersValid.await(5, TimeUnit.SECONDS), is(true));
sendRequest(session, associatedCSSRequestHeaders);
}
@Test
public void testUserAgentBlackList() throws Exception
{
@ -103,11 +150,11 @@ public class ReferrerPushStrategyTest extends AbstractHTTPSPDYTest
@Test
public void testReferrerPushPeriod() throws Exception
{
Session session1 = sendMainRequestAndCSSRequest();
Session session = sendMainRequestAndCSSRequest();
// Sleep for pushPeriod This should prevent application.js from being mapped as pushResource
Thread.sleep(referrerPushPeriod + 1);
sendJSRequest(session1);
sendRequest(session, associatedJSRequestHeaders);
run2ndClientRequests(false, true);
}
@ -119,9 +166,9 @@ public class ReferrerPushStrategyTest extends AbstractHTTPSPDYTest
connector.addConnectionFactory(defaultFactory);
connector.setDefaultProtocol(defaultFactory.getProtocol()); // TODO I don't think this is right
Session session1 = sendMainRequestAndCSSRequest();
Session session = sendMainRequestAndCSSRequest();
sendJSRequest(session1);
sendRequest(session, associatedJSRequestHeaders);
run2ndClientRequests(false, true);
}
@ -148,62 +195,43 @@ public class ReferrerPushStrategyTest extends AbstractHTTPSPDYTest
private Session sendMainRequestAndCSSRequest() throws Exception
{
Session session1 = startClient(version, serverAddress, null);
Session session = startClient(version, serverAddress, null);
final CountDownLatch mainResourceLatch = new CountDownLatch(1);
session1.syn(new SynInfo(mainRequestHeaders, true), new StreamFrameListener.Adapter()
{
@Override
public void onData(Stream stream, DataInfo dataInfo)
{
dataInfo.consume(dataInfo.length());
if (dataInfo.isClose())
mainResourceLatch.countDown();
}
});
Assert.assertTrue(mainResourceLatch.await(5, TimeUnit.SECONDS));
sendRequest(session, mainRequestHeaders);
sendRequest(session, associatedCSSRequestHeaders);
final CountDownLatch associatedResourceLatch1 = new CountDownLatch(1);
Fields associatedRequestHeaders1 = createHeaders(cssResource);
session1.syn(new SynInfo(associatedRequestHeaders1, true), new StreamFrameListener.Adapter()
{
@Override
public void onData(Stream stream, DataInfo dataInfo)
{
dataInfo.consume(dataInfo.length());
if (dataInfo.isClose())
associatedResourceLatch1.countDown();
}
});
Assert.assertTrue(associatedResourceLatch1.await(5, TimeUnit.SECONDS));
return session1;
return session;
}
private void sendJSRequest(Session session1) throws InterruptedException
private void sendRequest(Session session, Fields requestHeaders) throws InterruptedException
{
final CountDownLatch associatedResourceLatch2 = new CountDownLatch(1);
String jsResource = "/application.js";
Fields associatedRequestHeaders2 = createHeaders(jsResource);
session1.syn(new SynInfo(associatedRequestHeaders2, true), new StreamFrameListener.Adapter()
final CountDownLatch dataReceivedLatch = new CountDownLatch(1);
final CountDownLatch received200OKLatch = new CountDownLatch(1);
session.syn(new SynInfo(requestHeaders, true), new StreamFrameListener.Adapter()
{
@Override
public void onReply(Stream stream, ReplyInfo replyInfo)
{
if ("200 OK".equals(replyInfo.getHeaders().get(HTTPSPDYHeader.STATUS.name(version)).value()))
received200OKLatch.countDown();
super.onReply(stream, replyInfo);
}
@Override
public void onData(Stream stream, DataInfo dataInfo)
{
dataInfo.consume(dataInfo.length());
if (dataInfo.isClose())
associatedResourceLatch2.countDown();
dataReceivedLatch.countDown();
}
});
Assert.assertTrue(associatedResourceLatch2.await(5, TimeUnit.SECONDS));
Assert.assertTrue(received200OKLatch.await(5, TimeUnit.SECONDS));
Assert.assertTrue(dataReceivedLatch.await(5, TimeUnit.SECONDS));
}
private void run2ndClientRequests(final boolean validateHeaders,
boolean expectPushResource) throws Exception
{
// Create another client, and perform the same request for the main resource,
// we expect the css being pushed, but not the js
final CountDownLatch mainStreamLatch = new CountDownLatch(2);
final CountDownLatch pushDataLatch = new CountDownLatch(1);
final CountDownLatch pushSynHeadersValid = new CountDownLatch(1);
@ -215,11 +243,11 @@ public class ReferrerPushStrategyTest extends AbstractHTTPSPDYTest
if (validateHeaders)
validateHeaders(synInfo.getHeaders(), pushSynHeadersValid);
assertThat("Stream is unidirectional",stream.isUnidirectional(),is(true));
assertThat("Stream is unidirectional", stream.isUnidirectional(), is(true));
assertThat("URI header ends with css", synInfo.getHeaders().get(HTTPSPDYHeader.URI.name(version))
.value().endsWith
("" +
".css"),
("" +
".css"),
is(true));
return new StreamFrameListener.Adapter()
{
@ -252,13 +280,13 @@ public class ReferrerPushStrategyTest extends AbstractHTTPSPDYTest
}
});
assertThat("Main request reply and/or data not received", mainStreamLatch.await(5, TimeUnit.SECONDS), is(true));
assertThat("Main request reply and/or data received", mainStreamLatch.await(5, TimeUnit.SECONDS), is(true));
if (expectPushResource)
assertThat("Pushed data not received", pushDataLatch.await(5, TimeUnit.SECONDS), is(true));
assertThat("Pushed data received", pushDataLatch.await(5, TimeUnit.SECONDS), is(true));
else
assertThat("No push data is received", pushDataLatch.await(1, TimeUnit.SECONDS), is(false));
if (validateHeaders)
assertThat("Push syn headers not valid", pushSynHeadersValid.await(5, TimeUnit.SECONDS), is(true));
assertThat("Push syn headers valid", pushSynHeadersValid.await(5, TimeUnit.SECONDS), is(true));
}
@Test
@ -295,19 +323,7 @@ public class ReferrerPushStrategyTest extends AbstractHTTPSPDYTest
});
Assert.assertTrue(mainResourceLatch.await(5, TimeUnit.SECONDS));
final CountDownLatch associatedResourceLatch = new CountDownLatch(1);
Fields associatedRequestHeaders = createHeaders(cssResource);
session1.syn(new SynInfo(associatedRequestHeaders, true), new StreamFrameListener.Adapter()
{
@Override
public void onData(Stream stream, DataInfo dataInfo)
{
dataInfo.consume(dataInfo.length());
if (dataInfo.isClose())
associatedResourceLatch.countDown();
}
});
Assert.assertTrue(associatedResourceLatch.await(5, TimeUnit.SECONDS));
sendRequest(session1, createHeaders(cssResource));
// Create another client, and perform the same request for the main resource, we expect the css being pushed

View File

@ -36,6 +36,7 @@ import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.continuation.Continuation;
import org.eclipse.jetty.continuation.ContinuationSupport;
import org.eclipse.jetty.server.HttpChannel;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.spdy.api.BytesDataInfo;
@ -47,6 +48,7 @@ import org.eclipse.jetty.spdy.api.StreamFrameListener;
import org.eclipse.jetty.spdy.api.StringDataInfo;
import org.eclipse.jetty.spdy.api.SynInfo;
import org.eclipse.jetty.util.Fields;
import org.eclipse.jetty.util.log.StdErrLog;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
@ -58,7 +60,6 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
super(version);
}
@Test
public void testSimpleGET() throws Exception
{
final String path = "/foo";
@ -78,12 +79,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}
}), null);
Fields headers = new Fields();
headers.put(HTTPSPDYHeader.METHOD.name(version), "GET");
headers.put(HTTPSPDYHeader.URI.name(version), path);
headers.put(HTTPSPDYHeader.VERSION.name(version), "HTTP/1.1");
headers.put(HTTPSPDYHeader.SCHEME.name(version), "http");
headers.put(HTTPSPDYHeader.HOST.name(version), "localhost:" + connector.getLocalPort());
Fields headers = createHeaders("GET", path);
final CountDownLatch replyLatch = new CountDownLatch(1);
session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
{
@ -122,12 +118,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}
}), null);
Fields headers = new Fields();
headers.put(HTTPSPDYHeader.METHOD.name(version), "GET");
headers.put(HTTPSPDYHeader.URI.name(version), uri);
headers.put(HTTPSPDYHeader.VERSION.name(version), "HTTP/1.1");
headers.put(HTTPSPDYHeader.SCHEME.name(version), "http");
headers.put(HTTPSPDYHeader.HOST.name(version), "localhost:" + connector.getLocalPort());
Fields headers = createHeaders("GET", uri);
final CountDownLatch replyLatch = new CountDownLatch(1);
session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
{
@ -163,12 +154,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}
}), null);
Fields headers = new Fields();
headers.put(HTTPSPDYHeader.METHOD.name(version), "HEAD");
headers.put(HTTPSPDYHeader.URI.name(version), path);
headers.put(HTTPSPDYHeader.VERSION.name(version), "HTTP/1.1");
headers.put(HTTPSPDYHeader.SCHEME.name(version), "http");
headers.put(HTTPSPDYHeader.HOST.name(version), "localhost:" + connector.getLocalPort());
Fields headers = createHeaders("HEAD", path);
final CountDownLatch replyLatch = new CountDownLatch(1);
session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
{
@ -213,12 +199,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}
}), null);
Fields headers = new Fields();
headers.put(HTTPSPDYHeader.METHOD.name(version), "POST");
headers.put(HTTPSPDYHeader.URI.name(version), path);
headers.put(HTTPSPDYHeader.VERSION.name(version), "HTTP/1.1");
headers.put(HTTPSPDYHeader.SCHEME.name(version), "http");
headers.put(HTTPSPDYHeader.HOST.name(version), "localhost:" + connector.getLocalPort());
Fields headers = createHeaders("POST", path);
headers.put("content-type", "application/x-www-form-urlencoded");
final CountDownLatch replyLatch = new CountDownLatch(1);
Stream stream = session.syn(new SynInfo(headers, false), new StreamFrameListener.Adapter()
@ -259,12 +240,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}
}), null);
Fields headers = new Fields();
headers.put(HTTPSPDYHeader.METHOD.name(version), "POST");
headers.put(HTTPSPDYHeader.URI.name(version), path);
headers.put(HTTPSPDYHeader.VERSION.name(version), "HTTP/1.1");
headers.put(HTTPSPDYHeader.SCHEME.name(version), "http");
headers.put(HTTPSPDYHeader.HOST.name(version), "localhost:" + connector.getLocalPort());
Fields headers = createHeaders("POST", path);
headers.put("content-type", "application/x-www-form-urlencoded");
final CountDownLatch replyLatch = new CountDownLatch(1);
Stream stream = session.syn(new SynInfo(headers, false), new StreamFrameListener.Adapter()
@ -308,12 +284,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}
}), null);
Fields headers = new Fields();
headers.put(HTTPSPDYHeader.METHOD.name(version), "POST");
headers.put(HTTPSPDYHeader.URI.name(version), path);
headers.put(HTTPSPDYHeader.VERSION.name(version), "HTTP/1.1");
headers.put(HTTPSPDYHeader.SCHEME.name(version), "http");
headers.put(HTTPSPDYHeader.HOST.name(version), "localhost:" + connector.getLocalPort());
Fields headers = createHeaders("POST", path);
headers.put("content-type", "application/x-www-form-urlencoded");
final CountDownLatch replyLatch = new CountDownLatch(1);
Stream stream = session.syn(new SynInfo(headers, false), new StreamFrameListener.Adapter()
@ -354,7 +325,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}
}), null);
Fields headers = createHeaders("GET");
Fields headers = createHeaders("GET", "/foo");
final CountDownLatch replyLatch = new CountDownLatch(1);
final CountDownLatch dataLatch = new CountDownLatch(1);
session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
@ -400,7 +371,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}
}), null);
Fields headers = createHeaders("GET");
Fields headers = createHeaders("GET", "/foo");
final CountDownLatch replyLatch = new CountDownLatch(1);
final CountDownLatch dataLatch = new CountDownLatch(1);
session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
@ -451,7 +422,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}
}), null);
Fields headers = createHeaders("GET");
Fields headers = createHeaders("GET", "/foo");
final CountDownLatch replyLatch = new CountDownLatch(1);
final CountDownLatch dataLatch = new CountDownLatch(2);
session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
@ -506,7 +477,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}
}), null);
Fields headers = createHeaders("GET");
Fields headers = createHeaders("GET", "/foo");
final CountDownLatch replyLatch = new CountDownLatch(1);
final CountDownLatch dataLatch = new CountDownLatch(1);
session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
@ -559,7 +530,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}
}), null);
Fields headers = createHeaders("GET");
Fields headers = createHeaders("GET", "/foo");
final CountDownLatch replyLatch = new CountDownLatch(1);
final CountDownLatch dataLatch = new CountDownLatch(1);
session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
@ -612,7 +583,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}
}), null);
Fields headers = createHeaders("GET");
Fields headers = createHeaders("GET", "/foo");
final CountDownLatch replyLatch = new CountDownLatch(1);
final CountDownLatch dataLatch = new CountDownLatch(1);
session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
@ -670,7 +641,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}
}), null);
Fields headers = createHeaders("GET");
Fields headers = createHeaders("GET", "/foo");
final CountDownLatch replyLatch = new CountDownLatch(1);
final CountDownLatch dataLatch = new CountDownLatch(1);
session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
@ -723,7 +694,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}
}), null);
Fields headers = createHeaders("GET");
Fields headers = createHeaders("GET", "/foo");
final CountDownLatch replyLatch = new CountDownLatch(1);
session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
{
@ -760,7 +731,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}
}), null);
Fields headers = createHeaders("GET");
Fields headers = createHeaders("GET", "/foo");
final CountDownLatch replyLatch = new CountDownLatch(1);
final CountDownLatch dataLatch = new CountDownLatch(1);
session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
@ -792,18 +763,20 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
@Test
public void testGETWithException() throws Exception
{
StdErrLog log = StdErrLog.getLogger(HttpChannel.class);
log.setHideStacks(true);
Session session = startClient(version, startHTTPServer(version, new AbstractHandler()
{
@Override
public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse)
throws IOException, ServletException
{
// TODO suppress stack from test log
throw new NullPointerException("thrown_explicitly_by_the_test");
}
}), null);
Fields headers = createHeaders("GET");
Fields headers = createHeaders("GET", "/foo");
final CountDownLatch replyLatch = new CountDownLatch(1);
final CountDownLatch latch = new CountDownLatch(1);
session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
@ -830,6 +803,8 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
});
Assert.assertTrue(replyLatch.await(5, TimeUnit.SECONDS));
Assert.assertTrue(latch.await(5, TimeUnit.SECONDS));
log.setHideStacks(false);
}
@Test
@ -855,7 +830,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}
}), null);
Fields headers = createHeaders("GET");
Fields headers = createHeaders("GET", "/foo");
final CountDownLatch replyLatch = new CountDownLatch(1);
final CountDownLatch dataLatch = new CountDownLatch(2);
session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
@ -937,7 +912,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}
}), null);
Fields headers = createHeaders("GET");
Fields headers = createHeaders("GET", "/foo");
final CountDownLatch replyLatch = new CountDownLatch(1);
final CountDownLatch dataLatch = new CountDownLatch(1);
session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
@ -993,7 +968,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}
}), null);
Fields headers = createHeaders("GET");
Fields headers = createHeaders("GET", "/foo");
final CountDownLatch replyLatch = new CountDownLatch(1);
final CountDownLatch dataLatch = new CountDownLatch(1);
final AtomicInteger contentLength = new AtomicInteger();
@ -1057,7 +1032,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}
}), null);
Fields headers = createHeaders("POST");
Fields headers = createHeaders("POST", "/foo");
final CountDownLatch replyLatch = new CountDownLatch(1);
Stream stream = session.syn(new SynInfo(headers, false), new StreamFrameListener.Adapter()
{
@ -1100,7 +1075,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}
}), null);
Fields headers = createHeaders("POST");
Fields headers = createHeaders("POST", "/foo");
final CountDownLatch replyLatch = new CountDownLatch(1);
session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
{
@ -1145,7 +1120,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}
}), null);
Fields headers = createHeaders("POST");
Fields headers = createHeaders("POST", "/foo");
final CountDownLatch replyLatch = new CountDownLatch(1);
Stream stream = session.syn(new SynInfo(headers, false), new StreamFrameListener.Adapter()
{
@ -1213,7 +1188,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}
}), null);
Fields headers = createHeaders("POST");
Fields headers = createHeaders("POST", "/foo");
final CountDownLatch replyLatch = new CountDownLatch(1);
Stream stream = session.syn(new SynInfo(headers, false), new StreamFrameListener.Adapter()
{
@ -1281,7 +1256,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}
}), null);
Fields headers = createHeaders("POST");
Fields headers = createHeaders("POST", "/foo");
final CountDownLatch responseLatch = new CountDownLatch(2);
Stream stream = session.syn(new SynInfo(headers, false), new StreamFrameListener.Adapter()
{
@ -1322,7 +1297,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}
}), null);
Fields headers = createHeaders("POST");
Fields headers = createHeaders("POST", "/foo");
final CountDownLatch responseLatch = new CountDownLatch(1);
Stream stream = session.syn(new SynInfo(headers, false), new StreamFrameListener.Adapter()
{
@ -1341,14 +1316,15 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
Assert.assertTrue(responseLatch.await(5, TimeUnit.SECONDS));
}
private Fields createHeaders(String httpMethod)
private Fields createHeaders(String httpMethod, String path)
{
Fields headers = new Fields();
headers.put(HTTPSPDYHeader.METHOD.name(version), httpMethod);
headers.put(HTTPSPDYHeader.URI.name(version), "/foo");
headers.put(HTTPSPDYHeader.URI.name(version), path);
headers.put(HTTPSPDYHeader.VERSION.name(version), "HTTP/1.1");
headers.put(HTTPSPDYHeader.SCHEME.name(version), "http");
headers.put(HTTPSPDYHeader.HOST.name(version), "localhost:" + connector.getLocalPort());
return headers;
}
}