Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generated Proxies need to allow setting headers #139

Open
pmlopes opened this issue Nov 18, 2022 · 1 comment
Open

Generated Proxies need to allow setting headers #139

pmlopes opened this issue Nov 18, 2022 · 1 comment

Comments

@pmlopes
Copy link
Member

pmlopes commented Nov 18, 2022

The current proxy generator is very simple and does not take into consideration the headers in the event bus message. In a scenario where a user would want to send a Authentication token with the message to attest the id of the caller, this is currently not supported and requires the user to manually perform the marshalling, e.g.:

service = new MicroServiceVertxEBProxy(vertx, MicroService.ADDRESS);

vertx.eventBus()
              .<String>request(MicroService.ADDRESS, new JsonObject(), new DeliveryOptions()
                .addHeader("action", "execute")
                .addHeader("auth-token", ctx.user().get("id_token")));

This example is simple as the service method execute takes no arguments. This approach avoids the current generator that is unable to set headers and would like like:

service = new MicroServiceVertxEBProxy(vertx, MicroService.ADDRESS);

service.execute()

In order to address this we should have a better generated proxy, for example it should be usable as:

service = new MicroServiceVertxEBProxy(vertx, MicroService.ADDRESS);

service
  .execute()
  .call(deliveryOptions -> { ... })

Here in the optional argument of call, one can capture the request, (say we're on vertx-web) and add the required headers, e.g.:

.call(deliveryOptions -> deliveryOptions.addHeader("auth-token", ctx.user().get("id_token")))

In order to achive this we would need some abstract proxy class:

public abstract AbstractVertxEBProxy {
  private Vertx _vertx;
  private String _address;
  private DeliveryOptions _options;
  private boolean closed;

  public MicroServiceVertxEBProxy(Vertx vertx, String address) {
    this(vertx, address, null);
  }

  public MicroServiceVertxEBProxy(Vertx vertx, String address, DeliveryOptions options) {
    this._vertx = vertx;
    this._address = address;
    this._options = options;
    try {
      this._vertx.eventBus().registerDefaultCodec(ServiceException.class, new ServiceExceptionMessageCodec());
    } catch (IllegalStateException ex) {
    }
  }

  public final class Caller<T> {

    private final String _action;
    private final JsonObject _json;
    private final io.vertx.core.Future<T> _future;

    private Caller(io.vertx.core.Future<T> future) {
      this._action = null;
      this._future = future;
      this._json = null;
    }

    private Caller(String _action, JsonObject _json) {
      this._action = _action;
      this._json = _json;
      this._future = null;
    }

    public Future<T> call() {
      return call(null);
    }

    public Future<T> call(Consumer<DeliveryOptions> postage) {
      if (_action == null) {
        return _future;
      }

      DeliveryOptions _deliveryOptions = (_options != null) ? new DeliveryOptions(_options) : new DeliveryOptions();

      if (postage != null) {
        try {
          postage.accept(_deliveryOptions);
        } catch (RuntimeException e) {
          return Future.failedFuture(e);
        }
      }

      MultiMap headers = _deliveryOptions.getHeaders();
      if (headers == null) {
        _deliveryOptions.addHeader("action", _action);
      } else {
        _deliveryOptions.getHeaders().set("action", _action);
      }

      return _vertx.eventBus().<T>request(_address, _json, _deliveryOptions)
        .map(msg -> msg.body());
    }
  }
}

Then the generator would generate the following code:

// for each method in the @ProxyGen interface

  //@Override
  public Caller<String> method_name() { // <-- note Caller instead of `Future`
    if (closed) return new Caller<>(io.vertx.core.Future.failedFuture("Proxy is closed"));
    // encoding to JSON as usual...
    // ...
    return new Caller<>("execute", _json);
  }

With this approach we can now annotate the message with the headers we wish.

@pmlopes
Copy link
Member Author

pmlopes commented Nov 18, 2022

Extra helpers could be added. Like in the example above, we could have a helper just for passing the auth-token as:

service = new MicroServiceVertxEBProxy(vertx, MicroService.ADDRESS);

service
  .execute()
  .authorizeAndCall(ctx.user().get("id_token"))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

1 participant