httpproxy.java

来自「一款Java实现的HTTP代理服务器」· Java 代码 · 共 694 行 · 第 1/2 页

JAVA
694
字号
package rabbit.proxy;import java.io.IOException;import java.net.InetAddress;import java.net.InetSocketAddress;import java.net.NetworkInterface;import java.net.SocketException;import java.net.URL;import java.net.UnknownHostException;import java.nio.channels.CancelledKeyException;import java.nio.channels.SelectionKey;import java.nio.channels.Selector;import java.nio.channels.ServerSocketChannel;import java.nio.channels.SocketChannel;import java.util.ArrayList;import java.util.Collections;import java.util.Enumeration;import java.util.Iterator;import java.util.List;import java.util.Set;import java.util.StringTokenizer;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import rabbit.cache.Cache;import rabbit.cache.NCache;import rabbit.filter.HttpFilter;import rabbit.handler.HandlerFactory;import rabbit.http.HttpHeader;import rabbit.http.HttpDateParser;import rabbit.io.ConnectionHandler;import rabbit.io.HandlerRegistration;import rabbit.io.InetAddressListener;import rabbit.io.Resolver;import rabbit.io.SocketHandler;import rabbit.io.WebConnection;import rabbit.io.WebConnectionListener;import rabbit.util.Config;import rabbit.util.Counter;import rabbit.util.Logger;import rabbit.util.SProperties;/** A filtering and caching http proxy.  * * @author <a href="mailto:robo@khelekore.org">Robert Olofsson</a> */public class HttpProxy implements Runnable, Resolver, TaskRunner {    /** Current version */    public static final String VERSION = "RabbIT proxy version 3.2.0";    /** The current config of this proxy. */    private Config config;    /** The time this proxy was started. Time in millis. */    private long started;    /** The identity of this server. */    private String serverIdentity = VERSION;    /** The logger of this proxy. */    private ProxyLogger logger = new ProxyLogger ();    /** The id sequence for acceptors. */    private static int acceptorId = 0;    /** The dns handler */    private DNSHandler dnsHandler;    /** The socket access controller. */    private SocketAccessController socketAccessController;         /** The http header filterer. */    private HttpHeaderFilterer httpHeaderFilterer;        /** The connection handler */    private ConnectionHandler conhandler;    /** The local adress of the proxy. */    private InetAddress localhost;    /** The port the proxy is using. */    private int port = -1;    /** Adress of connected proxy. */    private InetAddress proxy = null;    /** Port of the connected proxy. */    private int proxyport = -1;    /** Is the proxy currently listening. */    private boolean accepting = false;    /** The serversocket the proxy is using. */    private ServerSocketChannel ssc = null;    /** The selector the proxy is using. */    private Selector selector = null;    /** If this proxy is using strict http parsing. */    private boolean strictHttp = true;    /** Maximum number of concurrent connections */    private int maxConnections = 50;    /** The counter of events. */    private Counter counter = new Counter ();    /** The thread pool */ // TODO: possibility to configure...    private ExecutorService executorService = Executors.newCachedThreadPool ();        /** The queue to get back on the main thread. */    private List<Runnable> returnedTasks = new ArrayList<Runnable> ();    /** The cache-handler */    private NCache<HttpHeader, HttpHeader> cache;    /** Are we allowed to proxy ssl? */    protected boolean proxySSL = false;    /** The List of acceptable ssl-ports. */    protected List<Integer> sslports = null;    /** The handler factory handler. */    private HandlerFactoryHandler handlerFactoryHandler;    /** All the currently active connections. */    private List<Connection> connections = new ArrayList<Connection> ();        /** The total traffic in and out of this proxy. */    private TrafficLoggerHandler tlh = new TrafficLoggerHandler ();    /** Is this proxy running. */    private boolean running = false;    public HttpProxy () throws UnknownHostException {	localhost = InetAddress.getLocalHost ();    }    /** Set the config file to use for this proxy.     * @param conf the name of the file to use for proxy configuration.     */    public void setConfig (String conf) throws IOException {	setConfig (new Config (conf));    }    private void setupLogging () {	logger.setup (config.getProperties ("logging"));    }    private void setupDateParsing () {	HttpDateParser.setOffset (getOffset ());    }    private void setupDNSHandler () {	/* DNSJava have problems with international versions of windows.	 * so we default to the default dns handler. 	 */	String osName = System.getProperty ("os.name");	if (osName.toLowerCase ().indexOf ("windows") > -1) {	    logger.logWarn ("This seems like a windows system, " + 			    "will use default sun handler for DNS");	    dnsHandler = new DNSSunHandler ();	} else {	    String dnsHandlerClass = 		config.getProperty (getClass ().getName (), "dnsHandler", 				    "rabbit.proxy.DNSJavaHandler");	    try {		Class<? extends DNSHandler> clz = 		    Class.forName (dnsHandlerClass).asSubclass (DNSHandler.class);		dnsHandler = clz.newInstance ();	    		dnsHandler.setup (config.getProperties ("dns"), logger);	    } catch (Exception e) {		logger.logError ("Unable to create and setup dns handler: " + e +				 ", will try to use default instead.");		dnsHandler = new DNSJavaHandler ();		dnsHandler.setup (config.getProperties ("dns"), logger);	    }	}    }    /** Configure the chained proxy rabbit is using (if any).      */    private void setupProxyConnection () {	String sec = getClass ().getName ();	String pname = config.getProperty (sec, "proxyhost", "");	String pport = config.getProperty (sec, "proxyport", "");	if (!pname.equals ("") && !pport.equals ("")) {	    try {		proxy = dnsHandler.getInetAddress (pname);	    } catch (UnknownHostException e) {		logger.logFatal ("Unknown proxyhost: '" + pname + "' exiting");	    }	    try {		proxyport = Integer.parseInt (pport.trim ());	    } catch (NumberFormatException e) {		logger.logFatal ("Strange proxyport: '" + pport + "' exiting");	    }	}    }    private void setupCache () {	SProperties props = 	    config.getProperties (NCache.class.getName ());	cache = new NCache<HttpHeader, HttpHeader> (getLogger (), props);    }    /** Configure the SSL support RabbIT should have.     */    private void setupSSLSupport () {	String ssl = config.getProperty ("sslhandler", "allowSSL", "no");	ssl = ssl.trim ();	if (ssl.equals ("no")) {	    proxySSL = false;	} else if (ssl.equals ("yes")) {	    proxySSL = true;	    sslports = null;	} else {	    proxySSL = true;	    	    // ok, try to get the portnumbers.	    sslports = new ArrayList<Integer> ();	    StringTokenizer st = new StringTokenizer (ssl, ",");	    while (st.hasMoreTokens ()) {		String s = null;		try {		    Integer port = new Integer (s = st.nextToken ());		    sslports.add (port);		} catch (NumberFormatException e) {		    logger.logWarn ("bad number: '" + s + 				    "' for ssl port, ignoring.");		}	    }	}    }    public void setStrictHttp (boolean b) {	this.strictHttp = b;    }    public boolean getStrictHttp () {	return strictHttp;    }    /** Configure the maximum number of simultanious connections we handle      */    private void setupMaxConnections () {	String mc = config.getProperty (getClass ().getName (), 					"maxconnections", "500").trim ();	try {	    maxConnections = Integer.parseInt (mc);	} catch (NumberFormatException e) {	    logger.logWarn ("bad number for maxconnections: '" + 			    mc + "', using old value: " + maxConnections);	}    }    private void setupConnectionHandler () {	conhandler = new ConnectionHandler (logger, counter, this, selector);	String p = conhandler.getClass ().getName ();	conhandler.setup (logger, config.getProperties (p));    }        private void setConfig (Config config) {	this.config = config;	setupLogging ();	setupDateParsing ();	setupDNSHandler ();	setupProxyConnection ();	String cn = getClass ().getName ();	serverIdentity = config.getProperty (cn, "serverIdentity", VERSION); 	String strictHttp = config.getProperty (cn, "StrictHTTP", "true"); 	setStrictHttp (strictHttp.equals ("true"));	setupMaxConnections ();		setupCache ();	setupSSLSupport ();	loadClasses ();	openSocket ();	setupConnectionHandler ();	logger.logMsg ("Configuration loaded: ready for action.");    }    /** Open a socket on the specified port      *  also make the proxy continue accepting connections.     */    private void openSocket () {	int tport = 	    Integer.parseInt (config.getProperty (getClass ().getName (), 						  "port", "9666").trim ());	if (tport != port) {	    try {		port = tport;		accepting = false;		closeSocket ();		ssc = ServerSocketChannel.open ();		ssc.configureBlocking (false);		ssc.socket ().bind (new InetSocketAddress (port));		accepting = true;		selector = Selector.open ();		Acceptor acceptor = 		    new Acceptor (acceptorId++, this, selector);		HandlerRegistration hr = 		    new HandlerRegistration (acceptor, Long.MAX_VALUE);		ssc.register (selector, SelectionKey.OP_ACCEPT, hr);	    } catch (IOException e) {		logger.logFatal ("Failed to open serversocket on port " + 				 port);		stop ();	    }	}    }        /** Closes the serversocket and makes the proxy stop listening for     *	connections.      */    private void closeSocket () {	try {	    accepting = false;	    if (selector != null) {		selector.close ();		selector = null;	    }	    	    if (ssc != null) {		ssc.close ();		ssc = null;	    }	} catch (IOException e) {	    logger.logFatal ("Failed to close serversocket on port " + port);	    stop ();	}    }    /** Make sure all filters and handlers are available     */    private void loadClasses () {	SProperties hProps = config.getProperties ("Handlers");	SProperties chProps = config.getProperties ("CacheHandlers");	handlerFactoryHandler = 	    new HandlerFactoryHandler (hProps, chProps, config, getLogger ());	String filters = config.getProperty ("Filters", "accessfilters","");	socketAccessController = 	    new SocketAccessController (filters, config, logger);		String in = config.getProperty ("Filters", "httpinfilters","");	String out = config.getProperty ("Filters", "httpoutfilters","");	httpHeaderFilterer = 	    new HttpHeaderFilterer (in, out, config, this);    }    

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?