import org.apache.cxf.helpers.IOUtils; import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.ByteArrayEntity; import org.apache.http.entity.InputStreamEntity; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.client.DefaultHttpRequestRetryHandler; import org.apache.http.params.HttpConnectionParams; import org.apache.http.params.HttpParams; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import java.io.*; import java.net.*; import java.util.ArrayList; import java.util.Arrays; /** * @author $Author: $ * @version $Revision: $ $Date: $ */ public class HttpURLConnectionTest { class Control { ServerSocket serverSocket = null; boolean stop = false; boolean respondWith100Continue = false; boolean write100ContinueTWice = false; String request = null; String response = null; } private Thread serverThread = null; private volatile Control control = null; @BeforeMethod public void startServerSocket() throws Exception { control = new Control(); control.serverSocket = new ServerSocket(); control.serverSocket.setReuseAddress(true); control.serverSocket.bind(new InetSocketAddress("127.0.0.1", 54321)); Runnable runnable = new Runnable() { @Override public void run() { while (!control.stop) { try { Socket socket = control.serverSocket.accept(); InputStream inputStream = socket.getInputStream(); InputStreamReader inputStreamReader = new InputStreamReader(inputStream); StringBuilder stringBuilder = new StringBuilder(); byte b = -1; while (true) { b = (byte)inputStreamReader.read(); stringBuilder.append((char)b); if (stringBuilder.length() >= 4) { char[] lastBytes = new char[4]; stringBuilder.getChars(stringBuilder.length() - 4, stringBuilder.length(), lastBytes, 0); if (Arrays.equals(lastBytes, new char[]{'\r', '\n', '\r', '\n'})) { break; } } } OutputStream outputStream = socket.getOutputStream(); String header = stringBuilder.toString(); System.out.println(header); String contentLengthString = "Content-Length:"; int idx = header.indexOf(contentLengthString); if (idx >= 0) { String substr = header.substring(idx + contentLengthString.length()); idx = substr.indexOf('\r'); substr = substr.substring(0, idx); int contentLength = Integer.parseInt(substr.trim()); if (control.respondWith100Continue) { outputStream.write("HTTP/1.1 100 Continue\r\n\r\n".getBytes()); if (control.write100ContinueTWice) { outputStream.write("HTTP/1.1 100 Continue\r\n\r\n".getBytes()); } } char[] body = new char[contentLength]; inputStreamReader.read(body); } else { if (control.respondWith100Continue) { outputStream.write("HTTP/1.1 100 Continue\r\n\r\n".getBytes()); if (control.write100ContinueTWice) { outputStream.write("HTTP/1.1 100 Continue\r\n\r\n".getBytes()); } } StringBuilder contentLengthBuilder = new StringBuilder(); b = -1; while (true) { b = (byte)inputStreamReader.read(); contentLengthBuilder.append((char)b); if (contentLengthBuilder.length() >= 2) { char[] lastBytes = new char[2]; contentLengthBuilder.getChars(contentLengthBuilder.length() - 2, contentLengthBuilder.length(), lastBytes, 0); if (Arrays.equals(lastBytes, new char[]{'\r', '\n'})) { int contentLength = Integer.parseInt(contentLengthBuilder.substring(0, contentLengthBuilder.length() - 2)); char[] body = new char[contentLength + 7]; inputStreamReader.read(body); break; //normally we have to parse more data, but for simplicity we expect no more chunks... } } } } outputStream.write(control.response.getBytes()); outputStream.flush(); } catch (SocketException e) { //ignore } catch (IOException e) { throw new RuntimeException(e); } } } }; serverThread = new Thread(runnable); serverThread.start(); } @AfterMethod(timeOut = 10000) public void stopServerSocket() throws Exception { control.stop = true; control.serverSocket.close(); serverThread.join(); } //-Djava.endorsed.dirs=/home/giger/projects/itserve/lohnstandard/distributor/production/trunk/patches @Test(timeOut = 10000) public void testChunkedRequestAndNoExpect100ContinueResponse() throws Exception { URL url = new URL("http://localhost:54321"); String body = "responseBody"; control.response = "HTTP/1.1 200 OK\n" + "Connection: close\n" + "Content-Length: " + body.length() + "\n" + "\r\n" + body; control.respondWith100Continue = false; control.write100ContinueTWice = false; HttpURLConnection connection = (HttpURLConnection)url.openConnection(); connection.setDoOutput(true); connection.setConnectTimeout(1000); connection.setReadTimeout(5000); connection.setUseCaches(false); connection.setInstanceFollowRedirects(false); connection.setRequestMethod("POST"); connection.setChunkedStreamingMode(-1); connection.setRequestProperty("Connection", "Close"); connection.setRequestProperty("Expect", "100-Continue"); OutputStream outputStream = connection.getOutputStream(); outputStream.write("test".getBytes()); outputStream.close(); InputStream inputStream = connection.getInputStream(); IOUtils.copyAndCloseInput(inputStream, System.out); } @Test(timeOut = 10000) public void testChunkedRequestWithExpect100ContinueResponse() throws Exception { URL url = new URL("http://localhost:54321"); String body = "responseBody"; control.response = "HTTP/1.1 200 OK\n" + "Connection: close\n" + "Content-Length: " + body.length() + "\n" + "\r\n" + body; control.respondWith100Continue = true; control.write100ContinueTWice = false; HttpURLConnection connection = (HttpURLConnection)url.openConnection(); connection.setDoOutput(true); connection.setConnectTimeout(1000); connection.setReadTimeout(5000); connection.setUseCaches(false); connection.setInstanceFollowRedirects(false); connection.setRequestMethod("POST"); connection.setChunkedStreamingMode(-1); connection.setRequestProperty("Connection", "Close"); connection.setRequestProperty("Expect", "100-Continue"); OutputStream outputStream = connection.getOutputStream(); outputStream.write("test".getBytes()); outputStream.close(); InputStream inputStream = connection.getInputStream(); IOUtils.copyAndCloseInput(inputStream, System.out); } @Test(timeOut = 10000) public void testChunkedRequestWithDoubleExpect100ContinueResponse() throws Exception { URL url = new URL("http://localhost:54321"); String body = "responseBody"; control.response = "HTTP/1.1 200 OK\n" + "Connection: close\n" + "Content-Length: " + body.length() + "\n" + "\r\n" + body; control.respondWith100Continue = true; control.write100ContinueTWice = true; HttpURLConnection connection = (HttpURLConnection)url.openConnection(); connection.setDoOutput(true); connection.setConnectTimeout(1000); connection.setReadTimeout(5000); connection.setUseCaches(false); connection.setInstanceFollowRedirects(false); connection.setRequestMethod("POST"); connection.setChunkedStreamingMode(-1); connection.setRequestProperty("Connection", "Close"); connection.setRequestProperty("Expect", "100-Continue"); OutputStream outputStream = connection.getOutputStream(); outputStream.write("test".getBytes()); outputStream.close(); InputStream inputStream = connection.getInputStream(); IOUtils.copyAndCloseInput(inputStream, System.out); } @Test//(timeOut = 10000) public void testNonChunkedRequestAndNoExpect100ContinueResponse() throws Exception { URL url = new URL("http://localhost:54321"); String body = "responseBody"; control.response = "HTTP/1.1 200 OK\n" + "Connection: close\n" + "Content-Length: " + body.length() + "\n" + "\r\n" + body; control.respondWith100Continue = false; control.write100ContinueTWice = false; HttpURLConnection connection = (HttpURLConnection)url.openConnection(); connection.setDoOutput(true); connection.setConnectTimeout(1000); connection.setReadTimeout(5000); connection.setUseCaches(false); connection.setInstanceFollowRedirects(false); connection.setRequestMethod("POST"); //connection.setChunkedStreamingMode(-1); connection.setRequestProperty("Connection", "Close"); connection.setRequestProperty("Expect", "100-Continue"); OutputStream outputStream = connection.getOutputStream(); outputStream.write("test".getBytes()); outputStream.close(); InputStream inputStream = connection.getInputStream(); IOUtils.copyAndCloseInput(inputStream, System.out); } @Test(timeOut = 10000) public void testNonChunkedRequestWithExpect100ContinueResponse() throws Exception { URL url = new URL("http://localhost:54321"); String body = "responseBody"; control.response = "HTTP/1.1 200 OK\n" + "Connection: close\n" + "Content-Length: " + body.length() + "\n" + "\r\n" + body; control.respondWith100Continue = true; control.write100ContinueTWice = false; HttpURLConnection connection = (HttpURLConnection)url.openConnection(); connection.setDoOutput(true); connection.setConnectTimeout(1000); connection.setReadTimeout(5000); connection.setUseCaches(false); connection.setInstanceFollowRedirects(false); connection.setRequestMethod("POST"); //connection.setChunkedStreamingMode(-1); connection.setRequestProperty("Connection", "Close"); connection.setRequestProperty("Expect", "100-Continue"); OutputStream outputStream = connection.getOutputStream(); outputStream.write("test".getBytes()); outputStream.close(); InputStream inputStream = connection.getInputStream(); IOUtils.copyAndCloseInput(inputStream, System.out); } @Test(timeOut = 10000) public void testNonChunkedRequestWithDoubleExpect100ContinueResponse() throws Exception { URL url = new URL("http://localhost:54321"); String body = "responseBody"; control.response = "HTTP/1.1 200 OK\n" + "Connection: close\n" + "Content-Length: " + body.length() + "\n" + "\r\n" + body; control.respondWith100Continue = true; control.write100ContinueTWice = true; HttpURLConnection connection = (HttpURLConnection)url.openConnection(); connection.setDoOutput(true); connection.setConnectTimeout(1000); connection.setReadTimeout(5000); connection.setUseCaches(false); connection.setInstanceFollowRedirects(false); connection.setRequestMethod("POST"); //connection.setChunkedStreamingMode(-1); connection.setRequestProperty("Connection", "Close"); connection.setRequestProperty("Expect", "100-Continue"); OutputStream outputStream = connection.getOutputStream(); outputStream.write("test".getBytes()); outputStream.close(); InputStream inputStream = connection.getInputStream(); IOUtils.copyAndCloseInput(inputStream, System.out); } @Test(timeOut = 10000) public void testCommonsHttpBehavior() throws Exception { DefaultHttpClient httpClient = new DefaultHttpClient(); HttpParams httpParams = httpClient.getParams(); httpClient.setHttpRequestRetryHandler( new DefaultHttpRequestRetryHandler(0, false) ); HttpConnectionParams.setSoTimeout(httpParams, 10000); httpParams.setParameter("http.protocol.expect-continue", Boolean.TRUE); //ByteArrayEntity entity = new ByteArrayEntity("test".getBytes()); InputStreamEntity entity = new InputStreamEntity(new ByteArrayInputStream("test".getBytes()), 4); entity.setChunked(false); HttpPost post = new HttpPost(); post.setURI(new URL("http://localhost:54321").toURI()); post.setEntity(entity); control.respondWith100Continue = true; String body = "responseBody"; control.response = "HTTP/1.1 200 OK\n" + "Connection: close\n" + "Content-Length: " + body.length() + "\n" + "\r\n" + body; HttpResponse httpResponse = httpClient.execute(post); int responseCode = httpResponse.getStatusLine().getStatusCode(); IOUtils.copy(httpResponse.getEntity().getContent(), System.out); } }