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 + -
显示快捷键?