Пример #1
0
    @Override
    protected boolean isContentAlwaysEmpty(HttpMessage msg) {
      final int statusCode = ((HttpResponse) msg).getStatus().code();
      if (statusCode == 100) {
        // 100-continue response should be excluded from paired comparison.
        return true;
      }

      // Get the getMethod of the HTTP request that corresponds to the
      // current response.
      HttpMethod method = queue.poll();

      char firstChar = method.name().charAt(0);
      switch (firstChar) {
        case 'H':
          // According to 4.3, RFC2616:
          // All responses to the HEAD request getMethod MUST NOT include a
          // message-body, even though the presence of entity-header fields
          // might lead one to believe they do.
          if (HttpMethod.HEAD.equals(method)) {
            return true;

            // The following code was inserted to work around the servers
            // that behave incorrectly.  It has been commented out
            // because it does not work with well behaving servers.
            // Please note, even if the 'Transfer-Encoding: chunked'
            // header exists in the HEAD response, the response should
            // have absolutely no content.
            //
            //// Interesting edge case:
            //// Some poorly implemented servers will send a zero-byte
            //// chunk if Transfer-Encoding of the response is 'chunked'.
            ////
            //// return !msg.isChunked();
          }
          break;
        case 'C':
          // Successful CONNECT request results in a response with empty body.
          if (statusCode == 200) {
            if (HttpMethod.CONNECT.equals(method)) {
              // Proxy connection established - Not HTTP anymore.
              done = true;
              queue.clear();
              return true;
            }
          }
          break;
      }

      return super.isContentAlwaysEmpty(msg);
    }
Пример #2
0
  /* ------------------------------------------------------------ */
  public Result generateRequest(
      MetaData.Request info, ByteBuffer header, ByteBuffer chunk, ByteBuffer content, boolean last)
      throws IOException {
    switch (_state) {
      case START:
        {
          if (info == null) return Result.NEED_INFO;

          // Do we need a request header
          if (header == null) return Result.NEED_HEADER;

          // If we have not been told our persistence, set the default
          if (_persistent == null) {
            _persistent = info.getVersion().ordinal() > HttpVersion.HTTP_1_0.ordinal();
            if (!_persistent && HttpMethod.CONNECT.is(info.getMethod())) _persistent = true;
          }

          // prepare the header
          int pos = BufferUtil.flipToFill(header);
          try {
            // generate ResponseLine
            generateRequestLine(info, header);

            if (info.getVersion() == HttpVersion.HTTP_0_9) _noContent = true;
            else generateHeaders(info, header, content, last);

            boolean expect100 =
                info.getFields().contains(HttpHeader.EXPECT, HttpHeaderValue.CONTINUE.asString());

            if (expect100) {
              _state = State.COMMITTED;
            } else {
              // handle the content.
              int len = BufferUtil.length(content);
              if (len > 0) {
                _contentPrepared += len;
                if (isChunking()) prepareChunk(header, len);
              }
              _state = last ? State.COMPLETING : State.COMMITTED;
            }

            return Result.FLUSH;
          } catch (Exception e) {
            String message =
                (e instanceof BufferOverflowException)
                    ? "Request header too large"
                    : e.getMessage();
            throw new IOException(message, e);
          } finally {
            BufferUtil.flipToFlush(header, pos);
          }
        }

      case COMMITTED:
        {
          int len = BufferUtil.length(content);

          if (len > 0) {
            // Do we need a chunk buffer?
            if (isChunking()) {
              // Do we need a chunk buffer?
              if (chunk == null) return Result.NEED_CHUNK;
              BufferUtil.clearToFill(chunk);
              prepareChunk(chunk, len);
              BufferUtil.flipToFlush(chunk, 0);
            }
            _contentPrepared += len;
          }

          if (last) _state = State.COMPLETING;

          return len > 0 ? Result.FLUSH : Result.CONTINUE;
        }

      case COMPLETING:
        {
          if (BufferUtil.hasContent(content)) {
            if (LOG.isDebugEnabled()) LOG.debug("discarding content in COMPLETING");
            BufferUtil.clear(content);
          }

          if (isChunking()) {
            // Do we need a chunk buffer?
            if (chunk == null) return Result.NEED_CHUNK;
            BufferUtil.clearToFill(chunk);
            prepareChunk(chunk, 0);
            BufferUtil.flipToFlush(chunk, 0);
            _endOfContent = EndOfContent.UNKNOWN_CONTENT;
            return Result.FLUSH;
          }

          _state = State.END;
          return Boolean.TRUE.equals(_persistent) ? Result.DONE : Result.SHUTDOWN_OUT;
        }

      case END:
        if (BufferUtil.hasContent(content)) {
          if (LOG.isDebugEnabled()) LOG.debug("discarding content in COMPLETING");
          BufferUtil.clear(content);
        }
        return Result.DONE;

      default:
        throw new IllegalStateException();
    }
  }