Author: markt Date: Wed Aug 28 13:10:49 2013 New Revision: 1518194 URL: http://svn.apache.org/r1518194 Log: Extend the AJP test client to support methods other than GET and implement a simple POST test.
Modified: tomcat/tc7.0.x/trunk/test/org/apache/coyote/ajp/SimpleAjpClient.java tomcat/tc7.0.x/trunk/test/org/apache/coyote/ajp/TestAbstractAjpProcessor.java tomcat/tc7.0.x/trunk/test/org/apache/coyote/ajp/TesterAjpMessage.java Modified: tomcat/tc7.0.x/trunk/test/org/apache/coyote/ajp/SimpleAjpClient.java URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/test/org/apache/coyote/ajp/SimpleAjpClient.java?rev=1518194&r1=1518193&r2=1518194&view=diff ============================================================================== --- tomcat/tc7.0.x/trunk/test/org/apache/coyote/ajp/SimpleAjpClient.java (original) +++ tomcat/tc7.0.x/trunk/test/org/apache/coyote/ajp/SimpleAjpClient.java Wed Aug 28 13:10:49 2013 @@ -67,6 +67,11 @@ public class SimpleAjpClient { * Create a message to request the given URL. */ public TesterAjpMessage createForwardMessage(String url) { + return createForwardMessage(url, 2); + } + + public TesterAjpMessage createForwardMessage(String url, int method) { + TesterAjpMessage message = new TesterAjpMessage(AJP_PACKET_SIZE); message.reset(); @@ -78,7 +83,7 @@ public class SimpleAjpClient { message.appendByte(Constants.JK_AJP13_FORWARD_REQUEST); // HTTP method, GET = 2 - message.appendByte(0x02); + message.appendByte(method); // Protocol message.appendString("http"); @@ -101,26 +106,44 @@ public class SimpleAjpClient { // Is ssl message.appendByte(0x00); - // No other headers or attributes - message.appendInt(0); + return message; + } - // Terminator - message.appendByte(0xFF); - // End the message and set the length + public TesterAjpMessage createBodyMessage(byte[] data) { + + TesterAjpMessage message = new TesterAjpMessage(AJP_PACKET_SIZE); + message.reset(); + + // Set the header bytes + message.getBuffer()[0] = 0x12; + message.getBuffer()[1] = 0x34; + + message.appendBytes(data, 0, data.length); message.end(); return message; } + /** * Sends an TesterAjpMessage to the server and returns the response message. */ - public TesterAjpMessage sendMessage(TesterAjpMessage message) + public TesterAjpMessage sendMessage(TesterAjpMessage headers) throws IOException { - // Send the message + return sendMessage(headers, null); + } + + public TesterAjpMessage sendMessage(TesterAjpMessage headers, + TesterAjpMessage body) throws IOException { + // Send the headers socket.getOutputStream().write( - message.getBuffer(), 0, message.getLen()); + headers.getBuffer(), 0, headers.getLen()); + if (body != null) { + // Send the body of present + socket.getOutputStream().write( + body.getBuffer(), 0, body.getLen()); + } // Read the response return readMessage(); } Modified: tomcat/tc7.0.x/trunk/test/org/apache/coyote/ajp/TestAbstractAjpProcessor.java URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/test/org/apache/coyote/ajp/TestAbstractAjpProcessor.java?rev=1518194&r1=1518193&r2=1518194&view=diff ============================================================================== --- tomcat/tc7.0.x/trunk/test/org/apache/coyote/ajp/TestAbstractAjpProcessor.java (original) +++ tomcat/tc7.0.x/trunk/test/org/apache/coyote/ajp/TestAbstractAjpProcessor.java Wed Aug 28 13:10:49 2013 @@ -16,11 +16,12 @@ */ package org.apache.coyote.ajp; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; +import java.io.File; +import org.junit.Assert; import org.junit.Test; +import org.apache.catalina.Context; import org.apache.catalina.startup.Tomcat; import org.apache.catalina.startup.TomcatBaseTest; @@ -56,8 +57,7 @@ public class TestAbstractAjpProcessor ex tomcat.start(); // Must have a real docBase - just use temp - org.apache.catalina.Context ctx = - tomcat.addContext("", System.getProperty("java.io.tmpdir")); + Context ctx = tomcat.addContext("", System.getProperty("java.io.tmpdir")); Tomcat.addServlet(ctx, "helloWorld", new HelloWorldServlet()); ctx.addServletMapping("/", "helloWorld"); @@ -70,6 +70,8 @@ public class TestAbstractAjpProcessor ex validateCpong(ajpClient.cping()); TesterAjpMessage forwardMessage = ajpClient.createForwardMessage("/"); + // Complete the message - no extra headers required. + forwardMessage.end(); // Two requests for (int i = 0; i < 2; i++) { @@ -90,6 +92,51 @@ public class TestAbstractAjpProcessor ex ajpClient.disconnect(); } + + + @Test + public void testSimplePost() throws Exception { + + Tomcat tomcat = getTomcatInstance(); + + // Use the normal Tomcat ROOT context + File root = new File("test/webapp"); + tomcat.addWebapp("", root.getAbsolutePath()); + + tomcat.start(); + + SimpleAjpClient ajpClient = new SimpleAjpClient(); + ajpClient.setPort(getPort()); + ajpClient.connect(); + + validateCpong(ajpClient.cping()); + + TesterAjpMessage forwardMessage = + ajpClient.createForwardMessage("/echo-params.jsp", 4); + forwardMessage.addHeader(0xA008, "9"); + forwardMessage.addHeader(0xA007, "application/x-www-form-urlencoded"); + forwardMessage.end(); + + TesterAjpMessage bodyMessage = + ajpClient.createBodyMessage("test=data".getBytes()); + + TesterAjpMessage responseHeaders = + ajpClient.sendMessage(forwardMessage, bodyMessage); + + // Expect 3 messages: headers, body, end + validateResponseHeaders(responseHeaders, 200); + // Skip the body + TesterAjpMessage responseBody = ajpClient.readMessage(); + validateResponseBody(responseBody, "test - data"); + validateResponseEnd(ajpClient.readMessage(), true); + + // Double check the connection is still open + validateCpong(ajpClient.cping()); + + ajpClient.disconnect(); + } + + /** * Process response header packet and checks the status. Any other data is * ignored. @@ -97,20 +144,20 @@ public class TestAbstractAjpProcessor ex private void validateResponseHeaders(TesterAjpMessage message, int expectedStatus) throws Exception { // First two bytes should always be AB - assertEquals((byte) 'A', message.buf[0]); - assertEquals((byte) 'B', message.buf[1]); + Assert.assertEquals((byte) 'A', message.buf[0]); + Assert.assertEquals((byte) 'B', message.buf[1]); // Set the start position and read the length message.processHeader(false); // Check the length - assertTrue(message.len > 0); + Assert.assertTrue(message.len > 0); // Should be a header message - assertEquals(0x04, message.readByte()); + Assert.assertEquals(0x04, message.readByte()); // Check status - assertEquals(expectedStatus, message.readInt()); + Assert.assertEquals(expectedStatus, message.readInt()); // Read the status message message.readString(); @@ -132,51 +179,52 @@ public class TestAbstractAjpProcessor ex */ private void validateResponseBody(TesterAjpMessage message, String expectedBody) throws Exception { - assertEquals((byte) 'A', message.buf[0]); - assertEquals((byte) 'B', message.buf[1]); + + Assert.assertEquals((byte) 'A', message.buf[0]); + Assert.assertEquals((byte) 'B', message.buf[1]); // Set the start position and read the length message.processHeader(false); // Should be a body chunk message - assertEquals(0x03, message.readByte()); + Assert.assertEquals(0x03, message.readByte()); int len = message.readInt(); - assertTrue(len > 0); + Assert.assertTrue(len > 0); String body = message.readString(len); - assertEquals(expectedBody, body); + Assert.assertTrue(body.contains(expectedBody)); } private void validateResponseEnd(TesterAjpMessage message, boolean expectedReuse) { - assertEquals((byte) 'A', message.buf[0]); - assertEquals((byte) 'B', message.buf[1]); + Assert.assertEquals((byte) 'A', message.buf[0]); + Assert.assertEquals((byte) 'B', message.buf[1]); message.processHeader(false); // Should be an end body message - assertEquals(0x05, message.readByte()); + Assert.assertEquals(0x05, message.readByte()); // Check the length - assertEquals(2, message.getLen()); + Assert.assertEquals(2, message.getLen()); boolean reuse = false; if (message.readByte() > 0) { reuse = true; } - assertEquals(Boolean.valueOf(expectedReuse), Boolean.valueOf(reuse)); + Assert.assertEquals(Boolean.valueOf(expectedReuse), Boolean.valueOf(reuse)); } private void validateCpong(TesterAjpMessage message) throws Exception { // First two bytes should always be AB - assertEquals((byte) 'A', message.buf[0]); - assertEquals((byte) 'B', message.buf[1]); + Assert.assertEquals((byte) 'A', message.buf[0]); + Assert.assertEquals((byte) 'B', message.buf[1]); // CPONG should have a message length of 1 // This effectively checks the next two bytes - assertEquals(1, message.getLen()); + Assert.assertEquals(1, message.getLen()); // Data should be the value 9 - assertEquals(9, message.buf[4]); + Assert.assertEquals(9, message.buf[4]); } } Modified: tomcat/tc7.0.x/trunk/test/org/apache/coyote/ajp/TesterAjpMessage.java URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/test/org/apache/coyote/ajp/TesterAjpMessage.java?rev=1518194&r1=1518193&r2=1518194&view=diff ============================================================================== --- tomcat/tc7.0.x/trunk/test/org/apache/coyote/ajp/TesterAjpMessage.java (original) +++ tomcat/tc7.0.x/trunk/test/org/apache/coyote/ajp/TesterAjpMessage.java Wed Aug 28 13:10:49 2013 @@ -16,6 +16,9 @@ */ package org.apache.coyote.ajp; +import java.util.ArrayList; +import java.util.List; + /** * Extends {@link AjpMessage} to provide additional methods for reading from the * message. @@ -24,6 +27,9 @@ package org.apache.coyote.ajp; */ public class TesterAjpMessage extends AjpMessage { + private final List<Header> headers = new ArrayList<Header>(); + + public TesterAjpMessage(int packetSize) { super(packetSize); } @@ -68,8 +74,29 @@ public class TesterAjpMessage extends Aj } } + + public void addHeader(int code, String value) { + headers.add(new Header(code, value)); + } + + + public void addHeader(String name, String value) { + headers.add(new Header(name, value)); + } + + @Override public void end() { + // Add the header count + appendInt(headers.size()); + + for (Header header : headers) { + header.append(this); + } + + // Terminator + appendByte(0xFF); + len = pos; int dLen = len - 4; @@ -80,4 +107,39 @@ public class TesterAjpMessage extends Aj } + @Override + public void reset() { + super.reset(); + headers.clear(); + } + + + + + private static class Header { + private final int code; + private final String name; + private final String value; + + public Header(int code, String value) { + this.code = code; + this.name = null; + this.value = value; + } + + public Header(String name, String value) { + this.code = 0; + this.name = name; + this.value = value; + } + + public void append(TesterAjpMessage message) { + if (code == 0) { + message.appendString(name); + } else { + message.appendInt(code); + } + message.appendString(value); + } + } } --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org