blob: c72fd1a2038933e666fa8cf9e0d2a80007ea2465 [file] [log] [blame]
//
// ========================================================================
// Copyright (c) 1995-2017 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.
// ========================================================================
//
/*
* Created on 9/01/2004
*
* To change the template for this generated file go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/
package org.eclipse.jetty.server;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.StringReader;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.HttpCompliance;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpParser;
import org.eclipse.jetty.http.MimeTypes;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.server.handler.ErrorHandler;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.log.StacklessLogging;
import org.hamcrest.Matchers;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
public class HttpConnectionTest
{
private Server server;
private LocalConnector connector;
@Before
public void init() throws Exception
{
server = new Server();
HttpConfiguration config = new HttpConfiguration();
config.setRequestHeaderSize(1024);
config.setResponseHeaderSize(1024);
config.setSendDateHeader(true);
HttpConnectionFactory http = new HttpConnectionFactory(config);
connector = new LocalConnector(server,http,null);
connector.setIdleTimeout(5000);
server.addConnector(connector);
server.setHandler(new DumpHandler());
ErrorHandler eh=new ErrorHandler();
eh.setServer(server);
server.addBean(eh);
server.start();
}
@After
public void destroy() throws Exception
{
server.stop();
server.join();
}
@Test
public void testFragmentedChunk() throws Exception
{
String response=null;
try
{
int offset=0;
// Chunk last
response=connector.getResponses("GET /R1 HTTP/1.1\r\n"+
"Host: localhost\r\n"+
"Transfer-Encoding: chunked\r\n"+
"Content-Type: text/plain\r\n"+
"Connection: close\r\n"+
"\r\n"+
"5;\r\n"+
"12345\r\n"+
"0;\r\n" +
"\r\n");
offset = checkContains(response,offset,"HTTP/1.1 200");
offset = checkContains(response,offset,"/R1");
checkContains(response,offset,"12345");
offset = 0;
response=connector.getResponses("GET /R2 HTTP/1.1\r\n"+
"Host: localhost\r\n"+
"Transfer-Encoding: chunked\r\n"+
"Content-Type: text/plain\r\n"+
"Connection: close\r\n"+
"\r\n"+
"5;\r\n"+
"ABCDE\r\n"+
"0;\r\n" +
"\r\n");
offset = checkContains(response,offset,"HTTP/1.1 200");
offset = checkContains(response,offset,"/R2");
checkContains(response,offset,"ABCDE");
}
catch(Exception e)
{
if(response != null)
System.err.println(response);
throw e;
}
}
@Test
public void testNoPath() throws Exception
{
String response=connector.getResponses("GET http://localhost:80 HTTP/1.1\r\n"+
"Host: localhost:80\r\n"+
"Connection: close\r\n"+
"\r\n");
int offset=0;
offset = checkContains(response,offset,"HTTP/1.1 200");
checkContains(response,offset,"pathInfo=/");
}
@Test
public void testDate() throws Exception
{
String response=connector.getResponse("GET / HTTP/1.1\r\n"+
"Host: localhost:80\r\n"+
"Connection: close\r\n"+
"\r\n");
int offset=0;
offset = checkContains(response,offset,"HTTP/1.1 200");
offset = checkContains(response,offset,"Date: ");
checkContains(response,offset,"pathInfo=/");
}
@Test
public void testSetDate() throws Exception
{
String response=connector.getResponses("GET /?date=1+Jan+1970 HTTP/1.1\r\n"+
"Host: localhost:80\r\n"+
"Connection: close\r\n"+
"\r\n");
int offset=0;
offset = checkContains(response,offset,"HTTP/1.1 200");
offset = checkContains(response,offset,"Date: 1 Jan 1970");
checkContains(response,offset,"pathInfo=/");
}
@Test
public void testBadNoPath() throws Exception
{
String response=connector.getResponses("GET http://localhost:80/../cheat HTTP/1.1\r\n"+
"Host: localhost:80\r\n"+
"\r\n");
checkContains(response,0,"HTTP/1.1 400");
}
@Test
public void testOKPathDotDotPath() throws Exception
{
String response=connector.getResponses("GET /ooops/../path HTTP/1.0\r\nHost: localhost:80\r\n\n");
checkContains(response,0,"HTTP/1.1 200 OK");
checkContains(response,0,"pathInfo=/path");
}
@Test
public void testBadPathDotDotPath() throws Exception
{
String response=connector.getResponses("GET /ooops/../../path HTTP/1.0\r\nHost: localhost:80\r\n\n");
checkContains(response,0,"HTTP/1.1 400 Bad URI");
}
@Test
public void testOKPathEncodedDotDotPath() throws Exception
{
String response=connector.getResponses("GET /ooops/%2e%2e/path HTTP/1.0\r\nHost: localhost:80\r\n\n");
checkContains(response,0,"HTTP/1.1 200 OK");
checkContains(response,0,"pathInfo=/path");
}
@Test
public void testBadPathEncodedDotDotPath() throws Exception
{
String response=connector.getResponses("GET /ooops/%2e%2e/%2e%2e/path HTTP/1.0\r\nHost: localhost:80\r\n\n");
checkContains(response,0,"HTTP/1.1 400 Bad URI");
}
@Test
public void testBadDotDotPath() throws Exception
{
String response=connector.getResponses("GET ../path HTTP/1.0\r\nHost: localhost:80\r\n\n");
checkContains(response,0,"HTTP/1.1 400 Bad URI");
}
@Test
public void testBadSlashDotDotPath() throws Exception
{
String response=connector.getResponses("GET /../path HTTP/1.0\r\nHost: localhost:80\r\n\n");
checkContains(response,0,"HTTP/1.1 400 Bad URI");
}
@Test
public void testEncodedBadDotDotPath() throws Exception
{
String response=connector.getResponses("GET %2e%2e/path HTTP/1.0\r\nHost: localhost:80\r\n\n");
checkContains(response,0,"HTTP/1.1 400 Bad URI");
}
@Test
public void test_0_9() throws Exception
{
connector.getConnectionFactory(HttpConnectionFactory.class).setHttpCompliance(HttpCompliance.RFC2616);
String response=connector.getResponses("GET /R1\n");
int offset=0;
checkNotContained(response,offset,"HTTP/1.1");
checkNotContained(response,offset,"200");
checkContains(response,offset,"pathInfo=/R1");
}
@Test
public void testSimple() throws Exception
{
String response=connector.getResponses("GET /R1 HTTP/1.1\r\n"+
"Host: localhost\r\n"+
"Connection: close\r\n"+
"\r\n");
int offset=0;
offset = checkContains(response,offset,"HTTP/1.1 200");
checkContains(response,offset,"/R1");
}
@Test
public void testEmptyChunk() throws Exception
{
String response=connector.getResponse("GET /R1 HTTP/1.1\r\n"+
"Host: localhost\r\n"+
"Transfer-Encoding: chunked\r\n"+
"Content-Type: text/plain\r\n"+
"Connection: close\r\n"+
"\r\n"+
"0\r\n" +
"\r\n");
int offset=0;
offset = checkContains(response,offset,"HTTP/1.1 200");
checkContains(response,offset,"/R1");
}
@Test
public void testChunk() throws Exception
{
String response=connector.getResponse("GET /R1 HTTP/1.1\r\n"+
"Host: localhost\r\n"+
"Transfer-Encoding: chunked\r\n"+
"Content-Type: text/plain\r\n"+
"Connection: close\r\n"+
"\r\n"+
"A\r\n" +
"0123456789\r\n"+
"0\r\n" +
"\r\n");
int offset=0;
offset = checkContains(response,offset,"HTTP/1.1 200");
offset = checkContains(response,offset,"/R1");
checkContains(response,offset,"0123456789");
}
@Test
public void testChunkTrailer() throws Exception
{
String response=connector.getResponse("GET /R1 HTTP/1.1\r\n"+
"Host: localhost\r\n"+
"Transfer-Encoding: chunked\r\n"+
"Content-Type: text/plain\r\n"+
"Connection: close\r\n"+
"\r\n"+
"A\r\n" +
"0123456789\r\n"+
"0\r\n" +
"Trailer: ignored\r\n" +
"\r\n");
int offset=0;
offset = checkContains(response,offset,"HTTP/1.1 200");
offset = checkContains(response,offset,"/R1");
checkContains(response,offset,"0123456789");
}
@Test
public void testChunkNoTrailer() throws Exception
{
String response=connector.getResponse("GET /R1 HTTP/1.1\r\n"+
"Host: localhost\r\n"+
"Transfer-Encoding: chunked\r\n"+
"Content-Type: text/plain\r\n"+
"Connection: close\r\n"+
"\r\n"+
"A\r\n" +
"0123456789\r\n"+
"0\r\n");
int offset=0;
offset = checkContains(response,offset,"HTTP/1.1 200");
offset = checkContains(response,offset,"/R1");
checkContains(response,offset,"0123456789");
}
@Test
public void testHead() throws Exception
{
String responsePOST=connector.getResponses("POST /R1 HTTP/1.1\r\n"+
"Host: localhost\r\n"+
"Connection: close\r\n"+
"\r\n");
String responseHEAD=connector.getResponses("HEAD /R1 HTTP/1.1\r\n"+
"Host: localhost\r\n"+
"Connection: close\r\n"+
"\r\n");
String postLine;
boolean postDate=false;
Set<String> postHeaders = new HashSet<>();
try(BufferedReader in = new BufferedReader(new StringReader(responsePOST)))
{
postLine = in.readLine();
String line=in.readLine();
while (line!=null && line.length()>0)
{
if (line.startsWith("Date:"))
postDate=true;
else
postHeaders.add(line);
line=in.readLine();
}
}
String headLine;
boolean headDate=false;
Set<String> headHeaders = new HashSet<>();
try(BufferedReader in = new BufferedReader(new StringReader(responseHEAD)))
{
headLine = in.readLine();
String line=in.readLine();
while (line!=null && line.length()>0)
{
if (line.startsWith("Date:"))
headDate=true;
else
headHeaders.add(line);
line=in.readLine();
}
}
assertThat(postLine,equalTo(headLine));
assertThat(postDate,equalTo(headDate));
assertTrue(postHeaders.equals(headHeaders));
}
@Test
public void testHeadChunked() throws Exception
{
String responsePOST=connector.getResponse("POST /R1?no-content-length=true HTTP/1.1\r\n"+
"Host: localhost\r\n"+
"\r\n",false,1,TimeUnit.SECONDS);
String responseHEAD=connector.getResponse("HEAD /R1?no-content-length=true HTTP/1.1\r\n"+
"Host: localhost\r\n"+
"\r\n",true,1,TimeUnit.SECONDS);
String postLine;
boolean postDate=false;
Set<String> postHeaders = new HashSet<>();
try(BufferedReader in = new BufferedReader(new StringReader(responsePOST)))
{
postLine = in.readLine();
String line=in.readLine();
while (line!=null && line.length()>0)
{
if (line.startsWith("Date:"))
postDate=true;
else
postHeaders.add(line);
line=in.readLine();
}
}
String headLine;
boolean headDate=false;
Set<String> headHeaders = new HashSet<>();
try(BufferedReader in = new BufferedReader(new StringReader(responseHEAD)))
{
headLine = in.readLine();
String line=in.readLine();
while (line!=null && line.length()>0)
{
if (line.startsWith("Date:"))
headDate=true;
else
headHeaders.add(line);
line=in.readLine();
}
}
assertThat(postLine,equalTo(headLine));
assertThat(postDate,equalTo(headDate));
assertTrue(postHeaders.equals(headHeaders));
}
@Test
public void testBadHostPort() throws Exception
{
Log.getLogger(HttpParser.class).info("badMessage: Number formate exception expected ...");
String response;
response=connector.getResponses("GET http://localhost:EXPECTED_NUMBER_FORMAT_EXCEPTION/ HTTP/1.1\r\n"+
"Host: localhost\r\n"+
"Connection: close\r\n"+
"\r\n");
checkContains(response,0,"HTTP/1.1 400");
}
@Test
public void testNoHost() throws Exception
{
String response;
response=connector.getResponse("GET / HTTP/1.1\r\n"+
"\r\n");
checkContains(response,0,"HTTP/1.1 400");
}
@Test
public void testEmptyHost() throws Exception
{
String response;
response=connector.getResponse("GET / HTTP/1.1\r\n"+
"Host:\r\n"+
"\r\n");
checkContains(response,0,"HTTP/1.1 200");
}
@Test
public void testBadURIencoding() throws Exception
{
Log.getLogger(HttpParser.class).info("badMessage: bad encoding expected ...");
String response;
try(StacklessLogging stackless = new StacklessLogging(HttpParser.class))
{
response=connector.getResponse("GET /bad/encoding%1 HTTP/1.1\r\n"+
"Host: localhost\r\n"+
"Connection: close\r\n"+
"\r\n");
checkContains(response,0,"HTTP/1.1 400");
}
}
@Test
public void testBadUTF8FallsbackTo8859() throws Exception
{
Log.getLogger(HttpParser.class).info("badMessage: bad encoding expected ...");
String response;
response=connector.getResponses("GET /foo/bar%c0%00 HTTP/1.1\r\n"+
"Host: localhost\r\n"+
"Connection: close\r\n"+
"\r\n");
checkContains(response,0,"HTTP/1.1 200"); //now fallback to iso-8859-1
response=connector.getResponses("GET /bad/utf8%c1 HTTP/1.1\r\n"+
"Host: localhost\r\n"+
"Connection: close\r\n"+
"\r\n");
checkContains(response,0,"HTTP/1.1 200"); //now fallback to iso-8859-1
}
@Test
public void testAutoFlush() throws Exception
{
int offset=0;
String response = connector.getResponses("GET /R1 HTTP/1.1\r\n" +
"Host: localhost\r\n" +
"Transfer-Encoding: chunked\r\n" +
"Content-Type: text/plain\r\n" +
"Connection: close\r\n" +
"\r\n" +
"5;\r\n" +
"12345\r\n" +
"0;\r\n" +
"\r\n");
offset = checkContains(response,offset,"HTTP/1.1 200");
checkNotContained(response,offset,"IgnoreMe");
offset = checkContains(response,offset,"/R1");
checkContains(response,offset,"12345");
}
@Test
public void testEmptyFlush() throws Exception
{
server.stop();
server.setHandler(new AbstractHandler()
{
@Override
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
response.setStatus(200);
OutputStream out =response.getOutputStream();
out.flush();
out.flush();
}
});
server.start();
String response=connector.getResponses("GET / HTTP/1.1\r\n"+
"Host: localhost\r\n"+
"Connection: close\r\n"+
"\r\n");
assertThat(response, Matchers.containsString("200 OK"));
}
@Test
public void testCharset() throws Exception
{
String response=null;
try
{
int offset=0;
response=connector.getResponses("GET /R1 HTTP/1.1\r\n"+
"Host: localhost\r\n"+
"Transfer-Encoding: chunked\r\n"+
"Content-Type: text/plain; charset=utf-8\r\n"+
"Connection: close\r\n"+
"\r\n"+
"5;\r\n"+
"12345\r\n"+
"0;\r\n" +
"\r\n");
offset = checkContains(response,offset,"HTTP/1.1 200");
offset = checkContains(response,offset,"/R1");
offset = checkContains(response,offset,"encoding=UTF-8");
checkContains(response,offset,"12345");
offset=0;
response=connector.getResponses("GET /R1 HTTP/1.1\r\n"+
"Host: localhost\r\n"+
"Transfer-Encoding: chunked\r\n"+
"Content-Type: text/plain; charset = iso-8859-1 ; other=value\r\n"+
"Connection: close\r\n"+
"\r\n"+
"5;\r\n"+
"12345\r\n"+
"0;\r\n" +
"\r\n");
offset = checkContains(response,offset,"HTTP/1.1 200");
offset = checkContains(response,offset,"encoding=iso-8859-1");
offset = checkContains(response,offset,"/R1");
checkContains(response,offset,"12345");
offset=0;
response=connector.getResponses("GET /R1 HTTP/1.1\r\n"+
"Host: localhost\r\n"+
"Transfer-Encoding: chunked\r\n"+
"Content-Type: text/plain; charset=unknown\r\n"+
"Connection: close\r\n"+
"\r\n"+
"5;\r\n"+
"12345\r\n"+
"0;\r\n" +
"\r\n");
offset = checkContains(response,offset,"HTTP/1.1 200");
offset = checkContains(response,offset,"encoding=unknown");
offset = checkContains(response,offset,"/R1");
checkContains(response,offset,"UnsupportedEncodingException");
}
catch(Exception e)
{
if(response != null)
System.err.println(response);
throw e;
}
}
@Test
public void testUnconsumed() throws Exception
{
int offset=0;
String requests =
"GET /R1?read=4 HTTP/1.1\r\n" +
"Host: localhost\r\n" +
"Transfer-Encoding: chunked\r\n" +
"Content-Type: text/plain; charset=utf-8\r\n" +
"\r\n" +
"5;\r\n" +
"12345\r\n" +
"5;\r\n" +
"67890\r\n" +
"0;\r\n" +
"\r\n" +
"GET /R2 HTTP/1.1\r\n" +
"Host: localhost\r\n" +
"Content-Type: text/plain; charset=utf-8\r\n" +
"Content-Length: 10\r\n" +
"Connection: close\r\n" +
"\r\n" +
"abcdefghij\r\n";
String response = connector.getResponses(requests);
offset = checkContains(response,offset,"HTTP/1.1 200");
offset = checkContains(response,offset,"pathInfo=/R1");
offset = checkContains(response,offset,"1234");
checkNotContained(response,offset,"56789");
offset = checkContains(response,offset,"HTTP/1.1 200");
offset = checkContains(response,offset,"pathInfo=/R2");
offset = checkContains(response,offset,"encoding=UTF-8");
checkContains(response,offset,"abcdefghij");
}
@Test
public void testUnconsumedTimeout() throws Exception
{
connector.setIdleTimeout(500);
int offset=0;
String requests=
"GET /R1?read=4 HTTP/1.1\r\n"+
"Host: localhost\r\n"+
"Transfer-Encoding: chunked\r\n"+
"Content-Type: text/plain; charset=utf-8\r\n"+
"\r\n"+
"5;\r\n"+
"12345\r\n";
long start=System.currentTimeMillis();
String response = connector.getResponses(requests, 2000, TimeUnit.MILLISECONDS);
if ((System.currentTimeMillis()-start)>=2000)
Assert.fail();
offset = checkContains(response,offset,"HTTP/1.1 200");
offset = checkContains(response,offset,"pathInfo=/R1");
offset = checkContains(response,offset,"1234");
checkNotContained(response,offset,"56789");
}
@Test
public void testUnconsumedErrorRead() throws Exception
{
int offset=0;
String requests=
"GET /R1?read=1&error=499 HTTP/1.1\r\n"+
"Host: localhost\r\n"+
"Transfer-Encoding: chunked\r\n"+
"Content-Type: text/plain; charset=utf-8\r\n"+
"\r\n"+
"5;\r\n"+
"12345\r\n"+
"5;\r\n"+
"67890\r\n"+
"0;\r\n" +
"\r\n"+
"GET /R2 HTTP/1.1\r\n"+
"Host: localhost\r\n"+
"Content-Type: text/plain; charset=utf-8\r\n"+
"Content-Length: 10\r\n"+
"Connection: close\r\n"+
"\r\n"+
"abcdefghij\r\n";
String response = connector.getResponses(requests);
offset = checkContains(response,offset,"HTTP/1.1 499");
offset = checkContains(response,offset,"HTTP/1.1 200");
offset = checkContains(response,offset,"/R2");
offset = checkContains(response,offset,"encoding=UTF-8");
checkContains(response,offset,"abcdefghij");
}
@Test
public void testUnconsumedErrorStream() throws Exception
{
int offset=0;
String requests=
"GET /R1?error=599 HTTP/1.1\r\n"+
"Host: localhost\r\n"+
"Transfer-Encoding: chunked\r\n"+
"Content-Type: application/data; charset=utf-8\r\n"+
"\r\n"+
"5;\r\n"+
"12345\r\n"+
"5;\r\n"+
"67890\r\n"+
"0;\r\n" +
"\r\n"+
"GET /R2 HTTP/1.1\r\n"+
"Host: localhost\r\n"+
"Content-Type: text/plain; charset=utf-8\r\n"+
"Content-Length: 10\r\n"+
"Connection: close\r\n"+
"\r\n"+
"abcdefghij\r\n";
String response = connector.getResponses(requests);
offset = checkContains(response,offset,"HTTP/1.1 599");
offset = checkContains(response,offset,"HTTP/1.1 200");
offset = checkContains(response,offset,"/R2");
offset = checkContains(response,offset,"encoding=UTF-8");
checkContains(response,offset,"abcdefghij");
}
@Test
public void testUnconsumedException() throws Exception
{
int offset=0;
String requests="GET /R1?read=1&ISE=true HTTP/1.1\r\n"+
"Host: localhost\r\n"+
"Transfer-Encoding: chunked\r\n"+
"Content-Type: text/plain; charset=utf-8\r\n"+
"\r\n"+
"5;\r\n"+
"12345\r\n"+
"5;\r\n"+
"67890\r\n"+
"0;\r\n" +
"\r\n"+
"GET /R2 HTTP/1.1\r\n"+
"Host: localhost\r\n"+
"Content-Type: text/plain; charset=utf-8\r\n"+
"Content-Length: 10\r\n"+
"\r\n"+
"abcdefghij\r\n";
Logger logger = Log.getLogger(HttpChannel.class);
try (StacklessLogging stackless = new StacklessLogging(logger))
{
logger.info("EXPECTING: java.lang.IllegalStateException...");
String response = connector.getResponses(requests);
offset = checkContains(response,offset,"HTTP/1.1 500");
offset = checkContains(response,offset,"Connection: close");
checkNotContained(response,offset,"HTTP/1.1 200");
}
}
@Test
public void testConnection() throws Exception
{
String response=null;
try
{
int offset=0;
response=connector.getResponse("GET /R1 HTTP/1.1\r\n"+
"Host: localhost\r\n"+
"Connection: TE, close\r\n"+
"Transfer-Encoding: chunked\r\n"+
"Content-Type: text/plain; charset=utf-8\r\n"+
"\r\n"+
"5;\r\n"+
"12345\r\n"+
"0;\r\n" +
"\r\n");
checkContains(response,offset,"Connection: close");
}
catch (Exception e)
{
if(response != null)
System.err.println(response);
throw e;
}
}
/**
* Creates a request header over 1k in size, by creating a single header entry with an huge value.
* @throws Exception if test failure
*/
@Test
public void testOversizedBuffer() throws Exception
{
String response = null;
try
{
int offset = 0;
String cookie = "thisisastringthatshouldreachover1kbytes";
for (int i=0;i<100;i++)
cookie+="xxxxxxxxxxxx";
response = connector.getResponses("GET / HTTP/1.1\r\n"+
"Host: localhost\r\n" +
"Cookie: "+cookie+"\r\n"+
"\r\n"
);
checkContains(response, offset, "HTTP/1.1 431");
}
catch(Exception e)
{
if(response != null)
System.err.println(response);
throw e;
}
}
/**
* Creates a request header with over 1000 entries.
* @throws Exception if test failure
*/
@Test
public void testExcessiveHeader() throws Exception
{
int offset = 0;
StringBuilder request = new StringBuilder();
request.append("GET / HTTP/1.1\r\n");
request.append("Host: localhost\r\n");
request.append("Cookie: thisisastring\r\n");
for(int i=0; i<1000; i++) {
request.append(String.format("X-Header-%04d: %08x\r\n", i, i));
}
request.append("\r\n");
String response = connector.getResponses(request.toString());
offset = checkContains(response, offset, "HTTP/1.1 431");
checkContains(response, offset, "<h1>Bad Message 431</h1>");
}
@Test
public void testOversizedResponse() throws Exception
{
String str = "thisisastringthatshouldreachover1kbytes-";
for (int i=0;i<500;i++)
str+="xxxxxxxxxxxx";
final String longstr = str;
final CountDownLatch checkError = new CountDownLatch(1);
String response = null;
server.stop();
server.setHandler(new DumpHandler()
{
@Override
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
baseRequest.setHandled(true);
response.setHeader(HttpHeader.CONTENT_TYPE.toString(),MimeTypes.Type.TEXT_HTML.toString());
response.setHeader("LongStr", longstr);
PrintWriter writer = response.getWriter();
writer.write("<html><h1>FOO</h1></html>");
writer.flush();
if (writer.checkError())
checkError.countDown();
response.flushBuffer();
}
});
server.start();
Logger logger = Log.getLogger(HttpChannel.class);
try (StacklessLogging stackless = new StacklessLogging(logger))
{
logger.info("Expect IOException: Response header too large...");
response = connector.getResponses("GET / HTTP/1.1\r\n"+
"Host: localhost\r\n" +
"\r\n"
);
checkContains(response, 0, "HTTP/1.1 500");
assertTrue(checkError.await(1,TimeUnit.SECONDS));
}
catch(Exception e)
{
if(response != null)
System.err.println(response);
throw e;
}
}
@Test
public void testAsterisk() throws Exception
{
String response = null;
try (StacklessLogging stackless = new StacklessLogging(HttpParser.LOG))
{
int offset=0;
response=connector.getResponses("OPTIONS * HTTP/1.1\r\n"+
"Host: localhost\r\n"+
"Transfer-Encoding: chunked\r\n"+
"Content-Type: text/plain; charset=utf-8\r\n"+
"Connection: close\r\n"+
"\r\n"+
"5;\r\n"+
"12345\r\n"+
"0;\r\n" +
"\r\n");
checkContains(response,offset,"HTTP/1.1 200");
offset=0;
response=connector.getResponses("GET * HTTP/1.1\r\n"+
"Host: localhost\r\n"+
"Transfer-Encoding: chunked\r\n"+
"Content-Type: text/plain; charset=utf-8\r\n"+
"Connection: close\r\n"+
"\r\n"+
"5;\r\n"+
"12345\r\n"+
"0;\r\n" +
"\r\n");
checkContains(response,offset,"HTTP/1.1 400");
offset=0;
response=connector.getResponses("GET ** HTTP/1.1\r\n"+
"Host: localhost\r\n"+
"Transfer-Encoding: chunked\r\n"+
"Content-Type: text/plain; charset=utf-8\r\n"+
"Connection: close\r\n"+
"\r\n"+
"5;\r\n"+
"12345\r\n"+
"0;\r\n" +
"\r\n");
checkContains(response,offset,"HTTP/1.1 400 Bad Request");
}
catch (Exception e)
{
if(response != null)
System.err.println(response);
throw e;
}
}
@Test
public void testCONNECT() throws Exception
{
String response = null;
try
{
int offset=0;
response=connector.getResponses("CONNECT www.webtide.com:8080 HTTP/1.1\r\n"+
"Host: myproxy:8888\r\n"+
"\r\n",200,TimeUnit.MILLISECONDS);
checkContains(response,offset,"HTTP/1.1 200");
}
catch (Exception e)
{
if(response != null)
System.err.println(response);
throw e;
}
}
private int checkContains(String s,int offset,String c)
{
Assert.assertThat(s.substring(offset),Matchers.containsString(c));
return s.indexOf(c,offset);
}
private void checkNotContained(String s,int offset,String c)
{
Assert.assertThat(s.substring(offset),Matchers.not(Matchers.containsString(c)));
}
}