예제 #1
0
  private void write(ByteBuf buff, boolean end) {
    int readableBytes = buff.readableBytes();
    if (readableBytes == 0 && !end) {
      // nothing to write to the connection just return
      return;
    }

    if (end) {
      completed = true;
    }
    if (!end && !chunked && !contentLengthSet()) {
      throw new IllegalStateException(
          "You must set the Content-Length header to be the total size of the message "
              + "body BEFORE sending any data if you are not using HTTP chunked encoding.");
    }

    written += buff.readableBytes();
    if (conn == null) {
      if (pendingChunks == null) {
        pendingChunks = buff;
      } else {
        CompositeByteBuf pending;
        if (pendingChunks instanceof CompositeByteBuf) {
          pending = (CompositeByteBuf) pendingChunks;
        } else {
          pending = Unpooled.compositeBuffer();
          pending.addComponent(pendingChunks).writerIndex(pendingChunks.writerIndex());
          pendingChunks = pending;
        }
        pending.addComponent(buff).writerIndex(pending.writerIndex() + buff.writerIndex());
      }
      connect();
    } else {
      if (!headWritten) {
        writeHeadWithContent(buff, end);
      } else {
        if (end) {
          if (buff.isReadable()) {
            conn.writeToChannel(new DefaultLastHttpContent(buff, false));
          } else {
            conn.writeToChannel(LastHttpContent.EMPTY_LAST_CONTENT);
          }
        } else {
          conn.writeToChannel(new DefaultHttpContent(buff));
        }
      }
      if (end) {
        conn.reportBytesWritten(written);

        if (respHandler != null) {
          conn.endRequest();
        }
      }
    }
  }
예제 #2
0
 @Override
 public void addContent(ByteBuf buffer, boolean last) throws IOException {
   if (buffer != null) {
     long localsize = buffer.readableBytes();
     if (definedSize > 0 && definedSize < size + localsize) {
       throw new IOException("Out of size: " + (size + localsize) + " > " + definedSize);
     }
     size += localsize;
     if (byteBuf == null) {
       byteBuf = buffer;
     } else if (byteBuf instanceof CompositeByteBuf) {
       CompositeByteBuf cbb = (CompositeByteBuf) byteBuf;
       cbb.addComponent(buffer);
       cbb.writerIndex(cbb.writerIndex() + buffer.readableBytes());
     } else {
       CompositeByteBuf cbb = compositeBuffer();
       cbb.addComponents(byteBuf, buffer);
       cbb.writerIndex(byteBuf.readableBytes() + buffer.readableBytes());
       byteBuf = cbb;
     }
   }
   if (last) {
     completed = true;
   } else {
     if (buffer == null) {
       throw new NullPointerException("buffer");
     }
   }
 }
예제 #3
0
  @Override
  protected void decode(ChannelHandlerContext ctx, HttpObject msg, MessageBuf<Object> out)
      throws Exception {
    FullHttpMessage currentMessage = this.currentMessage;

    if (msg instanceof HttpMessage) {
      assert currentMessage == null;

      HttpMessage m = (HttpMessage) msg;

      // Handle the 'Expect: 100-continue' header if necessary.
      // TODO: Respond with 413 Request Entity Too Large
      //   and discard the traffic or close the connection.
      //       No need to notify the upstream handlers - just log.
      //       If decoding a response, just throw an exception.
      if (is100ContinueExpected(m)) {
        ctx.write(CONTINUE.duplicate());
      }

      if (!m.getDecoderResult().isSuccess()) {
        removeTransferEncodingChunked(m);
        this.currentMessage = null;
        out.add(BufUtil.retain(m));
        return;
      }
      if (msg instanceof HttpRequest) {
        HttpRequest header = (HttpRequest) msg;
        this.currentMessage =
            currentMessage =
                new DefaultFullHttpRequest(
                    header.getProtocolVersion(),
                    header.getMethod(),
                    header.getUri(),
                    Unpooled.compositeBuffer(maxCumulationBufferComponents));
      } else if (msg instanceof HttpResponse) {
        HttpResponse header = (HttpResponse) msg;
        this.currentMessage =
            currentMessage =
                new DefaultFullHttpResponse(
                    header.getProtocolVersion(),
                    header.getStatus(),
                    Unpooled.compositeBuffer(maxCumulationBufferComponents));
      } else {
        throw new Error();
      }

      currentMessage.headers().set(m.headers());

      // A streamed message - initialize the cumulative buffer, and wait for incoming chunks.
      removeTransferEncodingChunked(currentMessage);
    } else if (msg instanceof HttpContent) {
      assert currentMessage != null;

      // Merge the received chunk into the content of the current message.
      HttpContent chunk = (HttpContent) msg;
      CompositeByteBuf content = (CompositeByteBuf) currentMessage.content();

      if (content.readableBytes() > maxContentLength - chunk.content().readableBytes()) {
        // TODO: Respond with 413 Request Entity Too Large
        //   and discard the traffic or close the connection.
        //       No need to notify the upstream handlers - just log.
        //       If decoding a response, just throw an exception.
        throw new TooLongFrameException(
            "HTTP content length exceeded " + maxContentLength + " bytes.");
      }

      // Append the content of the chunk
      if (chunk.content().isReadable()) {
        chunk.retain();
        content.addComponent(chunk.content());
        content.writerIndex(content.writerIndex() + chunk.content().readableBytes());
      }

      final boolean last;
      if (!chunk.getDecoderResult().isSuccess()) {
        currentMessage.setDecoderResult(DecoderResult.failure(chunk.getDecoderResult().cause()));
        last = true;
      } else {
        last = chunk instanceof LastHttpContent;
      }

      if (last) {
        this.currentMessage = null;

        // Merge trailing headers into the message.
        if (chunk instanceof LastHttpContent) {
          LastHttpContent trailer = (LastHttpContent) chunk;
          currentMessage.headers().add(trailer.trailingHeaders());
        }

        // Set the 'Content-Length' header.
        currentMessage
            .headers()
            .set(HttpHeaders.Names.CONTENT_LENGTH, String.valueOf(content.readableBytes()));

        // All done
        out.add(currentMessage);
      }
    } else {
      throw new Error();
    }
  }