Add HttpScheme Support in HttpToHttp2ConnectionHandler (#10641)

Motivation:
We should have a method to add `HttpScheme` if `HttpRequest` does not contain `x-http2-scheme` then we should use add it if `HttpToHttp2ConnectionHandler` is build using specified `HttpScheme`.

Modification:
Added `HttpScheme` in `HttpToHttp2ConnectionHandlerBuilder`.

Result:
Automatically add `HttpScheme` if missing in `HttpRequest`.
This commit is contained in:
Aayush Atharva 2020-11-05 20:23:32 +05:30 committed by GitHub
parent 027a686042
commit 76d5cdb9e8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 56 additions and 2 deletions

View File

@ -23,6 +23,7 @@ import io.netty.handler.codec.http.FullHttpMessage;
import io.netty.handler.codec.http.HttpContent;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpMessage;
import io.netty.handler.codec.http.HttpScheme;
import io.netty.handler.codec.http.LastHttpContent;
import io.netty.handler.codec.http2.Http2CodecUtil.SimpleChannelPromiseAggregator;
import io.netty.util.ReferenceCountUtil;
@ -38,6 +39,7 @@ public class HttpToHttp2ConnectionHandler extends Http2ConnectionHandler {
private final boolean validateHeaders;
private int currentStreamId;
private HttpScheme httpScheme;
protected HttpToHttp2ConnectionHandler(Http2ConnectionDecoder decoder, Http2ConnectionEncoder encoder,
Http2Settings initialSettings, boolean validateHeaders) {
@ -48,8 +50,15 @@ public class HttpToHttp2ConnectionHandler extends Http2ConnectionHandler {
protected HttpToHttp2ConnectionHandler(Http2ConnectionDecoder decoder, Http2ConnectionEncoder encoder,
Http2Settings initialSettings, boolean validateHeaders,
boolean decoupleCloseAndGoAway) {
this(decoder, encoder, initialSettings, validateHeaders, decoupleCloseAndGoAway, null);
}
protected HttpToHttp2ConnectionHandler(Http2ConnectionDecoder decoder, Http2ConnectionEncoder encoder,
Http2Settings initialSettings, boolean validateHeaders,
boolean decoupleCloseAndGoAway, HttpScheme httpScheme) {
super(decoder, encoder, initialSettings, decoupleCloseAndGoAway);
this.validateHeaders = validateHeaders;
this.httpScheme = httpScheme;
}
/**
@ -87,6 +96,12 @@ public class HttpToHttp2ConnectionHandler extends Http2ConnectionHandler {
// Provide the user the opportunity to specify the streamId
currentStreamId = getStreamId(httpMsg.headers());
// Add HttpScheme if it's defined in constructor and header does not contain it.
if (httpScheme != null &&
!httpMsg.headers().contains(HttpConversionUtil.ExtensionHeaderNames.SCHEME.text())) {
httpMsg.headers().set(HttpConversionUtil.ExtensionHeaderNames.SCHEME.text(), httpScheme.name());
}
// Convert and write the headers.
Http2Headers http2Headers = HttpConversionUtil.toHttp2Headers(httpMsg, validateHeaders);
endStream = msg instanceof FullHttpMessage && !((FullHttpMessage) msg).content().isReadable();

View File

@ -16,6 +16,7 @@
package io.netty.handler.codec.http2;
import io.netty.handler.codec.http.HttpScheme;
import io.netty.handler.codec.http2.Http2HeadersEncoder.SensitivityDetector;
import io.netty.util.internal.UnstableApi;
@ -26,6 +27,8 @@ import io.netty.util.internal.UnstableApi;
public final class HttpToHttp2ConnectionHandlerBuilder extends
AbstractHttp2ConnectionHandlerBuilder<HttpToHttp2ConnectionHandler, HttpToHttp2ConnectionHandlerBuilder> {
private HttpScheme httpScheme;
@Override
public HttpToHttp2ConnectionHandlerBuilder validateHeaders(boolean validateHeaders) {
return super.validateHeaders(validateHeaders);
@ -58,7 +61,7 @@ public final class HttpToHttp2ConnectionHandlerBuilder extends
@Override
public HttpToHttp2ConnectionHandlerBuilder codec(Http2ConnectionDecoder decoder,
Http2ConnectionEncoder encoder) {
Http2ConnectionEncoder encoder) {
return super.codec(decoder, encoder);
}
@ -90,6 +93,17 @@ public final class HttpToHttp2ConnectionHandlerBuilder extends
return super.decoupleCloseAndGoAway(decoupleCloseAndGoAway);
}
/**
* Add {@code scheme} in {@link Http2Headers} if not already present.
*
* @param httpScheme {@link HttpScheme} type
* @return {@code this}.
*/
public HttpToHttp2ConnectionHandlerBuilder httpScheme(HttpScheme httpScheme) {
this.httpScheme = httpScheme;
return self();
}
@Override
public HttpToHttp2ConnectionHandler build() {
return super.build();
@ -99,6 +113,6 @@ public final class HttpToHttp2ConnectionHandlerBuilder extends
protected HttpToHttp2ConnectionHandler build(Http2ConnectionDecoder decoder, Http2ConnectionEncoder encoder,
Http2Settings initialSettings) {
return new HttpToHttp2ConnectionHandler(decoder, encoder, initialSettings, isValidateHeaders(),
decoupleCloseAndGoAway());
decoupleCloseAndGoAway(), httpScheme);
}
}

View File

@ -37,6 +37,7 @@ import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpHeaderNames;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.HttpScheme;
import io.netty.handler.codec.http.LastHttpContent;
import io.netty.handler.codec.http2.Http2TestUtil.FrameCountDown;
import io.netty.util.AsciiString;
@ -147,6 +148,29 @@ public class HttpToHttp2ConnectionHandlerTest {
verifyHeadersOnly(http2Headers, writePromise, clientChannel.writeAndFlush(request, writePromise));
}
@Test
public void testHttpScheme() throws Exception {
bootstrapEnv(2, 1, 0);
final FullHttpRequest request = new DefaultFullHttpRequest(HTTP_1_1, GET,
"http://my-user_name@www.example.org:5555/example");
final HttpHeaders httpHeaders = request.headers();
httpHeaders.setInt(HttpConversionUtil.ExtensionHeaderNames.STREAM_ID.text(), 5);
httpHeaders.set(HttpHeaderNames.HOST, "my-user_name@www.example.org:5555");
httpHeaders.add(of("foo"), of("goo"));
httpHeaders.add(of("foo"), of("goo2"));
httpHeaders.add(of("foo2"), of("goo2"));
final Http2Headers http2Headers =
new DefaultHttp2Headers().method(new AsciiString("GET")).path(new AsciiString("/example"))
.authority(new AsciiString("www.example.org:5555")).scheme(new AsciiString("http"))
.scheme(new AsciiString("http"))
.add(new AsciiString("foo"), new AsciiString("goo"))
.add(new AsciiString("foo"), new AsciiString("goo2"))
.add(new AsciiString("foo2"), new AsciiString("goo2"));
ChannelPromise writePromise = newPromise();
verifyHeadersOnly(http2Headers, writePromise, clientChannel.writeAndFlush(request, writePromise));
}
@Test
public void testMultipleCookieEntriesAreCombined() throws Exception {
bootstrapEnv(2, 1, 0);
@ -520,6 +544,7 @@ public class HttpToHttp2ConnectionHandlerTest {
p.addLast(new HttpToHttp2ConnectionHandlerBuilder()
.server(true)
.frameListener(serverFrameCountDown)
.httpScheme(HttpScheme.HTTP)
.build());
serverChannelLatch.countDown();
}