Path: blob/master/test/jdk/java/net/URL/PerConnectionProxy.java
41149 views
/*1* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/* @test24* @bug 492052625* @summary Needs per connection proxy support for URLs26* @modules java.base/sun.net.www27* @library ../../../sun/net/www/httptest/ /test/lib28* @build ClosedChannelList TestHttpServer HttpTransaction HttpCallback29* @compile PerConnectionProxy.java30* @run main/othervm -Dhttp.proxyHost=inexistant -Dhttp.proxyPort=8080 PerConnectionProxy31*/3233import java.net.*;34import java.io.*;3536import jdk.test.lib.net.URIBuilder;3738public class PerConnectionProxy implements HttpCallback {39static TestHttpServer server;4041public void request (HttpTransaction req) {42req.setResponseEntityBody ("Hello .");43try {44req.sendResponse (200, "Ok");45req.orderlyClose();46} catch (IOException e) {47}48}4950public static void main(String[] args) {51try {52InetAddress loopbackAddress = InetAddress.getLoopbackAddress();53server = new TestHttpServer(new PerConnectionProxy(), 1, 10, loopbackAddress, 0);54ProxyServer pserver = new ProxyServer(loopbackAddress, server.getLocalPort());55// start proxy server56new Thread(pserver).start();5758URL url = URIBuilder.newBuilder()59.scheme("http")60.loopback()61.port(server.getLocalPort())62.toURLUnchecked();6364// for non existing proxy expect an IOException65try {66InetSocketAddress isa = InetSocketAddress.createUnresolved("inexistent", 8080);67Proxy proxy = new Proxy(Proxy.Type.HTTP, isa);68HttpURLConnection urlc = (HttpURLConnection)url.openConnection (proxy);69InputStream is = urlc.getInputStream ();70is.close();71throw new RuntimeException("non existing per connection proxy should lead to IOException");72} catch (IOException ioex) {73// expected74}7576// for NO_PROXY, expect direct connection77try {78HttpURLConnection urlc = (HttpURLConnection)url.openConnection (Proxy.NO_PROXY);79int respCode = urlc.getResponseCode();80urlc.disconnect();81} catch (IOException ioex) {82throw new RuntimeException("direct connection should succeed :"+ioex.getMessage());83}8485// for a normal proxy setting expect to see connection86// goes through that proxy87try {88InetSocketAddress isa = InetSocketAddress.createUnresolved(89loopbackAddress.getHostAddress(),90pserver.getPort());91Proxy p = new Proxy(Proxy.Type.HTTP, isa);92HttpURLConnection urlc = (HttpURLConnection)url.openConnection (p);93int respCode = urlc.getResponseCode();94urlc.disconnect();95} catch (IOException ioex) {96throw new RuntimeException("connection through a local proxy should succeed :"+ioex.getMessage());97}9899} catch (Exception e) {100throw new RuntimeException(e);101} finally {102if (server != null) {103server.terminate();104}105}106107}108109static class ProxyServer extends Thread {110private static ServerSocket ss = null;111112// client requesting for a tunnel113private Socket clientSocket = null;114115/*116* Origin server's address and port that the client117* wants to establish the tunnel for communication.118*/119private InetAddress serverInetAddr;120private int serverPort;121122public ProxyServer(InetAddress server, int port) throws IOException {123serverInetAddr = server;124serverPort = port;125ss = new ServerSocket(0, 0, InetAddress.getLoopbackAddress());126}127128public void run() {129try {130clientSocket = ss.accept();131processRequests();132} catch (Exception e) {133System.out.println("Proxy Failed: " + e);134e.printStackTrace();135try {136ss.close();137}138catch (IOException excep) {139System.out.println("ProxyServer close error: " + excep);140excep.printStackTrace();141}142}143}144145private void processRequests() throws Exception {146// connection set to the tunneling mode147148Socket serverSocket = new Socket(serverInetAddr, serverPort);149ProxyTunnel clientToServer = new ProxyTunnel(150clientSocket, serverSocket);151ProxyTunnel serverToClient = new ProxyTunnel(152serverSocket, clientSocket);153clientToServer.start();154serverToClient.start();155System.out.println("Proxy: Started tunneling.......");156157clientToServer.join();158serverToClient.join();159System.out.println("Proxy: Finished tunneling........");160161clientToServer.close();162serverToClient.close();163164}165166/**167***************************************************************168* helper methods follow169***************************************************************170*/171public int getPort() {172return ss.getLocalPort();173}174/*175* This inner class provides unidirectional data flow through the sockets176* by continuously copying bytes from the input socket onto the output177* socket, until both sockets are open and EOF has not been received.178*/179static class ProxyTunnel extends Thread {180Socket sockIn;181Socket sockOut;182InputStream input;183OutputStream output;184185public ProxyTunnel(Socket sockIn, Socket sockOut)186throws Exception {187this.sockIn = sockIn;188this.sockOut = sockOut;189input = sockIn.getInputStream();190output = sockOut.getOutputStream();191}192193public void run() {194int BUFFER_SIZE = 400;195byte[] buf = new byte[BUFFER_SIZE];196int bytesRead = 0;197int count = 0; // keep track of the amount of data transfer198199try {200while ((bytesRead = input.read(buf)) >= 0) {201output.write(buf, 0, bytesRead);202output.flush();203count += bytesRead;204}205} catch (IOException e) {206/*207* The peer end has closed the connection208* we will close the tunnel209*/210close();211}212}213214public void close() {215try {216if (!sockIn.isClosed())217sockIn.close();218if (!sockOut.isClosed())219sockOut.close();220} catch (IOException ignored) { }221}222}223224}225}226227228