The valid characters are defined in RFC 7230 and RFC 3986
发表于|更新于
|字数总计:1.4k|阅读时长:7分钟|阅读量:
今天在使用tomcat的过程中遇到了这个问题。表现为400错误以及空白页面。
1 2 3 4 5 6 7 8 9 10 11
Error parsing HTTP request header Note: further occurrences of HTTP header parsing errors will be logged at DEBUG level. Java.lang.IllegalArgumentException: Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986 at org.apache.coyote.http11.InternalInputBuffer.parseRequestLine(InternalInputBuffer.java:189) at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1000) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:637) at org.apache.tomcat.util.NET.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:318) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(Thread.java:745)
/** * HTTP header value parser implementation. Parsing HTTP headers as per RFC2616 * is not always as simple as it first appears. For headers that only use tokens * the simple approach will normally be sufficient. However, for the other * headers, while simple code meets 99.9% of cases, there are often some edge * cases that make things far more complicated. * * The purpose of this parser is to let the parser worry about the edge cases. * It provides tolerant (where safe to do so) parsing of HTTP header values * assuming that wrapped header lines have already been unwrapped. (The Tomcat * header processing code does the unwrapping.) * */ publicclassHttpParser{
privatestaticfinal StringManager sm = StringManager.getManager(HttpParser.class);
static { String prop = System.getProperty("tomcat.util.http.parser.HttpParser.requestTargetAllow"); if (prop != null) { for (int i = 0; i < prop.length(); i++) { char c = prop.charAt(i); if (c == '{' || c == '}' || c == '|') { REQUEST_TARGET_ALLOW[c] = true; } else { log.warn(sm.getString("httpparser.invalidRequestTargetCharacter", Character.valueOf(c))); } } }
for (int i = 0; i < ARRAY_SIZE; i++) { // Control> 0-31, 127 if (i < 32 || i == 127) { IS_CONTROL[i] = true; }
// Separator if ( i == '(' || i == ')' || i == '<' || i == '>' || i == '@' || i == ',' || i == ';' || i == ':' || i == '\\' || i == '\"' || i == '/' || i == '[' || i == ']' || i == '?' || i == '=' || i == '{' || i == '}' || i == ' ' || i == '\t') { IS_SEPARATOR[i] = true; }
// Token: Anything 0-127 that is not a control and not a separator if (!IS_CONTROL[i] && !IS_SEPARATOR[i] && i < 128) { IS_TOKEN[i] = true; }
// Hex: 0-9, a-f, A-F if ((i >= '0' && i <='9') || (i >= 'a' && i <= 'f') || (i >= 'A' && i <= 'F')) { IS_HEX[i] = true; }
// Not valid for request target. // Combination of multiple rules from RFC7230 and RFC 3986. Must be // ASCII, no controls plus a few additional characters excluded if (IS_CONTROL[i] || i > 127 || i == ' ' || i == '\"' || i == '#' || i == '<' || i == '>' || i == '\\' || i == '^' || i == '`' || i == '{' || i == '|' || i == '}') { if (!REQUEST_TARGET_ALLOW[i]) { IS_NOT_REQUEST_TARGET[i] = true; } }
// Not valid for HTTP protocol // "HTTP/" DIGIT "." DIGIT if (i == 'H' || i == 'T' || i == 'P' || i == '/' || i == '.' || (i >= '0' && i <= '9')) { IS_HTTP_PROTOCOL[i] = true; } } } }