Package org.xlightweb.client

Source Code of org.xlightweb.client.AutoRedirectHandler

/*
*  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.util.logging.Level;
import java.util.logging.Logger;

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.xlightweb.IHttpResponseHeader;
import org.xlightweb.InvokeOn;
import org.xsocket.Execution;
import org.xsocket.ILifeCycle;





/**
* Auto redirect handler
* @author grro@xlightweb.org
*/
final class AutoRedirectHandler implements IHttpRequestHandler, ILifeCycle {
 
  private static final Logger LOG = Logger.getLogger(AutoRedirectHandler.class.getName());

  private HttpClient httpClient = null;
 
 
  /**
   * constructor
   *
   * @param httpClient  the http client to perform the redirects
   */
  public AutoRedirectHandler(HttpClient httpClient) {
    this.httpClient = httpClient;
  }
 
  public void onInit() {
   
  }
 
  public void onDestroy() throws IOException {
    httpClient = null;
  }
 
 
  /**
   * {@inheritDoc}
   */
  @InvokeOn(InvokeOn.MESSAGE_RECEIVED)
  @Execution(Execution.NONTHREADED)
  public void onRequest(IHttpExchange exchange) throws IOException {
 
    IHttpRequest request = exchange.getRequest();
    exchange.forward(request, new RedirectedHandler(HttpUtils.copy(request), exchange));
  }
 
 

  private final class RedirectedHandler implements IHttpResponseHandler {

    private IHttpRequest request = null;
    private IHttpExchange exchange = null;
   
    private Integer countRedirects = 0;

   
    RedirectedHandler(IHttpRequest request, IHttpExchange exchange) throws IOException {
      this.request = request;
      this.exchange = exchange;
     
      countRedirects = (Integer) request.getAttribute("org.xlightweb.client.AutoRedirectHandler.countRedirects");
      if (countRedirects == null) {
        countRedirects = 0;
      }
    }
   

    @Execution(Execution.NONTHREADED)
    public void onResponse(IHttpResponse response) throws IOException {
     
      if (isRedirectResponse(request.getRequestHeader(), response.getResponseHeader())) {

          if (LOG.isLoggable(Level.FINE)) {
              LOG.fine("got redirect response: " + response.getResponseHeader());
          }
         
        // get the new location
        URL newLocation = getRedirectURI(response, request.isSecure(), request.getServerName(), request.getServerPort());
       
        // .. and update the stored request
        request.setRequestUrl(newLocation);

        if (countRedirects < httpClient.getMaxRedirects()) {

          // if is secured perform redirect request in threaded context -> implicit startSSL() has to be performed within threaded context  
          if (request.isSecure()) {
            Runnable task = new Runnable() {
              public void run() {
                sendRedirectedRequest();
              }
            };
            httpClient.getWorkerpool().execute(task);
           
          } else {
            sendRedirectedRequest();
          }
         
         
        } else {
          exchange.sendError(new IOException("max redirects " + httpClient.getMaxRedirects() + " reached. request will not be executed: " + request.getRequestHeader()));
        }
       
      } else {
       
        exchange.send(response);
      }
    }

   
    private void sendRedirectedRequest() {
            if (LOG.isLoggable(Level.FINE)) {
                LOG.fine("send redirected request: " + request.getRequestHeader());
            }
       
      try {
        request.setAttribute("org.xlightweb.client.AutoRedirectHandler.countRedirects", ++countRedirects);
       
        IHttpResponseHandler respHdl = new IHttpResponseHandler() {
         
          @Execution(Execution.NONTHREADED)
          public void onResponse(IHttpResponse response) throws IOException {
            exchange.send(response);
          }
         
          @Execution(Execution.NONTHREADED)
          public void onException(IOException ioe) throws IOException {
            exchange.sendError(ioe);
          }
        };
       
        httpClient.send(request, respHdl);
      } catch (IOException ioe) {
        exchange.sendError(new IOException("can execute redirect request " + request.getRequestHeader() + " reason: " + ioe.toString()));
      }
    }
   
   
    @Execution(Execution.NONTHREADED)
    public void onException(final IOException ioe) {
      exchange.sendError(ioe);
    }
   

    private boolean isRedirectResponse(IHttpRequestHeader requestHeader, IHttpResponseHeader responseHeader) {
     
      switch (responseHeader.getStatus()) {
     
     
      // 300 Multiple choices
      case 300:
        return false;
       
      // 301 Moved permanently
      case 301:
        if (requestHeader.getMethod().equalsIgnoreCase("GET") || requestHeader.getMethod().equalsIgnoreCase("HEAD")) {
          return true;
        }
       
        return false;

       
      // 302 found
      case 302:
        if (httpClient.isTreat302RedirectAs303()) {
          return true;
        }
       
        if (requestHeader.getMethod().equalsIgnoreCase("GET") || requestHeader.getMethod().equalsIgnoreCase("HEAD")) {
          return true;
        }
       
        return false;
     
      // 303 See other
      case 303:
        return true;
     
       
      // 304 Not modified
      case 304:
        return false;

      // 305 Use proxy
      case 305:
        return false;

      // 306 (unused)
      case 306:
        return false;

      // 307 temporary redirect
      case 307:
        return false;

       
      default:
        return false;
      }
    }
   
    private URL getRedirectURI(IHttpResponse response, boolean isSSL, String originalHost, int originalPort) {
     
      String location = response.getHeader("Location");
     
      if (location != null) {
       
        try {
         
          if (isRelativeUrl(location)) {
            if (isSSL) {
              if (originalPort == -1) {
                return new URL("https://" + originalHost + location);
              } else {
                return new URL("https://" + originalHost + ":" + originalPort + location);
              }
            } else {
              if (originalPort == -1) {
                return new URL("http://" + originalHost + location);
              } else {
                return new URL("http://" + originalHost + ":" + originalPort + location);
              }
            }
           
          } else {
            return new URL(location);
          }
         
        } catch (MalformedURLException e) {
          if (LOG.isLoggable(Level.FINE)) {
            LOG.fine("could not create relocation url . reason " + e.toString());
          }
        }
         
      }
   
      return null;
    }
  } 
 
 
  private boolean isRelativeUrl(String url) {
    url = url.toUpperCase();
    return (!url.startsWith("HTTP") && !url.startsWith("HTTPS"));
  }
}
TOP

Related Classes of org.xlightweb.client.AutoRedirectHandler

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.