I am new to vertx and have a few questions I'd like to ask. I am trying to build a middleware which replies to a webapp in HTTP. Before doing that, it needs to contact an old TCP server. Code is below.
- All is asynchronous... So, is it OK to access variables defined in the beginning of handlePost method (or parameters) from the client connect handler below (event loop => same thread => should be OK even if different events, and what about GC)?
- Is it right to say that the code below only works because I set a BodyHandler in the start method? Otherwise, different chunks from the same HTTP request could enter the handlePost method, producing different TCP connections to the server (one for each chunk?!).
- Do I need to gather chunks while reading the response from the TCP server? Is there a special handler for that?
- Where and how could I safely close the client connection (especially if chunks could arrive)?
- Do I need to close the Socket? If yes, where/how ?
Thanks for your help.
public class Server extends AbstractVerticle {
private final Logger logger = LoggerFactory.getLogger(Server.class);
private final Environnement env;
public Server(Environnement env) {
this.env = env;
}
@Override
public void start(Future<Void> fut) {
Router router = Router.router(vertx);
// Gather the entire body
router.route().handler(BodyHandler.create());
router.get("/").handler(this::handleGet);
// Handler paths for json
router
.post("/")
.handler(Server.this::handlePost)
.produces("application/json");
// Create the HTTP server
int port = env.getConfig().getInteger("server.port", 8888);
vertx
.createHttpServer()
.requestHandler(router::accept)
.listen(port, result -> {
if (result.succeeded()) {
fut.complete();
logger.info(String.format("Server listening at http://127.0.0.1:%s", port));
} else {
fut.fail(result.cause());
}
}
);
}
private void handleGet(RoutingContext routingContext) {
HttpServerResponse response = routingContext.response();
response.putHeader("Content-Type", "text/plain")
.end("The server is alive, welcome :)");
}
private void handlePost(RoutingContext routingContext) {
HttpServerResponse response = routingContext.response();
JsonObject action = routingContext.getBodyAsJson();
if (action == null) {
sendError(400, response);
return;
}
Buffer actionAsBuffer = Buffer.buffer(CodecUtils.encode(action));
NetClientOptions options = new NetClientOptions().setConnectTimeout(10_000);
NetClient client = vertx.createNetClient(options);
client.connect(EchoServer.PORT, "localhost", res -> {
if (res.succeeded()) { // Connected!
NetSocket socket = res.result();
socket.write(actionAsBuffer);
socket.handler(buffer -> {
Buffer result = CodecUtils.decodeAsJson(buffer);
// TODO chunked?
response.putHeader("Content-Type", "application/json").end(result);
client.close(); // TODO here?!
});
//socket.closeHandler(e -> client.close());
} else {
client.close();
logger.error(String.format("Failed to connect: %s", res.cause().getMessage()));
}
});
}
private void sendError(int statusCode, HttpServerResponse response) {
response.setStatusCode(statusCode).end();
}
}