@Override public void badMessage(int status, String reason) { if (status < 400 || status > 599) status = HttpStatus.BAD_REQUEST_400; try { if (_state.handling() == Next.CONTINUE) sendResponse( new ResponseInfo(HttpVersion.HTTP_1_1, new HttpFields(), 0, status, reason, false), null, true); } catch (IOException e) { LOG.warn("badMessage", e); } finally { if (_state.unhandle() == Next.COMPLETE) _state.completed(); } }
/** @return True if the channel is ready to continue handling (ie it is not suspended) */ public boolean handle() { LOG.debug("{} handle enter", this); setCurrentHttpChannel(this); String threadName = null; if (LOG.isDebugEnabled()) { threadName = Thread.currentThread().getName(); Thread.currentThread().setName(threadName + " - " + _uri); } // Loop here to handle async request redispatches. // The loop is controlled by the call to async.unhandle in the // finally block below. Unhandle will return false only if an async dispatch has // already happened when unhandle is called. HttpChannelState.Next next = _state.handling(); while (next == Next.CONTINUE && getServer().isRunning()) { boolean error = false; try { _request.setHandled(false); _response.getHttpOutput().reopen(); if (_state.isInitial()) { _request.setTimeStamp(System.currentTimeMillis()); _request.setDispatcherType(DispatcherType.REQUEST); for (HttpConfiguration.Customizer customizer : _configuration.getCustomizers()) customizer.customize(getConnector(), _configuration, _request); getServer().handle(this); } else { if (_request.getHttpChannelState().isExpired()) { _request.setDispatcherType(DispatcherType.ERROR); Throwable ex = _state.getAsyncContextEvent().getThrowable(); String reason = "Async Timeout"; if (ex != null) { reason = "Async Exception"; _request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, ex); } _request.setAttribute(RequestDispatcher.ERROR_STATUS_CODE, new Integer(500)); _request.setAttribute(RequestDispatcher.ERROR_MESSAGE, reason); _request.setAttribute(RequestDispatcher.ERROR_REQUEST_URI, _request.getRequestURI()); _response.setStatusWithReason(500, reason); ErrorHandler eh = _state.getContextHandler().getErrorHandler(); if (eh instanceof ErrorHandler.ErrorPageMapper) { String error_page = ((ErrorHandler.ErrorPageMapper) eh) .getErrorPage( (HttpServletRequest) _state.getAsyncContextEvent().getSuppliedRequest()); if (error_page != null) _state.getAsyncContextEvent().setDispatchPath(error_page); } } else _request.setDispatcherType(DispatcherType.ASYNC); getServer().handleAsync(this); } } catch (Error e) { if ("ContinuationThrowable".equals(e.getClass().getSimpleName())) LOG.ignore(e); else { error = true; throw e; } } catch (Exception e) { error = true; if (e instanceof EofException) LOG.debug(e); else LOG.warn(String.valueOf(_uri), e); _state.error(e); _request.setHandled(true); handleException(e); } finally { if (error && _state.isAsyncStarted()) _state.errorComplete(); next = _state.unhandle(); } } if (threadName != null && LOG.isDebugEnabled()) Thread.currentThread().setName(threadName); setCurrentHttpChannel(null); if (next == Next.COMPLETE) { try { _state.completed(); if (!_response.isCommitted() && !_request.isHandled()) _response.sendError(404); else // Complete generating the response _response.closeOutput(); } catch (EofException | ClosedChannelException e) { LOG.debug(e); } catch (Exception e) { LOG.warn("complete failed", e); } finally { _request.setHandled(true); _transport.completed(); } } LOG.debug("{} handle exit, result {}", this, next); return next != Next.WAIT; }