/* ------------------------------------------------------------ */
 public void flushResponse() throws IOException {
   try {
     commitResponse(Generator.MORE);
     _generator.flushBuffer();
   } catch (IOException e) {
     throw (e instanceof EofException) ? e : new EofException(e);
   }
 }
  /* ------------------------------------------------------------ */
  public void reset(boolean returnBuffers) {
    _parser.reset();
    if (returnBuffers) _parser.returnBuffers();
    _requestFields.clear();
    _request.recycle();

    _generator.reset(returnBuffers); // TODO maybe only release when low on resources
    _responseFields.clear();
    _response.recycle();

    _uri.clear();
  }
  /**
   * Get the inputStream from the connection.
   *
   * <p>If the associated response has the Expect header set to 100 Continue, then accessing the
   * input stream indicates that the handler/servlet is ready for the request body and thus a 100
   * Continue response is sent.
   *
   * @return The input stream for this connection. The stream will be created if it does not already
   *     exist.
   */
  public ServletInputStream getInputStream() throws IOException {
    // If the client is expecting 100 CONTINUE, then send it now.
    if (_expect100Continue) {
      // is content missing?
      if (((HttpParser) _parser).getHeaderBuffer() == null
          || ((HttpParser) _parser).getHeaderBuffer().length() < 2) {
        if (_generator.isCommitted())
          throw new IllegalStateException("Committed before 100 Continues");

        ((HttpGenerator) _generator).send1xx(HttpStatus.CONTINUE_100);
      }
      _expect100Continue = false;
    }

    if (_in == null) _in = new HttpInput(HttpConnection.this);
    return _in;
  }
 /** Constructor */
 public HttpConnection(Connector connector, EndPoint endpoint, Server server) {
   super(endpoint);
   _uri =
       StringUtil.__UTF8.equals(URIUtil.__CHARSET)
           ? new HttpURI()
           : new EncodedHttpURI(URIUtil.__CHARSET);
   _connector = connector;
   HttpBuffers ab = (HttpBuffers) _connector;
   _parser = new HttpParser(ab.getRequestBuffers(), endpoint, new RequestHandler());
   _requestFields = new HttpFields();
   _responseFields = new HttpFields(server.getMaxCookieVersion());
   _request = new Request(this);
   _response = new Response(this);
   _generator = new HttpGenerator(ab.getResponseBuffers(), _endp);
   _generator.setSendServerVersion(server.getSendServerVersion());
   _server = server;
 }
  /* ------------------------------------------------------------ */
  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();
  }
  /* ------------------------------------------------------------ */
  public void completeResponse() throws IOException {
    if (!_generator.isCommitted()) {
      _generator.setResponse(_response.getStatus(), _response.getReason());
      try {
        _generator.completeHeader(_responseFields, Generator.LAST);
      } catch (IOException io) {
        throw io;
      } catch (RuntimeException e) {
        LOG.warn("header full: " + e);
        LOG.debug(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);
      }
    }

    _generator.complete();
  }
  /* ------------------------------------------------------------ */
  protected HttpConnection(
      Connector connector,
      EndPoint endpoint,
      Server server,
      Parser parser,
      Generator generator,
      Request request) {
    super(endpoint);

    _uri =
        URIUtil.__CHARSET.equals(StringUtil.__UTF8)
            ? new HttpURI()
            : new EncodedHttpURI(URIUtil.__CHARSET);
    _connector = connector;
    _parser = parser;
    _requestFields = new HttpFields();
    _responseFields = new HttpFields(server.getMaxCookieVersion());
    _request = request;
    _response = new Response(this);
    _generator = generator;
    _generator.setSendServerVersion(server.getSendServerVersion());
    _server = server;
  }
 /* ------------------------------------------------------------ */
 public boolean isIdle() {
   return _generator.isIdle() && (_parser.isIdle() || _delayedHandling);
 }
  /* ------------------------------------------------------------ */
  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);
      }
    }
  }
Esempio n. 10
0
 /* ------------------------------------------------------------ */
 public boolean isResponseCommitted() {
   return _generator.isCommitted();
 }