init
This commit is contained in:
691
test/org/apache/coyote/http11/TestHttp11InputBuffer.java
Normal file
691
test/org/apache/coyote/http11/TestHttp11InputBuffer.java
Normal file
@@ -0,0 +1,691 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.coyote.http11;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Enumeration;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.apache.catalina.Context;
|
||||
import org.apache.catalina.connector.Connector;
|
||||
import org.apache.catalina.startup.SimpleHttpClient;
|
||||
import org.apache.catalina.startup.TesterServlet;
|
||||
import org.apache.catalina.startup.Tomcat;
|
||||
import org.apache.catalina.startup.TomcatBaseTest;
|
||||
|
||||
public class TestHttp11InputBuffer extends TomcatBaseTest {
|
||||
|
||||
/**
|
||||
* Test case for https://bz.apache.org/bugzilla/show_bug.cgi?id=48839
|
||||
*/
|
||||
@Test
|
||||
public void testBug48839() {
|
||||
|
||||
Bug48839Client client = new Bug48839Client();
|
||||
|
||||
client.doRequest();
|
||||
Assert.assertTrue(client.isResponse200());
|
||||
Assert.assertTrue(client.isResponseBodyOK());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Bug 48839 test client.
|
||||
*/
|
||||
private class Bug48839Client extends SimpleHttpClient {
|
||||
|
||||
private Exception doRequest() {
|
||||
|
||||
Tomcat tomcat = getTomcatInstance();
|
||||
|
||||
Context root = tomcat.addContext("", TEMP_DIR);
|
||||
Tomcat.addServlet(root, "Bug48839", new Bug48839Servlet());
|
||||
root.addServletMappingDecoded("/test", "Bug48839");
|
||||
|
||||
try {
|
||||
tomcat.start();
|
||||
setPort(tomcat.getConnector().getLocalPort());
|
||||
|
||||
// Open connection
|
||||
connect();
|
||||
|
||||
String[] request = new String[1];
|
||||
request[0] =
|
||||
"GET http://localhost:8080/test HTTP/1.1" + CRLF +
|
||||
"Host: localhost:8080" + CRLF +
|
||||
"X-Bug48839: abcd" + CRLF +
|
||||
"\tefgh" + CRLF +
|
||||
"Connection: close" + CRLF +
|
||||
CRLF;
|
||||
|
||||
setRequest(request);
|
||||
processRequest(); // blocks until response has been read
|
||||
|
||||
// Close the connection
|
||||
disconnect();
|
||||
} catch (Exception e) {
|
||||
return e;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isResponseBodyOK() {
|
||||
if (getResponseBody() == null) {
|
||||
return false;
|
||||
}
|
||||
if (!getResponseBody().contains("abcd\tefgh")) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class Bug48839Servlet extends HttpServlet {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* Only interested in the request headers from a GET request
|
||||
*/
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
|
||||
throws ServletException, IOException {
|
||||
// Just echo the header value back as plain text
|
||||
resp.setContentType("text/plain");
|
||||
|
||||
PrintWriter out = resp.getWriter();
|
||||
|
||||
Enumeration<String> values = req.getHeaders("X-Bug48839");
|
||||
while (values.hasMoreElements()) {
|
||||
out.println(values.nextElement());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testBug51557Valid() {
|
||||
|
||||
Bug51557Client client = new Bug51557Client("X-Bug51557Valid", "1234");
|
||||
|
||||
client.doRequest();
|
||||
Assert.assertTrue(client.isResponse200());
|
||||
Assert.assertEquals("1234abcd", client.getResponseBody());
|
||||
Assert.assertTrue(client.isResponseBodyOK());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testBug51557Invalid() {
|
||||
|
||||
Bug51557Client client = new Bug51557Client("X-Bug51557=Invalid", "1234", true);
|
||||
|
||||
client.doRequest();
|
||||
Assert.assertTrue(client.isResponse400());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testBug51557NoColon() {
|
||||
|
||||
Bug51557Client client = new Bug51557Client("X-Bug51557NoColon");
|
||||
|
||||
client.doRequest();
|
||||
Assert.assertTrue(client.isResponse200());
|
||||
Assert.assertEquals("abcd", client.getResponseBody());
|
||||
Assert.assertTrue(client.isResponseBodyOK());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testBug51557SeparatorsInName() throws Exception {
|
||||
char httpSeparators[] = new char[] {
|
||||
'\t', ' ', '\"', '(', ')', ',', '/', ':', ';', '<',
|
||||
'=', '>', '?', '@', '[', '\\', ']', '{', '}' };
|
||||
|
||||
for (char s : httpSeparators) {
|
||||
doTestBug51557CharInName(s);
|
||||
tearDown();
|
||||
setUp();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testBug51557CtlInName() throws Exception {
|
||||
for (int i = 0; i < 31; i++) {
|
||||
doTestBug51557CharInName((char) i);
|
||||
tearDown();
|
||||
setUp();
|
||||
}
|
||||
doTestBug51557CharInName((char) 127);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testBug51557CtlInValue() throws Exception {
|
||||
for (int i = 0; i < 31; i++) {
|
||||
if (i == '\t') {
|
||||
// TAB is allowed
|
||||
continue;
|
||||
}
|
||||
doTestBug51557InvalidCharInValue((char) i);
|
||||
tearDown();
|
||||
setUp();
|
||||
}
|
||||
doTestBug51557InvalidCharInValue((char) 127);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testBug51557ObsTextInValue() throws Exception {
|
||||
for (int i = 128; i < 255; i++) {
|
||||
doTestBug51557ValidCharInValue((char) i);
|
||||
tearDown();
|
||||
setUp();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testBug51557Continuation() {
|
||||
|
||||
Bug51557Client client = new Bug51557Client("X-Bug=51557NoColon",
|
||||
"foo" + SimpleHttpClient.CRLF + " bar");
|
||||
|
||||
client.doRequest();
|
||||
Assert.assertTrue(client.isResponse200());
|
||||
Assert.assertEquals("abcd", client.getResponseBody());
|
||||
Assert.assertTrue(client.isResponseBodyOK());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testBug51557BoundaryStart() {
|
||||
|
||||
Bug51557Client client = new Bug51557Client("=X-Bug51557",
|
||||
"invalid");
|
||||
|
||||
client.doRequest();
|
||||
Assert.assertTrue(client.isResponse200());
|
||||
Assert.assertEquals("abcd", client.getResponseBody());
|
||||
Assert.assertTrue(client.isResponseBodyOK());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testBug51557BoundaryEnd() {
|
||||
|
||||
Bug51557Client client = new Bug51557Client("X-Bug51557=",
|
||||
"invalid");
|
||||
|
||||
client.doRequest();
|
||||
Assert.assertTrue(client.isResponse200());
|
||||
Assert.assertEquals("abcd", client.getResponseBody());
|
||||
Assert.assertTrue(client.isResponseBodyOK());
|
||||
}
|
||||
|
||||
|
||||
private void doTestBug51557CharInName(char s) {
|
||||
Bug51557Client client =
|
||||
new Bug51557Client("X-Bug" + s + "51557", "invalid");
|
||||
|
||||
client.doRequest();
|
||||
Assert.assertTrue(client.isResponse200());
|
||||
Assert.assertEquals("abcd", client.getResponseBody());
|
||||
Assert.assertTrue(client.isResponseBodyOK());
|
||||
}
|
||||
|
||||
|
||||
private void doTestBug51557InvalidCharInValue(char s) {
|
||||
Bug51557Client client =
|
||||
new Bug51557Client("X-Bug51557-Invalid", "invalid" + s + "invalid");
|
||||
|
||||
client.doRequest();
|
||||
Assert.assertTrue("Testing [" + (int) s + "]", client.isResponse200());
|
||||
Assert.assertEquals("Testing [" + (int) s + "]", "abcd", client.getResponseBody());
|
||||
Assert.assertTrue(client.isResponseBodyOK());
|
||||
}
|
||||
|
||||
|
||||
private void doTestBug51557ValidCharInValue(char s) {
|
||||
Bug51557Client client =
|
||||
new Bug51557Client("X-Bug51557-Valid", "valid" + s + "valid");
|
||||
|
||||
client.doRequest();
|
||||
Assert.assertTrue("Testing [" + (int) s + "]", client.isResponse200());
|
||||
Assert.assertEquals("Testing [" + (int) s + "]", "valid" + s + "validabcd", client.getResponseBody());
|
||||
Assert.assertTrue(client.isResponseBodyOK());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Bug 51557 test client.
|
||||
*/
|
||||
private class Bug51557Client extends SimpleHttpClient {
|
||||
|
||||
private final String headerName;
|
||||
private final String headerLine;
|
||||
private final boolean rejectIllegalHeader;
|
||||
|
||||
public Bug51557Client(String headerName) {
|
||||
this.headerName = headerName;
|
||||
this.headerLine = headerName;
|
||||
this.rejectIllegalHeader = false;
|
||||
}
|
||||
|
||||
public Bug51557Client(String headerName, String headerValue) {
|
||||
this(headerName, headerValue, false);
|
||||
}
|
||||
|
||||
public Bug51557Client(String headerName, String headerValue,
|
||||
boolean rejectIllegalHeader) {
|
||||
this.headerName = headerName;
|
||||
this.headerLine = headerName + ": " + headerValue;
|
||||
this.rejectIllegalHeader = rejectIllegalHeader;
|
||||
}
|
||||
|
||||
private Exception doRequest() {
|
||||
|
||||
Tomcat tomcat = getTomcatInstance();
|
||||
|
||||
Context root = tomcat.addContext("", TEMP_DIR);
|
||||
Tomcat.addServlet(root, "Bug51557",
|
||||
new Bug51557Servlet(headerName));
|
||||
root.addServletMappingDecoded("/test", "Bug51557");
|
||||
|
||||
try {
|
||||
Connector connector = tomcat.getConnector();
|
||||
Assert.assertTrue(connector.setProperty(
|
||||
"rejectIllegalHeader", Boolean.toString(rejectIllegalHeader)));
|
||||
tomcat.start();
|
||||
setPort(connector.getLocalPort());
|
||||
|
||||
|
||||
// Open connection
|
||||
connect();
|
||||
|
||||
String[] request = new String[1];
|
||||
request[0] =
|
||||
"GET http://localhost:8080/test HTTP/1.1" + CRLF +
|
||||
"Host: localhost:8080" + CRLF +
|
||||
headerLine + CRLF +
|
||||
"X-Bug51557: abcd" + CRLF +
|
||||
"Connection: close" + CRLF +
|
||||
CRLF;
|
||||
|
||||
setRequest(request);
|
||||
processRequest(); // blocks until response has been read
|
||||
|
||||
// Close the connection
|
||||
disconnect();
|
||||
} catch (Exception e) {
|
||||
return e;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isResponseBodyOK() {
|
||||
if (getResponseBody() == null) {
|
||||
return false;
|
||||
}
|
||||
if (!getResponseBody().contains("abcd")) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class Bug51557Servlet extends HttpServlet {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String invalidHeaderName;
|
||||
|
||||
/**
|
||||
* @param invalidHeaderName The header name should be invalid and
|
||||
* therefore ignored by the header parsing code
|
||||
*/
|
||||
public Bug51557Servlet(String invalidHeaderName) {
|
||||
this.invalidHeaderName = invalidHeaderName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Only interested in the request headers from a GET request
|
||||
*/
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
|
||||
throws ServletException, IOException {
|
||||
// Just echo the header value back as plain text
|
||||
resp.setContentType("text/plain");
|
||||
|
||||
PrintWriter out = resp.getWriter();
|
||||
|
||||
processHeaders(invalidHeaderName, req, out);
|
||||
processHeaders("X-Bug51557", req, out);
|
||||
}
|
||||
|
||||
private void processHeaders(String header, HttpServletRequest req,
|
||||
PrintWriter out) {
|
||||
Enumeration<String> values = req.getHeaders(header);
|
||||
while (values.hasMoreElements()) {
|
||||
out.println(values.nextElement());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test case for new lines at the start of a request. RFC2616
|
||||
* does not permit any, but Tomcat is tolerant of them if they are present.
|
||||
*/
|
||||
@Test
|
||||
public void testNewLines() {
|
||||
|
||||
NewLinesClient client = new NewLinesClient(10);
|
||||
|
||||
client.doRequest();
|
||||
Assert.assertTrue(client.isResponse200());
|
||||
Assert.assertTrue(client.isResponseBodyOK());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test case for new lines at the start of a request. RFC2616
|
||||
* does not permit any, but Tomcat is tolerant of them if they are present.
|
||||
*/
|
||||
@Test
|
||||
public void testNewLinesExcessive() {
|
||||
|
||||
NewLinesClient client = new NewLinesClient(10000);
|
||||
|
||||
// If the connection is closed fast enough, writing the request will
|
||||
// fail and the response won't be read.
|
||||
Exception e = client.doRequest();
|
||||
if (e == null) {
|
||||
Assert.assertTrue(client.getResponseLine(), client.isResponse400());
|
||||
}
|
||||
Assert.assertFalse(client.isResponseBodyOK());
|
||||
}
|
||||
|
||||
|
||||
private class NewLinesClient extends SimpleHttpClient {
|
||||
|
||||
private final String newLines;
|
||||
|
||||
private NewLinesClient(int count) {
|
||||
StringBuilder sb = new StringBuilder(count * 2);
|
||||
for (int i = 0; i < count; i++) {
|
||||
sb.append(CRLF);
|
||||
}
|
||||
newLines = sb.toString();
|
||||
}
|
||||
|
||||
private Exception doRequest() {
|
||||
|
||||
Tomcat tomcat = getTomcatInstance();
|
||||
|
||||
Context root = tomcat.addContext("", TEMP_DIR);
|
||||
Tomcat.addServlet(root, "test", new TesterServlet());
|
||||
root.addServletMappingDecoded("/test", "test");
|
||||
|
||||
try {
|
||||
tomcat.start();
|
||||
setPort(tomcat.getConnector().getLocalPort());
|
||||
|
||||
// Open connection
|
||||
connect();
|
||||
|
||||
String[] request = new String[1];
|
||||
request[0] =
|
||||
newLines +
|
||||
"GET http://localhost:8080/test HTTP/1.1" + CRLF +
|
||||
"Host: localhost:8080" + CRLF +
|
||||
"X-Bug48839: abcd" + CRLF +
|
||||
"\tefgh" + CRLF +
|
||||
"Connection: close" + CRLF +
|
||||
CRLF;
|
||||
|
||||
setRequest(request);
|
||||
processRequest(); // blocks until response has been read
|
||||
|
||||
// Close the connection
|
||||
disconnect();
|
||||
} catch (Exception e) {
|
||||
return e;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isResponseBodyOK() {
|
||||
if (getResponseBody() == null) {
|
||||
return false;
|
||||
}
|
||||
if (!getResponseBody().contains("OK")) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test case for https://bz.apache.org/bugzilla/show_bug.cgi?id=54947
|
||||
*/
|
||||
@Test
|
||||
public void testBug54947() {
|
||||
|
||||
Bug54947Client client = new Bug54947Client();
|
||||
|
||||
client.doRequest();
|
||||
Assert.assertTrue(client.isResponse200());
|
||||
Assert.assertTrue(client.isResponseBodyOK());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Bug 54947 test client.
|
||||
*/
|
||||
private class Bug54947Client extends SimpleHttpClient {
|
||||
|
||||
private Exception doRequest() {
|
||||
|
||||
Tomcat tomcat = getTomcatInstance();
|
||||
|
||||
Context root = tomcat.addContext("", TEMP_DIR);
|
||||
Tomcat.addServlet(root, "Bug54947", new TesterServlet());
|
||||
root.addServletMappingDecoded("/test", "Bug54947");
|
||||
|
||||
try {
|
||||
tomcat.start();
|
||||
setPort(tomcat.getConnector().getLocalPort());
|
||||
|
||||
// Open connection
|
||||
connect();
|
||||
|
||||
String[] request = new String[2];
|
||||
request[0] = "GET http://localhost:8080/test HTTP/1.1" + CR;
|
||||
request[1] = LF +
|
||||
"Host: localhost:8080" + CRLF +
|
||||
"Connection: close" + CRLF +
|
||||
CRLF;
|
||||
|
||||
setRequest(request);
|
||||
processRequest(); // blocks until response has been read
|
||||
|
||||
// Close the connection
|
||||
disconnect();
|
||||
} catch (Exception e) {
|
||||
return e;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isResponseBodyOK() {
|
||||
if (getResponseBody() == null) {
|
||||
return false;
|
||||
}
|
||||
if (!getResponseBody().contains("OK")) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test case for https://bz.apache.org/bugzilla/show_bug.cgi?id=59089
|
||||
*/
|
||||
@Test
|
||||
public void testBug59089() {
|
||||
|
||||
Bug59089Client client = new Bug59089Client();
|
||||
|
||||
client.doRequest();
|
||||
Assert.assertTrue(client.isResponse200());
|
||||
Assert.assertTrue(client.isResponseBodyOK());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Bug 59089 test client.
|
||||
*/
|
||||
private class Bug59089Client extends SimpleHttpClient {
|
||||
|
||||
private Exception doRequest() {
|
||||
|
||||
// Ensure body is read correctly
|
||||
setUseContentLength(true);
|
||||
|
||||
Tomcat tomcat = getTomcatInstance();
|
||||
|
||||
Context root = tomcat.addContext("", TEMP_DIR);
|
||||
Tomcat.addServlet(root, "Bug59089", new TesterServlet());
|
||||
root.addServletMappingDecoded("/test", "Bug59089");
|
||||
|
||||
try {
|
||||
Connector connector = tomcat.getConnector();
|
||||
Assert.assertTrue(connector.setProperty("rejectIllegalHeader", "false"));
|
||||
tomcat.start();
|
||||
setPort(connector.getLocalPort());
|
||||
|
||||
// Open connection
|
||||
connect();
|
||||
|
||||
String[] request = new String[1];
|
||||
request[0] = "GET http://localhost:8080/test HTTP/1.1" + CRLF +
|
||||
"Host: localhost:8080" + CRLF +
|
||||
"X-Header: Ignore" + CRLF +
|
||||
"X-Header" + (char) 130 + ": Broken" + CRLF + CRLF;
|
||||
|
||||
setRequest(request);
|
||||
processRequest(); // blocks until response has been read
|
||||
|
||||
// Close the connection
|
||||
disconnect();
|
||||
} catch (Exception e) {
|
||||
return e;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isResponseBodyOK() {
|
||||
if (getResponseBody() == null) {
|
||||
return false;
|
||||
}
|
||||
if (!getResponseBody().contains("OK")) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testInvalidMethod() {
|
||||
|
||||
InvalidMethodClient client = new InvalidMethodClient();
|
||||
|
||||
client.doRequest();
|
||||
Assert.assertTrue(client.getResponseLine(), client.isResponse400());
|
||||
Assert.assertTrue(client.isResponseBodyOK());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Bug 48839 test client.
|
||||
*/
|
||||
private class InvalidMethodClient extends SimpleHttpClient {
|
||||
|
||||
private Exception doRequest() {
|
||||
|
||||
Tomcat tomcat = getTomcatInstance();
|
||||
|
||||
tomcat.addContext("", TEMP_DIR);
|
||||
|
||||
try {
|
||||
tomcat.start();
|
||||
setPort(tomcat.getConnector().getLocalPort());
|
||||
|
||||
// Open connection
|
||||
connect();
|
||||
|
||||
String[] request = new String[1];
|
||||
request[0] =
|
||||
"GET" + (char) 0 + " /test HTTP/1.1" + CRLF +
|
||||
"Host: localhost:8080" + CRLF +
|
||||
"Connection: close" + CRLF +
|
||||
CRLF;
|
||||
|
||||
setRequest(request);
|
||||
processRequest(); // blocks until response has been read
|
||||
|
||||
// Close the connection
|
||||
disconnect();
|
||||
} catch (Exception e) {
|
||||
return e;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isResponseBodyOK() {
|
||||
if (getResponseBody() == null) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user