Repository: eclipse-vertx/vert.x

Problem statement:
Support UNIX Domain Sockets in HttpClient
Netty already supports DomainSockets/DomainChannels, so I was hoping it might be possible to implement support (via HttpOptions/SocketOptions) to support UNIX Domain sockets (AF_UNIX)??? We do this quite often for secured APIs across docker containers. We mount the socket file as a volume in the container and then the different applications communicate via the UNIX Domain socket. We have also taken to communicating with the Docker daemon itself in this manner instead of exposing the Docker HTTP API.

My suggestion for implementation would be one of the following:

Add an overloaded method for Vertx.create(Net/Http)(Client/Server) which could take a "Path" object to point to the location for the UNIX domain socket..

Add logic to the Net/HTTP Client/Server implementations to parse a URL of the format "unix+http://" or "unix+socket://"

Probably many more questions to be answered, but that should be a good start.



Hints:
@InfoSec812 where is this unix+http:// format described ?

I actually talked about this last week with someone because of the docker client use case 

see https://github.com/vert-x3/issues/issues/188 also

ah but it's you :-)

so it's expected to be discussed at F2F meeting next week, is that something you could contribute ?

and I told you to open an issue here :-)

see also https://github.com/eclipse/vert.x/pull/1388

@vietj The format I was conceptualizing was the same one used by Twisted (The Python NIO framework). It is described [HERE](http://twistedmatrix.com/documents/13.1.0/core/howto/endpoints.html#auto9) under Server endpoint types.

@vietj Is the F2F meeting going to be on-line via something like a Google Hangout? I'd be happy to attend depending on the timing.

@InfoSec812 we will for sure take minutes and make slides available, can't promise for hangout

https://docs.docker.com/engine/reference/api/docker_remote_api/

thats my use case for this.  
@samart yes that's a very valid use case
@vietj , we plan to look at implementations like  https://github.com/gesellix/unix-socket-factory with apache http client :( until something emerges natively for vert.x http client
note that you can workaround using docker registry via socket domains with proper configuration.
You mean http?  Yes, but trying to avoid exposing http for our docker daemons as it's a security and certificate mgmt. issue.   Also, don't want to muck w/iptables to effect local access only, hence the domain socket preference.  Other option is to write this service in golang, but trying to stay w/vert.x for now.

https://netty.io/4.0/api/io/netty/channel/unix/package-summary.html

Any plans on adding this support in vert.x http client?
we might support epoll for 3.5
Domain socket support will be provided by https://github.com/eclipse/vert.x/issues/2135, I will rename this issue so it only scopes HTTP server and client
http server supports it
Is there any update on this?
not yet but it is still a, important feature. I've done some experiments locally and it might be back-portable to 3.x

Patch:
diff --git a/src/main/java/examples/CoreExamples.java b/src/main/java/examples/CoreExamples.java
--- a/src/main/java/examples/CoreExamples.java
+++ b/src/main/java/examples/CoreExamples.java
@@ -15,6 +15,8 @@
 import io.vertx.core.buffer.Buffer;
 import io.vertx.core.dns.AddressResolverOptions;
 import io.vertx.core.file.FileSystem;
+import io.vertx.core.http.HttpClient;
+import io.vertx.core.http.HttpMethod;
 import io.vertx.core.http.HttpServer;
 import io.vertx.core.http.HttpServerOptions;
 import io.vertx.core.http.HttpServerRequest;
@@ -394,7 +396,7 @@ public void configureBSDOptions(Vertx vertx, boolean reusePort) {
     vertx.createHttpServer(new HttpServerOptions().setReusePort(reusePort));
   }
 
-  public void serverWithDomainSockets(Vertx vertx) {
+  public void tcpServerWithDomainSockets(Vertx vertx) {
     // Only available on BSD and Linux
     vertx.createNetServer().connectHandler(so -> {
       // Handle application
@@ -413,11 +415,14 @@ public void httpServerWithDomainSockets(Vertx vertx) {
     });
   }
 
-  public void clientWithDomainSockets(Vertx vertx) {
+  public void tcpClientWithDomainSockets(Vertx vertx) {
     NetClient netClient = vertx.createNetClient();
 
     // Only available on BSD and Linux
-    netClient.connect(SocketAddress.domainSocketAddress("/var/tmp/myservice.sock"), ar -> {
+    SocketAddress addr = SocketAddress.domainSocketAddress("/var/tmp/myservice.sock");
+
+    // Connect to the server
+    netClient.connect(addr, ar -> {
       if (ar.succeeded()) {
         // Connected
       } else {
@@ -425,4 +430,16 @@ public void clientWithDomainSockets(Vertx vertx) {
       }
     });
   }
+
+  public void httpClientWithDomainSockets(Vertx vertx) {
+    HttpClient httpClient = vertx.createHttpClient();
+
+    // Only available on BSD and Linux
+    SocketAddress addr = SocketAddress.domainSocketAddress("/var/tmp/myservice.sock");
+
+    // Send request to the server
+    httpClient.request(HttpMethod.GET, addr, 8080, "localhost", "/", resp -> {
+      // Process response
+    }).end();
+  }
 }
diff --git a/src/main/java/io/vertx/core/http/HttpClient.java b/src/main/java/io/vertx/core/http/HttpClient.java
--- a/src/main/java/io/vertx/core/http/HttpClient.java
+++ b/src/main/java/io/vertx/core/http/HttpClient.java
@@ -18,6 +18,7 @@
 import io.vertx.core.Handler;
 import io.vertx.core.MultiMap;
 import io.vertx.core.metrics.Measured;
+import io.vertx.core.net.SocketAddress;
 import io.vertx.core.streams.ReadStream;
 
 import java.util.function.Function;
@@ -53,6 +54,16 @@
 @VertxGen
 public interface HttpClient extends Measured {
 
+  /**
+   * Like {@link #request(HttpMethod, RequestOptions)} using the {@code serverAddress} parameter to connect to the
+   * server instead of the {@code absoluteURI} parameter.
+   * <p>
+   * The request host header will still be created from the {@code options} parameter.
+   * <p>
+   * Use {@link SocketAddress#domainSocketAddress(String)} to connect to a unix domain socket server.
+   */
+  HttpClientRequest request(HttpMethod method, SocketAddress serverAddress, RequestOptions options);
+
   /**
    * Create an HTTP request to send to the server with the specified options.
    *
@@ -72,6 +83,16 @@ public interface HttpClient extends Measured {
    */
   HttpClientRequest request(HttpMethod method, int port, String host, String requestURI);
 
+  /**
+   * Like {@link #request(HttpMethod, int, String, String)} using the {@code serverAddress} parameter to connect to the
+   * server instead of the {@code absoluteURI} parameter.
+   * <p>
+   * The request host header will still be created from the {@code host} and {@code port} parameters.
+   * <p>
+   * Use {@link SocketAddress#domainSocketAddress(String)} to connect to a unix domain socket server.
+   */
+  HttpClientRequest request(HttpMethod method, SocketAddress serverAddress, int port, String host, String requestURI);
+
   /**
    * Create an HTTP request to send to the server at the specified host and default port.
    * @param method  the HTTP method
@@ -92,6 +113,16 @@ public interface HttpClient extends Measured {
   @Deprecated
   HttpClientRequest request(HttpMethod method, RequestOptions options, Handler<HttpClientResponse> responseHandler);
 
+  /**
+   * Like {@link #request(HttpMethod, RequestOptions, Handler)} using the {@code serverAddress} parameter to connect to the
+   * server instead of the {@code absoluteURI} parameter.
+   * <p>
+   * The request host header will still be created from the {@code options} parameter.
+   * <p>
+   * Use {@link SocketAddress#domainSocketAddress(String)} to connect to a unix domain socket server.
+   */
+  HttpClientRequest request(HttpMethod method, SocketAddress serverAddress, RequestOptions options, Handler<HttpClientResponse> responseHandler);
+
   /**
    * Create an HTTP request to send to the server at the specified host and port, specifying a response handler to receive
    * the response
@@ -107,6 +138,16 @@ public interface HttpClient extends Measured {
   @Deprecated
   HttpClientRequest request(HttpMethod method, int port, String host, String requestURI, Handler<HttpClientResponse> responseHandler);
 
+  /**
+   * Like {@link #request(HttpMethod, int, String, String, Handler)} using the {@code serverAddress} parameter to connect to the
+   * server instead of the {@code absoluteURI} parameter.
+   * <p>
+   * The request host header will still be created from the {@code host} and {@code port} parameters.
+   * <p>
+   * Use {@link SocketAddress#domainSocketAddress(String)} to connect to a unix domain socket server.
+   */
+  HttpClientRequest request(HttpMethod method, SocketAddress serverAddress, int port, String host, String requestURI, Handler<HttpClientResponse> responseHandler);
+
   /**
    * Create an HTTP request to send to the server at the specified host and default port, specifying a response handler to receive
    * the response
@@ -150,6 +191,16 @@ public interface HttpClient extends Measured {
    */
   HttpClientRequest requestAbs(HttpMethod method, String absoluteURI);
 
+  /**
+   * Like {@link #requestAbs(HttpMethod, String)} using the {@code serverAddress} parameter to connect to the
+   * server instead of the {@code absoluteURI} parameter.
+   * <p>
+   * The request host header will still be created from the {@code absoluteURI} parameter.
+   * <p>
+   * Use {@link SocketAddress#domainSocketAddress(String)} to connect to a unix domain socket server.
+   */
+  HttpClientRequest requestAbs(HttpMethod method, SocketAddress serverAddress, String absoluteURI);
+
   /**
    * Create an HTTP request to send to the server using an absolute URI, specifying a response handler to receive
    * the response
@@ -163,6 +214,16 @@ public interface HttpClient extends Measured {
   @Deprecated
   HttpClientRequest requestAbs(HttpMethod method, String absoluteURI, Handler<HttpClientResponse> responseHandler);
 
+  /**
+   * Like {@link #requestAbs(HttpMethod, String, Handler)} using the {@code serverAddress} parameter to connect to the
+   * server instead of the {@code absoluteURI} parameter.
+   * <p>
+   * The request host header will still be created from the {@code absoluteURI} parameter.
+   * <p>
+   * Use {@link SocketAddress#domainSocketAddress(String)} to connect to a unix domain socket server.
+   */
+  HttpClientRequest requestAbs(HttpMethod method, SocketAddress serverAddress, String absoluteURI, Handler<HttpClientResponse> responseHandler);
+
   /**
    * Create an HTTP GET request to send to the server with the specified options.
    * @param options  the request options
diff --git a/src/main/java/io/vertx/core/http/RequestOptions.java b/src/main/java/io/vertx/core/http/RequestOptions.java
--- a/src/main/java/io/vertx/core/http/RequestOptions.java
+++ b/src/main/java/io/vertx/core/http/RequestOptions.java
@@ -35,7 +35,7 @@ public class RequestOptions {
   /**
    * SSL enabled by default = false
    */
-  public static final boolean DEFAULT_SSL = false;
+  public static final Boolean DEFAULT_SSL = null;
 
   /**
    * The default relative request URI = ""
@@ -44,7 +44,7 @@ public class RequestOptions {
 
   private String host;
   private int port;
-  private boolean ssl;
+  private Boolean ssl;
   private String uri;
 
   /**
@@ -123,7 +123,7 @@ public RequestOptions setPort(int port) {
   /**
    * @return is SSL/TLS enabled?
    */
-  public boolean isSsl() {
+  public Boolean isSsl() {
     return ssl;
   }
 
@@ -133,7 +133,7 @@ public boolean isSsl() {
    * @param ssl  true if enabled
    * @return a reference to this, so the API can be used fluently
    */
-  public RequestOptions setSsl(boolean ssl) {
+  public RequestOptions setSsl(Boolean ssl) {
     this.ssl = ssl;
     return this;
   }
diff --git a/src/main/java/io/vertx/core/http/impl/ConnectionManager.java b/src/main/java/io/vertx/core/http/impl/ConnectionManager.java
--- a/src/main/java/io/vertx/core/http/impl/ConnectionManager.java
+++ b/src/main/java/io/vertx/core/http/impl/ConnectionManager.java
@@ -18,6 +18,7 @@
 import io.vertx.core.http.HttpVersion;
 import io.vertx.core.http.impl.pool.Pool;
 import io.vertx.core.impl.ContextInternal;
+import io.vertx.core.net.SocketAddress;
 import io.vertx.core.spi.metrics.HttpClientMetrics;
 
 import java.util.*;
@@ -66,21 +67,19 @@ private synchronized void checkExpired(long period) {
   private static final class EndpointKey {
 
     private final boolean ssl;
-    private final int port;
-    private final String peerHost;
-    private final String host;
+    private final SocketAddress server;
+    private final SocketAddress peerAddress;
 
-    EndpointKey(boolean ssl, int port, String peerHost, String host) {
-      if (host == null) {
+    EndpointKey(boolean ssl, SocketAddress server, SocketAddress peerAddress) {
+      if (server == null) {
         throw new NullPointerException("No null host");
       }
-      if (peerHost == null) {
-        throw new NullPointerException("No null peer host");
+      if (peerAddress == null) {
+        throw new NullPointerException("No null peer address");
       }
       this.ssl = ssl;
-      this.peerHost = peerHost;
-      this.host = host;
-      this.port = port;
+      this.peerAddress = peerAddress;
+      this.server = server;
     }
 
     @Override
@@ -88,15 +87,14 @@ public boolean equals(Object o) {
       if (this == o) return true;
       if (o == null || getClass() != o.getClass()) return false;
       EndpointKey that = (EndpointKey) o;
-      return ssl == that.ssl && port == that.port && peerHost.equals(that.peerHost) && host.equals(that.host);
+      return ssl == that.ssl && server.equals(that.server) && peerAddress.equals(that.peerAddress);
     }
 
     @Override
     public int hashCode() {
       int result = ssl ? 1 : 0;
-      result = 31 * result + peerHost.hashCode();
-      result = 31 * result + host.hashCode();
-      result = 31 * result + port;
+      result = 31 * result + peerAddress.hashCode();
+      result = 31 * result + server.hashCode();
       return result;
     }
   }
@@ -112,13 +110,22 @@ public Endpoint(Pool<HttpClientConnection> pool, Object metric) {
     }
   }
 
-  void getConnection(ContextInternal ctx, String peerHost, boolean ssl, int port, String host, Handler<AsyncResult<HttpClientConnection>> handler) {
-    EndpointKey key = new EndpointKey(ssl, port, peerHost, host);
+  void getConnection(ContextInternal ctx, SocketAddress peerAddress, boolean ssl, SocketAddress server, Handler<AsyncResult<HttpClientConnection>> handler) {
+    EndpointKey key = new EndpointKey(ssl, server, peerAddress);
     while (true) {
       Endpoint endpoint = endpointMap.computeIfAbsent(key, targetAddress -> {
         int maxPoolSize = Math.max(client.getOptions().getMaxPoolSize(), client.getOptions().getHttp2MaxPoolSize());
+        String host;
+        int port;
+        if (server.path() == null) {
+          host = server.host();
+          port = server.port();
+        } else {
+          host = server.path();
+          port = 0;
+        }
         Object metric = metrics != null ? metrics.createEndpoint(host, port, maxPoolSize) : null;
-        HttpChannelConnector connector = new HttpChannelConnector(client, metric, version, ssl, peerHost, host, port);
+        HttpChannelConnector connector = new HttpChannelConnector(client, metric, version, ssl, peerAddress, server);
         Pool<HttpClientConnection> pool = new Pool<>(ctx, connector, maxWaitQueueSize, connector.weight(), maxSize,
           v -> {
             if (metrics != null) {
diff --git a/src/main/java/io/vertx/core/http/impl/Http1xClientConnection.java b/src/main/java/io/vertx/core/http/impl/Http1xClientConnection.java
--- a/src/main/java/io/vertx/core/http/impl/Http1xClientConnection.java
+++ b/src/main/java/io/vertx/core/http/impl/Http1xClientConnection.java
@@ -35,6 +35,7 @@
 import io.vertx.core.logging.Logger;
 import io.vertx.core.logging.LoggerFactory;
 import io.vertx.core.net.NetSocket;
+import io.vertx.core.net.SocketAddress;
 import io.vertx.core.net.impl.NetSocketImpl;
 import io.vertx.core.net.impl.VertxHandler;
 import io.vertx.core.spi.metrics.HttpClientMetrics;
@@ -63,8 +64,7 @@ class Http1xClientConnection extends Http1xConnectionBase<WebSocketImpl> impleme
   private final HttpClientImpl client;
   private final HttpClientOptions options;
   private final boolean ssl;
-  private final String host;
-  private final int port;
+  private final SocketAddress server;
   private final Object endpointMetric;
   private final HttpClientMetrics metrics;
   private final HttpVersion version;
@@ -85,8 +85,7 @@ class Http1xClientConnection extends Http1xConnectionBase<WebSocketImpl> impleme
                          Object endpointMetric,
                          ChannelHandlerContext channel,
                          boolean ssl,
-                         String host,
-                         int port,
+                         SocketAddress server,
                          ContextInternal context,
                          HttpClientMetrics metrics) {
     super(client.getVertx(), channel, context);
@@ -94,8 +93,7 @@ class Http1xClientConnection extends Http1xConnectionBase<WebSocketImpl> impleme
     this.client = client;
     this.options = client.getOptions();
     this.ssl = ssl;
-    this.host = host;
-    this.port = port;
+    this.server = server;
     this.metrics = metrics;
     this.version = version;
     this.endpointMetric = endpointMetric;
@@ -577,17 +575,19 @@ private void handleResponseBegin(HttpResponse resp) {
     StreamImpl stream;
     HttpClientResponseImpl response;
     HttpClientRequestImpl request;
-    Throwable err;
+    Exception err;
     synchronized (this) {
       stream = responseInProgress;
       request = stream.request;
+      HttpClientResponseImpl r = null;
+      Exception t = null;
       try {
-        response = stream.beginResponse(resp);
-        err = null;
+        r = stream.beginResponse(resp);
       } catch (Exception e) {
-        err = e;
-        response = null;
+        t = e;
       }
+      response = r;
+      err = t;
     }
     if (response != null) {
       request.handleResponse(response);
@@ -651,7 +651,7 @@ synchronized void toWebSocket(String requestURI, MultiMap headers, WebsocketVers
       URI wsuri = new URI(requestURI);
       if (!wsuri.isAbsolute()) {
         // Netty requires an absolute url
-        wsuri = new URI((ssl ? "https:" : "http:") + "//" + host + ":" + port + requestURI);
+        wsuri = new URI((ssl ? "https:" : "http:") + "//" + server.host() + ":" + server.port() + requestURI);
       }
       WebSocketVersion version =
          WebSocketVersion.valueOf((vers == null ?
@@ -812,8 +812,9 @@ private void handshakeComplete(ChannelHandlerContext ctx, FullHttpResponse respo
   @Override
   public synchronized void handleInterestedOpsChanged() {
     if (!isNotWritable()) {
-      if (requestInProgress != null) {
-        requestInProgress.request.handleDrained();
+      StreamImpl current = requestInProgress;
+      if (current != null) {
+        current.request.handleDrained();
       } else if (ws != null) {
         ws.handleDrained();
       }
diff --git a/src/main/java/io/vertx/core/http/impl/Http2ClientConnection.java b/src/main/java/io/vertx/core/http/impl/Http2ClientConnection.java
--- a/src/main/java/io/vertx/core/http/impl/Http2ClientConnection.java
+++ b/src/main/java/io/vertx/core/http/impl/Http2ClientConnection.java
@@ -172,10 +172,19 @@ public synchronized void onPushPromiseRead(ChannelHandlerContext ctx, int stream
           String rawMethod = headers.method().toString();
           HttpMethod method = HttpUtils.toVertxMethod(rawMethod);
           String uri = headers.path().toString();
-          String host = headers.authority() != null ? headers.authority().toString() : null;
+          String authority = headers.authority() != null ? headers.authority().toString() : null;
           MultiMap headersMap = new Http2HeadersAdaptor(headers);
           Http2Stream promisedStream = handler.connection().stream(promisedStreamId);
-          int port = remoteAddress().port();
+          int pos = authority.indexOf(':');
+          int port;
+          String host;
+          if (pos == -1) {
+            host = authority;
+            port = 80;
+          } else {
+            host = authority.substring(0, pos);
+            port = Integer.parseInt(authority.substring(pos + 1));
+          }
           HttpClientRequestPushPromise pushReq = new HttpClientRequestPushPromise(this, promisedStream, client, isSsl(), method, rawMethod, uri, host, port, headersMap);
           if (metrics != null) {
             pushReq.metric(metrics.responsePushed(queueMetric, metric(), localAddress(), remoteAddress(), pushReq));
@@ -420,7 +429,7 @@ public void reportBytesRead(long numberOfBytes) {
     }
 
     @Override
-    public Context getContext() {
+    public ContextInternal getContext() {
       return context;
     }
 
diff --git a/src/main/java/io/vertx/core/http/impl/HttpChannelConnector.java b/src/main/java/io/vertx/core/http/impl/HttpChannelConnector.java
--- a/src/main/java/io/vertx/core/http/impl/HttpChannelConnector.java
+++ b/src/main/java/io/vertx/core/http/impl/HttpChannelConnector.java
@@ -51,18 +51,16 @@ class HttpChannelConnector implements ConnectionProvider<HttpClientConnection> {
   private final long http2Weight;
   private final long http1MaxConcurrency;
   private final boolean ssl;
-  private final String peerHost;
-  private final String host;
-  private final int port;
+  private final SocketAddress peerAddress;
+  private final SocketAddress server;
   private final Object endpointMetric;
 
   HttpChannelConnector(HttpClientImpl client,
                        Object endpointMetric,
                        HttpVersion version,
                        boolean ssl,
-                       String peerHost,
-                       String host,
-                       int port) {
+                       SocketAddress peerAddress,
+                       SocketAddress server) {
     this.client = client;
     this.endpointMetric = endpointMetric;
     this.options = client.getOptions();
@@ -80,9 +78,8 @@ class HttpChannelConnector implements ConnectionProvider<HttpClientConnection> {
     this.weight = version == HttpVersion.HTTP_2 ? http2Weight : http1Weight;
     this.http1MaxConcurrency = options.isPipelining() ? options.getPipeliningLimit() : 1;
     this.ssl = ssl;
-    this.peerHost = peerHost;
-    this.host = host;
-    this.port = port;
+    this.peerAddress = peerAddress;
+    this.server = server;
   }
 
   public long weight() {
@@ -109,20 +106,21 @@ private void doConnect(
     ContextInternal context,
     Future<ConnectResult<HttpClientConnection>> future) {
 
+    boolean domainSocket = server.path() != null;
+    boolean useAlpn = options.isUseAlpn();
+
     Bootstrap bootstrap = new Bootstrap();
     bootstrap.group(context.nettyEventLoop());
-    bootstrap.channelFactory(client.getVertx().transport().channelFactory(false));
+    bootstrap.channelFactory(client.getVertx().transport().channelFactory(domainSocket));
 
-    applyConnectionOptions(false, bootstrap);
-
-    boolean useAlpn = options.isUseAlpn();
+    applyConnectionOptions(domainSocket, bootstrap);
 
     ProxyOptions options = this.options.getProxyOptions();
     if (options != null && !ssl && options.getType()== ProxyType.HTTP) {
       // http proxy requests are handled in HttpClientImpl, everything else can use netty proxy handler
       options = null;
     }
-    ChannelProvider channelProvider = new ChannelProvider(bootstrap, sslHelper, ssl, context, options);
+    ChannelProvider channelProvider = new ChannelProvider(bootstrap, sslHelper, context, options);
 
     Handler<AsyncResult<Channel>> channelHandler = res -> {
       if (res.succeeded()) {
@@ -137,25 +135,25 @@ private void doConnect(
               applyHttp1xConnectionOptions(ch.pipeline());
               HttpVersion fallbackProtocol = "http/1.0".equals(protocol) ?
                 HttpVersion.HTTP_1_0 : HttpVersion.HTTP_1_1;
-              http1xConnected(listener, fallbackProtocol, host, port, true, context, ch, http1Weight, future);
+              http1xConnected(listener, fallbackProtocol, server, true, context, ch, http1Weight, future);
             }
           } else {
             applyHttp1xConnectionOptions(ch.pipeline());
-            http1xConnected(listener, version, host, port, true, context, ch, http1Weight, future);
+            http1xConnected(listener, version, server, true, context, ch, http1Weight, future);
           }
         } else {
           ChannelPipeline pipeline = ch.pipeline();
           if (version == HttpVersion.HTTP_2) {
             if (this.options.isHttp2ClearTextUpgrade()) {
               applyHttp1xConnectionOptions(pipeline);
-              http1xConnected(listener, version, host, port, false, context, ch, http2Weight, future);
+              http1xConnected(listener, version, server, false, context, ch, http2Weight, future);
             } else {
               applyHttp2ConnectionOptions(pipeline);
               http2Connected(listener, context, ch, future);
             }
           } else {
             applyHttp1xConnectionOptions(pipeline);
-            http1xConnected(listener, version, host, port, false, context, ch, http1Weight, future);
+            http1xConnected(listener, version, server, false, context, ch, http1Weight, future);
           }
         }
       } else {
@@ -163,7 +161,8 @@ private void doConnect(
       }
     };
 
-    channelProvider.connect(SocketAddress.inetSocketAddress(port, host), SocketAddress.inetSocketAddress(port, peerHost), this.options.isForceSni() ? peerHost : null, channelHandler);
+    // SocketAddress.inetSocketAddress(server.port(), peerHost)
+    channelProvider.connect(server, peerAddress, this.options.isForceSni() ? peerAddress.host() : null, ssl, channelHandler);
   }
 
   private void applyConnectionOptions(boolean domainSocket, Bootstrap bootstrap) {
@@ -197,15 +196,14 @@ private void applyHttp1xConnectionOptions(ChannelPipeline pipeline) {
 
   private void http1xConnected(ConnectionListener<HttpClientConnection> listener,
                                HttpVersion version,
-                               String host,
-                               int port,
+                               SocketAddress server,
                                boolean ssl,
                                ContextInternal context,
                                Channel ch, long weight,
                                Future<ConnectResult<HttpClientConnection>> future) {
     boolean upgrade = version == HttpVersion.HTTP_2 && options.isHttp2ClearTextUpgrade();
     VertxHandler<Http1xClientConnection> clientHandler = VertxHandler.create(context, chctx -> {
-      Http1xClientConnection conn = new Http1xClientConnection(listener, upgrade ? HttpVersion.HTTP_1_1 : version, client, endpointMetric, chctx, ssl, host, port, context, metrics);
+      Http1xClientConnection conn = new Http1xClientConnection(listener, upgrade ? HttpVersion.HTTP_1_1 : version, client, endpointMetric, chctx, ssl, server, context, metrics);
       if (metrics != null) {
         context.executeFromIO(v -> {
           Object socketMetric = metrics.connected(conn.remoteAddress(), conn.remoteName());
diff --git a/src/main/java/io/vertx/core/http/impl/HttpClientImpl.java b/src/main/java/io/vertx/core/http/impl/HttpClientImpl.java
--- a/src/main/java/io/vertx/core/http/impl/HttpClientImpl.java
+++ b/src/main/java/io/vertx/core/http/impl/HttpClientImpl.java
@@ -25,6 +25,7 @@
 import io.vertx.core.logging.LoggerFactory;
 import io.vertx.core.net.ProxyOptions;
 import io.vertx.core.net.ProxyType;
+import io.vertx.core.net.SocketAddress;
 import io.vertx.core.net.impl.SSLHelper;
 import io.vertx.core.spi.metrics.HttpClientMetrics;
 import io.vertx.core.spi.metrics.Metrics;
@@ -84,7 +85,7 @@ public class HttpClientImpl implements HttpClient, MetricsProvider {
         if (query != null) {
           requestURI += "?" + query;
         }
-        return Future.succeededFuture(createRequest(m, uri.getHost(), port, ssl, requestURI, null));
+        return Future.succeededFuture(createRequest(m, null, uri.getHost(), port, ssl, requestURI, null));
       }
       return null;
     } catch (Exception e) {
@@ -452,8 +453,12 @@ public WebSocketStream websocketStream(String requestURI, MultiMap headers, Webs
 
   @Override
   public HttpClientRequest requestAbs(HttpMethod method, String absoluteURI, Handler<HttpClientResponse> responseHandler) {
-    Objects.requireNonNull(responseHandler, "no null responseHandler accepted");
-    return requestAbs(method, absoluteURI).handler(responseHandler);
+    return requestAbs(method, null, absoluteURI, responseHandler);
+  }
+
+  @Override
+  public HttpClientRequest requestAbs(HttpMethod method, SocketAddress serverAddress, String absoluteURI, Handler<HttpClientResponse> responseHandler) {
+    return requestAbs(method, serverAddress, absoluteURI).handler(responseHandler);
   }
 
   @Override
@@ -467,6 +472,12 @@ public HttpClientRequest request(HttpMethod method, int port, String host, Strin
     return request(method, port, host, requestURI).handler(responseHandler);
   }
 
+  @Override
+  public HttpClientRequest request(HttpMethod method, SocketAddress serverAddress, int port, String host, String requestURI, Handler<HttpClientResponse> responseHandler) {
+    Objects.requireNonNull(responseHandler, "no null responseHandler accepted");
+    return request(method, serverAddress, port, host, requestURI).handler(responseHandler);
+  }
+
   @Override
   public HttpClientRequest request(HttpMethod method, String host, String requestURI, Handler<HttpClientResponse> responseHandler) {
     return request(method, options.getDefaultPort(), host, requestURI, responseHandler);
@@ -484,6 +495,11 @@ public HttpClientRequest request(HttpMethod method, String requestURI, Handler<H
 
   @Override
   public HttpClientRequest requestAbs(HttpMethod method, String absoluteURI) {
+    return requestAbs(method, null, absoluteURI);
+  }
+
+  @Override
+  public HttpClientRequest requestAbs(HttpMethod method, SocketAddress serverAddress, String absoluteURI) {
     URL url = parseUrl(absoluteURI);
     Boolean ssl = false;
     int port = url.getPort();
@@ -507,12 +523,17 @@ public HttpClientRequest requestAbs(HttpMethod method, String absoluteURI) {
       }
     }
     // if we do not know the protocol, the port still may be -1, we will handle that below
-    return createRequest(method, protocol, url.getHost(), port, ssl, relativeUri, null);
+    return createRequest(method, serverAddress, protocol, url.getHost(), port, ssl, relativeUri, null);
   }
 
   @Override
   public HttpClientRequest request(HttpMethod method, int port, String host, String requestURI) {
-    return createRequest(method, host, port, null, requestURI, null);
+    return createRequest(method, null, host, port, null, requestURI, null);
+  }
+
+  @Override
+  public HttpClientRequest request(HttpMethod method, SocketAddress serverAddress, int port, String host, String requestURI) {
+    return createRequest(method, serverAddress, host, port, null, requestURI, null);
   }
 
   @Override
@@ -520,9 +541,19 @@ public HttpClientRequest request(HttpMethod method, RequestOptions options, Hand
     return request(method, options).handler(responseHandler);
   }
 
+  @Override
+  public HttpClientRequest request(HttpMethod method, SocketAddress serverAddress, RequestOptions options, Handler<HttpClientResponse> responseHandler) {
+    return request(method, serverAddress, options).handler(responseHandler);
+  }
+
+  @Override
+  public HttpClientRequest request(HttpMethod method, SocketAddress serverAddress, RequestOptions options) {
+    return createRequest(method, serverAddress, options.getHost(), options.getPort(), options.isSsl(), options.getURI(), null);
+  }
+
   @Override
   public HttpClientRequest request(HttpMethod method, RequestOptions options) {
-    return createRequest(method, options.getHost(), options.getPort(), options.isSsl(), options.getURI(), null);
+    return createRequest(method, null, options.getHost(), options.getPort(), options.isSsl(), options.getURI(), null);
   }
 
   @Override
@@ -951,7 +982,7 @@ private void getConnectionForWebsocket(ContextInternal ctx,
                                          String host,
                                          Handler<Http1xClientConnection> handler,
                                          Handler<Throwable> connectionExceptionHandler) {
-    websocketCM.getConnection(ctx, host, ssl, port, host, ar -> {
+    websocketCM.getConnection(ctx, SocketAddress.inetSocketAddress(port, host), ssl, SocketAddress.inetSocketAddress(port, host), ar -> {
       if (ar.succeeded()) {
         HttpClientConnection conn = ar.result();
         conn.getContext().executeFromIO(v -> {
@@ -966,12 +997,11 @@ private void getConnectionForWebsocket(ContextInternal ctx,
   }
 
   void getConnectionForRequest(ContextInternal ctx,
-                               String peerHost,
+                               SocketAddress peerAddress,
                                boolean ssl,
-                               int port,
-                               String host,
+                               SocketAddress server,
                                Handler<AsyncResult<HttpClientStream>> handler) {
-    httpCM.getConnection(ctx, peerHost, ssl, port, host, ar -> {
+    httpCM.getConnection(ctx, peerAddress, ssl, server, ar -> {
       if (ar.succeeded()) {
         ar.result().createStream(handler);
       } else {
@@ -1001,15 +1031,15 @@ private URL parseUrl(String surl) {
   }
 
   private HttpClient requestNow(HttpMethod method, RequestOptions options, Handler<HttpClientResponse> responseHandler) {
-    createRequest(method, options.getHost(), options.getPort(), options.isSsl(), options.getURI(), null).handler(responseHandler).end();
+    createRequest(method, null, options.getHost(), options.getPort(), options.isSsl(), options.getURI(), null).handler(responseHandler).end();
     return this;
   }
 
-  private HttpClientRequest createRequest(HttpMethod method, String host, int port, Boolean ssl, String relativeURI, MultiMap headers) {
-    return createRequest(method, ssl==null || ssl==false ? "http" : "https", host, port, ssl, relativeURI, headers);
+  private HttpClientRequest createRequest(HttpMethod method, SocketAddress serverAddress, String host, int port, Boolean ssl, String relativeURI, MultiMap headers) {
+    return createRequest(method, serverAddress, ssl==null || ssl==false ? "http" : "https", host, port, ssl, relativeURI, headers);
   }
 
-  private HttpClientRequest createRequest(HttpMethod method, String protocol, String host, int port, Boolean ssl, String relativeURI, MultiMap headers) {
+  private HttpClientRequest createRequest(HttpMethod method, SocketAddress server, String protocol, String host, int port, Boolean ssl, String relativeURI, MultiMap headers) {
     Objects.requireNonNull(method, "no null method accepted");
     Objects.requireNonNull(protocol, "no null protocol accepted");
     Objects.requireNonNull(host, "no null host accepted");
@@ -1023,8 +1053,8 @@ private HttpClientRequest createRequest(HttpMethod method, String protocol, Stri
     HttpClientRequest req;
     boolean useProxy = !useSSL && proxyType == ProxyType.HTTP;
     if (useProxy) {
-      final int defaultPort = protocol.equals("ftp") ? 21 : 80;
-      final String addPort = (port != -1 && port != defaultPort) ? (":" + port) : "";
+      int defaultPort = protocol.equals("ftp") ? 21 : 80;
+      String addPort = (port != -1 && port != defaultPort) ? (":" + port) : "";
       relativeURI = protocol + "://" + host + addPort + relativeURI;
       ProxyOptions proxyOptions = options.getProxyOptions();
       if (proxyOptions.getUsername() != null && proxyOptions.getPassword() != null) {
@@ -1034,11 +1064,13 @@ private HttpClientRequest createRequest(HttpMethod method, String protocol, Stri
         headers.add("Proxy-Authorization", "Basic " + Base64.getEncoder()
             .encodeToString((proxyOptions.getUsername() + ":" + proxyOptions.getPassword()).getBytes()));
       }
-      req = new HttpClientRequestImpl(this, useSSL, method, proxyOptions.getHost(), proxyOptions.getPort(),
-          relativeURI, vertx);
-      req.setHost(host + addPort);
+      req = new HttpClientRequestImpl(this, useSSL, method, SocketAddress.inetSocketAddress(proxyOptions.getPort(), proxyOptions.getHost()),
+          host, port, relativeURI, vertx);
     } else {
-      req = new HttpClientRequestImpl(this, useSSL, method, host, port, relativeURI, vertx);
+      if (server == null) {
+        server = SocketAddress.inetSocketAddress(port, host);
+      }
+      req = new HttpClientRequestImpl(this, useSSL, method, server, host, port, relativeURI, vertx);
     }
     if (headers != null) {
       req.headers().setAll(headers);
diff --git a/src/main/java/io/vertx/core/http/impl/HttpClientRequestBase.java b/src/main/java/io/vertx/core/http/impl/HttpClientRequestBase.java
--- a/src/main/java/io/vertx/core/http/impl/HttpClientRequestBase.java
+++ b/src/main/java/io/vertx/core/http/impl/HttpClientRequestBase.java
@@ -16,6 +16,7 @@
 import io.vertx.core.http.HttpClientRequest;
 import io.vertx.core.http.HttpClientResponse;
 import io.vertx.core.http.HttpMethod;
+import io.vertx.core.net.SocketAddress;
 import io.vertx.core.logging.Logger;
 import io.vertx.core.logging.LoggerFactory;
 import io.vertx.core.streams.ReadStream;
@@ -33,9 +34,10 @@ public abstract class HttpClientRequestBase implements HttpClientRequest {
   protected final io.vertx.core.http.HttpMethod method;
   protected final String uri;
   protected final String path;
+  protected final String query;
   protected final String host;
   protected final int port;
-  protected final String query;
+  protected final SocketAddress server;
   protected final boolean ssl;
   private Handler<Throwable> exceptionHandler;
   private long currentTimeoutTimerId = -1;
@@ -46,10 +48,11 @@ public abstract class HttpClientRequestBase implements HttpClientRequest {
   private boolean paused;
   private HttpClientResponseImpl response;
 
-  HttpClientRequestBase(HttpClientImpl client, boolean ssl, HttpMethod method, String host, int port, String uri) {
+  HttpClientRequestBase(HttpClientImpl client, boolean ssl, HttpMethod method, SocketAddress server, String host, int port, String uri) {
     this.client = client;
     this.uri = uri;
     this.method = method;
+    this.server = server;
     this.host = host;
     this.port = port;
     this.path = uri.length() > 0 ? HttpUtils.parsePath(uri) : "";
@@ -94,7 +97,7 @@ public String uri() {
   }
 
   public String host() {
-    return host;
+    return server.host();
   }
 
   @Override
@@ -206,7 +209,7 @@ private void handleTimeout(long timeoutMs) {
   }
 
   private void timeout(long timeoutMs) {
-    String msg = "The timeout period of " + timeoutMs + "ms has been exceeded while executing " + method + " " + uri + " for host " + host;
+    String msg = "The timeout period of " + timeoutMs + "ms has been exceeded while executing " + method + " " + uri + " for server " + server;
     // Use a stack-less exception
     handleException(new TimeoutException(msg) {
       @Override
@@ -252,5 +255,5 @@ public synchronized HttpClientRequest fetch(long amount) {
     }
     return this;
   }
-  
+
 }
diff --git a/src/main/java/io/vertx/core/http/impl/HttpClientRequestImpl.java b/src/main/java/io/vertx/core/http/impl/HttpClientRequestImpl.java
--- a/src/main/java/io/vertx/core/http/impl/HttpClientRequestImpl.java
+++ b/src/main/java/io/vertx/core/http/impl/HttpClientRequestImpl.java
@@ -28,6 +28,7 @@
 import io.vertx.core.impl.VertxInternal;
 import io.vertx.core.logging.Logger;
 import io.vertx.core.logging.LoggerFactory;
+import io.vertx.core.net.SocketAddress;
 
 import java.util.Objects;
 
@@ -73,9 +74,10 @@ public class HttpClientRequestImpl extends HttpClientRequestBase implements Http
 
   // completed => drainHandler = null
 
-  HttpClientRequestImpl(HttpClientImpl client, boolean ssl, HttpMethod method, String host, int port,
+  HttpClientRequestImpl(HttpClientImpl client, boolean ssl, HttpMethod method, SocketAddress server,
+                        String host, int port,
                         String relativeURI, VertxInternal vertx) {
-    super(client, ssl, method, host, port, relativeURI);
+    super(client, ssl, method, server, host, port, relativeURI);
     this.chunked = false;
     this.vertx = vertx;
     this.priority = HttpUtils.DEFAULT_STREAM_PRIORITY;
@@ -448,16 +450,16 @@ private synchronized void connect(Handler<HttpVersion> headersHandler) {
         throw new IllegalStateException("You must provide a rawMethod when using an HttpMethod.OTHER method");
       }
 
-      String peerHost;
+      SocketAddress peerAddress;
       if (hostHeader != null) {
         int idx = hostHeader.lastIndexOf(':');
         if (idx != -1) {
-          peerHost = hostHeader.substring(0, idx);
+          peerAddress = SocketAddress.inetSocketAddress(Integer.parseInt(hostHeader.substring(idx + 1)), hostHeader.substring(0, idx));
         } else {
-          peerHost = hostHeader;
+          peerAddress = SocketAddress.inetSocketAddress(80, hostHeader);
         }
       } else {
-        peerHost = host;
+        peerAddress = SocketAddress.inetSocketAddress(port, host);
       }
 
       // Capture some stuff
@@ -478,11 +480,13 @@ private synchronized void connect(Handler<HttpVersion> headersHandler) {
       }
       ContextInternal connectCtx = vertx.getOrCreateContext();
 
+
+
       // We defer actual connection until the first part of body is written or end is called
       // This gives the user an opportunity to set an exception handler before connecting so
       // they can capture any exceptions on connection
       connecting = true;
-      client.getConnectionForRequest(connectCtx, peerHost, ssl, port, host, ar1 -> {
+      client.getConnectionForRequest(connectCtx, peerAddress, ssl, server, ar1 -> {
         if (ar1.succeeded()) {
           HttpClientStream stream = ar1.result();
           ContextInternal ctx = (ContextInternal) stream.getContext();
diff --git a/src/main/java/io/vertx/core/http/impl/HttpClientRequestPushPromise.java b/src/main/java/io/vertx/core/http/impl/HttpClientRequestPushPromise.java
--- a/src/main/java/io/vertx/core/http/impl/HttpClientRequestPushPromise.java
+++ b/src/main/java/io/vertx/core/http/impl/HttpClientRequestPushPromise.java
@@ -17,6 +17,7 @@
 import io.vertx.core.MultiMap;
 import io.vertx.core.buffer.Buffer;
 import io.vertx.core.http.*;
+import io.vertx.core.net.SocketAddress;
 
 /**
  * @author <a href="mailto:julien@julienviet.com">Julien Viet</a>
@@ -40,7 +41,7 @@ public HttpClientRequestPushPromise(
       String host,
       int port,
       MultiMap headers) {
-    super(client, ssl, method, host, port, uri);
+    super(client, ssl, method, SocketAddress.inetSocketAddress(port, host), host, port, uri);
     this.conn = conn;
     this.stream = new Http2ClientConnection.Http2ClientStream(conn, this, stream, false);
     this.rawMethod = rawMethod;
@@ -117,7 +118,7 @@ public String uri() {
 
   @Override
   public String getHost() {
-    return host;
+    return server.host();
   }
 
   @Override
diff --git a/src/main/java/io/vertx/core/net/impl/ChannelProvider.java b/src/main/java/io/vertx/core/net/impl/ChannelProvider.java
--- a/src/main/java/io/vertx/core/net/impl/ChannelProvider.java
+++ b/src/main/java/io/vertx/core/net/impl/ChannelProvider.java
@@ -43,7 +43,6 @@ public final class ChannelProvider {
 
   private final Bootstrap bootstrap;
   private final SSLHelper sslHelper;
-  private final boolean ssl;
   private final ContextInternal context;
   private final ProxyOptions proxyOptions;
   private String applicationProtocol;
@@ -51,12 +50,10 @@ public final class ChannelProvider {
 
   public ChannelProvider(Bootstrap bootstrap,
                          SSLHelper sslHelper,
-                         boolean ssl,
                          ContextInternal context,
                          ProxyOptions proxyOptions) {
     this.bootstrap = bootstrap;
     this.context = context;
-    this.ssl = ssl;
     this.sslHelper = sslHelper;
     this.proxyOptions = proxyOptions;
   }
@@ -75,7 +72,7 @@ public Channel channel() {
     return channel;
   }
 
-  public void connect(SocketAddress remoteAddress, SocketAddress peerAddress, String serverName, Handler<AsyncResult<Channel>> channelHandler) {
+  public void connect(SocketAddress remoteAddress, SocketAddress peerAddress, String serverName, boolean ssl, Handler<AsyncResult<Channel>> channelHandler) {
     Handler<AsyncResult<Channel>> handler = res -> {
       if (Context.isOnEventLoopThread()) {
         channelHandler.handle(res);
@@ -85,13 +82,13 @@ public void connect(SocketAddress remoteAddress, SocketAddress peerAddress, Stri
       }
     };
     if (proxyOptions != null) {
-      handleProxyConnect(remoteAddress, peerAddress, serverName, handler);
+      handleProxyConnect(remoteAddress, peerAddress, serverName, ssl, handler);
     } else {
-      handleConnect(remoteAddress, peerAddress, serverName, handler);
+      handleConnect(remoteAddress, peerAddress, serverName, ssl, handler);
     }
   }
 
-  private void initSSL(SocketAddress peerAddress, String serverName, Channel ch, Handler<AsyncResult<Channel>> channelHandler) {
+  private void initSSL(SocketAddress peerAddress, String serverName, boolean ssl, Channel ch, Handler<AsyncResult<Channel>> channelHandler) {
     if (ssl) {
       SslHandler sslHandler = new SslHandler(sslHelper.createEngine(context.owner(), peerAddress, serverName));
       ChannelPipeline pipeline = ch.pipeline();
@@ -124,19 +121,19 @@ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
   }
 
 
-  private void handleConnect(SocketAddress remoteAddress, SocketAddress peerAddress, String serverName, Handler<AsyncResult<Channel>> channelHandler) {
+  private void handleConnect(SocketAddress remoteAddress, SocketAddress peerAddress, String serverName, boolean ssl, Handler<AsyncResult<Channel>> channelHandler) {
     VertxInternal vertx = context.owner();
     bootstrap.resolver(vertx.nettyAddressResolverGroup());
     bootstrap.handler(new ChannelInitializer<Channel>() {
       @Override
       protected void initChannel(Channel ch) {
-        initSSL(peerAddress, serverName, ch, channelHandler);
+        initSSL(peerAddress, serverName, ssl, ch, channelHandler);
       }
     });
     ChannelFuture fut = bootstrap.connect(vertx.transport().convert(remoteAddress, false));
     fut.addListener(res -> {
       if (res.isSuccess()) {
-        connected(fut.channel(), channelHandler);
+        connected(fut.channel(), ssl, channelHandler);
       } else {
         channelHandler.handle(io.vertx.core.Future.failedFuture(res.cause()));
       }
@@ -149,7 +146,7 @@ protected void initChannel(Channel ch) {
    * @param channel the channel
    * @param channelHandler the channel handler
    */
-  private void connected(Channel channel, Handler<AsyncResult<Channel>> channelHandler) {
+  private void connected(Channel channel, boolean ssl, Handler<AsyncResult<Channel>> channelHandler) {
     this.channel = channel;
     if (!ssl) {
       // No handshake
@@ -160,7 +157,7 @@ private void connected(Channel channel, Handler<AsyncResult<Channel>> channelHan
   /**
    * A channel provider that connects via a Proxy : HTTP or SOCKS
    */
-  private void handleProxyConnect(SocketAddress remoteAddress, SocketAddress peerAddress, String serverName, Handler<AsyncResult<Channel>> channelHandler) {
+  private void handleProxyConnect(SocketAddress remoteAddress, SocketAddress peerAddress, String serverName, boolean ssl, Handler<AsyncResult<Channel>> channelHandler) {
 
     final VertxInternal vertx = context.owner();
     final String proxyHost = proxyOptions.getHost();
@@ -206,8 +203,8 @@ public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {
                 if (evt instanceof ProxyConnectionEvent) {
                   pipeline.remove(proxy);
                   pipeline.remove(this);
-                  initSSL(peerAddress, serverName, ch, channelHandler);
-                  connected(ch, channelHandler);
+                  initSSL(peerAddress, serverName, ssl, ch, channelHandler);
+                  connected(ch, ssl, channelHandler);
                 }
                 ctx.fireUserEventTriggered(evt);
               }
diff --git a/src/main/java/io/vertx/core/net/impl/ConnectionBase.java b/src/main/java/io/vertx/core/net/impl/ConnectionBase.java
--- a/src/main/java/io/vertx/core/net/impl/ConnectionBase.java
+++ b/src/main/java/io/vertx/core/net/impl/ConnectionBase.java
@@ -414,22 +414,28 @@ public ChannelPromise channelFuture() {
   }
 
   public String remoteName() {
-    InetSocketAddress addr = (InetSocketAddress) chctx.channel().remoteAddress();
-    if (addr == null) return null;
-    // Use hostString that does not trigger a DNS resolution
-    return addr.getHostString();
+    java.net.SocketAddress addr = chctx.channel().remoteAddress();
+    if (addr instanceof InetSocketAddress) {
+      // Use hostString that does not trigger a DNS resolution
+      return ((InetSocketAddress)addr).getHostString();
+    }
+    return null;
   }
 
   public SocketAddress remoteAddress() {
-    InetSocketAddress addr = (InetSocketAddress) chctx.channel().remoteAddress();
-    if (addr == null) return null;
-    return new SocketAddressImpl(addr);
+    java.net.SocketAddress addr = chctx.channel().remoteAddress();
+    if (addr != null) {
+      return vertx.transport().convert(addr);
+    }
+    return null;
   }
 
   public SocketAddress localAddress() {
-    InetSocketAddress addr = (InetSocketAddress) chctx.channel().localAddress();
-    if (addr == null) return null;
-    return new SocketAddressImpl(addr);
+    java.net.SocketAddress addr = chctx.channel().localAddress();
+    if (addr != null) {
+      return vertx.transport().convert(addr);
+    }
+    return null;
   }
 
   public void handleMessage(Object msg) {
diff --git a/src/main/java/io/vertx/core/net/impl/NetClientImpl.java b/src/main/java/io/vertx/core/net/impl/NetClientImpl.java
--- a/src/main/java/io/vertx/core/net/impl/NetClientImpl.java
+++ b/src/main/java/io/vertx/core/net/impl/NetClientImpl.java
@@ -113,7 +113,7 @@ public synchronized NetClient connect(int port, String host, Handler<AsyncResult
 
   @Override
   public NetClient connect(int port, String host, String serverName, Handler<AsyncResult<NetSocket>> connectHandler) {
-    doConnect(SocketAddress.inetSocketAddress(port, host), serverName, connectHandler != null ? ar -> connectHandler.handle(ar.map(s -> (NetSocket) s)) : null);
+    doConnect(SocketAddress.inetSocketAddress(port, host), serverName, connectHandler);
     return this;
   }
 
@@ -180,7 +180,7 @@ protected void doConnect(SocketAddress remoteAddress, String serverName, Handler
 
     applyConnectionOptions(remoteAddress.path() != null, bootstrap);
 
-    ChannelProvider channelProvider = new ChannelProvider(bootstrap, sslHelper, sslHelper.isSSL(), context, options.getProxyOptions());
+    ChannelProvider channelProvider = new ChannelProvider(bootstrap, sslHelper, context, options.getProxyOptions());
 
     Handler<AsyncResult<Channel>> channelHandler = res -> {
       if (res.succeeded()) {
@@ -204,7 +204,7 @@ protected void doConnect(SocketAddress remoteAddress, String serverName, Handler
       }
     };
 
-    channelProvider.connect(remoteAddress, remoteAddress, serverName, channelHandler);
+    channelProvider.connect(remoteAddress, remoteAddress, serverName, sslHelper.isSSL(), channelHandler);
   }
 
   private void connected(ContextInternal context, Channel ch, Handler<AsyncResult<NetSocket>> connectHandler, SocketAddress remoteAddress) {
diff --git a/src/main/java/io/vertx/core/net/impl/transport/EpollTransport.java b/src/main/java/io/vertx/core/net/impl/transport/EpollTransport.java
--- a/src/main/java/io/vertx/core/net/impl/transport/EpollTransport.java
+++ b/src/main/java/io/vertx/core/net/impl/transport/EpollTransport.java
@@ -28,6 +28,7 @@
 import io.vertx.core.datagram.DatagramSocketOptions;
 import io.vertx.core.net.ClientOptionsBase;
 import io.vertx.core.net.NetServerOptions;
+import io.vertx.core.net.impl.SocketAddressImpl;
 
 import java.net.InetSocketAddress;
 import java.net.SocketAddress;
@@ -77,6 +78,14 @@ public SocketAddress convert(io.vertx.core.net.SocketAddress address, boolean re
     }
   }
 
+  @Override
+  public io.vertx.core.net.SocketAddress convert(SocketAddress address) {
+    if (address instanceof DomainSocketAddress) {
+      return new SocketAddressImpl(((DomainSocketAddress) address).path());
+    }
+    return super.convert(address);
+  }
+
   @Override
   public boolean isAvailable() {
     return Epoll.isAvailable();
diff --git a/src/main/java/io/vertx/core/net/impl/transport/KQueueTransport.java b/src/main/java/io/vertx/core/net/impl/transport/KQueueTransport.java
--- a/src/main/java/io/vertx/core/net/impl/transport/KQueueTransport.java
+++ b/src/main/java/io/vertx/core/net/impl/transport/KQueueTransport.java
@@ -22,6 +22,7 @@
 import io.netty.channel.unix.DomainSocketAddress;
 import io.vertx.core.datagram.DatagramSocketOptions;
 import io.vertx.core.net.NetServerOptions;
+import io.vertx.core.net.impl.SocketAddressImpl;
 
 import java.net.InetSocketAddress;
 import java.net.SocketAddress;
@@ -48,6 +49,14 @@ public SocketAddress convert(io.vertx.core.net.SocketAddress address, boolean re
     }
   }
 
+  @Override
+  public io.vertx.core.net.SocketAddress convert(SocketAddress address) {
+    if (address instanceof DomainSocketAddress) {
+      return new SocketAddressImpl(((DomainSocketAddress) address).path());
+    }
+    return super.convert(address);
+  }
+
   @Override
   public boolean isAvailable() {
     return KQueue.isAvailable();
diff --git a/src/main/java/io/vertx/core/net/impl/transport/Transport.java b/src/main/java/io/vertx/core/net/impl/transport/Transport.java
--- a/src/main/java/io/vertx/core/net/impl/transport/Transport.java
+++ b/src/main/java/io/vertx/core/net/impl/transport/Transport.java
@@ -24,6 +24,7 @@
 import io.vertx.core.net.ClientOptionsBase;
 import io.vertx.core.net.NetServerOptions;
 import io.vertx.core.net.impl.PartialPooledByteBufAllocator;
+import io.vertx.core.net.impl.SocketAddressImpl;
 
 import java.net.InetSocketAddress;
 import java.net.NetworkInterface;
@@ -114,6 +115,14 @@ public SocketAddress convert(io.vertx.core.net.SocketAddress address, boolean re
     }
   }
 
+  public io.vertx.core.net.SocketAddress convert(SocketAddress address) {
+    if (address instanceof InetSocketAddress) {
+      return new SocketAddressImpl((InetSocketAddress) address);
+    } else {
+      return null;
+    }
+  }
+
   /**
    * Return a channel option for given {@code name} or null if that options does not exist
    * for this transport.


Test patch:
diff --git a/src/test/java/io/vertx/core/http/Http1xProxyTest.java b/src/test/java/io/vertx/core/http/Http1xProxyTest.java
new file mode 100644
--- /dev/null
+++ b/src/test/java/io/vertx/core/http/Http1xProxyTest.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2011-2017 Contributors to the Eclipse Foundation
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ * which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ */
+package io.vertx.core.http;
+
+import io.vertx.core.net.ProxyOptions;
+import io.vertx.core.net.ProxyType;
+import org.junit.Test;
+
+public class Http1xProxyTest extends HttpTestBase {
+
+  @Test
+  public void testHttpProxyRequest() throws Exception {
+    startProxy(null, ProxyType.HTTP);
+    client = vertx.createHttpClient(new HttpClientOptions()
+      .setProxyOptions(new ProxyOptions().setType(ProxyType.HTTP).setHost("localhost").setPort(proxy.getPort())));
+    testHttpProxyRequest2(client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/"));
+  }
+
+  @Test
+  public void testHttpProxyRequestOverrideClientSsl() throws Exception {
+    startProxy(null, ProxyType.HTTP);
+    client = vertx.createHttpClient(new HttpClientOptions()
+      .setSsl(true).setProxyOptions(new ProxyOptions().setType(ProxyType.HTTP).setHost("localhost").setPort(proxy.getPort())));
+    testHttpProxyRequest2(client.get(new RequestOptions().setSsl(false).setHost("localhost").setPort(8080)));
+  }
+
+  private void testHttpProxyRequest2(HttpClientRequest clientReq) throws Exception {
+    server.requestHandler(req -> {
+      req.response().end();
+    });
+
+    server.listen(onSuccess(s -> {
+      clientReq.handler(resp -> {
+        assertEquals(200, resp.statusCode());
+        assertNotNull("request did not go through proxy", proxy.getLastUri());
+        assertEquals("Host header doesn't contain target host", "localhost:8080", proxy.getLastRequestHeaders().get("Host"));
+        testComplete();
+      });
+      clientReq.exceptionHandler(this::fail);
+      clientReq.end();
+    }));
+    await();
+  }
+
+  @Test
+  public void testHttpProxyRequestAuth() throws Exception {
+    startProxy("user", ProxyType.HTTP);
+
+    client = vertx.createHttpClient(new HttpClientOptions()
+      .setProxyOptions(new ProxyOptions().setType(ProxyType.HTTP).setHost("localhost").setPort(proxy.getPort())
+        .setUsername("user").setPassword("user")));
+
+    server.requestHandler(req -> {
+      req.response().end();
+    });
+
+    server.listen(onSuccess(s -> {
+      client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", resp -> {
+        assertEquals(200, resp.statusCode());
+        assertNotNull("request did not go through proxy", proxy.getLastUri());
+        assertEquals("Host header doesn't contain target host", "localhost:8080", proxy.getLastRequestHeaders().get("Host"));
+        testComplete();
+      }).exceptionHandler(th -> fail(th)).end();
+    }));
+    await();
+  }
+
+  @Test
+  public void testHttpProxyFtpRequest() throws Exception {
+    startProxy(null, ProxyType.HTTP);
+    client = vertx.createHttpClient(new HttpClientOptions()
+      .setProxyOptions(new ProxyOptions().setType(ProxyType.HTTP).setHost("localhost").setPort(proxy.getPort())));
+    final String url = "ftp://ftp.gnu.org/gnu/";
+    proxy.setForceUri("http://localhost:8080/");
+    HttpClientRequest clientReq = client.getAbs(url);
+    server.requestHandler(req -> {
+      req.response().end();
+    });
+
+    server.listen(onSuccess(s -> {
+      clientReq.handler(resp -> {
+        assertEquals(200, resp.statusCode());
+        assertEquals("request did sent the expected url", url, proxy.getLastUri());
+        testComplete();
+      });
+      clientReq.exceptionHandler(this::fail);
+      clientReq.end();
+    }));
+    await();
+  }
+
+  @Test
+  public void testHttpSocksProxyRequest() throws Exception {
+    startProxy(null, ProxyType.SOCKS5);
+
+    client = vertx.createHttpClient(new HttpClientOptions()
+      .setProxyOptions(new ProxyOptions().setType(ProxyType.SOCKS5).setHost("localhost").setPort(proxy.getPort())));
+
+    server.requestHandler(req -> {
+      req.response().end();
+    });
+
+    server.listen(onSuccess(s -> {
+      client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", resp -> {
+        assertEquals(200, resp.statusCode());
+        assertNotNull("request did not go through proxy", proxy.getLastUri());
+        testComplete();
+      }).exceptionHandler(th -> fail(th)).end();
+    }));
+    await();
+  }
+
+  @Test
+  public void testHttpSocksProxyRequestAuth() throws Exception {
+    startProxy("user", ProxyType.SOCKS5);
+
+    client = vertx.createHttpClient(new HttpClientOptions()
+      .setProxyOptions(new ProxyOptions().setType(ProxyType.SOCKS5).setHost("localhost").setPort(proxy.getPort())
+        .setUsername("user").setPassword("user")));
+
+    server.requestHandler(req -> {
+      req.response().end();
+    });
+
+    server.listen(onSuccess(s -> {
+      client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", resp -> {
+        assertEquals(200, resp.statusCode());
+        assertNotNull("request did not go through proxy", proxy.getLastUri());
+        testComplete();
+      }).exceptionHandler(th -> fail(th)).end();
+    }));
+    await();
+  }
+}
diff --git a/src/test/java/io/vertx/core/http/Http1xTLSTest.java b/src/test/java/io/vertx/core/http/Http1xTLSTest.java
--- a/src/test/java/io/vertx/core/http/Http1xTLSTest.java
+++ b/src/test/java/io/vertx/core/http/Http1xTLSTest.java
@@ -130,7 +130,7 @@ public void testRedirectFromSSL() throws Exception {
       req.response().setStatusCode(303).putHeader("location", "http://" + DEFAULT_HTTP_HOST + ":4043/" + DEFAULT_TEST_URI).end();
     });
     startServer(redirectServer);
-    RequestOptions options = new RequestOptions().setHost(DEFAULT_HTTP_HOST).setURI(DEFAULT_TEST_URI).setPort(4043);
+    RequestOptions options = new RequestOptions().setHost(DEFAULT_HTTP_HOST).setURI(DEFAULT_TEST_URI).setPort(4043).setSsl(false);
     testTLS(Cert.NONE, Trust.SERVER_JKS, Cert.NONE, Trust.NONE)
         .clientSSL(true)
         .serverSSL(false)
diff --git a/src/test/java/io/vertx/core/http/Http1xTest.java b/src/test/java/io/vertx/core/http/Http1xTest.java
--- a/src/test/java/io/vertx/core/http/Http1xTest.java
+++ b/src/test/java/io/vertx/core/http/Http1xTest.java
@@ -28,6 +28,7 @@
 import io.vertx.test.core.CheckingSender;
 import io.vertx.test.verticles.SimpleServer;
 import io.vertx.test.core.TestUtils;
+import org.junit.Assume;
 import org.junit.Test;
 
 import java.io.File;
@@ -46,7 +47,6 @@
 import static io.vertx.test.core.TestUtils.*;
 
 /**
- *
  * @author <a href="http://tfox.org">Tim Fox</a>
  * @author <a href="mailto:nscavell@redhat.com">Nick Scavelli</a>
  */
@@ -1105,6 +1105,7 @@ public void testCloseHandlerNotCalledWhenConnectionClosedAfterEnd() throws Excep
 
   @Test
   public void testTimedOutWaiterDoesntConnect() throws Exception {
+    Assume.assumeTrue("Domain socket don't pass this test", testAddress.path() == null);
     long responseDelay = 300;
     int requests = 6;
     client.close();
@@ -1113,10 +1114,10 @@ public void testTimedOutWaiterDoesntConnect() throws Exception {
     // Make sure server is closed before continuing
     awaitLatch(firstCloseLatch);
 
-    client = vertx.createHttpClient(new HttpClientOptions().setKeepAlive(false).setMaxPoolSize(1));
+    client = vertx.createHttpClient(createBaseClientOptions().setKeepAlive(false).setMaxPoolSize(1));
     AtomicInteger requestCount = new AtomicInteger(0);
     // We need a net server because we need to intercept the socket connection, not just full http requests
-    NetServer server = vertx.createNetServer(new NetServerOptions().setHost(DEFAULT_HTTP_HOST).setPort(DEFAULT_HTTP_PORT));
+    NetServer server = vertx.createNetServer();
     server.connectHandler(socket -> {
       Buffer content = Buffer.buffer();
       AtomicBoolean closed = new AtomicBoolean();
@@ -1137,14 +1138,20 @@ public void testTimedOutWaiterDoesntConnect() throws Exception {
 
     CountDownLatch latch = new CountDownLatch(requests);
 
-    server.listen(onSuccess(s -> {
+    server.listen(testAddress, onSuccess(s -> {
       for(int count = 0; count < requests; count++) {
 
+        RequestOptions reqOptions = new RequestOptions()
+          .setPort(DEFAULT_HTTP_PORT)
+          .setHost(DEFAULT_HTTP_HOST)
+          .setURI(DEFAULT_TEST_URI);
+
         HttpClientRequest req = client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI);
         if (count % 2 == 0) {
           req.handler(resp -> {
             resp.bodyHandler(buff -> {
               assertEquals("OK", buff.toString());
+              System.out.println("got resp");
               latch.countDown();
             });
           });
@@ -1174,7 +1181,7 @@ public void testTimedOutWaiterDoesntConnect() throws Exception {
   @Test
   public void testPipeliningOrder() throws Exception {
     client.close();
-    client = vertx.createHttpClient(new HttpClientOptions().setKeepAlive(true).setPipelining(true).setMaxPoolSize(1));
+    client = vertx.createHttpClient(createBaseClientOptions().setKeepAlive(true).setPipelining(true).setMaxPoolSize(1));
     int requests = 100;
 
     AtomicInteger reqCount = new AtomicInteger(0);
@@ -1198,11 +1205,11 @@ public void testPipeliningOrder() throws Exception {
 
     CountDownLatch latch = new CountDownLatch(requests);
 
-    server.listen(onSuccess(s -> {
+    server.listen(testAddress, onSuccess(s -> {
       vertx.setTimer(500, id -> {
         for (int count = 0; count < requests; count++) {
           int theCount = count;
-          HttpClientRequest req = client.request(HttpMethod.POST, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+          HttpClientRequest req = client.request(HttpMethod.POST, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
             assertEquals(theCount, Integer.parseInt(resp.headers().get("count")));
             resp.bodyHandler(buff -> {
               assertEquals("This is content " + theCount, buff.toString());
@@ -1256,19 +1263,19 @@ public void testPipeliningLimit() throws Exception {
       });
     });
     CountDownLatch listenLatch = new CountDownLatch(1);
-    server.listen(onSuccess(v -> {
+    server.listen(testAddress, onSuccess(v -> {
       listenLatch.countDown();
     }));
     awaitLatch(listenLatch);
 
     AtomicInteger responses = new AtomicInteger();
     for (int i = 0;i < requests;i++) {
-      client.getNow(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> {
+      client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> {
         assertEquals(200, resp.statusCode());
         if (responses.incrementAndGet() == requests) {
           testComplete();
         }
-      });
+      }).end();
     }
     await();
   }
@@ -1282,12 +1289,12 @@ public void testCloseServerConnectionWithPendingMessages() throws Exception {
         req.response().close();
       });
     });
-    startServer();
+    startServer(testAddress);
     client.close();
-    client = vertx.createHttpClient(new HttpClientOptions().setMaxPoolSize(n).setPipelining(true));
+    client = vertx.createHttpClient(createBaseClientOptions().setMaxPoolSize(n).setPipelining(true));
     AtomicBoolean completed = new AtomicBoolean();
     for (int i = 0;i < n * 2;i++) {
-      client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+      client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
         fail();
       }).connectionHandler(conn -> {
         conn.closeHandler(v -> {
@@ -1316,7 +1323,7 @@ public void testPipeliningFailure() throws Exception {
         req.response().end();
       }
     });
-    startServer();
+    startServer(testAddress);
     AtomicInteger succeeded = new AtomicInteger();
     List<HttpClientRequest> requests = new CopyOnWriteArrayList<>();
     Consumer<HttpClientRequest> checkEnd = req -> {
@@ -1327,14 +1334,15 @@ public void testPipeliningFailure() throws Exception {
       }
     };
     for (int i = 0;i < n * 2;i++) {
-      HttpClientRequest req = client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/" + i);
-      req.handler(resp -> {
+      AtomicReference<HttpClientRequest> ref = new AtomicReference<>();
+      HttpClientRequest req = client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/" + i, resp -> {
         succeeded.incrementAndGet();
-        checkEnd.accept(req);
+        checkEnd.accept(ref.get());
       });
       req.exceptionHandler(err -> {
         checkEnd.accept(req);
       }).end();
+      ref.set(req);
       requests.add(req);
     }
     closeFuture.complete(null);
@@ -1359,10 +1367,10 @@ public void testPipeliningPauseRequest() throws Exception {
         req.resume();
       });
     });
-    startServer();
+    startServer(testAddress);
     AtomicInteger remaining = new AtomicInteger(n);
     for (int i = 0;i < n;i++) {
-      HttpClientRequest req = client.put(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+      HttpClientRequest req = client.request(HttpMethod.PUT, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
         resp.endHandler(v -> {
           if (remaining.decrementAndGet() == 0) {
             testComplete();
@@ -1392,13 +1400,13 @@ public void testServerPipeliningConnectionConcurrency() throws Exception {
         }
       });
     });
-    startServer();
+    startServer(testAddress);
     Buffer requests = Buffer.buffer();
     for (int i = 0;i < n;i++) {
       requests.appendString("GET " + DEFAULT_TEST_URI + " HTTP/1.1\r\n\r\n");
     }
     NetClient client = vertx.createNetClient();
-    client.connect(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, onSuccess(so -> {
+    client.connect(testAddress, onSuccess(so -> {
       so.closeHandler(v -> testComplete());
       so.write(requests);
     }));
@@ -1422,7 +1430,7 @@ private void testKeepAlive(boolean keepAlive, int poolSize, int numServers, int
     // Make sure server is closed before continuing
     awaitLatch(firstCloseLatch);
 
-    client = vertx.createHttpClient(new HttpClientOptions().setKeepAlive(keepAlive).setPipelining(false).setMaxPoolSize(poolSize));
+    client = vertx.createHttpClient(createBaseClientOptions().setKeepAlive(keepAlive).setPipelining(false).setMaxPoolSize(poolSize));
     int requests = 100;
 
     // Start the servers
@@ -1435,10 +1443,9 @@ private void testKeepAlive(boolean keepAlive, int poolSize, int numServers, int
         connectedServers.add(server);
         req.response().end();
       });
-      server.listen(ar -> {
-        assertTrue(ar.succeeded());
+      server.listen(testAddress, onSuccess(s -> {
         startServerLatch.countDown();
-      });
+      }));
       servers[i] = server;
     }
 
@@ -1451,7 +1458,7 @@ private void testKeepAlive(boolean keepAlive, int poolSize, int numServers, int
     // number of total connections being > pool size (which is correct)
     vertx.runOnContext(v -> {
       for (int count = 0; count < requests; count++) {
-        client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+        client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
           assertEquals(200, resp.statusCode());
           reqLatch.countDown();
         }).end();
@@ -1465,10 +1472,9 @@ private void testKeepAlive(boolean keepAlive, int poolSize, int numServers, int
 
     CountDownLatch serverCloseLatch = new CountDownLatch(numServers);
     for (HttpServer server: servers) {
-      server.close(ar -> {
-        assertTrue(ar.succeeded());
+      server.close(onSuccess(s -> {
         serverCloseLatch.countDown();
-      });
+      }));
     }
 
     awaitLatch(serverCloseLatch);
@@ -1494,7 +1500,11 @@ private void testPooling(boolean keepAlive, boolean pipelining) {
     int numGets = 100;
     int maxPoolSize = 10;
     client.close();
-    client = vertx.createHttpClient(new HttpClientOptions().setKeepAlive(keepAlive).setPipelining(pipelining).setMaxPoolSize(maxPoolSize));
+    client = vertx.createHttpClient(createBaseClientOptions()
+      .setKeepAlive(keepAlive)
+      .setPipelining(pipelining)
+      .setMaxPoolSize(maxPoolSize)
+    );
 
     server.requestHandler(req -> {
       String cnt = req.headers().get("count");
@@ -1502,14 +1512,13 @@ private void testPooling(boolean keepAlive, boolean pipelining) {
       req.response().end();
     });
 
-    AtomicBoolean completeAlready = new AtomicBoolean();
-
-    server.listen(onSuccess(s -> {
+    server.listen(testAddress, onSuccess(s -> {
 
       AtomicInteger cnt = new AtomicInteger(0);
       for (int i = 0; i < numGets; i++) {
         int theCount = i;
-        HttpClientRequest req = client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, path, resp -> {
+        HttpClientRequest req = client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, path, resp -> {
+          resp.exceptionHandler(this::fail);
           assertEquals(200, resp.statusCode());
           assertEquals(theCount, Integer.parseInt(resp.headers().get("count")));
           if (cnt.incrementAndGet() == numGets) {
@@ -1540,7 +1549,7 @@ public void testPoolingNoKeepAliveAndPipelining() {
   public void testMaxWaitQueueSizeIsRespected() throws Exception {
     client.close();
 
-    client = vertx.createHttpClient(new HttpClientOptions().setDefaultHost(DEFAULT_HTTP_HOST).setDefaultPort(DEFAULT_HTTP_PORT)
+    client = vertx.createHttpClient(createBaseClientOptions().setDefaultHost(DEFAULT_HTTP_HOST).setDefaultPort(DEFAULT_HTTP_PORT)
         .setPipelining(false).setMaxWaitQueueSize(0).setMaxPoolSize(2));
 
     waitFor(3);
@@ -1551,17 +1560,17 @@ public void testMaxWaitQueueSizeIsRespected() throws Exception {
       complete();
     });
 
-    startServer();
+    startServer(testAddress);
 
-    HttpClientRequest req1 = client.get("/1", resp -> {
+    HttpClientRequest req1 = client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/1", resp -> {
       fail("Should not be called.");
     });
 
-    HttpClientRequest req2 = client.get("/2", resp -> {
+    HttpClientRequest req2 = client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/2", resp -> {
       fail("Should not be called.");
     });
 
-    HttpClientRequest req3 = client.get("/3", resp -> {
+    HttpClientRequest req3 = client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/3", resp -> {
       fail("Should not be called.");
     });
     req3.exceptionHandler(t -> {
@@ -1595,8 +1604,8 @@ public void testRequestTimeoutExtendedWhenResponseChunksReceived() {
       });
     });
 
-    server.listen(onSuccess(s -> {
-      HttpClientRequest req = client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    server.listen(testAddress, onSuccess(s -> {
+      HttpClientRequest req = client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
         assertEquals(200, resp.statusCode());
         resp.endHandler(v -> testComplete());
       });
@@ -1611,7 +1620,7 @@ public void testRequestTimeoutExtendedWhenResponseChunksReceived() {
   @Test
   public void testServerWebsocketIdleTimeout() {
     server.close();
-    server = vertx.createHttpServer(new HttpServerOptions().setIdleTimeout(1).setPort(DEFAULT_HTTP_PORT).setHost(DEFAULT_HTTP_HOST));
+    server = vertx.createHttpServer(createBaseServerOptions().setIdleTimeout(1).setPort(DEFAULT_HTTP_PORT).setHost(DEFAULT_HTTP_HOST));
     server.websocketHandler(ws -> {}).listen(ar -> {
       assertTrue(ar.succeeded());
       client.websocket(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", ws -> {
@@ -1640,7 +1649,7 @@ public void testClientWebsocketIdleTimeout() {
   public void testSharedServersRoundRobin() throws Exception {
     client.close();
     server.close();
-    client = vertx.createHttpClient(new HttpClientOptions().setKeepAlive(false));
+    client = vertx.createHttpClient(createBaseClientOptions().setKeepAlive(false));
     int numServers = VertxOptions.DEFAULT_EVENT_LOOP_POOL_SIZE / 2- 1;
     int numRequests = numServers * 100;
 
@@ -1670,9 +1679,11 @@ public void testSharedServersRoundRobin() throws Exception {
         requestCount.put(theServer, icnt);
         latchConns.countDown();
         req.response().end();
-      }).listen(onSuccess(s -> {
+      }).listen(testAddress, onSuccess(s -> {
+        if (s.actualPort() > 0) {
           assertEquals(DEFAULT_HTTP_PORT, s.actualPort());
-          latchListen.countDown();
+        }
+        latchListen.countDown();
       }));
     }
     awaitLatch(latchListen);
@@ -1681,7 +1692,7 @@ public void testSharedServersRoundRobin() throws Exception {
     // Create a bunch of connections
     CountDownLatch latchClient = new CountDownLatch(numRequests);
     for (int i = 0; i < numRequests; i++) {
-      client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, res -> latchClient.countDown()).end();
+      client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, res -> latchClient.countDown()).end();
     }
 
     assertTrue(latchClient.await(10, TimeUnit.SECONDS));
@@ -1766,8 +1777,8 @@ public void testIncorrectHttpVersion() throws Exception {
       so.write(Buffer.buffer("HTTP/1.2 200 OK\r\nContent-Length:5\r\n\r\nHELLO"));
       so.close();
     });
-    startServer();
-    HttpClientRequest req = client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> fail("Should not be called"));
+    startServer(testAddress);
+    HttpClientRequest req = client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> fail("Should not be called"));
     AtomicBoolean a = new AtomicBoolean();
     req.exceptionHandler(err -> {
       if (a.compareAndSet(false, true)) {
@@ -1817,9 +1828,9 @@ public void testHttp11NonPersistentConnectionClosed() throws Exception {
       assertTrue(req.response().closed());
     });
 
-    server.listen(onSuccess(s -> {
-      client = vertx.createHttpClient(new HttpClientOptions().setProtocolVersion(HttpVersion.HTTP_1_1).setKeepAlive(false));
-      HttpClientRequest req = client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    server.listen(testAddress, onSuccess(s -> {
+      client = vertx.createHttpClient(createBaseClientOptions().setProtocolVersion(HttpVersion.HTTP_1_1).setKeepAlive(false));
+      HttpClientRequest req = client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
         resp.endHandler(v -> {
           assertEquals(resp.getHeader("Connection"), "close");
           testComplete();
@@ -1842,9 +1853,9 @@ public void testHttp10KeepAliveConnectionNotClosed() throws Exception {
       assertFalse(req.response().closed());
     });
 
-    server.listen(onSuccess(s -> {
-      client = vertx.createHttpClient(new HttpClientOptions().setProtocolVersion(HttpVersion.HTTP_1_0).setKeepAlive(true));
-      HttpClientRequest req = client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    server.listen(testAddress, onSuccess(s -> {
+      client = vertx.createHttpClient(createBaseClientOptions().setProtocolVersion(HttpVersion.HTTP_1_0).setKeepAlive(true));
+      HttpClientRequest req = client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
         resp.endHandler(v -> {
           assertEquals(resp.getHeader("Connection"), "keep-alive");
           assertEquals(resp.getHeader("Content-Length"), "0");
@@ -1868,9 +1879,9 @@ public void testHttp10RequestNonKeepAliveConnectionClosed() throws Exception {
       assertTrue(req.response().closed());
     });
 
-    server.listen(onSuccess(s -> {
-      client = vertx.createHttpClient(new HttpClientOptions().setProtocolVersion(HttpVersion.HTTP_1_0).setKeepAlive(false));
-      HttpClientRequest req = client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    server.listen(testAddress, onSuccess(s -> {
+      client = vertx.createHttpClient(createBaseClientOptions().setProtocolVersion(HttpVersion.HTTP_1_0).setKeepAlive(false));
+      HttpClientRequest req = client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
         resp.endHandler(v -> {
           assertNull(resp.getHeader("Connection"));
           testComplete();
@@ -1900,11 +1911,11 @@ public void testHttp10ResponseNonKeepAliveConnectionClosed() throws Exception {
         }
       });
     });
-    server.listen(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, onSuccess(v1 -> {
+    server.listen(testAddress, onSuccess(v1 -> {
       client.close();
-      client = vertx.createHttpClient(new HttpClientOptions().setKeepAlive(true).setMaxPoolSize(1));
+      client = vertx.createHttpClient(createBaseClientOptions().setKeepAlive(true).setMaxPoolSize(1));
       for (int i = 0;i < 3;i++) {
-        client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", resp -> {
+        client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", resp -> {
           resp.endHandler(v2 -> {
             complete();
           });
@@ -1934,8 +1945,8 @@ public void testAccessNetSocket() throws Exception {
       });
     });
 
-    server.listen(onSuccess(s -> {
-      HttpClientRequest req = client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    server.listen(testAddress, onSuccess(s -> {
+      HttpClientRequest req = client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
         resp.endHandler(v -> {
           assertNotNull(resp.netSocket());
           testComplete();
@@ -1963,10 +1974,10 @@ public void testRequestsTimeoutInQueue() {
     client.close();
     client = vertx.createHttpClient(new HttpClientOptions().setKeepAlive(false).setMaxPoolSize(1));
 
-    server.listen(onSuccess(s -> {
+    server.listen(testAddress, onSuccess(s -> {
       // Add a few requests that should all timeout
       for (int i = 0; i < 5; i++) {
-        HttpClientRequest req = client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+        HttpClientRequest req = client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
           fail("Should not be called");
         });
         AtomicBoolean failed = new AtomicBoolean();
@@ -1979,7 +1990,7 @@ public void testRequestsTimeoutInQueue() {
         req.end();
       }
       // Now another request that should not timeout
-      HttpClientRequest req = client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+      HttpClientRequest req = client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
         assertEquals(200, resp.statusCode());
         testComplete();
       });
@@ -2034,14 +2045,14 @@ public void testClientOptionsCopiedBeforeUse() {
   @Test
   public void testClientContextWithKeepAlive() throws Exception {
     client.close();
-    client = vertx.createHttpClient(new HttpClientOptions().setKeepAlive(true).setPipelining(false).setMaxPoolSize(1));
+    client = vertx.createHttpClient(createBaseClientOptions().setKeepAlive(true).setPipelining(false).setMaxPoolSize(1));
     testClientContext();
   }
 
   @Test
   public void testClientContextWithPipelining() throws Exception {
     client.close();
-    client = vertx.createHttpClient(new HttpClientOptions().setKeepAlive(true).setPipelining(true).setMaxPoolSize(1));
+    client = vertx.createHttpClient(createBaseClientOptions().setKeepAlive(true).setPipelining(true).setMaxPoolSize(1));
     testClientContext();
   }
 
@@ -2049,21 +2060,21 @@ private void testClientContext() throws Exception {
     server.requestHandler(req -> {
       req.response().end();
     });
-    startServer();
+    startServer(testAddress);
     Set<Context> contexts = Collections.synchronizedSet(new HashSet<>());
     Set<HttpConnection> connections = Collections.synchronizedSet(new HashSet<>());
     Handler<HttpClientResponse> checker = response -> {
       contexts.add(Vertx.currentContext());
       connections.add(response.request().connection());
     };
-    HttpClientRequest req1 = client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/2");
+    HttpClientRequest req1 = client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/2");
     req1.handler(checker).exceptionHandler(this::fail);
-    HttpClientRequest req2 = client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/3");
+    HttpClientRequest req2 = client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/3");
     req2.handler(checker).exceptionHandler(this::fail);
     CompletableFuture<HttpClientRequest> fut = new CompletableFuture<>();
     Context ctx = vertx.getOrCreateContext();
     ctx.runOnContext(v -> {
-      HttpClientRequest req3 = client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/4");
+      HttpClientRequest req3 = client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/4");
       req3.handler(resp -> {
         // This should warn in the log (console) as we are called back on the connection context
         // and not on the context doing the request
@@ -2100,11 +2111,10 @@ public void testContexts() throws Exception {
     });
     CountDownLatch latch = new CountDownLatch(1);
     AtomicReference<ContextInternal> listenContext = new AtomicReference<>();
-    server.listen(ar -> {
-      assertTrue(ar.succeeded());
+    server.listen(testAddress, onSuccess(s -> {
       listenContext.set(((VertxInternal) vertx).getContext());
       latch.countDown();
-    });
+    }));
     awaitLatch(latch);
     CountDownLatch latch2 = new CountDownLatch(1);
     int numReqs = 16;
@@ -2113,7 +2123,7 @@ public void testContexts() throws Exception {
     client.close();
     client = vertx.createHttpClient(new HttpClientOptions().setMaxPoolSize(numConns));
     for (int i = 0; i < numReqs; i++) {
-      client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", resp -> {
+      client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", resp -> {
         assertEquals(200, resp.statusCode());
         contexts.add(((VertxInternal) vertx).getContext());
         if (cnt.incrementAndGet() == numReqs) {
@@ -2126,15 +2136,14 @@ public void testContexts() throws Exception {
     }
     awaitLatch(latch2);
     // Close should be in own context
-    server.close(ar -> {
-      assertTrue(ar.succeeded());
+    server.close(onSuccess(v -> {
       ContextInternal closeContext = ((VertxInternal) vertx).getContext();
       assertFalse(contexts.contains(closeContext));
       assertNotSame(serverRequestContext.get(), closeContext);
       assertFalse(contexts.contains(listenContext.get()));
       assertSame(serverRequestContext.get(), listenContext.get());
       testComplete();
-    });
+    }));
 
     server = null;
     await();
@@ -2145,8 +2154,8 @@ public void testRequestHandlerNotCalledInvalidRequest() {
     server.requestHandler(req -> {
       fail();
     });
-    server.listen(onSuccess(s -> {
-      vertx.createNetClient(new NetClientOptions()).connect(8080, "127.0.0.1", onSuccess(socket -> {
+    server.listen(testAddress, onSuccess(s -> {
+      vertx.createNetClient(new NetClientOptions()).connect(testAddress, onSuccess(socket -> {
         socket.closeHandler(r -> {
           testComplete();
         });
@@ -2174,9 +2183,8 @@ public void testInWorker() throws Exception {
       public void start() throws Exception {
         assertTrue(Vertx.currentContext().isWorkerContext());
         assertTrue(Context.isOnWorkerThread());
-        HttpServer server1 = vertx.createHttpServer(new HttpServerOptions()
-                .setHost(HttpTestBase.DEFAULT_HTTP_HOST).setPort(HttpTestBase.DEFAULT_HTTP_PORT));
-        server1.requestHandler(req -> {
+        HttpServer server = vertx.createHttpServer();
+        server.requestHandler(req -> {
           assertTrue(Vertx.currentContext().isWorkerContext());
           assertTrue(Context.isOnWorkerThread());
           Buffer buf = Buffer.buffer();
@@ -2185,11 +2193,11 @@ public void start() throws Exception {
             assertEquals("hello", buf.toString());
             req.response().end("bye");
           });
-        }).listen(onSuccess(s -> {
+        }).listen(testAddress, onSuccess(s -> {
           assertTrue(Vertx.currentContext().isWorkerContext());
           assertTrue(Context.isOnWorkerThread());
           HttpClient client = vertx.createHttpClient();
-          client.put(HttpTestBase.DEFAULT_HTTP_PORT, HttpTestBase.DEFAULT_HTTP_HOST, "/blah", resp -> {
+          client.request(HttpMethod.PUT, testAddress, HttpTestBase.DEFAULT_HTTP_PORT, HttpTestBase.DEFAULT_HTTP_HOST, "/blah", resp -> {
             assertEquals(200, resp.statusCode());
             assertTrue(Vertx.currentContext().isWorkerContext());
             assertTrue(Context.isOnWorkerThread());
@@ -2223,30 +2231,29 @@ public void testPauseResumeClientResponse() {
       }
       request.response().end();
     });
-    server.listen(10000, onSuccess(hs -> {
+    server.listen(testAddress, onSuccess(hs -> {
       HttpClient httpClient = vertx.createHttpClient();
-      HttpClientRequest clientRequest = httpClient.get(10000, "localhost", "/");
-      clientRequest.handler(resp -> {
-        resp.handler(b -> {
-          readBuffer.appendBuffer(b);
-          for (int i = 0; i < 64; i++) {
-            vertx.setTimer(1, n -> {
-              try {
-                Thread.sleep(0);
-              } catch (InterruptedException e) {
-                e.printStackTrace();
-              }
+      HttpClientRequest clientRequest = httpClient.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI,
+        resp -> {
+          resp.handler(b -> {
+            readBuffer.appendBuffer(b);
+            for (int i = 0; i < 64; i++) {
+              vertx.setTimer(1, n -> {
+                try {
+                  Thread.sleep(0);
+                } catch (InterruptedException e) {
+                  e.printStackTrace();
+                }
+              });
+            }
+            resp.endHandler(v -> {
+              byte[] expectedData = buffer.getBytes();
+              byte[] actualData = readBuffer.getBytes();
+              assertTrue(Arrays.equals(expectedData, actualData));
+              testComplete();
             });
-          }
-          ;
-          resp.endHandler(v -> {
-            byte[] expectedData = buffer.getBytes();
-            byte[] actualData = readBuffer.getBytes();
-            assertTrue(Arrays.equals(expectedData, actualData));
-            testComplete();
           });
         });
-      });
       clientRequest.end();
     }));
     await();
@@ -2280,8 +2287,8 @@ public void testPauseResumeServerRequestFromAnotherThread() throws Exception {
         testComplete();
       });
     });
-    startServer();
-    HttpClientRequest req = client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTPS_HOST, "/", resp -> fail());
+    startServer(testAddress);
+    HttpClientRequest req = client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTPS_HOST, "/", resp -> fail());
     req.setChunked(true);
     for (int i = 0; i < buffer.length() / 8192; i++) {
       req.write(buffer.slice(i * 8192, (i + 1) * 8192));
@@ -2298,18 +2305,18 @@ public void testEndServerResponseResumeTheConnection() throws Exception {
         req.response().end();
       });
     });
-    startServer();
+    startServer(testAddress);
     client.close();
     waitFor(2);
     client = vertx.createHttpClient(new HttpClientOptions().setKeepAlive(true).setMaxPoolSize(1));
-    client.getNow(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
       assertEquals(200, resp.statusCode());
       complete();
-    });
-    client.getNow(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    }).end();
+    client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
       assertEquals(200, resp.statusCode());
       complete();
-    });
+    }).end();
     await();
   }
 
@@ -2321,15 +2328,15 @@ public void testEndServerRequestResumeTheConnection() throws Exception {
         req.pause();
       });
     });
-    startServer();
+    startServer(testAddress);
     client.close();
     waitFor(2);
-    client = vertx.createHttpClient(new HttpClientOptions().setKeepAlive(true).setMaxPoolSize(1));
-    client.put(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    client = vertx.createHttpClient(createBaseClientOptions().setKeepAlive(true).setMaxPoolSize(1));
+    client.request(HttpMethod.PUT, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
       assertEquals(200, resp.statusCode());
       complete();
     }).end("1");
-    client.put(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    client.request(HttpMethod.PUT, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
       assertEquals(200, resp.statusCode());
       complete();
     }).end("2");
@@ -2343,12 +2350,11 @@ public void testMultipleRecursiveCallsAndPipelining() throws Exception {
     server.requestHandler(x -> {
         x.response().end("hello");
       })
-      .listen(8080, r -> {
+      .listen(testAddress, r -> {
         if (r.succeeded()) {
-          HttpClient client = vertx.createHttpClient(new HttpClientOptions()
+          HttpClient client = vertx.createHttpClient(createBaseClientOptions()
               .setKeepAlive(true)
               .setPipelining(true)
-              .setDefaultPort(8080)
           );
           IntStream.range(0, 5).forEach(i -> recursiveCall(client, receivedRequests, sendRequests));
         }
@@ -2357,14 +2363,14 @@ public void testMultipleRecursiveCallsAndPipelining() throws Exception {
   }
 
   private void recursiveCall(HttpClient client, AtomicInteger receivedRequests, int sendRequests){
-    client.getNow("/", r -> {
+    client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTPS_HOST, DEFAULT_TEST_URI, r -> {
       int numRequests = receivedRequests.incrementAndGet();
       if (numRequests == sendRequests) {
         testComplete();
       } else if (numRequests < sendRequests) {
         recursiveCall(client, receivedRequests, sendRequests);
       }
-    });
+    }).end();
   }
 
   @Test
@@ -2386,23 +2392,21 @@ private void testUnsupported(String rawReq, boolean method) throws Exception {
           // OK
         }
       })
-      .listen(8080, r -> {
-        if (r.succeeded()) {
-          NetClient client = vertx.createNetClient();
-          // Send a raw request
-          client.connect(8080, "localhost", onSuccess(conn -> {
-            conn.write(rawReq);
-            Buffer respBuff = Buffer.buffer();
-            conn.handler(respBuff::appendBuffer);
-            conn.closeHandler(v -> {
-              // Server should automatically close it after sending back 501
-              assertTrue(respBuff.toString().contains("501 Not Implemented"));
-              client.close();
-              testComplete();
-            });
-          }));
-        }
-      });
+      .listen(testAddress, onSuccess(s -> {
+        NetClient client = vertx.createNetClient();
+        // Send a raw request
+        client.connect(testAddress, onSuccess(conn -> {
+          conn.write(rawReq);
+          Buffer respBuff = Buffer.buffer();
+          conn.handler(respBuff::appendBuffer);
+          conn.closeHandler(v -> {
+            // Server should automatically close it after sending back 501
+            assertTrue(respBuff.toString().contains("501 Not Implemented"));
+            client.close();
+            testComplete();
+          });
+        }));
+      }));
     await();
   }
 
@@ -2414,24 +2418,27 @@ public void testTwoServersDifferentEventLoopsCloseOne() throws Exception {
     server.requestHandler(req -> {
       server1Count.incrementAndGet();
       req.response().end();
-    }).listen(8080, onSuccess(s -> {
+    }).listen(testAddress, onSuccess(s -> {
       latch1.countDown();
     }));
     HttpServer server2 = vertx.createHttpServer().requestHandler(req -> {
       server2Count.incrementAndGet();
       req.response().end();
-    }).listen(8080, onSuccess(s -> {
+    }).listen(testAddress, onSuccess(s -> {
       latch1.countDown();
     }));
     awaitLatch(latch1);
-    HttpClient client = vertx.createHttpClient(new HttpClientOptions().setKeepAlive(false).setDefaultPort(8080));
 
+    HttpClient[] clients = new HttpClient[5];
+    for (int i = 0;i < 5;i++) {
+      clients[i] = vertx.createHttpClient(createBaseClientOptions());
+    }
     for (int i = 0; i < 2; i++) {
       CountDownLatch latch2 = new CountDownLatch(1);
-      client.getNow("/", resp -> {
+      clients[i].request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
         assertEquals(200, resp.statusCode());
         latch2.countDown();
-      });
+      }).end();
       awaitLatch(latch2);
     }
 
@@ -2444,10 +2451,10 @@ public void testTwoServersDifferentEventLoopsCloseOne() throws Exception {
     // Send some more requests
     for (int i = 0; i < 2; i++) {
       CountDownLatch latch2 = new CountDownLatch(1);
-      client.getNow("/", resp -> {
+      clients[2 + i].request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
         assertEquals(200, resp.statusCode());
         latch2.countDown();
-      });
+      }).end();
       awaitLatch(latch2);
     }
 
@@ -2468,11 +2475,11 @@ public void testSetWriteQueueMaxSize() throws Exception {
       resp.setWriteQueueMaxSize(128 * 1024);
       resp.setWriteQueueMaxSize(129 * 1024);
       resp.end();
-    }).listen(8080, onSuccess(s -> {
-      client.getNow(8080, "localhost", "/", resp -> {
+    }).listen(testAddress, onSuccess(s -> {
+      client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
         assertEquals(200, resp.statusCode());
         testComplete();
-      });
+      }).end();
     }));
     await();
   }
@@ -2491,24 +2498,24 @@ public void testServerMaxInitialLineLengthOption() {
   private void testServerMaxInitialLineLength(int maxInitialLength) {
     String longParam = TestUtils.randomAlphaString(5000);
     server.close();
-    server = vertx.createHttpServer(new HttpServerOptions().setMaxInitialLineLength(maxInitialLength)
-        .setHost("localhost").setPort(8080)).requestHandler(req -> {
+    server = vertx.createHttpServer(createBaseServerOptions().setMaxInitialLineLength(maxInitialLength))
+      .requestHandler(req -> {
       assertEquals(req.getParam("t"), longParam);
       req.response().end();
-    }).listen(onSuccess(res -> {
-      HttpClientRequest req = vertx.createHttpClient(new HttpClientOptions())
-          .request(HttpMethod.GET, 8080, "localhost", "/?t=" + longParam);
-      req.handler(resp -> {
-        if (maxInitialLength > HttpServerOptions.DEFAULT_MAX_INITIAL_LINE_LENGTH) {
-          assertEquals(200, resp.statusCode());
-          testComplete();
-        } else {
-          assertEquals(414, resp.statusCode());
-          req.connection().closeHandler(v -> {
-            testComplete();
-          });
-        }
-      });
+    }).listen(testAddress, onSuccess(res -> {
+      HttpClientRequest req = vertx.createHttpClient()
+          .request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/?t=" + longParam,
+            resp -> {
+              if (maxInitialLength > HttpServerOptions.DEFAULT_MAX_INITIAL_LINE_LENGTH) {
+                assertEquals(200, resp.statusCode());
+                testComplete();
+              } else {
+                assertEquals(414, resp.statusCode());
+                resp.request().connection().closeHandler(v -> {
+                  testComplete();
+                });
+              }
+            });
       req.end();
     }));
     await();
@@ -2533,9 +2540,9 @@ public void testClientMaxInitialLineLengthOption() {
 
     // 5017 = 5000 for longParam and 17 for the rest in the following line - "GET /?t=longParam HTTP/1.1"
     try {
-      server.listen(DEFAULT_HTTP_PORT, DEFAULT_HTTPS_HOST, onSuccess(v -> {
+      server.listen(testAddress, onSuccess(v -> {
         vertx.createHttpClient(new HttpClientOptions().setMaxInitialLineLength(6000))
-            .request(HttpMethod.GET, 8080, "localhost", "/?t=" + longParam, resp -> {
+            .request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/?t=" + longParam, resp -> {
               resp.bodyHandler(body -> {
                 assertEquals("0123456789", body.toString());
                 testComplete();
@@ -2554,12 +2561,12 @@ public void testClientMaxHeaderSizeOption() {
     String longHeader = TestUtils.randomAlphaString(9000);
 
     // min 9023 = 9000 for longHeader and 23 for "Content-Length: 0 t: "
-    vertx.createHttpServer(new HttpServerOptions().setHost(DEFAULT_HTTP_HOST).setPort(DEFAULT_HTTP_PORT)).requestHandler(req -> {
+    vertx.createHttpServer(createBaseServerOptions()).requestHandler(req -> {
       // Add longHeader
       req.response().putHeader("t", longHeader).end();
-    }).listen(onSuccess(res -> {
+    }).listen(testAddress, onSuccess(res -> {
       HttpClientRequest req = vertx.createHttpClient(new HttpClientOptions().setMaxHeaderSize(10000))
-          .request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", resp -> {
+          .request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
             assertEquals(200, resp.statusCode());
             assertEquals(resp.getHeader("t"), longHeader);
             testComplete();
@@ -2585,24 +2592,24 @@ private void testServerMaxHeaderSize(int maxHeaderSize) {
 
     String longHeader = TestUtils.randomAlphaString(9000);
 
-    vertx.createHttpServer(new HttpServerOptions().setMaxHeaderSize(maxHeaderSize)
-        .setHost("localhost").setPort(8080)).requestHandler(req -> {
+    vertx.createHttpServer(createBaseServerOptions().setMaxHeaderSize(maxHeaderSize))
+      .requestHandler(req -> {
       assertEquals(req.getHeader("t"), longHeader);
       req.response().end();
-    }).listen(onSuccess(res -> {
+    }).listen(testAddress, onSuccess(res -> {
       HttpClientRequest req = vertx.createHttpClient(new HttpClientOptions())
-          .request(HttpMethod.GET, 8080, "localhost", "/");
-      req.handler(resp -> {
-        if (maxHeaderSize > HttpServerOptions.DEFAULT_MAX_HEADER_SIZE) {
-          assertEquals(200, resp.statusCode());
-          testComplete();
-        } else {
-          assertEquals(400, resp.statusCode());
-          req.connection().closeHandler(v -> {
-            testComplete();
-          });
-        }
-      });
+          .request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI,
+            resp -> {
+              if (maxHeaderSize > HttpServerOptions.DEFAULT_MAX_HEADER_SIZE) {
+                assertEquals(200, resp.statusCode());
+                testComplete();
+              } else {
+                assertEquals(400, resp.statusCode());
+                resp.request().connection().closeHandler(v -> {
+                  testComplete();
+                });
+              }
+            });
       // Add longHeader
       req.putHeader("t", longHeader);
       req.end();
@@ -2645,13 +2652,13 @@ public void testInvalidHttpResponse() {
           }
         }
       });
-    }).listen(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, onSuccess(s -> {
+    }).listen(testAddress, onSuccess(s -> {
 
       // We force two pipelined requests to check that the second request does not get stuck after the first failing
-      client = vertx.createHttpClient(new HttpClientOptions().setKeepAlive(true).setPipelining(true).setMaxPoolSize(1));
+      client = vertx.createHttpClient(createBaseClientOptions().setKeepAlive(true).setPipelining(true).setMaxPoolSize(1));
 
       AtomicBoolean fail1 = new AtomicBoolean();
-      HttpClientRequest req1 = client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> {
+      HttpClientRequest req1 = client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> {
         fail();
       }).exceptionHandler(err -> {
         if (fail1.compareAndSet(false, true)) {
@@ -2661,7 +2668,7 @@ public void testInvalidHttpResponse() {
       });
 
       AtomicBoolean fail2 = new AtomicBoolean();
-      HttpClientRequest req2 = client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> {
+      HttpClientRequest req2 = client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> {
         fail();
       }).exceptionHandler(err -> {
         if (fail2.compareAndSet(false, true)) {
@@ -2686,15 +2693,15 @@ public void testHandleInvalid204Response() throws Exception {
     server.requestHandler(r -> {
       // Generate an invalid response for the pipe-lined
       r.response().setChunked(true).setStatusCode(204).end();
-    }).listen(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, onSuccess(v1 -> {
+    }).listen(testAddress, onSuccess(v1 -> {
       for (int i = 0;i < numReq;i++) {
-        HttpClientRequest post = client.post(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath");
         AtomicInteger count = new AtomicInteger();
-        post.handler(r -> {
-          r.endHandler(v2 -> {
-            complete();
-          });
-        }).exceptionHandler(err -> {
+        client.request(HttpMethod.POST, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI,
+          r -> {
+            r.endHandler(v2 -> {
+              complete();
+            });
+          }).exceptionHandler(err -> {
           if (count.incrementAndGet() == 1) {
             complete();
           }
@@ -2713,11 +2720,11 @@ public void testConnectionCloseHttp_1_0_NoClose() throws Exception {
       AtomicBoolean firstRequest = new AtomicBoolean(true);
       socket.handler(RecordParser.newDelimited("\r\n\r\n", buffer -> {
         if (firstRequest.getAndSet(false)) {
-          socket.write("HTTP/1.0 200 OK\n" + "Content-Type: text/plain\n" + "Content-Length: 4\n"
-              + "Connection: keep-alive\n" + "\n" + "xxx\n");
+          socket.write("HTTP/1.0 200 OK\r\n" + "Content-Type: text/plain\r\n" + "Content-Length: 4\r\n"
+              + "Connection: keep-alive\r\n" + "\r\n" + "xxx\n");
         } else {
-          socket.write("HTTP/1.0 200 OK\n" + "Content-Type: text/plain\n" + "Content-Length: 1\n"
-              + "\n" + "\n");
+          socket.write("HTTP/1.0 200 OK\r\n" + "Content-Type: text/plain\r\n" + "Content-Length: 1\r\n"
+              + "\r\n" + "\n");
         }
       }));
     });
@@ -2732,11 +2739,11 @@ public void testConnectionCloseHttp_1_0_Close() throws Exception {
       AtomicBoolean firstRequest = new AtomicBoolean(true);
       socket.handler(RecordParser.newDelimited("\r\n\r\n", buffer -> {
         if (firstRequest.getAndSet(false)) {
-          socket.write("HTTP/1.0 200 OK\n" + "Content-Type: text/plain\n" + "Content-Length: 4\n"
-              + "Connection: keep-alive\n" + "\n" + "xxx\n");
+          socket.write("HTTP/1.0 200 OK\r\n" + "Content-Type: text/plain\r\n" + "Content-Length: 4\r\n"
+              + "Connection: keep-alive\r\n" + "\n" + "xxx\n");
         } else {
-          socket.write("HTTP/1.0 200 OK\n" + "Content-Type: text/plain\n" + "Content-Length: 1\n"
-              + "\n" + "\n");
+          socket.write("HTTP/1.0 200 OK\r\n" + "Content-Type: text/plain\r\n" + "Content-Length: 1\r\n"
+              + "\r\n" + "\n");
           socket.close();
         }
       }));
@@ -2753,7 +2760,7 @@ public void testConnectionCloseHttp_1_1_NoClose() throws Exception {
               + "\r\n" + "xxx\n");
         } else {
           socket.write("HTTP/1.1 200 OK\r\n" + "Content-Type: text/plain\r\n" + "Content-Length: 1\r\n"
-              + "Connection: close\r\n" + "\r\n" + "\r\n");
+              + "Connection: close\r\n" + "\r\n" + "\n");
         }
       }));
     });
@@ -2768,8 +2775,8 @@ public void testConnectionCloseHttp_1_1_Close() throws Exception {
           socket.write("HTTP/1.1 200 OK\r\n" + "Content-Type: text/plain\r\n" + "Content-Length: 3\r\n"
               + "\r\n" + "xxx");
         } else {
-          socket.write("HTTP/1.1 200 OK\r\n" + "Content-Type: text/plain\r\n" + "Content-Length: 0\r\n"
-              + "Connection: close\r\n" + "\r\n");
+          socket.write("HTTP/1.1 200 OK\r\n" + "Content-Type: text/plain\r\n" + "Content-Length: 1\r\n"
+              + "Connection: close\r\n" + "\r\n" + "\n");
           socket.close();
         }
       }));
@@ -2780,6 +2787,8 @@ private void testConnectionClose(
       Handler<HttpClientRequest> clientRequest,
       Handler<NetSocket> connectHandler
   ) throws Exception {
+    // Cannot reliably pass due to https://github.com/netty/netty/issues/9113
+    Assume.assumeTrue(testAddress.path() == null);
 
     client.close();
     server.close();
@@ -2787,7 +2796,7 @@ private void testConnectionClose(
     NetServerOptions serverOptions = new NetServerOptions();
 
     CountDownLatch serverLatch = new CountDownLatch(1);
-    vertx.createNetServer(serverOptions).connectHandler(connectHandler).listen(8080, result -> {
+    vertx.createNetServer(serverOptions).connectHandler(connectHandler).listen(testAddress, result -> {
       if (result.succeeded()) {
         serverLatch.countDown();
       } else {
@@ -2799,7 +2808,6 @@ private void testConnectionClose(
 
     HttpClientOptions clientOptions = new HttpClientOptions()
         .setDefaultHost("localhost")
-        .setDefaultPort(8080)
         .setKeepAlive(true)
         .setPipelining(false);
     client = vertx.createHttpClient(clientOptions);
@@ -2808,7 +2816,7 @@ private void testConnectionClose(
     AtomicInteger count = new AtomicInteger(requests);
 
     for (int i = 0; i < requests; i++) {
-      HttpClientRequest req = client.get("/", resp -> {
+      HttpClientRequest req = client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
         resp.handler(buffer -> {
           // Should check
         });
@@ -2817,12 +2825,8 @@ private void testConnectionClose(
             complete();
           }
         });
-        resp.exceptionHandler(th -> {
-          fail();
-        });
-      }).exceptionHandler(th -> {
-        fail();
-      });
+        resp.exceptionHandler(this::fail);
+      }).exceptionHandler(this::fail);
       clientRequest.handle(req);
     }
 
@@ -2836,26 +2840,21 @@ public void testDontReuseConnectionWhenResponseEndsDuringAnOngoingRequest() thro
     server.requestHandler(req -> {
       req.response().end();
     });
-    CountDownLatch serverLatch = new CountDownLatch(1);
-    server.listen(ar -> {
-      assertTrue(ar.succeeded());
-      serverLatch.countDown();
-    });
+    startServer(testAddress);
 
-    awaitLatch(serverLatch);
-    HttpClientRequest req1 = client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/");
-    req1.handler(resp -> {
-      resp.endHandler(v1 -> {
-        // End request after the response ended
-        vertx.setTimer(100, v2 -> {
-          req1.end();
+    HttpClientRequest req1 = client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI,
+      resp -> {
+        resp.endHandler(v1 -> {
+          // End request after the response ended
+          vertx.setTimer(100, v2 -> {
+            resp.request().end();
+          });
         });
       });
-    });
     // Send head to the server and trigger the request handler
     req1.sendHead();
 
-    client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", resp -> {
+    client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", resp -> {
       testComplete();
     }).end();
 
@@ -2872,28 +2871,28 @@ public void testRecyclePipelinedConnection() throws Exception {
       req.response().end();
       doneLatch.countDown();
     });
-    server.listen(onSuccess(s -> {
+    server.listen(testAddress, onSuccess(s -> {
       listenLatch.countDown();
     }));
     awaitLatch(listenLatch);
     client.close();
-    client = vertx.createHttpClient(new HttpClientOptions().setMaxPoolSize(1).setPipelining(true).setKeepAlive(true));
+    client = vertx.createHttpClient(createBaseClientOptions().setMaxPoolSize(1).setPipelining(true).setKeepAlive(true));
     AtomicInteger connCount = new AtomicInteger();
     client.connectionHandler(conn -> connCount.incrementAndGet());
-    HttpClientRequest req = client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/first", resp -> {
+    HttpClientRequest req = client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/first", resp -> {
       fail();
     });
     // Force connect
     req.sendHead(v -> {});
     req.reset();
     CountDownLatch respLatch = new CountDownLatch(2);
-    client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/second", resp -> {
+    client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/second", resp -> {
       assertEquals(200, resp.statusCode());
       resp.endHandler(v -> {
         respLatch.countDown();
       });
     }).exceptionHandler(this::fail).end();
-    client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/third", resp -> {
+    client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/third", resp -> {
       assertEquals(200, resp.statusCode());
       resp.endHandler(v -> {
         respLatch.countDown();
@@ -2912,10 +2911,8 @@ public void testClientConnectionExceptionHandler() throws Exception {
       NetSocket so = req.netSocket();
       so.write(Buffer.buffer(TestUtils.randomAlphaString(40) + "\r\n"));
     });
-    CountDownLatch listenLatch = new CountDownLatch(1);
-    server.listen(onSuccess(s -> listenLatch.countDown()));
-    awaitLatch(listenLatch);
-    HttpClientRequest req = client.post(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> {
+    startServer(testAddress);
+    HttpClientRequest req = client.request(HttpMethod.POST, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> {
     });
     req.connectionHandler(conn -> {
       conn.exceptionHandler(err -> {
@@ -2937,17 +2934,15 @@ public void testServerConnectionExceptionHandler() throws Exception {
     server.requestHandler(req -> {
       req.response().end();
     });
-    CountDownLatch listenLatch = new CountDownLatch(1);
-    server.listen(onSuccess(s -> listenLatch.countDown()));
-    awaitLatch(listenLatch);
+    startServer(testAddress);
     client.close();
-    client = vertx.createHttpClient(new HttpClientOptions().setMaxPoolSize(1));
-    client.getNow(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp1 -> {
-      HttpClientRequest req = client.post(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp2 -> {
+    client = vertx.createHttpClient(createBaseClientOptions().setMaxPoolSize(1));
+    client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp1 -> {
+      HttpClientRequest req = client.request(HttpMethod.POST, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp2 -> {
       });
       req.putHeader("the_header", TestUtils.randomAlphaString(10000));
       req.sendHead();
-    });
+    }).end();
     await();
   }
 
@@ -2960,10 +2955,8 @@ public void testServerExceptionHandler() throws Exception {
     server.requestHandler(req -> {
       fail();
     });
-    CountDownLatch listenLatch = new CountDownLatch(1);
-    server.listen(onSuccess(s -> listenLatch.countDown()));
-    awaitLatch(listenLatch);
-    HttpClientRequest req = client.post(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> {
+    startServer(testAddress);
+    HttpClientRequest req = client.request(HttpMethod.POST, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> {
     });
     req.putHeader("the_header", TestUtils.randomAlphaString(10000));
     req.sendHead();
@@ -2971,137 +2964,7 @@ public void testServerExceptionHandler() throws Exception {
   }
 
   @Test
-  public void testHttpProxyRequest() throws Exception {
-    startProxy(null, ProxyType.HTTP);
-    client.close();
-    client = vertx.createHttpClient(new HttpClientOptions()
-        .setProxyOptions(new ProxyOptions().setType(ProxyType.HTTP).setHost("localhost").setPort(proxy.getPort())));
-    testHttpProxyRequest2(client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/"));
-  }
-
-  @Test
-  public void testHttpProxyRequestOverrideClientSsl() throws Exception {
-    startProxy(null, ProxyType.HTTP);
-    client.close();
-    client = vertx.createHttpClient(new HttpClientOptions()
-        .setSsl(true).setProxyOptions(new ProxyOptions().setType(ProxyType.HTTP).setHost("localhost").setPort(proxy.getPort())));
-    testHttpProxyRequest2(client.get(new RequestOptions().setSsl(false).setHost("localhost").setPort(8080)));
-  }
-
-  private void testHttpProxyRequest2(HttpClientRequest clientReq) throws Exception {
-    server.requestHandler(req -> {
-      req.response().end();
-    });
-
-    server.listen(onSuccess(s -> {
-      clientReq.handler(resp -> {
-        assertEquals(200, resp.statusCode());
-        assertNotNull("request did not go through proxy", proxy.getLastUri());
-        assertEquals("Host header doesn't contain target host", "localhost:8080", proxy.getLastRequestHeaders().get("Host"));
-        testComplete();
-      });
-      clientReq.exceptionHandler(this::fail);
-      clientReq.end();
-    }));
-    await();
-  }
-
-  @Test
-  public void testHttpProxyRequestAuth() throws Exception {
-    startProxy("user", ProxyType.HTTP);
-
-    client.close();
-    client = vertx.createHttpClient(new HttpClientOptions()
-        .setProxyOptions(new ProxyOptions().setType(ProxyType.HTTP).setHost("localhost").setPort(proxy.getPort())
-            .setUsername("user").setPassword("user")));
-
-    server.requestHandler(req -> {
-      req.response().end();
-    });
-
-    server.listen(onSuccess(s -> {
-      client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", resp -> {
-        assertEquals(200, resp.statusCode());
-        assertNotNull("request did not go through proxy", proxy.getLastUri());
-        assertEquals("Host header doesn't contain target host", "localhost:8080", proxy.getLastRequestHeaders().get("Host"));
-        testComplete();
-      }).exceptionHandler(th -> fail(th)).end();
-    }));
-    await();
-  }
-
-  @Test
-  public void testHttpProxyFtpRequest() throws Exception {
-    startProxy(null, ProxyType.HTTP);
-    client.close();
-    client = vertx.createHttpClient(new HttpClientOptions()
-        .setProxyOptions(new ProxyOptions().setType(ProxyType.HTTP).setHost("localhost").setPort(proxy.getPort())));
-    final String url = "ftp://ftp.gnu.org/gnu/";
-    proxy.setForceUri("http://localhost:8080/");
-    HttpClientRequest clientReq = client.getAbs(url);
-    server.requestHandler(req -> {
-      req.response().end();
-    });
-
-    server.listen(onSuccess(s -> {
-      clientReq.handler(resp -> {
-        assertEquals(200, resp.statusCode());
-        assertEquals("request did sent the expected url", url, proxy.getLastUri());
-        testComplete();
-      });
-      clientReq.exceptionHandler(this::fail);
-      clientReq.end();
-    }));
-    await();
-  }
-
-  @Test
-  public void testHttpSocksProxyRequest() throws Exception {
-    startProxy(null, ProxyType.SOCKS5);
-
-    client.close();
-    client = vertx.createHttpClient(new HttpClientOptions()
-        .setProxyOptions(new ProxyOptions().setType(ProxyType.SOCKS5).setHost("localhost").setPort(proxy.getPort())));
-
-    server.requestHandler(req -> {
-      req.response().end();
-    });
-
-    server.listen(onSuccess(s -> {
-      client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", resp -> {
-        assertEquals(200, resp.statusCode());
-        assertNotNull("request did not go through proxy", proxy.getLastUri());
-        testComplete();
-      }).exceptionHandler(th -> fail(th)).end();
-    }));
-    await();
-  }
-
-  @Test
-  public void testHttpSocksProxyRequestAuth() throws Exception {
-    startProxy("user", ProxyType.SOCKS5);
-
-    client.close();
-    client = vertx.createHttpClient(new HttpClientOptions()
-        .setProxyOptions(new ProxyOptions().setType(ProxyType.SOCKS5).setHost("localhost").setPort(proxy.getPort())
-            .setUsername("user").setPassword("user")));
-
-    server.requestHandler(req -> {
-      req.response().end();
-    });
-
-    server.listen(onSuccess(s -> {
-      client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", resp -> {
-        assertEquals(200, resp.statusCode());
-        assertNotNull("request did not go through proxy", proxy.getLastUri());
-        testComplete();
-      }).exceptionHandler(th -> fail(th)).end();
-    }));
-    await();
-  }
-
-  @Test
-  public void testRandomPorts() throws Exception {
+  public void testRandomPorts() {
     int numServers = 10;
     Set<Integer> ports = Collections.synchronizedSet(new HashSet<>());
     AtomicInteger count = new AtomicInteger();
@@ -3136,9 +2999,9 @@ public void testContentDecompression() throws Exception {
       });
     });
 
-    server.listen(onSuccess(server -> {
+    server.listen(testAddress, onSuccess(server -> {
       client
-      .request(HttpMethod.POST, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "some-uri", resp -> testComplete())
+      .request(HttpMethod.POST, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "some-uri", resp -> testComplete())
       .putHeader("Content-Encoding", "gzip")
       .end(Buffer.buffer(dataGzipped));
     }));
@@ -3182,24 +3045,24 @@ private void testResetClientRequestNotYetSent(boolean keepAlive, boolean pipelin
         });
       });
       CountDownLatch latch = new CountDownLatch(1);
-      server.listen(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, onSuccess(v -> {
+      server.listen(testAddress, onSuccess(v -> {
         latch.countDown();
       }));
       awaitLatch(latch);
       client.close();
-      client = vertx.createHttpClient(new HttpClientOptions().setMaxPoolSize(1).setKeepAlive(keepAlive).setPipelining(pipelined));
-      HttpClientRequest post = client.post(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
-        fail();
-      });
+      client = vertx.createHttpClient(createBaseClientOptions().setMaxPoolSize(1).setKeepAlive(keepAlive).setPipelining(pipelined));
       // There might be a race between the request write and the request reset
       // so we do it on the context thread to avoid it
       vertx.runOnContext(v -> {
+        HttpClientRequest post = client.request(HttpMethod.POST, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+          fail();
+        });
         post.setChunked(true).write(TestUtils.randomBuffer(1024));
         assertTrue(post.reset());
-        client.getNow(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+        client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
           assertEquals(1, numReq.get());
           complete();
-        });
+        }).end();
       });
       await();
     } finally {
@@ -3235,14 +3098,14 @@ public void testResetKeepAliveClientRequest() throws Exception {
         });
       });
       CountDownLatch listenLatch = new CountDownLatch(1);
-      server.listen(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, onSuccess(v -> {
+      server.listen(testAddress, onSuccess(v -> {
         listenLatch.countDown();
       }));
       awaitLatch(listenLatch);
       client.close();
       client = vertx.createHttpClient(new HttpClientOptions().setMaxPoolSize(1).setPipelining(false).setKeepAlive(true));
       AtomicInteger status = new AtomicInteger();
-      HttpClientRequest req1 = client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> {
+      HttpClientRequest req1 = client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> {
         assertEquals(0, status.getAndIncrement());
       });
       req1.connectionHandler(conn -> {
@@ -3252,7 +3115,7 @@ public void testResetKeepAliveClientRequest() throws Exception {
         });
       });
       req1.end();
-      HttpClientRequest req2 = client.post(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> {
+      HttpClientRequest req2 = client.request(HttpMethod.POST, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> {
         fail();
       });
       req2.sendHead(v -> {
@@ -3297,13 +3160,13 @@ public void testResetPipelinedClientRequest() throws Exception {
     });
     try {
       CountDownLatch listenLatch = new CountDownLatch(1);
-      server.listen(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, onSuccess(v -> {
+      server.listen(testAddress, onSuccess(v -> {
         listenLatch.countDown();
       }));
       awaitLatch(listenLatch);
       client.close();
-      client = vertx.createHttpClient(new HttpClientOptions().setMaxPoolSize(1).setPipelining(true).setKeepAlive(true));
-      HttpClientRequest req1 = client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> {
+      client = vertx.createHttpClient(createBaseClientOptions().setMaxPoolSize(1).setPipelining(true).setKeepAlive(true));
+      HttpClientRequest req1 = client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> {
         // We may or not receive the response
       });
       req1.connectionHandler(conn -> {
@@ -3312,7 +3175,7 @@ public void testResetPipelinedClientRequest() throws Exception {
         });
       });
       req1.end();
-      HttpClientRequest req2 = client.post(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> {
+      HttpClientRequest req2 = client.request(HttpMethod.POST, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> {
         fail();
       });
       req2.sendHead();
@@ -3380,24 +3243,24 @@ private void testCloseTheConnectionAfterResetPersistentClientRequest(boolean pip
         }
       });
       CountDownLatch listenLatch = new CountDownLatch(1);
-      server.listen(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, onSuccess(v -> {
+      server.listen(testAddress, onSuccess(v -> {
         listenLatch.countDown();
       }));
       awaitLatch(listenLatch);
       client.close();
       client = vertx.createHttpClient(new HttpClientOptions().setMaxPoolSize(1).setPipelining(pipelined).setKeepAlive(true));
-      HttpClientRequest req1 = client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> {
+      HttpClientRequest req1 = client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> {
         fail();
       });
       if (pipelined) {
         req1.connectionHandler(conn -> conn.closeHandler(v2 -> {
-          client.getNow(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> {
+          client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> {
             assertEquals(200, resp.statusCode());
             resp.bodyHandler(body -> {
               assertEquals("Hello world", body.toString());
               complete();
             });
-          });
+          }).end();
         }));
         req1.sendHead(v -> {
           assertTrue(req1.reset());
@@ -3406,13 +3269,13 @@ private void testCloseTheConnectionAfterResetPersistentClientRequest(boolean pip
         req1.sendHead(v -> {
           assertTrue(req1.reset());
         });
-        client.getNow(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> {
+        client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> {
           assertEquals(200, resp.statusCode());
           resp.bodyHandler(body -> {
             assertEquals("Hello world", body.toString());
             complete();
           });
-        });
+        }).end();
       }
       await();
     } finally {
@@ -3481,44 +3344,43 @@ private void testCloseTheConnectionAfterResetPersistentClientResponse(boolean pi
         }
       });
       CountDownLatch listenLatch = new CountDownLatch(1);
-      server.listen(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, onSuccess(v -> {
+      server.listen(testAddress, onSuccess(v -> {
         listenLatch.countDown();
       }));
       awaitLatch(listenLatch);
       client.close();
-      client = vertx.createHttpClient(new HttpClientOptions().setMaxPoolSize(1).setPipelining(pipelined).setKeepAlive(true));
-      HttpClientRequest req1 = client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath");
+      client = vertx.createHttpClient(createBaseClientOptions().setMaxPoolSize(1).setPipelining(pipelined).setKeepAlive(true));
       if (pipelined) {
-        req1.handler(resp1 -> {
-          resp1.handler(buff -> {
-            req1.reset();
-            // Since we pipeline we must be sure that the first request is closed before running a new one
-            req1.connection().closeHandler(v -> {
-              client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> {
-                assertEquals(200, resp.statusCode());
-                resp.bodyHandler(body -> {
-                  assertEquals("Hello world", body.toString());
-                  complete();
-                });
-              }).end();
+        client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath",
+          resp1 -> {
+            resp1.handler(buff -> {
+              resp1.request().reset();
+              // Since we pipeline we must be sure that the first request is closed before running a new one
+              resp1.request().connection().closeHandler(v -> {
+                client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> {
+                  assertEquals(200, resp.statusCode());
+                  resp.bodyHandler(body -> {
+                    assertEquals("Hello world", body.toString());
+                    complete();
+                  });
+                }).end();
+              });
             });
-          });
-        });
-        req1.end();
+          }).end();
       } else {
-        req1.handler(resp -> {
-          resp.handler(buff -> {
-            req1.reset();
-          });
-        });
-        req1.end();
-        client.getNow(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> {
+        client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath",
+          resp -> {
+            resp.handler(buff -> {
+              resp.request().reset();
+            });
+          }).end();
+        client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> {
           assertEquals(200, resp.statusCode());
           resp.bodyHandler(body -> {
             assertEquals("Hello world", body.toString());
             complete();
           });
-        });
+        }).end();
       }
       await();
     } finally {
@@ -3589,25 +3451,25 @@ private void testCloseTheConnectionAfterResetBeforeResponseReceived(boolean pipe
         }
       });
       CountDownLatch listenLatch = new CountDownLatch(1);
-      server.listen(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, onSuccess(v -> {
+      server.listen(testAddress, onSuccess(v -> {
         listenLatch.countDown();
       }));
       awaitLatch(listenLatch);
       client.close();
-      client = vertx.createHttpClient(new HttpClientOptions().setMaxPoolSize(1).setPipelining(pipelined).setKeepAlive(true));
-      HttpClientRequest req1 = client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/1");
+      client = vertx.createHttpClient(createBaseClientOptions().setMaxPoolSize(1).setPipelining(pipelined).setKeepAlive(true));
+      HttpClientRequest req1 = client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/1");
       if (pipelined) {
         requestReceived.thenAccept(v -> {
           req1.reset();
         });
         req1.connectionHandler(conn -> conn.closeHandler(v2 -> {
-          client.getNow(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/2", resp -> {
+          client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/2", resp -> {
             assertEquals(200, resp.statusCode());
             resp.bodyHandler(body -> {
               assertEquals("Hello world", body.toString());
               complete();
             });
-          });
+          }).end();
         }));
         req1.handler(resp1 -> fail());
         req1.end();
@@ -3617,13 +3479,13 @@ private void testCloseTheConnectionAfterResetBeforeResponseReceived(boolean pipe
         });
         req1.handler(resp -> fail());
         req1.end();
-        client.getNow(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/2", resp -> {
+        client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/2", resp -> {
           assertEquals(200, resp.statusCode());
           resp.bodyHandler(body -> {
             assertEquals("Hello world", body.toString());
             complete();
           });
-        });
+        }).end();
       }
       await();
     } finally {
@@ -3642,10 +3504,10 @@ public void testTooLongContentInHttpServerRequest() throws Exception {
         testComplete();
       });
     });
-    startServer();
+    startServer(testAddress);
     NetClient client = vertx.createNetClient();
     try {
-      client.connect(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, onSuccess(so -> {
+      client.connect(testAddress, onSuccess(so -> {
         so.write("POST / HTTP/1.1\r\nContent-Length: 4\r\n\r\ntoolong\r\n");
       }));
       await();
@@ -3691,9 +3553,9 @@ private void testHttpServerRequestDecodeError(Handler<NetSocket> bodySender, Han
       req.exceptionHandler(handler);
       bodySender.handle(current.get());
     });
-    startServer();
+    startServer(testAddress);
     NetClient client = vertx.createNetClient();
-    client.connect(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, onSuccess(so -> {
+    client.connect(testAddress, onSuccess(so -> {
       current.set(so);
       so.write("POST /somepath HTTP/1.1\r\n");
       so.write("Transfer-Encoding: chunked\r\n");
@@ -3755,10 +3617,10 @@ public void testInvalidTrailersInHttpClientResponse() throws Exception {
   }
 
   private void testHttpClientResponseDecodeError(Handler<Throwable> errorHandler) throws Exception {
-    startServer();
-    client.getNow(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> {
+    startServer(testAddress);
+    client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> {
       resp.exceptionHandler(errorHandler);
-    });
+    }).end();
     await();
   }
 
@@ -3769,14 +3631,14 @@ public void testRequestTimeoutIsNotDelayedAfterResponseIsReceived() throws Excep
     server.requestHandler(req -> {
       req.response().end();
     });
-    startServer();
+    startServer(testAddress);
     vertx.deployVerticle(new AbstractVerticle() {
       @Override
       public void start() throws Exception {
         HttpClient client = vertx.createHttpClient(new HttpClientOptions().setMaxPoolSize(n));
         for (int i = 0;i < n;i++) {
           AtomicBoolean responseReceived = new AtomicBoolean();
-          client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+          client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
             try {
               Thread.sleep(150);
             } catch (InterruptedException e) {
@@ -3883,10 +3745,10 @@ public void testSendFileFailsWhenClientClosesConnection() throws Exception {
         fail(e);
       }
     });
-    startServer();
-    vertx.createNetClient().connect(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, socket -> {
-      socket.result().write("GET / HTTP/1.1\r\n\r\n").close();
-    });
+    startServer(testAddress);
+    vertx.createNetClient().connect(testAddress, onSuccess(socket -> {
+      socket.write("GET / HTTP/1.1\r\n\r\n").close();
+    }));
     await();
   }
 
@@ -3898,11 +3760,11 @@ protected MultiMap checkEmptyHttpResponse(HttpMethod method, int sc, MultiMap re
       resp.headers().addAll(reqHeaders);
       resp.end();
     });
-    startServer();
+    startServer(testAddress);
     NetClient client = vertx.createNetClient();
     try {
       CompletableFuture<MultiMap> result = new CompletableFuture<>();
-      client.connect(DEFAULT_HTTP_PORT, DEFAULT_HTTPS_HOST, ar -> {
+      client.connect(testAddress, ar -> {
         if (ar.succeeded()) {
           NetSocket so = ar.result();
           so.write(
@@ -3946,13 +3808,13 @@ public void testUnknownContentLengthIsSetToZeroWithHTTP_1_0() throws Exception {
     server.requestHandler(req -> {
       req.response().write("Some-String").end();
     });
-    startServer();
+    startServer(testAddress);
     client.close();
     client = vertx.createHttpClient(new HttpClientOptions().setProtocolVersion(HttpVersion.HTTP_1_0));
-    client.getNow(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
       assertNull(resp.getHeader("Content-Length"));
       testComplete();
-    });
+    }).end();
     await();
   }
 
@@ -3963,9 +3825,9 @@ public void testPartialH2CAmbiguousRequest() throws Exception {
       testComplete();
     });
     Buffer fullRequest = Buffer.buffer("POST /whatever HTTP/1.1\r\n\r\n");
-    startServer();
+    startServer(testAddress);
     NetClient client = vertx.createNetClient();
-    client.connect(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, onSuccess(so -> {
+    client.connect(testAddress, onSuccess(so -> {
       so.write(fullRequest.slice(0, 1));
       vertx.setTimer(1000, id -> {
         so.write(fullRequest.slice(1, fullRequest.length()));
@@ -3984,9 +3846,9 @@ public void testIdleTimeoutWithPartialH2CRequest() throws Exception {
     server.requestHandler(req -> {
       testComplete();
     });
-    startServer();
+    startServer(testAddress);
     NetClient client = vertx.createNetClient();
-    client.connect(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, onSuccess(so -> {
+    client.connect(testAddress, onSuccess(so -> {
       so.closeHandler(v -> {
         testComplete();
       });
@@ -3997,16 +3859,13 @@ public void testIdleTimeoutWithPartialH2CRequest() throws Exception {
   @Test
   public void testIdleTimeoutInfiniteSkipOfControlCharactersState() throws Exception {
     server.close();
-    server = vertx.createHttpServer(new HttpServerOptions()
-      .setPort(DEFAULT_HTTP_PORT)
-      .setHost(DEFAULT_HTTP_HOST)
-      .setIdleTimeout(1));
+    server = vertx.createHttpServer(createBaseServerOptions().setIdleTimeout(1));
     server.requestHandler(req -> {
       testComplete();
     });
-    startServer();
+    startServer(testAddress);
     NetClient client = vertx.createNetClient();
-    client.connect(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, onSuccess(so -> {
+    client.connect(testAddress, onSuccess(so -> {
       long id = vertx.setPeriodic(1, timerID -> {
         so.write(Buffer.buffer().setInt(0, 0xD));
       });
@@ -4022,15 +3881,12 @@ public void testIdleTimeoutInfiniteSkipOfControlCharactersState() throws Excepti
   public void testCompressedResponseWithConnectionCloseAndNoCompressionHeader() throws Exception {
     Buffer expected = Buffer.buffer(TestUtils.randomAlphaString(2048));
     server.close();
-    server = vertx.createHttpServer(new HttpServerOptions()
-      .setPort(DEFAULT_HTTP_PORT)
-      .setHost(DEFAULT_HTTP_HOST)
-      .setCompressionSupported(true));
+    server = vertx.createHttpServer(createBaseServerOptions().setCompressionSupported(true));
     server.requestHandler(req -> {
       req.response().end(expected);
     });
-    startServer();
-    client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    startServer(testAddress);
+    client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
       resp.bodyHandler(buff -> {
         assertEquals(expected, buff);
         complete();
@@ -4091,13 +3947,13 @@ public void testKeepAliveTimeoutHeaderOverwritePrevious() throws Exception {
   }
 
   private void testKeepAliveTimeout(HttpClientOptions options, int numReqs) throws Exception {
-    startServer();
+    startServer(testAddress);
     client.close();
     client = vertx.createHttpClient(options.setPoolCleanerPeriod(1));
     AtomicInteger respCount = new AtomicInteger();
     for (int i = 0;i < numReqs;i++) {
       int current = 1 + i;
-      client.getNow(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+      client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
         respCount.incrementAndGet();
         if (current == numReqs) {
           long now = System.currentTimeMillis();
@@ -4111,7 +3967,7 @@ private void testKeepAliveTimeout(HttpClientOptions options, int numReqs) throws
             testComplete();
           });
         }
-      });
+      }).end();
     }
     await();
   }
@@ -4126,10 +3982,10 @@ public void testPoolNotExpiring() throws Exception {
         req.connection().close();
       });
     });
-    startServer();
+    startServer(testAddress);
     client.close();
     client = vertx.createHttpClient(new HttpClientOptions().setPoolCleanerPeriod(0).setKeepAliveTimeout(100));
-    client.getNow(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
       resp.endHandler(v1 -> {
         resp.request().connection().closeHandler(v2 -> {
           long time = System.currentTimeMillis() - now.get();
@@ -4137,7 +3993,7 @@ public void testPoolNotExpiring() throws Exception {
           testComplete();
         });
       });
-    });
+    }).end();
     await();
   }
 
@@ -4161,11 +4017,11 @@ public void testPausedHttpServerRequestPauseTheConnectionAtRequestEnd() throws E
         req.response().end();
       });
     });
-    startServer();
+    startServer(testAddress);
     client.close();
     client = vertx.createHttpClient(createBaseClientOptions().setMaxPoolSize(1));
     for (int i = 0; i < numRequests; i++) {
-      client.put(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/someuri", resp -> {
+      client.request(HttpMethod.PUT, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/someuri", resp -> {
         complete();
       }).end("small");
     }
@@ -4195,19 +4051,19 @@ public void testHttpClientResponsePauseIsIgnoredAtRequestEnd() throws Exception
 
   private void testHttpClientResponsePause(Handler<HttpClientResponse> h) throws Exception {
     server.requestHandler(req -> req.response().end("ok"));
-    startServer();
+    startServer(testAddress);
     client.close();
-    client = vertx.createHttpClient(new HttpClientOptions().setMaxPoolSize(1).setKeepAlive(true));
-    client.getNow(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp1 -> {
+    client = vertx.createHttpClient(createBaseClientOptions().setMaxPoolSize(1).setKeepAlive(true));
+    client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp1 -> {
       h.handle(resp1);
       vertx.setTimer(10, timerId -> {
         // The connection should be resumed as it's ended
-        client.getNow(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp2 -> {
+        client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp2 -> {
           assertSame(resp1.request().connection(), resp2.request().connection());
           resp2.endHandler(v -> testComplete());
-        });
+        }).end();
       });
-    });
+    }).end();
     await();
   }
 
@@ -4225,7 +4081,7 @@ public void testPoolLIFOPolicy() throws Exception {
           break;
       }
     });
-    startServer();
+    startServer(testAddress);
     client.close();
     client = vertx.createHttpClient(createBaseClientOptions().setMaxPoolSize(2));
     // Make two concurrent requests and finish one first
@@ -4234,7 +4090,7 @@ public void testPoolLIFOPolicy() throws Exception {
     // Use one event loop to be sure about response ordering
     vertx.runOnContext(v0 -> {
       for (int i = 0;i < 2;i++) {
-        client.getNow(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/someuri", resp -> {
+        client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/someuri", resp -> {
           resp.endHandler(v1 -> {
             // Use runOnContext to be sure the connections is put back in the pool
             vertx.runOnContext(v2 -> {
@@ -4242,14 +4098,14 @@ public void testPoolLIFOPolicy() throws Exception {
               latch.countDown();
             });
           });
-        });
+        }).end();
       }
     });
     awaitLatch(latch);
-    client.getNow(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/someuri", resp -> {
+    client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/someuri", resp -> {
       assertSame(resp.request().connection(), connections.get(1));
       testComplete();
-    });
+    }).end();
     await();
   }
 
@@ -4304,13 +4160,13 @@ private void testHttpClientResponseThrowsExceptionInHandler(
         resp.end();
       }
     });
-    startServer();
+    startServer(testAddress);
     int num = 50;
     CountDownLatch latch = new CountDownLatch(num);
     for (int i = 0;i < num;i++) {
-      client.getNow(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/someuri", resp -> {
+      client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/someuri", resp -> {
         handler.accept(resp, latch);
-      });
+      }).end();
     }
     awaitLatch(latch);
   }
@@ -4323,8 +4179,8 @@ public void testConnectionCloseDuringShouldCallHandleExceptionOnlyOnce() throws
       });
     });
     AtomicInteger count = new AtomicInteger();
-    startServer();
-    HttpClientRequest post = client.post(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", res -> fail());
+    startServer(testAddress);
+    HttpClientRequest post = client.request(HttpMethod.POST, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", res -> fail());
     post.setChunked(true);
     post.write(TestUtils.randomBuffer(10000));
     CountDownLatch latch = new CountDownLatch(1);
@@ -4352,9 +4208,9 @@ public void testDeferredRequestEnd() throws Exception {
         req.resume();
       });
     });
-    startServer();
+    startServer(testAddress);
     Buffer expected = Buffer.buffer(TestUtils.randomAlphaString(1024));
-    client.post(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", resp -> {
+    client.request(HttpMethod.POST, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", resp -> {
       resp.bodyHandler(body -> {
         assertEquals(expected, body);
         testComplete();
@@ -4384,12 +4240,12 @@ public void testPipelinedWithResponseSent() throws Exception {
         req.resume();
       });
     });
-    startServer();
+    startServer(testAddress);
     client.close();
-    client = vertx.createHttpClient(new HttpClientOptions().setPipelining(true).setMaxPoolSize(1).setKeepAlive(true));
+    client = vertx.createHttpClient(createBaseClientOptions().setPipelining(true).setMaxPoolSize(1).setKeepAlive(true));
     for (int i = 0;i < numReq;i++) {
       String expected = "" + i;
-      client.post(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", resp -> {
+      client.request(HttpMethod.POST, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", resp -> {
         resp.bodyHandler(body -> {
           assertEquals(expected, body.toString());
           complete();
@@ -4413,12 +4269,12 @@ public void testPipelinedWithPendingResponse() throws Exception {
         req.response().end("" + val);
       });
     });
-    startServer();
+    startServer(testAddress);
     client.close();
-    client = vertx.createHttpClient(new HttpClientOptions().setPipelining(true).setMaxPoolSize(1).setKeepAlive(true));
+    client = vertx.createHttpClient(createBaseClientOptions().setPipelining(true).setMaxPoolSize(1).setKeepAlive(true));
     for (int i = 0;i < numReq;i++) {
       String expected = "" + i;
-      client.post(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", resp -> {
+      client.request(HttpMethod.POST, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", resp -> {
         resp.bodyHandler(body -> {
           assertEquals(expected, body.toString());
           complete();
@@ -4454,12 +4310,12 @@ public void testPipelinedPostRequestStartedByResponseSent() throws Exception {
           break;
       }
     });
-    startServer();
+    startServer(testAddress);
     client.close();
     client = vertx.createHttpClient(new HttpClientOptions().setPipelining(true).setMaxPoolSize(1).setKeepAlive(true));
-    client.post(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", resp -> {
+    client.request(HttpMethod.POST, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", resp -> {
     }).end(TestUtils.randomAlphaString(1024));
-    HttpClientRequest req = client.post(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", resp -> {
+    HttpClientRequest req = client.request(HttpMethod.POST, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", resp -> {
       testComplete();
     }).setChunked(true).write(chunk1);
     awaitLatch(latch);
@@ -4480,14 +4336,14 @@ public void testBeginPipelinedRequestByResponseSentOnRequestCompletion() throws
         req.response().end();
       });
     });
-    startServer();
+    startServer(testAddress);
     client.close();
-    client = vertx.createHttpClient(new HttpClientOptions().setPipelining(true).setMaxPoolSize(1).setKeepAlive(true));
+    client = vertx.createHttpClient(createBaseClientOptions().setPipelining(true).setMaxPoolSize(1).setKeepAlive(true));
     client.post(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", resp -> {
     }).end(TestUtils.randomAlphaString(1024));
-    client.getNow(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", resp -> {
+    client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", resp -> {
       testComplete();
-    });
+    }).end();
     await();
   }
 
@@ -4506,14 +4362,14 @@ public void testBeginPipelinedRequestByResponseSentBeforeRequestCompletion() thr
         req.response().end();
       }
     });
-    startServer();
+    startServer(testAddress);
     client.close();
-    client = vertx.createHttpClient(new HttpClientOptions().setPipelining(true).setMaxPoolSize(1).setKeepAlive(true));
-    client.post(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", resp -> {
+    client = vertx.createHttpClient(createBaseClientOptions().setPipelining(true).setMaxPoolSize(1).setKeepAlive(true));
+    client.request(HttpMethod.POST, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", resp -> {
     }).end(TestUtils.randomAlphaString(1024));
-    client.getNow(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", resp -> {
+    client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", resp -> {
       testComplete();
-    });
+    }).end();
     await();
   }
 
@@ -4523,15 +4379,15 @@ public void testHttpClientResponseBufferedWithPausedEnd() throws Exception {
     server.requestHandler(req -> {
       req.response().end("HelloWorld" + i.incrementAndGet());
     });
-    startServer();
+    startServer(testAddress);
     client.close();
     client = vertx.createHttpClient(new HttpClientOptions().setMaxPoolSize(1).setKeepAlive(true));
-    client.getNow(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp1 -> {
+    client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp1 -> {
       // Response is paused but request is put back in the pool since the HTTP response fully arrived
       // but the response it's not yet delivered to the application as we pause the response
       resp1.pause();
       // Do a request on the same connection
-      client.getNow(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp2 -> {
+      client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp2 -> {
         resp2.bodyHandler(body2 -> {
           // When the response arrives -> resume the first request
           assertEquals("HelloWorld2", body2.toString());
@@ -4541,33 +4397,33 @@ public void testHttpClientResponseBufferedWithPausedEnd() throws Exception {
           });
           resp1.resume();
         });
-      });
-    });
+      }).end();
+    }).end();
     await();
   }
 
   @Test
   public void testHttpClientResumeConnectionOnResponseOnLastMessage() throws Exception {
     server.requestHandler(req -> req.response().end("ok"));
-    startServer();
+    startServer(testAddress);
     client.close();
     client = vertx.createHttpClient(new HttpClientOptions().setKeepAlive(true).setMaxPoolSize(1));
-    client.getNow(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp1 -> {
+    client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp1 -> {
       resp1.pause();
       // The connection resume is asynchronous and the end message will be received before connection resume happens
       resp1.resume();
-      client.getNow(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp2 -> {
+      client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp2 -> {
         testComplete();
-      });
-    });
+      }).end();
+    }).end();
     await();
   }
 
   @Test
   public void testSetChunkedToFalse() throws Exception {
     server.requestHandler(req -> req.response().setChunked(false).end());
-    startServer();
-    client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", resp -> {
+    startServer(testAddress);
+    client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", resp -> {
       testComplete();
     }).setChunked(false).end();
     await();
@@ -4589,12 +4445,12 @@ public void testHttpServerRequestShouldCallExceptionHandlerWhenTheClosedHandlerI
         }
       });
     });
-    server.listen(onSuccess(s -> {
-      client.getNow(DEFAULT_HTTP_PORT, HttpTestBase.DEFAULT_HTTP_HOST, "/someuri", resp -> {
+    server.listen(testAddress, onSuccess(s -> {
+      client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, HttpTestBase.DEFAULT_HTTP_HOST, "/someuri", resp -> {
         vertx.setTimer(1000, id -> {
           resp.request().connection().close();
         });
-      });
+      }).end();
     }));
     await();
   }
@@ -4606,8 +4462,8 @@ public void testHttpClientRequestShouldCallExceptionHandlerWhenTheClosedHandlerI
         req.response().close();
       });
     });
-    startServer();
-    HttpClientRequest req = client.put(DEFAULT_HTTP_PORT, HttpTestBase.DEFAULT_HTTP_HOST, "/someuri", resp -> {
+    startServer(testAddress);
+    HttpClientRequest req = client.request(HttpMethod.PUT, testAddress, DEFAULT_HTTP_PORT, HttpTestBase.DEFAULT_HTTP_HOST, "/someuri", resp -> {
     }).setChunked(true);
     CheckingSender sender = new CheckingSender(vertx.getOrCreateContext(), req);
     AtomicBoolean connected = new AtomicBoolean();
@@ -4666,14 +4522,14 @@ public void testChunkedServerResponse() {
       vertx.setTimer(1, id -> {
         resp.end();
       });
-    }).listen(onSuccess(server -> {
-      client.getNow(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", res -> {
+    }).listen(testAddress, onSuccess(server -> {
+      client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", res -> {
         assertEquals("chunked", res.getHeader("transfer-encoding"));
         res.bodyHandler(body -> {
           assertEquals("the-chunk", body.toString());
           testComplete();
         });
-      });
+      }).end();
     }));
     await();
   }
@@ -4687,8 +4543,8 @@ public void testChunkedClientRequest() {
         assertEquals("the-chunk", body.toString());
         req.response().end();
       });
-    }).listen(onSuccess(server -> {
-      HttpClientRequest req = client.put(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", res -> {
+    }).listen(testAddress, onSuccess(server -> {
+      HttpClientRequest req = client.request(HttpMethod.PUT, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", res -> {
         testComplete();
       });
       req.setChunked(true);
@@ -4733,8 +4589,8 @@ public void testHttpServerWithIdleTimeoutSendChunkedFile() throws Exception {
         req -> {
           req.response().sendFile(sent.getAbsolutePath());
         });
-    startServer();
-    client.getNow(8080, "localhost", "/", resp -> {
+    startServer(testAddress);
+    client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", resp -> {
       long now = System.currentTimeMillis();
       int[] length = {0};
       resp.handler(buff -> {
@@ -4750,7 +4606,7 @@ public void testHttpServerWithIdleTimeoutSendChunkedFile() throws Exception {
         assertTrue(System.currentTimeMillis() - now > 1000);
         testComplete();
       });
-    });
+    }).end();
     await();
   }
 
@@ -4763,16 +4619,16 @@ public void testSendFilePipelined() throws Exception {
       req -> {
         req.response().sendFile(sent.getAbsolutePath());
       });
-    startServer();
+    startServer(testAddress);
     client.close();
     client = vertx.createHttpClient(createBaseClientOptions().setPipelining(true).setMaxPoolSize(1));
     for (int i = 0;i < n;i++) {
-      client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+      client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
         resp.exceptionHandler(this::fail);
         resp.bodyHandler(body -> {
           complete();
         });
-      }).exceptionHandler(this::fail).end();
+      }).end();
     }
     await();
   }
diff --git a/src/test/java/io/vertx/core/http/Http2Test.java b/src/test/java/io/vertx/core/http/Http2Test.java
--- a/src/test/java/io/vertx/core/http/Http2Test.java
+++ b/src/test/java/io/vertx/core/http/Http2Test.java
@@ -11,6 +11,7 @@
 
 package io.vertx.core.http;
 
+import io.netty.channel.socket.DuplexChannel;
 import io.netty.channel.socket.SocketChannel;
 import io.netty.handler.codec.http2.Http2CodecUtil;
 import io.vertx.core.Context;
@@ -66,8 +67,8 @@ public void testServerResponseWriteBufferFromOtherThread() throws Exception {
       runAsync(() -> {
         req.response().write("hello ").end("world");
       });
-    }).listen(onSuccess(v -> {
-      client.get(8080, "localhost", "/somepath", resp -> {
+    }).listen(testAddress, onSuccess(v -> {
+      client.request(HttpMethod.GET, testAddress, 8080, "localhost", "/somepath", resp -> {
         assertEquals(200, resp.statusCode());
         resp.bodyHandler(buff -> {
           assertEquals(Buffer.buffer("hello world"), buff);
@@ -84,8 +85,8 @@ public void testServerResponseResetFromOtherThread() throws Exception {
       runAsync(() -> {
         req.response().reset(0);
       });
-    }).listen(onSuccess(v -> {
-      client.get(8080, "localhost", "/somepath", resp -> {
+    }).listen(testAddress, onSuccess(v -> {
+      client.request(HttpMethod.GET, testAddress, 8080, "localhost", "/somepath", resp -> {
         fail();
       }).exceptionHandler(err -> {
         assertTrue(err instanceof StreamResetException);
@@ -114,11 +115,11 @@ public void testClientRequestWriteFromOtherThread() throws Exception {
       req.endHandler(v -> {
         req.response().end();
       });
-    }).listen(onSuccess(v -> {
+    }).listen(testAddress, onSuccess(v -> {
       latch1.countDown();
     }));
     awaitLatch(latch1);
-    HttpClientRequest req = client.get(8080, "localhost", "/somepath", resp -> {
+    HttpClientRequest req = client.request(HttpMethod.GET, testAddress, 8080, "localhost", "/somepath", resp -> {
       assertEquals(200, resp.statusCode());
       testComplete();
     }).setChunked(true).sendHead();
@@ -143,16 +144,8 @@ public void testServerOpenSSL() throws Exception {
     server.requestHandler(req -> {
       req.response().end();
     });
-    CountDownLatch latch = new CountDownLatch(1);
-    System.out.println("starting");
-    try {
-      server.listen(onSuccess(v -> latch.countDown()));
-    } catch (Throwable e) {
-      e.printStackTrace();
-    }
-    System.out.println("listening");
-    awaitLatch(latch);
-    client.get(DEFAULT_HTTPS_PORT, DEFAULT_HTTPS_HOST, "/somepath", resp -> {
+    startServer(testAddress);
+    client.request(HttpMethod.GET, testAddress, DEFAULT_HTTPS_PORT, DEFAULT_HTTPS_HOST, "/somepath", resp -> {
       assertEquals(200, resp.statusCode());
       testComplete();
     }).exceptionHandler(this::fail).end();
@@ -187,8 +180,8 @@ public void testServerStreamPausedWhenConnectionIsPaused() throws Exception {
         }
       }
     });
-    startServer();
-    client.getNow(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/0", resp -> {
+    startServer(testAddress);
+    client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/0", resp -> {
       resp.pause();
       Context ctx = vertx.getOrCreateContext();
       resumeLatch.thenAccept(v1 -> {
@@ -199,13 +192,13 @@ public void testServerStreamPausedWhenConnectionIsPaused() throws Exception {
           resp.resume();
         });
       });
-    });
+    }).end();
     awaitLatch(fullLatch);
-    client.getNow(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/1", resp -> {
+    client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/1", resp -> {
       resp.endHandler(v -> {
         complete();
       });
-    });
+    }).end();
     resumeLatch.get(20, TimeUnit.SECONDS); // Make sure it completes
     await();
   }
@@ -236,15 +229,15 @@ public void testClientStreamPausedWhenConnectionIsPaused() throws Exception {
         }
       }
     });
-    startServer();
-    HttpClientRequest req1 = client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/0", resp -> {
+    startServer(testAddress);
+    HttpClientRequest req1 = client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/0", resp -> {
       complete();
     }).setChunked(true);
     while (!req1.writeQueueFull()) {
       req1.write(Buffer.buffer(TestUtils.randomAlphaString(512)));
       Thread.sleep(1);
     }
-    HttpClientRequest req2 = client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/1", resp -> {
+    HttpClientRequest req2 = client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/1", resp -> {
       complete();
     }).setChunked(true);
     assertFalse(req2.writeQueueFull());
@@ -270,19 +263,19 @@ public void testResetClientRequestNotYetSent() throws Exception {
       req.response().end();
       complete();
     });
-    startServer();
+    startServer(testAddress);
     // There might be a race between the request write and the request reset
     // so we do it on the context thread to avoid it
     vertx.runOnContext(v -> {
-      HttpClientRequest post = client.post(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+      HttpClientRequest post = client.request(HttpMethod.POST, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
       fail();
       });
       post.setChunked(true).write(TestUtils.randomBuffer(1024));
       assertTrue(post.reset());
-      client.getNow(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+      client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
         assertEquals(1, numReq.get());
         complete();
-      });
+      }).end();
     });
     await();
   }
@@ -293,19 +286,19 @@ public void testDiscardConnectionWhenChannelBecomesInactive() throws Exception {
     server.requestHandler(req -> {
       if (count.getAndIncrement() == 0) {
         Http2ServerConnection a = (Http2ServerConnection) req.connection();
-        SocketChannel channel = (SocketChannel) a.channel();
+        DuplexChannel channel = (DuplexChannel) a.channel();
         channel.shutdown();
       } else {
         req.response().end();
       }
     });
-    startServer();
+    startServer(testAddress);
     AtomicBoolean closed = new AtomicBoolean();
-    client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
       fail();
     }).connectionHandler(conn -> conn.closeHandler(v -> closed.set(true))).end();
     AsyncTestBase.assertWaitUntil(closed::get);
-    client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
       testComplete();
     }).exceptionHandler(err -> {
       fail();
@@ -321,10 +314,10 @@ public void testClientDoesNotSupportAlpn() throws Exception {
       req.response().end();
       complete();
     });
-    startServer();
+    startServer(testAddress);
     client.close();
     client = vertx.createHttpClient(createBaseClientOptions().setProtocolVersion(HttpVersion.HTTP_1_1).setUseAlpn(false));
-    client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
       assertEquals(HttpVersion.HTTP_1_1, resp.version());
       complete();
     }).exceptionHandler(this::fail).end();
@@ -341,8 +334,8 @@ public void testServerDoesNotSupportAlpn() throws Exception {
       req.response().end();
       complete();
     });
-    startServer();
-    client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    startServer(testAddress);
+    client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
       assertEquals(HttpVersion.HTTP_1_1, resp.version());
       complete();
     }).exceptionHandler(this::fail).end();
@@ -354,7 +347,7 @@ public void testClientMakeRequestHttp2WithSSLWithoutAlpn() throws Exception {
     client.close();
     client = vertx.createHttpClient(createBaseClientOptions().setUseAlpn(false));
     try {
-      client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI);
+      client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI);
       fail();
     } catch (IllegalArgumentException ignore) {
       // Expected
@@ -377,9 +370,9 @@ public void testServePendingRequests() throws Exception {
         }
       }
     });
-    startServer();
+    startServer(testAddress);
     for (int i = 0;i < n;i++) {
-      client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> complete()).end();
+      client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> complete()).end();
     }
     await();
   }
@@ -396,8 +389,8 @@ public void testInitialMaxConcurrentStreamZero() throws Exception {
         conn.updateSettings(new Http2Settings().setMaxConcurrentStreams(10));
       });
     });
-    startServer();
-    client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    startServer(testAddress);
+    client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
       testComplete();
     }).connectionHandler(conn -> {
       assertEquals(10, conn.remoteSettings().getMaxConcurrentStreams());
@@ -415,14 +408,14 @@ public void testFoo() throws Exception {
       assertNull(resp.headers().get("content-length"));
       complete();
     });
-    startServer();
-    client.getNow(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    startServer(testAddress);
+    client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
       assertNull(resp.getHeader("content-length"));
       resp.bodyHandler(body -> {
         assertEquals("HelloWorld", body.toString());
         complete();
       });
-    });
+    }).end();
     await();
   }
 
@@ -431,10 +424,10 @@ public void testKeepAliveTimeout() throws Exception {
     server.requestHandler(req -> {
       req.response().end();
     });
-    startServer();
+    startServer(testAddress);
     client.close();
     client = vertx.createHttpClient(createBaseClientOptions().setHttp2KeepAliveTimeout(3).setPoolCleanerPeriod(1));
-    client.getNow(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
       long now = System.currentTimeMillis();
       resp.request().connection().closeHandler(v -> {
         long timeout = System.currentTimeMillis() - now;
@@ -445,7 +438,7 @@ public void testKeepAliveTimeout() throws Exception {
         assertTrue("Expected actual close timeout " + timeout + " to be < " + high, timeout < high);
         testComplete();
       });
-    });
+    }).end();
     await();
   }
   
@@ -466,9 +459,9 @@ public void testStreamWeightAndDependency() throws Exception {
       req.response().end();
       complete();
     });
-    startServer();
+    startServer(testAddress);
     client = vertx.createHttpClient(createBaseClientOptions().setHttp2KeepAliveTimeout(3).setPoolCleanerPeriod(1));
-    HttpClientRequest request = client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    HttpClientRequest request = client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
       assertEquals(responseStreamWeight, resp.request().getStreamPriority().getWeight());
       assertEquals(responseStreamDependency, resp.request().getStreamPriority().getDependency());
       complete();
@@ -515,9 +508,9 @@ public void testStreamWeightAndDependencyChange() throws Exception {
       req.response().end("world");
       complete();
     });
-    startServer();
+    startServer(testAddress);
     client = vertx.createHttpClient(createBaseClientOptions().setHttp2KeepAliveTimeout(3).setPoolCleanerPeriod(1));
-    HttpClientRequest request = client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    HttpClientRequest request = client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
       assertEquals(responseStreamWeight, resp.request().getStreamPriority().getWeight());
       assertEquals(responseStreamDependency, resp.request().getStreamPriority().getDependency());
       resp.streamPriorityHandler( sp -> {
@@ -569,9 +562,9 @@ public void testStreamWeightAndDependencyNoChange() throws Exception {
       req.response().end("world");
       complete();
     });
-    startServer();
+    startServer(testAddress);
     client = vertx.createHttpClient(createBaseClientOptions().setHttp2KeepAliveTimeout(3).setPoolCleanerPeriod(1));
-    HttpClientRequest request = client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    HttpClientRequest request = client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
       assertEquals(responseStreamWeight, resp.request().getStreamPriority().getWeight());
       assertEquals(responseStreamDependency, resp.request().getStreamPriority().getDependency());
       resp.streamPriorityHandler( sp -> {
@@ -606,9 +599,9 @@ public void testStreamWeightAndDependencyInheritance() throws Exception {
       req.response().end();
       complete();
     });
-    startServer();
+    startServer(testAddress);
     client = vertx.createHttpClient(createBaseClientOptions().setHttp2KeepAliveTimeout(3).setPoolCleanerPeriod(1));
-    HttpClientRequest request = client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    HttpClientRequest request = client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
       assertEquals(requestStreamWeight, resp.request().getStreamPriority().getWeight());
       assertEquals(requestStreamDependency, resp.request().getStreamPriority().getDependency());
       complete();
@@ -632,9 +625,9 @@ public void testDefaultStreamWeightAndDependency() throws Exception {
       req.response().end();
       complete();
     });
-    startServer();
+    startServer(testAddress);
     client = vertx.createHttpClient(createBaseClientOptions().setHttp2KeepAliveTimeout(3).setPoolCleanerPeriod(1));
-    HttpClientRequest request = client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    HttpClientRequest request = client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
       assertEquals(defaultStreamWeight, resp.request().getStreamPriority().getWeight());
       assertEquals(defaultStreamDependency, resp.request().getStreamPriority().getDependency());
       complete();
@@ -661,9 +654,9 @@ public void testStreamWeightAndDependencyPushPromise() throws Exception {
       req.response().end();
       complete();
     });
-    startServer();
+    startServer(testAddress);
     client = vertx.createHttpClient(createBaseClientOptions().setHttp2KeepAliveTimeout(3).setPoolCleanerPeriod(1));
-    HttpClientRequest request = client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    HttpClientRequest request = client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
       complete();
     });
     request.pushHandler(pushReq -> {
@@ -692,9 +685,9 @@ public void testStreamWeightAndDependencyInheritancePushPromise() throws Excepti
       req.response().end();
       complete();
     });
-    startServer();
+    startServer(testAddress);
     client = vertx.createHttpClient(createBaseClientOptions().setHttp2KeepAliveTimeout(3).setPoolCleanerPeriod(1));
-    HttpClientRequest request = client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    HttpClientRequest request = client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
       complete();
     });
     request.pushHandler(pushReq -> {
diff --git a/src/test/java/io/vertx/core/http/HttpTest.java b/src/test/java/io/vertx/core/http/HttpTest.java
--- a/src/test/java/io/vertx/core/http/HttpTest.java
+++ b/src/test/java/io/vertx/core/http/HttpTest.java
@@ -56,11 +56,17 @@ public abstract class HttpTest extends HttpTestBase {
   public TemporaryFolder testFolder = new TemporaryFolder();
 
   protected File testDir;
+  private File tmp;
 
   @Override
   public void setUp() throws Exception {
     super.setUp();
     testDir = testFolder.newFolder();
+    if (USE_DOMAIN_SOCKETS) {
+      assertTrue("Native transport not enabled", USE_NATIVE_TRANSPORT);
+      tmp = TestUtils.tmpFile(".sock");
+      testAddress = SocketAddress.domainSocketAddress(tmp.getAbsolutePath());
+    }
   }
 
   protected HttpServerOptions createBaseServerOptions() {
@@ -92,8 +98,8 @@ public void testClientRequestArguments() throws Exception {
   public void testClientChaining() {
     server.requestHandler(noOpHandler());
 
-    server.listen(onSuccess(server -> {
-      HttpClientRequest req = client.request(HttpMethod.PUT, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, noOpHandler());
+    server.listen(testAddress, onSuccess(server -> {
+      HttpClientRequest req = client.request(HttpMethod.PUT, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, noOpHandler());
       assertTrue(req.setChunked(true) == req);
       assertTrue(req.sendHead() == req);
       assertTrue(req.write("foo", "UTF-8") == req);
@@ -131,18 +137,16 @@ public void testListenSocketAddress() {
   public void testListenDomainSocketAddress() throws Exception {
     Vertx vx = Vertx.vertx(new VertxOptions().setPreferNativeTransport(true));
     Assume.assumeTrue("Native transport must be enabled", vx.isNativeTransportEnabled());
-    NetClient netClient = vx.createNetClient();
-    HttpServer httpserver = vx.createHttpServer().requestHandler(req -> req.response().end());
+    HttpServer httpserver = vx.createHttpServer(createBaseServerOptions()).requestHandler(req -> req.response().end());
     File sockFile = TestUtils.tmpFile(".sock");
     SocketAddress sockAddress = SocketAddress.domainSocketAddress(sockFile.getAbsolutePath());
     httpserver.listen(sockAddress, onSuccess(server -> {
-      netClient.connect(sockAddress, onSuccess(sock -> {
-        sock.handler(buf -> {
-          assertTrue("Response is not an http 200", buf.toString("UTF-8").startsWith("HTTP/1.1 200 OK"));
-          testComplete();
-        });
-        sock.write("GET / HTTP/1.1\r\n\r\n");
-      }));
+      client.request(HttpMethod.GET, sockAddress, new RequestOptions()
+        .setHost(DEFAULT_HTTP_HOST).setPort(DEFAULT_HTTP_PORT).setURI(DEFAULT_TEST_URI), resp -> {
+          resp.endHandler(v -> {
+            testComplete();
+          });
+      }).end();
     }));
 
     try {
@@ -154,7 +158,7 @@ public void testListenDomainSocketAddress() throws Exception {
 
 
   @Test
-  public void testLowerCaseHeaders() {
+  public void testLowerCaseHeaders() throws Exception {
     server.requestHandler(req -> {
       assertEquals("foo", req.headers().get("Foo"));
       assertEquals("foo", req.headers().get("foo"));
@@ -175,8 +179,8 @@ public void testLowerCaseHeaders() {
       req.response().end();
     });
 
-    server.listen(onSuccess(server -> {
-      HttpClientRequest req = client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    server.listen(testAddress, onSuccess(server -> {
+      HttpClientRequest req = client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
         assertEquals("quux", resp.headers().get("Quux"));
         assertEquals("quux", resp.headers().get("quux"));
         assertEquals("quux", resp.headers().get("qUUX"));
@@ -293,8 +297,8 @@ public void testPutHeadersOnRequest() {
       assertEquals("bar", req.getHeader("foo"));
       req.response().end();
     });
-    server.listen(onSuccess(server -> {
-      client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    server.listen(testAddress, onSuccess(server -> {
+      client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
         assertEquals(200, resp.statusCode());
         testComplete();
       }).putHeader("foo", "bar").end();
@@ -309,8 +313,8 @@ public void testPutHeaderReplacesPreviousHeaders() throws Exception {
         .putHeader("Location", "http://example1.org")
         .putHeader("location", "http://example2.org")
         .end());
-    server.listen(onSuccess(server -> {
-      client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    server.listen(testAddress, onSuccess(server -> {
+      client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
         assertEquals(singletonList("http://example2.org"), resp.headers().getAll("LocatioN"));
         testComplete();
        }).end();
@@ -446,9 +450,9 @@ private void testSimpleRequest(String uri, HttpMethod method, boolean absolute,
     boolean ssl = this instanceof Http2Test;
     HttpClientRequest req;
     if (absolute) {
-      req = client.requestAbs(method, (ssl ? "https://" : "http://") + DEFAULT_HTTP_HOST + ":" + DEFAULT_HTTP_PORT + uri, handler);
+      req = client.requestAbs(method, testAddress, (ssl ? "https://" : "http://") + DEFAULT_HTTP_HOST + ":" + DEFAULT_HTTP_PORT + uri, handler);
     } else {
-      req = client.request(method, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, uri, handler);
+      req = client.request(method, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, uri, handler);
     }
     testSimpleRequest(uri, method, req, absolute);
   }
@@ -474,7 +478,7 @@ private void testSimpleRequest(String uri, HttpMethod method, HttpClientRequest
       req.response().end();
     });
 
-    server.listen(onSuccess(server -> request.end()));
+    server.listen(testAddress, onSuccess(server -> request.end()));
 
     await();
   }
@@ -488,8 +492,8 @@ public void testServerChaining() {
       testComplete();
     });
 
-    server.listen(onSuccess(server -> {
-      client.request(HttpMethod.PUT, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, noOpHandler()).end();
+    server.listen(testAddress, onSuccess(server -> {
+      client.request(HttpMethod.PUT, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, noOpHandler()).end();
     }));
 
     await();
@@ -505,8 +509,8 @@ public void testServerChainingSendFile() throws Exception {
       testComplete();
     });
 
-    server.listen(onSuccess(server -> {
-      client.request(HttpMethod.PUT, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, noOpHandler()).end();
+    server.listen(testAddress, onSuccess(server -> {
+      client.request(HttpMethod.PUT, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, noOpHandler()).end();
     }));
 
     await();
@@ -528,8 +532,8 @@ public void testResponseEndHandlers1() {
         complete();
       });
       req.response().end();
-    }).listen(onSuccess(server -> {
-      client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", res -> {
+    }).listen(testAddress, onSuccess(server -> {
+      client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", res -> {
         assertEquals(200, res.statusCode());
         assertEquals("wibble", res.headers().get("extraheader"));
         complete();
@@ -555,8 +559,8 @@ public void testResponseEndHandlers2() {
         complete();
       });
       req.response().end(content);
-    }).listen(onSuccess(server -> {
-      client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", res -> {
+    }).listen(testAddress, onSuccess(server -> {
+      client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", res -> {
         assertEquals(200, res.statusCode());
         assertEquals("wibble", res.headers().get("extraheader"));
         res.bodyHandler(buff -> {
@@ -592,8 +596,8 @@ public void testResponseEndHandlersChunkedResponse() {
       IntStream.range(0, numChunks - 1).forEach(x -> req.response().write(chunk));
       // End with a chunk to ensure size is correctly calculated
       req.response().end(chunk);
-    }).listen(onSuccess(server -> {
-      client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", res -> {
+    }).listen(testAddress, onSuccess(server -> {
+      client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", res -> {
         assertEquals(200, res.statusCode());
         assertEquals("wibble", res.headers().get("extraheader"));
         res.bodyHandler(buff -> {
@@ -623,8 +627,8 @@ public void testResponseEndHandlersSendFile() throws Exception {
         complete();
       });
       req.response().sendFile(toSend.getAbsolutePath());
-    }).listen(onSuccess(server -> {
-      client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", res -> {
+    }).listen(testAddress, onSuccess(server -> {
+      client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", res -> {
         assertEquals(200, res.statusCode());
         assertEquals("wibble", res.headers().get("extraheader"));
         res.bodyHandler(buff -> {
@@ -668,8 +672,8 @@ private void testURIAndPath(String uri, String path) {
       req.response().end();
     });
 
-    server.listen(onSuccess(server -> {
-      client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, uri, resp -> testComplete()).end();
+    server.listen(testAddress, onSuccess(server -> {
+      client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, uri, resp -> testComplete()).end();
     }));
 
     await();
@@ -716,8 +720,8 @@ private void testParamDecoding(String value) throws UnsupportedEncodingException
       req.response().end();
     });
     String postData = "param=" + URLEncoder.encode(value,"UTF-8");
-    server.listen(onSuccess(server -> {
-      client.post(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/")
+    server.listen(testAddress, onSuccess(server -> {
+      client.request(HttpMethod.POST, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", resp -> testComplete())
           .putHeader(HttpHeaders.CONTENT_TYPE, HttpHeaders.APPLICATION_X_WWW_FORM_URLENCODED)
           .putHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(postData.length()))
           .handler(resp -> {
@@ -742,7 +746,6 @@ public void testParamsSemiColon() {
   private void testParams(char delim) {
     Map<String, String> params = genMap(10);
     String query = generateQueryString(params, delim);
-
     server.requestHandler(req -> {
       assertEquals(query, req.query());
       assertEquals(params.size(), req.params().size());
@@ -752,8 +755,8 @@ private void testParams(char delim) {
       req.response().end();
     });
 
-    server.listen(onSuccess(server -> {
-      client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "some-uri/?" + query, resp -> testComplete()).end();
+    server.listen(testAddress, onSuccess(server -> {
+      client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "some-uri/?" + query, resp -> testComplete()).end();
     }));
 
     await();
@@ -790,8 +793,8 @@ public void testDefaultRequestHeaders() {
       req.response().end();
     });
 
-    server.listen(onSuccess(server -> {
-      client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> testComplete()).end();
+    server.listen(testAddress, onSuccess(server -> {
+      client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> testComplete()).end();
     }));
 
     await();
@@ -814,8 +817,8 @@ public void testRequestHeadersWithCharSequence() {
       req.response().end();
     });
 
-    server.listen(onSuccess(server -> {
-      HttpClientRequest req = client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> testComplete());
+    server.listen(testAddress, onSuccess(server -> {
+      HttpClientRequest req = client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> testComplete());
 
       headers.forEach((k, v) -> req.headers().add(k, v));
 
@@ -847,8 +850,8 @@ private void testRequestHeaders(boolean individually) {
       req.response().end();
     });
 
-    server.listen(onSuccess(server -> {
-      HttpClientRequest req = client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> testComplete());
+    server.listen(testAddress, onSuccess(server -> {
+      HttpClientRequest req = client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> testComplete());
       if (individually) {
         for (Map.Entry<String, String> header : headers) {
           req.headers().add(header.getKey(), header.getValue());
@@ -886,8 +889,8 @@ private void testResponseHeaders(boolean individually) {
       req.response().end();
     });
 
-    server.listen(onSuccess(server -> {
-      client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    server.listen(testAddress, onSuccess(server -> {
+      client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
         assertTrue(headers.size() < resp.headers().size());
         for (Map.Entry<String, String> entry : headers) {
           assertEquals(entry.getValue(), resp.headers().get(entry.getKey()));
@@ -912,8 +915,8 @@ public void testResponseHeadersWithCharSequence() {
       req.response().end();
     });
 
-    server.listen(onSuccess(server -> {
-      client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    server.listen(testAddress, onSuccess(server -> {
+      client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
         assertTrue(headers.size() < resp.headers().size());
 
         headers.forEach((k,v) -> assertEquals(v, resp.headers().get(k)));
@@ -963,8 +966,8 @@ private void testResponseMultipleSetCookie(boolean inHeader, boolean inTrailer)
       req.response().end();
     });
 
-    server.listen(onSuccess(server -> {
-      client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    server.listen(testAddress, onSuccess(server -> {
+      client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
         resp.endHandler(v -> {
           assertEquals(cookies.size(), resp.cookies().size());
           for (int i = 0; i < cookies.size(); ++i) {
@@ -982,8 +985,8 @@ private void testResponseMultipleSetCookie(boolean inHeader, boolean inTrailer)
   public void testUseRequestAfterComplete() {
     server.requestHandler(noOpHandler());
 
-    server.listen(onSuccess(server -> {
-      HttpClientRequest req = client.request(HttpMethod.POST, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, noOpHandler());
+    server.listen(testAddress, onSuccess(server -> {
+      HttpClientRequest req = client.request(HttpMethod.POST, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, noOpHandler());
       req.end();
 
       Buffer buff = Buffer.buffer();
@@ -1016,8 +1019,8 @@ public void testRequestBodyBufferAtEnd() {
       req.response().end();
     }));
 
-    server.listen(onSuccess(server -> {
-      client.request(HttpMethod.POST, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> testComplete()).end(body);
+    server.listen(testAddress, onSuccess(server -> {
+      client.request(HttpMethod.POST, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> testComplete()).end(body);
     }));
 
     await();
@@ -1055,8 +1058,8 @@ private void testRequestBodyStringAtEnd(String encoding) {
       });
     });
 
-    server.listen(onSuccess(server -> {
-      HttpClientRequest req = client.request(HttpMethod.POST, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, noOpHandler());
+    server.listen(testAddress, onSuccess(server -> {
+      HttpClientRequest req = client.request(HttpMethod.POST, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, noOpHandler());
       if (encoding == null) {
         req.end(body);
       } else {
@@ -1087,8 +1090,8 @@ private void testRequestBodyWrite(boolean chunked) {
       });
     });
 
-    server.listen(onSuccess(server -> {
-      HttpClientRequest req = client.request(HttpMethod.POST, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> testComplete());
+    server.listen(testAddress, onSuccess(server -> {
+      HttpClientRequest req = client.request(HttpMethod.POST, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> testComplete());
       int numWrites = 10;
       int chunkSize = 100;
 
@@ -1155,8 +1158,8 @@ private void testRequestBodyWriteString(boolean chunked, String encoding) {
       });
     });
 
-    server.listen(onSuccess(server -> {
-      HttpClientRequest req = client.request(HttpMethod.POST, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, noOpHandler());
+    server.listen(testAddress, onSuccess(server -> {
+      HttpClientRequest req = client.request(HttpMethod.POST, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, noOpHandler());
 
       if (chunked) {
         req.setChunked(true);
@@ -1189,8 +1192,8 @@ public void testRequestWrite() {
         testComplete();
       });
     });
-    server.listen(onSuccess(s -> {
-      HttpClientRequest req = client.request(HttpMethod.POST, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, noOpHandler());
+    server.listen(testAddress, onSuccess(s -> {
+      HttpClientRequest req = client.request(HttpMethod.POST, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, noOpHandler());
       req.setChunked(true);
       int padding = 5;
       for (int i = 0;i < times;i++) {
@@ -1250,7 +1253,7 @@ public void testConnectWithoutResponseHandler() throws Exception {
 
   @Test
   public void testClientExceptionHandlerCalledWhenFailingToConnect() throws Exception {
-    client.request(HttpMethod.GET, 9998, "255.255.255.255", DEFAULT_TEST_URI, resp -> fail("Connect should not be called")).
+    client.request(HttpMethod.GET, testAddress, 9998, "255.255.255.255", DEFAULT_TEST_URI, resp -> fail("Connect should not be called")).
         exceptionHandler(error -> testComplete()).
         endHandler(done -> fail()).
         end();
@@ -1260,17 +1263,17 @@ public void testClientExceptionHandlerCalledWhenFailingToConnect() throws Except
   @Test
   public void testClientExceptionHandlerCalledWhenServerTerminatesConnection() throws Exception {
     int numReqs = 10;
-    CountDownLatch latch = new CountDownLatch(numReqs);
+    waitFor(numReqs);
     server.requestHandler(request -> {
       request.response().close();
-    }).listen(DEFAULT_HTTP_PORT, onSuccess(s -> {
+    }).listen(testAddress, onSuccess(s -> {
       // Exception handler should be called for any requests in the pipeline if connection is closed
       for (int i = 0; i < numReqs; i++) {
-        client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> fail("Connect should not be called")).
-            exceptionHandler(error -> latch.countDown()).endHandler(done -> fail()).end();
+        client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> fail("Connect should not be called")).
+            exceptionHandler(error -> complete()).endHandler(done -> fail()).end();
       }
     }));
-    awaitLatch(latch);
+    await();
   }
 
   @Test
@@ -1278,9 +1281,9 @@ public void testClientExceptionHandlerCalledWhenServerTerminatesConnectionAfterP
     server.requestHandler(request -> {
       //Write partial response then close connection before completing it
       request.response().setChunked(true).write("foo").close();
-    }).listen(DEFAULT_HTTP_PORT, onSuccess(s -> {
+    }).listen(testAddress, onSuccess(s -> {
       // Exception handler should be called for any requests in the pipeline if connection is closed
-      client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp ->
+      client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp ->
           resp.exceptionHandler(t -> testComplete())).exceptionHandler(error -> fail()).end();
     }));
     await();
@@ -1290,9 +1293,15 @@ public void testClientExceptionHandlerCalledWhenServerTerminatesConnectionAfterP
   public void testClientExceptionHandlerCalledWhenExceptionOnDataHandler() throws Exception {
     server.requestHandler(request -> {
       request.response().end("foo");
-    }).listen(DEFAULT_HTTP_PORT, onSuccess(s -> {
+    }).listen(testAddress, onSuccess(s -> {
       // Exception handler should be called for any exceptions in the data handler
-      client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+      client.request(HttpMethod.GET, testAddress,  DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+        RuntimeException cause = new RuntimeException("should be caught");
+        resp.exceptionHandler(err -> {
+          if (err == cause) {
+            testComplete();
+          }
+        });
         resp.handler(data -> {
           throw new RuntimeException("should be caught");
         });
@@ -1306,9 +1315,15 @@ public void testClientExceptionHandlerCalledWhenExceptionOnDataHandler() throws
   public void testClientExceptionHandlerCalledWhenExceptionOnBodyHandler() throws Exception {
     server.requestHandler(request -> {
       request.response().end("foo");
-    }).listen(DEFAULT_HTTP_PORT, onSuccess(s -> {
+    }).listen(testAddress, onSuccess(s -> {
       // Exception handler should be called for any exceptions in the data handler
-      client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+      client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+        RuntimeException cause = new RuntimeException("should be caught");
+        resp.exceptionHandler(err -> {
+          if (err == cause) {
+            testComplete();
+          }
+        });
         resp.bodyHandler(data -> {
           throw new RuntimeException("should be caught");
         });
@@ -1324,11 +1339,11 @@ public void testNoExceptionHandlerCalledWhenResponseEnded() throws Exception {
       HttpServerResponse resp = req.response();
       req.exceptionHandler(this::fail);
       resp.exceptionHandler(err -> {
-        err.printStackTrace();
+        fail(err);
       });
       resp.end();
-    }).listen(DEFAULT_HTTP_PORT, onSuccess(s -> {
-      client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    }).listen(testAddress, onSuccess(s -> {
+      client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
         resp.endHandler(v -> {
           vertx.setTimer(100, tid -> testComplete());
         });
@@ -1377,9 +1392,9 @@ public void testServerExceptionHandlerOnClose() {
         assertEquals(1, respEndHandlerCount.get());
         testComplete();
       });
-    }).listen(DEFAULT_HTTP_PORT, ar -> {
+    }).listen(testAddress, ar -> {
       HttpClient client = vertx.createHttpClient();
-      HttpClientRequest req = client.put(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somerui", handler -> {
+      HttpClientRequest req = client.request(HttpMethod.PUT, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somerui", handler -> {
 
       }).setChunked(true);
       req.sendHead(v -> {
@@ -1397,7 +1412,7 @@ public void testClientRequestExceptionHandlerCalledWhenConnectionClosed() throws
       });
     });
     startServer();
-    HttpClientRequest req = client.post(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> {
+    HttpClientRequest req = client.request(HttpMethod.POST, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> {
       resp.handler(chunk -> {
         resp.request().connection().close();
       });
@@ -1416,15 +1431,15 @@ public void testClientResponseExceptionHandlerCalledWhenConnectionClosed() throw
       conn.set(req.connection());
       req.response().setChunked(true).write("chunk");
     });
-    startServer();
-    client.getNow(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> {
+    startServer(testAddress);
+    client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> {
       resp.handler(buff -> {
         conn.get().close();
       });
       resp.exceptionHandler(err -> {
         testComplete();
       });
-    });
+    }).end();
     await();
   }
 
@@ -1460,8 +1475,8 @@ private void testStatusCode(int code, String statusMessage) {
       req.response().end();
     });
 
-    server.listen(onSuccess(s -> {
-      client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    server.listen(testAddress, onSuccess(s -> {
+      client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
         int theCode;
         if (code == -1) {
           // Default code - 200
@@ -1507,8 +1522,8 @@ private void testResponseTrailers(boolean individually) {
       req.response().end();
     });
 
-    server.listen(onSuccess(s -> {
-      client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    server.listen(testAddress, onSuccess(s -> {
+      client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
         resp.endHandler(v -> {
           assertEquals(trailers.size(), resp.trailers().size());
           for (Map.Entry<String, String> entry : trailers) {
@@ -1530,8 +1545,8 @@ public void testResponseNoTrailers() {
       req.response().end();
     });
 
-    server.listen(onSuccess(s -> {
-      client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    server.listen(testAddress, onSuccess(s -> {
+      client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
         resp.endHandler(v -> {
           assertTrue(resp.trailers().isEmpty());
           testComplete();
@@ -1552,8 +1567,8 @@ public void testUseResponseAfterComplete() throws Exception {
       checkHttpServerResponse(resp);
       testComplete();
     });
-    startServer();
-    client.getNow(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, noOpHandler());
+    startServer(testAddress);
+    client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, noOpHandler()).end();
     await();
   }
 
@@ -1583,8 +1598,8 @@ public void testResponseBodyBufferAtEnd() {
       req.response().end(body);
     });
 
-    server.listen(onSuccess(s -> {
-      client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    server.listen(testAddress, onSuccess(s -> {
+      client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
         resp.bodyHandler(buff -> {
           assertEquals(body, buff);
           testComplete();
@@ -1629,8 +1644,8 @@ private void testResponseBodyWrite(boolean chunked) {
       assertTrue(req.response().headWritten());
     });
 
-    server.listen(onSuccess(s -> {
-      client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    server.listen(testAddress, onSuccess(s -> {
+      client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
         resp.bodyHandler(buff -> {
           assertEquals(body, buff);
           testComplete();
@@ -1695,8 +1710,8 @@ private void testResponseBodyWriteString(boolean chunked, String encoding) {
       req.response().end();
     });
 
-    server.listen(onSuccess(s -> {
-      client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    server.listen(testAddress, onSuccess(s -> {
+      client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
         resp.bodyHandler(buff -> {
           assertEquals(bodyBuff, buff);
           testComplete();
@@ -1717,8 +1732,8 @@ public void testResponseWrite() {
       req.response().end();
     });
 
-    server.listen(onSuccess(s -> {
-      client.request(HttpMethod.POST, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    server.listen(testAddress, onSuccess(s -> {
+      client.request(HttpMethod.POST, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
         resp.bodyHandler(buff -> {
           assertEquals(body, buff);
           testComplete();
@@ -1733,14 +1748,14 @@ public void testResponseWrite() {
   public void testSendFile() throws Exception {
     String content = TestUtils.randomUnicodeString(10000);
     sendFile("test-send-file.html", content, false,
-      handler -> client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, handler));
+      handler -> client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, handler));
   }
 
   @Test
   public void testSendFileWithHandler() throws Exception {
     String content = TestUtils.randomUnicodeString(10000);
     sendFile("test-send-file.html", content, true,
-      handler -> client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, handler));
+      handler -> client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, handler));
   }
 
   @Test
@@ -1748,7 +1763,7 @@ public void testSendFileWithConnectionCloseHeader() throws Exception {
     String content = TestUtils.randomUnicodeString(1024 * 1024 * 2);
     sendFile("test-send-file.html", content, false,
       handler -> client
-        .get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, handler)
+        .request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, handler)
         .putHeader(HttpHeaders.CONNECTION, "close"));
   }
 
@@ -1764,7 +1779,7 @@ private void sendFile(String fileName, String contentExpected, boolean useHandle
         complete();
       }
     });
-    startServer();
+    startServer(testAddress);
     requestFact.apply(resp -> {
       assertEquals(200, resp.statusCode());
       assertEquals("text/html", resp.headers().get("Content-Type"));
@@ -1791,8 +1806,8 @@ public void testSendNonExistingFile() throws Exception {
       });
     });
 
-    server.listen(onSuccess(s -> {
-      client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    server.listen(testAddress, onSuccess(s -> {
+      client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
         resp.bodyHandler(buff -> {
           assertEquals("failed", buff.toString());
           testComplete();
@@ -1813,8 +1828,8 @@ public void testSendFileOverrideHeaders() throws Exception {
       req.response().sendFile(file.getAbsolutePath());
     });
 
-    server.listen(onSuccess(s -> {
-      client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    server.listen(testAddress, onSuccess(s -> {
+      client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
         assertEquals(file.length(), Long.parseLong(resp.headers().get("content-length")));
         assertEquals("wibble", resp.headers().get("content-type"));
         resp.bodyHandler(buff -> {
@@ -1837,7 +1852,7 @@ public void testSendFileNotFound() throws Exception {
     });
 
     server.listen(onSuccess(s -> {
-      client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+      client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
         fail("Should not receive response");
       }).end();
       vertx.setTimer(100, tid -> testComplete());
@@ -1857,8 +1872,8 @@ public void testSendFileNotFoundWithHandler() throws Exception {
       }));
     });
 
-    server.listen(onSuccess(s -> {
-      client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    server.listen(testAddress, onSuccess(s -> {
+      client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
         fail("Should not receive response");
       }).end();
     }));
@@ -1879,8 +1894,8 @@ public void testSendFileDirectoryWithHandler() throws Exception {
       }));
     });
 
-    server.listen(onSuccess(s -> {
-      client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    server.listen(testAddress, onSuccess(s -> {
+      client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
         fail("Should not receive response");
       }).end();
     }));
@@ -1890,10 +1905,10 @@ public void testSendFileDirectoryWithHandler() throws Exception {
 
   @Test
   public void testSendOpenRangeFileFromClasspath() {
-    vertx.createHttpServer(new HttpServerOptions().setPort(8080)).requestHandler(res -> {
+    server.requestHandler(res -> {
       res.response().sendFile("webroot/somefile.html", 6);
-    }).listen(onSuccess(res -> {
-      vertx.createHttpClient(new HttpClientOptions()).request(HttpMethod.GET, 8080, "localhost", "/", resp -> {
+    }).listen(testAddress, onSuccess(res -> {
+      client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
         resp.bodyHandler(buff -> {
           assertTrue(buff.toString().startsWith("<body>blah</body></html>"));
           testComplete();
@@ -1905,10 +1920,10 @@ public void testSendOpenRangeFileFromClasspath() {
 
   @Test
   public void testSendRangeFileFromClasspath() {
-    vertx.createHttpServer(new HttpServerOptions().setPort(8080)).requestHandler(res -> {
+    server.requestHandler(res -> {
       res.response().sendFile("webroot/somefile.html", 6, 6);
-    }).listen(onSuccess(res -> {
-      vertx.createHttpClient(new HttpClientOptions()).request(HttpMethod.GET, 8080, "localhost", "/", resp -> {
+    }).listen(testAddress, onSuccess(res -> {
+      client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
         resp.bodyHandler(buff -> {
           assertEquals("<body>", buff.toString());
           testComplete();
@@ -1919,7 +1934,7 @@ public void testSendRangeFileFromClasspath() {
   }
 
   @Test
-  public void test100ContinueHandledAutomatically() throws Exception {
+  public void test100ContinueHandledAutomatically() {
     Buffer toSend = TestUtils.randomBuffer(1000);
 
     server.requestHandler(req -> {
@@ -1929,8 +1944,8 @@ public void test100ContinueHandledAutomatically() throws Exception {
       });
     });
 
-    server.listen(onSuccess(s -> {
-      HttpClientRequest req = client.request(HttpMethod.PUT, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    server.listen(testAddress, onSuccess(s -> {
+      HttpClientRequest req = client.request(HttpMethod.PUT, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
         resp.endHandler(v -> testComplete());
       });
       req.headers().set("Expect", "100-continue");
@@ -1946,7 +1961,7 @@ public void test100ContinueHandledAutomatically() throws Exception {
   }
 
   @Test
-  public void test100ContinueHandledManually() throws Exception {
+  public void test100ContinueHandledManually() {
 
     server.close();
     server = vertx.createHttpServer(createBaseServerOptions());
@@ -1961,8 +1976,8 @@ public void test100ContinueHandledManually() throws Exception {
       });
     });
 
-    server.listen(onSuccess(s -> {
-      HttpClientRequest req = client.request(HttpMethod.PUT, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    server.listen(testAddress, onSuccess(s -> {
+      HttpClientRequest req = client.request(HttpMethod.PUT, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
         resp.endHandler(v -> testComplete());
       });
       req.headers().set("Expect", "100-continue");
@@ -1978,7 +1993,7 @@ public void test100ContinueHandledManually() throws Exception {
   }
 
   @Test
-  public void test100ContinueRejectedManually() throws Exception {
+  public void test100ContinueRejectedManually() {
 
     server.close();
     server = vertx.createHttpServer(createBaseServerOptions());
@@ -1990,8 +2005,8 @@ public void test100ContinueRejectedManually() throws Exception {
       });
     });
 
-    server.listen(onSuccess(s -> {
-      HttpClientRequest req = client.request(HttpMethod.PUT, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    server.listen(testAddress, onSuccess(s -> {
+      HttpClientRequest req = client.request(HttpMethod.PUT, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
         assertEquals(405, resp.statusCode());
         testComplete();
       });
@@ -2009,7 +2024,7 @@ public void test100ContinueRejectedManually() throws Exception {
   @Test
   public void testClientDrainHandler() {
     pausingServer(resumeFuture -> {
-      HttpClientRequest req = client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, noOpHandler());
+      HttpClientRequest req = client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, noOpHandler());
       req.setChunked(true);
       assertFalse(req.writeQueueFull());
       req.setWriteQueueMaxSize(1000);
@@ -2035,7 +2050,7 @@ public void testClientDrainHandler() {
   @Test
   public void testClientRequestExceptionHandlerCalledWhenExceptionOnDrainHandler() {
     pausingServer(resumeFuture -> {
-      HttpClientRequest req = client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, noOpHandler());
+      HttpClientRequest req = client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, noOpHandler());
       req.setChunked(true);
       assertFalse(req.writeQueueFull());
       req.setWriteQueueMaxSize(1000);
@@ -2080,13 +2095,13 @@ private void pausingServer(Consumer<Future<Void>> consumer) {
       });
     });
 
-    server.listen(onSuccess(s -> consumer.accept(resumeFuture)));
+    server.listen(testAddress, onSuccess(s -> consumer.accept(resumeFuture)));
   }
 
   @Test
   public void testServerDrainHandler() {
     drainingServer(resumeFuture -> {
-      client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+      client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
         resp.pause();
         resumeFuture.setHandler(ar -> resp.resume());
       }).end();
@@ -2121,7 +2136,7 @@ private void drainingServer(Consumer<Future<Void>> consumer) {
       });
     });
 
-    server.listen(onSuccess(s -> consumer.accept(resumeFuture)));
+    server.listen(testAddress, onSuccess(s -> consumer.accept(resumeFuture)));
   }
 
   @Test
@@ -2133,7 +2148,7 @@ public void testConnectionErrorsGetReportedToRequest() throws InterruptedExcepti
     CountDownLatch latch = new CountDownLatch(3);
 
     // This one should cause an error in the Client Exception handler, because it has no exception handler set specifically.
-    HttpClientRequest req1 = client.request(HttpMethod.GET, 9998, DEFAULT_HTTP_HOST, "someurl1", resp -> {
+    HttpClientRequest req1 = client.request(HttpMethod.GET, testAddress, 9998, DEFAULT_HTTP_HOST, "someurl1", resp -> {
       fail("Should never get a response on a bad port, if you see this message than you are running an http server on port 9998");
     });
 
@@ -2142,7 +2157,7 @@ public void testConnectionErrorsGetReportedToRequest() throws InterruptedExcepti
       latch.countDown();
     });
 
-    HttpClientRequest req2 = client.request(HttpMethod.GET, 9998, DEFAULT_HTTP_HOST, "someurl2", resp -> {
+    HttpClientRequest req2 = client.request(HttpMethod.GET, testAddress, 9998, DEFAULT_HTTP_HOST, "someurl2", resp -> {
       fail("Should never get a response on a bad port, if you see this message than you are running an http server on port 9998");
     });
 
@@ -2151,7 +2166,7 @@ public void testConnectionErrorsGetReportedToRequest() throws InterruptedExcepti
       latch.countDown();
     });
 
-    HttpClientRequest req3 = client.request(HttpMethod.GET, 9998, DEFAULT_HTTP_HOST, "someurl2", resp -> {
+    HttpClientRequest req3 = client.request(HttpMethod.GET, testAddress, 9998, DEFAULT_HTTP_HOST, "someurl2", resp -> {
       fail("Should never get a response on a bad port, if you see this message than you are running an http server on port 9998");
     });
 
@@ -2172,8 +2187,8 @@ public void testConnectionErrorsGetReportedToRequest() throws InterruptedExcepti
   public void testRequestTimesoutWhenIndicatedPeriodExpiresWithoutAResponseFromRemoteServer() {
     server.requestHandler(noOpHandler()); // No response handler so timeout triggers
     AtomicBoolean failed = new AtomicBoolean();
-    server.listen(onSuccess(s -> {
-      HttpClientRequest req = client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    server.listen(testAddress, onSuccess(s -> {
+      HttpClientRequest req = client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
         fail("End should not be called because the request should timeout");
       });
       req.exceptionHandler(t -> {
@@ -2215,11 +2230,11 @@ public void testRequestTimeoutCanceledWhenRequestHasAnOtherError() {
   public void testRequestTimeoutCanceledWhenRequestEndsNormally() {
     server.requestHandler(req -> req.response().end());
 
-    server.listen(onSuccess(s -> {
+    server.listen(testAddress, onSuccess(s -> {
       AtomicReference<Throwable> exception = new AtomicReference<>();
 
       // There is no server running, should fail to connect
-      HttpClientRequest req = client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, noOpHandler());
+      HttpClientRequest req = client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, noOpHandler());
       req.exceptionHandler(exception::set);
       req.setTimeout(500);
       req.end();
@@ -2244,8 +2259,8 @@ public void testHttpClientRequestTimeoutResetsTheConnection() throws Exception {
         }
       });
     });
-    startServer();
-    HttpClientRequest req = client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> fail("Response should not be handled"));
+    startServer(testAddress);
+    HttpClientRequest req = client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> fail("Response should not be handled"));
     req.exceptionHandler(err -> {
       complete();
     });
@@ -2275,10 +2290,10 @@ public void testConnectInvalidHost() {
   }
 
   @Test
-  public void testSetHandlersAfterListening() throws Exception {
+  public void testSetHandlersAfterListening() {
     server.requestHandler(noOpHandler());
 
-    server.listen(onSuccess(s -> {
+    server.listen(testAddress, onSuccess(s -> {
       assertIllegalStateException(() -> server.requestHandler(noOpHandler()));
       assertIllegalStateException(() -> server.websocketHandler(noOpHandler()));
       testComplete();
@@ -2288,47 +2303,46 @@ public void testSetHandlersAfterListening() throws Exception {
   }
 
   @Test
-  public void testSetHandlersAfterListening2() throws Exception {
+  public void testSetHandlersAfterListening2() {
     server.requestHandler(noOpHandler());
 
-    server.listen(onSuccess(v -> testComplete()));
+    server.listen(testAddress, onSuccess(v -> testComplete()));
     assertIllegalStateException(() -> server.requestHandler(noOpHandler()));
     assertIllegalStateException(() -> server.websocketHandler(noOpHandler()));
     await();
   }
 
   @Test
-  public void testListenNoHandlers() throws Exception {
+  public void testListenNoHandlers() {
     assertIllegalStateException(() -> server.listen(ar -> {
     }));
   }
 
   @Test
-  public void testListenNoHandlers2() throws Exception {
+  public void testListenNoHandlers2() {
     assertIllegalStateException(() -> server.listen());
   }
 
   @Test
-  public void testListenTwice() throws Exception {
+  public void testListenTwice() {
     server.requestHandler(noOpHandler());
-    server.listen(onSuccess(v -> testComplete()));
+    server.listen(testAddress, onSuccess(v -> testComplete()));
     assertIllegalStateException(() -> server.listen());
     await();
   }
 
   @Test
-  public void testListenTwice2() throws Exception {
+  public void testListenTwice2() {
     server.requestHandler(noOpHandler());
-    server.listen(ar -> {
-      assertTrue(ar.succeeded());
+    server.listen(testAddress, onSuccess(s -> {
       assertIllegalStateException(() -> server.listen());
       testComplete();
-    });
+    }));
     await();
   }
 
   @Test
-  public void testHeadCanSetContentLength() {
+  public void testHeadCanSetContentLength() throws Exception {
     server.requestHandler(req -> {
       assertEquals(HttpMethod.HEAD, req.method());
       // Head never contains a body but it can contain a Content-Length header
@@ -2336,14 +2350,16 @@ public void testHeadCanSetContentLength() {
       req.response().headers().set("Content-Length", String.valueOf(41));
       req.response().end();
     });
-
-    server.listen(onSuccess(s -> {
-      client.request(HttpMethod.HEAD, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
-        assertEquals("41", resp.headers().get("Content-Length"));
-        resp.endHandler(v -> testComplete());
-      }).end();
-    }));
-
+    startServer(testAddress);
+    client.request(HttpMethod.HEAD, testAddress, new RequestOptions()
+      .setHost(DEFAULT_HTTP_HOST)
+      .setPort(DEFAULT_HTTP_PORT)
+      .setURI(DEFAULT_TEST_URI), resp -> {
+      assertEquals("41", resp.headers().get("Content-Length"));
+      resp.endHandler(v -> testComplete());
+      assertEquals("41", resp.headers().get("Content-Length"));
+      resp.endHandler(v -> testComplete());
+    }).end();
     await();
   }
 
@@ -2438,10 +2454,10 @@ protected MultiMap checkEmptyHttpResponse(HttpMethod method, int sc, MultiMap re
       resp.headers().addAll(reqHeaders);
       resp.end();
     });
-    startServer();
+    startServer(testAddress);
     try {
       CompletableFuture<MultiMap> result = new CompletableFuture<>();
-      client.request(method, DEFAULT_HTTP_PORT, DEFAULT_HTTPS_HOST, "/", resp -> {
+      client.request(method, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTPS_HOST, "/", resp -> {
         Buffer body = Buffer.buffer();
         resp.exceptionHandler(result::completeExceptionally);
         resp.handler(body::appendBuffer);
@@ -2469,8 +2485,8 @@ public void testHeadHasNoContentLengthByDefault() {
       req.response().end();
     });
 
-    server.listen(onSuccess(s -> {
-      client.request(HttpMethod.HEAD, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    server.listen(testAddress, onSuccess(s -> {
+      client.request(HttpMethod.HEAD, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
         assertNull(resp.headers().get(HttpHeaders.CONTENT_LENGTH));
         resp.endHandler(v -> testComplete());
       }).end();
@@ -2488,8 +2504,8 @@ public void testHeadButCanSetContentLength() {
       req.response().putHeader(HttpHeaders.CONTENT_LENGTH, "41").end();
     });
 
-    server.listen(onSuccess(s -> {
-      client.request(HttpMethod.HEAD, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    server.listen(testAddress, onSuccess(s -> {
+      client.request(HttpMethod.HEAD, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
         assertEquals("41", resp.headers().get(HttpHeaders.CONTENT_LENGTH));
         resp.endHandler(v -> testComplete());
       }).end();
@@ -2501,12 +2517,16 @@ public void testHeadButCanSetContentLength() {
   @Test
   public void testRemoteAddress() {
     server.requestHandler(req -> {
-      assertEquals("127.0.0.1", req.remoteAddress().host());
+      if (testAddress.host() != null) {
+        assertEquals("127.0.0.1", req.remoteAddress().host());
+      } else {
+        // Returns null for domain sockets
+      }
       req.response().end();
     });
 
-    server.listen(onSuccess(s -> {
-      client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> resp.endHandler(v -> testComplete())).end();
+    server.listen(testAddress, onSuccess(s -> {
+      client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> resp.endHandler(v -> testComplete())).end();
     }));
 
     await();
@@ -2519,8 +2539,8 @@ public void testGetAbsoluteURI() {
       req.response().end();
     });
 
-    server.listen(onSuccess(s -> {
-      client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/foo/bar", resp -> resp.endHandler(v -> testComplete())).end();
+    server.listen(testAddress, onSuccess(s -> {
+      client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/foo/bar", resp -> resp.endHandler(v -> testComplete())).end();
     }));
 
     await();
@@ -2550,8 +2570,8 @@ public void testPauseResumeClientResponseWontCallEndHandlePrematurely() throws E
     server.requestHandler(req -> {
       req.response().end(expected);
     });
-    startServer();
-    client.getNow(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    startServer(testAddress);
+    client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
       resp.bodyHandler(body -> {
         assertEquals(expected, body);
         testComplete();
@@ -2559,7 +2579,7 @@ public void testPauseResumeClientResponseWontCallEndHandlePrematurely() throws E
       // Check that pause resume won't call the end handler prematurely
       resp.pause();
       resp.resume();
-    });
+    }).end();
     await();
   }
 
@@ -2578,7 +2598,7 @@ public void testPauseClientResponse() {
 
     AtomicBoolean paused = new AtomicBoolean();
     Buffer totBuff = Buffer.buffer();
-    HttpClientRequest clientRequest = client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    HttpClientRequest clientRequest = client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
       resp.pause();
       paused.set(true);
       resp.handler(chunk -> {
@@ -2602,7 +2622,7 @@ public void testPauseClientResponse() {
       });
     });
 
-    server.listen(onSuccess(s -> clientRequest.end()));
+    server.listen(testAddress, onSuccess(s -> clientRequest.end()));
 
     await();
   }
@@ -2646,12 +2666,12 @@ private void testDeliverPausedBufferWhenResume(Consumer<Runnable> scheduler) thr
       });
       resp.setChunked(true).write(data);
     });
-    startServer();
+    startServer(testAddress);
     client.close();
     client = vertx.createHttpClient(createBaseClientOptions().setMaxPoolSize(1).setKeepAlive(true));
     for (int i = 0;i < num;i++) {
       int idx = i;
-      client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/" + i, resp -> {
+      client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/" + i, resp -> {
         Buffer body = Buffer.buffer();
         Thread t = Thread.currentThread();
         resp.handler(buff -> {
@@ -2678,11 +2698,11 @@ public void testClearPausedBuffersWhenResponseEnds() throws Exception {
     server.requestHandler(req -> {
       req.response().end(data);
     });
-    startServer();
+    startServer(testAddress);
     client.close();
     client = vertx.createHttpClient(createBaseClientOptions().setMaxPoolSize(1).setKeepAlive(true));
     for (int i = 0;i < num;i++) {
-      client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+      client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
         resp.bodyHandler(buff -> {
           assertEquals(data, buff);
           complete();
@@ -2717,8 +2737,8 @@ public void testPausedHttpServerRequest() throws Exception {
         req.response().end();
       });
     });
-    startServer();
-    HttpClientRequest req = client.put(DEFAULT_HTTP_PORT, DEFAULT_HTTPS_HOST, DEFAULT_TEST_URI, resp -> {
+    startServer(testAddress);
+    HttpClientRequest req = client.request(HttpMethod.PUT, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTPS_HOST, DEFAULT_TEST_URI, resp -> {
       resp.endHandler(v -> {
         testComplete();
       });
@@ -2768,10 +2788,10 @@ private void testHttpServerRequestPausedDuringLastChunk(boolean fetching) throws
         req.response().end();
       });
     });
-    startServer();
+    startServer(testAddress);
     client.close();
     client = vertx.createHttpClient(createBaseClientOptions().setMaxPoolSize(1));
-    client.put(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/someuri", resp -> {
+    client.request(HttpMethod.PUT, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/someuri", resp -> {
       complete();
     }).end("small");
     await();
@@ -2791,10 +2811,10 @@ private void testHttpClientResponsePausedDuringLastChunk(boolean fetching) throw
     server.requestHandler(req -> {
       req.response().end("small");
     });
-    startServer();
+    startServer(testAddress);
     client.close();
     client = vertx.createHttpClient(createBaseClientOptions().setMaxPoolSize(1));
-    client.getNow(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/someuri", resp -> {
+    client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/someuri", resp -> {
       AtomicBoolean ended = new AtomicBoolean();
       AtomicBoolean paused = new AtomicBoolean();
       resp.handler(buff -> {
@@ -2816,91 +2836,91 @@ private void testHttpClientResponsePausedDuringLastChunk(boolean fetching) throw
         ended.set(true);
         complete();
       });
-    });
+    }).end();
     await();
   }
 
   @Test
-  public void testFormUploadEmptyFile() throws Exception {
+  public void testFormUploadEmptyFile() {
     testFormUploadFile("", false, false);
   }
 
   @Test
-  public void testFormUploadSmallFile() throws Exception {
+  public void testFormUploadSmallFile() {
     testFormUploadFile(TestUtils.randomAlphaString(100), false, false);
   }
 
   @Test
-  public void testFormUploadMediumFile() throws Exception {
+  public void testFormUploadMediumFile() {
     testFormUploadFile(TestUtils.randomAlphaString(20000), false, false);
   }
 
   @Test
-  public void testFormUploadLargeFile() throws Exception {
+  public void testFormUploadLargeFile() {
     testFormUploadFile(TestUtils.randomAlphaString(4 * 1024 * 1024), false, false);
   }
 
   @Test
-  public void testFormUploadEmptyFileStreamToDisk() throws Exception {
+  public void testFormUploadEmptyFileStreamToDisk() {
     testFormUploadFile("", true, false);
   }
 
   @Test
-  public void testFormUploadSmallFileStreamToDisk() throws Exception {
+  public void testFormUploadSmallFileStreamToDisk() {
     testFormUploadFile(TestUtils.randomAlphaString(100), true, false);
   }
 
   @Test
-  public void testFormUploadMediumFileStreamToDisk() throws Exception {
+  public void testFormUploadMediumFileStreamToDisk() {
     testFormUploadFile(TestUtils.randomAlphaString(20 * 1024), true, false);
   }
 
   @Test
-  public void testFormUploadLargeFileStreamToDisk() throws Exception {
+  public void testFormUploadLargeFileStreamToDisk() {
     testFormUploadFile(TestUtils.randomAlphaString(4 * 1024 * 1024), true, false);
   }
 
   @Test
-  public void testBrokenFormUploadEmptyFile() throws Exception {
+  public void testBrokenFormUploadEmptyFile() {
     testFormUploadFile("", true, true);
   }
 
   @Test
-  public void testBrokenFormUploadSmallFile() throws Exception {
+  public void testBrokenFormUploadSmallFile() {
     testFormUploadFile(TestUtils.randomAlphaString(100), true, true);
   }
 
   @Test
-  public void testBrokenFormUploadMediumFile() throws Exception {
+  public void testBrokenFormUploadMediumFile() {
     testFormUploadFile(TestUtils.randomAlphaString(20 * 1024), true, true);
   }
 
   @Test
-  public void testBrokenFormUploadLargeFile() throws Exception {
+  public void testBrokenFormUploadLargeFile() {
     testFormUploadFile(TestUtils.randomAlphaString(4 * 1024 * 1024), true, true);
   }
 
   @Test
-  public void testBrokenFormUploadEmptyFileStreamToDisk() throws Exception {
+  public void testBrokenFormUploadEmptyFileStreamToDisk() {
     testFormUploadFile("", true, true);
   }
 
   @Test
-  public void testBrokenFormUploadSmallFileStreamToDisk() throws Exception {
+  public void testBrokenFormUploadSmallFileStreamToDisk() {
     testFormUploadFile(TestUtils.randomAlphaString(100), true, true);
   }
 
   @Test
-  public void testBrokenFormUploadMediumFileStreamToDisk() throws Exception {
+  public void testBrokenFormUploadMediumFileStreamToDisk() {
     testFormUploadFile(TestUtils.randomAlphaString(20 * 1024), true, true);
   }
 
   @Test
-  public void testBrokenFormUploadLargeFileStreamToDisk() throws Exception {
+  public void testBrokenFormUploadLargeFileStreamToDisk() {
     testFormUploadFile(TestUtils.randomAlphaString(4 * 1024 * 1024), true, true);
   }
 
-  private void testFormUploadFile(String contentStr, boolean streamToDisk, boolean abortClient) throws Exception {
+  private void testFormUploadFile(String contentStr, boolean streamToDisk, boolean abortClient) {
 
     waitFor(2);
 
@@ -2972,9 +2992,9 @@ private void testFormUploadFile(String contentStr, boolean streamToDisk, boolean
       }
     });
 
-    server.listen(onSuccess(s -> {
+    server.listen(testAddress, onSuccess(s -> {
       AtomicBoolean failed = new AtomicBoolean();
-      HttpClientRequest req = client.request(HttpMethod.POST, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/form", resp -> {
+      HttpClientRequest req = client.request(HttpMethod.POST, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/form", resp -> {
         assertFalse(abortClient);
         // assert the response
         assertEquals(200, resp.statusCode());
@@ -3015,7 +3035,7 @@ private void testFormUploadFile(String contentStr, boolean streamToDisk, boolean
   }
 
   @Test
-  public void testFormUploadAttributes() throws Exception {
+  public void testFormUploadAttributes() {
     AtomicInteger attributeCount = new AtomicInteger();
     server.requestHandler(req -> {
       if (req.method() == HttpMethod.POST) {
@@ -3037,8 +3057,8 @@ public void testFormUploadAttributes() throws Exception {
       }
     });
 
-    server.listen(onSuccess(s -> {
-      HttpClientRequest req = client.request(HttpMethod.POST, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/form", resp -> {
+    server.listen(testAddress, onSuccess(s -> {
+      HttpClientRequest req = client.request(HttpMethod.POST, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/form", resp -> {
         // assert the response
         assertEquals(200, resp.statusCode());
         resp.bodyHandler(body -> {
@@ -3063,7 +3083,7 @@ public void testFormUploadAttributes() throws Exception {
   }
 
   @Test
-  public void testFormUploadAttributes2() throws Exception {
+  public void testFormUploadAttributes2() {
     AtomicInteger attributeCount = new AtomicInteger();
     server.requestHandler(req -> {
       if (req.method() == HttpMethod.POST) {
@@ -3083,8 +3103,8 @@ public void testFormUploadAttributes2() throws Exception {
       }
     });
 
-    server.listen(onSuccess(s -> {
-      HttpClientRequest req = client.request(HttpMethod.POST, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/form", resp -> {
+    server.listen(testAddress, onSuccess(s -> {
+      HttpClientRequest req = client.request(HttpMethod.POST, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/form", resp -> {
         // assert the response
         assertEquals(200, resp.statusCode());
         resp.bodyHandler(body -> {
@@ -3110,8 +3130,8 @@ public void testHostHeaderOverridePossible() {
       req.response().end();
     });
 
-    server.listen(onSuccess(s -> {
-      HttpClientRequest req = client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> testComplete());
+    server.listen(testAddress, onSuccess(s -> {
+      HttpClientRequest req = client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> testComplete());
       req.setHost("localhost:4444");
       req.end();
     }));
@@ -3130,8 +3150,8 @@ public void testResponseBodyWriteFixedString() {
       req.response().end();
     });
 
-    server.listen(onSuccess(s -> {
-      client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    server.listen(testAddress, onSuccess(s -> {
+      client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
         resp.bodyHandler(buff -> {
           assertEquals(bodyBuff, buff);
           testComplete();
@@ -3148,11 +3168,10 @@ public void testResponseDataTimeout() {
     server.requestHandler(req -> {
       req.response().setChunked(true).write(expected);
     });
-    server.listen(onSuccess(s -> {
-      HttpClientRequest req = client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI);
+    server.listen(testAddress, onSuccess(s -> {
       Buffer received = Buffer.buffer();
-      req.handler(resp -> {
-        req.setTimeout(500);
+      HttpClientRequest req = client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+        resp.request().setTimeout(500);
         resp.handler(received::appendBuffer);
       });
       AtomicInteger count = new AtomicInteger();
@@ -3176,13 +3195,12 @@ public void testClientMultiThreaded() throws Exception {
     server.requestHandler(req -> {
       req.response().putHeader("count", req.headers().get("count"));
       req.response().end();
-    }).listen(ar -> {
-      assertTrue(ar.succeeded());
+    }).listen(testAddress, onSuccess(s -> {
       for (int i = 0; i < numThreads; i++) {
         int index = i;
         threads[i] = new Thread() {
           public void run() {
-            client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", res -> {
+            client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", res -> {
               assertEquals(200, res.statusCode());
               assertEquals(String.valueOf(index), res.headers().get("count"));
               latch.countDown();
@@ -3191,7 +3209,7 @@ public void run() {
         };
         threads[i].start();
       }
-    });
+    }));
     awaitLatch(latch);
     for (int i = 0; i < numThreads; i++) {
       threads[i].join();
@@ -3203,7 +3221,7 @@ public void testInVerticle() throws Exception {
     testInVerticle(false);
   }
 
-  private void testInVerticle(boolean worker) throws Exception {
+  private void testInVerticle(boolean worker) {
     client.close();
     server.close();
     class MyVerticle extends AbstractVerticle {
@@ -3225,14 +3243,13 @@ public void start() {
             assertSame(thr, Thread.currentThread());
           }
         });
-        server.listen(ar -> {
-          assertTrue(ar.succeeded());
+        server.listen(testAddress, onSuccess(s -> {
           assertSame(ctx, Vertx.currentContext());
           if (!worker) {
             assertSame(thr, Thread.currentThread());
           }
           client = vertx.createHttpClient(new HttpClientOptions());
-          client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", res -> {
+          client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", res -> {
             assertSame(ctx, Vertx.currentContext());
             if (!worker) {
               assertSame(thr, Thread.currentThread());
@@ -3240,7 +3257,7 @@ public void start() {
             assertEquals(200, res.statusCode());
             testComplete();
           }).end();
-        });
+        }));
       }
     }
     MyVerticle verticle = new MyVerticle();
@@ -3429,13 +3446,12 @@ public void testRequestEnded() {
         req.response().setStatusCode(200).end();
       });
     });
-    server.listen(ar -> {
-      assertTrue(ar.succeeded());
-      client.getNow(HttpTestBase.DEFAULT_HTTP_PORT, HttpTestBase.DEFAULT_HTTP_HOST, "/blah", resp -> {
+    server.listen(testAddress, onSuccess(s -> {
+      client.request(HttpMethod.GET, testAddress, HttpTestBase.DEFAULT_HTTP_PORT, HttpTestBase.DEFAULT_HTTP_HOST, "/blah", resp -> {
         assertEquals(200, resp.statusCode());
         testComplete();
-      });
-    });
+      }).end();
+    }));
     await();
   }
 
@@ -3476,12 +3492,11 @@ public void testRequestEndedNoEndHandler() {
         testComplete();
       });
     });
-    server.listen(ar -> {
-      assertTrue(ar.succeeded());
-      client.getNow(HttpTestBase.DEFAULT_HTTP_PORT, HttpTestBase.DEFAULT_HTTP_HOST, "/blah", resp -> {
+    server.listen(testAddress, onSuccess(s -> {
+      client.request(HttpMethod.GET, testAddress, HttpTestBase.DEFAULT_HTTP_PORT, HttpTestBase.DEFAULT_HTTP_HOST, "/blah", resp -> {
         assertEquals(200, resp.statusCode());
-      });
-    });
+      }).end();
+    }));
     await();
   }
 
@@ -3521,14 +3536,14 @@ public void testAbsoluteURIServer() {
       assertEquals(req.scheme() + "://localhost:8080/path", absURI);
       req.response().end();
     });
-    server.listen(onSuccess(s -> {
+    server.listen(testAddress, onSuccess(s -> {
       String host = "localhost";
       String path = "/path";
       int port = 8080;
-      client.getNow(port, host, path, resp -> {
+      client.request(HttpMethod.GET, testAddress, port, host, path, resp -> {
         assertEquals(200, resp.statusCode());
         testComplete();
-      });
+      }).end();
     }));
 
     await();
@@ -3538,26 +3553,27 @@ public void testAbsoluteURIServer() {
   public void testDumpManyRequestsOnQueue() throws Exception {
     int sendRequests = 10000;
     AtomicInteger receivedRequests = new AtomicInteger();
+    HttpClientOptions ops = createBaseClientOptions()
+      .setDefaultPort(DEFAULT_HTTP_PORT)
+      .setPipelining(true)
+      .setKeepAlive(true);
+    client.close();
+    client = vertx.createHttpClient(ops);
     vertx.createHttpServer(createBaseServerOptions()).requestHandler(r-> {
       r.response().end();
       if (receivedRequests.incrementAndGet() == sendRequests) {
         testComplete();
       }
-    }).listen(onSuccess(s -> {
-      HttpClientOptions ops = createBaseClientOptions()
-          .setDefaultPort(DEFAULT_HTTP_PORT)
-          .setPipelining(true)
-          .setKeepAlive(true);
-      HttpClient client = vertx.createHttpClient(ops);
-      IntStream.range(0, sendRequests).forEach(x -> client.getNow("/", r -> {}));
+    }).listen(testAddress, onSuccess(s -> {
+      IntStream.range(0, sendRequests).forEach(x -> client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, r -> {}).end());
     }));
     await();
   }
 
   @Test
-  public void testOtherMethodWithRawMethod() throws Exception {
+  public void testOtherMethodWithRawMethod() {
     try {
-      client.request(HttpMethod.OTHER, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> {
+      client.request(HttpMethod.OTHER, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> {
       }).end();
       fail();
     } catch (IllegalStateException expected) {
@@ -3565,13 +3581,13 @@ public void testOtherMethodWithRawMethod() throws Exception {
   }
 
   @Test
-  public void testOtherMethodRequest() throws Exception {
+  public void testOtherMethodRequest() {
     server.requestHandler(r -> {
       assertEquals(HttpMethod.OTHER, r.method());
       assertEquals("COPY", r.rawMethod());
       r.response().end();
-    }).listen(onSuccess(s -> {
-      client.request(HttpMethod.OTHER, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> {
+    }).listen(testAddress, onSuccess(s -> {
+      client.request(HttpMethod.OTHER, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> {
         testComplete();
       }).setRawMethod("COPY").end();
     }));
@@ -3597,15 +3613,13 @@ private void testClientConnectionHandler(boolean local, boolean global) throws E
     server.requestHandler(req -> {
       req.response().end();
     });
-    CountDownLatch listenLatch = new CountDownLatch(1);
-    server.listen(onSuccess(s -> listenLatch.countDown()));
-    awaitLatch(listenLatch);
+    startServer(testAddress);
     AtomicInteger status = new AtomicInteger();
     Handler<HttpConnection> handler = conn -> status.getAndIncrement();
     if (global) {
       client.connectionHandler(handler);
     }
-    HttpClientRequest req = client.post(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> {
+    HttpClientRequest req = client.request(HttpMethod.POST, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> {
       assertEquals((local ? 1 : 0) + (global ? 1 : 0), status.getAndIncrement());
       testComplete();
     });
@@ -3620,6 +3634,7 @@ private void testClientConnectionHandler(boolean local, boolean global) throws E
   public void testServerConnectionHandler() throws Exception {
     AtomicInteger status = new AtomicInteger();
     AtomicReference<HttpConnection> connRef = new AtomicReference<>();
+    Context serverCtx = vertx.getOrCreateContext();
     server.connectionHandler(conn -> {
       assertEquals(0, status.getAndIncrement());
       assertNull(connRef.getAndSet(conn));
@@ -3629,12 +3644,10 @@ public void testServerConnectionHandler() throws Exception {
       assertSame(connRef.get(), req.connection());
       req.response().end();
     });
-    CountDownLatch listenLatch = new CountDownLatch(1);
-    server.listen(onSuccess(s -> listenLatch.countDown()));
-    awaitLatch(listenLatch);
-    client.getNow(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> {
+    startServer(testAddress, serverCtx, server);
+    client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> {
       testComplete();
-    });
+    }).end();
     await();
   }
 
@@ -3653,10 +3666,8 @@ public void testClientConnectionClose() throws Exception {
         testComplete();
       });
     });
-    CountDownLatch listenLatch = new CountDownLatch(1);
-    server.listen(onSuccess(s -> listenLatch.countDown()));
-    awaitLatch(listenLatch);
-    HttpClientRequest req = client.post(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> {
+    startServer(testAddress);
+    HttpClientRequest req = client.request(HttpMethod.POST, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> {
       fail();
     });
     req.setChunked(true);
@@ -3672,10 +3683,8 @@ public void testServerConnectionClose() throws Exception {
     server.requestHandler(req -> {
       req.connection().close();
     });
-    CountDownLatch listenLatch = new CountDownLatch(1);
-    server.listen(onSuccess(s -> listenLatch.countDown()));
-    awaitLatch(listenLatch);
-    HttpClientRequest req = client.post(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> {
+    startServer(testAddress);
+    HttpClientRequest req = client.request(HttpMethod.POST, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> {
       fail();
     });
     req.connectionHandler(conn -> {
@@ -3727,10 +3736,10 @@ public void testClientLocalAddress() throws Exception {
       req.response().end();
     });
     startServer();
-    client.getNow(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> {
+    client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> {
       assertEquals(200, resp.statusCode());
       testComplete();
-    });
+    }).end();
     await();
   }
 
@@ -4316,9 +4325,9 @@ public void testEventHandlersNotHoldingLock() throws Exception {
           break;
       }
     });
-    startServer();
+    startServer(testAddress);
     for (int i = 0;i < 2;i++) {
-      client.post(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/" + i, resp -> {
+      client.request(HttpMethod.POST, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/" + i, resp -> {
         assertEquals(200, resp.statusCode());
         HttpConnection conn = resp.request().connection();
         switch (resp.request().path()) {
@@ -4385,8 +4394,8 @@ public void testEventHandlersNotHoldingLockOnClose() throws Exception {
       });
       resp.setChunked(true).write("hello");
     });
-    startServer();
-    HttpClientRequest req = client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> {
+    startServer(testAddress);
+    HttpClientRequest req = client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> {
       assertEquals(200, resp.statusCode());
       HttpConnection conn = resp.request().connection();
       resp.exceptionHandler(err -> {
@@ -4415,12 +4424,12 @@ public void testCloseHandlerWhenConnectionEnds() throws Exception {
       });
       req.response().setChunked(true).write("some-data");
     });
-    startServer();
-    client.getNow(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> {
+    startServer(testAddress);
+    client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> {
       resp.handler(v -> {
         resp.request().connection().close();
       });
-    });
+    }).end();
     await();
   }
 
@@ -4463,12 +4472,12 @@ protected void testCloseHandlerNotCalledWhenConnectionClosedAfterEnd(int expecte
       });
       req.response().end("some-data");
     });
-    startServer();
-    client.getNow(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> {
+    startServer(testAddress);
+    client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> {
       resp.endHandler(v -> {
         resp.request().connection().close();
       });
-    });
+    }).end();
     await();
   }
 
@@ -4497,11 +4506,11 @@ public void testClientDecompressionError() throws Exception {
         .putHeader("Content-Encoding", "gzip")
         .end("long response with mismatched encoding causes connection leaks");
     });
-    startServer();
+    startServer(testAddress);
     AtomicInteger exceptionCount = new AtomicInteger();
     client.close();
     client = vertx.createHttpClient(createBaseClientOptions().setTryUseCompression(true));
-    client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
       resp.exceptionHandler(err -> {
         if (exceptionCount.incrementAndGet() == 1) {
           if (err instanceof Http2Exception) {
@@ -4531,8 +4540,8 @@ public void testContainsValueString() {
       req.response().putHeader("quux", "quux");
       req.response().end();
     });
-    server.listen(onSuccess(server -> {
-      HttpClientRequest req = client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    server.listen(testAddress, onSuccess(server -> {
+      HttpClientRequest req = client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
         assertTrue(resp.headers().contains("Quux", "quux", false));
         assertFalse(resp.headers().contains("Quux", "quUx", false));
         testComplete();
@@ -4551,8 +4560,8 @@ public void testContainsValueStringIgnoreCase() {
       req.response().putHeader("quux", "quux");
       req.response().end();
     });
-    server.listen(onSuccess(server -> {
-      HttpClientRequest req = client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    server.listen(testAddress, onSuccess(server -> {
+      HttpClientRequest req = client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
         assertTrue(resp.headers().contains("Quux", "quux", true));
         assertTrue(resp.headers().contains("Quux", "quUx", true));
         testComplete();
@@ -4579,8 +4588,8 @@ public void testContainsValueCharSequence() {
       req.response().putHeader(quux, quux);
       req.response().end();
     });
-    server.listen(onSuccess(server -> {
-      HttpClientRequest req = client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    server.listen(testAddress, onSuccess(server -> {
+      HttpClientRequest req = client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
         assertTrue(resp.headers().contains(Quux, quux, false));
         assertFalse(resp.headers().contains(Quux, quUx, false));
         testComplete();
@@ -4607,8 +4616,8 @@ public void testContainsValueCharSequenceIgnoreCase() {
       req.response().putHeader(quux, quux);
       req.response().end();
     });
-    server.listen(onSuccess(server -> {
-      HttpClientRequest req = client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    server.listen(testAddress, onSuccess(server -> {
+      HttpClientRequest req = client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
         assertTrue(resp.headers().contains(Quux, quux, true));
         assertTrue(resp.headers().contains(Quux, quUx, true));
         testComplete();
@@ -4629,8 +4638,8 @@ public void testBytesReadRequest() throws Exception {
         req.response().end();
       });
     });
-    startServer();
-    client.post(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    startServer(testAddress);
+    client.request(HttpMethod.POST, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
       resp.bodyHandler(buff -> {
         testComplete();
       });
@@ -4672,14 +4681,12 @@ public void testClientSynchronousConnectFailures() {
 
   @Test
   public void testClientConnectInvalidPort() {
-    client.get(-1, "localhost", "/someuri", resp -> {
-      fail();
-    }).exceptionHandler(err -> {
-      assertEquals(err.getClass(), IllegalArgumentException.class);
-      assertEquals(err.getMessage(), "port p must be in range 0 <= p <= 65535");
-      testComplete();
-    }).end();
-    await();
+    try {
+      client.request(HttpMethod.GET, testAddress, -1, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, ar -> fail());
+    } catch (Exception e) {
+      assertEquals(e.getClass(), IllegalArgumentException.class);
+      assertEquals(e.getMessage(), "port p must be in range 0 <= p <= 65535");
+    }
   }
 
   protected File setupFile(String fileName, String content) throws Exception {
@@ -4744,8 +4751,8 @@ public void testHttpClientRequestHeadersDontContainCROrLF() throws Exception {
       });
       testComplete();
     });
-    startServer();
-    HttpClientRequest req = client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {});
+    startServer(testAddress);
+    HttpClientRequest req = client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {});
     List<BiConsumer<String, String>> list = Arrays.asList(
       req::putHeader,
       req.headers()::set,
@@ -4781,8 +4788,8 @@ public void testHttpServerResponseHeadersDontContainCROrLF() throws Exception {
       assertEquals(Collections.emptySet(), req.response().headers().names());
       req.response().end();
     });
-    startServer();
-    client.getNow(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    startServer(testAddress);
+    client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
       resp.headers().forEach(header -> {
         String name = header.getKey();
         switch (name.toLowerCase()) {
@@ -4794,7 +4801,7 @@ public void testHttpServerResponseHeadersDontContainCROrLF() throws Exception {
         }
       });
       testComplete();
-    });
+    }).end();
     await();
   }
 
@@ -4803,14 +4810,14 @@ public void testDisableIdleTimeoutInPool() throws Exception {
     server.requestHandler(req -> {
       req.response().end();
     });
-    startServer();
+    startServer(testAddress);
     client.close();
     client = vertx.createHttpClient(createBaseClientOptions()
       .setIdleTimeout(1)
       .setMaxPoolSize(1)
       .setKeepAliveTimeout(10)
     );
-    client.getNow(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
       resp.endHandler(v1 -> {
         AtomicBoolean closed = new AtomicBoolean();
         resp.request().connection().closeHandler(v2 -> {
@@ -4821,7 +4828,7 @@ public void testDisableIdleTimeoutInPool() throws Exception {
           testComplete();
         });
       });
-    });
+    }).end();
     await();
   }
 
@@ -4830,14 +4837,14 @@ public void testHttpConnect() {
     Buffer buffer = TestUtils.randomBuffer(128);
     Buffer received = Buffer.buffer();
     CompletableFuture<Void> closeSocket = new CompletableFuture<>();
-    vertx.createNetServer(new NetServerOptions().setPort(1235)).connectHandler(socket -> {
+    vertx.createNetServer(new NetServerOptions().setPort(1235).setHost("localhost")).connectHandler(socket -> {
       socket.handler(socket::write);
       closeSocket.thenAccept(v -> {
         socket.close();
       });
     }).listen(onSuccess(netServer -> {
       server.requestHandler(req -> {
-        vertx.createNetClient(new NetClientOptions()).connect(netServer.actualPort(), "localhost", onSuccess(dst -> {
+        vertx.createNetClient(new NetClientOptions()).connect(1235, "localhost", onSuccess(dst -> {
 
           req.response().setStatusCode(200);
           req.response().setStatusMessage("Connection established");
@@ -4855,8 +4862,8 @@ public void testHttpConnect() {
           });
         }));
       });
-      server.listen(onSuccess(s -> {
-        client.request(HttpMethod.CONNECT, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+      server.listen(testAddress, onSuccess(s -> {
+        client.request(HttpMethod.CONNECT, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
           assertEquals(200, resp.statusCode());
           NetSocket socket = resp.netSocket();
           socket.handler(buff -> {
@@ -4893,8 +4900,8 @@ private void testAccessNetSocketPendingResponseData(boolean pause) {
       so.write("hello");
     });
 
-    server.listen(onSuccess(s -> {
-      HttpClientRequest req = client.request(HttpMethod.CONNECT, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    server.listen(testAddress, onSuccess(s -> {
+      HttpClientRequest req = client.request(HttpMethod.CONNECT, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
         NetSocket so = resp.netSocket();
         assertNotNull(so);
         so.handler(buff -> {
@@ -4927,8 +4934,8 @@ public void testHttpInvalidConnectResponseEnded() {
         complete();
       }
     });
-    server.listen(onSuccess(s -> {
-      client.request(HttpMethod.CONNECT, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    server.listen(testAddress, onSuccess(s -> {
+      client.request(HttpMethod.CONNECT, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
         assertEquals(200, resp.statusCode());
         complete();
       }).end();
@@ -4949,8 +4956,8 @@ public void testHttpInvalidConnectResponseChunked() {
         complete();
       }
     });
-    server.listen(onSuccess(s -> {
-      client.request(HttpMethod.CONNECT, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+    server.listen(testAddress, onSuccess(s -> {
+      client.request(HttpMethod.CONNECT, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
         assertEquals(200, resp.statusCode());
         complete();
       }).end();
@@ -4959,6 +4966,27 @@ public void testHttpInvalidConnectResponseChunked() {
     await();
   }
 
+  @Test
+  public void testEndFromAnotherThread() throws Exception {
+    waitFor(2);
+    disableThreadChecks();
+    server.requestHandler(req -> {
+      req.response().endHandler(v -> {
+        complete();
+      });
+      new Thread(() -> {
+        req.response().end();
+      }).start();
+    });
+    startServer(testAddress);
+    client.request(HttpMethod.GET, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+      assertEquals(200, resp.statusCode());
+      complete();
+    }).end();
+
+    await();
+  }
+
   // This test check that ending an HttpClientRequest will not hold a lock when sending Netty messages
   // holding suck lock might deadlock when the ChannelOutboundBuffer is full and becomes drained
   // doing an HttpClientRequest reentrant during the drain
@@ -4966,10 +4994,10 @@ public void testHttpInvalidConnectResponseChunked() {
   @Test
   public void testClientRequestEndDeadlock() throws Exception {
     server.requestHandler(req -> req.endHandler(v -> req.response().end()));
-    startServer();
+    startServer(testAddress);
     Context ctx = vertx.getOrCreateContext();
     ctx.runOnContext(v1 -> {
-      HttpClientRequest request = client.post(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
+      HttpClientRequest request = client.request(HttpMethod.POST, testAddress, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> {
         resp.endHandler(v2 -> {
           testComplete();
         });
diff --git a/src/test/java/io/vertx/core/http/HttpTestBase.java b/src/test/java/io/vertx/core/http/HttpTestBase.java
--- a/src/test/java/io/vertx/core/http/HttpTestBase.java
+++ b/src/test/java/io/vertx/core/http/HttpTestBase.java
@@ -11,9 +11,11 @@
 
 package io.vertx.core.http;
 
+import io.vertx.core.AsyncResult;
 import io.vertx.core.Context;
 import io.vertx.core.Handler;
 import io.vertx.core.net.ProxyType;
+import io.vertx.core.net.SocketAddress;
 import io.vertx.test.proxy.HttpProxy;
 import io.vertx.test.proxy.SocksProxy;
 import io.vertx.test.proxy.TestProxyBase;
@@ -37,10 +39,12 @@ public class HttpTestBase extends VertxTestBase {
   protected HttpServer server;
   protected HttpClient client;
   protected TestProxyBase proxy;
+  protected SocketAddress testAddress;
 
   public void setUp() throws Exception {
     super.setUp();
     server = vertx.createHttpServer(new HttpServerOptions().setPort(DEFAULT_HTTP_PORT).setHost(DEFAULT_HTTP_HOST));
+    testAddress = SocketAddress.inetSocketAddress(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST);
   }
 
   protected void tearDown() throws Exception {
@@ -77,18 +81,39 @@ protected void startServer() throws Exception {
     startServer(vertx.getOrCreateContext());
   }
 
+  protected void startServer(SocketAddress bindAddress) throws Exception {
+    startServer(bindAddress, vertx.getOrCreateContext());
+  }
+
   protected void startServer(HttpServer server) throws Exception {
     startServer(vertx.getOrCreateContext(), server);
   }
 
+  protected void startServer(SocketAddress bindAddress, HttpServer server) throws Exception {
+    startServer(bindAddress, vertx.getOrCreateContext(), server);
+  }
+
   protected void startServer(Context context) throws Exception {
     startServer(context, server);
   }
 
+  protected void startServer(SocketAddress bindAddress, Context context) throws Exception {
+    startServer(bindAddress, context, server);
+  }
+
   protected void startServer(Context context, HttpServer server) throws Exception {
+    startServer(null, context, server);
+  }
+
+  protected void startServer(SocketAddress bindAddress, Context context, HttpServer server) throws Exception {
     CountDownLatch latch = new CountDownLatch(1);
     context.runOnContext(v -> {
-      server.listen(onSuccess(s -> latch.countDown()));
+      Handler<AsyncResult<HttpServer>> onListen = onSuccess(s -> latch.countDown());
+      if (bindAddress != null) {
+        server.listen(bindAddress, onListen);
+      } else {
+        server.listen(onListen);
+      }
     });
     awaitLatch(latch);
   }