| /* | |
| * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved. | |
| * | |
| * This program and the accompanying materials are made available under the | |
| * terms of the Eclipse Public License v. 2.0, which is available at | |
| * http://www.eclipse.org/legal/epl-2.0. | |
| * | |
| * This Source Code may also be made available under the following Secondary | |
| * Licenses when the conditions for such availability set forth in the | |
| * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, | |
| * version 2 with the GNU Classpath Exception, which is available at | |
| * https://www.gnu.org/software/classpath/license.html. | |
| * | |
| * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 | |
| */ | |
| import java.io.*; | |
| import java.net.*; | |
| import com.sun.ejte.ccl.reporter.*; | |
| import org.apache.catalina.startup.SimpleHttpClient; | |
| /* | |
| * Unit test for https://issues.apache.org/bugzilla/show_bug.cgi?id=49779 | |
| * 501 Method not implemented with successive POST requests | |
| */ | |
| public class WebTest { | |
| private static final String TEST_NAME = | |
| "test-form-authenticator"; | |
| private static final SimpleReporterAdapter stat = | |
| new SimpleReporterAdapter("appserv-tests"); | |
| private String host; | |
| private int port; | |
| private String contextRoot; | |
| private String adminUser; | |
| private String adminPassword; | |
| public WebTest(String[] args) { | |
| host = args[0]; | |
| port = Integer.parseInt(args[1]); | |
| contextRoot = args[2]; | |
| adminUser = args[3]; | |
| adminPassword = args[4]; | |
| } | |
| public static void main(String[] args) { | |
| stat.addDescription("Unit test for Tomcat bug 49779"); | |
| WebTest webTest = new WebTest(args); | |
| try { | |
| webTest.run(); | |
| stat.addStatus(TEST_NAME, stat.PASS); | |
| } catch( Exception ex) { | |
| ex.printStackTrace(); | |
| stat.addStatus(TEST_NAME, stat.FAIL); | |
| } | |
| stat.printSummary(); | |
| } | |
| public void run() throws Exception { | |
| testGet(); | |
| testPostNoContinue(); | |
| testPostWithContinue(); | |
| testPostNoContinuePostRedirect(); | |
| testPostWithContinuePostRedirect(); | |
| } | |
| public void testGet() throws Exception { | |
| doTest("GET", "GET", false); | |
| } | |
| public void testPostNoContinue() throws Exception { | |
| doTest("POST", "GET", false); | |
| } | |
| public void testPostWithContinue() throws Exception { | |
| doTest("POST", "GET", true); | |
| } | |
| // Bugzilla Bug 49779 | |
| public void testPostNoContinuePostRedirect() throws Exception { | |
| doTest("POST", "POST", false); | |
| } | |
| // Bugzilla Bug 49779 | |
| public void testPostWithContinuePostRedirect() throws Exception { | |
| doTest("POST", "POST", true); | |
| } | |
| public void doTest(String resourceMethod, String redirectMethod, | |
| boolean useContinue) throws Exception { | |
| FormAuthClient client = new FormAuthClient(); | |
| // First request for authenticated resource | |
| client.setUseContinue(useContinue); | |
| client.doResourceRequest(resourceMethod); | |
| assertTrue(client.isResponse200()); | |
| assertTrue(client.isResponseBodyOK()); | |
| client.reset(); | |
| // Second request for the login page | |
| client.setUseContinue(useContinue); | |
| client.doLoginRequest(); | |
| assertTrue(client.isResponse302()); | |
| assertTrue(client.isResponseBodyOK()); | |
| client.reset(); | |
| // Third request - follow the redirect | |
| client.doResourceRequest(redirectMethod); | |
| if ("POST".equals(redirectMethod)) { | |
| client.setUseContinue(useContinue); | |
| } | |
| assertTrue(client.isResponse200()); | |
| assertTrue(client.isResponseBodyOK()); | |
| client.reset(); | |
| // Subsequent requests - direct to the resource | |
| for (int i = 0; i < 5; i++) { | |
| client.setUseContinue(useContinue); | |
| client.doResourceRequest(resourceMethod); | |
| assertTrue(client.isResponse200()); | |
| assertTrue(client.isResponseBodyOK()); | |
| client.reset(); | |
| } | |
| } | |
| private static void assertTrue(boolean status) { | |
| if (!status) { | |
| throw new RuntimeException(); | |
| } | |
| } | |
| private final class FormAuthClient extends SimpleHttpClient { | |
| private static final String LOGIN_PAGE = "j_security_check"; | |
| private String protectedPage = "index.jsp"; | |
| private String protectedLocation = contextRoot; | |
| private int requestCount = 0; | |
| private String sessionId = null; | |
| private FormAuthClient() { | |
| setHost(host); | |
| setPort(port); | |
| } | |
| private void doResourceRequest(String method) throws Exception { | |
| StringBuilder requestHead = new StringBuilder(128); | |
| String requestTail; | |
| requestHead.append(method).append(" ").append(protectedLocation) | |
| .append("/").append(protectedPage); | |
| if ("GET".equals(method)) { | |
| requestHead.append("?role=bar"); | |
| } | |
| requestHead.append(" HTTP/1.1").append(CRLF); | |
| requestHead.append("Host: " + host).append(CRLF); | |
| requestHead.append("Connection: close").append(CRLF); | |
| if (getUseContinue()) { | |
| requestHead.append("Expect: 100-continue").append(CRLF); | |
| } | |
| if (sessionId != null) { | |
| requestHead.append("Cookie: JSESSIONID=").append(sessionId) | |
| .append(CRLF); | |
| } | |
| if ("POST".equals(method)) { | |
| requestHead.append( | |
| "Content-Type: application/x-www-form-urlencoded") | |
| .append(CRLF); | |
| requestHead.append("Content-length: 8").append(CRLF); | |
| requestHead.append(CRLF); | |
| requestTail = "role=bar"; | |
| } else { | |
| requestTail = CRLF; | |
| } | |
| String request[] = new String[2]; | |
| request[0] = requestHead.toString(); | |
| request[1] = requestTail; | |
| doRequest(request); | |
| } | |
| private void doLoginRequest() throws Exception { | |
| StringBuilder requestHead = new StringBuilder(128); | |
| requestHead.append("POST ").append(protectedLocation) | |
| .append("/").append(LOGIN_PAGE).append(" HTTP/1.1").append(CRLF); | |
| requestHead.append("Host: " + host).append(CRLF); | |
| requestHead.append("Connection: close").append(CRLF); | |
| if (getUseContinue()) { | |
| requestHead.append("Expect: 100-continue").append(CRLF); | |
| } | |
| if (sessionId != null) { | |
| requestHead.append("Cookie: JSESSIONID=").append(sessionId) | |
| .append(CRLF); | |
| } | |
| requestHead.append( | |
| "Content-Type: application/x-www-form-urlencoded").append( | |
| CRLF); | |
| requestHead.append("Content-length: 35").append(CRLF); | |
| requestHead.append(CRLF); | |
| String request[] = new String[2]; | |
| request[0] = requestHead.toString(); | |
| request[1] = "j_username=" + adminUser + "&j_password=" + adminPassword; | |
| doRequest(request); | |
| } | |
| private void doRequest(String request[]) throws Exception { | |
| setRequest(request); | |
| try { | |
| connect(); | |
| processRequest(); | |
| String newSessionId = getSessionId(); | |
| if (newSessionId != null) { | |
| sessionId = newSessionId; | |
| } | |
| } finally { | |
| disconnect(); | |
| } | |
| requestCount++; | |
| } | |
| @Override | |
| public boolean isResponseBodyOK() { | |
| if (requestCount == 1) { | |
| // First request should result in the login page | |
| assertContains(getResponseBody(), "A JSP Login Page"); | |
| return true; | |
| } else if (requestCount == 2) { | |
| // Second request should result in a redirect | |
| return true; | |
| } else { | |
| // Subsequent requests should result in the protected page | |
| // The role parameter should have reached the page | |
| String body = getResponseBody(); | |
| assertContains(body, "Hello javaee, bar"); | |
| /* | |
| assertContains(body, | |
| "<input type=\"text\" name=\"role\" value=\"bar\""); | |
| */ | |
| return true; | |
| } | |
| } | |
| private void assertContains(String body, String expected) { | |
| if (!body.contains(expected)) { | |
| throw new RuntimeException("Response body check failure.\n" | |
| + "Expected to contain substring: [" + expected | |
| + "]\nActual: [" + body + "]"); | |
| } | |
| } | |
| } | |
| } |