jetty-9: extract common stuff from HttpManyWaysToCommitTest and HttpManyWaysToAsyncCommitTest into abstract class
This commit is contained in:
parent
188e749bb6
commit
ce6820b67b
|
@ -0,0 +1,115 @@
|
||||||
|
//========================================================================
|
||||||
|
//Copyright 2012 Mort Bay Consulting Pty. Ltd.
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
//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.server;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.OutputStreamWriter;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.net.Socket;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.server.handler.AbstractHandler;
|
||||||
|
import org.eclipse.jetty.server.util.SimpleHttpParser;
|
||||||
|
import org.eclipse.jetty.util.log.Log;
|
||||||
|
import org.eclipse.jetty.util.log.StdErrLog;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.is;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
|
||||||
|
public abstract class AbstractHttpTest
|
||||||
|
{
|
||||||
|
protected static Server server;
|
||||||
|
protected static SelectChannelConnector connector;
|
||||||
|
protected String httpVersion;
|
||||||
|
protected SimpleHttpParser httpParser;
|
||||||
|
|
||||||
|
public AbstractHttpTest(String httpVersion)
|
||||||
|
{
|
||||||
|
this.httpVersion = httpVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception
|
||||||
|
{
|
||||||
|
server = new Server();
|
||||||
|
connector = new SelectChannelConnector(server);
|
||||||
|
server.setConnectors(new Connector[]{connector});
|
||||||
|
httpParser = new SimpleHttpParser(httpVersion);
|
||||||
|
((StdErrLog)Log.getLogger(HttpChannel.class)).setHideStacks(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() throws Exception
|
||||||
|
{
|
||||||
|
((StdErrLog)Log.getLogger(HttpChannel.class)).setHideStacks(false);
|
||||||
|
server.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected TestHttpResponse executeRequest() throws URISyntaxException, IOException
|
||||||
|
{
|
||||||
|
Socket socket = new Socket("localhost", connector.getLocalPort());
|
||||||
|
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
|
||||||
|
PrintWriter writer = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
|
||||||
|
String request = "GET / " + httpVersion + "\r\n";
|
||||||
|
|
||||||
|
writer.write(request);
|
||||||
|
writer.write("Host: localhost");
|
||||||
|
writer.println("\r\n");
|
||||||
|
writer.flush();
|
||||||
|
|
||||||
|
return httpParser.readResponse(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void assertResponseBody(TestHttpResponse response, String expectedResponseBody)
|
||||||
|
{
|
||||||
|
assertThat("response body is" + expectedResponseBody, response.getBody(), is(expectedResponseBody));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void assertHeader(TestHttpResponse response, String headerName, String expectedValue)
|
||||||
|
{
|
||||||
|
assertThat(headerName + "=" + expectedValue, response.getHeaders().get(headerName), is(expectedValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class TestCommitException extends IllegalStateException
|
||||||
|
{
|
||||||
|
public TestCommitException()
|
||||||
|
{
|
||||||
|
super("Thrown by test");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected class ThrowExceptionOnDemandHandler extends AbstractHandler
|
||||||
|
{
|
||||||
|
private final boolean throwException;
|
||||||
|
|
||||||
|
protected ThrowExceptionOnDemandHandler(boolean throwException)
|
||||||
|
{
|
||||||
|
this.throwException = throwException;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||||
|
{
|
||||||
|
if (throwException)
|
||||||
|
throw new TestCommitException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,21 +12,9 @@
|
||||||
//========================================================================
|
//========================================================================
|
||||||
package org.eclipse.jetty.server;
|
package org.eclipse.jetty.server;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.EOFException;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.io.OutputStreamWriter;
|
|
||||||
import java.io.PrintWriter;
|
|
||||||
import java.net.Socket;
|
|
||||||
import java.net.SocketTimeoutException;
|
|
||||||
import java.net.URISyntaxException;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
import javax.servlet.AsyncContext;
|
import javax.servlet.AsyncContext;
|
||||||
import javax.servlet.ServletException;
|
import javax.servlet.ServletException;
|
||||||
import javax.servlet.ServletResponse;
|
import javax.servlet.ServletResponse;
|
||||||
|
@ -34,11 +22,6 @@ import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import org.eclipse.jetty.http.HttpVersion;
|
import org.eclipse.jetty.http.HttpVersion;
|
||||||
import org.eclipse.jetty.server.handler.AbstractHandler;
|
|
||||||
import org.eclipse.jetty.util.log.Log;
|
|
||||||
import org.eclipse.jetty.util.log.StdErrLog;
|
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Ignore;
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
@ -46,17 +29,13 @@ import org.junit.runners.Parameterized;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.is;
|
import static org.hamcrest.Matchers.is;
|
||||||
import static org.junit.Assert.assertThat;
|
import static org.junit.Assert.assertThat;
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
//TODO: reset buffer tests
|
//TODO: reset buffer tests
|
||||||
//TODO: add protocol specific tests for connection: close and/or chunking
|
//TODO: add protocol specific tests for connection: close and/or chunking
|
||||||
@RunWith(value = Parameterized.class)
|
@RunWith(value = Parameterized.class)
|
||||||
public class HttpManyWaysToAsyncCommitTest
|
public class HttpManyWaysToAsyncCommitTest extends AbstractHttpTest
|
||||||
{
|
{
|
||||||
private static Server server;
|
|
||||||
private static SelectChannelConnector connector;
|
|
||||||
private final String CONTEXT_ATTRIBUTE = getClass().getName() + ".asyncContext";
|
private final String CONTEXT_ATTRIBUTE = getClass().getName() + ".asyncContext";
|
||||||
private String httpVersion;
|
|
||||||
private boolean dispatch; // if true we dispatch, otherwise we complete
|
private boolean dispatch; // if true we dispatch, otherwise we complete
|
||||||
|
|
||||||
@Parameterized.Parameters
|
@Parameterized.Parameters
|
||||||
|
@ -69,33 +48,18 @@ public class HttpManyWaysToAsyncCommitTest
|
||||||
|
|
||||||
public HttpManyWaysToAsyncCommitTest(String httpVersion, boolean dispatch)
|
public HttpManyWaysToAsyncCommitTest(String httpVersion, boolean dispatch)
|
||||||
{
|
{
|
||||||
|
super(httpVersion);
|
||||||
this.httpVersion = httpVersion;
|
this.httpVersion = httpVersion;
|
||||||
this.dispatch = dispatch;
|
this.dispatch = dispatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Before
|
|
||||||
public void setUp() throws Exception
|
|
||||||
{
|
|
||||||
server = new Server();
|
|
||||||
connector = new SelectChannelConnector(server);
|
|
||||||
server.setConnectors(new Connector[]{connector});
|
|
||||||
((StdErrLog)Log.getLogger(HttpChannel.class)).setHideStacks(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@After
|
|
||||||
public void tearDown() throws Exception
|
|
||||||
{
|
|
||||||
((StdErrLog)Log.getLogger(HttpChannel.class)).setHideStacks(false);
|
|
||||||
server.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testHandlerDoesNotSetHandled() throws Exception
|
public void testHandlerDoesNotSetHandled() throws Exception
|
||||||
{
|
{
|
||||||
server.setHandler(new DoesNotSetHandledHandler(false));
|
server.setHandler(new DoesNotSetHandledHandler(false));
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
Response response = executeRequest();
|
TestHttpResponse response = executeRequest();
|
||||||
|
|
||||||
assertThat("response code is 404", response.getCode(), is("404"));
|
assertThat("response code is 404", response.getCode(), is("404"));
|
||||||
}
|
}
|
||||||
|
@ -106,7 +70,7 @@ public class HttpManyWaysToAsyncCommitTest
|
||||||
server.setHandler(new DoesNotSetHandledHandler(true));
|
server.setHandler(new DoesNotSetHandledHandler(true));
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
Response response = executeRequest();
|
TestHttpResponse response = executeRequest();
|
||||||
|
|
||||||
assertThat("response code is 500", response.getCode(), is("500"));
|
assertThat("response code is 500", response.getCode(), is("500"));
|
||||||
}
|
}
|
||||||
|
@ -149,7 +113,7 @@ public class HttpManyWaysToAsyncCommitTest
|
||||||
server.setHandler(new OnlySetHandledHandler(false));
|
server.setHandler(new OnlySetHandledHandler(false));
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
Response response = executeRequest();
|
TestHttpResponse response = executeRequest();
|
||||||
|
|
||||||
assertThat("response code is 200", response.getCode(), is("200"));
|
assertThat("response code is 200", response.getCode(), is("200"));
|
||||||
assertHeader(response, "content-length", "0");
|
assertHeader(response, "content-length", "0");
|
||||||
|
@ -161,7 +125,7 @@ public class HttpManyWaysToAsyncCommitTest
|
||||||
server.setHandler(new OnlySetHandledHandler(true));
|
server.setHandler(new OnlySetHandledHandler(true));
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
Response response = executeRequest();
|
TestHttpResponse response = executeRequest();
|
||||||
|
|
||||||
assertThat("response code is 500", response.getCode(), is("500"));
|
assertThat("response code is 500", response.getCode(), is("500"));
|
||||||
}
|
}
|
||||||
|
@ -206,7 +170,7 @@ public class HttpManyWaysToAsyncCommitTest
|
||||||
server.setHandler(new SetHandledWriteSomeDataHandler(false));
|
server.setHandler(new SetHandledWriteSomeDataHandler(false));
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
Response response = executeRequest();
|
TestHttpResponse response = executeRequest();
|
||||||
|
|
||||||
assertThat("response code is 200", response.getCode(), is("200"));
|
assertThat("response code is 200", response.getCode(), is("200"));
|
||||||
assertHeader(response, "content-length", "6");
|
assertHeader(response, "content-length", "6");
|
||||||
|
@ -218,7 +182,7 @@ public class HttpManyWaysToAsyncCommitTest
|
||||||
server.setHandler(new SetHandledWriteSomeDataHandler(true));
|
server.setHandler(new SetHandledWriteSomeDataHandler(true));
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
Response response = executeRequest();
|
TestHttpResponse response = executeRequest();
|
||||||
|
|
||||||
assertThat("response code is 500", response.getCode(), is("500"));
|
assertThat("response code is 500", response.getCode(), is("500"));
|
||||||
}
|
}
|
||||||
|
@ -270,7 +234,7 @@ public class HttpManyWaysToAsyncCommitTest
|
||||||
server.setHandler(new ExplicitFlushHandler(false));
|
server.setHandler(new ExplicitFlushHandler(false));
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
Response response = executeRequest();
|
TestHttpResponse response = executeRequest();
|
||||||
|
|
||||||
|
|
||||||
assertThat("response code is 200", response.getCode(), is("200"));
|
assertThat("response code is 200", response.getCode(), is("200"));
|
||||||
|
@ -284,7 +248,7 @@ public class HttpManyWaysToAsyncCommitTest
|
||||||
server.setHandler(new ExplicitFlushHandler(true));
|
server.setHandler(new ExplicitFlushHandler(true));
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
Response response = executeRequest();
|
TestHttpResponse response = executeRequest();
|
||||||
|
|
||||||
assertThat("response code is 200", response.getCode(), is("200"));
|
assertThat("response code is 200", response.getCode(), is("200"));
|
||||||
if ("HTTP/1.1".equals(httpVersion))
|
if ("HTTP/1.1".equals(httpVersion))
|
||||||
|
@ -340,7 +304,7 @@ public class HttpManyWaysToAsyncCommitTest
|
||||||
server.setHandler(new SetHandledAndFlushWithoutContentHandler(false));
|
server.setHandler(new SetHandledAndFlushWithoutContentHandler(false));
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
Response response = executeRequest();
|
TestHttpResponse response = executeRequest();
|
||||||
|
|
||||||
assertThat("response code is 200", response.getCode(), is("200"));
|
assertThat("response code is 200", response.getCode(), is("200"));
|
||||||
if ("HTTP/1.1".equals(httpVersion))
|
if ("HTTP/1.1".equals(httpVersion))
|
||||||
|
@ -353,7 +317,7 @@ public class HttpManyWaysToAsyncCommitTest
|
||||||
server.setHandler(new SetHandledAndFlushWithoutContentHandler(true));
|
server.setHandler(new SetHandledAndFlushWithoutContentHandler(true));
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
Response response = executeRequest();
|
TestHttpResponse response = executeRequest();
|
||||||
|
|
||||||
assertThat("response code is 200", response.getCode(), is("200"));
|
assertThat("response code is 200", response.getCode(), is("200"));
|
||||||
if ("HTTP/1.1".equals(httpVersion))
|
if ("HTTP/1.1".equals(httpVersion))
|
||||||
|
@ -407,7 +371,7 @@ public class HttpManyWaysToAsyncCommitTest
|
||||||
server.setHandler(new WriteFlushWriteMoreHandler(false));
|
server.setHandler(new WriteFlushWriteMoreHandler(false));
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
Response response = executeRequest();
|
TestHttpResponse response = executeRequest();
|
||||||
|
|
||||||
assertThat("response code is 200", response.getCode(), is("200"));
|
assertThat("response code is 200", response.getCode(), is("200"));
|
||||||
if ("HTTP/1.1".equals(httpVersion))
|
if ("HTTP/1.1".equals(httpVersion))
|
||||||
|
@ -420,7 +384,7 @@ public class HttpManyWaysToAsyncCommitTest
|
||||||
server.setHandler(new WriteFlushWriteMoreHandler(true));
|
server.setHandler(new WriteFlushWriteMoreHandler(true));
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
Response response = executeRequest();
|
TestHttpResponse response = executeRequest();
|
||||||
|
|
||||||
assertThat("response code is 200", response.getCode(), is("200"));
|
assertThat("response code is 200", response.getCode(), is("200"));
|
||||||
if ("HTTP/1.1".equals(httpVersion))
|
if ("HTTP/1.1".equals(httpVersion))
|
||||||
|
@ -477,7 +441,7 @@ public class HttpManyWaysToAsyncCommitTest
|
||||||
server.setHandler(new OverflowHandler(false));
|
server.setHandler(new OverflowHandler(false));
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
Response response = executeRequest();
|
TestHttpResponse response = executeRequest();
|
||||||
|
|
||||||
assertThat("response code is 200", response.getCode(), is("200"));
|
assertThat("response code is 200", response.getCode(), is("200"));
|
||||||
assertResponseBody(response, "foobar");
|
assertResponseBody(response, "foobar");
|
||||||
|
@ -490,7 +454,7 @@ public class HttpManyWaysToAsyncCommitTest
|
||||||
server.setHandler(new OverflowHandler(true));
|
server.setHandler(new OverflowHandler(true));
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
Response response = executeRequest();
|
TestHttpResponse response = executeRequest();
|
||||||
|
|
||||||
// response not committed when we throw, so 500 expected
|
// response not committed when we throw, so 500 expected
|
||||||
assertThat("response code is 500", response.getCode(), is("500"));
|
assertThat("response code is 500", response.getCode(), is("500"));
|
||||||
|
@ -545,7 +509,7 @@ public class HttpManyWaysToAsyncCommitTest
|
||||||
server.setHandler(new SetContentLengthAndWriteThatAmountOfBytesHandler(false));
|
server.setHandler(new SetContentLengthAndWriteThatAmountOfBytesHandler(false));
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
Response response = executeRequest();
|
TestHttpResponse response = executeRequest();
|
||||||
|
|
||||||
assertThat("response code is 200", response.getCode(), is("200"));
|
assertThat("response code is 200", response.getCode(), is("200"));
|
||||||
assertThat("response body is foo", response.getBody(), is("foo"));
|
assertThat("response body is foo", response.getBody(), is("foo"));
|
||||||
|
@ -558,7 +522,7 @@ public class HttpManyWaysToAsyncCommitTest
|
||||||
server.setHandler(new SetContentLengthAndWriteThatAmountOfBytesHandler(true));
|
server.setHandler(new SetContentLengthAndWriteThatAmountOfBytesHandler(true));
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
Response response = executeRequest();
|
TestHttpResponse response = executeRequest();
|
||||||
|
|
||||||
//TODO: should we expect 500 here?
|
//TODO: should we expect 500 here?
|
||||||
assertThat("response code is 200", response.getCode(), is("200"));
|
assertThat("response code is 200", response.getCode(), is("200"));
|
||||||
|
@ -615,7 +579,7 @@ public class HttpManyWaysToAsyncCommitTest
|
||||||
server.setHandler(new SetContentLengthAndWriteMoreBytesHandler(false));
|
server.setHandler(new SetContentLengthAndWriteMoreBytesHandler(false));
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
Response response = executeRequest();
|
TestHttpResponse response = executeRequest();
|
||||||
|
|
||||||
assertThat("response code is 200", response.getCode(), is("200"));
|
assertThat("response code is 200", response.getCode(), is("200"));
|
||||||
// jetty truncates the body when content-length is reached.! This is correct and desired behaviour?
|
// jetty truncates the body when content-length is reached.! This is correct and desired behaviour?
|
||||||
|
@ -629,7 +593,7 @@ public class HttpManyWaysToAsyncCommitTest
|
||||||
server.setHandler(new SetContentLengthAndWriteMoreBytesHandler(true));
|
server.setHandler(new SetContentLengthAndWriteMoreBytesHandler(true));
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
Response response = executeRequest();
|
TestHttpResponse response = executeRequest();
|
||||||
|
|
||||||
// TODO: we throw before response is committed. should we expect 500?
|
// TODO: we throw before response is committed. should we expect 500?
|
||||||
assertThat("response code is 200", response.getCode(), is("200"));
|
assertThat("response code is 200", response.getCode(), is("200"));
|
||||||
|
@ -686,7 +650,7 @@ public class HttpManyWaysToAsyncCommitTest
|
||||||
server.setHandler(new WriteAndSetContentLengthHandler(false));
|
server.setHandler(new WriteAndSetContentLengthHandler(false));
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
Response response = executeRequest();
|
TestHttpResponse response = executeRequest();
|
||||||
|
|
||||||
assertThat("response code is 200", response.getCode(), is("200"));
|
assertThat("response code is 200", response.getCode(), is("200"));
|
||||||
//TODO: jetty ignores setContentLength and sends transfer-encoding header. Correct?
|
//TODO: jetty ignores setContentLength and sends transfer-encoding header. Correct?
|
||||||
|
@ -698,7 +662,7 @@ public class HttpManyWaysToAsyncCommitTest
|
||||||
server.setHandler(new WriteAndSetContentLengthHandler(true));
|
server.setHandler(new WriteAndSetContentLengthHandler(true));
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
Response response = executeRequest();
|
TestHttpResponse response = executeRequest();
|
||||||
|
|
||||||
assertThat("response code is 200", response.getCode(), is("200"));
|
assertThat("response code is 200", response.getCode(), is("200"));
|
||||||
}
|
}
|
||||||
|
@ -753,7 +717,7 @@ public class HttpManyWaysToAsyncCommitTest
|
||||||
server.setHandler(new WriteAndSetContentLengthTooSmallHandler(false));
|
server.setHandler(new WriteAndSetContentLengthTooSmallHandler(false));
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
Response response = executeRequest();
|
TestHttpResponse response = executeRequest();
|
||||||
|
|
||||||
assertThat("response code is 200", response.getCode(), is("200"));
|
assertThat("response code is 200", response.getCode(), is("200"));
|
||||||
assertResponseBody(response, "foobar");
|
assertResponseBody(response, "foobar");
|
||||||
|
@ -768,7 +732,7 @@ public class HttpManyWaysToAsyncCommitTest
|
||||||
server.setHandler(new WriteAndSetContentLengthTooSmallHandler(true));
|
server.setHandler(new WriteAndSetContentLengthTooSmallHandler(true));
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
Response response = executeRequest();
|
TestHttpResponse response = executeRequest();
|
||||||
|
|
||||||
assertThat(response.getCode(), is("500"));
|
assertThat(response.getCode(), is("500"));
|
||||||
}
|
}
|
||||||
|
@ -815,213 +779,4 @@ public class HttpManyWaysToAsyncCommitTest
|
||||||
super.handle(target, baseRequest, request, response);
|
super.handle(target, baseRequest, request, response);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Response executeRequest() throws URISyntaxException, IOException
|
|
||||||
{
|
|
||||||
Socket socket = new Socket("localhost", connector.getLocalPort());
|
|
||||||
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
|
|
||||||
PrintWriter writer = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
|
|
||||||
String request = "GET / " + httpVersion + "\r\n";
|
|
||||||
|
|
||||||
writer.write(request);
|
|
||||||
writer.write("Host: localhost");
|
|
||||||
writer.println("\r\n");
|
|
||||||
writer.flush();
|
|
||||||
|
|
||||||
return readResponse(reader);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Response readResponse(BufferedReader reader) throws IOException
|
|
||||||
{
|
|
||||||
// Simplified parser for HTTP responses
|
|
||||||
String line = reader.readLine();
|
|
||||||
if (line == null)
|
|
||||||
throw new EOFException();
|
|
||||||
Matcher responseLine = Pattern.compile("HTTP/1.1" + "\\s+(\\d+)").matcher(line);
|
|
||||||
assertThat("http version is 1.1", responseLine.lookingAt(), is(true));
|
|
||||||
String code = responseLine.group(1);
|
|
||||||
|
|
||||||
Map<String, String> headers = new LinkedHashMap<>();
|
|
||||||
while ((line = reader.readLine()) != null)
|
|
||||||
{
|
|
||||||
if (line.trim().length() == 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
parseHeader(line, headers);
|
|
||||||
}
|
|
||||||
|
|
||||||
StringBuilder body;
|
|
||||||
if (headers.containsKey("content-length"))
|
|
||||||
{
|
|
||||||
body = parseContentLengthDelimitedBody(reader, headers);
|
|
||||||
}
|
|
||||||
else if ("chunked".equals(headers.get("transfer-encoding")))
|
|
||||||
{
|
|
||||||
body = parseChunkedBody(reader);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
body = parseEOFDelimitedBody(reader, headers);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Response(code, headers, body.toString().trim());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void parseHeader(String line, Map<String, String> headers)
|
|
||||||
{
|
|
||||||
Matcher header = Pattern.compile("([^:]+):\\s*(.*)").matcher(line);
|
|
||||||
assertTrue(header.lookingAt());
|
|
||||||
String headerName = header.group(1);
|
|
||||||
String headerValue = header.group(2);
|
|
||||||
headers.put(headerName.toLowerCase(), headerValue.toLowerCase());
|
|
||||||
}
|
|
||||||
|
|
||||||
private StringBuilder parseContentLengthDelimitedBody(BufferedReader reader, Map<String, String> headers) throws IOException
|
|
||||||
{
|
|
||||||
StringBuilder body;
|
|
||||||
int readLen = 0;
|
|
||||||
int length = Integer.parseInt(headers.get("content-length"));
|
|
||||||
body = new StringBuilder(length);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
//TODO: UTF-8 reader from joakim
|
|
||||||
for (int i = 0; i < length; ++i)
|
|
||||||
{
|
|
||||||
char c = (char)reader.read();
|
|
||||||
body.append(c);
|
|
||||||
readLen++;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
catch (SocketTimeoutException e)
|
|
||||||
{
|
|
||||||
System.err.printf("Read %,d bytes (out of an expected %,d bytes)%n", readLen, length);
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
return body;
|
|
||||||
}
|
|
||||||
|
|
||||||
private StringBuilder parseChunkedBody(BufferedReader reader) throws IOException
|
|
||||||
{
|
|
||||||
StringBuilder body;
|
|
||||||
String line;
|
|
||||||
body = new StringBuilder(64 * 1024);
|
|
||||||
while ((line = reader.readLine()) != null)
|
|
||||||
{
|
|
||||||
if ("0".equals(line))
|
|
||||||
{
|
|
||||||
line = reader.readLine();
|
|
||||||
assertThat("There's no more content after as 0 indicated the final chunk", line, is(""));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
int length = Integer.parseInt(line, 16);
|
|
||||||
//TODO: UTF-8 reader from joakim
|
|
||||||
for (int i = 0; i < length; ++i)
|
|
||||||
{
|
|
||||||
char c = (char)reader.read();
|
|
||||||
body.append(c);
|
|
||||||
}
|
|
||||||
reader.readLine();
|
|
||||||
// assertThat("chunk is followed by an empty line", line, is("")); //TODO: is this right? - NO. Don't
|
|
||||||
// think you can really do chunks with read line generally, but maybe for this test is OK.
|
|
||||||
}
|
|
||||||
return body;
|
|
||||||
}
|
|
||||||
|
|
||||||
private StringBuilder parseEOFDelimitedBody(BufferedReader reader, Map<String, String> headers) throws IOException
|
|
||||||
{
|
|
||||||
StringBuilder body;
|
|
||||||
if ("HTTP/1.1".equals(httpVersion))
|
|
||||||
assertThat("if no content-length or transfer-encoding header is set, " +
|
|
||||||
"connection: close header must be set", headers.get("connection"),
|
|
||||||
is("close"));
|
|
||||||
|
|
||||||
// read until EOF
|
|
||||||
body = new StringBuilder();
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
//TODO: UTF-8 reader from joakim
|
|
||||||
int read = reader.read();
|
|
||||||
if (read == -1)
|
|
||||||
break;
|
|
||||||
char c = (char)read;
|
|
||||||
body.append(c);
|
|
||||||
}
|
|
||||||
return body;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void assertResponseBody(Response response, String expectedResponseBody)
|
|
||||||
{
|
|
||||||
assertThat("response body is" + expectedResponseBody, response.getBody(), is(expectedResponseBody));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void assertHeader(Response response, String headerName, String expectedValue)
|
|
||||||
{
|
|
||||||
assertThat(headerName + "=" + expectedValue, response.getHeaders().get(headerName), is(expectedValue));
|
|
||||||
}
|
|
||||||
|
|
||||||
private class Response
|
|
||||||
{
|
|
||||||
private final String code;
|
|
||||||
private final Map<String, String> headers;
|
|
||||||
private final String body;
|
|
||||||
|
|
||||||
private Response(String code, Map<String, String> headers, String body)
|
|
||||||
{
|
|
||||||
this.code = code;
|
|
||||||
this.headers = headers;
|
|
||||||
this.body = body;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getCode()
|
|
||||||
{
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, String> getHeaders()
|
|
||||||
{
|
|
||||||
return headers;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getBody()
|
|
||||||
{
|
|
||||||
return body;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString()
|
|
||||||
{
|
|
||||||
return "Response{" +
|
|
||||||
"code='" + code + '\'' +
|
|
||||||
", headers=" + headers +
|
|
||||||
", body='" + body + '\'' +
|
|
||||||
'}';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class ThrowExceptionOnDemandHandler extends AbstractHandler
|
|
||||||
{
|
|
||||||
private final boolean throwException;
|
|
||||||
|
|
||||||
private ThrowExceptionOnDemandHandler(boolean throwException)
|
|
||||||
{
|
|
||||||
this.throwException = throwException;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
|
||||||
{
|
|
||||||
if (throwException)
|
|
||||||
throw new TestCommitException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class TestCommitException extends IllegalStateException
|
|
||||||
{
|
|
||||||
public TestCommitException()
|
|
||||||
{
|
|
||||||
super("Thrown by test");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,31 +12,14 @@
|
||||||
//========================================================================
|
//========================================================================
|
||||||
package org.eclipse.jetty.server;
|
package org.eclipse.jetty.server;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.EOFException;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.io.OutputStreamWriter;
|
|
||||||
import java.io.PrintWriter;
|
|
||||||
import java.net.Socket;
|
|
||||||
import java.net.SocketTimeoutException;
|
|
||||||
import java.net.URISyntaxException;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
import javax.servlet.ServletException;
|
import javax.servlet.ServletException;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import org.eclipse.jetty.http.HttpVersion;
|
import org.eclipse.jetty.http.HttpVersion;
|
||||||
import org.eclipse.jetty.server.handler.AbstractHandler;
|
|
||||||
import org.eclipse.jetty.util.log.Log;
|
|
||||||
import org.eclipse.jetty.util.log.StdErrLog;
|
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Ignore;
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
@ -44,17 +27,12 @@ import org.junit.runners.Parameterized;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.is;
|
import static org.hamcrest.Matchers.is;
|
||||||
import static org.junit.Assert.assertThat;
|
import static org.junit.Assert.assertThat;
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
//TODO: reset buffer tests
|
//TODO: reset buffer tests
|
||||||
//TODO: add protocol specific tests for connection: close and/or chunking
|
//TODO: add protocol specific tests for connection: close and/or chunking
|
||||||
@RunWith(value = Parameterized.class)
|
@RunWith(value = Parameterized.class)
|
||||||
public class HttpManyWaysToCommitTest
|
public class HttpManyWaysToCommitTest extends AbstractHttpTest
|
||||||
{
|
{
|
||||||
private static Server server;
|
|
||||||
private static SelectChannelConnector connector;
|
|
||||||
private String httpVersion;
|
|
||||||
|
|
||||||
@Parameterized.Parameters
|
@Parameterized.Parameters
|
||||||
public static Collection<Object[]> data()
|
public static Collection<Object[]> data()
|
||||||
{
|
{
|
||||||
|
@ -64,23 +42,7 @@ public class HttpManyWaysToCommitTest
|
||||||
|
|
||||||
public HttpManyWaysToCommitTest(String httpVersion)
|
public HttpManyWaysToCommitTest(String httpVersion)
|
||||||
{
|
{
|
||||||
this.httpVersion = httpVersion;
|
super(httpVersion);
|
||||||
}
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void setUp() throws Exception
|
|
||||||
{
|
|
||||||
server = new Server();
|
|
||||||
connector = new SelectChannelConnector(server);
|
|
||||||
server.setConnectors(new Connector[]{connector});
|
|
||||||
((StdErrLog)Log.getLogger(HttpChannel.class)).setHideStacks(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@After
|
|
||||||
public void tearDown() throws Exception
|
|
||||||
{
|
|
||||||
((StdErrLog)Log.getLogger(HttpChannel.class)).setHideStacks(false);
|
|
||||||
server.stop();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -89,7 +51,7 @@ public class HttpManyWaysToCommitTest
|
||||||
server.setHandler(new DoesNotSetHandledHandler(false));
|
server.setHandler(new DoesNotSetHandledHandler(false));
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
Response response = executeRequest();
|
TestHttpResponse response = executeRequest();
|
||||||
|
|
||||||
assertThat("response code is 404", response.getCode(), is("404"));
|
assertThat("response code is 404", response.getCode(), is("404"));
|
||||||
}
|
}
|
||||||
|
@ -100,7 +62,7 @@ public class HttpManyWaysToCommitTest
|
||||||
server.setHandler(new DoesNotSetHandledHandler(true));
|
server.setHandler(new DoesNotSetHandledHandler(true));
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
Response response = executeRequest();
|
TestHttpResponse response = executeRequest();
|
||||||
|
|
||||||
assertThat("response code is 500", response.getCode(), is("500"));
|
assertThat("response code is 500", response.getCode(), is("500"));
|
||||||
}
|
}
|
||||||
|
@ -126,7 +88,7 @@ public class HttpManyWaysToCommitTest
|
||||||
server.setHandler(new OnlySetHandledHandler(false));
|
server.setHandler(new OnlySetHandledHandler(false));
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
Response response = executeRequest();
|
TestHttpResponse response = executeRequest();
|
||||||
|
|
||||||
assertThat("response code is 200", response.getCode(), is("200"));
|
assertThat("response code is 200", response.getCode(), is("200"));
|
||||||
assertHeader(response, "content-length", "0");
|
assertHeader(response, "content-length", "0");
|
||||||
|
@ -138,7 +100,7 @@ public class HttpManyWaysToCommitTest
|
||||||
server.setHandler(new OnlySetHandledHandler(true));
|
server.setHandler(new OnlySetHandledHandler(true));
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
Response response = executeRequest();
|
TestHttpResponse response = executeRequest();
|
||||||
|
|
||||||
assertThat("response code is 500", response.getCode(), is("500"));
|
assertThat("response code is 500", response.getCode(), is("500"));
|
||||||
}
|
}
|
||||||
|
@ -165,7 +127,7 @@ public class HttpManyWaysToCommitTest
|
||||||
server.setHandler(new SetHandledWriteSomeDataHandler(false));
|
server.setHandler(new SetHandledWriteSomeDataHandler(false));
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
Response response = executeRequest();
|
TestHttpResponse response = executeRequest();
|
||||||
|
|
||||||
assertThat("response code is 200", response.getCode(), is("200"));
|
assertThat("response code is 200", response.getCode(), is("200"));
|
||||||
assertHeader(response, "content-length", "6");
|
assertHeader(response, "content-length", "6");
|
||||||
|
@ -177,7 +139,7 @@ public class HttpManyWaysToCommitTest
|
||||||
server.setHandler(new SetHandledWriteSomeDataHandler(true));
|
server.setHandler(new SetHandledWriteSomeDataHandler(true));
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
Response response = executeRequest();
|
TestHttpResponse response = executeRequest();
|
||||||
|
|
||||||
assertThat("response code is 500", response.getCode(), is("500"));
|
assertThat("response code is 500", response.getCode(), is("500"));
|
||||||
}
|
}
|
||||||
|
@ -204,7 +166,7 @@ public class HttpManyWaysToCommitTest
|
||||||
server.setHandler(new ExplicitFlushHandler(false));
|
server.setHandler(new ExplicitFlushHandler(false));
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
Response response = executeRequest();
|
TestHttpResponse response = executeRequest();
|
||||||
|
|
||||||
|
|
||||||
assertThat("response code is 200", response.getCode(), is("200"));
|
assertThat("response code is 200", response.getCode(), is("200"));
|
||||||
|
@ -218,7 +180,7 @@ public class HttpManyWaysToCommitTest
|
||||||
server.setHandler(new ExplicitFlushHandler(true));
|
server.setHandler(new ExplicitFlushHandler(true));
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
Response response = executeRequest();
|
TestHttpResponse response = executeRequest();
|
||||||
|
|
||||||
assertThat("response code is 200", response.getCode(), is("200"));
|
assertThat("response code is 200", response.getCode(), is("200"));
|
||||||
if ("HTTP/1.1".equals(httpVersion))
|
if ("HTTP/1.1".equals(httpVersion))
|
||||||
|
@ -248,7 +210,7 @@ public class HttpManyWaysToCommitTest
|
||||||
server.setHandler(new SetHandledAndFlushWithoutContentHandler(false));
|
server.setHandler(new SetHandledAndFlushWithoutContentHandler(false));
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
Response response = executeRequest();
|
TestHttpResponse response = executeRequest();
|
||||||
|
|
||||||
assertThat("response code is 200", response.getCode(), is("200"));
|
assertThat("response code is 200", response.getCode(), is("200"));
|
||||||
if ("HTTP/1.1".equals(httpVersion))
|
if ("HTTP/1.1".equals(httpVersion))
|
||||||
|
@ -261,7 +223,7 @@ public class HttpManyWaysToCommitTest
|
||||||
server.setHandler(new SetHandledAndFlushWithoutContentHandler(true));
|
server.setHandler(new SetHandledAndFlushWithoutContentHandler(true));
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
Response response = executeRequest();
|
TestHttpResponse response = executeRequest();
|
||||||
|
|
||||||
assertThat("response code is 200", response.getCode(), is("200"));
|
assertThat("response code is 200", response.getCode(), is("200"));
|
||||||
if ("HTTP/1.1".equals(httpVersion))
|
if ("HTTP/1.1".equals(httpVersion))
|
||||||
|
@ -290,7 +252,7 @@ public class HttpManyWaysToCommitTest
|
||||||
server.setHandler(new WriteFlushWriteMoreHandler(false));
|
server.setHandler(new WriteFlushWriteMoreHandler(false));
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
Response response = executeRequest();
|
TestHttpResponse response = executeRequest();
|
||||||
|
|
||||||
assertThat("response code is 200", response.getCode(), is("200"));
|
assertThat("response code is 200", response.getCode(), is("200"));
|
||||||
if ("HTTP/1.1".equals(httpVersion))
|
if ("HTTP/1.1".equals(httpVersion))
|
||||||
|
@ -303,7 +265,7 @@ public class HttpManyWaysToCommitTest
|
||||||
server.setHandler(new WriteFlushWriteMoreHandler(true));
|
server.setHandler(new WriteFlushWriteMoreHandler(true));
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
Response response = executeRequest();
|
TestHttpResponse response = executeRequest();
|
||||||
|
|
||||||
assertThat("response code is 200", response.getCode(), is("200"));
|
assertThat("response code is 200", response.getCode(), is("200"));
|
||||||
if ("HTTP/1.1".equals(httpVersion))
|
if ("HTTP/1.1".equals(httpVersion))
|
||||||
|
@ -334,7 +296,7 @@ public class HttpManyWaysToCommitTest
|
||||||
server.setHandler(new OverflowHandler(false));
|
server.setHandler(new OverflowHandler(false));
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
Response response = executeRequest();
|
TestHttpResponse response = executeRequest();
|
||||||
|
|
||||||
assertThat("response code is 200", response.getCode(), is("200"));
|
assertThat("response code is 200", response.getCode(), is("200"));
|
||||||
assertResponseBody(response, "foobar");
|
assertResponseBody(response, "foobar");
|
||||||
|
@ -347,7 +309,7 @@ public class HttpManyWaysToCommitTest
|
||||||
server.setHandler(new OverflowHandler(true));
|
server.setHandler(new OverflowHandler(true));
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
Response response = executeRequest();
|
TestHttpResponse response = executeRequest();
|
||||||
|
|
||||||
// response not committed when we throw, so 500 expected
|
// response not committed when we throw, so 500 expected
|
||||||
assertThat("response code is 500", response.getCode(), is("500"));
|
assertThat("response code is 500", response.getCode(), is("500"));
|
||||||
|
@ -376,7 +338,7 @@ public class HttpManyWaysToCommitTest
|
||||||
server.setHandler(new SetContentLengthAndWriteThatAmountOfBytesHandler(false));
|
server.setHandler(new SetContentLengthAndWriteThatAmountOfBytesHandler(false));
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
Response response = executeRequest();
|
TestHttpResponse response = executeRequest();
|
||||||
|
|
||||||
assertThat("response code is 200", response.getCode(), is("200"));
|
assertThat("response code is 200", response.getCode(), is("200"));
|
||||||
assertThat("response body is foo", response.getBody(), is("foo"));
|
assertThat("response body is foo", response.getBody(), is("foo"));
|
||||||
|
@ -390,7 +352,7 @@ public class HttpManyWaysToCommitTest
|
||||||
server.setHandler(new SetContentLengthAndWriteThatAmountOfBytesHandler(true));
|
server.setHandler(new SetContentLengthAndWriteThatAmountOfBytesHandler(true));
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
Response response = executeRequest();
|
TestHttpResponse response = executeRequest();
|
||||||
|
|
||||||
//TODO: should we expect 500 here?
|
//TODO: should we expect 500 here?
|
||||||
assertThat("response code is 200", response.getCode(), is("200"));
|
assertThat("response code is 200", response.getCode(), is("200"));
|
||||||
|
@ -421,7 +383,7 @@ public class HttpManyWaysToCommitTest
|
||||||
server.setHandler(new SetContentLengthAndWriteMoreBytesHandler(false));
|
server.setHandler(new SetContentLengthAndWriteMoreBytesHandler(false));
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
Response response = executeRequest();
|
TestHttpResponse response = executeRequest();
|
||||||
|
|
||||||
assertThat("response code is 200", response.getCode(), is("200"));
|
assertThat("response code is 200", response.getCode(), is("200"));
|
||||||
// jetty truncates the body when content-length is reached.! This is correct and desired behaviour?
|
// jetty truncates the body when content-length is reached.! This is correct and desired behaviour?
|
||||||
|
@ -435,7 +397,7 @@ public class HttpManyWaysToCommitTest
|
||||||
server.setHandler(new SetContentLengthAndWriteMoreBytesHandler(true));
|
server.setHandler(new SetContentLengthAndWriteMoreBytesHandler(true));
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
Response response = executeRequest();
|
TestHttpResponse response = executeRequest();
|
||||||
|
|
||||||
// TODO: we throw before response is committed. should we expect 500?
|
// TODO: we throw before response is committed. should we expect 500?
|
||||||
assertThat("response code is 200", response.getCode(), is("200"));
|
assertThat("response code is 200", response.getCode(), is("200"));
|
||||||
|
@ -466,7 +428,7 @@ public class HttpManyWaysToCommitTest
|
||||||
server.setHandler(new WriteAndSetContentLengthHandler(false));
|
server.setHandler(new WriteAndSetContentLengthHandler(false));
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
Response response = executeRequest();
|
TestHttpResponse response = executeRequest();
|
||||||
|
|
||||||
assertThat("response code is 200", response.getCode(), is("200"));
|
assertThat("response code is 200", response.getCode(), is("200"));
|
||||||
//TODO: jetty ignores setContentLength and sends transfer-encoding header. Correct?
|
//TODO: jetty ignores setContentLength and sends transfer-encoding header. Correct?
|
||||||
|
@ -478,7 +440,7 @@ public class HttpManyWaysToCommitTest
|
||||||
server.setHandler(new WriteAndSetContentLengthHandler(true));
|
server.setHandler(new WriteAndSetContentLengthHandler(true));
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
Response response = executeRequest();
|
TestHttpResponse response = executeRequest();
|
||||||
|
|
||||||
assertThat("response code is 200", response.getCode(), is("200"));
|
assertThat("response code is 200", response.getCode(), is("200"));
|
||||||
}
|
}
|
||||||
|
@ -507,7 +469,7 @@ public class HttpManyWaysToCommitTest
|
||||||
server.setHandler(new WriteAndSetContentLengthTooSmallHandler(false));
|
server.setHandler(new WriteAndSetContentLengthTooSmallHandler(false));
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
Response response = executeRequest();
|
TestHttpResponse response = executeRequest();
|
||||||
|
|
||||||
assertThat("response code is 200", response.getCode(), is("200"));
|
assertThat("response code is 200", response.getCode(), is("200"));
|
||||||
assertResponseBody(response, "foobar");
|
assertResponseBody(response, "foobar");
|
||||||
|
@ -522,7 +484,7 @@ public class HttpManyWaysToCommitTest
|
||||||
server.setHandler(new WriteAndSetContentLengthTooSmallHandler(true));
|
server.setHandler(new WriteAndSetContentLengthTooSmallHandler(true));
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
Response response = executeRequest();
|
TestHttpResponse response = executeRequest();
|
||||||
|
|
||||||
assertThat(response.getCode(), is("500"));
|
assertThat(response.getCode(), is("500"));
|
||||||
}
|
}
|
||||||
|
@ -543,213 +505,4 @@ public class HttpManyWaysToCommitTest
|
||||||
super.handle(target, baseRequest, request, response);
|
super.handle(target, baseRequest, request, response);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Response executeRequest() throws URISyntaxException, IOException
|
|
||||||
{
|
|
||||||
Socket socket = new Socket("localhost", connector.getLocalPort());
|
|
||||||
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
|
|
||||||
PrintWriter writer = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
|
|
||||||
String request = "GET / " + httpVersion + "\r\n";
|
|
||||||
|
|
||||||
writer.write(request);
|
|
||||||
writer.write("Host: localhost");
|
|
||||||
writer.println("\r\n");
|
|
||||||
writer.flush();
|
|
||||||
|
|
||||||
return readResponse(reader);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Response readResponse(BufferedReader reader) throws IOException
|
|
||||||
{
|
|
||||||
// Simplified parser for HTTP responses
|
|
||||||
String line = reader.readLine();
|
|
||||||
if (line == null)
|
|
||||||
throw new EOFException();
|
|
||||||
Matcher responseLine = Pattern.compile("HTTP/1.1" + "\\s+(\\d+)").matcher(line);
|
|
||||||
assertThat("http version is 1.1", responseLine.lookingAt(), is(true));
|
|
||||||
String code = responseLine.group(1);
|
|
||||||
|
|
||||||
Map<String, String> headers = new LinkedHashMap<>();
|
|
||||||
while ((line = reader.readLine()) != null)
|
|
||||||
{
|
|
||||||
if (line.trim().length() == 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
parseHeader(line, headers);
|
|
||||||
}
|
|
||||||
|
|
||||||
StringBuilder body;
|
|
||||||
if (headers.containsKey("content-length"))
|
|
||||||
{
|
|
||||||
body = parseContentLengthDelimitedBody(reader, headers);
|
|
||||||
}
|
|
||||||
else if ("chunked".equals(headers.get("transfer-encoding")))
|
|
||||||
{
|
|
||||||
body = parseChunkedBody(reader);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
body = parseEOFDelimitedBody(reader, headers);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Response(code, headers, body.toString().trim());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void parseHeader(String line, Map<String, String> headers)
|
|
||||||
{
|
|
||||||
Matcher header = Pattern.compile("([^:]+):\\s*(.*)").matcher(line);
|
|
||||||
assertTrue(header.lookingAt());
|
|
||||||
String headerName = header.group(1);
|
|
||||||
String headerValue = header.group(2);
|
|
||||||
headers.put(headerName.toLowerCase(), headerValue.toLowerCase());
|
|
||||||
}
|
|
||||||
|
|
||||||
private StringBuilder parseContentLengthDelimitedBody(BufferedReader reader, Map<String, String> headers) throws IOException
|
|
||||||
{
|
|
||||||
StringBuilder body;
|
|
||||||
int readLen = 0;
|
|
||||||
int length = Integer.parseInt(headers.get("content-length"));
|
|
||||||
body = new StringBuilder(length);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
//TODO: UTF-8 reader from joakim
|
|
||||||
for (int i = 0; i < length; ++i)
|
|
||||||
{
|
|
||||||
char c = (char)reader.read();
|
|
||||||
body.append(c);
|
|
||||||
readLen++;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
catch (SocketTimeoutException e)
|
|
||||||
{
|
|
||||||
System.err.printf("Read %,d bytes (out of an expected %,d bytes)%n", readLen, length);
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
return body;
|
|
||||||
}
|
|
||||||
|
|
||||||
private StringBuilder parseChunkedBody(BufferedReader reader) throws IOException
|
|
||||||
{
|
|
||||||
StringBuilder body;
|
|
||||||
String line;
|
|
||||||
body = new StringBuilder(64 * 1024);
|
|
||||||
while ((line = reader.readLine()) != null)
|
|
||||||
{
|
|
||||||
if ("0".equals(line))
|
|
||||||
{
|
|
||||||
line = reader.readLine();
|
|
||||||
assertThat("There's no more content after as 0 indicated the final chunk", line, is(""));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
int length = Integer.parseInt(line, 16);
|
|
||||||
//TODO: UTF-8 reader from joakim
|
|
||||||
for (int i = 0; i < length; ++i)
|
|
||||||
{
|
|
||||||
char c = (char)reader.read();
|
|
||||||
body.append(c);
|
|
||||||
}
|
|
||||||
reader.readLine();
|
|
||||||
// assertThat("chunk is followed by an empty line", line, is("")); //TODO: is this right? - NO. Don't
|
|
||||||
// think you can really do chunks with read line generally, but maybe for this test is OK.
|
|
||||||
}
|
|
||||||
return body;
|
|
||||||
}
|
|
||||||
|
|
||||||
private StringBuilder parseEOFDelimitedBody(BufferedReader reader, Map<String, String> headers) throws IOException
|
|
||||||
{
|
|
||||||
StringBuilder body;
|
|
||||||
if ("HTTP/1.1".equals(httpVersion))
|
|
||||||
assertThat("if no content-length or transfer-encoding header is set, " +
|
|
||||||
"connection: close header must be set", headers.get("connection"),
|
|
||||||
is("close"));
|
|
||||||
|
|
||||||
// read until EOF
|
|
||||||
body = new StringBuilder();
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
//TODO: UTF-8 reader from joakim
|
|
||||||
int read = reader.read();
|
|
||||||
if (read == -1)
|
|
||||||
break;
|
|
||||||
char c = (char)read;
|
|
||||||
body.append(c);
|
|
||||||
}
|
|
||||||
return body;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void assertResponseBody(Response response, String expectedResponseBody)
|
|
||||||
{
|
|
||||||
assertThat("response body is" + expectedResponseBody, response.getBody(), is(expectedResponseBody));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void assertHeader(Response response, String headerName, String expectedValue)
|
|
||||||
{
|
|
||||||
assertThat(headerName + "=" + expectedValue, response.getHeaders().get(headerName), is(expectedValue));
|
|
||||||
}
|
|
||||||
|
|
||||||
private class Response
|
|
||||||
{
|
|
||||||
private final String code;
|
|
||||||
private final Map<String, String> headers;
|
|
||||||
private final String body;
|
|
||||||
|
|
||||||
private Response(String code, Map<String, String> headers, String body)
|
|
||||||
{
|
|
||||||
this.code = code;
|
|
||||||
this.headers = headers;
|
|
||||||
this.body = body;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getCode()
|
|
||||||
{
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, String> getHeaders()
|
|
||||||
{
|
|
||||||
return headers;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getBody()
|
|
||||||
{
|
|
||||||
return body;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString()
|
|
||||||
{
|
|
||||||
return "Response{" +
|
|
||||||
"code='" + code + '\'' +
|
|
||||||
", headers=" + headers +
|
|
||||||
", body='" + body + '\'' +
|
|
||||||
'}';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class ThrowExceptionOnDemandHandler extends AbstractHandler
|
|
||||||
{
|
|
||||||
private final boolean throwException;
|
|
||||||
|
|
||||||
private ThrowExceptionOnDemandHandler(boolean throwException)
|
|
||||||
{
|
|
||||||
this.throwException = throwException;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
|
||||||
{
|
|
||||||
if (throwException)
|
|
||||||
throw new TestCommitException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class TestCommitException extends IllegalStateException
|
|
||||||
{
|
|
||||||
public TestCommitException()
|
|
||||||
{
|
|
||||||
super("Thrown by test");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
//========================================================================
|
||||||
|
//Copyright 2012 Mort Bay Consulting Pty. Ltd.
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
//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.server;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class TestHttpResponse
|
||||||
|
{
|
||||||
|
private final String code;
|
||||||
|
private final Map<String, String> headers;
|
||||||
|
private final String body;
|
||||||
|
|
||||||
|
public TestHttpResponse(String code, Map<String, String> headers, String body)
|
||||||
|
{
|
||||||
|
this.code = code;
|
||||||
|
this.headers = headers;
|
||||||
|
this.body = body;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCode()
|
||||||
|
{
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getHeaders()
|
||||||
|
{
|
||||||
|
return headers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBody()
|
||||||
|
{
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return "Response{" +
|
||||||
|
"code='" + code + '\'' +
|
||||||
|
", headers=" + headers +
|
||||||
|
", body='" + body + '\'' +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,158 @@
|
||||||
|
//========================================================================
|
||||||
|
//Copyright 2012 Mort Bay Consulting Pty. Ltd.
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
//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.server.util;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.EOFException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.SocketTimeoutException;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.server.TestHttpResponse;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.is;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
public class SimpleHttpParser
|
||||||
|
{
|
||||||
|
final String httpVersion;
|
||||||
|
|
||||||
|
public SimpleHttpParser(String httpVersion)
|
||||||
|
{
|
||||||
|
this.httpVersion = httpVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TestHttpResponse readResponse(BufferedReader reader) throws IOException
|
||||||
|
{
|
||||||
|
// Simplified parser for HTTP responses
|
||||||
|
String line = reader.readLine();
|
||||||
|
if (line == null)
|
||||||
|
throw new EOFException();
|
||||||
|
Matcher responseLine = Pattern.compile("HTTP/1.1" + "\\s+(\\d+)").matcher(line);
|
||||||
|
assertThat("http version is 1.1", responseLine.lookingAt(), is(true));
|
||||||
|
String code = responseLine.group(1);
|
||||||
|
|
||||||
|
Map<String, String> headers = new LinkedHashMap<>();
|
||||||
|
while ((line = reader.readLine()) != null)
|
||||||
|
{
|
||||||
|
if (line.trim().length() == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
parseHeader(line, headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder body;
|
||||||
|
if (headers.containsKey("content-length"))
|
||||||
|
{
|
||||||
|
body = parseContentLengthDelimitedBody(reader, headers);
|
||||||
|
}
|
||||||
|
else if ("chunked".equals(headers.get("transfer-encoding")))
|
||||||
|
{
|
||||||
|
body = parseChunkedBody(reader);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
body = parseEOFDelimitedBody(reader, headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new TestHttpResponse(code, headers, body.toString().trim());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parseHeader(String line, Map<String, String> headers)
|
||||||
|
{
|
||||||
|
Matcher header = Pattern.compile("([^:]+):\\s*(.*)").matcher(line);
|
||||||
|
assertTrue(header.lookingAt());
|
||||||
|
String headerName = header.group(1);
|
||||||
|
String headerValue = header.group(2);
|
||||||
|
headers.put(headerName.toLowerCase(), headerValue.toLowerCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
private StringBuilder parseContentLengthDelimitedBody(BufferedReader reader, Map<String, String> headers) throws IOException
|
||||||
|
{
|
||||||
|
StringBuilder body;
|
||||||
|
int readLen = 0;
|
||||||
|
int length = Integer.parseInt(headers.get("content-length"));
|
||||||
|
body = new StringBuilder(length);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
//TODO: UTF-8 reader from joakim
|
||||||
|
for (int i = 0; i < length; ++i)
|
||||||
|
{
|
||||||
|
char c = (char)reader.read();
|
||||||
|
body.append(c);
|
||||||
|
readLen++;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (SocketTimeoutException e)
|
||||||
|
{
|
||||||
|
System.err.printf("Read %,d bytes (out of an expected %,d bytes)%n", readLen, length);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
|
||||||
|
private StringBuilder parseChunkedBody(BufferedReader reader) throws IOException
|
||||||
|
{
|
||||||
|
StringBuilder body;
|
||||||
|
String line;
|
||||||
|
body = new StringBuilder(64 * 1024);
|
||||||
|
while ((line = reader.readLine()) != null)
|
||||||
|
{
|
||||||
|
if ("0".equals(line))
|
||||||
|
{
|
||||||
|
line = reader.readLine();
|
||||||
|
assertThat("There's no more content after as 0 indicated the final chunk", line, is(""));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
int length = Integer.parseInt(line, 16);
|
||||||
|
//TODO: UTF-8 reader from joakim
|
||||||
|
for (int i = 0; i < length; ++i)
|
||||||
|
{
|
||||||
|
char c = (char)reader.read();
|
||||||
|
body.append(c);
|
||||||
|
}
|
||||||
|
reader.readLine();
|
||||||
|
// assertThat("chunk is followed by an empty line", line, is("")); //TODO: is this right? - NO. Don't
|
||||||
|
// think you can really do chunks with read line generally, but maybe for this test is OK.
|
||||||
|
}
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
|
||||||
|
private StringBuilder parseEOFDelimitedBody(BufferedReader reader, Map<String, String> headers) throws IOException
|
||||||
|
{
|
||||||
|
StringBuilder body;
|
||||||
|
if ("HTTP/1.1".equals(httpVersion))
|
||||||
|
assertThat("if no content-length or transfer-encoding header is set, " +
|
||||||
|
"connection: close header must be set", headers.get("connection"),
|
||||||
|
is("close"));
|
||||||
|
|
||||||
|
// read until EOF
|
||||||
|
body = new StringBuilder();
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
//TODO: UTF-8 reader from joakim
|
||||||
|
int read = reader.read();
|
||||||
|
if (read == -1)
|
||||||
|
break;
|
||||||
|
char c = (char)read;
|
||||||
|
body.append(c);
|
||||||
|
}
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue