http11processor.java

来自「Tomcat 4.1与WebServer集成组件的源代码包.」· Java 代码 · 共 1,300 行 · 第 1/3 页

JAVA
1,300
字号
            for (int i = 0; i < restrictedUserAgents.length; i++) {                if (restrictedUserAgents[i].equals(userAgentValue)) {                    http11 = false;                    keepAlive = false;                }            }        }        // Check for a full URI (including protocol://host:port/)        ByteChunk uriBC = request.requestURI().getByteChunk();        if (uriBC.startsWithIgnoreCase("http", 0)) {            int pos = uriBC.indexOf("://", 0, 3, 4);            int uriBCStart = uriBC.getStart();            int slashPos = -1;            if (pos != -1) {                byte[] uriB = uriBC.getBytes();                slashPos = uriBC.indexOf('/', pos + 3);                if (slashPos == -1) {                    slashPos = uriBC.getLength();                    // Set URI as "/"                    request.requestURI().setBytes                        (uriB, uriBCStart + pos + 1, 1);                } else {                    request.requestURI().setBytes                        (uriB, uriBCStart + slashPos,                          uriBC.getLength() - slashPos);                }                MessageBytes hostMB =                     request.getMimeHeaders().setValue("host");                hostMB.setBytes(uriB, uriBCStart + pos + 3,                                 slashPos - pos - 3);            }        }        // Input filter setup        InputFilter[] inputFilters = inputBuffer.getFilters();        // Parse content-length header        int contentLength = request.getContentLength();        if (contentLength >= 0) {            inputBuffer.addActiveFilter                (inputFilters[Constants.IDENTITY_FILTER]);            contentDelimitation = true;        }        // Parse transfer-encoding header        MessageBytes transferEncodingValueMB = null;        if (http11)            transferEncodingValueMB =                 request.getMimeHeaders().getValue("transfer-encoding");        if (transferEncodingValueMB != null) {            String transferEncodingValue = transferEncodingValueMB.toString();            // Parse the comma separated list. "identity" codings are ignored            int startPos = 0;            int commaPos = transferEncodingValue.indexOf(',');            String encodingName = null;            while (commaPos != -1) {                encodingName = transferEncodingValue.substring                    (startPos, commaPos).toLowerCase().trim();                if (!addInputFilter(inputFilters, encodingName)) {                    // Unsupported transfer encoding                    error = true;                    // 501 - Unimplemented                    response.setStatus(501);                }                startPos = commaPos + 1;                commaPos = transferEncodingValue.indexOf(',', startPos);            }            encodingName = transferEncodingValue.substring(startPos)                .toLowerCase().trim();            if (!addInputFilter(inputFilters, encodingName)) {                // Unsupported transfer encoding                error = true;                // 501 - Unimplemented                response.setStatus(501);            }        }        MessageBytes valueMB = request.getMimeHeaders().getValue("host");        // Check host header        if (http11 && (valueMB == null)) {            error = true;            // 400 - Bad request            response.setStatus(400);        }        parseHost(valueMB);        if (!contentDelimitation) {            // If there's no content length and we're using keep-alive             // (HTTP/1.0 with keep-alive or HTTP/1.1), assume            // the client is not broken and didn't send a body            if (keepAlive) {                inputBuffer.addActiveFilter                    (inputFilters[Constants.VOID_FILTER]);                contentDelimitation = true;            }        }        if (!contentDelimitation)            keepAlive = false;    }    /**     * Parse host.     */    public void parseHost(MessageBytes valueMB) {        if (valueMB == null || valueMB.isNull()) {            // HTTP/1.0            // Default is what the socket tells us. Overriden if a host is             // found/parsed            request.setServerPort(socket.getLocalPort());            InetAddress localAddress = socket.getLocalAddress();            // Setting the socket-related fields. The adapter doesn't know             // about socket.            request.setLocalHost(localAddress.getHostName());            request.serverName().setString(localAddress.getHostName());            return;        }        ByteChunk valueBC = valueMB.getByteChunk();        byte[] valueB = valueBC.getBytes();        int valueL = valueBC.getLength();        int valueS = valueBC.getStart();        int colonPos = -1;        if (hostNameC.length < valueL) {            hostNameC = new char[valueL];        }        for (int i = 0; i < valueL; i++) {            char b = (char) valueB[i + valueS];            hostNameC[i] = b;            if (b == ':') {                colonPos = i;                break;            }        }        if (colonPos < 0) {            if (sslSupport == null) {                // 80 - Default HTTTP port                request.setServerPort(80);            } else {                // 443 - Default HTTPS port                request.setServerPort(443);            }            request.serverName().setChars(hostNameC, 0, valueL);        } else {            request.serverName().setChars(hostNameC, 0, colonPos);            int port = 0;            int mult = 1;            for (int i = valueL - 1; i > colonPos; i--) {                int charValue = HexUtils.DEC[(int) valueB[i + valueS]];                if (charValue == -1) {                    // Invalid character                    error = true;                    // 400 - Bad request                    response.setStatus(400);                    break;                }                port = port + (charValue * mult);                mult = 10 * mult;            }            request.setServerPort(port);        }    }    /*     * Check for compression     *     */	private boolean isCompressable()	{        // Compression only since HTTP 1.1        if (! http11)            return false;        // Check if browser support gzip encoding        MessageBytes acceptEncodingMB =             request.getMimeHeaders().getValue("accept-encoding");                    if ((acceptEncodingMB == null)             || (acceptEncodingMB.indexOf("gzip") == -1))            return false;        // Check if content is not allready gzipped        MessageBytes contentEncodingMB =            response.getMimeHeaders().getValue("Content-Encoding");        if ((contentEncodingMB != null)             && (contentEncodingMB.indexOf("gzip") != -1))            return false;        // If force mode, allways compress (test purposes only)        if (compressionLevel == 2)           return true;        // Check for incompatible Browser        if (noCompressionUserAgents != null) {            MessageBytes userAgentValueMB =                  request.getMimeHeaders().getValue("user-agent");            String userAgentValue = userAgentValueMB.toString();        	if (inStringArray(noCompressionUserAgents, userAgentValue))        		return false;        }        // Check if suffisant len to trig the compression                int contentLength = response.getContentLength();        if ((contentLength == -1)             || (contentLength > compressionMinSize)) {            // Check for compatible MIME-TYPE            if (compressableMimeTypes != null)                return (inStringArray(compressableMimeTypes, response.getContentType()));        }		return false;	}	    /**     * When committing the response, we have to validate the set of headers, as     * well as setup the response filters.     */    protected void prepareResponse() {        boolean entityBody = true;        contentDelimitation = false;        OutputFilter[] outputFilters = outputBuffer.getFilters();        if (http09 == true) {            // HTTP/0.9            outputBuffer.addActiveFilter                (outputFilters[Constants.IDENTITY_FILTER]);            return;        }        int statusCode = response.getStatus();        if ((statusCode == 204) || (statusCode == 205)             || (statusCode == 304)) {            // No entity body            outputBuffer.addActiveFilter                (outputFilters[Constants.VOID_FILTER]);            entityBody = false;            contentDelimitation = true;        }        MessageBytes methodMB = request.method();        if (methodMB.equals("HEAD")) {            // No entity body            outputBuffer.addActiveFilter                (outputFilters[Constants.VOID_FILTER]);            contentDelimitation = true;        }        // Check for compression        boolean useCompression = false;        if (entityBody && (compressionLevel > 0)) {            useCompression = isCompressable();                        // Change content-length to -1 to force chunking            if (useCompression) {                response.setContentLength(-1);            }        }        MimeHeaders headers = response.getMimeHeaders();        if (!entityBody) {            response.setContentLength(-1);        } else {            String contentType = response.getContentType();            if (contentType != null) {                headers.setValue("Content-Type").setString(contentType);            }            String contentLanguage = response.getContentLanguage();            if (contentLanguage != null) {                headers.setValue("Content-Language")                    .setString(contentLanguage);            }        }        int contentLength = response.getContentLength();        if (contentLength != -1) {            response.getMimeHeaders().setValue("Content-Length")                .setInt(contentLength);            outputBuffer.addActiveFilter                (outputFilters[Constants.IDENTITY_FILTER]);            contentDelimitation = true;        } else {            if (entityBody && http11) {                outputBuffer.addActiveFilter                    (outputFilters[Constants.CHUNKED_FILTER]);                contentDelimitation = true;                response.addHeader("Transfer-Encoding", "chunked");            }        }        if (useCompression) {            outputBuffer.addActiveFilter(outputFilters[Constants.GZIP_FILTER]);            // FIXME: Make content-encoding generation dynamic            response.setHeader("Content-Encoding", "gzip");            // Make Proxies happy via Vary (from mod_deflate)            response.setHeader("Vary", "Accept-Encoding");        }        // Add date header        if (! response.containsHeader("Date"))          response.addHeader("Date", FastHttpDateFormat.getCurrentDate());        // Add server header        response.addHeader("Server", Constants.SERVER);        // Add transfer encoding header        // FIXME        if ((entityBody) && (!contentDelimitation)) {            // Mark as close the connection after the request, and add the             // connection: close header            keepAlive = false;        }        if (!keepAlive) {            response.addHeader("Connection", "close");        } else if (!http11) {            response.addHeader("Connection", "Keep-Alive");        }        // Build the response header        outputBuffer.sendStatus();        int size = headers.size();        for (int i = 0; i < size; i++) {            outputBuffer.sendHeader(headers.getName(i), headers.getValue(i));        }        outputBuffer.endHeaders();    }    /**     * Initialize standard input and output filters.     */    protected void initializeFilters() {        // Create and add the identity filters.        inputBuffer.addFilter(new IdentityInputFilter());        outputBuffer.addFilter(new IdentityOutputFilter());        // Create and add the chunked filters.        inputBuffer.addFilter(new ChunkedInputFilter());        outputBuffer.addFilter(new ChunkedOutputFilter());        // Create and add the void filters.        inputBuffer.addFilter(new VoidInputFilter());        outputBuffer.addFilter(new VoidOutputFilter());        // Create and add the chunked filters.        //inputBuffer.addFilter(new GzipInputFilter());        outputBuffer.addFilter(new GzipOutputFilter());    }    /**     * Add an input filter to the current request.     *      * @return false if the encoding was not found (which would mean it is      * unsupported)     */    protected boolean addInputFilter(InputFilter[] inputFilters,                                      String encodingName) {        if (encodingName.equals("identity")) {            // Skip        } else if (encodingName.equals("chunked")) {            inputBuffer.addActiveFilter                (inputFilters[Constants.CHUNKED_FILTER]);            contentDelimitation = true;        } else {            for (int i = 2; i < inputFilters.length; i++) {                if (inputFilters[i].getEncodingName()                    .toString().equals(encodingName)) {                    inputBuffer.addActiveFilter(inputFilters[i]);                    return true;                }            }            return false;        }        return true;    }    /**     * Specialized utility method: find a sequence of lower case bytes inside     * a ByteChunk.     */    protected int findBytes(ByteChunk bc, byte[] b) {        byte first = b[0];        byte[] buff = bc.getBuffer();        int start = bc.getStart();        int end = bc.getEnd();	// Look for first char 	int srcEnd = b.length;        	for (int i = start; i <= (end - srcEnd); i++) {	    if (Ascii.toLower(buff[i]) != first) continue;	    // found first char, now look for a match            int myPos = i+1;	    for (int srcPos = 1; srcPos < srcEnd; ) {                if (Ascii.toLower(buff[myPos++]) != b[srcPos++])		    break;                if (srcPos == srcEnd) return i - start; // found it	    }	}	return -1;    }}

⌨️ 快捷键说明

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