use of org.apache.flink.shaded.netty4.io.netty.handler.codec.http.HttpContent 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.HttpContent 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.HttpContent in project ambry by linkedin.
the class CopyForcingByteBuf method backPressureTest.
/**
* Tests backpressure support in {@link NettyRequest} for different values of {@link NettyRequest#bufferWatermark}.
* @param digestAlgorithm the digest algorithm to use. Can be empty or {@code null} if digest checking is not
* required.
* @param useCopyForcingByteBuf if {@code true}, uses {@link CopyForcingByteBuf} instead of the default
* {@link ByteBuf}.
* @param method Http method
* @throws Exception
*/
private void backPressureTest(String digestAlgorithm, boolean useCopyForcingByteBuf, HttpMethod method) throws Exception {
List<HttpContent> httpContents = new ArrayList<HttpContent>();
byte[] contentBytes = TestUtils.getRandomBytes(GENERATED_CONTENT_SIZE);
ByteBuffer content = ByteBuffer.wrap(contentBytes);
splitContent(contentBytes, GENERATED_CONTENT_PART_COUNT, httpContents, useCopyForcingByteBuf);
int chunkSize = httpContents.get(0).content().readableBytes();
int[] bufferWatermarks = { 1, chunkSize - 1, chunkSize, chunkSize + 1, chunkSize * httpContents.size() / 2, content.limit() - 1, content.limit(), content.limit() + 1 };
for (int bufferWatermark : bufferWatermarks) {
NettyRequest.bufferWatermark = bufferWatermark;
// start reading before addition of content
httpContents.clear();
content.rewind();
splitContent(contentBytes, GENERATED_CONTENT_PART_COUNT, httpContents, useCopyForcingByteBuf);
doBackPressureTest(digestAlgorithm, content, httpContents, 0, method);
// start reading in the middle of content add
httpContents.clear();
content.rewind();
splitContent(contentBytes, GENERATED_CONTENT_PART_COUNT, httpContents, useCopyForcingByteBuf);
doBackPressureTest(digestAlgorithm, content, httpContents, httpContents.size() / 2, method);
// start reading after all content added
httpContents.clear();
content.rewind();
splitContent(contentBytes, GENERATED_CONTENT_PART_COUNT, httpContents, useCopyForcingByteBuf);
doBackPressureTest(digestAlgorithm, content, httpContents, httpContents.size(), method);
}
}
use of org.apache.flink.shaded.netty4.io.netty.handler.codec.http.HttpContent 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());
}
}
use of org.apache.flink.shaded.netty4.io.netty.handler.codec.http.HttpContent in project ambry by linkedin.
the class CopyForcingByteBuf method readIntoExceptionsTest.
/**
* Tests exception scenarios of {@link NettyRequest#readInto(AsyncWritableChannel, Callback)} and behavior of
* {@link NettyRequest} when {@link AsyncWritableChannel} instances fail.
* @throws Exception
*/
@Test
public void readIntoExceptionsTest() throws Exception {
Channel channel = new MockChannel();
// try to call readInto twice.
NettyRequest nettyRequest = createNettyRequest(HttpMethod.POST, "/", null, channel);
AsyncWritableChannel writeChannel = new ByteBufferAsyncWritableChannel();
nettyRequest.readInto(writeChannel, null);
try {
nettyRequest.readInto(writeChannel, null);
fail("Calling readInto twice should have failed");
} catch (IllegalStateException e) {
// expected. Nothing to do.
}
closeRequestAndValidate(nettyRequest, channel);
// write into a channel that throws exceptions
// non RuntimeException
nettyRequest = createNettyRequest(HttpMethod.POST, "/", null, channel);
List<HttpContent> httpContents = new ArrayList<HttpContent>();
generateContent(httpContents);
assertTrue("Not enough content has been generated", httpContents.size() > 2);
String expectedMsg = "@@expectedMsg@@";
Exception exception = new Exception(expectedMsg);
writeChannel = new BadAsyncWritableChannel(exception);
ReadIntoCallback callback = new ReadIntoCallback();
// add content initially
int addedCount = 0;
for (; addedCount < httpContents.size() / 2; addedCount++) {
HttpContent httpContent = httpContents.get(addedCount);
nettyRequest.addContent(httpContent);
assertEquals("Reference count is not as expected", 2, httpContent.refCnt());
}
Future<Long> future = nettyRequest.readInto(writeChannel, callback);
// add some more content
for (; addedCount < httpContents.size(); addedCount++) {
HttpContent httpContent = httpContents.get(addedCount);
nettyRequest.addContent(httpContent);
}
writeChannel.close();
verifyRefCnts(httpContents);
callback.awaitCallback();
assertNotNull("Exception was not piped correctly", callback.exception);
assertEquals("Exception message mismatch (callback)", expectedMsg, callback.exception.getMessage());
try {
future.get();
fail("Future should have thrown exception");
} catch (ExecutionException e) {
assertEquals("Exception message mismatch (future)", expectedMsg, Utils.getRootCause(e).getMessage());
}
closeRequestAndValidate(nettyRequest, channel);
// RuntimeException
// during readInto
nettyRequest = createNettyRequest(HttpMethod.POST, "/", null, channel);
httpContents = new ArrayList<HttpContent>();
generateContent(httpContents);
exception = new IllegalStateException(expectedMsg);
writeChannel = new BadAsyncWritableChannel(exception);
callback = new ReadIntoCallback();
for (HttpContent httpContent : httpContents) {
nettyRequest.addContent(httpContent);
assertEquals("Reference count is not as expected", 2, httpContent.refCnt());
}
try {
nettyRequest.readInto(writeChannel, callback);
fail("readInto did not throw expected exception");
} catch (Exception e) {
assertEquals("Exception caught does not match expected exception", expectedMsg, e.getMessage());
}
writeChannel.close();
closeRequestAndValidate(nettyRequest, channel);
verifyRefCnts(httpContents);
// after readInto
nettyRequest = createNettyRequest(HttpMethod.POST, "/", null, channel);
httpContents = new ArrayList<HttpContent>();
generateContent(httpContents);
exception = new IllegalStateException(expectedMsg);
writeChannel = new BadAsyncWritableChannel(exception);
callback = new ReadIntoCallback();
nettyRequest.readInto(writeChannel, callback);
// add content
HttpContent httpContent = httpContents.get(1);
try {
nettyRequest.addContent(httpContent);
fail("addContent did not throw expected exception");
} catch (Exception e) {
assertEquals("Exception caught does not match expected exception", expectedMsg, e.getMessage());
}
writeChannel.close();
closeRequestAndValidate(nettyRequest, channel);
verifyRefCnts(httpContents);
}
Aggregations