/* ------------------------------------------------------------ */ public void commitResponse(boolean last) throws IOException { if (!_generator.isCommitted()) { _generator.setResponse(_response.getStatus(), _response.getReason()); try { // If the client was expecting 100 continues, but we sent something // else, then we need to close the connection if (_expect100Continue && _response.getStatus() != 100) _generator.setPersistent(false); _generator.completeHeader(_responseFields, last); } catch (IOException io) { throw io; } catch (RuntimeException e) { LOG.warn("header full: " + e); _response.reset(); _generator.reset(true); _generator.setResponse(HttpStatus.INTERNAL_SERVER_ERROR_500, null); _generator.completeHeader(_responseFields, Generator.LAST); _generator.complete(); throw new HttpException(HttpStatus.INTERNAL_SERVER_ERROR_500); } } if (last) _generator.complete(); }
/* ------------------------------------------------------------ */ protected void handleRequest() throws IOException { boolean error = false; String threadName = null; try { 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. If call is from a non-blocking connector, // then the unhandle will return false only if an async dispatch has // already happened when unhandle is called. For a blocking connector, // the wait for the asynchronous dispatch or timeout actually happens // within the call to unhandle(). final Server server = _server; boolean handling = _request._async.handling() && server != null && server.isRunning(); while (handling) { _request.setHandled(false); String info = null; try { _uri.getPort(); info = URIUtil.canonicalPath(_uri.getDecodedPath()); if (info == null && !_request.getMethod().equals(HttpMethods.CONNECT)) throw new HttpException(400); _request.setPathInfo(info); if (_out != null) _out.reopen(); if (_request._async.isInitial()) { _request.setDispatcherType(DispatcherType.REQUEST); _connector.customize(_endp, _request); server.handle(this); } else { _request.setDispatcherType(DispatcherType.ASYNC); server.handleAsync(this); } } catch (ContinuationThrowable e) { LOG.ignore(e); } catch (EofException e) { LOG.debug(e); error = true; _request.setHandled(true); } catch (RuntimeIOException e) { LOG.debug(e); error = true; _request.setHandled(true); } catch (HttpException e) { LOG.debug(e); error = true; _request.setHandled(true); _response.sendError(e.getStatus(), e.getReason()); } catch (Throwable e) { if (e instanceof ThreadDeath) throw (ThreadDeath) e; LOG.warn(String.valueOf(_uri), e); error = true; _request.setHandled(true); _generator.sendError(info == null ? 400 : 500, null, null, true); } finally { handling = !_request._async.unhandle() && server.isRunning() && _server != null; } } } finally { if (threadName != null) Thread.currentThread().setName(threadName); if (_request._async.isUncompleted()) { _request._async.doComplete(); if (_expect100Continue) { LOG.debug("100 continues not sent"); // We didn't send 100 continues, but the latest interpretation // of the spec (see httpbis) is that the client will either // send the body anyway, or close. So we no longer need to // do anything special here other than make the connection not persistent _expect100Continue = false; if (!_response.isCommitted()) _generator.setPersistent(false); } if (_endp.isOpen()) { if (error) { _endp.shutdownOutput(); _generator.setPersistent(false); if (!_generator.isComplete()) _response.complete(); } else { if (!_response.isCommitted() && !_request.isHandled()) _response.sendError(HttpServletResponse.SC_NOT_FOUND); _response.complete(); if (_generator.isPersistent()) _connector.persist(_endp); } } else { _response.complete(); } _request.setHandled(true); } } }