Package org.archive.wayback.accesspoint.proxy

Source Code of org.archive.wayback.accesspoint.proxy.ProxyAccessPoint

/*
*  This file is part of the Wayback archival access software
*   (http://archive-access.sourceforge.net/projects/wayback/).
*
*  Licensed to the Internet Archive (IA) by one or more individual
*  contributors.
*
*  The IA licenses this file to You under the Apache License, Version 2.0
*  (the "License"); you may not use this file except in compliance with
*  the License.  You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*/

package org.archive.wayback.accesspoint.proxy;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import java.util.logging.Logger;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.archive.wayback.ResultURIConverter;
import org.archive.wayback.accesspoint.CompositeAccessPoint;
import org.archive.wayback.webapp.AccessPoint;

public class ProxyAccessPoint extends CompositeAccessPoint {
 
  private static final Logger LOGGER =
    Logger.getLogger(ProxyAccessPoint.class.getName());
 
  public final static String SWITCH_COLLECTION_PATH = "http://wayback-proxy/switchCollection";
  public final static String PROXY_PAC_PATH = "/proxy.pac";
 
  private List<String> directHosts;
  private AccessPoint nonProxyAccessPoint;
 
  private ResultURIConverter archivalToProxyConverter;
 
  private ProxyConfigSelector configSelector;
 
  private String proxyHostPort;
  private String httpsProxyHostPort;
 
  @Override
  public boolean isProxyEnabled() {
    return (configSelector != null);
 

  public ProxyConfigSelector getConfigSelector() {
    return configSelector;
  }

  public void setConfigSelector(ProxyConfigSelector configSelector) {
    this.configSelector = configSelector;
  }

  public List<String> getDirectHosts() {
    return directHosts;
  }

  public void setDirectHosts(List<String> directHosts) {
    this.directHosts = directHosts;
  }
 
  public AccessPoint getNonProxyAccessPoint() {
    return nonProxyAccessPoint;
  }

  public void setNonProxyAccessPoint(AccessPoint nonProxyAccessPoint) {
    this.nonProxyAccessPoint = nonProxyAccessPoint;
  }

  public String getProxyHostPort() {
    return proxyHostPort;
  }

  public void setProxyHostPort(String proxyHostPort) {
    this.proxyHostPort = proxyHostPort;
  }

  public String getHttpsProxyHostPort() {
    return httpsProxyHostPort;
  }

  public void setHttpsProxyHostPort(String httpsProxyHostPort) {
    this.httpsProxyHostPort = httpsProxyHostPort;
  }

  // Special converter for fomratting archival url that comes in to proxy mode
  // if not specified, default uriConverter from AccessPoint may be used
  public ResultURIConverter getArchivalToProxyConverter() {
    return archivalToProxyConverter;
  }

  public void setArchivalToProxyConverter(
          ResultURIConverter archivalToProxyConverter) {
    this.archivalToProxyConverter = archivalToProxyConverter;
  }

  @Override
  public boolean handleRequest(HttpServletRequest request,
      HttpServletResponse response) throws ServletException,
      IOException {
   
//    boolean isProxyReq = false;
 
// Proxy-Connection header is not reliable to differentiate between proxy and non-proxy
// so not using it anymore.. Define access points explicitly and proxy or non-proxy
// on different ports
   
//    if (request.getHeader("Proxy-Connection") != null) {
//      isProxyReq = true;
   
   
    if (!isProxyEnabled()) {
      return handleNonProxy(request, response);
    } else {
      return handleProxy(request, response);
    }
  }
 
  protected boolean handleNonProxy(HttpServletRequest request,
      HttpServletResponse response) throws ServletException, IOException
  {
    String uri = request.getRequestURI();
                             
    if (uri.endsWith(PROXY_PAC_PATH)) {
      this.writeProxyPac(request, response);
      return true;
    }

    return baseHandleRequest(request, response);
  }

  protected boolean handleProxy(HttpServletRequest request,
      HttpServletResponse response) throws ServletException, IOException {
   
    // if request is Archival-URL style URL, redirect to proxy calendar view or
    // proxy replay end point. Archival-URL is recognized only when the request
    // URL starts with replayPrefix of this AccessPoint (or non-proxy AccessPoint)

    StringBuffer urlBuff = request.getRequestURL();
    String url = urlBuff.toString();
   
    boolean isProxyHost = url.contains(getReplayPrefix());
   
    // Check the nonProxyAccessPoint prefix
    if (!isProxyHost && (nonProxyAccessPoint != null)) {
      isProxyHost = url.contains(nonProxyAccessPoint.getReplayPrefix());
    }
               
    // Special reset link
    if (url.equals(SWITCH_COLLECTION_PATH)) {
      configSelector.handleSwitch(request, response, this);
      return true;
    }
   
    // name of collection specified in the request (ex. Proxy-Authorization),
    // such as "3548"
    String realAccessPoint = configSelector.resolveConfig(request);
   
    if (realAccessPoint != null) {
     
      // See if the archival url form was included and redirect to strip it
      if (isProxyHost) {
        String prefix = "/" + realAccessPoint + "/";
        // ex. "/3548/20140101123059/http://example.com/"
        String uri = request.getRequestURI();
       
        if (uri.length() > prefix.length()) {
          // "20140101123059/http://example.com/"
          String requestUrl = uri.substring(prefix.length());
         
          // If matches this config, simply redirect and strip
          if (uri.startsWith(prefix)) {
           
            String paths[] = requestUrl.split("/", 2);
            if (paths.length < 2) {
              return false;
            }
            String timestamp = paths[0];
            String replayUrl = paths[1];
            String queryString = request.getQueryString();
            if (queryString != null) {
              replayUrl = replayUrl + "?" + queryString;
            }
           
            String redirUrl = null;
            if (timestamp.contains("*")) {
              // Calendar -> redirect to collection-less proxy query
              redirUrl = "/" + requestUrl;
            } else {
              // specific timestamp -> redirect to collection-less
              // proxy replay.
              ResultURIConverter converter = getArchivalToProxyConverter();
              if (converter == null) {
                converter = this.getUriConverter();
              }
              redirUrl = converter.makeReplayURI(timestamp, replayUrl);
            }
           
            response.sendRedirect(redirUrl);
         
            return true;
          }
        }
       
        // URL doesn't have collection part, or collection part does not match
        // collection specified in the request.

        //If archival url with any *different* config, force a selection
        //if (ReplayRequestParser.WB_REQUEST_REGEX.matcher(requestUrl).matches()) {
        //  return configSelector.selectConfigHandler(request, response, this);         
        //}
     
     
      // handle regular proxy-mode requests.
      Status status = handleRequest(realAccessPoint, request, response);
     
      switch (status) {
      case ConfigHandled:
        return true;
       
      case ConfigNotHandled:
        return false;
       
      case ConfigNotFound:
        break;
      }
    }
   
    // collection is unknown. let user choose.
    return configSelector.selectConfigHandler(request, response, this);
  }
 
  protected boolean baseHandleRequest(HttpServletRequest request,
      HttpServletResponse response) throws ServletException, IOException {
   
    if (nonProxyAccessPoint != null) {
      return nonProxyAccessPoint.handleRequest(request, response);
    } else {
      return super.handleRequest(request, response);
    }
  } 
 
  protected void writeProxyPac(HttpServletRequest httpRequest,
      HttpServletResponse httpResponse) throws ServletException,
      IOException {
   
    //TODO: Is this needed anymore (was only for Ipauth testing)
    if (configSelector != null) {   
      configSelector.handleProxyPac(httpRequest, httpResponse);
    }
   
    String proxyPath = getProxyHostPort();

    if (proxyPath == null) {
      String hostName = httpRequest.getServerName();
      int port = httpRequest.getServerPort();
      proxyPath = hostName + ":" + port;
    }
   
    String httpsProxyPath = getHttpsProxyHostPort();
   
    if (httpsProxyPath == null) {
      httpsProxyPath = proxyPath;
    }
     
    httpResponse.setContentType("application/x-ns-proxy-autoconfig");
   
    LOGGER.fine("updating proxy .pac");
   
    PrintWriter writer = httpResponse.getWriter();
    writer.println("function FindProxyForURL (url, host) {");
   
    for (String host : directHosts) {
      writer.println("  if (shExpMatch(host, \"" + host + "\")) { return \"DIRECT\"; }");
    }
   
    // For https support
    writer.println("  if (url.substring(0, 6) == \"https:\") { return \"PROXY " + httpsProxyPath + "\"; }\n");
   
    writer.println("  return \"PROXY " + proxyPath + "\";\n}");
  }
}
TOP

Related Classes of org.archive.wayback.accesspoint.proxy.ProxyAccessPoint

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.