TransparentProxyRequestHandler xref

    1   /*
    2    * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//httpclient/src/test/org/apache/commons/httpclient/server/TransparentProxyRequestHandler.java,v 1.7 2004/12/11 22:35:26 olegk Exp $
    3    * $Revision: 480424 $
    4    * $Date: 2006-11-29 06:56:49 +0100 (Wed, 29 Nov 2006) $
    5    *
    6    * ====================================================================
    7    *
    8    *  Licensed to the Apache Software Foundation (ASF) under one or more
    9    *  contributor license agreements.  See the NOTICE file distributed with
    10   *  this work for additional information regarding copyright ownership.
    11   *  The ASF licenses this file to You under the Apache License, Version 2.0
    12   *  (the "License"); you may not use this file except in compliance with
    13   *  the License.  You may obtain a copy of the License at
    14   *
    15   *      http://www.apache.org/licenses/LICENSE-2.0
    16   *
    17   *  Unless required by applicable law or agreed to in writing, software
    18   *  distributed under the License is distributed on an "AS IS" BASIS,
    19   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    20   *  See the License for the specific language governing permissions and
    21   *  limitations under the License.
    22   * ====================================================================
    23   *
    24   * This software consists of voluntary contributions made by many
    25   * individuals on behalf of the Apache Software Foundation.  For more
    26   * information on the Apache Software Foundation, please see
    27   * <http://www.apache.org/>.
    28   *
    29   */
    30
    31  package org.apache.commons.httpclient.server;
    32
    33  import java.io.IOException;
    34  import java.io.InputStream;
    35  import java.io.InterruptedIOException;
    36  import java.io.OutputStream;
    37  import java.net.Socket;
    38
    39  import org.apache.commons.httpclient.Header;
    40  import org.apache.commons.httpclient.HttpStatus;
    41  import org.apache.commons.httpclient.HttpVersion;
    42
    43  /**
    44   * This request handler can handle the CONNECT method. It does nothing for any
    45   * other HTTP methods.
    46   *
    47   * @author Ortwin Glueck
    48   */
    49  public class TransparentProxyRequestHandler implements HttpRequestHandler {
    50
    51      /*
    52       * (non-Javadoc)
    53       *
    54       * @see org.apache.commons.httpclient.server.HttpRequestHandler#processRequest(org.apache.commons.httpclient.server.SimpleHttpServerConnection)
    55       */
    56      public boolean processRequest(
    57          final SimpleHttpServerConnection conn,
    58          final SimpleRequest request) throws IOException
    59      {
    60
    61          RequestLine line = request.getRequestLine();
    62          HttpVersion ver = line.getHttpVersion();
    63          String method = line.getMethod();
    64          if (!"CONNECT".equalsIgnoreCase(method)) {
    65              return false;
    66          }
    67          Socket targetSocket = null;
    68          try {
    69              targetSocket = connect(line.getUri());
    70          } catch (IOException e) {
    71              SimpleResponse response = new SimpleResponse();
    72              response.setStatusLine(ver, HttpStatus.SC_NOT_FOUND);
    73              response.setHeader(new Header("Server", "test proxy"));
    74              response.setBodyString("Cannot connect to " + line.getUri());
    75              conn.writeResponse(response);
    76              return true;
    77          }
    78          SimpleResponse response = new SimpleResponse();
    79          response.setHeader(new Header("Server", "test proxy"));
    80          response.setStatusLine(ver, HttpStatus.SC_OK, "Connection established");
    81          conn.writeResponse(response);
    82
    83          SimpleHttpServerConnection target = new SimpleHttpServerConnection(targetSocket);
    84          pump(conn, target);
    85          return true;
    86      }
    87
    88      private void pump(final SimpleHttpServerConnection source, final SimpleHttpServerConnection target)
    89          throws IOException {
    90
    91          source.setSocketTimeout(100);
    92          target.setSocketTimeout(100);
    93
    94          InputStream sourceIn = source.getInputStream();
    95          OutputStream sourceOut = source.getOutputStream();
    96          InputStream targetIn = target.getInputStream();
    97          OutputStream targetOut = target.getOutputStream();
    98
    99          byte[] tmp = new byte[1024];
    100         int l;
    101         for (;;) {
    102             if (!source.isOpen() || !target.isOpen()) {
    103                 break;
    104             }
    105             try {
    106                 l = sourceIn.read(tmp);
    107                 if (l == -1) {
    108                     break;
    109                 }
    110                 targetOut.write(tmp, 0, l);
    111             } catch (InterruptedIOException ignore) {
    112                 if (Thread.interrupted()) {
    113                     break;
    114                 }
    115             }
    116             try {
    117                 l = targetIn.read(tmp);
    118                 if (l == -1) {
    119                     break;
    120                 }
    121                 sourceOut.write(tmp, 0, l);
    122             } catch (InterruptedIOException ignore) {
    123                 if (Thread.interrupted()) {
    124                     break;
    125                 }
    126             }
    127         }
    128     }
    129
    130     private static Socket connect(final String host) throws IOException {
    131         String hostname = null;
    132         int port;
    133         int i = host.indexOf(':');
    134         if (i != -1) {
    135             hostname = host.substring(0, i);
    136             try {
    137                 port = Integer.parseInt(host.substring(i + 1));
    138             } catch (NumberFormatException ex) {
    139                 throw new IOException("Invalid host address: " + host);
    140             }
    141         } else {
    142             hostname = host;
    143             port = 80;
    144         }
    145         return new Socket(hostname, port);
    146     }
    147
    148 }