我们在上篇文章分析了http request line tomcat的解析。本文主要讲header 的解析
tomcat 默认对header的个数做了限制,通过maxHeaderCount 参数设置,默认
maxHeaderCount = 100
//解析header 部分前,设置了header 个数的限制
request.getMimeHeaders().setLimit(endpoint.getMaxHeaderCount());
if (!inputBuffer.parseHeaders()) {
// head 部分数据缺少,半包的情况,需要等待后面的数据报到来继续读。
// We've read part of the request, don't recycle it
// instead associate it with the socket
openSocket = true;
readComplete = false;
break;
}
parseHeaders 是循环解析所有的header name 和value 对,并添加到
MimeHeaders 的headers 数组中,headers 数组的大小是maxHeaderCount,也就是100,
do {
//循环读所有的header头
status = parseHeader();
// Checking that
// (1) Headers plus request line size does not exceed its limit
// (2) There are enough bytes to avoid expanding the buffer when
// reading body
// Technically, (2) is technical limitation, (1) is logical
// limitation to enforce the meaning of headerBufferSize
// From the way how buf is allocated and how blank lines are being
// read, it should be enough to check (1) only.
if (byteBuffer.position() > headerBufferSize || byteBuffer.capacity() - byteBuffer.position() < socketReadBufferSize) {
throw new IllegalArgumentException(sm.getString("iib.requestheadertoolarge.error"));
}
} while (status == HeaderParseStatus.HAVE_MORE_HEADERS);
if (status == HeaderParseStatus.DONE) {
parsingHeader = false;
end = byteBuffer.position();
return true;
} else {
return false;
}
读到':' 时,就添加一个header 并返回value的引用,后面value 解析完后,直接设置headerData.headerValue 即可,headers.addValue() 会判断大小是否超过maxHeaderCount,如超过,则抛headers.maxCountFail
错误。
if (chr == Constants.COLON) {
headerParsePos = HeaderParsePosition.HEADER_VALUE_START;
//header name 读完了,创建一个MimeHeaderField 标记该name 的在buffer 里的 offset 和 length headerData.headerValue = headers.addValue(byteBuffer.array(), headerData.start,
pos - headerData.start);
headers 里存放的是MimeHeaderField,代表一个header,MimeHeaderField 有两个MessageBytes 类型的nameB和valueB,分别表示header name 和 header value
MessageBytes 只是对上篇讲到的httpinputbuffer的引用,并记录偏移量和长度。这样所有的header name 和value 都引用了tomcat input buffer,只是每一个的offset 和length 不一样而已。