Issues with vertx HTTP Proxy module

77 views
Skip to first unread message

Evaristo Camarero

unread,
Feb 12, 2024, 3:51:14 AM2/12/24
to vert.x
Hi there,

I am using HTTP vertx module, and I have encountered some issues. I wante to double check if the use of the API I am doing is wrong.

My use case requires, to proxy the request to multiple origins based on processing some headers and querying a DB in order to determine the origin. Looks to me that makes sense to delay ProxyRequest creation until I can know the origin (in case it fails the DB access)


If I delay the creation ProxyRequest, basically the proxy functionally does NOT work. 

I include a reproducer. Port 7070 used for origin, port 8080 handler shows the issue, port 9090 works because ProxyRequest is NOT delayed. 

Thanks in advance,

Evaristo

curl -X GET  -v http://localhost:8080

Example.java

package com.cheva.proxy;

import io.vertx.core.Handler;
import io.vertx.core.Vertx;
import io.vertx.core.http.HttpClient;
import io.vertx.core.http.HttpServerRequest;
import io.vertx.httpproxy.ProxyRequest;

public class Example{

  public static void main(String[] args) throws Exception {

    final Vertx vertx = Vertx.vertx();
    vertx
        .createHttpServer()
        .requestHandler(
            req -> {
              req.response()
                  .putHeader("content-type", "text/html")
                  .end("<html><body><h1>I'm the target resource!</h1></body></html>");
            })
        .listen(7070);

    final HttpClient proxyClient = vertx.createHttpClient();

    vertx.createHttpServer().requestHandler(hanldeRequestNoOk(vertx, proxyClient)).listen(8080);
    vertx.createHttpServer().requestHandler(hanldeRequestOk(vertx, proxyClient)).listen(9090);
  }

  private static Handler<HttpServerRequest> hanldeRequestOk(
      final Vertx vertx, final HttpClient proxyClient) {

    return request -> {
      ProxyRequest proxyRequest = ProxyRequest.reverseProxy(request);
      vertx
          .<Integer>executeBlocking(() -> getPort(), false)
          .onSuccess(
              port -> {
                System.out.println("XXX1 " + port);
                // ProxyRequest proxyRequest = ProxyRequest.reverseProxy(request);
                System.out.println("XXX2 " + proxyRequest);
                proxyClient
                    .request(proxyRequest.getMethod(), port, "localhost", proxyRequest.getURI())
                    .compose(
                        proxyHttpRequest -> {
                          System.out.println("XXX3");
                          return proxyRequest.send(proxyHttpRequest);
                        })
                    .onSuccess(
                        proxyResponse -> {
                          System.out.println("XXX4");
                          // Send the proxy response
                          proxyResponse.send().onFailure(err -> err.printStackTrace());
                        })
                    .onFailure(
                        err -> {
                          err.printStackTrace();
                          // Release the request
                          proxyRequest.release();
                          // Send error
                          request.response().setStatusCode(500).send();
                        });
              })
          .onFailure(err -> err.printStackTrace());
    };
  }

  private static Handler<HttpServerRequest> hanldeRequestNoOk(
      final Vertx vertx, final HttpClient proxyClient) {

    return request -> {
      vertx
          .<Integer>executeBlocking(() -> getPort(), false)
          .onSuccess(
              port -> {
                System.out.println("XXX1 " + port);
                ProxyRequest proxyRequest = ProxyRequest.reverseProxy(request);
                System.out.println("XXX2 " + proxyRequest);
                proxyClient
                    .request(proxyRequest.getMethod(), port, "localhost", proxyRequest.getURI())
                    .compose(
                        proxyHttpRequest -> {
                          System.out.println("XXX3");
                          return proxyRequest.send(proxyHttpRequest);
                        })
                    .onSuccess(
                        proxyResponse -> {
                          System.out.println("XXX4");
                          // Send the proxy response
                          proxyResponse.send().onFailure(err -> err.printStackTrace());
                        })
                    .onFailure(
                        err -> {
                          err.printStackTrace();
                          // Release the request
                          proxyRequest.release();
                          // Send error
                          request.response().setStatusCode(500).send();
                        });
              })
          .onFailure(err -> err.printStackTrace());
    };
  }

  private static Integer getPort() throws InterruptedException {
    Thread.sleep(10L);
    return 7070;
  }
}


GERARD Nicolas

unread,
Feb 14, 2024, 11:00:53 AM2/14/24
to vert.x
I don't dig into the code but a proxy is just a http client making another request.
Here a minimal example:

Evaristo Camarero

unread,
Feb 15, 2024, 2:49:32 AM2/15/24
to vert.x

Thanks Gerard.

 I have no problems understanding the functionality (my use case it is bit more elaborate that simple one). Basically the code will decide the origin getting a request header and making a query to external DB in order to pick the right origin. In order to do that, the request handler in the proxy server is composing a set of Futures (one of them access an external DB with blocking API (using vertx.executeBlocking...) in order to determine the origin that I will proxy the request)


If I delay ProxyRequest creation until DB has answered back I get this exception that hopefully can ring a bell:


java.lang.IllegalStateException: Request has already been read
            at io.vertx.core.http.impl.Http2ServerRequest.checkEnded(Http2ServerRequest.java:209) ~[vertx-core-4.5.3.jar:4.5.3]
            at io.vertx.core.http.impl.Http2ServerRequest.pause(Http2ServerRequest.java:261) ~[vertx-core-4.5.3.jar:4.5.3]
            at io.vertx.httpproxy.ProxyRequest.reverseProxy(ProxyRequest.java:41) ~[vertx-http-proxy-4.5.3.jar:4.5.3]

Regards,

 

Evaristo

GERARD Nicolas

unread,
Feb 15, 2024, 3:29:48 AM2/15/24
to vert.x
Hy Evaristo.

As far as I remember, I tried the proxy module 
when it was still in early development 
and I got also some weird behavior.

They still have a preview status

I went with an adaptation of the previous code 
adding just an extra request to handle the redirection.

May be, there was a better way to debug the proxy module and add it to our
project but my knowledge of code binding of external repos is pretty limited.

Cheers
Nico
Reply all
Reply to author
Forward
0 new messages