All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.julienviet.retrofit.vertx.VertxCallFactory Maven / Gradle / Ivy

package com.julienviet.retrofit.vertx;

import io.vertx.core.Future;
import io.vertx.core.MultiMap;
import io.vertx.core.http.HttpClient;
import io.vertx.core.http.HttpClientRequest;
import io.vertx.core.http.HttpMethod;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Headers;
import okhttp3.MediaType;
import okhttp3.Protocol;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okio.Buffer;

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * @author Julien Viet
 */
public class VertxCallFactory implements Call.Factory {

  private final HttpClient client;

  public VertxCallFactory(HttpClient client) {
    this.client = client;
  }

  private class VertxCall implements okhttp3.Call {

    private final Request retroRequest;
    private final AtomicBoolean executed = new AtomicBoolean();

    VertxCall(Request retroRequest) {
      this.retroRequest = retroRequest;
    }

    @Override
    public Request request() {
      return retroRequest;
    }

    @Override
    public Response execute() throws IOException {
      CompletableFuture future = new CompletableFuture<>();
      enqueue(new Callback() {

        @Override
        public void onResponse(okhttp3.Call call, Response response) throws IOException {
          future.complete(response);
        }

        @Override
        public void onFailure(okhttp3.Call call, IOException e) {
          future.completeExceptionally(e);
        }
      });
      try {
        return future.get(10, TimeUnit.SECONDS);
      } catch (Exception e) {
        throw new IOException(e);
      }
    }

    @Override
    public void enqueue(Callback callback) {
      if (executed.compareAndSet(false, true)) {
        Future fut = Future.future();
        fut.setHandler(ar -> {
          if (ar.succeeded()) {
            try {
              callback.onResponse(this, ar.result());
            } catch (IOException e) {
              // WTF ?
              e.printStackTrace();
            }
          } else {
            IOException ioe;
            Throwable cause = ar.cause();
            if (cause instanceof IOException) {
              ioe = (IOException) cause;
            } else {
              ioe = new IOException(cause);
            }
            callback.onFailure(this, ioe);
          }
        });
        HttpMethod method = HttpMethod.valueOf(retroRequest.method());
        HttpClientRequest request = client.requestAbs(method, this.retroRequest.url().toString(), resp -> {
          resp.exceptionHandler(fut::tryFail);
          resp.bodyHandler(body -> {
            Response.Builder builder = new Response.Builder();
            builder.protocol(Protocol.HTTP_1_1);
            builder.request(this.retroRequest);
            builder.code(resp.statusCode());
            builder.message(resp.statusMessage());
            for (Map.Entry header : resp.headers()) {
              builder.addHeader(header.getKey(), header.getValue());
            }
            String mediaTypeHeader = resp.getHeader("Content-Type");
            MediaType mediaType = mediaTypeHeader != null ? MediaType.parse(mediaTypeHeader) : null;
            builder.body(ResponseBody.create(mediaType, body.getBytes()));
            fut.tryComplete(builder.build());
          });
        });
        request.exceptionHandler(fut::tryFail);
        int size = retroRequest.headers().size();
        Headers retroHeaders = retroRequest.headers();
        MultiMap headers = request.headers();
        for (int i = 0;i < size;i++) {
          String header = retroHeaders.name(i);
          String value = retroHeaders.value(i);
          headers.add(header, value);
        }
        try {
          RequestBody body = this.retroRequest.body();
          if (body != null && body.contentLength() > 0) {
            MediaType mediaType = body.contentType();
            request.putHeader("content-type", mediaType.toString());

            request.putHeader("content-length", "" + body.contentLength());
            Buffer buffer = new Buffer();
            body.writeTo(buffer);
            request.write(io.vertx.core.buffer.Buffer.buffer(buffer.readByteArray()));
          }
        } catch (IOException e) {
          e.printStackTrace(); // ?
        }
        request.end();
      } else {
        callback.onFailure(this, new IOException("Already executed"));
      }
    }

    @Override
    public void cancel() {
    }

    @Override
    public boolean isExecuted() {
      return executed.get();
    }

    @Override
    public boolean isCanceled() {
      return false;
    }

    @Override
    public Call clone() {
      return new VertxCall(retroRequest);
    }
  }

  @Override
  public okhttp3.Call newCall(Request request) {
    return new VertxCall(request);
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy