More tests for the HTTP over SPDY layer.

This commit is contained in:
Simone Bordet 2012-02-08 09:29:08 +01:00
parent 81a8c57e3b
commit 9316a9601b
5 changed files with 150 additions and 13 deletions

View File

@ -58,4 +58,10 @@ public class HeadersInfo
flags += isResetCompression() ? FLAG_RESET_COMPRESSION : 0;
return flags;
}
@Override
public String toString()
{
return String.format("HEADER close=%b %s", close, headers);
}
}

View File

@ -48,4 +48,10 @@ public class ReplyInfo
{
return isClose() ? FLAG_FIN : 0;
}
@Override
public String toString()
{
return String.format("REPLY close=%b %s", close, headers);
}
}

View File

@ -77,4 +77,10 @@ public class SynInfo
flags += isUnidirectional() ? FLAG_UNIDIRECTIONAL : 0;
return flags;
}
@Override
public String toString()
{
return String.format("SYN close=%b %s", close, headers);
}
}

View File

@ -46,12 +46,15 @@ import org.eclipse.jetty.spdy.api.SynInfo;
import org.eclipse.jetty.spdy.api.server.ServerSessionFrameListener;
import org.eclipse.jetty.spdy.nio.EmptyAsyncEndPoint;
import org.eclipse.jetty.spdy.nio.ServerSPDYAsyncConnectionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class HTTP11OverSPDYAsyncConnectionFactory extends ServerSPDYAsyncConnectionFactory
public class HTTPOverSPDYAsyncConnectionFactory extends ServerSPDYAsyncConnectionFactory
{
private final Logger logger = LoggerFactory.getLogger(getClass());
private final Connector connector;
public HTTP11OverSPDYAsyncConnectionFactory(Connector connector)
public HTTPOverSPDYAsyncConnectionFactory(Connector connector)
{
this.connector = connector;
}
@ -73,10 +76,13 @@ public class HTTP11OverSPDYAsyncConnectionFactory extends ServerSPDYAsyncConnect
// cycle is processed at a time, so we need to fake an http connection
// for each SYN in order to run concurrently.
logger.debug("Received {}", synInfo);
try
{
HTTPSPDYConnection connection = new HTTPSPDYConnection(connector, new HTTPSPDYAsyncEndPoint(stream), connector.getServer(), stream);
stream.setAttribute("connection", connection);
stream.setAttribute(ParseStatus.class.getName(), ParseStatus.INITIAL);
Headers headers = synInfo.getHeaders();
if (headers.isEmpty())
@ -101,6 +107,8 @@ public class HTTP11OverSPDYAsyncConnectionFactory extends ServerSPDYAsyncConnect
}
else
{
if (headers.names().contains("expect"))
forwardHeadersComplete(stream);
return this;
}
}
@ -119,11 +127,8 @@ public class HTTP11OverSPDYAsyncConnectionFactory extends ServerSPDYAsyncConnect
private boolean processRequest(Stream stream, Headers headers) throws IOException
{
Boolean requestSeen = (Boolean)stream.getAttribute("request");
if (requestSeen == null || !requestSeen)
if (stream.getAttribute(ParseStatus.class.getName()) == ParseStatus.INITIAL)
{
stream.setAttribute("request", Boolean.TRUE);
Headers.Header method = headers.get("method");
Headers.Header uri = headers.get("url");
Headers.Header version = headers.get("version");
@ -146,6 +151,8 @@ public class HTTP11OverSPDYAsyncConnectionFactory extends ServerSPDYAsyncConnect
@Override
public void onHeaders(Stream stream, HeadersInfo headersInfo)
{
logger.debug("Received {}", headersInfo);
// TODO: support trailers
Boolean dataSeen = (Boolean)stream.getAttribute("data");
if (dataSeen != null && dataSeen)
@ -176,9 +183,8 @@ public class HTTP11OverSPDYAsyncConnectionFactory extends ServerSPDYAsyncConnect
{
try
{
forwardHeadersComplete(stream);
stream.setAttribute("data", Boolean.TRUE);
if (stream.getAttribute(ParseStatus.class.getName()) == ParseStatus.REQUEST)
forwardHeadersComplete(stream);
ByteBuffer buffer = ByteBuffer.allocate(dataInfo.getBytesCount());
dataInfo.getBytes(buffer);
@ -206,12 +212,18 @@ public class HTTP11OverSPDYAsyncConnectionFactory extends ServerSPDYAsyncConnect
private void forwardRequest(Stream stream, String method, String uri, String version) throws IOException
{
assert stream.getAttribute(ParseStatus.class.getName()) == ParseStatus.INITIAL;
HTTPSPDYConnection connection = (HTTPSPDYConnection)stream.getAttribute("connection");
connection.startRequest(new ByteArrayBuffer(method), new ByteArrayBuffer(uri), new ByteArrayBuffer(version));
stream.setAttribute(ParseStatus.class.getName(), ParseStatus.REQUEST);
}
private void forwardHeaders(Stream stream, Headers headers) throws IOException
{
assert stream.getAttribute(ParseStatus.class.getName()) == ParseStatus.REQUEST;
HTTPSPDYConnection connection = (HTTPSPDYConnection)stream.getAttribute("connection");
for (Headers.Header header : headers)
{
@ -259,14 +271,20 @@ public class HTTP11OverSPDYAsyncConnectionFactory extends ServerSPDYAsyncConnect
private void forwardHeadersComplete(Stream stream) throws IOException
{
assert stream.getAttribute(ParseStatus.class.getName()) == ParseStatus.REQUEST;
HTTPSPDYConnection connection = (HTTPSPDYConnection)stream.getAttribute("connection");
connection.headerComplete();
stream.setAttribute(ParseStatus.class.getName(), ParseStatus.HEADERS);
}
private void forwardContent(Stream stream, ByteBuffer buffer) throws IOException
{
HTTPSPDYConnection connection = (HTTPSPDYConnection)stream.getAttribute("connection");
connection.content(new IndirectNIOBuffer(buffer, false));
stream.setAttribute(ParseStatus.class.getName(), ParseStatus.CONTENT);
}
private void forwardRequestComplete(Stream stream) throws IOException
@ -279,6 +297,12 @@ public class HTTP11OverSPDYAsyncConnectionFactory extends ServerSPDYAsyncConnect
{
stream.getSession().goAway(stream.getVersion());
}
}
private enum ParseStatus
{
INITIAL, REQUEST, HEADERS, CONTENT
}
private class HTTPSPDYConnection extends AbstractHttpConnection
@ -368,7 +392,10 @@ public class HTTP11OverSPDYAsyncConnectionFactory extends ServerSPDYAsyncConnect
@Override
public void send1xx(int code) throws IOException
{
// TODO
Headers headers = new Headers();
headers.put("status", String.valueOf(code));
headers.put("version", "HTTP/1.1");
stream.reply(new ReplyInfo(headers, false));
}
@Override
@ -392,6 +419,7 @@ public class HTTP11OverSPDYAsyncConnectionFactory extends ServerSPDYAsyncConnect
public void addContent(Buffer content, boolean last) throws IOException
{
// TODO
System.out.println("SIMON");
}
@Override

View File

@ -16,6 +16,7 @@
package org.eclipse.jetty.spdy.nio.http;
import java.io.BufferedReader;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.concurrent.CountDownLatch;
@ -33,11 +34,13 @@ import org.eclipse.jetty.spdy.api.ReplyInfo;
import org.eclipse.jetty.spdy.api.SPDY;
import org.eclipse.jetty.spdy.api.Session;
import org.eclipse.jetty.spdy.api.Stream;
import org.eclipse.jetty.spdy.api.StringDataInfo;
import org.eclipse.jetty.spdy.api.SynInfo;
import org.eclipse.jetty.spdy.nio.SPDYClient;
import org.eclipse.jetty.spdy.nio.SPDYServerConnector;
import org.junit.After;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
public class HTTPOverSPDYTest
@ -52,7 +55,7 @@ public class HTTPOverSPDYTest
server = new Server();
connector = new SPDYServerConnector(null);
server.addConnector(connector);
connector.putAsyncConnectionFactory("spdy/2", new HTTP11OverSPDYAsyncConnectionFactory(connector));
connector.putAsyncConnectionFactory("spdy/2", new HTTPOverSPDYAsyncConnectionFactory(connector));
server.setHandler(handler);
server.start();
@ -72,6 +75,53 @@ public class HTTPOverSPDYTest
server.join();
}
@Ignore
@Test
public void test100Continue() throws Exception
{
final String data = "data";
start(new AbstractHandler()
{
@Override
public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException, ServletException
{
request.setHandled(true);
httpResponse.sendError(100);
BufferedReader reader = httpRequest.getReader();
String read = reader.readLine();
Assert.assertEquals(data, read);
Assert.assertNull(reader.readLine());
httpResponse.setStatus(200);
}
}, null);
Headers headers = new Headers();
headers.put("method", "POST");
headers.put("url", "http://localhost:" + connector.getLocalPort() + "/100");
headers.put("version", "HTTP/1.1");
headers.put("expect", "100-continue");
final CountDownLatch replyLatch = new CountDownLatch(1);
session.syn(SPDY.V2, new SynInfo(headers, false), new Stream.FrameListener.Adapter()
{
@Override
public void onReply(Stream stream, ReplyInfo replyInfo)
{
Assert.assertTrue(replyInfo.getHeaders().get("status").value().contains("100"));
replyLatch.countDown();
// Now send the data
stream.data(new StringDataInfo(data, true));
}
});
Assert.assertTrue(replyLatch.await(5, TimeUnit.SECONDS));
Thread.sleep(500_000);
}
@Test
public void testSimpleGET() throws Exception
{
@ -85,8 +135,8 @@ public class HTTPOverSPDYTest
{
request.setHandled(true);
Assert.assertEquals(path, target);
Assert.assertEquals(httpRequest.getRequestURI(), path);
Assert.assertEquals(httpRequest.getHeader("host"), "localhost:" + connector.getLocalPort());
Assert.assertEquals(path, httpRequest.getRequestURI());
Assert.assertEquals("localhost:" + connector.getLocalPort(), httpRequest.getHeader("host"));
handlerLatch.countDown();
}
}, null);
@ -110,4 +160,45 @@ public class HTTPOverSPDYTest
Assert.assertTrue(handlerLatch.await(5, TimeUnit.SECONDS));
Assert.assertTrue(replyLatch.await(5, TimeUnit.SECONDS));
}
@Test
public void testGETWithQueryString() throws Exception
{
final String path = "/foo";
final String query = "p=1";
final String uri = path + "?" + query;
final CountDownLatch handlerLatch = new CountDownLatch(1);
start(new AbstractHandler()
{
@Override
public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse)
throws IOException, ServletException
{
request.setHandled(true);
Assert.assertEquals(path, target);
Assert.assertEquals(path, httpRequest.getRequestURI());
Assert.assertEquals(query, httpRequest.getQueryString());
handlerLatch.countDown();
}
}, null);
Headers headers = new Headers();
headers.put("method", "GET");
headers.put("url", "http://localhost:" + connector.getLocalPort() + uri);
headers.put("version", "HTTP/1.1");
final CountDownLatch replyLatch = new CountDownLatch(1);
session.syn(SPDY.V2, new SynInfo(headers, true), new Stream.FrameListener.Adapter()
{
@Override
public void onReply(Stream stream, ReplyInfo replyInfo)
{
Assert.assertTrue(replyInfo.isClose());
Headers replyHeaders = replyInfo.getHeaders();
Assert.assertTrue(replyHeaders.get("status").value().contains("200"));
replyLatch.countDown();
}
});
Assert.assertTrue(handlerLatch.await(5, TimeUnit.SECONDS));
Assert.assertTrue(replyLatch.await(5, TimeUnit.SECONDS));
}
}