diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/InboundHttp2ToHttpAdapter.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/InboundHttp2ToHttpAdapter.java index 0c8ba812c6..8ab511ea42 100644 --- a/codec-http2/src/main/java/io/netty/handler/codec/http2/InboundHttp2ToHttpAdapter.java +++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/InboundHttp2ToHttpAdapter.java @@ -29,6 +29,7 @@ import io.netty.util.internal.UnstableApi; import static io.netty.handler.codec.http2.Http2Error.INTERNAL_ERROR; import static io.netty.handler.codec.http2.Http2Error.PROTOCOL_ERROR; import static io.netty.handler.codec.http2.Http2Exception.connectionError; +import static io.netty.handler.codec.http.HttpResponseStatus.OK; import static io.netty.util.internal.ObjectUtil.checkNotNull; /** @@ -296,6 +297,14 @@ public class InboundHttp2ToHttpAdapter extends Http2EventAdapter { Http2Headers headers, int padding) throws Http2Exception { // A push promise should not be allowed to add headers to an existing stream Http2Stream promisedStream = connection.stream(promisedStreamId); + if (headers.status() == null) { + // A PUSH_PROMISE frame has no Http response status. + // https://tools.ietf.org/html/rfc7540#section-8.2.1 + // Server push is semantically equivalent to a server responding to a + // request; however, in this case, that request is also sent by the + // server, as a PUSH_PROMISE frame. + headers.status(OK.codeAsText()); + } FullHttpMessage msg = processHeadersBegin(ctx, promisedStream, headers, false, false, false); if (msg == null) { throw connectionError(PROTOCOL_ERROR, "Push Promise Frame received for pre-existing stream id %d", diff --git a/codec-http2/src/test/java/io/netty/handler/codec/http2/InboundHttp2ToHttpAdapterTest.java b/codec-http2/src/test/java/io/netty/handler/codec/http2/InboundHttp2ToHttpAdapterTest.java index 33393afc0a..07fa916cbc 100644 --- a/codec-http2/src/test/java/io/netty/handler/codec/http2/InboundHttp2ToHttpAdapterTest.java +++ b/codec-http2/src/test/java/io/netty/handler/codec/http2/InboundHttp2ToHttpAdapterTest.java @@ -498,7 +498,12 @@ public class InboundHttp2ToHttpAdapterTest { assertEquals(request, capturedRequests.get(0)); final Http2Headers http2Headers = new DefaultHttp2Headers().status(new AsciiString("200")); - final Http2Headers http2Headers2 = new DefaultHttp2Headers().status(new AsciiString("201")) + // The PUSH_PROMISE frame includes a header block that contains a + // complete set of request header fields that the server attributes to + // the request. + // https://tools.ietf.org/html/rfc7540#section-8.2.1 + // Therefore, we should consider the case where there is no Http response status. + final Http2Headers http2Headers2 = new DefaultHttp2Headers() .scheme(new AsciiString("https")) .authority(new AsciiString("example.org")); runInChannel(serverConnectedChannel, new Http2Runnable() {