use of io.netty.handler.codec.http.DefaultHttpContent in project netty by netty.
the class HttpPostRequestDecoderTest method testNoZeroOut.
// See https://github.com/netty/netty/issues/1848
@Test
public void testNoZeroOut() throws Exception {
final String boundary = "E832jQp_Rq2ErFmAduHSR8YlMSm0FCY";
final DefaultHttpDataFactory aMemFactory = new DefaultHttpDataFactory(false);
DefaultHttpRequest aRequest = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, "http://localhost");
aRequest.headers().set(HttpHeaderNames.CONTENT_TYPE, "multipart/form-data; boundary=" + boundary);
aRequest.headers().set(HttpHeaderNames.TRANSFER_ENCODING, HttpHeaderValues.CHUNKED);
HttpPostRequestDecoder aDecoder = new HttpPostRequestDecoder(aMemFactory, aRequest);
final String aData = "some data would be here. the data should be long enough that it " + "will be longer than the original buffer length of 256 bytes in " + "the HttpPostRequestDecoder in order to trigger the issue. Some more " + "data just to be on the safe side.";
final String body = "--" + boundary + "\r\n" + "Content-Disposition: form-data; name=\"root\"\r\n" + "Content-Type: text/plain\r\n" + "\r\n" + aData + "\r\n" + "--" + boundary + "--\r\n";
byte[] aBytes = body.getBytes();
int split = 125;
ByteBufAllocator aAlloc = new UnpooledByteBufAllocator(true);
ByteBuf aSmallBuf = aAlloc.heapBuffer(split, split);
ByteBuf aLargeBuf = aAlloc.heapBuffer(aBytes.length - split, aBytes.length - split);
aSmallBuf.writeBytes(aBytes, 0, split);
aLargeBuf.writeBytes(aBytes, split, aBytes.length - split);
aDecoder.offer(new DefaultHttpContent(aSmallBuf));
aDecoder.offer(new DefaultHttpContent(aLargeBuf));
aDecoder.offer(LastHttpContent.EMPTY_LAST_CONTENT);
assertTrue("Should have a piece of data", aDecoder.hasNext());
InterfaceHttpData aDecodedData = aDecoder.next();
assertEquals(InterfaceHttpData.HttpDataType.Attribute, aDecodedData.getHttpDataType());
Attribute aAttr = (Attribute) aDecodedData;
assertEquals(aData, aAttr.getValue());
aDecodedData.release();
aDecoder.destroy();
}
use of io.netty.handler.codec.http.DefaultHttpContent in project netty by netty.
the class HttpToHttp2ConnectionHandlerTest method testChunkedRequestWithBodyAndTrailingHeaders.
@Test
public void testChunkedRequestWithBodyAndTrailingHeaders() throws Exception {
final String text = "foooooo";
final String text2 = "goooo";
final List<String> receivedBuffers = Collections.synchronizedList(new ArrayList<String>());
doAnswer(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock in) throws Throwable {
receivedBuffers.add(((ByteBuf) in.getArguments()[2]).toString(UTF_8));
return null;
}
}).when(serverListener).onDataRead(any(ChannelHandlerContext.class), eq(3), any(ByteBuf.class), eq(0), eq(false));
bootstrapEnv(4, 1, 1);
final HttpRequest request = new DefaultHttpRequest(HTTP_1_1, POST, "http://your_user-name123@www.example.org:5555/example");
final HttpHeaders httpHeaders = request.headers();
httpHeaders.set(HttpHeaderNames.HOST, "www.example.org:5555");
httpHeaders.add(HttpHeaderNames.TRANSFER_ENCODING, "chunked");
httpHeaders.add(of("foo"), of("goo"));
httpHeaders.add(of("foo"), of("goo2"));
httpHeaders.add(of("foo2"), of("goo2"));
final Http2Headers http2Headers = new DefaultHttp2Headers().method(new AsciiString("POST")).path(new AsciiString("/example")).authority(new AsciiString("www.example.org:5555")).scheme(new AsciiString("http")).add(new AsciiString("foo"), new AsciiString("goo")).add(new AsciiString("foo"), new AsciiString("goo2")).add(new AsciiString("foo2"), new AsciiString("goo2"));
final DefaultHttpContent httpContent = new DefaultHttpContent(Unpooled.copiedBuffer(text, UTF_8));
final LastHttpContent lastHttpContent = new DefaultLastHttpContent(Unpooled.copiedBuffer(text2, UTF_8));
lastHttpContent.trailingHeaders().add(of("trailing"), of("bar"));
final Http2Headers http2TrailingHeaders = new DefaultHttp2Headers().add(new AsciiString("trailing"), new AsciiString("bar"));
ChannelPromise writePromise = newPromise();
ChannelFuture writeFuture = clientChannel.write(request, writePromise);
ChannelPromise contentPromise = newPromise();
ChannelFuture contentFuture = clientChannel.write(httpContent, contentPromise);
ChannelPromise lastContentPromise = newPromise();
ChannelFuture lastContentFuture = clientChannel.write(lastHttpContent, lastContentPromise);
clientChannel.flush();
assertTrue(writePromise.awaitUninterruptibly(WAIT_TIME_SECONDS, SECONDS));
assertTrue(writePromise.isSuccess());
assertTrue(writeFuture.awaitUninterruptibly(WAIT_TIME_SECONDS, SECONDS));
assertTrue(writeFuture.isSuccess());
assertTrue(contentPromise.awaitUninterruptibly(WAIT_TIME_SECONDS, SECONDS));
assertTrue(contentPromise.isSuccess());
assertTrue(contentFuture.awaitUninterruptibly(WAIT_TIME_SECONDS, SECONDS));
assertTrue(contentFuture.isSuccess());
assertTrue(lastContentPromise.awaitUninterruptibly(WAIT_TIME_SECONDS, SECONDS));
assertTrue(lastContentPromise.isSuccess());
assertTrue(lastContentFuture.awaitUninterruptibly(WAIT_TIME_SECONDS, SECONDS));
assertTrue(lastContentFuture.isSuccess());
awaitRequests();
verify(serverListener).onHeadersRead(any(ChannelHandlerContext.class), eq(3), eq(http2Headers), eq(0), anyShort(), anyBoolean(), eq(0), eq(false));
verify(serverListener).onDataRead(any(ChannelHandlerContext.class), eq(3), any(ByteBuf.class), eq(0), eq(false));
verify(serverListener).onHeadersRead(any(ChannelHandlerContext.class), eq(3), eq(http2TrailingHeaders), eq(0), anyShort(), anyBoolean(), eq(0), eq(true));
assertEquals(1, receivedBuffers.size());
assertEquals(text + text2, receivedBuffers.get(0));
}
use of io.netty.handler.codec.http.DefaultHttpContent in project netty by netty.
the class HttpPostRequestEncoder method encodeNextChunkUrlEncoded.
/**
* From the current context (currentBuffer and currentData), returns the next HttpChunk (if possible) trying to get
* sizeleft bytes more into the currentBuffer. This is the UrlEncoded version.
*
* @param sizeleft
* the number of bytes to try to get from currentData
* @return the next HttpChunk or null if not enough bytes were found
* @throws ErrorDataEncoderException
* if the encoding is in error
*/
private HttpContent encodeNextChunkUrlEncoded(int sizeleft) throws ErrorDataEncoderException {
if (currentData == null) {
return null;
}
int size = sizeleft;
ByteBuf buffer;
// Set name=
if (isKey) {
String key = currentData.getName();
buffer = wrappedBuffer(key.getBytes());
isKey = false;
if (currentBuffer == null) {
currentBuffer = wrappedBuffer(buffer, wrappedBuffer("=".getBytes()));
// continue
size -= buffer.readableBytes() + 1;
} else {
currentBuffer = wrappedBuffer(currentBuffer, buffer, wrappedBuffer("=".getBytes()));
// continue
size -= buffer.readableBytes() + 1;
}
if (currentBuffer.readableBytes() >= HttpPostBodyUtil.chunkSize) {
buffer = fillByteBuf();
return new DefaultHttpContent(buffer);
}
}
// Put value into buffer
try {
buffer = ((HttpData) currentData).getChunk(size);
} catch (IOException e) {
throw new ErrorDataEncoderException(e);
}
// Figure out delimiter
ByteBuf delimiter = null;
if (buffer.readableBytes() < size) {
isKey = true;
delimiter = iterator.hasNext() ? wrappedBuffer("&".getBytes()) : null;
}
// End for current InterfaceHttpData, need potentially more data
if (buffer.capacity() == 0) {
currentData = null;
if (currentBuffer == null) {
currentBuffer = delimiter;
} else {
if (delimiter != null) {
currentBuffer = wrappedBuffer(currentBuffer, delimiter);
}
}
if (currentBuffer.readableBytes() >= HttpPostBodyUtil.chunkSize) {
buffer = fillByteBuf();
return new DefaultHttpContent(buffer);
}
return null;
}
// Put it all together: name=value&
if (currentBuffer == null) {
if (delimiter != null) {
currentBuffer = wrappedBuffer(buffer, delimiter);
} else {
currentBuffer = buffer;
}
} else {
if (delimiter != null) {
currentBuffer = wrappedBuffer(currentBuffer, buffer, delimiter);
} else {
currentBuffer = wrappedBuffer(currentBuffer, buffer);
}
}
// end for current InterfaceHttpData, need more data
if (currentBuffer.readableBytes() < HttpPostBodyUtil.chunkSize) {
currentData = null;
isKey = true;
return null;
}
buffer = fillByteBuf();
return new DefaultHttpContent(buffer);
}
use of io.netty.handler.codec.http.DefaultHttpContent in project netty by netty.
the class HttpPostRequestEncoder method encodeNextChunkMultipart.
/**
* From the current context (currentBuffer and currentData), returns the next HttpChunk (if possible) trying to get
* sizeleft bytes more into the currentBuffer. This is the Multipart version.
*
* @param sizeleft
* the number of bytes to try to get from currentData
* @return the next HttpChunk or null if not enough bytes were found
* @throws ErrorDataEncoderException
* if the encoding is in error
*/
private HttpContent encodeNextChunkMultipart(int sizeleft) throws ErrorDataEncoderException {
if (currentData == null) {
return null;
}
ByteBuf buffer;
if (currentData instanceof InternalAttribute) {
buffer = ((InternalAttribute) currentData).toByteBuf();
currentData = null;
} else {
if (currentData instanceof Attribute) {
try {
buffer = ((Attribute) currentData).getChunk(sizeleft);
} catch (IOException e) {
throw new ErrorDataEncoderException(e);
}
} else {
try {
buffer = ((HttpData) currentData).getChunk(sizeleft);
} catch (IOException e) {
throw new ErrorDataEncoderException(e);
}
}
if (buffer.capacity() == 0) {
// end for current InterfaceHttpData, need more data
currentData = null;
return null;
}
}
if (currentBuffer == null) {
currentBuffer = buffer;
} else {
currentBuffer = wrappedBuffer(currentBuffer, buffer);
}
if (currentBuffer.readableBytes() < HttpPostBodyUtil.chunkSize) {
currentData = null;
return null;
}
buffer = fillByteBuf();
return new DefaultHttpContent(buffer);
}
use of io.netty.handler.codec.http.DefaultHttpContent in project netty by netty.
the class Http2ServerDowngrader method decode.
@Override
protected void decode(ChannelHandlerContext ctx, Http2StreamFrame frame, List<Object> out) throws Exception {
if (frame instanceof Http2HeadersFrame) {
// not really the id
int id = 0;
Http2HeadersFrame headersFrame = (Http2HeadersFrame) frame;
Http2Headers headers = headersFrame.headers();
if (headersFrame.isEndStream()) {
if (headers.method() == null) {
LastHttpContent last = new DefaultLastHttpContent(Unpooled.EMPTY_BUFFER, validateHeaders);
HttpConversionUtil.addHttp2ToHttpHeaders(id, headers, last.trailingHeaders(), HttpVersion.HTTP_1_1, true, true);
out.add(last);
} else {
FullHttpRequest full = HttpConversionUtil.toFullHttpRequest(id, headers, ctx.alloc(), validateHeaders);
out.add(full);
}
} else {
HttpRequest req = HttpConversionUtil.toHttpRequest(id, headersFrame.headers(), validateHeaders);
if (!HttpUtil.isContentLengthSet(req)) {
req.headers().add(HttpHeaderNames.TRANSFER_ENCODING, HttpHeaderValues.CHUNKED);
}
out.add(req);
}
} else if (frame instanceof Http2DataFrame) {
Http2DataFrame dataFrame = (Http2DataFrame) frame;
if (dataFrame.isEndStream()) {
out.add(new DefaultLastHttpContent(dataFrame.content(), validateHeaders));
} else {
out.add(new DefaultHttpContent(dataFrame.content()));
}
}
ReferenceCountUtil.retain(frame);
}
Aggregations