newbie questions for a middleware in vertx

532 views
Skip to first unread message

Nicolas Ocquidant

unread,
Mar 22, 2017, 4:43:30 PM3/22/17
to vert.x
Hello

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.
--nick

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();
}
}

Thomas SEGISMONT

unread,
Mar 23, 2017, 5:06:18 AM3/23/17
to ve...@googlegroups.com
2017-03-22 21:43 GMT+01:00 Nicolas Ocquidant <nocqu...@gmail.com>:
Hello

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)?
It's ok, as long as you don't mix client data, of course. Not sure what you mean with 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?!).

Yes. It may still incidentally work if the request body is small and received at once.
 
  • Do I need to gather chunks while reading the response from the TCP server? Is there a special handler for that?

Yes. Again, it may work if data is received at once.
  • 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 ? 

Both answers depend on your protocol. Does the server expect you to send one request per connection? Or multiplexed? In this case, is the protocol delimited by special characters? Or do messages are prefixed with a message-length. These are common patterns for proprietary TCP protocol.

 

--
You received this message because you are subscribed to the Google Groups "vert.x" group.
To unsubscribe from this group and stop receiving emails from it, send an email to vertx+unsubscribe@googlegroups.com.
Visit this group at https://groups.google.com/group/vertx.
To view this discussion on the web, visit https://groups.google.com/d/msgid/vertx/511409a1-efd7-4519-8d3a-699dad8009af%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Nicolas Ocquidant

unread,
Mar 23, 2017, 8:20:09 AM3/23/17
to vert.x
Thank you for your time, I really appreciate.

It's ok, as long as you don't mix client data, of course. Not sure what you mean with GC.

By GC I mean, for instance, the HttpServerResponse object below is referenced only from the 'response' variable. As we come later in the socker handler, are we sure HttpServerResponse will still be there? Actually, it is not a vertx question but a java one...

private void handlePost(RoutingContext routingContext) {
HttpServerResponse response = routingContext.response();
    // ...
    client.connect(EchoServer.PORT, "localhost", res -> {
if (res.succeeded()) {
            // ...
socket.handler(buffer -> {
// ...

response.putHeader("Content-Type", "application/json").end(result);
            });
}
});
}
 
Yes. Again, it may work if data is received at once.
 
OK, so I will mimic the BodyHandler to gather the message.

Both answers depend on your protocol. Does the server expect you to send one request per connection? Or multiplexed? In this case, is the protocol delimited by special characters? Or do messages are prefixed with a message-length. These are common patterns for proprietary TCP protocol.

Absolutely, first 2 chars are the length of the message. I see, after the message is complete, I will close the socket and the client.

Thanks again,
--nick

Thomas SEGISMONT

unread,
Mar 23, 2017, 11:34:03 AM3/23/17
to ve...@googlegroups.com
2017-03-23 13:20 GMT+01:00 Nicolas Ocquidant <nocqu...@gmail.com>:
Thank you for your time, I really appreciate.

You're welcome
 

It's ok, as long as you don't mix client data, of course. Not sure what you mean with GC.

By GC I mean, for instance, the HttpServerResponse object below is referenced only from the 'response' variable. As we come later in the socker handler, are we sure HttpServerResponse will still be there? Actually, it is not a vertx question but a java one...

Yes this is not related to Vert.x. Search the web for articles about lambdas, variable-capture and effectively final variables, you'll find what the answers.
 

private void handlePost(RoutingContext routingContext) {
HttpServerResponse response = routingContext.response();
    // ...
    client.connect(EchoServer.PORT, "localhost", res -> {
if (res.succeeded()) {
            // ...
socket.handler(buffer -> {
// ...
response.putHeader("Content-Type", "application/json").end(result);
});
}
});
}
 
Yes. Again, it may work if data is received at once.
 
OK, so I will mimic the BodyHandler to gather the message.

Both answers depend on your protocol. Does the server expect you to send one request per connection? Or multiplexed? In this case, is the protocol delimited by special characters? Or do messages are prefixed with a message-length. These are common patterns for proprietary TCP protocol.

Absolutely, first 2 chars are the length of the message. I see, after the message is complete, I will close the socket and the client.

Thanks again,
--nick

--
You received this message because you are subscribed to the Google Groups "vert.x" group.
To unsubscribe from this group and stop receiving emails from it, send an email to vertx+unsubscribe@googlegroups.com.
Visit this group at https://groups.google.com/group/vertx.
Reply all
Reply to author
Forward
0 new messages