Enable https tests (#3258)

This commit is contained in:
Lauri Tulmin 2021-06-12 03:16:34 +03:00 committed by GitHub
parent 24aa31ebc3
commit de7eaa0fe6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 191 additions and 71 deletions

View File

@ -60,11 +60,6 @@ class AsyncHttpClientTest extends HttpClientTest<Request> implements AgentTestTr
false false
} }
@Override
boolean testHttps() {
false
}
@Override @Override
SingleConnection createSingleConnection(String host, int port) { SingleConnection createSingleConnection(String host, int port) {
// AsyncHttpClient does not support HTTP 1.1 pipelining nor waiting for connection pool slots to // AsyncHttpClient does not support HTTP 1.1 pipelining nor waiting for connection pool slots to

View File

@ -66,11 +66,6 @@ class AsyncHttpClientTest extends HttpClientTest<Request> implements AgentTestTr
false false
} }
@Override
boolean testHttps() {
false
}
@Override @Override
Set<AttributeKey<?>> httpAttributes(URI uri) { Set<AttributeKey<?>> httpAttributes(URI uri) {
Set<AttributeKey<?>> extra = [ Set<AttributeKey<?>> extra = [

View File

@ -34,7 +34,8 @@ public class HttpClientRequestTracingHandler extends ChannelOutboundHandlerAdapt
return; return;
} }
Context context = tracer().startSpan(parentContext, ctx, (HttpRequest) msg); NettyRequestWrapper requestWrapper = new NettyRequestWrapper((HttpRequest) msg, ctx);
Context context = tracer().startSpan(parentContext, ctx, requestWrapper);
ctx.channel().attr(AttributeKeys.CLIENT_CONTEXT).set(context); ctx.channel().attr(AttributeKeys.CLIENT_CONTEXT).set(context);
ctx.channel().attr(AttributeKeys.CLIENT_PARENT_CONTEXT).set(parentContext); ctx.channel().attr(AttributeKeys.CLIENT_PARENT_CONTEXT).set(parentContext);

View File

@ -15,7 +15,6 @@ import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.socket.DatagramChannel; import io.netty.channel.socket.DatagramChannel;
import io.netty.handler.codec.http.HttpHeaders; import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.HttpResponse; import io.netty.handler.codec.http.HttpResponse;
import io.opentelemetry.api.trace.SpanBuilder; import io.opentelemetry.api.trace.SpanBuilder;
import io.opentelemetry.context.Context; import io.opentelemetry.context.Context;
@ -29,7 +28,7 @@ import java.net.URISyntaxException;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
public class NettyHttpClientTracer public class NettyHttpClientTracer
extends HttpClientTracer<HttpRequest, HttpHeaders, HttpResponse> { extends HttpClientTracer<NettyRequestWrapper, HttpHeaders, HttpResponse> {
private static final NettyHttpClientTracer TRACER = new NettyHttpClientTracer(); private static final NettyHttpClientTracer TRACER = new NettyHttpClientTracer();
private NettyHttpClientTracer() { private NettyHttpClientTracer() {
@ -40,7 +39,8 @@ public class NettyHttpClientTracer
return TRACER; return TRACER;
} }
public Context startSpan(Context parentContext, ChannelHandlerContext ctx, HttpRequest request) { public Context startSpan(
Context parentContext, ChannelHandlerContext ctx, NettyRequestWrapper request) {
SpanBuilder spanBuilder = spanBuilder(parentContext, spanNameForRequest(request), CLIENT); SpanBuilder spanBuilder = spanBuilder(parentContext, spanNameForRequest(request), CLIENT);
onRequest(spanBuilder, request); onRequest(spanBuilder, request);
NetPeerAttributes.INSTANCE.setNetPeer( NetPeerAttributes.INSTANCE.setNetPeer(
@ -62,24 +62,24 @@ public class NettyHttpClientTracer
} }
@Override @Override
protected String method(HttpRequest httpRequest) { protected String method(NettyRequestWrapper httpRequest) {
return httpRequest.getMethod().name(); return httpRequest.method().name();
} }
@Override @Override
@Nullable @Nullable
protected String flavor(HttpRequest httpRequest) { protected String flavor(NettyRequestWrapper httpRequest) {
return httpRequest.getProtocolVersion().text(); return httpRequest.protocolVersion().text();
} }
@Override @Override
protected URI url(HttpRequest request) throws URISyntaxException { protected URI url(NettyRequestWrapper request) throws URISyntaxException {
URI uri = new URI(request.getUri()); URI uri = new URI(request.uri());
if ((uri.getHost() == null || uri.getHost().equals("")) && request.headers().contains(HOST)) { if ((uri.getHost() == null || uri.getHost().equals("")) && request.headers().contains(HOST)) {
return new URI("http://" + request.headers().get(HOST) + request.getUri()); String protocol = request.isHttps() ? "https://" : "http://";
} else { uri = new URI(protocol + request.headers().get(HOST) + request.uri());
return uri;
} }
return uri;
} }
@Override @Override
@ -88,7 +88,7 @@ public class NettyHttpClientTracer
} }
@Override @Override
protected String requestHeader(HttpRequest httpRequest, String name) { protected String requestHeader(NettyRequestWrapper httpRequest, String name) {
return httpRequest.headers().get(name); return httpRequest.headers().get(name);
} }

View File

@ -0,0 +1,62 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.netty.v4_0.client;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.HttpVersion;
public class NettyRequestWrapper {
private static final Class<? extends ChannelHandler> sslHandlerClass = getSslHandlerClass();
@SuppressWarnings("unchecked")
private static Class<? extends ChannelHandler> getSslHandlerClass() {
try {
return (Class<? extends ChannelHandler>)
Class.forName(
"io.netty.handler.ssl.SslHandler",
false,
HttpClientRequestTracingHandler.class.getClassLoader());
} catch (ClassNotFoundException exception) {
return null;
}
}
private final HttpRequest request;
private final ChannelHandlerContext ctx;
public NettyRequestWrapper(HttpRequest request, ChannelHandlerContext ctx) {
this.request = request;
this.ctx = ctx;
}
public HttpRequest request() {
return request;
}
public boolean isHttps() {
return sslHandlerClass != null && ctx.pipeline().get(sslHandlerClass) != null;
}
public HttpHeaders headers() {
return request.headers();
}
public HttpVersion protocolVersion() {
return request.getProtocolVersion();
}
public String uri() {
return request.getUri();
}
public HttpMethod method() {
return request().getMethod();
}
}

View File

@ -27,13 +27,15 @@ import spock.lang.Shared
class Netty40ClientTest extends HttpClientTest<DefaultFullHttpRequest> implements AgentTestTrait { class Netty40ClientTest extends HttpClientTest<DefaultFullHttpRequest> implements AgentTestTrait {
@Shared
private EventLoopGroup eventLoopGroup = new NioEventLoopGroup()
@Shared @Shared
private Bootstrap bootstrap private Bootstrap bootstrap
def setupSpec() { def setupSpec() {
EventLoopGroup group = new NioEventLoopGroup()
bootstrap = new Bootstrap() bootstrap = new Bootstrap()
bootstrap.group(group) bootstrap.group(eventLoopGroup)
.channel(NioSocketChannel) .channel(NioSocketChannel)
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, CONNECT_TIMEOUT_MS) .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, CONNECT_TIMEOUT_MS)
.handler(new ChannelInitializer<SocketChannel>() { .handler(new ChannelInitializer<SocketChannel>() {
@ -45,6 +47,10 @@ class Netty40ClientTest extends HttpClientTest<DefaultFullHttpRequest> implement
}) })
} }
def cleanupSpec() {
eventLoopGroup?.shutdownGracefully()
}
@Override @Override
DefaultFullHttpRequest buildRequest(String method, URI uri, Map<String, String> headers) { DefaultFullHttpRequest buildRequest(String method, URI uri, Map<String, String> headers) {
def request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.valueOf(method), uri.toString(), Unpooled.EMPTY_BUFFER) def request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.valueOf(method), uri.toString(), Unpooled.EMPTY_BUFFER)

View File

@ -35,7 +35,8 @@ public class HttpClientRequestTracingHandler extends ChannelOutboundHandlerAdapt
return; return;
} }
Context context = tracer().startSpan(parentContext, ctx, (HttpRequest) msg); NettyRequestWrapper requestWrapper = new NettyRequestWrapper((HttpRequest) msg, ctx);
Context context = tracer().startSpan(parentContext, ctx, requestWrapper);
Attribute<Context> clientContextAttr = ctx.channel().attr(AttributeKeys.CLIENT_CONTEXT); Attribute<Context> clientContextAttr = ctx.channel().attr(AttributeKeys.CLIENT_CONTEXT);
Attribute<Context> parentContextAttr = ctx.channel().attr(AttributeKeys.CLIENT_PARENT_CONTEXT); Attribute<Context> parentContextAttr = ctx.channel().attr(AttributeKeys.CLIENT_PARENT_CONTEXT);

View File

@ -29,7 +29,7 @@ import java.net.URISyntaxException;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
public class NettyHttpClientTracer public class NettyHttpClientTracer
extends HttpClientTracer<HttpRequest, HttpHeaders, HttpResponse> { extends HttpClientTracer<NettyRequestWrapper, HttpHeaders, HttpResponse> {
private static final NettyHttpClientTracer TRACER = new NettyHttpClientTracer(); private static final NettyHttpClientTracer TRACER = new NettyHttpClientTracer();
private NettyHttpClientTracer() { private NettyHttpClientTracer() {
@ -40,7 +40,8 @@ public class NettyHttpClientTracer
return TRACER; return TRACER;
} }
public Context startSpan(Context parentContext, ChannelHandlerContext ctx, HttpRequest request) { public Context startSpan(
Context parentContext, ChannelHandlerContext ctx, NettyRequestWrapper request) {
SpanBuilder spanBuilder = spanBuilder(parentContext, spanNameForRequest(request), CLIENT); SpanBuilder spanBuilder = spanBuilder(parentContext, spanNameForRequest(request), CLIENT);
onRequest(spanBuilder, request); onRequest(spanBuilder, request);
NetPeerAttributes.INSTANCE.setNetPeer( NetPeerAttributes.INSTANCE.setNetPeer(
@ -62,24 +63,24 @@ public class NettyHttpClientTracer
} }
@Override @Override
protected String method(HttpRequest httpRequest) { protected String method(NettyRequestWrapper httpRequest) {
return httpRequest.method().name(); return httpRequest.method().name();
} }
@Override @Override
@Nullable @Nullable
protected String flavor(HttpRequest httpRequest) { protected String flavor(NettyRequestWrapper httpRequest) {
return httpRequest.protocolVersion().text(); return httpRequest.protocolVersion().text();
} }
@Override @Override
protected URI url(HttpRequest request) throws URISyntaxException { protected URI url(NettyRequestWrapper request) throws URISyntaxException {
URI uri = new URI(request.uri()); URI uri = new URI(request.uri());
if ((uri.getHost() == null || uri.getHost().equals("")) && request.headers().contains(HOST)) { if ((uri.getHost() == null || uri.getHost().equals("")) && request.headers().contains(HOST)) {
return new URI("http://" + request.headers().get(HOST) + request.uri()); String protocol = request.isHttps() ? "https://" : "http://";
} else { uri = new URI(protocol + request.headers().get(HOST) + request.uri());
return uri;
} }
return uri;
} }
@Override @Override
@ -88,7 +89,7 @@ public class NettyHttpClientTracer
} }
@Override @Override
protected String requestHeader(HttpRequest httpRequest, String name) { protected String requestHeader(NettyRequestWrapper httpRequest, String name) {
return httpRequest.headers().get(name); return httpRequest.headers().get(name);
} }

View File

@ -0,0 +1,62 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.netty.v4_1.client;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.HttpVersion;
public class NettyRequestWrapper {
private static final Class<? extends ChannelHandler> sslHandlerClass = getSslHandlerClass();
@SuppressWarnings("unchecked")
private static Class<? extends ChannelHandler> getSslHandlerClass() {
try {
return (Class<? extends ChannelHandler>)
Class.forName(
"io.netty.handler.ssl.SslHandler",
false,
HttpClientRequestTracingHandler.class.getClassLoader());
} catch (ClassNotFoundException exception) {
return null;
}
}
private final HttpRequest request;
private final ChannelHandlerContext ctx;
public NettyRequestWrapper(HttpRequest request, ChannelHandlerContext ctx) {
this.request = request;
this.ctx = ctx;
}
public HttpRequest request() {
return request;
}
public boolean isHttps() {
return sslHandlerClass != null && ctx.pipeline().get(sslHandlerClass) != null;
}
public HttpHeaders headers() {
return request.headers();
}
public HttpVersion protocolVersion() {
return request.protocolVersion();
}
public String uri() {
return request.uri();
}
public HttpMethod method() {
return request().method();
}
}

View File

@ -25,6 +25,9 @@ import io.netty.handler.codec.http.HttpClientCodec
import io.netty.handler.codec.http.HttpHeaderNames import io.netty.handler.codec.http.HttpHeaderNames
import io.netty.handler.codec.http.HttpMethod import io.netty.handler.codec.http.HttpMethod
import io.netty.handler.codec.http.HttpVersion import io.netty.handler.codec.http.HttpVersion
import io.netty.handler.ssl.SslContext
import io.netty.handler.ssl.SslContextBuilder
import io.netty.handler.ssl.util.InsecureTrustManagerFactory
import io.opentelemetry.api.common.AttributeKey import io.opentelemetry.api.common.AttributeKey
import io.opentelemetry.instrumentation.test.AgentTestTrait import io.opentelemetry.instrumentation.test.AgentTestTrait
import io.opentelemetry.instrumentation.test.base.HttpClientTest import io.opentelemetry.instrumentation.test.base.HttpClientTest
@ -39,24 +42,39 @@ import spock.lang.Unroll
class Netty41ClientTest extends HttpClientTest<DefaultFullHttpRequest> implements AgentTestTrait { class Netty41ClientTest extends HttpClientTest<DefaultFullHttpRequest> implements AgentTestTrait {
@Shared @Shared
private Bootstrap bootstrap private EventLoopGroup eventLoopGroup = buildEventLoopGroup()
def setupSpec() { @Shared
EventLoopGroup group = getEventLoopGroup() private Bootstrap bootstrap = buildBootstrap(false)
bootstrap = new Bootstrap()
bootstrap.group(group) @Shared
private Bootstrap httpsBootstrap = buildBootstrap(true)
def cleanupSpec() {
eventLoopGroup?.shutdownGracefully()
}
Bootstrap buildBootstrap(boolean https) {
Bootstrap bootstrap = new Bootstrap()
bootstrap.group(eventLoopGroup)
.channel(getChannelClass()) .channel(getChannelClass())
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, CONNECT_TIMEOUT_MS) .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, CONNECT_TIMEOUT_MS)
.handler(new ChannelInitializer<SocketChannel>() { .handler(new ChannelInitializer<SocketChannel>() {
@Override @Override
protected void initChannel(SocketChannel socketChannel) throws Exception { protected void initChannel(SocketChannel socketChannel) throws Exception {
ChannelPipeline pipeline = socketChannel.pipeline() ChannelPipeline pipeline = socketChannel.pipeline()
if (https) {
SslContext sslContext = SslContextBuilder.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE).build()
pipeline.addLast(sslContext.newHandler(socketChannel.alloc()))
}
pipeline.addLast(new HttpClientCodec()) pipeline.addLast(new HttpClientCodec())
} }
}) })
return bootstrap
} }
EventLoopGroup getEventLoopGroup() { EventLoopGroup buildEventLoopGroup() {
return new NioEventLoopGroup() return new NioEventLoopGroup()
} }
@ -64,6 +82,10 @@ class Netty41ClientTest extends HttpClientTest<DefaultFullHttpRequest> implement
return NioSocketChannel return NioSocketChannel
} }
Bootstrap getBootstrap(URI uri) {
return uri.getScheme() == "https" ? httpsBootstrap : bootstrap
}
@Override @Override
DefaultFullHttpRequest buildRequest(String method, URI uri, Map<String, String> headers) { DefaultFullHttpRequest buildRequest(String method, URI uri, Map<String, String> headers) {
def request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.valueOf(method), uri.toString(), Unpooled.EMPTY_BUFFER) def request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.valueOf(method), uri.toString(), Unpooled.EMPTY_BUFFER)
@ -74,7 +96,7 @@ class Netty41ClientTest extends HttpClientTest<DefaultFullHttpRequest> implement
@Override @Override
int sendRequest(DefaultFullHttpRequest request, String method, URI uri, Map<String, String> headers) { int sendRequest(DefaultFullHttpRequest request, String method, URI uri, Map<String, String> headers) {
def channel = bootstrap.connect(uri.host, getPort(uri)).sync().channel() def channel = getBootstrap(uri).connect(uri.host, getPort(uri)).sync().channel()
def result = new CompletableFuture<Integer>() def result = new CompletableFuture<Integer>()
channel.pipeline().addLast(new ClientHandler(result)) channel.pipeline().addLast(new ClientHandler(result))
channel.writeAndFlush(request).get() channel.writeAndFlush(request).get()
@ -85,7 +107,7 @@ class Netty41ClientTest extends HttpClientTest<DefaultFullHttpRequest> implement
void sendRequestWithCallback(DefaultFullHttpRequest request, String method, URI uri, Map<String, String> headers, RequestResult requestResult) { void sendRequestWithCallback(DefaultFullHttpRequest request, String method, URI uri, Map<String, String> headers, RequestResult requestResult) {
Channel ch Channel ch
try { try {
ch = bootstrap.connect(uri.host, getPort(uri)).sync().channel() ch = getBootstrap(uri).connect(uri.host, getPort(uri)).sync().channel()
} catch (Exception exception) { } catch (Exception exception) {
requestResult.complete(exception) requestResult.complete(exception)
return return
@ -124,11 +146,6 @@ class Netty41ClientTest extends HttpClientTest<DefaultFullHttpRequest> implement
false false
} }
@Override
boolean testHttps() {
false
}
def "test connection reuse and second request with lazy execute"() { def "test connection reuse and second request with lazy execute"() {
setup: setup:
//Create a simple Netty pipeline //Create a simple Netty pipeline

View File

@ -16,7 +16,7 @@ import org.junit.Assume
// netty client test with epoll/kqueue native library // netty client test with epoll/kqueue native library
class Netty41NativeClientTest extends Netty41ClientTest { class Netty41NativeClientTest extends Netty41ClientTest {
EventLoopGroup getEventLoopGroup() { EventLoopGroup buildEventLoopGroup() {
// linux // linux
if (Epoll.isAvailable()) { if (Epoll.isAvailable()) {
return new EpollEventLoopGroup() return new EpollEventLoopGroup()
@ -28,7 +28,7 @@ class Netty41NativeClientTest extends Netty41ClientTest {
// skip test when native library was not found // skip test when native library was not found
Assume.assumeTrue("Native library was not found", false) Assume.assumeTrue("Native library was not found", false)
return super.getEventLoopGroup() return super.buildEventLoopGroup()
} }
@Override @Override

View File

@ -62,11 +62,6 @@ class PlayWsClientTest extends HttpClientTest<WSRequest> implements AgentTestTra
false false
} }
@Override
boolean testHttps() {
false
}
@Override @Override
Set<AttributeKey<?>> httpAttributes(URI uri) { Set<AttributeKey<?>> httpAttributes(URI uri) {
Set<AttributeKey<?>> extra = [ Set<AttributeKey<?>> extra = [

View File

@ -148,9 +148,4 @@ class RatpackHttpClientTest extends HttpClientTest<Void> implements AgentTestTra
// these tests will pass, but they don't really test anything since REQUEST is Void // these tests will pass, but they don't really test anything since REQUEST is Void
false false
} }
@Override
boolean testHttps() {
false
}
} }

View File

@ -27,11 +27,6 @@ abstract class AbstractReactorNettyHttpClientTest extends HttpClientTest<HttpCli
false false
} }
@Override
boolean testHttps() {
false
}
@Override @Override
String userAgent() { String userAgent() {
return "ReactorNetty" return "ReactorNetty"

View File

@ -32,11 +32,6 @@ abstract class AbstractReactorNettyHttpClientTest extends HttpClientTest<HttpCli
false false
} }
@Override
boolean testHttps() {
false
}
@Override @Override
String userAgent() { String userAgent() {
return "ReactorNetty" return "ReactorNetty"