| /* |
| * ==================================================================== |
| * |
| * Copyright 2003-2004 The Apache Software Foundation |
| * |
| * Licensed 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. |
| * ==================================================================== |
| * |
| * This software consists of voluntary contributions made by many |
| * individuals on behalf of the Apache Software Foundation. For more |
| * information on the Apache Software Foundation, please see |
| * <http://www.apache.org/>. |
| * |
| * [Additional notices, if required by prior licensing conditions] |
| * |
| */ |
| package org.apache.commons.httpclient; |
| |
| import java.io.IOException; |
| |
| import junit.framework.*; |
| import org.apache.commons.httpclient.methods.*; |
| import org.apache.commons.httpclient.params.HttpMethodParams; |
| import org.apache.commons.httpclient.server.HttpRequestHandler; |
| import org.apache.commons.httpclient.server.ResponseWriter; |
| import org.apache.commons.httpclient.server.SimpleHttpServerConnection; |
| import org.apache.commons.httpclient.server.SimpleRequest; |
| |
| /** |
| * Tests handling of non-compliant responses. |
| * |
| * @author Oleg Kalnichevski |
| * @author Jeff Dever |
| */ |
| public class TestNoncompliant extends HttpClientTestBase { |
| |
| public TestNoncompliant(String s) throws IOException { |
| super(s); |
| } |
| |
| public static Test suite() { |
| TestSuite suite = new TestSuite(TestNoncompliant.class); |
| return suite; |
| } |
| |
| /** |
| * Tests if client is able to recover gracefully when HTTP server or |
| * proxy fails to send 100 status code when expected. The client should |
| * resume sending the request body after a defined timeout without having |
| * received "continue" code. |
| */ |
| public void testNoncompliantPostMethodString() throws Exception { |
| this.server.setRequestHandler(new HttpRequestHandler() { |
| public boolean processRequest(SimpleHttpServerConnection conn, |
| SimpleRequest request) throws IOException { |
| ResponseWriter out = conn.getWriter(); |
| out.println("HTTP/1.1 200 OK"); |
| out.println("Connection: close"); |
| out.println("Content-Length: 0"); |
| out.println(); |
| out.flush(); |
| return true; |
| } |
| }); |
| |
| PostMethod method = new PostMethod("/"); |
| method.getParams().setBooleanParameter( |
| HttpMethodParams.USE_EXPECT_CONTINUE, true); |
| method.setRequestEntity(new StringRequestEntity( |
| "This is data to be sent in the body of an HTTP POST.")); |
| client.executeMethod(method); |
| assertEquals(200, method.getStatusCode()); |
| } |
| |
| /** |
| * Tests that a response status line containing \r and \n is handled. |
| */ |
| public void testNoncompliantStatusLine() { |
| this.server.setRequestHandler(new HttpRequestHandler() { |
| public boolean processRequest(SimpleHttpServerConnection conn, |
| SimpleRequest request) throws IOException { |
| ResponseWriter out = conn.getWriter(); |
| out.println("HTTP/1.1 444 This status message contains\n" |
| + " a newline and a\r" |
| + " carrage return but that should be OK."); |
| out.println("Connection: close"); |
| out.println("Content-Length: 0"); |
| out.println(); |
| out.flush(); |
| return true; |
| } |
| }); |
| GetMethod method = new GetMethod("/"); |
| try { |
| client.executeMethod(method); |
| } catch (Exception e) { |
| e.printStackTrace(); |
| fail("Unexpected exception: " + e.toString()); |
| } |
| assertEquals(444, method.getStatusCode()); |
| } |
| |
| /** |
| * Test if a response to HEAD method from non-compliant server that contains |
| * an unexpected body content can be correctly redirected |
| */ |
| public void testNoncompliantHeadWithResponseBody() throws Exception { |
| final String body = "Test body"; |
| this.server.setRequestHandler(new HttpRequestHandler() { |
| public boolean processRequest(SimpleHttpServerConnection conn, |
| SimpleRequest request) throws IOException { |
| ResponseWriter out = conn.getWriter(); |
| out.println("HTTP/1.1 200 OK"); |
| out.println("Connection: close"); |
| out.println("Content-Length: " + body.length()); |
| out.println(); |
| out.print(body); |
| out.flush(); |
| return true; |
| } |
| }); |
| HeadMethod method = new HeadMethod("/"); |
| method.getParams().setIntParameter( |
| HttpMethodParams.HEAD_BODY_CHECK_TIMEOUT, 50); |
| client.executeMethod(method); |
| assertEquals(200, method.getStatusCode()); |
| method.releaseConnection(); |
| } |
| |
| /** |
| * Test if a response to HEAD method from non-compliant server causes an |
| * HttpException to be thrown |
| */ |
| public void testNoncompliantHeadStrictMode() throws Exception { |
| final String body = "Test body"; |
| this.server.setRequestHandler(new HttpRequestHandler() { |
| public boolean processRequest(SimpleHttpServerConnection conn, |
| SimpleRequest request) throws IOException { |
| ResponseWriter out = conn.getWriter(); |
| out.println("HTTP/1.1 200 OK"); |
| out.println("Connection: close"); |
| out.println("Content-Length: " + body.length()); |
| out.println(); |
| out.print(body); |
| out.flush(); |
| return true; |
| } |
| }); |
| client.getParams().setBooleanParameter( |
| HttpMethodParams.REJECT_HEAD_BODY, true); |
| HeadMethod method = new NoncompliantHeadMethod("/"); |
| method.getParams().setIntParameter( |
| HttpMethodParams.HEAD_BODY_CHECK_TIMEOUT, 50); |
| try { |
| client.executeMethod(method); |
| fail("HttpException should have been thrown"); |
| } catch (HttpException e) { |
| // Expected |
| } |
| method.releaseConnection(); |
| } |
| |
| /** |
| * Tests if client is able to handle gracefully malformed responses |
| * that may not include response body. |
| */ |
| public void testMalformed304Response() throws Exception { |
| this.server.setRequestHandler(new HttpRequestHandler() { |
| public boolean processRequest(SimpleHttpServerConnection conn, |
| SimpleRequest request) throws IOException { |
| conn.setSocketTimeout(20000); |
| ResponseWriter out = conn.getWriter(); |
| out.println("HTTP/1.1 304 OK"); |
| out.println("Connection: keep-alive"); |
| out.println("Content-Length: 100"); |
| out.println(); |
| out.flush(); |
| conn.setKeepAlive(true); |
| return true; |
| } |
| }); |
| |
| GetMethod method = new GetMethod("/"); |
| method.getParams().setSoTimeout(1000); |
| client.executeMethod(method); |
| assertEquals(HttpStatus.SC_NOT_MODIFIED, method.getStatusCode()); |
| method.getResponseBody(); |
| } |
| |
| public void testMalformed204Response() throws Exception { |
| this.server.setRequestHandler(new HttpRequestHandler() { |
| public boolean processRequest(SimpleHttpServerConnection conn, |
| SimpleRequest request) throws IOException { |
| conn.setSocketTimeout(20000); |
| ResponseWriter out = conn.getWriter(); |
| out.println("HTTP/1.1 204 OK"); |
| out.println("Connection: close"); |
| out.println("Content-Length: 100"); |
| out.println(); |
| out.flush(); |
| conn.setKeepAlive(true); |
| return true; |
| } |
| }); |
| |
| GetMethod method = new GetMethod("/"); |
| method.getParams().setSoTimeout(1000); |
| client.executeMethod(method); |
| assertEquals(HttpStatus.SC_NO_CONTENT, method.getStatusCode()); |
| method.getResponseBody(); |
| } |
| |
| } |