test/jdk/java/net/httpclient/ProxyServer.java
author chegar
Thu, 08 Mar 2018 17:42:16 +0000
branchhttp-client-branch
changeset 56265 ec34ae013fbe
parent 56233 1753108d07b9
child 56369 24a8fafec3ff
permissions -rw-r--r--
http-client-branch: tests should bind to the loopback only
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
36131
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
     1
/*
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
     2
 * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
36131
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
     4
 *
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
     7
 * published by the Free Software Foundation.
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
     8
 *
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
     9
 * This code is distributed in the hope that it will be useful, but WITHOUT
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    10
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    11
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    12
 * version 2 for more details (a copy is included in the LICENSE file that
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    13
 * accompanied this code).
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    14
 *
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    15
 * You should have received a copy of the GNU General Public License version
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    16
 * 2 along with this work; if not, write to the Free Software Foundation,
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    17
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    18
 *
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    19
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    20
 * or visit www.oracle.com if you need additional information or have any
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    21
 * questions.
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    22
 */
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    23
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    24
import java.net.*;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    25
import java.io.*;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    26
import java.util.*;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    27
import java.security.*;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    28
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    29
/**
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    30
 * A minimal proxy server that supports CONNECT tunneling. It does not do
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    31
 * any header transformations. In future this could be added.
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    32
 * Two threads are created per client connection. So, it's not
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    33
 * intended for large numbers of parallel connections.
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    34
 */
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    35
public class ProxyServer extends Thread implements Closeable {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    36
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    37
    ServerSocket listener;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    38
    int port;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    39
    volatile boolean debug;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    40
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    41
    /**
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    42
     * Create proxy on port (zero means don't care). Call getPort()
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    43
     * to get the assigned port.
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    44
     */
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    45
    public ProxyServer(Integer port) throws IOException {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    46
        this(port, false);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    47
    }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    48
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    49
    public ProxyServer(Integer port, Boolean debug) throws IOException {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    50
        this.debug = debug;
56233
1753108d07b9 http-client-branch: setReuseAddress(false) for all test ServerSockets
chegar
parents: 55973
diff changeset
    51
        listener = new ServerSocket();
1753108d07b9 http-client-branch: setReuseAddress(false) for all test ServerSockets
chegar
parents: 55973
diff changeset
    52
        listener.setReuseAddress(false);
56265
ec34ae013fbe http-client-branch: tests should bind to the loopback only
chegar
parents: 56233
diff changeset
    53
        listener.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), port));
36131
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    54
        this.port = listener.getLocalPort();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    55
        setName("ProxyListener");
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    56
        setDaemon(true);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    57
        connections = new LinkedList<>();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    58
        start();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    59
    }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    60
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    61
    public ProxyServer(String s) {  }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    62
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    63
    /**
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    64
     * Returns the port number this proxy is listening on
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    65
     */
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    66
    public int getPort() {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    67
        return port;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    68
    }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    69
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    70
    /**
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    71
     * Shuts down the proxy, probably aborting any connections
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    72
     * currently open
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    73
     */
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    74
    public void close() throws IOException {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    75
        if (debug) System.out.println("Proxy: closing");
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    76
            done = true;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    77
        listener.close();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    78
        for (Connection c : connections) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    79
            if (c.running()) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    80
                c.close();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    81
            }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    82
        }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    83
    }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    84
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    85
    List<Connection> connections;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    86
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    87
    volatile boolean done;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    88
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    89
    public void run() {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    90
        if (System.getSecurityManager() == null) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    91
            execute();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    92
        } else {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    93
            // so calling domain does not need to have socket permission
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    94
            AccessController.doPrivileged(new PrivilegedAction<Void>() {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    95
                public Void run() {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    96
                    execute();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    97
                    return null;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    98
                }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    99
            });
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   100
        }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   101
    }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   102
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   103
    public void execute() {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   104
        try {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   105
            while(!done) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   106
                Socket s = listener.accept();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   107
                if (debug)
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   108
                    System.out.println("Client: " + s);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   109
                Connection c = new Connection(s);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   110
                connections.add(c);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   111
            }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   112
        } catch(Throwable e) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   113
            if (debug && !done) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   114
                System.out.println("Fatal error: Listener: " + e);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   115
                e.printStackTrace();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   116
            }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   117
        }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   118
    }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   119
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   120
    /**
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   121
     * Transparently forward everything, once we know what the destination is
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   122
     */
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   123
    class Connection {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   124
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   125
        Socket clientSocket, serverSocket;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   126
        Thread out, in;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   127
        volatile InputStream clientIn, serverIn;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   128
        volatile OutputStream clientOut, serverOut;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   129
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   130
        boolean forwarding = false;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   131
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   132
        final static int CR = 13;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   133
        final static int LF = 10;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   134
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   135
        Connection(Socket s) throws IOException {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   136
            this.clientSocket= s;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   137
            this.clientIn = new BufferedInputStream(s.getInputStream());
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   138
            this.clientOut = s.getOutputStream();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   139
            init();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   140
        }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   141
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   142
        byte[] readHeaders(InputStream is) throws IOException {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   143
            byte[] outbuffer = new byte[8000];
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   144
            int crlfcount = 0;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   145
            int bytecount = 0;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   146
            int c;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   147
            while ((c=is.read()) != -1 && bytecount < outbuffer.length) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   148
                outbuffer[bytecount++] = (byte)c;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   149
                if (debug) System.out.write(c);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   150
                // were looking for CRLFCRLF sequence
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   151
                if (c == CR || c == LF) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   152
                    switch(crlfcount) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   153
                        case 0:
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   154
                            if (c == CR) crlfcount ++;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   155
                            break;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   156
                        case 1:
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   157
                            if (c == LF) crlfcount ++;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   158
                            break;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   159
                        case 2:
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   160
                            if (c == CR) crlfcount ++;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   161
                            break;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   162
                        case 3:
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   163
                            if (c == LF) crlfcount ++;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   164
                            break;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   165
                    }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   166
                } else {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   167
                    crlfcount = 0;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   168
                }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   169
                if (crlfcount == 4) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   170
                    break;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   171
                }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   172
            }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   173
            byte[] ret = new byte[bytecount];
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   174
            System.arraycopy(outbuffer, 0, ret, 0, bytecount);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   175
            return ret;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   176
        }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   177
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   178
        boolean running() {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   179
            return out.isAlive() || in.isAlive();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   180
        }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   181
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   182
        public void close() throws IOException {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   183
            if (debug) System.out.println("Closing connection (proxy)");
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   184
            if (serverSocket != null) serverSocket.close();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   185
            if (clientSocket != null) clientSocket.close();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   186
        }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   187
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   188
        int findCRLF(byte[] b) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   189
            for (int i=0; i<b.length-1; i++) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   190
                if (b[i] == CR && b[i+1] == LF) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   191
                    return i;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   192
                }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   193
            }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   194
            return -1;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   195
        }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   196
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   197
        public void init() {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   198
            try {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   199
                byte[] buf = readHeaders(clientIn);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   200
                int p = findCRLF(buf);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   201
                if (p == -1) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   202
                    close();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   203
                    return;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   204
                }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   205
                String cmd = new String(buf, 0, p, "US-ASCII");
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   206
                String[] params = cmd.split(" ");
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   207
                if (params[0].equals("CONNECT")) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   208
                    doTunnel(params[1]);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   209
                } else {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   210
                    doProxy(params[1], buf, p, cmd);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   211
                }
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   212
            } catch (Throwable e) {
36131
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   213
                if (debug) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   214
                    System.out.println (e);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   215
                }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   216
                try {close(); } catch (IOException e1) {}
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   217
            }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   218
        }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   219
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   220
        void doProxy(String dest, byte[] buf, int p, String cmdLine)
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   221
            throws IOException
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   222
        {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   223
            try {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   224
                URI uri = new URI(dest);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   225
                if (!uri.isAbsolute()) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   226
                    throw new IOException("request URI not absolute");
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   227
                }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   228
                dest = uri.getAuthority();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   229
                // now extract the path from the URI and recreate the cmd line
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   230
                int sp = cmdLine.indexOf(' ');
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   231
                String method = cmdLine.substring(0, sp);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   232
                cmdLine = method + " " + uri.getPath() + " HTTP/1.1";
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   233
                int x = cmdLine.length() - 1;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   234
                int i = p;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   235
                while (x >=0) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   236
                    buf[i--] = (byte)cmdLine.charAt(x--);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   237
                }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   238
                i++;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   239
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   240
                commonInit(dest, 80);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   241
                serverOut.write(buf, i, buf.length-i);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   242
                proxyCommon();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   243
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   244
            } catch (URISyntaxException e) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   245
                throw new IOException(e);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   246
            }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   247
        }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   248
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   249
        void commonInit(String dest, int defaultPort) throws IOException {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   250
            int port;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   251
            String[] hostport = dest.split(":");
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   252
            if (hostport.length == 1) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   253
                port = defaultPort;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   254
            } else {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   255
                port = Integer.parseInt(hostport[1]);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   256
            }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   257
            if (debug) System.out.printf("Server: (%s/%d)\n", hostport[0], port);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   258
            serverSocket = new Socket(hostport[0], port);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   259
            serverOut = serverSocket.getOutputStream();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   260
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   261
            serverIn = new BufferedInputStream(serverSocket.getInputStream());
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   262
        }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   263
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   264
        void proxyCommon() throws IOException {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   265
            out = new Thread(() -> {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   266
                try {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   267
                    byte[] bb = new byte[8000];
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   268
                    int n;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   269
                    while ((n = clientIn.read(bb)) != -1) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   270
                        serverOut.write(bb, 0, n);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   271
                    }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   272
                    serverSocket.close();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   273
                    clientSocket.close();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   274
                } catch (IOException e) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   275
                    if (debug) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   276
                        System.out.println (e);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   277
                    }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   278
                }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   279
            });
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   280
            in = new Thread(() -> {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   281
                try {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   282
                    byte[] bb = new byte[8000];
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   283
                    int n;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   284
                    while ((n = serverIn.read(bb)) != -1) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   285
                        clientOut.write(bb, 0, n);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   286
                    }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   287
                    serverSocket.close();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   288
                    clientSocket.close();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   289
                } catch (IOException e) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   290
                    if (debug) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   291
                        System.out.println(e);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   292
                        e.printStackTrace();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   293
                    }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   294
                }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   295
            });
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   296
            out.setName("Proxy-outbound");
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   297
            out.setDaemon(true);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   298
            in.setDaemon(true);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   299
            in.setName("Proxy-inbound");
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   300
            out.start();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   301
            in.start();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   302
        }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   303
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   304
        void doTunnel(String dest) throws IOException {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   305
            commonInit(dest, 443);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   306
            clientOut.write("HTTP/1.1 200 OK\r\n\r\n".getBytes());
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   307
            proxyCommon();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   308
        }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   309
    }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   310
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   311
    public static void main(String[] args) throws Exception {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   312
        int port = Integer.parseInt(args[0]);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   313
        boolean debug = args.length > 1 && args[1].equals("-debug");
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   314
        System.out.println("Debugging : " + debug);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   315
        ProxyServer ps = new ProxyServer(port, debug);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   316
        System.out.println("Proxy server listening on port " + ps.getPort());
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   317
        while (true) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   318
            Thread.sleep(5000);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   319
        }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   320
    }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   321
}