use of io.netty.handler.codec.http.LastHttpContent in project riposte by Nike-Inc.
the class RequestInfoImplTest method uber_constructor_works_for_valid_values.
@Test
public void uber_constructor_works_for_valid_values() {
// given
String uri = "/some/uri/path/%24foobar%26?notused=blah";
HttpMethod method = HttpMethod.PATCH;
Charset contentCharset = CharsetUtil.US_ASCII;
HttpHeaders headers = new DefaultHttpHeaders().add("header1", "val1").add(HttpHeaders.Names.CONTENT_TYPE, "text/text charset=" + contentCharset.displayName());
QueryStringDecoder queryParams = new QueryStringDecoder(uri + "?foo=bar&secondparam=secondvalue");
Set<Cookie> cookies = new HashSet<>(Arrays.asList(new DefaultCookie("cookie1", "val1"), new DefaultCookie("cookie2", "val2")));
Map<String, String> pathParams = Arrays.stream(new String[][] { { "pathParam1", "val1" }, { "pathParam2", "val2" } }).collect(Collectors.toMap(pair -> pair[0], pair -> pair[1]));
String content = UUID.randomUUID().toString();
byte[] contentBytes = content.getBytes();
LastHttpContent chunk = new DefaultLastHttpContent(Unpooled.copiedBuffer(contentBytes));
chunk.trailingHeaders().add("trailingHeader1", "trailingVal1");
List<HttpContent> contentChunks = Collections.singletonList(chunk);
HttpVersion protocolVersion = HttpVersion.HTTP_1_1;
boolean keepAlive = true;
boolean fullRequest = true;
boolean isMultipart = false;
// when
RequestInfoImpl<?> requestInfo = new RequestInfoImpl<>(uri, method, headers, chunk.trailingHeaders(), queryParams, cookies, pathParams, contentChunks, protocolVersion, keepAlive, fullRequest, isMultipart);
// then
assertThat("getUri should return passed in value", requestInfo.getUri(), is(uri));
assertThat("getPath did not decode as expected", requestInfo.getPath(), is("/some/uri/path/$foobar&"));
assertThat(requestInfo.getMethod(), is(method));
assertThat(requestInfo.getHeaders(), is(headers));
assertThat(requestInfo.getTrailingHeaders(), is(chunk.trailingHeaders()));
assertThat(requestInfo.getQueryParams(), is(queryParams));
assertThat(requestInfo.getCookies(), is(cookies));
assertThat(requestInfo.pathTemplate, nullValue());
assertThat(requestInfo.pathParams, is(pathParams));
assertThat(requestInfo.getRawContentBytes(), is(contentBytes));
assertThat(requestInfo.getRawContent(), is(content));
assertThat(requestInfo.content, nullValue());
assertThat(requestInfo.getContentCharset(), is(contentCharset));
assertThat(requestInfo.getProtocolVersion(), is(protocolVersion));
assertThat(requestInfo.isKeepAliveRequested(), is(keepAlive));
assertThat(requestInfo.isCompleteRequestWithAllChunks, is(fullRequest));
assertThat(requestInfo.isMultipart, is(isMultipart));
}
use of io.netty.handler.codec.http.LastHttpContent in project riposte by Nike-Inc.
the class RequestInfoImplTest method addContentChunk_adds_last_chunk_trailing_headers.
@Test
public void addContentChunk_adds_last_chunk_trailing_headers() {
// given
RequestInfoImpl<?> requestInfo = RequestInfoImpl.dummyInstanceForUnknownRequests();
requestInfo.isCompleteRequestWithAllChunks = false;
LastHttpContent lastChunk = new DefaultLastHttpContent(Unpooled.copiedBuffer(UUID.randomUUID().toString(), CharsetUtil.UTF_8));
String headerKey = UUID.randomUUID().toString();
List<String> headerVal = Arrays.asList(UUID.randomUUID().toString(), UUID.randomUUID().toString());
lastChunk.trailingHeaders().add(headerKey, headerVal);
// when
requestInfo.addContentChunk(lastChunk);
// then
assertThat(requestInfo.trailingHeaders.names().size(), is(1));
assertThat(requestInfo.trailingHeaders.getAll(headerKey), is(headerVal));
}
use of io.netty.handler.codec.http.LastHttpContent in project riposte by Nike-Inc.
the class RequestInfoImplTest method addContentChunk_does_not_set_isCompleteRequestWithAllChunks_to_true_if_contentChunksWillBeReleasedExternally_is_true.
@Test
public void addContentChunk_does_not_set_isCompleteRequestWithAllChunks_to_true_if_contentChunksWillBeReleasedExternally_is_true() {
// given
RequestInfoImpl<?> requestInfo = RequestInfoImpl.dummyInstanceForUnknownRequests();
requestInfo.isCompleteRequestWithAllChunks = false;
requestInfo.contentChunksWillBeReleasedExternally();
LastHttpContent lastChunk = new DefaultLastHttpContent(Unpooled.copiedBuffer(UUID.randomUUID().toString(), CharsetUtil.UTF_8));
// when
requestInfo.addContentChunk(lastChunk);
// then
Assertions.assertThat(requestInfo.isCompleteRequestWithAllChunks()).isFalse();
Assertions.assertThat(requestInfo.contentChunks).isEmpty();
}
use of io.netty.handler.codec.http.LastHttpContent in project riposte by Nike-Inc.
the class ResponseSender method writeChunk.
protected void writeChunk(ChannelHandlerContext ctx, HttpObject chunkToWrite, RequestInfo requestInfo, ResponseInfo<?> responseInfo, HttpProcessingState state) {
boolean chunkIsInitialHttpResponse = chunkToWrite instanceof HttpResponse;
boolean chunkIsPayloadContent = chunkToWrite instanceof HttpContent;
boolean isLastChunk = chunkToWrite instanceof LastHttpContent;
if (responseInfo.getUncompressedRawContentLength() == null) {
// This is the first chunk being sent for this response. Initialize the uncompressed raw content length
// value to 0 so we can add to it as we find content.
responseInfo.setUncompressedRawContentLength(0L);
}
// Add to responseInfo's uncompressed content length value if appropriate
if (chunkIsPayloadContent) {
ByteBuf actualContent = ((HttpContent) chunkToWrite).content();
if (actualContent != null) {
long newUncompressedRawContentLengthValue = responseInfo.getUncompressedRawContentLength() + actualContent.readableBytes();
responseInfo.setUncompressedRawContentLength(newUncompressedRawContentLengthValue);
}
}
// (or finished).
if (state != null) {
// Update the ResponseInfo to indicate that the response sending has been started if this is the first chunk
if (chunkIsInitialHttpResponse) {
responseInfo.setResponseSendingStarted(true);
}
// Update ResponseInfo to indicate that the last chunk has been sent if this is the last chunk.
if (isLastChunk) {
responseInfo.setResponseSendingLastChunkSent(true);
}
}
// Debog-log the chunk.
if (chunkIsInitialHttpResponse) {
logResponseFirstChunk((HttpResponse) chunkToWrite, ctx);
} else if (chunkIsPayloadContent) {
logResponseContentChunk((HttpContent) chunkToWrite, ctx);
} else {
throw new IllegalStateException("What is this?: " + chunkToWrite.getClass().getName());
}
if (chunkIsInitialHttpResponse && state != null) {
// This is the first bytes of the response, and the state's ResponseInfo has been updated with the final
// response data (like HTTP response status code), so we want to handle the response tagging on the
// overall-request distributed tracing span, and set final span name.
state.handleTracingResponseTaggingAndFinalSpanNameIfNotAlreadyDone();
// We also want to set the wire-send annotation on the span.
Span overallRequestSpan = state.getOverallRequestSpan();
if (overallRequestSpan != null && spanNamingAndTaggingStrategy.shouldAddWireSendStartAnnotation()) {
overallRequestSpan.addTimestampedAnnotationForCurrentTime(spanNamingAndTaggingStrategy.wireSendStartAnnotationName());
}
}
// Write the response, which will send it through the outbound pipeline
// (where it might be modified by outbound handlers).
ChannelFuture writeFuture = ctx.write(chunkToWrite);
// Handle state-related bookkeeping
if (state != null && isLastChunk) {
// Set the state's responseWriterFinalChunkChannelFuture so that handlers can hook into it if desired.
state.setResponseWriterFinalChunkChannelFuture(writeFuture);
// Always attach a listener that sets response end time, and adds a "we sent the last bytes of the
// response on the wire" annotation to the overall request span.
writeFuture.addListener(future -> {
state.setResponseEndTimeNanosToNowIfNotAlreadySet();
Span overallRequestSpan = state.getOverallRequestSpan();
if (overallRequestSpan != null && spanNamingAndTaggingStrategy.shouldAddWireSendFinishAnnotation()) {
overallRequestSpan.addTimestampedAnnotationForCurrentTime(spanNamingAndTaggingStrategy.wireSendFinishAnnotationName());
}
});
}
// Always attach a listener that logs write errors.
writeFuture.addListener(logOnWriteErrorOperationListener(ctx));
// Any other situation should be a close-only-on-failure.
if (isLastChunk && (!requestInfo.isKeepAliveRequested() || responseInfo.isForceConnectionCloseAfterResponseSent())) {
writeFuture.addListener(ChannelFutureListener.CLOSE);
} else
writeFuture.addListener(ChannelFutureListener.CLOSE_ON_FAILURE);
}
use of io.netty.handler.codec.http.LastHttpContent in project riposte by Nike-Inc.
the class StreamingAsyncHttpClientTest method StreamingChannel_doStreamChunk_works_as_expected_when_last_chunk_already_sent_downstream_and_incoming_chunk_is_empty_last_chunk.
@Test
public void StreamingChannel_doStreamChunk_works_as_expected_when_last_chunk_already_sent_downstream_and_incoming_chunk_is_empty_last_chunk() {
// given
streamingChannelSpy.downstreamLastChunkSentHolder.heldObject = true;
LastHttpContent contentChunkMock = mock(LastHttpContent.class);
ByteBuf contentByteBufMock = mock(ByteBuf.class);
doReturn(contentByteBufMock).when(contentChunkMock).content();
doReturn(0).when(contentByteBufMock).readableBytes();
ChannelFuture successFutureMock = mock(ChannelFuture.class);
doReturn(successFutureMock).when(channelMock).newSucceededFuture();
// when
ChannelFuture result = streamingChannelSpy.doStreamChunk(contentChunkMock);
// then
verify(channelMock, never()).writeAndFlush(any(Object.class));
verify(contentChunkMock).release();
verify(channelMock).newSucceededFuture();
assertThat(result).isSameAs(successFutureMock);
}
Aggregations