0

I have created an API Gateway with a Web Socket on AWS. I would like to connect to it using the HttpClient provided by VertX. I am using the following code for the client verticle:

public class WebSocketClient extends AbstractVerticle {

// application address replaced by [address]
protected final String host = "[address].execute-api.us-east-1.amazonaws.com";
protected final String path = "/dev";
protected final int port = 80;
protected final String webSocketAddress = "wss://[address].execute-api.us-east-1.amazonaws.com/dev";

@Override
public void start() throws Exception {
    startClient(this.vertx);
}

protected void startClient(Vertx vertx) {
    HttpClient client = vertx.createHttpClient();
    client.webSocket(port, host, path, asyncWebSocket -> {
        if (asyncWebSocket.succeeded()) {
            WebSocket socket = asyncWebSocket.result();
            System.out.println("Successfully connected. Node closing.");
            socket.close().onFailure(throwable -> {
                throwable.printStackTrace();
            });
        } else {
            asyncWebSocket.cause().printStackTrace();

        }
    });
 }
}

The same code works when I am testing it with a VertX server running on the localhost, so I assume that it is a question of the correct WebSocketConnectionOptions.

When I try to connect to the AWS socket using the HttpClient verticle, I get a "connection refused" error. Connecting to it using wscat works without problems.

Thanks a lot for your help.

fedorSmirnov
  • 701
  • 3
  • 9
  • 19
  • Why do you need to use this VertX http client? Can you not use something more basic? – D. Richard Aug 06 '21 at 15:26
  • @D.Richard I am working on an orchestration framework for serverless function compositions. The framework is build on VertX as a backbone and I would like to extend it with the ability to use Websocket connections without introducing additional dependencies. – fedorSmirnov Aug 06 '21 at 15:53

1 Answers1

1

This question is dealing with basically the same problem. I will post the solution here just to document a straight-forward way to use AWS ApiGateway Websockets with VertX.

So, the goal is to implement a VertX WebClient connected to a deployed AWS Api WebSocket Gateway which can be reached under the WsUri "wss://[address].execute-api.us-east-1.amazonaws.com/dev" (you will have to replace [address] by the address of your ApiGateway Websocket).

Here the code to set up the WebClient, connect to the Websocket, print out a success message, and then disconnect again:

public class WebSocketClient extends AbstractVerticle {

protected final String webSocketUrl = "wss://[address].execute-api.us-east-1.amazonaws.com/dev"    

protected final String host = "[address].execute-api.us-east-1.amazonaws.com";
protected final String path = "/dev";
protected final int sslPort = 443;


@Override
public void start() throws Exception {
    startClient(this.vertx);
}

protected void startClient(Vertx vertx) {
    HttpClient client = vertx
            .createHttpClient(new 
HttpClientOptions().setDefaultHost(host).setDefaultPort(sslPort).setSsl(true));

    // connect to the web socket
    client.webSocket(path, asyncWebSocket -> {            
        if (asyncWebSocket.succeeded()) {
            // executed on a successful connection
            WebSocket socket = asyncWebSocket.result(); // use this for further communication                
            System.out.println("Successfully connected. Closing the socket.");
            // Closing the socket
            socket.close().onFailure(throwable -> {
                throwable.printStackTrace();
            });
        } else {
            // executed if the connection attempt fails
            asyncWebSocket.cause().printStackTrace();
        }
    });
}

You can use the following class to run the example:

public class PlayWebSocket {
public static void main(String[] args) throws URISyntaxException{
    Vertx vertx = Vertx.vertx();
    WebSocketClient clientVerticle = new WebSocketClient();
    vertx.deployVerticle(clientVerticle);
  }
}

On the Java side, this should print the message about the successful connection and the closing of the socket. On the AWS side, the $connect and the $disconnect methods of the ApiGateway should be called. You can check this in the logs of your handler function(s) using CloudWatch.

fedorSmirnov
  • 701
  • 3
  • 9
  • 19