| /* |
| * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| /* |
| * @test |
| * @bug 6726695 6993490 |
| * @summary HttpURLConnection shoul support 'Expect: 100-contimue' headers for PUT |
| */ |
| |
| import java.net.*; |
| import java.io.*; |
| |
| public class B6726695 extends Thread { |
| private ServerSocket server = null; |
| private int port = 0; |
| private byte[] data = new byte[512]; |
| private String boundary = "----------------7774563516523621"; |
| |
| public static void main(String[] args) throws Exception { |
| B6726695 test = new B6726695(); |
| // Exit even if server is still running |
| test.setDaemon(true); |
| // start server |
| test.start(); |
| // run test |
| test.test(); |
| } |
| |
| public B6726695() { |
| try { |
| server = new ServerSocket(0); |
| port = server.getLocalPort(); |
| } catch (IOException e) { |
| e.printStackTrace(); |
| } |
| } |
| |
| public void test() throws Exception { |
| /** |
| * This is a hardcoded test. The server side expects 3 requests with a |
| * Expect: 100-continue header. It will reject the 1st one and accept |
| * the second one. Thus allowing us to test both scenarios. |
| * The 3rd case is the simulation of a server that just plains ignore |
| * the Expect: 100-Continue header. So the POST should proceed after |
| * a timeout. |
| */ |
| URL url = new URL("http://localhost:" + port + "/foo"); |
| |
| // 1st Connection. Should be rejected. I.E. get a ProtocolException |
| URLConnection con = url.openConnection(); |
| HttpURLConnection http = (HttpURLConnection) con; |
| http.setRequestMethod("POST"); |
| http.setRequestProperty("Expect", "100-Continue"); |
| http.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary); |
| http.setDoOutput(true); |
| http.setFixedLengthStreamingMode(512); |
| OutputStream out = null; |
| int errorCode = -1; |
| try { |
| out = http.getOutputStream(); |
| } catch (ProtocolException e) { |
| errorCode = http.getResponseCode(); |
| } |
| if (errorCode != 417) { |
| throw new RuntimeException("Didn't get the ProtocolException"); |
| } |
| |
| // 2nd connection. Should be accepted by server. |
| http = (HttpURLConnection) url.openConnection(); |
| http.setRequestMethod("POST"); |
| http.setRequestProperty("Expect", "100-Continue"); |
| http.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary); |
| http.setDoOutput(true); |
| http.setFixedLengthStreamingMode(data.length); |
| out = null; |
| try { |
| out = http.getOutputStream(); |
| } catch (ProtocolException e) { |
| } |
| if (out == null) { |
| throw new RuntimeException("Didn't get an OutputStream"); |
| } |
| out.write(data); |
| out.flush(); |
| errorCode = http.getResponseCode(); |
| if (errorCode != 200) { |
| throw new RuntimeException("Response code is " + errorCode); |
| } |
| out.close(); |
| |
| // 3rd connection. Simulate a server that doesn't implement 100-continue |
| http = (HttpURLConnection) url.openConnection(); |
| http.setRequestMethod("POST"); |
| http.setRequestProperty("Expect", "100-Continue"); |
| http.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary); |
| http.setDoOutput(true); |
| http.setFixedLengthStreamingMode(data.length); |
| out = null; |
| try { |
| out = http.getOutputStream(); |
| } catch (ProtocolException e) { |
| } |
| if (out == null) { |
| throw new RuntimeException("Didn't get an OutputStream"); |
| } |
| out.write(data); |
| out.flush(); |
| out.close(); |
| errorCode = http.getResponseCode(); |
| if (errorCode != 200) { |
| throw new RuntimeException("Response code is " + errorCode); |
| } |
| } |
| |
| |
| @Override |
| public void run() { |
| try { |
| // Fist connection: don't accetpt the request |
| Socket s = server.accept(); |
| serverReject(s); |
| // Second connection: accept the request (send 100-continue) |
| s = server.accept(); |
| serverAccept(s); |
| // 3rd connection: just ignore the 'Expect:' header |
| s = server.accept(); |
| serverIgnore(s); |
| } catch (IOException e) { |
| e.printStackTrace(); |
| } finally { |
| try { server.close(); } catch (IOException unused) {} |
| } |
| } |
| |
| public void serverReject(Socket s) throws IOException { |
| BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream())); |
| PrintStream out = new PrintStream(new BufferedOutputStream(s.getOutputStream())); |
| String line = null; |
| do { |
| line = in.readLine(); |
| } while (line != null && line.length() != 0); |
| |
| out.print("HTTP/1.1 417 Expectation Failed\r\n"); |
| out.print("Server: Sun-Java-System-Web-Server/7.0\r\n"); |
| out.print("Connection: close\r\n"); |
| out.print("Content-Length: 0\r\n"); |
| out.print("\r\n"); |
| out.flush(); |
| out.close(); |
| in.close(); |
| } |
| |
| public void serverAccept(Socket s) throws IOException { |
| BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream())); |
| PrintStream out = new PrintStream(new BufferedOutputStream(s.getOutputStream())); |
| String line = null; |
| do { |
| line = in.readLine(); |
| } while (line != null && line.length() != 0); |
| |
| // Send 100-Continue |
| out.print("HTTP/1.1 100 Continue\r\n"); |
| out.print("\r\n"); |
| out.flush(); |
| // Then read the body |
| char[] cbuf = new char[512]; |
| in.read(cbuf); |
| |
| /* Force the server to not respond for more that the expect 100-Continue |
| * timeout set by the HTTP handler (5000 millis). This ensures the |
| * timeout is correctly resets the default read timeout, infinity. |
| * See 6993490. */ |
| System.out.println("server sleeping..."); |
| try {Thread.sleep(6000); } catch (InterruptedException e) {} |
| |
| // finally send the 200 OK |
| out.print("HTTP/1.1 200 OK"); |
| out.print("Server: Sun-Java-System-Web-Server/7.0\r\n"); |
| out.print("Connection: close\r\n"); |
| out.print("Content-Length: 0\r\n"); |
| out.print("\r\n"); |
| out.flush(); |
| out.close(); |
| in.close(); |
| } |
| |
| public void serverIgnore(Socket s) throws IOException { |
| BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream())); |
| PrintStream out = new PrintStream(new BufferedOutputStream(s.getOutputStream())); |
| String line = null; |
| do { |
| line = in.readLine(); |
| } while (line != null && line.length() != 0); |
| |
| // Then read the body |
| char[] cbuf = new char[512]; |
| int l = in.read(cbuf); |
| // finally send the 200 OK |
| out.print("HTTP/1.1 200 OK"); |
| out.print("Server: Sun-Java-System-Web-Server/7.0\r\n"); |
| out.print("Content-Length: 0\r\n"); |
| out.print("Connection: close\r\n"); |
| out.print("\r\n"); |
| out.flush(); |
| out.close(); |
| in.close(); |
| } |
| } |