Package org.xlightweb.client

Source Code of org.xlightweb.client.ProxyHandler$DataHandler

/*
*  Copyright (c) xlightweb.org, 2008 - 2009. All rights reserved.
*
*  This library is free software; you can redistribute it and/or
*  modify it under the terms of the GNU Lesser General Public
*  License as published by the Free Software Foundation; either
*  version 2.1 of the License, or (at your option) any later version.
*
*  This library 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
*  Lesser General Public License for more details.
*
*  You should have received a copy of the GNU Lesser General Public
*  License along with this library; if not, write to the Free Software
*  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*
* Please refer to the LGPL license at: http://www.gnu.org/copyleft/lesser.txt
* The latest copy of this software may be found on http://www.xlightweb.org/
*/
package org.xlightweb.client;


import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.BufferUnderflowException;
import java.nio.channels.ClosedChannelException;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.net.ssl.SSLContext;

import org.xlightweb.HttpRequest;
import org.xlightweb.HttpRequestHeaderWrapper;
import org.xlightweb.HttpUtils;
import org.xlightweb.IHttpExchange;
import org.xlightweb.IHttpRequest;
import org.xlightweb.IHttpRequestHandler;
import org.xlightweb.IHttpRequestHeader;
import org.xlightweb.IHttpResponse;
import org.xlightweb.IHttpResponseHandler;
import org.xsocket.Execution;
import org.xsocket.MaxReadSizeExceededException;
import org.xsocket.connection.IDataHandler;
import org.xsocket.connection.INonBlockingConnection;
import org.xsocket.connection.NonBlockingConnection;





/**
* Proxy handler
* @author grro@xlightweb.org
*/
final class ProxyHandler implements IHttpRequestHandler {
 
  private static final Logger LOG = Logger.getLogger(ProxyHandler.class.getName());
 

  private String proxyHost;
  private int proxyPort = -1;
 
  private String securedProxyHost;
  private int securedProxyPort = -1;
 
  private String proxyUser;
  private String proxyPassword;
  private String proxyUserPassword;
 
  private SSLContext sslContext;
 
 
 
 
  public void setSSLContext(SSLContext sslContext) {
    this.sslContext = sslContext;
  }
 
  public void setProxyPort(int proxyPort) {
    this.proxyPort = proxyPort;
  }

  public void setSecuredProxyHost(String host) {
    if ((host != null) && (host.length() == 0)) {
      host = null;
    }
    this.securedProxyHost = host;
  }

  public void setSecuredProxyPort(int proxyPort) {
    this.securedProxyPort = proxyPort;
  }

 
  public void setProxyUser(String proxyUser) {
    this.proxyUser = proxyUser;
   
    if (proxyPassword != null) {
      try {
        proxyUserPassword = new String(HttpUtils.encodeBase64((proxyUser + ":" + proxyPassword).getBytes()));
      } catch (IOException ioe) {
        throw new RuntimeException(ioe.toString());
      }
    }
  }

  public void setProxyPassword(String proxyPassword) {
    this.proxyPassword = proxyPassword;
    if (proxyUser != null) {
      try {
        proxyUserPassword = new String(HttpUtils.encodeBase64((proxyUser + ":" + proxyPassword).getBytes()));
      } catch (IOException ioe) {
        throw new RuntimeException(ioe.toString());
      }
    }
 
  }
 
  public void setProxyHost(String host) {
    if ((host != null) && (host.length() == 0)) {
      host = null;
    }
    this.proxyHost = host;
  }
 
 
 
  /**
   * {@inheritDoc}
   */
  @Execution(Execution.NONTHREADED)
  public void onRequest(IHttpExchange exchange) throws IOException {
   
    IHttpRequest request = exchange.getRequest();
   
    if (!hasProxytoUse(request)) {
      exchange.forward(request);
      return;
    }
     
    if (request.isSecure()) {
      forwardSSL(exchange);
     
    } else {
      forwardNonSSL(exchange);
    }
  }
 
 
  private boolean hasProxytoUse(IHttpRequest request) {

    if (!request.isSecure() && (proxyHost == null)) {
      return false;
    }
     
    if (request.isSecure() && (securedProxyHost == null)) {
      return false;
    }
   
    return true;
  }
 
 
  private void forwardNonSSL(IHttpExchange exchange) throws IOException {
   
    IHttpRequest request = exchange.getRequest();
   
    if (proxyUser != null) {
      if (proxyUserPassword != null) {
        request.addHeader("Proxy-Authorization", "Basic " + proxyUserPassword);
       
      } else {
        if (LOG.isLoggable(Level.FINE)) {
          LOG.fine("proxy password is not send send error");
        }
        exchange.sendError(new IOException("proxy user password is not set (hint: usage <HttpClient>.setProxyPassword(...)"));
        return;
      }
    }
   
    IHttpRequest wrappedRequest = null;
    if (request.hasBody()) {
      wrappedRequest = new HttpRequest(new NonSSLRequestHeaderWrapper(request.getRequestHeader()), request.getNonBlockingBody());
    } else {
      wrappedRequest = new HttpRequest(new NonSSLRequestHeaderWrapper(request.getRequestHeader()));
    }
   
    exchange.forward(wrappedRequest);
  }
 
 
  private void forwardSSL(IHttpExchange exchange) throws IOException {
   
   
   
    String host = exchange.getRequest().getHeader("Host");
    String forwardHost = host;
    int forwardPort = 443;
   
    int idx = host.lastIndexOf(":");
    if (idx != -1) {
      forwardPort = Integer.parseInt(host.substring(idx + 1, host.length()));
      forwardHost = host.substring(0, idx);
    }

    INonBlockingConnection con = new NonBlockingConnection(securedProxyHost, securedProxyPort, sslContext, false);
    con.setHandler(new DataHandler(exchange));

   
    StringBuilder sb = new StringBuilder();
   
    sb.append("CONNECT " + forwardHost + ":" + forwardPort + " HTTP/1.1\r\n" +
          "Host: " + host + "\r\n" +
          "User-Agent: xLightweb/" + HttpUtils.getImplementationVersion() + "\r\n");
   
   
    if (proxyUser != null) {
      if (proxyUserPassword != null) {
        sb.append("Proxy-Authorization: Basic " + proxyUserPassword + "\r\n");
       
      } else {
        exchange.sendError(401, "proxy user password is not set (hint: usage <HttpClient>.setProxyPassword(...)");
        return;
      }
    }

    sb.append("Proxy-Connection: keep-alive\r\n" +
          "\r\n");
   
    con.write(sb.toString());
  }

 
  private static final class DataHandler implements IDataHandler {
   
    private IHttpExchange exchange = null;
   
    public DataHandler(IHttpExchange exchange) {
      this.exchange = exchange;
    }
   
    public boolean onData(INonBlockingConnection connection) throws IOException, BufferUnderflowException, ClosedChannelException, MaxReadSizeExceededException {

      String header = connection.readStringByDelimiter("\r\n\r\n");
      String[] lines = header.split("\r\n");
     
      int idx = lines[0].indexOf(" ");
      String statusAndReason = lines[0].substring(idx, lines[0].length()).trim();
      if (!statusAndReason.startsWith("200")) {
        exchange.sendError(new IOException("could not set up tunnel to " + exchange.getRequest().getHeader("Host") + " got " + statusAndReason));
        connection.close();
        return true;
      }
     
     
      IHttpResponseHandler respHdl = new IHttpResponseHandler() {
       
        public void onResponse(IHttpResponse response) throws IOException {
          exchange.send(response);
        }
       
        public void onException(IOException ioe) throws IOException {
          exchange.sendError(ioe);
        }
      };

     
      connection.activateSecuredMode();
      new HttpClientConnection(connection).send(exchange.getRequest(), respHdl);
      return true;
    }
  }
 


 
  private final class NonSSLRequestHeaderWrapper extends HttpRequestHeaderWrapper {
   
    public NonSSLRequestHeaderWrapper(IHttpRequestHeader delegee) {
      super(delegee);
    }
   
    public URL getRequestUrl() {
     
      try {
        URL orgURL = getWrappedRequestHeader().getRequestUrl();
       
        int port = proxyPort;
        if (port == -1) {
          port = 80;
        }
       
        URL url = new URL("http", proxyHost, port, orgURL.getFile());
       
        return url;
      } catch (MalformedURLException murl) {
        throw new RuntimeException(murl.toString());
      }
    }
   
    @Override
    public String toString() {
      String s = getWrappedRequestHeader().toString();
      int idx = s.indexOf("\r\n");
   
      StringBuilder sb = new StringBuilder(getMethod() + " http://" + getHost() + getRequestURI());
      if (getQueryString() != null) {
        sb.append("?");
        sb.append(getQueryString());
      }

      sb.append(" ");
      sb.append(getProtocol());
     
      sb.append("\r\n");

      sb.append(s.substring(idx + 2, s.length()));
     
      return sb.toString();
    }   
  }
}
TOP

Related Classes of org.xlightweb.client.ProxyHandler$DataHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.