Acceptor
public void run() {
int errorDelay = 0;
// 循环播放,直到收到关闭命令
while (running) {
// 如果端点已暂停则循环
while (paused && running) {
state = AcceptorState.PAUSED;
try {
Thread.sleep(50);
} catch (InterruptedException e) {
// Ignore
}
}
if (!running) {
break;
}
state = AcceptorState.RUNNING;
try {
//如果我们已达到最大连接数,请等待
countUpOrAwaitConnection();
SocketChannel socket = null;
try {
// 接受来自服务器套接字的下一个传入连接
socket = serverSock.accept();
} catch (IOException ioe) {
// We didn't get a socket
countDownConnection();
if (running) {
// Introduce delay if necessary
errorDelay = handleExceptionWithDelay(errorDelay);
// re-throw
throw ioe;
} else {
break;
}
}
// 成功接受,重置错误延迟
errorDelay = 0;
// 配置套接字
if (running && !paused) {
// 如果成功,setSocketOptions()会将套接字移交给适当的处理器
if (!setSocketOptions(socket)) {
closeSocket(socket);
}
} else {
closeSocket(socket);
}
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
log.error(sm.getString("endpoint.accept.fail"), t);
}
}
state = AcceptorState.ENDED;
}
setSocketOptions(socket)
protected boolean setSocketOptions(SocketChannel socket) {
// 处理连接
try {
//设置为非堵塞, APR样式,我们将对其进行轮询
socket.configureBlocking(false);
Socket sock = socket.socket();
//设置sock的一些属性
socketProperties.setProperties(sock);
NioChannel channel = nioChannels.pop();
// 第一次连接为null 就构建一个
if (channel == null) {
SocketBufferHandler bufhandler = new SocketBufferHandler(
socketProperties.getAppReadBufSize(),
socketProperties.getAppWriteBufSize(),
socketProperties.getDirectBuffer());
if (isSSLEnabled()) {
channel = new SecureNioChannel(socket, bufhandler, selectorPool, this);
} else {
channel = new NioChannel(socket, bufhandler);
}
} else {
channel.setIOChannel(socket);
channel.reset();
}
getPoller0().register(channel);
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
try {
log.error("",t);
} catch (Throwable tt) {
ExceptionUtils.handleThrowable(tt);
}
// Tell to close the socket
return false;
}
return true;
}
register(channel)
public void register(final NioChannel socket) {
// 将socket关联当前的poller
socket.setPoller(this);
/**
* 构建NioSocketWrapper
* 初始化父类SocketWrapperBase的socket和endpoint 和读写信号量
* 赋值pool为endpoint里面的selectorPool
* socketBufferHandler为NioChannel的bufHandler
*/
NioSocketWrapper ka = new NioSocketWrapper(socket, NioEndpoint.this);
// 将socket关联NioSocketWrapper
socket.setSocketWrapper(ka);
/**
* 初始化NioSocketWrapper的值
*/
ka.setPoller(this);
ka.setReadTimeout(getSocketProperties().getSoTimeout());
ka.setWriteTimeout(getSocketProperties().getSoTimeout());
ka.setKeepAliveLeft(NioEndpoint.this.getMaxKeepAliveRequests());
ka.setReadTimeout(getConnectionTimeout());
ka.setWriteTimeout(getConnectionTimeout());
// 先从事件缓存里面拿
PollerEvent r = eventCache.pop();
// 设置对读感兴趣
ka.interestOps(SelectionKey.OP_READ);//这就是OP_REGISTER变成的。
// 如果缓存里面没有就构建一个Poller事件
if ( r==null) r = new PollerEvent(socket,ka,OP_REGISTER);
else r.reset(socket,ka,OP_REGISTER);
// 添加事件
addEvent(r);
}
Poller.run()
public void run() {
// 循环直到调用destroy()
while (true) {
boolean hasEvents = false;
try {
if (!close) {
hasEvents = events();
if (wakeupCounter.getAndSet(-1) > 0) {
//如果我们在这里,则意味着我们还有其他工作要做非阻塞选择
keyCount = selector.selectNow();
} else {
keyCount = selector.select(selectorTimeout);
}
wakeupCounter.set(0);
}
if (close) {
events();
timeout(0, false);
try {
selector.close();
} catch (IOException ioe) {
log.error(sm.getString("endpoint.nio.selectorCloseFail"), ioe);
}
break;
}
} catch (Throwable x) {
ExceptionUtils.handleThrowable(x);
log.error("",x);
continue;
}
//我们要么超时要么醒来,首先处理事件
if ( keyCount == 0 ) hasEvents = (hasEvents | events());
Iterator<SelectionKey> iterator =
keyCount > 0 ? selector.selectedKeys().iterator() : null;
// 遍历准备键的集合并调度任何活动事件
while (iterator != null && iterator.hasNext()) {
SelectionKey sk = iterator.next();
NioSocketWrapper attachment = (NioSocketWrapper)sk.attachment();
// 如果另一个线程调用cancelledKey(),则附件可能为null
if (attachment == null) {
iterator.remove();
} else {
iterator.remove();
processKey(sk, attachment);
}
}//while
//处理超时
timeout(keyCount,hasEvents);
}//while
getStopLatch().countDown();
}
events()
public boolean events() {
boolean result = false;
PollerEvent pe = null;
for (int i = 0, size = events.size(); i < size && (pe = events.poll()) != null; i++ ) {
result = true;
try {
pe.run();
// 这里防止频繁创建事件,复用事件
pe.reset();
if (running && !paused) {
// 放入事件缓存
eventCache.push(pe);
}
} catch ( Throwable x ) {
log.error("",x);
}
}
return result;
}
public void run() {
// 如果是对OP_REGISTER感兴趣
if (interestOps == OP_REGISTER) {
try {
// 获取Poller注册OP_READ并且把socketWrapper当成参数注册
socket.getIOChannel().register(
socket.getPoller().getSelector(), SelectionKey.OP_READ, socketWrapper);
} catch (Exception x) {
log.error(sm.getString("endpoint.nio.registerFail"), x);
}
} else {
final SelectionKey key = socket.getIOChannel().keyFor(socket.getPoller().getSelector());
try {
if (key == null) {
// 密钥已取消(例如由于套接字关闭),并在处理过程中从选择器中删除。
// 由于连接器在关闭插座时不会被倒数,因此请对连接进行倒数。
socket.socketWrapper.getEndpoint().countDownConnection();
((NioSocketWrapper) socket.socketWrapper).closed = true;
} else {
final NioSocketWrapper socketWrapper = (NioSocketWrapper) key.attachment();
if (socketWrapper != null) {
//我们正在注册开始的密钥,请重置公平性计数器。
int ops = key.interestOps() | interestOps;
socketWrapper.interestOps(ops);
key.interestOps(ops);
} else {
socket.getPoller().cancelledKey(key);
}
}
} catch (CancelledKeyException ckx) {
try {
socket.getPoller().cancelledKey(key);
} catch (Exception ignore) {}
}
}
}
processKey(sk, attachment)
protected void processKey(SelectionKey sk, NioSocketWrapper attachment) {
try {
if ( close ) {
cancelledKey(sk);
// SelectionKey是有效的并且NioSocketWrapper不为null
} else if ( sk.isValid() && attachment != null ) {
// SelectionKey是可读可写的
if (sk.isReadable() || sk.isWritable() ) {
if ( attachment.getSendfileData() != null ) {
processSendfile(sk,attachment, false);
} else {
unreg(sk, attachment, sk.readyOps());
boolean closeSocket = false;
// 先读再写
if (sk.isReadable()) {
if (!processSocket(attachment, SocketEvent.OPEN_READ, true)) {
closeSocket = true;
}
}
if (!closeSocket && sk.isWritable()) {
if (!processSocket(attachment, SocketEvent.OPEN_WRITE, true)) {
closeSocket = true;
}
}
if (closeSocket) {
cancelledKey(sk);
}
}
}
} else {
//无效的key
cancelledKey(sk);
}
} catch ( CancelledKeyException ckx ) {
cancelledKey(sk);
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
log.error("",t);
}
}
processSocket(attachment, SocketEvent.OPEN_READ, true)
public boolean processSocket(SocketWrapperBase<S> socketWrapper,
SocketEvent event, boolean dispatch) {
try {
if (socketWrapper == null) {
return false;
}
// 从缓存拿处理器 等同于Worker线程
SocketProcessorBase<S> sc = processorCache.pop();
if (sc == null) {
//没有就创建
sc = createSocketProcessor(socketWrapper, event);
} else {
sc.reset(socketWrapper, event);
}
//获取线程池 是在NioEndpoint.createExecutor()创建的
Executor executor = getExecutor();
if (dispatch && executor != null) {
// 通过线程池执行
executor.execute(sc);
} else {
// 直接执行
sc.run();
}
} catch (RejectedExecutionException ree) {
getLog().warn(sm.getString("endpoint.executor.fail", socketWrapper) , ree);
return false;
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
// 这意味着我们得到了一个OOM或类似的对象来创建线程,或者池及其队列已满
getLog().error(sm.getString("endpoint.process.fail"), t);
return false;
}
return true;
}
createSocketProcessor(socketWrapper, event)
protected SocketProcessorBase<NioChannel> createSocketProcessor(
SocketWrapperBase<NioChannel> socketWrapper, SocketEvent event) {
return new SocketProcessor(socketWrapper, event);
}
public abstract class SocketProcessorBase<S> implements Runnable {
protected SocketWrapperBase<S> socketWrapper;
protected SocketEvent event;
public SocketProcessorBase(SocketWrapperBase<S> socketWrapper, SocketEvent event) {
reset(socketWrapper, event);
}
public void reset(SocketWrapperBase<S> socketWrapper, SocketEvent event) {
Objects.requireNonNull(event);
this.socketWrapper = socketWrapper;
this.event = event;
}
@Override
public final void run() {
synchronized (socketWrapper) {
// 可能会同时触发用于读取和写入的处理。
// 上面的同步可确保不会并行进行处理。下
// 面的测试确保如果要处理的第一个事件导致套接字被关闭,则不处理后续事件
if (socketWrapper.isClosed()) {
return;
}
doRun();
}
}
protected abstract void doRun();
}
protected void doRun() {
// 获取socket
NioChannel socket = socketWrapper.getSocket();
// 获取该selector上的SelectionKey
SelectionKey key = socket.getIOChannel().keyFor(socket.getPoller().getSelector());
try {
int handshake = -1;
try {
// https是否握手完毕
if (key != null) {
if (socket.isHandshakeComplete()) {
// 无需TLS握手。让处理程序处理此套接字事件组合。
handshake = 0;
} else if (event == SocketEvent.STOP || event == SocketEvent.DISCONNECT ||
event == SocketEvent.ERROR) {
// Unable to complete the TLS handshake. Treat it as
// if the handshake failed.
handshake = -1;
} else {
handshake = socket.handshake(key.isReadable(), key.isWritable());
// The handshake process reads/writes from/to the
// socket. status may therefore be OPEN_WRITE once
// the handshake completes. However, the handshake
// happens when the socket is opened so the status
// must always be OPEN_READ after it completes. It
// is OK to always set this as it is only used if
// the handshake completes.
event = SocketEvent.OPEN_READ;
}
}
} catch (IOException x) {
handshake = -1;
if (log.isDebugEnabled()) log.debug("Error during SSL handshake",x);
} catch (CancelledKeyException ckx) {
handshake = -1;
}
if (handshake == 0) {
SocketState state = SocketState.OPEN;
// 处理来自此套接字的请求
if (event == null) {
state = getHandler().process(socketWrapper, SocketEvent.OPEN_READ);
} else {
state = getHandler().process(socketWrapper, event);
}
if (state == SocketState.CLOSED) {
close(socket, key);
}
} else if (handshake == -1 ) {
getHandler().process(socketWrapper, SocketEvent.CONNECT_FAIL);
close(socket, key);
} else if (handshake == SelectionKey.OP_READ){
socketWrapper.registerReadInterest();
} else if (handshake == SelectionKey.OP_WRITE){
socketWrapper.registerWriteInterest();
}
} catch (CancelledKeyException cx) {
socket.getPoller().cancelledKey(key);
} catch (VirtualMachineError vme) {
ExceptionUtils.handleThrowable(vme);
} catch (Throwable t) {
log.error("", t);
socket.getPoller().cancelledKey(key);
} finally {
socketWrapper = null;
event = null;
//return to cache
if (running && !paused) {
processorCache.push(this);
}
}123456
}
}
getHandler().process(socketWrapper, event)
state = getHandler().process(socketWrapper, event)
public SocketState process(SocketWrapperBase<S> wrapper, SocketEvent status) {
if (getLog().isDebugEnabled()) {
getLog().debug(sm.getString("abstractConnectionHandler.process",
wrapper.getSocket(), status));
}
if (wrapper == null) {
// 没事做。socket已关闭。
return SocketState.CLOSED;
}
S socket = wrapper.getSocket();
Processor processor = connections.get(socket);
if (getLog().isDebugEnabled()) {
getLog().debug(sm.getString("abstractConnectionHandler.connectionsGet",
processor, socket));
}
// 超时是在专用线程上计算的,然后分派。
// 由于调度过程中的延迟,可能不再需要超时。
// 检查此处,避免不必要的处理。
if (SocketEvent.TIMEOUT == status &&
(processor == null ||
!processor.isAsync() && !processor.isUpgrade() ||
processor.isAsync() && !processor.checkAsyncTimeoutGeneration())) {
// 这实际上是一个NO-OP
return SocketState.OPEN;
}
if (processor != null) {
// 确保异步超时不会触发
getProtocol().removeWaitingProcessor(processor);
} else if (status == SocketEvent.DISCONNECT || status == SocketEvent.ERROR) {
// 没事做。端点请求关闭,并且不再有与此套接字关联的处理器。
return SocketState.CLOSED;
}
// 标记当前的线程为容器线程 通过ThreadLocal
ContainerThreadMarker.set();
try {
if (processor == null) {
String negotiatedProtocol = wrapper.getNegotiatedProtocol();
// 当未协商任何协议时,OpenSSL通常返回null,而JSSE通常返回“”
if (negotiatedProtocol != null && negotiatedProtocol.length() > 0) {
UpgradeProtocol upgradeProtocol = getProtocol().getNegotiatedProtocol(negotiatedProtocol);
if (upgradeProtocol != null) {
processor = upgradeProtocol.getProcessor(wrapper, getProtocol().getAdapter());
if (getLog().isDebugEnabled()) {
getLog().debug(sm.getString("abstractConnectionHandler.processorCreate", processor));
}
} else if (negotiatedProtocol.equals("http/1.1")) {
// 明确协商默认协议。在下面获取处理器。
} else {
// TODO:
// 如果无法协商任何协议,则OpenSSL 1.0.2的ALPN回调不支持握手失败并显示错误。
// 因此,我们需要在这里使连接失败。解决此问题后,将下面的代码替换为注释掉的代码块。
if (getLog().isDebugEnabled()) {
getLog().debug(sm.getString("abstractConnectionHandler.negotiatedProcessor.fail",
negotiatedProtocol));
}
return SocketState.CLOSED;
/*
* 使用OpenSSL 1.1.0替换上面的代码。
// Failed to create processor. This is a bug.
throw new IllegalStateException(sm.getString(
"abstractConnectionHandler.negotiatedProcessor.fail",
negotiatedProtocol));
*/
}
}
}
if (processor == null) {
processor = recycledProcessors.pop();
if (getLog().isDebugEnabled()) {
getLog().debug(sm.getString("abstractConnectionHandler.processorPop", processor));
}
}
if (processor == null) {
processor = getProtocol().createProcessor();
register(processor);
if (getLog().isDebugEnabled()) {
getLog().debug(sm.getString("abstractConnectionHandler.processorCreate", processor));
}
}
processor.setSslSupport(
wrapper.getSslSupport(getProtocol().getClientCertProvider()));
// 将处理器与连接关联
connections.put(socket, processor);
SocketState state = SocketState.CLOSED;
do {
state = processor.process(wrapper, status);
if (state == SocketState.UPGRADING) {
// 获取HTTP升级处理程序
UpgradeToken upgradeToken = processor.getUpgradeToken();
// 检索剩余的输入
ByteBuffer leftOverInput = processor.getLeftoverInput();
if (upgradeToken == null) {
// 假设直接HTTP2连接
UpgradeProtocol upgradeProtocol = getProtocol().getUpgradeProtocol("h2c");
if (upgradeProtocol != null) {
// 释放要重新使用的Http11处理器
release(processor);
// 创建升级处理器
processor = upgradeProtocol.getProcessor(wrapper, getProtocol().getAdapter());
wrapper.unRead(leftOverInput);
// 将处理器与连接相关联
connections.put(socket, processor);
} else {
if (getLog().isDebugEnabled()) {
getLog().debug(sm.getString(
"abstractConnectionHandler.negotiatedProcessor.fail",
"h2c"));
}
// 退出循环并触发适当的清理
state = SocketState.CLOSED;
}
} else {
HttpUpgradeHandler httpUpgradeHandler = upgradeToken.getHttpUpgradeHandler();
// 释放要重新使用的Http11处理器
release(processor);
//创建升级处理器
processor = getProtocol().createUpgradeProcessor(wrapper, upgradeToken);
if (getLog().isDebugEnabled()) {
getLog().debug(sm.getString("abstractConnectionHandler.upgradeCreate",
processor, wrapper));
}
wrapper.unRead(leftOverInput);
// 将处理器与连接相关联
connections.put(socket, processor);
// 初始化升级处理程序(这可能会使用新协议触发某些IO,这就是为什么上面的行是必需的)的原因此转换应该是安全的。
// 如果失败,则对周围trycatch的错误处理将对其进行处理。
if (upgradeToken.getInstanceManager() == null) {
httpUpgradeHandler.init((WebConnection) processor);
} else {
ClassLoader oldCL = upgradeToken.getContextBind().bind(false, null);
try {
httpUpgradeHandler.init((WebConnection) processor);
} finally {
upgradeToken.getContextBind().unbind(false, oldCL);
}
}
}
}
} while ( state == SocketState.UPGRADING);
if (state == SocketState.LONG) {
// 在处理请求响应时。保持插槽与处理器关联。确切要求取决于长期民意调查的类型
longPoll(wrapper, processor);
if (processor.isAsync()) {
getProtocol().addWaitingProcessor(processor);
}
} else if (state == SocketState.OPEN) {
// 在保持活动状态但在请求之间。单击确定以回收处理器。继续轮询下一个请求。
connections.remove(socket);
release(processor);
// 注册阅读事件
wrapper.registerReadInterest();
} else if (state == SocketState.SENDFILE) {
// 发送文件正在进行中。如果失败,则插座将关闭。
// 如果可行,则将套接字添加到轮询器(或等效轮询器)以等待更多数据,或者在剩余任何流水线请求的情况下进行处理。
} else if (state == SocketState.UPGRADED) {
// 如果这是非阻塞写操作,请不要将套接字添加回轮询器,
// 否则轮询器可能会触发多个读取事件,这可能导致连接器中的线程不足。
// 如有必要,write()方法将将此套接字添加到轮询器。
if (status != SocketEvent.OPEN_WRITE) {
longPoll(wrapper, processor);
getProtocol().addWaitingProcessor(processor);
}
} else if (state == SocketState.SUSPENDED) {
// 不要将套接字添加回轮询器。 resumeProcessing()方法会将这个套接字添加到轮询器中。
} else {
// 连接已关闭。单击确定以回收处理器。处理升级的处理器需要在发布之前进行额外的清理。
connections.remove(socket);
if (processor.isUpgrade()) {
UpgradeToken upgradeToken = processor.getUpgradeToken();
HttpUpgradeHandler httpUpgradeHandler = upgradeToken.getHttpUpgradeHandler();
InstanceManager instanceManager = upgradeToken.getInstanceManager();
if (instanceManager == null) {
httpUpgradeHandler.destroy();
} else {
ClassLoader oldCL = upgradeToken.getContextBind().bind(false, null);
try {
httpUpgradeHandler.destroy();
} finally {
try {
instanceManager.destroyInstance(httpUpgradeHandler);
} catch (Throwable e) {
ExceptionUtils.handleThrowable(e);
getLog().error(sm.getString("abstractConnectionHandler.error"), e);
}
upgradeToken.getContextBind().unbind(false, oldCL);
}
}
}
release(processor);
}
return state;
} catch(java.net.SocketException e) {
// SocketException是正常的
getLog().debug(sm.getString(
"abstractConnectionHandler.socketexception.debug"), e);
} catch (java.io.IOException e) {
// IOExceptions are normal
getLog().debug(sm.getString(
"abstractConnectionHandler.ioexception.debug"), e);
} catch (ProtocolException e) {
// Protocol exceptions normally mean the client sent invalid or
// incomplete data.
getLog().debug(sm.getString(
"abstractConnectionHandler.protocolexception.debug"), e);
}
// Future developers: if you discover any other
// rare-but-nonfatal exceptions, catch them here, and log as
// above.
catch (OutOfMemoryError oome) {
// Try and handle this here to give Tomcat a chance to close the
// connection and prevent clients waiting until they time out.
// Worst case, it isn't recoverable and the attempt at logging
// will trigger another OOME.
getLog().error(sm.getString("abstractConnectionHandler.oome"), oome);
} catch (Throwable e) {
ExceptionUtils.handleThrowable(e);
// any other exception or error is odd. Here we log it
// with "ERROR" level, so it will show up even on
// less-than-verbose logs.
getLog().error(sm.getString("abstractConnectionHandler.error"), e);
} finally {
ContainerThreadMarker.clear();
}
// Make sure socket/processor is removed from the list of current
// connections
connections.remove(socket);
release(processor);
return SocketState.CLOSED;
}
AbstractProcessorLight.process(SocketWrapperBase<?> socketWrapper, SocketEvent status)
public SocketState process(SocketWrapperBase<?> socketWrapper, SocketEvent status)
throws IOException {
SocketState state = SocketState.CLOSED;
Iterator<DispatchType> dispatches = null;
do {
if (dispatches != null) {
DispatchType nextDispatch = dispatches.next();
if (getLog().isDebugEnabled()) {
getLog().debug("Processing dispatch type: [" + nextDispatch + "]");
}
state = dispatch(nextDispatch.getSocketStatus());
if (!dispatches.hasNext()) {
state = checkForPipelinedData(state, socketWrapper);
}
} else if (status == SocketEvent.DISCONNECT) {
// 在这里什么也不做,只要等待它被回收
} else if (isAsync() || isUpgrade() || state == SocketState.ASYNC_END) {
state = dispatch(status);
state = checkForPipelinedData(state, socketWrapper);
} else if (status == SocketEvent.OPEN_WRITE) {
// 异步后可能会发生额外的写入事件,请忽略
state = SocketState.LONG;
} else if (status == SocketEvent.OPEN_READ) {
state = service(socketWrapper);
} else if (status == SocketEvent.CONNECT_FAIL) {
logAccess(socketWrapper);
} else {
// 如果传入的SocketEvent与Processor的当前状态不一致,则默认为关闭套接字
state = SocketState.CLOSED;
}
if (getLog().isDebugEnabled()) {
getLog().debug("Socket: [" + socketWrapper +
"], Status in: [" + status +
"], State out: [" + state + "]");
}
if (isAsync()) {
state = asyncPostProcess();
if (getLog().isDebugEnabled()) {
getLog().debug("Socket: [" + socketWrapper +
"], State after async post processing: [" + state + "]");
}
}
if (dispatches == null || !dispatches.hasNext()) {
// 仅在有要处理的分派时才返回非null迭代器。
dispatches = getIteratorAndClearDispatches();
}
} while (state == SocketState.ASYNC_END ||
dispatches != null && state != SocketState.CLOSED);
return state;
}
service(socketWrapper);
public SocketState service(SocketWrapperBase<?> socketWrapper)
throws IOException {
RequestInfo rp = request.getRequestProcessor();
// 设置RequestInfo的阶段为解析阶段
rp.setStage(org.apache.coyote.Constants.STAGE_PARSE);
/**
* 设置IO
* 初始化 inputBuffer
* outputBuffer
*/
setSocketWrapper(socketWrapper);
// Flags
keepAlive = true;
openSocket = false;
readComplete = true;
boolean keptAlive = false;
SendfileState sendfileState = SendfileState.DONE;
while (!getErrorState().isError() && keepAlive && !isAsync() && upgradeToken == null &&
sendfileState == SendfileState.DONE && !endpoint.isPaused()) {
// 解析请求头
try {
if (!inputBuffer.parseRequestLine(keptAlive)) {
if (inputBuffer.getParsingRequestLinePhase() == -1) {
return SocketState.UPGRADING;
} else if (handleIncompleteRequestLineRead()) {
break;
}
}
// 处理请求行的协议组件在尝试解析标头之前,
// 需要知道这是否是HTTP 0.9请求。
prepareRequestProtocol();
if (endpoint.isPaused()) {
// 503 - Service unavailable
response.setStatus(503);
setErrorState(ErrorState.CLOSE_CLEAN, null);
} else {
keptAlive = true;
// 每次通过JMX更改限制时都要设置此设置
request.getMimeHeaders().setLimit(endpoint.getMaxHeaderCount());
// 不要解析HTTP0.9的标头
if (!http09 && !inputBuffer.parseHeaders()) {
// We've read part of the request, don't recycle it
// instead associate it with the socket
openSocket = true;
readComplete = false;
break;
}
if (!disableUploadTimeout) {
socketWrapper.setReadTimeout(connectionUploadTimeout);
}
}
} catch (IOException e) {
if (log.isDebugEnabled()) {
log.debug(sm.getString("http11processor.header.parse"), e);
}
setErrorState(ErrorState.CLOSE_CONNECTION_NOW, e);
break;
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
UserDataHelper.Mode logMode = userDataHelper.getNextMode();
if (logMode != null) {
String message = sm.getString("http11processor.header.parse");
switch (logMode) {
case INFO_THEN_DEBUG:
message += sm.getString("http11processor.fallToDebug");
//$FALL-THROUGH$
case INFO:
log.info(message, t);
break;
case DEBUG:
log.debug(message, t);
}
}
// 400 - Bad Request
response.setStatus(400);
setErrorState(ErrorState.CLOSE_CLEAN, t);
}
Object name = request.getAttribute("name");
// 是否要求升级?
if (isConnectionToken(request.getMimeHeaders(), "upgrade")) {
// Check the protocol
String requestedProtocol = request.getHeader("Upgrade");
UpgradeProtocol upgradeProtocol = protocol.getUpgradeProtocol(requestedProtocol);
if (upgradeProtocol != null) {
if (upgradeProtocol.accept(request)) {
// TODO Figure out how to handle request bodies at this
// point.
response.setStatus(HttpServletResponse.SC_SWITCHING_PROTOCOLS);
response.setHeader("Connection", "Upgrade");
response.setHeader("Upgrade", requestedProtocol);
action(ActionCode.CLOSE, null);
getAdapter().log(request, response, 0);
InternalHttpUpgradeHandler upgradeHandler =
upgradeProtocol.getInternalUpgradeHandler(
getAdapter(), cloneRequest(request));
UpgradeToken upgradeToken = new UpgradeToken(upgradeHandler, null, null);
action(ActionCode.UPGRADE, upgradeToken);
return SocketState.UPGRADING;
}
}
}
if (getErrorState().isIoAllowed()) {
// 设置过滤器,并解析一些请求标头
rp.setStage(org.apache.coyote.Constants.STAGE_PREPARE);
try {
prepareRequest();
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
if (log.isDebugEnabled()) {
log.debug(sm.getString("http11processor.request.prepare"), t);
}
// 500 - Internal Server Error
response.setStatus(500);
setErrorState(ErrorState.CLOSE_CLEAN, t);
}
}
if (maxKeepAliveRequests == 1) {
keepAlive = false;
} else if (maxKeepAliveRequests > 0 &&
socketWrapper.decrementKeepAlive() <= 0) {
keepAlive = false;
}
// 在适配器中处理请求
if (getErrorState().isIoAllowed()) {
try {
rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);
getAdapter().service(request, response);
// 处理在发生严重错误之前提交响应的时间。抛出ServletException应该同时将状态设置为500并设置errorException。
// 如果我们在这里失败,则响应可能已经提交,因此我们无法尝试设置标头。
if(keepAlive && !getErrorState().isError() && !isAsync() &&
statusDropsConnection(response.getStatus())) {
setErrorState(ErrorState.CLOSE_CLEAN, null);
}
} catch (InterruptedIOException e) {
setErrorState(ErrorState.CLOSE_CONNECTION_NOW, e);
} catch (HeadersTooLargeException e) {
log.error(sm.getString("http11processor.request.process"), e);
// The response should not have been committed but check it
// anyway to be safe
if (response.isCommitted()) {
setErrorState(ErrorState.CLOSE_NOW, e);
} else {
response.reset();
response.setStatus(500);
setErrorState(ErrorState.CLOSE_CLEAN, e);
response.setHeader("Connection", "close"); // TODO: Remove
}
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
log.error(sm.getString("http11processor.request.process"), t);
// 500 - Internal Server Error
response.setStatus(500);
setErrorState(ErrorState.CLOSE_CLEAN, t);
getAdapter().log(request, response, 0);
}
}
// 完成请求的处理
rp.setStage(org.apache.coyote.Constants.STAGE_ENDINPUT);
if (!isAsync()) {
// 如果这是一个异步请求,则该请求将在完成后结束。在这种情况下,AsyncContext负责调用endRequest()。
endRequest();
}
rp.setStage(org.apache.coyote.Constants.STAGE_ENDOUTPUT);
// 如果有错误,请确保将请求计为和错误,然后更新统计信息计数器
if (getErrorState().isError()) {
response.setStatus(500);
}
if (!isAsync() || getErrorState().isError()) {
request.updateCounters();
if (getErrorState().isIoAllowed()) {
inputBuffer.nextRequest();
outputBuffer.nextRequest();
}
}
if (!disableUploadTimeout) {
int soTimeout = endpoint.getConnectionTimeout();
if(soTimeout > 0) {
socketWrapper.setReadTimeout(soTimeout);
} else {
socketWrapper.setReadTimeout(0);
}
}
rp.setStage(org.apache.coyote.Constants.STAGE_KEEPALIVE);
sendfileState = processSendfile(socketWrapper);
}
rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);
if (getErrorState().isError() || (endpoint.isPaused() && !isAsync())) {
return SocketState.CLOSED;
} else if (isAsync()) {
return SocketState.LONG;
} else if (isUpgrade()) {
return SocketState.UPGRADING;
} else {
if (sendfileState == SendfileState.PENDING) {
return SocketState.SENDFILE;
} else {
if (openSocket) {
if (readComplete) {
return SocketState.OPEN;
} else {
return SocketState.LONG;
}
} else {
return SocketState.CLOSED;
}
}
}
}
- inputBuffer.parseRequestLine(keptAlive)
解析了 method queryString requestURI protocol
boolean parseRequestLine(boolean keptAlive) throws IOException {
//检查状态
if (!parsingRequestLine) {
return true;
}
//
// 跳过空白行
//
if (parsingRequestLinePhase < 2) {
do {
// 如果需要,读取新的字节
if (byteBuffer.position() >= byteBuffer.limit()) {
if (keptAlive) {
// 还没有读取任何请求数据,所以使用keep-alive
// 超时。
wrapper.setReadTimeout(wrapper.getEndpoint().getKeepAliveTimeout());
}
if (!fill(false)) {
// 一个读正在挂起,因此不再处于初始状态
parsingRequestLinePhase = 1;
return false;
}
// 已接收到请求的至少一个字节。
// 切换到socket超时。
wrapper.setReadTimeout(wrapper.getEndpoint().getConnectionTimeout());
}
if (!keptAlive && byteBuffer.position() == 0 && byteBuffer.limit() >= CLIENT_PREFACE_START.length - 1) {
boolean prefaceMatch = true;
for (int i = 0; i < CLIENT_PREFACE_START.length && prefaceMatch; i++) {
if (CLIENT_PREFACE_START[i] != byteBuffer.get(i)) {
prefaceMatch = false;
}
}
if (prefaceMatch) {
// HTTP / 2前言匹配
parsingRequestLinePhase = -1;
return false;
}
}
// 一旦开始读取数据,就设置开始时间(即使它是)
// 跳过空行)
if (request.getStartTime() < 0) {
request.setStartTime(System.currentTimeMillis());
}
chr = byteBuffer.get();
} while ((chr == Constants.CR) || (chr == Constants.LF));
byteBuffer.position(byteBuffer.position() - 1);
parsingRequestLineStart = byteBuffer.position();
parsingRequestLinePhase = 2;
}
if (parsingRequestLinePhase == 2) {
//
// 读取方法名称
// 方法名称是一个标记
//
boolean space = false;
while (!space) {
// 如果需要,读取新的字节
if (byteBuffer.position() >= byteBuffer.limit()) {
if (!fill(false)) // request line parsing
return false;
}
// Spec说方法名称是一个令牌,后跟一个SP,但也可以容忍多个SP和/或HT。
int pos = byteBuffer.position();
chr = byteBuffer.get();
if (chr == Constants.SP || chr == Constants.HT) {
space = true;
request.method().setBytes(byteBuffer.array(), parsingRequestLineStart,
pos - parsingRequestLineStart);
} else if (!HttpParser.isToken(chr)) {
// Avoid unknown protocol triggering an additional error
request.protocol().setString(Constants.HTTP_11);
String invalidMethodValue = parseInvalid(parsingRequestLineStart, byteBuffer);
throw new IllegalArgumentException(sm.getString("iib.invalidmethod", invalidMethodValue));
}
}
parsingRequestLinePhase = 3;
}
if (parsingRequestLinePhase == 3) {
// Spec说单个SP但也可以容忍多个SP和HT
boolean space = true;
while (space) {
// Read new bytes if needed
if (byteBuffer.position() >= byteBuffer.limit()) {
if (!fill(false)) // request line parsing
return false;
}
chr = byteBuffer.get();
if (!(chr == Constants.SP || chr == Constants.HT)) {
space = false;
byteBuffer.position(byteBuffer.position() - 1);
}
}
parsingRequestLineStart = byteBuffer.position();
parsingRequestLinePhase = 4;
}
if (parsingRequestLinePhase == 4) {
// 标记当前缓冲区位置
int end = 0;
//
// 读取URI
//
boolean space = false;
while (!space) {
// 如果需要,读取新的字节
if (byteBuffer.position() >= byteBuffer.limit()) {
if (!fill(false)) // request line parsing
return false;
}
int pos = byteBuffer.position();
prevChr = chr;
chr = byteBuffer.get();
if (prevChr == Constants.CR && chr != Constants.LF) {
// CR后面没有LF,因此没有HTTP0.9请求,因此无效。触发错误处理。避免未知协议触发其他错误
request.protocol().setString(Constants.HTTP_11);
String invalidRequestTarget = parseInvalid(parsingRequestLineStart, byteBuffer);
throw new IllegalArgumentException(sm.getString("iib.invalidRequestTarget", invalidRequestTarget));
}
if (chr == Constants.SP || chr == Constants.HT) {
space = true;
end = pos;
} else if (chr == Constants.CR) {
// HTTP/0.9 style request. CR is optional. LF is not.
} else if (chr == Constants.LF) {
// HTTP/0.9 style request
// Stop this processing loop
space = true;
// Set blank protocol (indicates HTTP/0.9)
request.protocol().setString("");
// Skip the protocol processing
parsingRequestLinePhase = 7;
if (prevChr == Constants.CR) {
end = pos - 1;
} else {
end = pos;
}
} else if (chr == Constants.QUESTION && parsingRequestLineQPos == -1) {
parsingRequestLineQPos = pos;
} else if (parsingRequestLineQPos != -1 && !httpParser.isQueryRelaxed(chr)) {
// Avoid unknown protocol triggering an additional error
request.protocol().setString(Constants.HTTP_11);
// %nn decoding will be checked at the point of decoding
String invalidRequestTarget = parseInvalid(parsingRequestLineStart, byteBuffer);
throw new IllegalArgumentException(sm.getString("iib.invalidRequestTarget", invalidRequestTarget));
} else if (httpParser.isNotRequestTargetRelaxed(chr)) {
// Avoid unknown protocol triggering an additional error
request.protocol().setString(Constants.HTTP_11);
// This is a general check that aims to catch problems early
// Detailed checking of each part of the request target will
// happen in Http11Processor#prepareRequest()
String invalidRequestTarget = parseInvalid(parsingRequestLineStart, byteBuffer);
throw new IllegalArgumentException(sm.getString("iib.invalidRequestTarget", invalidRequestTarget));
}
}
if (parsingRequestLineQPos >= 0) {
request.queryString().setBytes(byteBuffer.array(), parsingRequestLineQPos + 1,
end - parsingRequestLineQPos - 1);
request.requestURI().setBytes(byteBuffer.array(), parsingRequestLineStart,
parsingRequestLineQPos - parsingRequestLineStart);
} else {
request.requestURI().setBytes(byteBuffer.array(), parsingRequestLineStart,
end - parsingRequestLineStart);
}
// HTTP/0.9 处理跳转到第7阶段。
// 我不想在这里覆盖它。
if (parsingRequestLinePhase == 4) {
parsingRequestLinePhase = 5;
}
}
if (parsingRequestLinePhase == 5) {
// 规范说单SP,但也可以忍受多个和/或HT
boolean space = true;
while (space) {
//如果需要,读取新的字节
if (byteBuffer.position() >= byteBuffer.limit()) {
if (!fill(false)) // request line parsing
return false;
}
byte chr = byteBuffer.get();
if (!(chr == Constants.SP || chr == Constants.HT)) {
space = false;
byteBuffer.position(byteBuffer.position() - 1);
}
}
parsingRequestLineStart = byteBuffer.position();
parsingRequestLinePhase = 6;
// Mark the current buffer position
end = 0;
}
if (parsingRequestLinePhase == 6) {
//
//读取协议协议始终是“ HTTP”,“ DIGIT”。数字
//
while (!parsingRequestLineEol) {
// Read new bytes if needed
if (byteBuffer.position() >= byteBuffer.limit()) {
if (!fill(false)) // request line parsing
return false;
}
int pos = byteBuffer.position();
prevChr = chr;
chr = byteBuffer.get();
if (chr == Constants.CR) {
// Possible end of request line. Need LF next.
} else if (prevChr == Constants.CR && chr == Constants.LF) {
end = pos - 1;
parsingRequestLineEol = true;
} else if (!HttpParser.isHttpProtocol(chr)) {
String invalidProtocol = parseInvalid(parsingRequestLineStart, byteBuffer);
throw new IllegalArgumentException(sm.getString("iib.invalidHttpProtocol", invalidProtocol));
}
}
if ((end - parsingRequestLineStart) > 0) {
request.protocol().setBytes(byteBuffer.array(), parsingRequestLineStart,
end - parsingRequestLineStart);
parsingRequestLinePhase = 7;
}
// 如果未找到协议,则将触发以下ISE。
}
if (parsingRequestLinePhase == 7) {
// 解析完成。返回和清理。
parsingRequestLine = false;
parsingRequestLinePhase = 0;
parsingRequestLineEol = false;
parsingRequestLineStart = 0;
return true;
}
throw new IllegalStateException(sm.getString("iib.invalidPhase", Integer.valueOf(parsingRequestLinePhase)));
}
- prepareRequestProtocol()
根据protocol() 赋值 http09 http11protocolMB.strValue
private void prepareRequestProtocol() {
MessageBytes protocolMB = request.protocol();
if (protocolMB.equals(Constants.HTTP_11)) {
http09 = false;
http11 = true;
protocolMB.setString(Constants.HTTP_11);
} else if (protocolMB.equals(Constants.HTTP_10)) {
http09 = false;
http11 = false;
keepAlive = false;
protocolMB.setString(Constants.HTTP_10);
} else if (protocolMB.equals("")) {
// HTTP/0.9
http09 = true;
http11 = false;
keepAlive = false;
} else {
// 不受支持的协议
http09 = false;
http11 = false;
// 发送505;不支持的HTTP版本
response.setStatus(505);
setErrorState(ErrorState.CLOSE_CLEAN, null);
if (log.isDebugEnabled()) {
log.debug(sm.getString("http11processor.request.prepare")+
" Unsupported HTTP version \""+protocolMB+"\"");
}
}
}
- inputBuffer.parseHeaders()
boolean parseHeaders() throws IOException {
if (!parsingHeader) {
throw new IllegalStateException(sm.getString("iib.parseheaders.ise.error"));
}
HeaderParseStatus status = HeaderParseStatus.HAVE_MORE_HEADERS;
do {
status = parseHeader();
// 检查
// (1) 标头和请求行的大小不超过其限制
// (2) 有足够的字节可以避免在以下情况下扩展缓冲区阅读正文从技术上讲,
// (2)是技术限制,
// (1)是逻辑
// 限制强制执行headerBufferSize的含义
// 从如何分配buf以及如何创建空白行开始读取,仅检查(1)就足够了。
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;
}
}
private HeaderParseStatus parseHeader() throws IOException {
while (headerParsePos == HeaderParsePosition.HEADER_START) {
// 如果需要,读取新的字节
if (byteBuffer.position() >= byteBuffer.limit()) {
if (!fill(false)) {// parse header
headerParsePos = HeaderParsePosition.HEADER_START;
return HeaderParseStatus.NEED_MORE_DATA;
}
}
prevChr = chr;
chr = byteBuffer.get();
if (chr == Constants.CR && prevChr != Constants.CR) {
// CRLF的可能开始-处理下一个字节。
} else if (prevChr == Constants.CR && chr == Constants.LF) {
return HeaderParseStatus.DONE;
} else {
if (prevChr == Constants.CR) {
// 必须读取了两个字节(第一个是CR,第二个不是LF)
byteBuffer.position(byteBuffer.position() - 2);
} else {
// 必须只读取一个字节
byteBuffer.position(byteBuffer.position() - 1);
}
break;
}
}
if (headerParsePos == HeaderParsePosition.HEADER_START) {
// 标记当前缓冲区位置
headerData.start = byteBuffer.position();
headerData.lineStart = headerData.start;
headerParsePos = HeaderParsePosition.HEADER_NAME;
}
//
// 读取头名称
// 标题名称总是US-ASCII
//
while (headerParsePos == HeaderParsePosition.HEADER_NAME) {
// 如果需要,读取新字节
if (byteBuffer.position() >= byteBuffer.limit()) {
if (!fill(false)) { // parse header
return HeaderParseStatus.NEED_MORE_DATA;
}
}
int pos = byteBuffer.position();
chr = byteBuffer.get();
// 判断如果读取到了冒号(:)
if (chr == Constants.COLON) {
headerParsePos = HeaderParsePosition.HEADER_VALUE_START;
//添加header请求头的值
headerData.headerValue = headers.addValue(byteBuffer.array(), headerData.start,
pos - headerData.start);
pos = byteBuffer.position();
// 标记当前缓冲区位置
headerData.start = pos;
headerData.realPos = pos;
headerData.lastSignificantChar = pos;
break;
} else if (!HttpParser.isToken(chr)) {
// 在头名称中非标记字符是非法的
// 解析继续进行,以便可以在上下文中报告错误
headerData.lastSignificantChar = pos;
byteBuffer.position(byteBuffer.position() - 1);
// skipLine() will handle the error
return skipLine();
}
// CHR是头名称的下一个字节。转换为小写的。
if ((chr >= Constants.A) && (chr <= Constants.Z)) {
byteBuffer.put(pos, (byte) (chr - Constants.LC_OFFSET));
}
}
// 跳过这一行,忽略标题
if (headerParsePos == HeaderParsePosition.HEADER_SKIPLINE) {
return skipLine();
}
//
// 读取标题值(可以跨多行)
//
while (headerParsePos == HeaderParsePosition.HEADER_VALUE_START ||
headerParsePos == HeaderParsePosition.HEADER_VALUE ||
headerParsePos == HeaderParsePosition.HEADER_MULTI_LINE) {
if (headerParsePos == HeaderParsePosition.HEADER_VALUE_START) {
// 跳过空格
while (true) {
// 如果需要,读取新字节
if (byteBuffer.position() >= byteBuffer.limit()) {
if (!fill(false)) {// 解析头
// HEADER_VALUE_START
return HeaderParseStatus.NEED_MORE_DATA;
}
}
chr = byteBuffer.get();
if (!(chr == Constants.SP || chr == Constants.HT)) {
headerParsePos = HeaderParsePosition.HEADER_VALUE;
byteBuffer.position(byteBuffer.position() - 1);
break;
}
}
}
if (headerParsePos == HeaderParsePosition.HEADER_VALUE) {
// 读取字节直到行尾
boolean eol = false;
while (!eol) {
// 如果需要,读取新字节
if (byteBuffer.position() >= byteBuffer.limit()) {
if (!fill(false)) {// parse header
// HEADER_VALUE
return HeaderParseStatus.NEED_MORE_DATA;
}
}
prevChr = chr;
chr = byteBuffer.get();
if (chr == Constants.CR) {
// 可能的CRLF开始-处理下一个字节。
} else if (prevChr == Constants.CR && chr == Constants.LF) {
eol = true;
} else if (prevChr == Constants.CR) {
// 无效值
// 删除标题(它将是最近的一个)
headers.removeHeader(headers.size() - 1);
return skipLine();
} else if (chr != Constants.HT && HttpParser.isControl(chr)) {
// 无效值
// 删除标题(它将是最近的一个)
headers.removeHeader(headers.size() - 1);
return skipLine();
} else if (chr == Constants.SP || chr == Constants.HT) {
byteBuffer.put(headerData.realPos, chr);
headerData.realPos++;
} else {
byteBuffer.put(headerData.realPos, chr);
headerData.realPos++;
headerData.lastSignificantChar = headerData.realPos;
}
}
// 忽略行尾的空白
headerData.realPos = headerData.lastSignificantChar;
// 检查新行第一个字符。如果字符
// 如果它是一个LWS,那么它是一个多行头文件
headerParsePos = HeaderParsePosition.HEADER_MULTI_LINE;
}
// 如果需要,读取新字节
if (byteBuffer.position() >= byteBuffer.limit()) {
if (!fill(false)) {// parse header
// HEADER_MULTI_LINE
return HeaderParseStatus.NEED_MORE_DATA;
}
}
byte peek = byteBuffer.get(byteBuffer.position());
if (headerParsePos == HeaderParsePosition.HEADER_MULTI_LINE) {
if ((peek != Constants.SP) && (peek != Constants.HT)) {
headerParsePos = HeaderParsePosition.HEADER_START;
break;
} else {
// 在缓冲区中复制一个额外的空间(因为必须行与行之间至少有一个空格)
byteBuffer.put(headerData.realPos, peek);
headerData.realPos++;
headerParsePos = HeaderParsePosition.HEADER_VALUE_START;
}
}
}
// 设置头部值
headerData.headerValue.setBytes(byteBuffer.array(), headerData.start,
headerData.lastSignificantChar - headerData.start);
headerData.recycle();
return HeaderParseStatus.HAVE_MORE_HEADERS;
}
- prepareRequest()
private void prepareRequest() throws IOException {
contentDelimitation = false;
if (endpoint.isSSLEnabled()) {
request.scheme().setString("https");
}
MimeHeaders headers = request.getMimeHeaders();
// 检查连接头
MessageBytes connectionValueMB = headers.getValue(Constants.CONNECTION);
if (connectionValueMB != null && !connectionValueMB.isNull()) {
Set<String> tokens = new HashSet<>();
TokenList.parseTokenList(headers.values(Constants.CONNECTION), tokens);
if (tokens.contains(Constants.CLOSE)) {
keepAlive = false;
} else if (tokens.contains(Constants.KEEP_ALIVE_HEADER_VALUE_TOKEN)) {
keepAlive = true;
}
}
/**
* 检查expect请求头
*/
if (http11) {
MessageBytes expectMB = headers.getValue("expect");
if (expectMB != null && !expectMB.isNull()) {
if (expectMB.toString().trim().equalsIgnoreCase("100-continue")) {
inputBuffer.setSwallowInput(false);
request.setExpectation(true);
} else {
response.setStatus(HttpServletResponse.SC_EXPECTATION_FAILED);
setErrorState(ErrorState.CLOSE_CLEAN, null);
}
}
}
// 检查用户代理标头
if (restrictedUserAgents != null && (http11 || keepAlive)) {
MessageBytes userAgentValueMB = headers.getValue("user-agent");
// 签入限制列表,并调整http11和相应的keepAlive标志
if(userAgentValueMB != null && !userAgentValueMB.isNull()) {
String userAgentValue = userAgentValueMB.toString();
if (restrictedUserAgents != null &&
restrictedUserAgents.matcher(userAgentValue).matches()) {
http11 = false;
keepAlive = false;
}
}
}
// 检查host header
MessageBytes hostValueMB = null;
try {
hostValueMB = headers.getUniqueValue("host");
} catch (IllegalArgumentException iae) {
// 不允许使用多个主机头
badRequest("http11processor.request.multipleHosts");
}
if (http11 && hostValueMB == null) {
badRequest("http11processor.request.noHostHeader");
}
// 检查绝对URI减去在请求行解析期间已删除的查询字符串
ByteChunk uriBC = request.requestURI().getByteChunk();
byte[] uriB = uriBC.getBytes();
if (uriBC.startsWithIgnoreCase("http", 0)) {
int pos = 4;
// 检查https
if (uriBC.startsWithIgnoreCase("s", pos)) {
pos++;
}
// 接下来的3个字符必须为“://”
if (uriBC.startsWith("://", pos)) {
pos += 3;
int uriBCStart = uriBC.getStart();
//'/'没有出现在权限中,因此请使用第一个实例以分割权限和路径段
int slashPos = uriBC.indexOf('/', pos);
// 权限中的“ @”分隔用户信息
int atPos = uriBC.indexOf('@', pos);
if (slashPos > -1 && atPos > slashPos) {
// 第一个“ @”在路径段中,因此没有userinfo
atPos = -1;
}
if (slashPos == -1) {
slashPos = uriBC.getLength();
// 将URI设置为“ /”。 使用6,因为它将始终为'/'。
// 01234567
// http://
// https://
request.requestURI().setBytes(uriB, uriBCStart + 6, 1);
} else {
request.requestURI().setBytes(uriB, uriBCStart + slashPos, uriBC.getLength() - slashPos);
}
// 跳过任何用户信息
if (atPos != -1) {
// 验证用户信息
for (; pos < atPos; pos++) {
byte c = uriB[uriBCStart + pos];
if (!HttpParser.isUserInfo(c)) {
// 严格需要检查有效的%nn
// 在这里编码,但请跳过它,
// 因为它永远不会解码,因为忽略了userinfo
badRequest("http11processor.request.invalidUserInfo");
break;
}
}
// 跳过“ @”
pos = atPos + 1;
}
if (http11) {
// 缺少主机头是非法的,但已在上面进行了处理
if (hostValueMB != null) {
// 请求行中的任何主机都必须与Host标头一致
if (!hostValueMB.getByteChunk().equals(
uriB, uriBCStart + pos, slashPos - pos)) {
if (protocol.getAllowHostHeaderMismatch()) {
//正在应用RFC 2616的要求。
// 如果主机标头和请求行不一致,则请求行优先
hostValueMB = headers.setValue("host");
hostValueMB.setBytes(uriB, uriBCStart + pos, slashPos - pos);
} else {
// 正在应用RFC 7230的要求。
// 如果主机标头和请求行不一致,则触发400响应。
badRequest("http11processor.request.inconsistentHosts");
}
}
}
} else {
// 不是HTTP / 1.1-没有主机标头,
// 因此会生成一个标头,因为Tomcat内部假设已设置该标头
try {
hostValueMB = headers.setValue("host");
hostValueMB.setBytes(uriB, uriBCStart + pos, slashPos - pos);
} catch (IllegalStateException e) {
// 边缘情况如果请求中的标头太多,将无法创建主机标头。
// 忽略这一点是因为处理不会达到Tomcat内部人员期望的主机标头的程度。
}
}
} else {
badRequest("http11processor.request.invalidScheme");
}
}
// 验证URI中的字符。 %nn解码将在解码时检查。
for (int i = uriBC.getStart(); i < uriBC.getEnd(); i++) {
if (!httpParser.isAbsolutePathRelaxed(uriB[i])) {
badRequest("http11processor.request.invalidUri");
break;
}
}
// 输入过滤器设置
InputFilter[] inputFilters = inputBuffer.getFilters();
// 解析传输编码标头
if (http11) {
MessageBytes transferEncodingValueMB = headers.getValue("transfer-encoding");
if (transferEncodingValueMB != null) {
List<String> encodingNames = new ArrayList<>();
if (TokenList.parseTokenList(headers.values("transfer-encoding"), encodingNames)) {
for (String encodingName : encodingNames) {
// “身份”编码被忽略
addInputFilter(inputFilters, encodingName);
}
} else {
// 无效的传输编码
badRequest("http11processor.request.invalidTransferEncoding");
}
}
}
// 解析内容长度标头
long contentLength = -1;
try {
contentLength = request.getContentLengthLong();
} catch (NumberFormatException e) {
badRequest("http11processor.request.nonNumericContentLength");
} catch (IllegalArgumentException e) {
badRequest("http11processor.request.multipleContentLength");
}
if (contentLength >= 0) {
if (contentDelimitation) {
//此时的contentDelimitation为true表示正在使用分块编码,但不应将分块编码与内容长度一起使用。
//RFC 2616第4.4节,项目3指出在这种情况下必须忽略Content-Length-
//所以删除它。
headers.removeHeader("content-length");
request.setContentLength(-1);
} else {
inputBuffer.addActiveFilter(inputFilters[Constants.IDENTITY_FILTER]);
contentDelimitation = true;
}
}
// 验证主机名并提取端口(如果存在)
parseHost(hostValueMB);
if (!contentDelimitation) {
// 如果没有内容长度(HTTP1.0或HTTP1.1损坏),则假定客户端未损坏且未发送正文
inputBuffer.addActiveFilter(inputFilters[Constants.VOID_FILTER]);
contentDelimitation = true;
}
if (!getErrorState().isIoAllowed()) {
getAdapter().log(request, response, 0);
}
}
CoyoteAdapter.service(org.apache.coyote.Request req, org.apache.coyote.Response res)
public void service(org.apache.coyote.Request req, org.apache.coyote.Response res)
throws Exception {
Request request = (Request) req.getNote(ADAPTER_NOTES);
Response response = (Response) res.getNote(ADAPTER_NOTES);
if (request == null) {
// 创建Request对象
request = connector.createRequest();
// 设置coyoteRequest 和关联inputBuffer的coyoteRequest
request.setCoyoteRequest(req);
response = connector.createResponse();
// 设置coyoteResponse 和关联outputBuffer的coyoteResponse
response.setCoyoteResponse(res);
// 链接对象
request.setResponse(response);
response.setRequest(request);
// 将connector的req和res设为coyote的笔记
req.setNote(ADAPTER_NOTES, request);
res.setNote(ADAPTER_NOTES, response);
// 设置查询字符串编码
req.getParameters().setQueryStringCharset(connector.getURICharset());
}
if (connector.getXpoweredBy()) {
response.addHeader("X-Powered-By", POWERED_BY);
}
boolean async = false;
boolean postParseSuccess = false;
// 设置reqProcessorMX的workerThreadName为当前线程名
req.getRequestProcessor().setWorkerThreadName(THREAD_NAME.get());
try {
// 解析并设置Catalina和特定于配置的请求参数
postParseSuccess = postParseRequest(req, request, res, response);
if (postParseSuccess) {
//如果我们支持异步止回阀
request.setAsyncSupported(
connector.getService().getContainer().getPipeline().isAsyncSupported());
// 调用容器
connector.getService().getContainer().getPipeline().getFirst().invoke(
request, response);
}
if (request.isAsync()) {
async = true;
ReadListener readListener = req.getReadListener();
if (readListener != null && request.isFinished()) {
// 可能在service()期间已读取所有数据
// 方法,因此需要在此处进行检查
ClassLoader oldCL = null;
try {
oldCL = request.getContext().bind(false, null);
if (req.sendAllDataReadEvent()) {
req.getReadListener().onAllDataRead();
}
} finally {
request.getContext().unbind(false, oldCL);
}
}
Throwable throwable =
(Throwable) request.getAttribute(RequestDispatcher.ERROR_EXCEPTION);
// 如果启动了异步请求,则该请求不会一次结束
// 此容器线程完成并且发生错误,触发
// 异步错误过程
if (!request.isAsyncCompleting() && throwable != null) {
request.getAsyncContextInternal().setErrorState(throwable, true);
}
} else {
request.finishRequest();
response.finishResponse();
}
} catch (IOException e) {
// 忽略
} finally {
AtomicBoolean error = new AtomicBoolean(false);
res.action(ActionCode.IS_ERROR, error);
if (request.isAsyncCompleting() && error.get()) {
// 连接将被强行关闭,这将阻止
// 完成是在通常的时间点进行的。 需要触发
// 在此处调用onComplete()。
res.action(ActionCode.ASYNC_POST_PROCESS, null);
async = false;
}
// 访问日志
if (!async && postParseSuccess) {
// 仅在调用处理后才记录日志。
// 如果postParseRequest()失败,则它已经记录了它。
Context context = request.getContext();
Host host = request.getHost();
// 如果上下文为空,则端点可能是
// 关闭,此连接已关闭,并且请求在其中回收
// 一个不同的线程。 该线程将更新访问权限
// 日志,这样就可以在此处不更新访问日志了
// 案件。
// 他的另一种可能性是在早期发生了错误
// 处理,并且请求无法映射到上下文。
// 在这种情况下,通过主机或引擎登录。
long time = System.currentTimeMillis() - req.getStartTime();
if (context != null) {
context.logAccess(request, response, time, false);
} else if (response.isError()) {
if (host != null) {
host.logAccess(request, response, time, false);
} else {
connector.getService().getContainer().logAccess(
request, response, time, false);
}
}
}
req.getRequestProcessor().setWorkerThreadName(null);
// 回收包装器请求和响应
if (!async) {
updateWrapperErrorCount(request, response);
request.recycle();
response.recycle();
}
}
}
StandardEngineValve.invoke(Request request, Response response)
public final void invoke(Request request, Response response)
throws IOException, ServletException {
// 选择用于此请求的主机
Host host = request.getHost();
if (host == null) {
// 如果未定义默认主机,则没有主机的HTTP 0.9或HTTP 1.0请求。不要覆盖现有错误
if (!response.isError()) {
response.sendError(404);
}
return;
}
if (request.isAsyncSupported()) {
request.setAsyncSupported(host.getPipeline().isAsyncSupported());
}
// 要求Host处理此请求
host.getPipeline().getFirst().invoke(request, response);
}
AbstractAccessLogValve.invoke(Request request, Response response)
public void invoke(Request request, Response response) throws IOException,
ServletException {
if (tlsAttributeRequired) {
// 日志模式使用TLS属性。确保在处理请求之前已填充这些文件,
// 因为使用NIO2可以在访问日志请求TLS信息之前关闭连接(并且TLS信息丢失)。现在,请求它会使它被缓存在请求中。
request.getAttribute(Globals.CERTIFICATES_ATTR);
}
if (cachedElements != null) {
for (CachedElement element : cachedElements) {
element.cache(request);
}
}
getNext().invoke(request, response);
}
ErrorReportValve.invoke(Request request, Response response)
public void invoke(Request request, Response response) throws IOException, ServletException {
// 执行请求
getNext().invoke(request, response);
if (response.isCommitted()) {
if (response.setErrorReported()) {
// 之前未报告过错误,但是我们无法写出错误页面,因为响应已经提交。
// 试图刷新仍要写入客户端的所有数据。
try {
response.flushBuffer();
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
}
// 立即关闭以告知客户发生问题
response.getCoyoteResponse().action(ActionCode.CLOSE_NOW,
request.getAttribute(RequestDispatcher.ERROR_EXCEPTION));
}
return;
}
Throwable throwable = (Throwable) request.getAttribute(RequestDispatcher.ERROR_EXCEPTION);
// 如果异步请求正在进行中,并且一旦此容器线程完成后也不会结束,则不要在此处处理任何错误页面。
if (request.isAsync() && !request.isAsyncCompleting()) {
return;
}
if (throwable != null && !response.isError()) {
// 确保已在响应上调用了必要的方法。
// (有可能一个组件可能只是设置了Throwable。Tomcat不会设置,但其他组件可以。)
// 由于我们知道响应尚未提交,因此可以安全地调用这些组件。
response.reset();
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
// 在执行到这一点并暂停响应之前,将调用一种或另一种方法response.sendError()。
// 需要反转,以便该阀可以写入响应。
response.setSuspended(false);
try {
report(request, response, throwable);
} catch (Throwable tt) {
ExceptionUtils.handleThrowable(tt);
}
}
StandardHostValve.invoke(Request request, Response response)
public final void invoke(Request request, Response response)
throws IOException, ServletException {
// 选择用于此请求的上下文
Context context = request.getContext();
if (context == null) {
// 不要覆盖现有错误
if (!response.isError()) {
response.sendError(404);
}
return;
}
if (request.isAsyncSupported()) {
request.setAsyncSupported(context.getPipeline().isAsyncSupported());
}
boolean asyncAtStart = request.isAsync();
try {
context.bind(Globals.IS_SECURITY_ENABLED, MY_CLASSLOADER);
// 调用request作用域的监听器init方法
if (!asyncAtStart && !context.fireRequestInitEvent(request.getRequest())) {
//在异步处理期间不要触发监听器(监听器为调用startAsync()的请求而触发)。
// 如果请求初始化侦听器引发异常,则该请求将中止。
return;
}
// 要求此上下文处理此请求。
// 必须将已经出错的请求路由到此处,以检查应用程序定义的错误页面,因此请勿将它们转发给应用程序进行处理。
try {
if (!response.isErrorReportRequired()) {
context.getPipeline().getFirst().invoke(request, response);
}
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
container.getLogger().error("Exception Processing " + request.getRequestURI(), t);
// 如果尝试报告先前的错误时发生了新的错误,则允许报告原始错误。
if (!response.isErrorReportRequired()) {
request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, t);
throwable(request, response, t);
}
}
// 现在,请求响应对返回到容器控制之下,抬起悬架,以便完成错误处理和/或容器可以刷新所有剩余数据
response.setSuspended(false);
Throwable t = (Throwable) request.getAttribute(RequestDispatcher.ERROR_EXCEPTION);
// 如果上下文在长时间运行的请求中被破坏,则防止NPE。
if (!context.getState().isAvailable()) {
return;
}
// 查找(并在找到时渲染)应用程序级错误页面
if (response.isErrorReportRequired()) {
// 如果发生了阻止进一步IO的错误,请不要浪费时间生成永远不会被读取的错误报告
AtomicBoolean result = new AtomicBoolean(false);
response.getCoyoteResponse().action(ActionCode.IS_IO_ALLOWED, result);
if (result.get()) {
if (t != null) {
throwable(request, response, t);
} else {
status(request, response);
}
}
}
if (!request.isAsync() && !asyncAtStart) {
context.fireRequestDestroyEvent(request.getRequest());
}
} finally {
// 基于对规范的严格解释,访问会话(如果存在)以更新上次访问时间
if (ACCESS_SESSION) {
request.getSession(false);
}
context.unbind(Globals.IS_SECURITY_ENABLED, MY_CLASSLOADER);
}
}
AuthenticatorBase.invoke(Request request, Response response)
public void invoke(Request request, Response response) throws IOException, ServletException {
if (log.isDebugEnabled()) {
log.debug("Security checking request " + request.getMethod() + " " +
request.getRequestURI());
}
// 我们是否有一个缓存的经过身份验证的主体要记录?
if (cache) {
Principal principal = request.getUserPrincipal();
if (principal == null) {
Session session = request.getSessionInternal(false);
if (session != null) {
principal = session.getPrincipal();
if (principal != null) {
if (log.isDebugEnabled()) {
log.debug("We have cached auth type " + session.getAuthType() +
" for principal " + principal);
}
request.setAuthType(session.getAuthType());
request.setUserPrincipal(principal);
}
}
}
}
boolean authRequired = isContinuationRequired(request);
Realm realm = this.context.getRealm();
// 此请求URI是否受安全性约束?
SecurityConstraint[] constraints = realm.findSecurityConstraints(request, this.context);
AuthConfigProvider jaspicProvider = getJaspicProvider();
if (jaspicProvider != null) {
authRequired = true;
}
if (constraints == null && !context.getPreemptiveAuthentication() && !authRequired) {
if (log.isDebugEnabled()) {
log.debug("Not subject to any constraint");
}
getNext().invoke(request, response);
return;
}
// 确保受约束的资源不会被Web代理或浏览器缓存,因为缓存会提供安全漏洞
if (constraints != null && disableProxyCaching &&
!"POST".equalsIgnoreCase(request.getMethod())) {
if (securePagesWithPragma) {
// 注意:这些可能会导致使用IE下载文件时出现问题
response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "no-cache");
} else {
response.setHeader("Cache-Control", "private");
}
response.setHeader("Expires", DATE_ONE);
}
if (constraints != null) {
// 对此安全性约束实施任何用户数据约束
if (log.isDebugEnabled()) {
log.debug("Calling hasUserDataPermission()");
}
if (!realm.hasUserDataPermission(request, response, constraints)) {
if (log.isDebugEnabled()) {
log.debug("Failed hasUserDataPermission() test");
}
/*
* ASSERT: Authenticator已设置适当的HTTP状态代码,因此我们不必做任何特殊的事情
*/
return;
}
}
// 由于身份验证会修改失败响应,我们必须先检查全部允许。
boolean hasAuthConstraint = false;
if (constraints != null) {
hasAuthConstraint = true;
for (int i = 0; i < constraints.length && hasAuthConstraint; i++) {
if (!constraints[i].getAuthConstraint()) {
hasAuthConstraint = false;
} else if (!constraints[i].getAllRoles() &&
!constraints[i].getAuthenticatedUsers()) {
String[] roles = constraints[i].findAuthRoles();
if (roles == null || roles.length == 0) {
hasAuthConstraint = false;
}
}
}
}
if (!authRequired && hasAuthConstraint) {
authRequired = true;
}
if (!authRequired && context.getPreemptiveAuthentication()) {
authRequired =
request.getCoyoteRequest().getMimeHeaders().getValue("authorization") != null;
}
if (!authRequired && context.getPreemptiveAuthentication() &&
HttpServletRequest.CLIENT_CERT_AUTH.equals(getAuthMethod())) {
X509Certificate[] certs = getRequestCertificates(request);
authRequired = certs != null && certs.length > 0;
}
JaspicState jaspicState = null;
if ((authRequired || constraints != null) && allowCorsPreflightBypass(request)) {
if (log.isDebugEnabled()) {
log.debug("CORS Preflight request bypassing authentication");
}
getNext().invoke(request, response);
return;
}
if (authRequired) {
if (log.isDebugEnabled()) {
log.debug("Calling authenticate()");
}
if (jaspicProvider != null) {
jaspicState = getJaspicState(jaspicProvider, request, response, hasAuthConstraint);
if (jaspicState == null) {
return;
}
}
if (jaspicProvider == null && !doAuthenticate(request, response) ||
jaspicProvider != null &&
!authenticateJaspic(request, response, jaspicState, false)) {
if (log.isDebugEnabled()) {
log.debug("Failed authenticate() test");
}
/*
* ASSERT:身份验证器已设置适当的HTTP状态代码,因此我们不必做任何特殊的事情
*/
return;
}
}
if (constraints != null) {
if (log.isDebugEnabled()) {
log.debug("Calling accessControl()");
}
if (!realm.hasResourcePermission(request, response, constraints, this.context)) {
if (log.isDebugEnabled()) {
log.debug("Failed accessControl() test");
}
/*
* ASSERT: AccessControl method has already set the appropriate
* HTTP status code, so we do not have to do anything special
*/
return;
}
}
// 任何指定的约束均已满足
if (log.isDebugEnabled()) {
log.debug("Successfully passed all security constraints");
}
getNext().invoke(request, response);
if (jaspicProvider != null) {
secureResponseJspic(request, response, jaspicState);
}
}
StandardContextValve.invoke(Request request, Response response)
public final void invoke(Request request, Response response)
throws IOException, ServletException {
// 禁止直接访问WEB-INF或META-INF下的资源
MessageBytes requestPathMB = request.getRequestPathMB();
if ((requestPathMB.startsWithIgnoreCase("/META-INF/", 0))
|| (requestPathMB.equalsIgnoreCase("/META-INF"))
|| (requestPathMB.startsWithIgnoreCase("/WEB-INF/", 0))
|| (requestPathMB.equalsIgnoreCase("/WEB-INF"))) {
response.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}
//选择用于此请求的包装器
Wrapper wrapper = request.getWrapper();
if (wrapper == null || wrapper.isUnavailable()) {
response.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}
try {
// 确认ACK请求
response.sendAcknowledgement(ContinueResponseTiming.IMMEDIATELY);
} catch (IOException ioe) {
container.getLogger().error(sm.getString(
"standardContextValve.acknowledgeException"), ioe);
request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, ioe);
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
return;
}
if (request.isAsyncSupported()) {
request.setAsyncSupported(wrapper.getPipeline().isAsyncSupported());
}
wrapper.getPipeline().getFirst().invoke(request, response);
}
StandardWrapperValve.invoke(Request request, Response response)
public final void invoke(Request request, Response response)
throws IOException, ServletException {
// 初始化可能需要的局部变量
boolean unavailable = false;
Throwable throwable = null;
// 这应该是一个请求属性…
long t1=System.currentTimeMillis();
requestCount.incrementAndGet();
StandardWrapper wrapper = (StandardWrapper) getContainer();
Servlet servlet = null;
Context context = (Context) wrapper.getParent();
// 检查标记为不可用的应用程序
if (!context.getState().isAvailable()) {
response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,
sm.getString("standardContext.isUnavailable"));
unavailable = true;
}
// 检查被标记为不可用的servlet
if (!unavailable && wrapper.isUnavailable()) {
container.getLogger().info(sm.getString("standardWrapper.isUnavailable",
wrapper.getName()));
long available = wrapper.getAvailable();
if ((available > 0L) && (available < Long.MAX_VALUE)) {
response.setDateHeader("Retry-After", available);
response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,
sm.getString("standardWrapper.isUnavailable",
wrapper.getName()));
} else if (available == Long.MAX_VALUE) {
response.sendError(HttpServletResponse.SC_NOT_FOUND,
sm.getString("standardWrapper.notFound",
wrapper.getName()));
}
unavailable = true;
}
// 分配一个servlet实例来处理这个请求
try {
if (!unavailable) {
servlet = wrapper.allocate();
}
} catch (UnavailableException e) {
container.getLogger().error(
sm.getString("standardWrapper.allocateException",
wrapper.getName()), e);
long available = wrapper.getAvailable();
if ((available > 0L) && (available < Long.MAX_VALUE)) {
response.setDateHeader("Retry-After", available);
response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,
sm.getString("standardWrapper.isUnavailable",
wrapper.getName()));
} else if (available == Long.MAX_VALUE) {
response.sendError(HttpServletResponse.SC_NOT_FOUND,
sm.getString("standardWrapper.notFound",
wrapper.getName()));
}
} catch (ServletException e) {
container.getLogger().error(sm.getString("standardWrapper.allocateException",
wrapper.getName()), StandardWrapper.getRootCause(e));
throwable = e;
exception(request, response, e);
} catch (Throwable e) {
ExceptionUtils.handleThrowable(e);
container.getLogger().error(sm.getString("standardWrapper.allocateException",
wrapper.getName()), e);
throwable = e;
exception(request, response, e);
servlet = null;
}
MessageBytes requestPathMB = request.getRequestPathMB();
DispatcherType dispatcherType = DispatcherType.REQUEST;
if (request.getDispatcherType()==DispatcherType.ASYNC) dispatcherType = DispatcherType.ASYNC;
request.setAttribute(Globals.DISPATCHER_TYPE_ATTR,dispatcherType);
request.setAttribute(Globals.DISPATCHER_REQUEST_PATH_ATTR,
requestPathMB);
//:为这个请求创建过滤器链
ApplicationFilterChain filterChain =
ApplicationFilterFactory.createFilterChain(request, wrapper, servlet);
// 调用此请求的过滤器链
// 注意:这也调用了servlet的service()方法
try {
if ((servlet != null) && (filterChain != null)) {
// S如有需要,吞咽量
if (context.getSwallowOutput()) {
try {
SystemLogHandler.startCapture();
if (request.isAsyncDispatching()) {
request.getAsyncContextInternal().doInternalDispatch();
} else {
filterChain.doFilter(request.getRequest(),
response.getResponse());
}
} finally {
String log = SystemLogHandler.stopCapture();
if (log != null && log.length() > 0) {
context.getLogger().info(log);
}
}
} else {
if (request.isAsyncDispatching()) {
request.getAsyncContextInternal().doInternalDispatch();
} else {
filterChain.doFilter
(request.getRequest(), response.getResponse());
}
}
}
} catch (ClientAbortException | CloseNowException e) {
if (container.getLogger().isDebugEnabled()) {
container.getLogger().debug(sm.getString(
"standardWrapper.serviceException", wrapper.getName(),
context.getName()), e);
}
throwable = e;
exception(request, response, e);
} catch (IOException e) {
container.getLogger().error(sm.getString(
"standardWrapper.serviceException", wrapper.getName(),
context.getName()), e);
throwable = e;
exception(request, response, e);
} catch (UnavailableException e) {
container.getLogger().error(sm.getString(
"standardWrapper.serviceException", wrapper.getName(),
context.getName()), e);
// throwable = e;
// exception(request, response, e);
wrapper.unavailable(e);
long available = wrapper.getAvailable();
if ((available > 0L) && (available < Long.MAX_VALUE)) {
response.setDateHeader("Retry-After", available);
response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,
sm.getString("standardWrapper.isUnavailable",
wrapper.getName()));
} else if (available == Long.MAX_VALUE) {
response.sendError(HttpServletResponse.SC_NOT_FOUND,
sm.getString("standardWrapper.notFound",
wrapper.getName()));
}
// 不要将异常保存在“ throwable”中,
// 因为我们不想执行异常(请求,响应,e)处理
} catch (ServletException e) {
Throwable rootCause = StandardWrapper.getRootCause(e);
if (!(rootCause instanceof ClientAbortException)) {
container.getLogger().error(sm.getString(
"standardWrapper.serviceExceptionRoot",
wrapper.getName(), context.getName(), e.getMessage()),
rootCause);
}
throwable = e;
exception(request, response, e);
} catch (Throwable e) {
ExceptionUtils.handleThrowable(e);
container.getLogger().error(sm.getString(
"standardWrapper.serviceException", wrapper.getName(),
context.getName()), e);
throwable = e;
exception(request, response, e);
} finally {
// 释放此请求的过滤器链(如果有)
if (filterChain != null) {
filterChain.release();
}
// 取消分配已分配的servlet实例
try {
if (servlet != null) {
wrapper.deallocate(servlet);
}
} catch (Throwable e) {
ExceptionUtils.handleThrowable(e);
container.getLogger().error(sm.getString("standardWrapper.deallocateException",
wrapper.getName()), e);
if (throwable == null) {
throwable = e;
exception(request, response, e);
}
}
// 如果此servlet被标记为永久不可用,请卸载它并释放该实例
try {
if ((servlet != null) &&
(wrapper.getAvailable() == Long.MAX_VALUE)) {
wrapper.unload();
}
} catch (Throwable e) {
ExceptionUtils.handleThrowable(e);
container.getLogger().error(sm.getString("standardWrapper.unloadException",
wrapper.getName()), e);
if (throwable == null) {
exception(request, response, e);
}
}
long t2=System.currentTimeMillis();
long time=t2-t1;
processingTime += time;
if( time > maxTime) maxTime=time;
if( time < minTime) minTime=time;
}
}
wrapper.allocate()
public Servlet allocate() throws ServletException {
// 如果我们正在卸载这个servlet,抛出一个异常
if (unloading) {
throw new ServletException(sm.getString("standardWrapper.unloading", getName()));
}
boolean newInstance = false;
// 如果不是singlethreaddmodel,则每次返回相同的实例
if (!singleThreadModel) {
// 如果需要,加载并初始化我们的实例
if (instance == null || !instanceInitialized) {
synchronized (this) {
if (instance == null) {
try {
if (log.isDebugEnabled()) {
log.debug("Allocating non-STM instance");
}
// 注意:我们不知道Servlet是否实现了SingleThreadModel直到我们加载它。
instance = loadServlet();
newInstance = true;
if (!singleThreadModel) {
// 对于非stm,这里增加以防止竞赛条件与卸载。Bug 43683,测试用例 # 3
countAllocated.incrementAndGet();
}
} catch (ServletException e) {
throw e;
} catch (Throwable e) {
ExceptionUtils.handleThrowable(e);
throw new ServletException(sm.getString("standardWrapper.allocate"), e);
}
}
if (!instanceInitialized) {
initServlet(instance);
}
}
}
if (singleThreadModel) {
if (newInstance) {
// 必须在以上同步之外做这个,以防止a
// 可能死锁
synchronized (instancePool) {
instancePool.push(instance);
nInstances++;
}
}
} else {
if (log.isTraceEnabled()) {
log.trace(" Returning non-STM instance");
}
// 对于新实例,计数将在
// 创建时间
if (!newInstance) {
countAllocated.incrementAndGet();
}
return instance;
}
}
synchronized (instancePool) {
while (countAllocated.get() >= nInstances) {
// 如果可能,分配一个新的实例,否则等待
if (nInstances < maxInstances) {
try {
instancePool.push(loadServlet());
nInstances++;
} catch (ServletException e) {
throw e;
} catch (Throwable e) {
ExceptionUtils.handleThrowable(e);
throw new ServletException(sm.getString("standardWrapper.allocate"), e);
}
} else {
try {
instancePool.wait();
} catch (InterruptedException e) {
// Ignore
}
}
}
if (log.isTraceEnabled()) {
log.trace(" Returning allocated STM instance");
}
countAllocated.incrementAndGet();
return instancePool.pop();
}
}
loadServlet()
public synchronized Servlet loadServlet() throws ServletException {
// 如果我们已经有一个实例或实例池,则无需执行任何操作
if (!singleThreadModel && (instance != null))
return instance;
PrintStream out = System.out;
if (swallowOutput) {
SystemLogHandler.startCapture();
}
Servlet servlet;
try {
long t1=System.currentTimeMillis();
// 投诉是否未指定servlet类
if (servletClass == null) {
unavailable(null);
throw new ServletException
(sm.getString("standardWrapper.notClass", getName()));
}
InstanceManager instanceManager = ((StandardContext)getParent()).getInstanceManager();
try {
servlet = (Servlet) instanceManager.newInstance(servletClass);
} catch (ClassCastException e) {
unavailable(null);
// 恢复上下文ClassLoader
throw new ServletException
(sm.getString("standardWrapper.notServlet", servletClass), e);
} catch (Throwable e) {
e = ExceptionUtils.unwrapInvocationTargetException(e);
ExceptionUtils.handleThrowable(e);
unavailable(null);
// 为Bugzilla 36630添加了额外的日志语句:
// https://bz.apache.org/bugzilla/show_bug.cgi?id=36630
if(log.isDebugEnabled()) {
log.debug(sm.getString("standardWrapper.instantiate", servletClass), e);
}
// 恢复上下文ClassLoader
throw new ServletException
(sm.getString("standardWrapper.instantiate", servletClass), e);
}
if (multipartConfigElement == null) {
MultipartConfig annotation =
servlet.getClass().getAnnotation(MultipartConfig.class);
if (annotation != null) {
multipartConfigElement =
new MultipartConfigElement(annotation);
}
}
// 对ContainerServlet实例的特殊处理
// 注意:InstanceManager检查是否允许应用程序加载ContainerServlets。
if (servlet instanceof ContainerServlet) {
((ContainerServlet) servlet).setWrapper(this);
}
classLoadTime=(int) (System.currentTimeMillis() -t1);
if (servlet instanceof SingleThreadModel) {
if (instancePool == null) {
instancePool = new Stack<>();
}
singleThreadModel = true;
}
// 调用servlet的init方法
initServlet(servlet);
fireContainerEvent("load", this);
loadTime=System.currentTimeMillis() -t1;
} finally {
if (swallowOutput) {
String log = SystemLogHandler.stopCapture();
if (log != null && log.length() > 0) {
if (getServletContext() != null) {
getServletContext().log(log);
} else {
out.println(log);
}
}
}
}
return servlet;
}
servlet = (Servlet) instanceManager.newInstance(servletClass)
protected Class<?> loadClassMaybePrivileged(final String className,
final ClassLoader classLoader) throws ClassNotFoundException {
Class<?> clazz;
if (SecurityUtil.isPackageProtectionEnabled()) {
try {
clazz = AccessController.doPrivileged(new PrivilegedExceptionAction<Class<?>>() {
@Override
public Class<?> run() throws Exception {
return loadClass(className, classLoader);
}
});
} catch (PrivilegedActionException e) {
Throwable t = e.getCause();
if (t instanceof ClassNotFoundException) {
throw (ClassNotFoundException) t;
}
throw new RuntimeException(t);
}
} else {
clazz = loadClass(className, classLoader);
}
/**
* 检查class
* 不能是ContainerServlet的子类
* 不能是restrictedClasses里面的类
*/
checkAccess(clazz);
return clazz;
}
protected Class<?> loadClass(String className, ClassLoader classLoader)
throws ClassNotFoundException {
/**
* 如果class是org.apache.catalina开头的
* 就用containerClassLoader去加载
*/
if (className.startsWith("org.apache.catalina")) {
return containerClassLoader.loadClass(className);
}
try {
//尝试用containerClassLoader去加载
Class<?> clazz = containerClassLoader.loadClass(className);
if (ContainerServlet.class.isAssignableFrom(clazz)) {
return clazz;
}
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
}
return classLoader.loadClass(className);
}
ApplicationFilterChain filterChain = ApplicationFilterFactory.createFilterChain(request, wrapper, servlet);
public static ApplicationFilterChain createFilterChain(ServletRequest request,
Wrapper wrapper, Servlet servlet) {
// 如果没有servlet要执行,则返回null
if (servlet == null)
return null;
// 创建并初始化一个过滤器链对象
ApplicationFilterChain filterChain = null;
if (request instanceof Request) {
Request req = (Request) request;
if (Globals.IS_SECURITY_ENABLED) {
// Security: Do not recycle
filterChain = new ApplicationFilterChain();
} else {
filterChain = (ApplicationFilterChain) req.getFilterChain();
if (filterChain == null) {
filterChain = new ApplicationFilterChain();
// 设置与请求关联的过滤器链。
req.setFilterChain(filterChain);
}
}
} else {
// 请求调度程序正在使用中
filterChain = new ApplicationFilterChain();
}
// 设置与过滤器链关联的servlet。
filterChain.setServlet(servlet);
filterChain.setServletSupportsAsync(wrapper.isAsyncSupported());
// 获取此上下文的筛选器映射
StandardContext context = (StandardContext) wrapper.getParent();
FilterMap filterMaps[] = context.findFilterMaps();
// 如果没有过滤器映射,我们就完成了
if ((filterMaps == null) || (filterMaps.length == 0))
return filterChain;
// 获取匹配过滤器映射所需的信息
DispatcherType dispatcher =
(DispatcherType) request.getAttribute(Globals.DISPATCHER_TYPE_ATTR);
String requestPath = null;
Object attribute = request.getAttribute(Globals.DISPATCHER_REQUEST_PATH_ATTR);
if (attribute != null){
requestPath = attribute.toString();
}
String servletName = wrapper.getName();
// 将相关的路径映射过滤器添加到此过滤器链
for (FilterMap filterMap : filterMaps) {
if (!matchDispatcher(filterMap, dispatcher)) {
continue;
}
if (!matchFiltersURL(filterMap, requestPath))
continue;
ApplicationFilterConfig filterConfig = (ApplicationFilterConfig)
context.findFilterConfig(filterMap.getFilterName());
if (filterConfig == null) {
// FIXME - log configuration problem
continue;
}
filterChain.addFilter(filterConfig);
}
// 添加与servlet名称第二匹配的过滤器
for (FilterMap filterMap : filterMaps) {
if (!matchDispatcher(filterMap, dispatcher)) {
continue;
}
if (!matchFiltersServlet(filterMap, servletName))
continue;
ApplicationFilterConfig filterConfig = (ApplicationFilterConfig)
context.findFilterConfig(filterMap.getFilterName());
if (filterConfig == null) {
// FIXME - log configuration problem
continue;
}
filterChain.addFilter(filterConfig);
}
// 返回完整的过滤器链
return filterChain;
}
filterChain.doFilter(request.getRequest(),response.getResponse());
public void doFilter(ServletRequest request, ServletResponse response)
throws IOException, ServletException {
if( Globals.IS_SECURITY_ENABLED ) {
final ServletRequest req = request;
final ServletResponse res = response;
try {
java.security.AccessController.doPrivileged(
new java.security.PrivilegedExceptionAction<Void>() {
@Override
public Void run()
throws ServletException, IOException {
internalDoFilter(req,res);
return null;
}
}
);
} catch( PrivilegedActionException pe) {
Exception e = pe.getException();
if (e instanceof ServletException)
throw (ServletException) e;
else if (e instanceof IOException)
throw (IOException) e;
else if (e instanceof RuntimeException)
throw (RuntimeException) e;
else
throw new ServletException(e.getMessage(), e);
}
} else {
internalDoFilter(request,response);
}
}
internalDoFilter(ServletRequest request,ServletResponse response)
private void internalDoFilter(ServletRequest request,
ServletResponse response)
throws IOException, ServletException {
// 如果有一个过滤器,则调用下一个过滤器
if (pos < n) {
ApplicationFilterConfig filterConfig = filters[pos++];
try {
Filter filter = filterConfig.getFilter();
if (request.isAsyncSupported() && "false".equalsIgnoreCase(
filterConfig.getFilterDef().getAsyncSupported())) {
request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR, Boolean.FALSE);
}
if( Globals.IS_SECURITY_ENABLED ) {
final ServletRequest req = request;
final ServletResponse res = response;
Principal principal =
((HttpServletRequest) req).getUserPrincipal();
Object[] args = new Object[]{req, res, this};
SecurityUtil.doAsPrivilege ("doFilter", filter, classType, args, principal);
} else {
filter.doFilter(request, response, this);
}
} catch (IOException | ServletException | RuntimeException e) {
throw e;
} catch (Throwable e) {
e = ExceptionUtils.unwrapInvocationTargetException(e);
ExceptionUtils.handleThrowable(e);
throw new ServletException(sm.getString("filterChain.filter"), e);
}
return;
}
// 我们从链的末端掉了下来——调用servlet实例
try {
if (ApplicationDispatcher.WRAP_SAME_OBJECT) {
lastServicedRequest.set(request);
lastServicedResponse.set(response);
}
if (request.isAsyncSupported() && !servletSupportsAsync) {
request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR,
Boolean.FALSE);
}
// 从此点使用潜在的包装请求
if ((request instanceof HttpServletRequest) &&
(response instanceof HttpServletResponse) &&
Globals.IS_SECURITY_ENABLED ) {
final ServletRequest req = request;
final ServletResponse res = response;
Principal principal =
((HttpServletRequest) req).getUserPrincipal();
Object[] args = new Object[]{req, res};
SecurityUtil.doAsPrivilege("service",
servlet,
classTypeUsedInService,
args,
principal);
} else {
// 调用servlet的service方法
servlet.service(request, response);
}
} catch (IOException | ServletException | RuntimeException e) {
throw e;
} catch (Throwable e) {
e = ExceptionUtils.unwrapInvocationTargetException(e);
ExceptionUtils.handleThrowable(e);
throw new ServletException(sm.getString("filterChain.servlet"), e);
} finally {
if (ApplicationDispatcher.WRAP_SAME_OBJECT) {
lastServicedRequest.set(null);
lastServicedResponse.set(null);
}
}
}
HttpServlet.service(ServletRequest req, ServletResponse res)
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException {
HttpServletRequest request;
HttpServletResponse response;
try {
request = (HttpServletRequest) req;
response = (HttpServletResponse) res;
} catch (ClassCastException e) {
throw new ServletException(lStrings.getString("http.non_http"));
}
service(request, response);
}
HttpServlet.service(HttpServletRequest req, HttpServletResponse resp)
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String method = req.getMethod();
if (method.equals(METHOD_GET)) {
long lastModified = getLastModified(req);
if (lastModified == -1) {
// servlet不支持if-modified-因为,没有理由通过更昂贵的逻辑
doGet(req, resp);
} else {
long ifModifiedSince;
try {
ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
} catch (IllegalArgumentException iae) {
// 无效的日期标头-如同未设置任何内容一样继续进行
ifModifiedSince = -1;
}
if (ifModifiedSince < (lastModified / 1000 * 1000)) {
// 如果servlet mod时间晚了,请调用doGet()向下舍入到最接近的秒以进行适当的比较。
// -1的ifModifiedSince将始终小于
maybeSetLastModified(resp, lastModified);
doGet(req, resp);
} else {
resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
}
}
} else if (method.equals(METHOD_HEAD)) {
long lastModified = getLastModified(req);
maybeSetLastModified(resp, lastModified);
doHead(req, resp);
} else if (method.equals(METHOD_POST)) {
doPost(req, resp);
} else if (method.equals(METHOD_PUT)) {
doPut(req, resp);
} else if (method.equals(METHOD_DELETE)) {
doDelete(req, resp);
} else if (method.equals(METHOD_OPTIONS)) {
doOptions(req,resp);
} else if (method.equals(METHOD_TRACE)) {
doTrace(req,resp);
} else {
//
// 请注意,这意味着该服务器上任何位置的servlet均不支持所请求的任何方法。
//
String errMsg = lStrings.getString("http.method_not_implemented");
Object[] errArgs = new Object[1];
errArgs[0] = method;
errMsg = MessageFormat.format(errMsg, errArgs);
resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
}
}