下面列出了怎么用 io.netty.handler.codec.http2.DefaultHttp2HeadersFrame 的API类实例代码及写法,或者点击链接到github查看源代码。
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) {
if (msg instanceof HttpResponseMetaData) {
HttpResponseMetaData metaData = (HttpResponseMetaData) msg;
HttpHeaders h1Headers = metaData.headers();
Http2Headers h2Headers = h1HeadersToH2Headers(h1Headers);
h2Headers.status(metaData.status().codeAsCharSequence());
ctx.write(new DefaultHttp2HeadersFrame(h2Headers, false), promise);
} else if (msg instanceof Buffer) {
writeBuffer(ctx, msg, promise);
} else if (msg instanceof HttpHeaders) {
writeTrailers(ctx, msg, promise);
} else {
ctx.write(msg, promise);
}
}
private void onHeadersRead(ChannelHandlerContext ctx, Http2HeadersFrame headers) {
if (headers.isEndStream()) {
ctx.write(new DefaultHttp2HeadersFrame(headers.headers(), true));
} else {
Http2Headers outHeaders = new DefaultHttp2Headers();
if (headers.headers().contains(EXPECT, CONTINUE)) {
if (headers.headers().contains(EXPECT_FAIL_HEADER)) {
outHeaders.status(
io.netty.handler.codec.http.HttpResponseStatus.EXPECTATION_FAILED.codeAsText());
ctx.write(new DefaultHttp2HeadersFrame(outHeaders, true));
return;
} else {
outHeaders.status(io.netty.handler.codec.http.HttpResponseStatus.CONTINUE.codeAsText());
}
} else {
outHeaders.status(io.netty.handler.codec.http.HttpResponseStatus.OK.codeAsText());
}
CharSequence contentType = headers.headers().get(CONTENT_TYPE);
if (contentType != null) {
outHeaders.add(CONTENT_TYPE, contentType);
}
outHeaders.add(HttpHeaderNames.COOKIE, headers.headers().getAll(HttpHeaderNames.COOKIE));
ctx.write(new DefaultHttp2HeadersFrame(outHeaders));
}
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
if (!(msg instanceof Http2Frame)) {
ctx.fireChannelRead(msg);
return;
}
Http2Frame frame = (Http2Frame) msg;
receivedFrames.add(frame);
if (frame instanceof Http2DataFrame) {
Http2DataFrame dataFrame = (Http2DataFrame) frame;
if (dataFrame.isEndStream()) {
Http2HeadersFrame respHeaders = new DefaultHttp2HeadersFrame(
new DefaultHttp2Headers().status("204"), true)
.stream(dataFrame.stream());
ctx.writeAndFlush(respHeaders);
}
}
ReferenceCountUtil.release(frame);
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, Http2Frame frame) {
if (frame instanceof Http2DataFrame) {
// Not respond if this is channel 1
if (channelIds[0].equals(ctx.channel().parent().id().asShortText()) && failOnFirstChannel) {
ctx.channel().parent().close();
} else {
DefaultHttp2DataFrame dataFrame = new DefaultHttp2DataFrame(false);
try {
LOGGER.info(() -> "return empty data " + ctx.channel() + " frame " + frame.getClass());
Http2Headers headers = new DefaultHttp2Headers().status(OK.codeAsText());
ctx.write(dataFrame);
ctx.write(new DefaultHttp2HeadersFrame(headers, true));
ctx.flush();
} finally {
dataFrame.release();
}
}
}
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, Http2Frame frame) {
if (frame instanceof Http2DataFrame) {
// Not respond if this is channel 1
if (channelIds[0].equals(ctx.channel().parent().id().asShortText()) && notRespondOnFirstChannel) {
LOGGER.info(() -> "This is the first request, not responding" + ctx.channel());
} else {
DefaultHttp2DataFrame dataFrame = new DefaultHttp2DataFrame(false);
try {
LOGGER.info(() -> "return empty data " + ctx.channel() + " frame " + frame.getClass());
Http2Headers headers = new DefaultHttp2Headers().status(OK.codeAsText());
ctx.write(dataFrame);
ctx.write(new DefaultHttp2HeadersFrame(headers, true));
ctx.flush();
} finally {
dataFrame.release();
}
}
}
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
if (msg instanceof Http2HeadersFrame) {
Http2HeadersFrame msgHeader = (Http2HeadersFrame) msg;
if (msgHeader.isEndStream()) {
ByteBuf content = ctx.alloc()
.buffer();
content.writeBytes(RESPONSE_BYTES.duplicate());
Http2Headers headers = new DefaultHttp2Headers().status(HttpResponseStatus.OK.codeAsText());
ctx.write(new DefaultHttp2HeadersFrame(headers).stream(msgHeader.stream()));
ctx.write(new DefaultHttp2DataFrame(content, true).stream(msgHeader.stream()));
}
} else {
super.channelRead(ctx, msg);
}
}
/**
* Sends a "Hello World" DATA frame to the client.
*/
private static void sendResponse(ChannelHandlerContext ctx, ByteBuf payload) {
// Send a frame for the response status
Http2Headers headers = new DefaultHttp2Headers().status(OK.codeAsText());
ctx.write(new DefaultHttp2HeadersFrame(headers));
ctx.write(new DefaultHttp2DataFrame(payload, true));
}
/**
* 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));
}
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) {
if (msg instanceof HttpRequestMetaData) {
HttpRequestMetaData metaData = (HttpRequestMetaData) msg;
HttpHeaders h1Headers = metaData.headers();
CharSequence host = h1Headers.getAndRemove(HOST);
Http2Headers h2Headers = h1HeadersToH2Headers(h1Headers);
if (host == null) {
host = metaData.effectiveHost();
if (host != null) {
h2Headers.authority(host);
}
} else {
h2Headers.authority(host);
}
method = metaData.method();
h2Headers.method(method.name());
if (!CONNECT.equals(method)) {
// The ":scheme" and ":path" pseudo-header fields MUST be omitted for CONNECT.
// https://tools.ietf.org/html/rfc7540#section-8.3
h2Headers.scheme(scheme.name());
h2Headers.path(metaData.requestTarget());
}
ctx.write(new DefaultHttp2HeadersFrame(h2Headers, false), promise);
} else if (msg instanceof Buffer) {
writeBuffer(ctx, msg, promise);
} else if (msg instanceof HttpHeaders) {
writeTrailers(ctx, msg, promise);
} else {
ctx.write(msg, promise);
}
}
final void writeTrailers(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) {
// For H2 we don't need to notify protocolPayloadEndOutboundSuccess(ctx); the codecs takes care of half-closure
closeHandler.protocolPayloadEndOutbound(ctx);
HttpHeaders h1Headers = (HttpHeaders) msg;
Http2Headers h2Headers = h1HeadersToH2Headers(h1Headers);
if (h2Headers.isEmpty()) {
ctx.write(new DefaultHttp2DataFrame(EMPTY_BUFFER, true), promise);
} else {
ctx.write(new DefaultHttp2HeadersFrame(h2Headers, true), promise);
}
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
if (!(msg instanceof Http2Frame)) {
ctx.fireChannelRead(msg);
return;
}
Http2Frame frame = (Http2Frame) msg;
if (frame instanceof Http2DataFrame) {
Http2DataFrame dataFrame = (Http2DataFrame) frame;
ReferenceCountUtil.release(frame);
if (dataFrame.isEndStream()) {
Http2HeadersFrame respHeaders = new DefaultHttp2HeadersFrame(
new DefaultHttp2Headers().status("204"), true)
.stream(dataFrame.stream());
ctx.writeAndFlush(respHeaders);
}
if (sleeps > 0) {
--sleeps;
// Simulate a server that's slow to read data. Since our
// window size is equal to the max frame size, the client
// shouldn't be able to send more data until we update our
// window
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
ctx.writeAndFlush(new DefaultHttp2WindowUpdateFrame(dataFrame.initialFlowControlledBytes())
.stream(dataFrame.stream()));
}
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, Http2Frame http2Frame) throws Exception {
if (http2Frame instanceof Http2DataFrame) {
Http2DataFrame dataFrame = (Http2DataFrame) http2Frame;
if (dataFrame.isEndStream()) {
Http2Headers headers = new DefaultHttp2Headers().status("200");
ctx.writeAndFlush(new DefaultHttp2HeadersFrame(headers, false));
ctx.executor().scheduleAtFixedRate(() -> {
DefaultHttp2DataFrame respData = new DefaultHttp2DataFrame(Unpooled.wrappedBuffer("hello".getBytes()), false);
ctx.writeAndFlush(respData);
}, 0, 2, TimeUnit.SECONDS);
}
}
}
/**
* 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);
// TODO: Use {@link RetainingAsyncWritableChannel} after writeTo(AsyncWritableChannel channel, Callback<Long> callback) is fully implemented.
ByteBufChannel byteBufChannel = new ByteBufChannel();
try {
send.writeTo(byteBufChannel);
} catch (IOException e) {
promise.setFailure(e);
return;
}
DefaultHttp2DataFrame dataFrame = new DefaultHttp2DataFrame(byteBufChannel.getBuf(), true);
// Caller should call writeAndFlush().
ctx.write(dataFrame, promise);
}