smallrye / smallrye-mutiny-vertx-bindings

Smallrye Mutiny bindings for Eclipse Vert.x
https://smallrye.io/smallrye-mutiny-vertx-bindings
Apache License 2.0
82 stars 25 forks source link

Generate binding from io.vertx.httproxy.ProxyInterceptor interface ? #713

Open lucaspouzac opened 1 year ago

lucaspouzac commented 1 year ago

Is it possible to generate the following interface from the io.vertx.httpproxy.ProxyInterceptor interface? Currently, it is a class that is generated and it is not easy to use ? Or another idea ?

package io.vertx.mutiny.httpproxy;

import io.vertx.codegen.annotations.VertxGen;
import io.smallrye.mutiny.Uni;

/**
 * A {@link HttpProxy} interceptor.
 */
@io.smallrye.mutiny.vertx.MutinyGen(io.vertx.httpproxy.ProxyInterceptor.class)
public interface ProxyInterceptor {

  /**
   * Handle the proxy request at the stage of this interceptor.
   *
   * @param context the proxy context
   * @return when the request has actually been sent to the origin
   */
  default Uni<io.vertx.mutiny.httpproxy.ProxyResponse> handleProxyRequest(io.vertx.mutiny.httpproxy.ProxyContext context) {
    return context.sendRequest();
  }

  /**
   * Handle the proxy response at the stage of this interceptor.
   *
   * @param context the proxy context
   * @return when the response has actually been sent to the user-agent
   */
  default Uni<Void> handleProxyResponse(io.vertx.mutiny.httpproxy.ProxyContext context) {
    return context.sendResponse();
  }
}

Example of expected use.

public class TestInterceptor implements io.vertx.mutiny.httpproxy.ProxyInterceptor {

  public Uni<io.vertx.mutiny.httpproxy.ProxyResponse> handleProxyRequest(io.vertx.mutiny.httpproxy.ProxyContext context) {
    System.out.println("handleProxyRequest");
    return context.sendRequest();
  }

  public Uni<Void> handleProxyResponse(io.vertx.mutiny.httpproxy.ProxyContext context) {
    System.out.println("handleProxyResponse");
    return context.sendResponse();
  }

}

io.vertx.mutiny.core.Vertx vertx = ...;
io.vertx.mutiny.httpproxy.HttpProxy httpProxy = io.vertx.mutiny.httpproxy.HttpProxy.reverseProxy(vertx.createHttpClient());
httpProxy.addInterceptor(new TestInterceptor());
lucaspouzac commented 1 year ago

Vertx 4.4.0 has been released with the fix. I tested the generation and an interface was correctly generated.

@io.smallrye.mutiny.vertx.MutinyGen(io.vertx.httpproxy.ProxyInterceptor.class)
public interface ProxyInterceptor {

  static final io.smallrye.mutiny.vertx.TypeArg<io.vertx.mutiny.httpproxy.ProxyResponse> TYPE_ARG_0 = new TypeArg<io.vertx.mutiny.httpproxy.ProxyResponse>(o1 -> io.vertx.mutiny.httpproxy.ProxyResponse.newInstance((io.vertx.httpproxy.ProxyResponse)o1), o1 -> o1.getDelegate());
  io.vertx.httpproxy.ProxyInterceptor getDelegate();

  /**
   * @param context the proxy context
   * @return when the request has actually been sent to the origin
   */
  public io.smallrye.mutiny.Uni<io.vertx.mutiny.httpproxy.ProxyResponse> handleProxyRequest(io.vertx.mutiny.httpproxy.ProxyContext context);

  /**
   * @param context the proxy context
   * @return when the response has actually been sent to the user-agent
   */
  public io.smallrye.mutiny.Uni<Void> handleProxyResponse(io.vertx.mutiny.httpproxy.ProxyContext context);

  public static  ProxyInterceptor newInstance(io.vertx.httpproxy.ProxyInterceptor arg) {
    return arg != null ? new ProxyInterceptorImpl(arg) : null;
  }

}

class ProxyInterceptorImpl implements ProxyInterceptor {
   ...
}

However, a getDelegate() method is generated. I had trouble understanding how one can implement this interface? Below is an example implementation that I would like to do.

import io.smallrye.mutiny.Uni;
import io.vertx.mutiny.httpproxy.ProxyContext;
import io.vertx.mutiny.httpproxy.ProxyInterceptor;
import io.vertx.mutiny.httpproxy.ProxyResponse;
import jakarta.enterprise.context.ApplicationScoped;
import org.eclipse.microprofile.rest.client.inject.RestClient;

@ApplicationScoped
public class TestRequestInterceptor implements ProxyInterceptor {

    @RestClient
    private Service1 service1;

    @RestClient
    private Service2 service2;

    @Override
    public final Uni<ProxyResponse> handleProxyRequest(ProxyContext context) {
        Uni<ProxyResponse> result = null;

        if (context.request().headers().contains("header-name")) {
            return service1.get()
                    .onItemOrFailure().transformToUni((resp, throwable) -> {
                        // process response
                        return context.sendRequest();
                    });
        } else {
            return service2.get()
                    .onItemOrFailure().transformToUni((resp, throwable) -> {
                        // process response
                        return context.sendRequest();
                    });
        }
    }

    public Uni<Void> handleProxyResponse(ProxyContext context) {
        return context.sendResponse();
    }
}
import io.vertx.mutiny.core.Vertx;
import io.vertx.mutiny.core.http.HttpClient;
import io.vertx.mutiny.ext.web.Router;
import io.vertx.mutiny.ext.web.proxy.handler.ProxyHandler;
import io.vertx.mutiny.httpproxy.HttpProxy;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.event.Observes;

@ApplicationScoped
public class TestHttpProxy {
    private final HttpProxy httpProxy;
    public TestHttpProxy(Vertx vertx, TestRequestInterceptor testRequestInterceptor) {
        HttpClient proxyClient = vertx.createHttpClient();
        httpProxy = HttpProxy.reverseProxy(proxyClient);
        httpProxy.origin(7000, "localhost");
        httpProxy.addInterceptor(testRequestInterceptor);
    }

    public void init(@Observes Router router) {
        router.routeWithRegex("^.*$").handler(ProxyHandler.create(httpProxy));
    }
}
cescoffier commented 1 year ago

Mutiny APIs are implemented directly on top of the "Bare" API. The getDelegate provides a way to get the "bare" object.

lucaspouzac commented 1 year ago

Hello, any idea to use ProxyInterceptor with mutiny ? I can't find a solution to chain interceptor...