⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 requesthandler.java

📁 轻量级Http代理服务器
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
 * jRevProxy, an opensource Java reverse proxy server
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
  
 * This program 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 General Public License for more details.
  
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
 *
 * $Id: RequestHandler.java,v 2.14 2003/04/24 09:21:45 fnoe Exp $ 
 */

package cx.noe.jrevproxy;

import java.net.Socket;
import java.net.SocketTimeoutException;
import java.io.*;
import java.util.*;
import java.net.URL;

import cx.noe.jrevproxy.logging.ILog;
import cx.noe.jrevproxy.IHandlerInfo;
import cx.noe.jrevproxy.Ruleset;
import cx.noe.jrevproxy.Rule;

/**
 * RequestHandler
 *
 * The RequestHandler handles the external request.
 *
 * @author <a href="mailto:frederik@noe.cx"> Frederik Noe </a>
 * @version <tt>$Revision: 2.14 $</tt>
 */
public class RequestHandler implements RevProRunnable,ILog {
    
    private PoolManager manager = null;
    private ILog logger = null;
    private Socket socket = null;
    private Properties properties = null;
    private int timeout = 5000;
    private int soTimeout = 1000;
    private Ruleset ruleset = null;
    private int NRRETRIES = 10;
    private ConnectionInfo connectioninfo = null;
    
    /** Creates a new instance of RequestHandler
     *
     * @param manager the poolmanager instance
     * @param properties the properties instance used to retrieve some key/value pairs
     * @param connectioninfo the object instance that holds the connection and authentication info
     */
    public RequestHandler(PoolManager manager, Properties properties, ConnectionInfo connectioninfo) {
        this.manager = manager;
        logger = manager.getLogger();
        this.properties = properties;
        this.connectioninfo = connectioninfo;
        
        String strSOTimeout = null;
        
        if((strSOTimeout = properties.getProperty("SOTIMEOUT")) != null)
            try {
                soTimeout = Integer.parseInt(strSOTimeout);
            }
            catch(Exception e) {}
        
        String strTimeout = null;
        
        if((strTimeout = properties.getProperty("TIMEOUT")) != null)
            try {
                timeout = Integer.parseInt(strTimeout);
            }
            catch(Exception e) {}
    }
    
    /**
     * Thread execution code
     *
     * @param info information about the poolinstance that will run this method
     */
    public void run(IHandlerInfo info) {
        ILog oldLogger = logger;
        logger = info.getLogger();
        
        log(METHOD,"--run--");
        
        OutputStream outEx = null;
        InputStream inEx = null;
        
        try {
            
            SocketFactory factory = new SocketFactory(properties,logger);
            log(DEBUG,"external socketfactory created");
            
            // set a timeout to avoid infinite reads while no new bytes are arriving
            socket.setSoTimeout(soTimeout);
            log(DEBUG,"external socket timeout set: " + soTimeout);
            
            // create the in/out streams for the external socket connection
            outEx = socket.getOutputStream();
            inEx = socket.getInputStream();
            log(DEBUG,"external input- and outputstreams created");
            
            ByteArrayOutputStream outStream = null;
            int size = 0;
            String inStr = null;
            
            outStream = readRequest(inEx);
            
            // convert to String so that we can start parsing the request
            // check that we have a non-empty reques that is well formed (GET || POST)
            if((size = outStream.size()) == 0 || !HTTPRequest.isHTTPRequest(inStr = outStream.toString())) {
                if(size == 0) {
                    log(INFO,"no external request data available");
                    sendBadRequestResponse(outEx,"No data received");
                }
                else {
                    log(DEBUG,"external request: " + inStr);
                    log(INFO,"no valid external HTTP request received");
                    sendBadRequestResponse(outEx,"No valid HTTP request received");
                }
                
                // let's reset the logger back to the original
                logger = oldLogger;
                return;
            }
            
            // log the external request in case we are in debug mode
            log(DEBUG,"external request: " + inStr);
            
            // find out what virtual directory the request refers to
            String vdir = null;
            vdir = HTTPRequest.getVirtualDir(inStr);
            log(DEBUG,"external virtual dir:" + vdir);
             
            // find what rule applies out of the ruleset
            Rule rule = ruleset.getApplicableRule(vdir);
            
            if(rule == null) {
                log(INFO,"Did not find an applicable rule for virtualdir " + vdir);
                sendBadRequestResponse(outEx,"Exception");
                
                // let's reset the logger back to the original
                logger = oldLogger;
                return;
            }
            
            // show in the logging what the rule is doing
            log(INFO,"Found applicable rule " + rule.getName());
            log(DEBUG,"Rule: " + vdir + " <-> " + rule.getJunction());
            
            // check if client authentication is enabled and check if we have a user restriction
            if(connectioninfo.getCertificate() != null) {
            String subjectDN = connectioninfo.getCertificate().getSubjectDN().getName();
            
            if(subjectDN != null)
                if(!rule.isAuthorized(subjectDN)) {
                    sendNotAuthorizedResponse(outEx);
                    log(INFO,"User is NOT authorized to read the requested resource");
                    return;
                }
                else
                    log(INFO,"User is authorized to read the requested resource");
            }
            // modify the request so that it will seem that jRevProxy made the internal request instead of
            // the external computer
            String hostName = rule.getJunction().getHost();
            int intPort = rule.getJunction().getPort();
            
            inStr = HTTPRequest.setHostname(inStr, hostName);
            inStr = HTTPRequest.trim(inStr);
            
            String newVdir= rule.getJunction().getPath();
            if (newVdir == null || newVdir == "")
                newVdir = "/";
            
            inStr = HTTPRequest.setVirtualDir(inStr,newVdir);
            log(DEBUG,"jRevProxy modified request: " + inStr);
            
            // send the internal request, receive the response and send it to the external host
            Socket intSocket = null;
            
            if(rule.getJunction().getProtocol().compareToIgnoreCase("HTTPS") == 0) {
                intSocket = factory.getSSLClientSocket(hostName,intPort);
                log(DEBUG,"internal SSLSocket created");
            }
            else {
                intSocket = factory.getClientSocket(hostName,intPort);
                log(DEBUG,"internal socket created");
            }
            
            intSocket.setSoTimeout(soTimeout);
            log(DEBUG,"internal socket timeout set: " + soTimeout);
            
            InputStream inIn = intSocket.getInputStream();
            OutputStream outIn = intSocket.getOutputStream();
            log(DEBUG,"internal input- and outputstreams created");
            
            outStream = null;
            int nrretries = 1;
            
            // let's try a couple of times to send the request and receive a non-empty response back
            do {
                log(INFO, nrretries + " try to send and receive");
                outIn.write(inStr.getBytes());
                log(DEBUG,"internal request send");
                
                outStream = readResponse(inIn);
                log(DEBUG,"internal response received");
            }
            while((outStream.size() == 0 || HTTPResponse.isMsgBodyEmpty(outStream.toString())) && nrretries++ <NRRETRIES);
            
            if(outStream.size() != 0) {
                // check the contenttype
                String outStr = outStream.toString();
                log(DEBUG,"internal response: " + outStr);
                
                if(HTTPResponse.getContentType(outStr) == HTTPResponse.TEXT_HTML) {
                    log(DEBUG,"Content is HTML");
                    // check if we have a chunked transfer encoding
                    if(HTTPResponse.isChunkedTransfer(outStr)) {
                        log(DEBUG,"Transfer-Encoding is chunked; let's decode it");
                        outStr = HTTPResponse.decodeTransferEncoding(outStr);
                        log(DEBUG,"decoded internal response: " + outStr);
                    }
                    log(DEBUG,"Let's update the response headers");
                    outStr = HTTPResponse.updateHeaders(outStr, socket.getLocalAddress().getHostName(), vdir);
                    log(DEBUG, "internal response with updated headers: " + outStr);
                    //
                    log(DEBUG,"Let's filter the response now");
                    outStr = HTTPResponse.filter(outStr, socket.getLocalAddress().getHostName(), vdir, rule.getJunction(), true);
                    log(DEBUG,"filtered internal response: " + outStr);

⌨️ 快捷键说明

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