use of org.apache.flink.shaded.netty4.io.netty.handler.codec.http.LastHttpContent in project ambry by linkedin.
the class MockChannelHandlerContext method responsesWithContentLengthTest.
/**
* Tests the common workflow of the {@link NettyResponseChannel} i.e., add some content to response body via
* {@link NettyResponseChannel#write(ByteBuffer, Callback)} and then complete the response.
* <p/>
* These responses have the header Content-Length set.
* @throws Exception
*/
@Test
public void responsesWithContentLengthTest() throws Exception {
EmbeddedChannel channel = createEmbeddedChannel();
MockNettyMessageProcessor processor = channel.pipeline().get(MockNettyMessageProcessor.class);
final int ITERATIONS = 10;
for (int i = 0; i < ITERATIONS; i++) {
boolean isKeepAlive = i != (ITERATIONS - 1);
HttpHeaders httpHeaders = new DefaultHttpHeaders();
httpHeaders.set(MockNettyMessageProcessor.CHUNK_COUNT_HEADER_NAME, i);
HttpRequest httpRequest = RestTestUtils.createRequest(HttpMethod.POST, TestingUri.ResponseWithContentLength.toString(), httpHeaders);
HttpUtil.setKeepAlive(httpRequest, isKeepAlive);
channel.writeInbound(httpRequest);
verifyCallbacks(processor);
// first outbound has to be response.
HttpResponse response = channel.readOutbound();
assertEquals("Unexpected response status", HttpResponseStatus.OK, response.status());
long contentLength = HttpUtil.getContentLength(response, NettyRequest.UNKNOWN_CONTENT_LENGTH);
assertEquals("Unexpected Content-Length", MockNettyMessageProcessor.CHUNK.length * i, contentLength);
if (contentLength == 0) {
// special case. Since Content-Length is set, the response should be an instance of FullHttpResponse.
assertTrue("Response not instance of FullHttpResponse", response instanceof FullHttpResponse);
} else {
HttpContent httpContent = null;
for (int j = 0; j < i; j++) {
httpContent = channel.readOutbound();
byte[] returnedContent = new byte[httpContent.content().readableBytes()];
httpContent.content().readBytes(returnedContent);
httpContent.release();
assertArrayEquals("Content does not match with expected content", MockNettyMessageProcessor.CHUNK, returnedContent);
}
// When we know the content-length, the last httpContent would be an instance of LastHttpContent and there is no
// empty last http content following it.
// the last HttpContent should also be an instance of LastHttpContent
assertTrue("The last part of the content is not LastHttpContent", httpContent instanceof LastHttpContent);
}
assertEquals("Unexpected channel state on the server", isKeepAlive, channel.isActive());
}
}
use of org.apache.flink.shaded.netty4.io.netty.handler.codec.http.LastHttpContent in project ambry by linkedin.
the class MockChannelHandlerContext method responsesWithTransferEncodingChunkedTest.
/**
* Tests the common workflow of the {@link NettyResponseChannel} i.e., add some content to response body via
* {@link NettyResponseChannel#write(ByteBuf, Callback)} and then complete the response.
* <p/>
* These responses have the header Transfer-Encoding set to chunked.
* @throws Exception
*/
@Test
public void responsesWithTransferEncodingChunkedTest() throws Exception {
String content = "@@randomContent@@@";
String lastContent = "@@randomLastContent@@@";
EmbeddedChannel channel = createEmbeddedChannel();
MockNettyMessageProcessor processor = channel.pipeline().get(MockNettyMessageProcessor.class);
AtomicLong contentIdGenerator = new AtomicLong(0);
final int ITERATIONS = 10;
for (int i = 0; i < ITERATIONS; i++) {
boolean isKeepAlive = i != (ITERATIONS - 1);
HttpRequest httpRequest = RestTestUtils.createRequest(HttpMethod.POST, "/", null);
HttpUtil.setKeepAlive(httpRequest, isKeepAlive);
channel.writeInbound(httpRequest);
ArrayList<String> contents = new ArrayList<>();
for (int j = 0; j <= i; j++) {
String contentToSend = content + contentIdGenerator.getAndIncrement();
channel.writeInbound(createContent(contentToSend, false));
contents.add(contentToSend);
}
channel.writeInbound(createContent(lastContent, true));
verifyCallbacks(processor);
// first outbound has to be response.
HttpResponse response = channel.readOutbound();
assertEquals("Unexpected response status", HttpResponseStatus.OK, response.status());
assertTrue("Response must say 'Transfer-Encoding : chunked'", HttpUtil.isTransferEncodingChunked(response));
// content echoed back.
for (String srcOfTruth : contents) {
HttpContent responseContent = channel.readOutbound();
String returnedContent = RestTestUtils.getContentString(responseContent);
responseContent.release();
assertEquals("Content does not match with expected content", srcOfTruth, returnedContent);
}
HttpContent responseContent = channel.readOutbound();
// last content echoed back.
String returnedContent = RestTestUtils.getContentString(responseContent);
responseContent.release();
assertEquals("Content does not match with expected content", lastContent, returnedContent);
// When the Transfer-Encoding is Chunked, response channel would send the last http content in the request as
// regular http content and then send an empty last http content after that.
assertTrue("Did not receive end marker", channel.readOutbound() instanceof LastHttpContent);
assertEquals("Unexpected channel state on the server", isKeepAlive, channel.isActive());
}
}
use of org.apache.flink.shaded.netty4.io.netty.handler.codec.http.LastHttpContent in project ambry by linkedin.
the class PublicAccessLogHandler method write.
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
long startTimeInMs = System.currentTimeMillis();
boolean shouldReset = msg instanceof LastHttpContent;
boolean isHttpContent = msg instanceof HttpContent;
if (request != null) {
if (msg instanceof HttpResponse) {
HttpResponse response = (HttpResponse) msg;
logHeaders("Response", response, publicAccessLogger.getResponseHeaders());
logMessage.append(", ");
logMessage.append("status=").append(response.status().code());
logMessage.append(", ");
if (HttpUtil.isTransferEncodingChunked(response)) {
responseFirstChunkStartTimeInMs = System.currentTimeMillis();
} else {
shouldReset = true;
}
} else if (!(msg instanceof HttpContent)) {
logger.error("Sending response that is not of type HttpResponse or HttpContent. Sending response to {}. Request is of type {}. No action being taken other than logging this unexpected state.", ctx.channel().remoteAddress(), msg.getClass());
}
if (isHttpContent) {
HttpContent httpContent = (HttpContent) msg;
responseBytesSent += httpContent.content().readableBytes();
}
if (shouldReset) {
logDurations();
publicAccessLogger.logInfo(logMessage.toString());
reset();
}
}
nettyMetrics.publicAccessLogResponseProcessingTimeInMs.update(System.currentTimeMillis() - startTimeInMs);
super.write(ctx, msg, promise);
}
use of org.apache.flink.shaded.netty4.io.netty.handler.codec.http.LastHttpContent in project ambry by linkedin.
the class NettyMessageProcessorTest method sendRequestCheckResponse.
/**
* Sends the provided {@code httpRequest} and verifies that the response is an echo of the {@code restMethod}.
* @param channel the {@link EmbeddedChannel} to send the request over.
* @param httpMethod the {@link HttpMethod} for the request.
* @param restMethod the equivalent {@link RestMethod} for {@code httpMethod}. Used to check for correctness of
* response.
* @param isKeepAlive if the request needs to be keep-alive.
* @throws IOException
*/
private void sendRequestCheckResponse(EmbeddedChannel channel, HttpMethod httpMethod, RestMethod restMethod, boolean isKeepAlive) throws IOException {
long requestId = REQUEST_ID_GENERATOR.getAndIncrement();
String uri = MockRestRequestService.ECHO_REST_METHOD + requestId;
HttpRequest httpRequest = RestTestUtils.createRequest(httpMethod, uri, null);
HttpUtil.setKeepAlive(httpRequest, isKeepAlive);
channel.writeInbound(httpRequest);
channel.writeInbound(new DefaultLastHttpContent());
HttpResponse response = (HttpResponse) channel.readOutbound();
assertEquals("Unexpected response status", HttpResponseStatus.OK, response.status());
// MockRestRequestService echoes the RestMethod + request id.
String expectedResponse = restMethod.toString() + requestId;
assertEquals("Unexpected content", expectedResponse, RestTestUtils.getContentString((HttpContent) channel.readOutbound()));
assertTrue("End marker was expected", channel.readOutbound() instanceof LastHttpContent);
}
use of org.apache.flink.shaded.netty4.io.netty.handler.codec.http.LastHttpContent in project ambry by linkedin.
the class CopyForcingByteBuf method doHeaderAndContentSizeMismatchTest.
/**
* Tests reaction of NettyRequest when content size is different from the size specified in the headers.
* @param httpHeaders {@link HttpHeaders} that need to be a part of the request.
* @param httpContents the {@link List<HttpContent>} that needs to be added to {@code nettyRequest}.
* @throws Exception
*/
private void doHeaderAndContentSizeMismatchTest(HttpHeaders httpHeaders, List<HttpContent> httpContents) throws Exception {
Channel channel = new MockChannel();
NettyRequest nettyRequest = createNettyRequest(HttpMethod.POST, "/", httpHeaders, channel);
AsyncWritableChannel writeChannel = new ByteBufferAsyncWritableChannel();
ReadIntoCallback callback = new ReadIntoCallback();
Future<Long> future = nettyRequest.readInto(writeChannel, callback);
int bytesAdded = 0;
HttpContent httpContentToAdd = null;
for (HttpContent httpContent : httpContents) {
httpContentToAdd = httpContent;
int contentBytes = httpContentToAdd.content().readableBytes();
if (!(httpContentToAdd instanceof LastHttpContent) && (bytesAdded + contentBytes <= nettyRequest.getSize())) {
nettyRequest.addContent(httpContentToAdd);
assertEquals("Reference count is not as expected", 2, httpContentToAdd.refCnt());
bytesAdded += contentBytes;
} else {
break;
}
}
// the addition of the next content should throw an exception.
try {
nettyRequest.addContent(httpContentToAdd);
fail("Adding content should have failed because there was a mismatch in size");
} catch (RestServiceException e) {
assertEquals("Unexpected RestServiceErrorCode", RestServiceErrorCode.BadRequest, e.getErrorCode());
}
closeRequestAndValidate(nettyRequest, channel);
writeChannel.close();
verifyRefCnts(httpContents);
callback.awaitCallback();
assertNotNull("There should be a RestServiceException in the callback", callback.exception);
assertEquals("Unexpected RestServiceErrorCode", RestServiceErrorCode.BadRequest, ((RestServiceException) callback.exception).getErrorCode());
try {
future.get();
fail("Should have thrown exception because the future is expected to have been given one");
} catch (ExecutionException e) {
RestServiceException restServiceException = (RestServiceException) Utils.getRootCause(e);
assertNotNull("There should be a RestServiceException in the future", restServiceException);
assertEquals("Unexpected RestServiceErrorCode", RestServiceErrorCode.BadRequest, restServiceException.getErrorCode());
}
}
Aggregations