use of io.netty.handler.codec.http2.DefaultHttp2DataFrame in project ambry by linkedin.
the class AmbrySendToHttp2Adaptor method write.
/**
* Handles conversion of {@link Send} to HTTP/2 frames.
*/
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) {
if (!ctx.channel().isOpen()) {
logger.debug("Channel closed when write. Channel: {}", ctx.channel());
promise.setFailure(new ChannelException("Channel has been closed when write."));
}
if (!(msg instanceof Send)) {
ctx.write(msg, promise);
return;
}
Send send = (Send) msg;
Http2Headers http2Headers;
if (forServer) {
logger.trace("Write content to channel as server {}", ctx.channel());
http2Headers = new DefaultHttp2Headers().status(HttpResponseStatus.OK.codeAsText());
} else {
logger.trace("Write content to channel as client {}", ctx.channel());
http2Headers = new DefaultHttp2Headers().method(HttpMethod.POST.asciiName()).scheme("https").path("/");
}
DefaultHttp2HeadersFrame headersFrame = new DefaultHttp2HeadersFrame(http2Headers, false);
ctx.write(headersFrame);
// Referencing counting for derived {@link ByteBuf}: https://netty.io/wiki/reference-counted-objects.html#derived-buffers
try {
while (send.content().isReadable(maxFrameSize)) {
ByteBuf slice = send.content().readSlice(maxFrameSize);
slice.retain();
DefaultHttp2DataFrame dataFrame = new DefaultHttp2DataFrame(slice, false);
ctx.write(dataFrame);
}
// The last slice
ByteBuf slice = send.content().readSlice(send.content().readableBytes());
slice.retain();
DefaultHttp2DataFrame dataFrame = new DefaultHttp2DataFrame(slice, true);
ctx.write(dataFrame, promise);
} catch (Exception e) {
logger.error("Error while processing frames. Channel: {}", ctx.channel(), e);
} finally {
send.content().release();
}
}
use of io.netty.handler.codec.http2.DefaultHttp2DataFrame in project jersey by jersey.
the class NettyHttp2ResponseWriter method writeResponseStatusAndHeaders.
@Override
public OutputStream writeResponseStatusAndHeaders(long contentLength, ContainerResponse responseContext) throws ContainerException {
String reasonPhrase = responseContext.getStatusInfo().getReasonPhrase();
int statusCode = responseContext.getStatus();
HttpResponseStatus status = reasonPhrase == null ? HttpResponseStatus.valueOf(statusCode) : new HttpResponseStatus(statusCode, reasonPhrase);
DefaultHttp2Headers response = new DefaultHttp2Headers();
response.status(Integer.toString(responseContext.getStatus()));
for (final Map.Entry<String, List<String>> e : responseContext.getStringHeaders().entrySet()) {
response.add(e.getKey().toLowerCase(), e.getValue());
}
response.set(HttpHeaderNames.CONTENT_LENGTH, Long.toString(contentLength));
ctx.writeAndFlush(new DefaultHttp2HeadersFrame(response));
if (!headersFrame.headers().method().equals(HttpMethod.HEAD.asciiName()) && (contentLength > 0 || contentLength == -1)) {
return new OutputStream() {
@Override
public void write(int b) throws IOException {
write(new byte[] { (byte) b });
}
@Override
public void write(byte[] b) throws IOException {
write(b, 0, b.length);
}
@Override
public void write(byte[] b, int off, int len) throws IOException {
ByteBuf buffer = ctx.alloc().buffer(len);
buffer.writeBytes(b, off, len);
ctx.writeAndFlush(new DefaultHttp2DataFrame(buffer, false));
}
@Override
public void flush() throws IOException {
ctx.flush();
}
@Override
public void close() throws IOException {
ctx.write(new DefaultHttp2DataFrame(true)).addListener(NettyResponseWriter.FLUSH_FUTURE);
}
};
} else {
ctx.writeAndFlush(new DefaultHttp2DataFrame(true));
return null;
}
}
use of io.netty.handler.codec.http2.DefaultHttp2DataFrame in project netty by netty.
the class Http2StaticFileServerHandler method sendListing.
private void sendListing(ChannelHandlerContext ctx, File dir, String dirPath) {
StringBuilder buf = new StringBuilder().append("<!DOCTYPE html>\r\n").append("<html><head><meta charset='utf-8' /><title>").append("Listing of: ").append(dirPath).append("</title></head><body>\r\n").append("<h3>Listing of: ").append(dirPath).append("</h3>\r\n").append("<ul>").append("<li><a href=\"../\">..</a></li>\r\n");
File[] files = dir.listFiles();
if (files != null) {
for (File f : files) {
if (f.isHidden() || !f.canRead()) {
continue;
}
String name = f.getName();
if (!ALLOWED_FILE_NAME.matcher(name).matches()) {
continue;
}
buf.append("<li><a href=\"").append(name).append("\">").append(name).append("</a></li>\r\n");
}
}
buf.append("</ul></body></html>\r\n");
ByteBuf buffer = ctx.alloc().buffer(buf.length());
buffer.writeCharSequence(buf.toString(), CharsetUtil.UTF_8);
Http2Headers headers = new DefaultHttp2Headers();
headers.status(OK.toString());
headers.add(HttpHeaderNames.CONTENT_TYPE, "text/html; charset=UTF-8");
ctx.write(new DefaultHttp2HeadersFrame(headers).stream(stream));
ctx.writeAndFlush(new DefaultHttp2DataFrame(buffer, true).stream(stream));
}
use of io.netty.handler.codec.http2.DefaultHttp2DataFrame in project netty by netty.
the class HelloWorldHttp2Handler method sendResponse.
/**
* Sends a "Hello World" DATA frame to the client.
*/
private static void sendResponse(ChannelHandlerContext ctx, Http2FrameStream stream, ByteBuf payload) {
// Send a frame for the response status
Http2Headers headers = new DefaultHttp2Headers().status(OK.codeAsText());
ctx.write(new DefaultHttp2HeadersFrame(headers).stream(stream));
ctx.write(new DefaultHttp2DataFrame(payload, true).stream(stream));
}
use of io.netty.handler.codec.http2.DefaultHttp2DataFrame in project netty by netty.
the class Http2MultiplexTest method childQueueIsDrainedAndNewDataIsDispatchedInParentReadLoopNoAutoRead.
@Test
public void childQueueIsDrainedAndNewDataIsDispatchedInParentReadLoopNoAutoRead() {
final AtomicInteger numReads = new AtomicInteger(1);
final AtomicInteger channelReadCompleteCount = new AtomicInteger(0);
final AtomicBoolean shouldDisableAutoRead = new AtomicBoolean();
Consumer<ChannelHandlerContext> ctxConsumer = new Consumer<ChannelHandlerContext>() {
@Override
public void accept(ChannelHandlerContext obj) {
channelReadCompleteCount.incrementAndGet();
if (shouldDisableAutoRead.get()) {
obj.channel().config().setAutoRead(false);
}
}
};
final LastInboundHandler inboundHandler = new LastInboundHandler(ctxConsumer);
Http2StreamChannel childChannel = newInboundStream(3, false, numReads, inboundHandler);
childChannel.config().setAutoRead(false);
Http2DataFrame dataFrame1 = new DefaultHttp2DataFrame(bb("1")).stream(childChannel.stream());
Http2DataFrame dataFrame2 = new DefaultHttp2DataFrame(bb("2")).stream(childChannel.stream());
Http2DataFrame dataFrame3 = new DefaultHttp2DataFrame(bb("3")).stream(childChannel.stream());
Http2DataFrame dataFrame4 = new DefaultHttp2DataFrame(bb("4")).stream(childChannel.stream());
assertEquals(new DefaultHttp2HeadersFrame(request).stream(childChannel.stream()), inboundHandler.readInbound());
ChannelHandler readCompleteSupressHandler = new ChannelInboundHandlerAdapter() {
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
// We want to simulate the parent channel calling channelRead and delay calling channelReadComplete.
}
};
parentChannel.pipeline().addFirst(readCompleteSupressHandler);
frameInboundWriter.writeInboundData(childChannel.stream().id(), bb("1"), 0, false);
assertEqualsAndRelease(dataFrame1, inboundHandler.<Http2Frame>readInbound());
// We want one item to be in the queue, and allow the numReads to be larger than 1. This will ensure that
// when beginRead() is called the child channel is added to the readPending queue of the parent channel.
frameInboundWriter.writeInboundData(childChannel.stream().id(), bb("2"), 0, false);
numReads.set(2);
childChannel.read();
assertEqualsAndRelease(dataFrame2, inboundHandler.<Http2Frame>readInbound());
assertNull(inboundHandler.readInbound());
// This is the second item that was read, this should be the last until we call read() again. This should also
// notify of readComplete().
frameInboundWriter.writeInboundData(childChannel.stream().id(), bb("3"), 0, false);
assertEqualsAndRelease(dataFrame3, inboundHandler.<Http2Frame>readInbound());
frameInboundWriter.writeInboundData(childChannel.stream().id(), bb("4"), 0, false);
assertNull(inboundHandler.readInbound());
childChannel.read();
assertEqualsAndRelease(dataFrame4, inboundHandler.<Http2Frame>readInbound());
assertNull(inboundHandler.readInbound());
// Now we want to call channelReadComplete and simulate the end of the read loop.
parentChannel.pipeline().remove(readCompleteSupressHandler);
parentChannel.flushInbound();
// 3 = 1 for initialization + 1 for first read of 2 items + 1 for second read of 2 items +
// 1 for parent channel readComplete
assertEquals(4, channelReadCompleteCount.get());
}
Aggregations