io.ventu.rpc.rest.HttpRestInvokerImpl.java Source code

Java tutorial

Introduction

Here is the source code for io.ventu.rpc.rest.HttpRestInvokerImpl.java

Source

/*
 * Copyright (c) 2015-2016. Ventu.io, Oleg Sklyar and contributors, distributed under the MIT license.
 */

package io.ventu.rpc.rest;

import java.util.Collections;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;

import io.ventu.rpc.exception.ApiException;
import io.ventu.rpc.exception.EncodingException;
import io.ventu.rpc.rest.exception.HttpException;
import io.ventu.rpc.rest.util.HttpRequestRouter;
import io.ventu.rpc.util.Serializer;
import io.ventu.rpc.util.Validator;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.http.HttpClient;
import io.vertx.core.http.HttpClientOptions;
import io.vertx.core.http.HttpClientRequest;
import io.vertx.core.http.HttpMethod;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

class HttpRestInvokerImpl implements HttpRestInvoker {

    private static Logger log = LoggerFactory.getLogger(HttpRestInvoker.class);

    private final HttpClient client;
    private final HttpRequestRouter requestRouter;
    private final Validator responseValidator;
    private final Serializer serializer;
    private final Map<String, String> headers;

    HttpRestInvokerImpl(Function<HttpClientOptions, HttpClient> initializer, HttpClientOptions opts,
            HttpRequestRouter requestRouter, Validator responseValidator, Serializer serializer,
            Map<String, String> headers) {
        this.requestRouter = requestRouter;
        this.responseValidator = responseValidator;
        this.serializer = serializer;
        this.headers = Collections.unmodifiableMap(headers);

        client = initializer.apply(opts);
    }

    @Override
    public <RQ, RS> CompletableFuture<RS> invoke(final RQ request, final Class<RS> responseClass) {
        final CompletableFuture<RS> answer = new CompletableFuture<>();
        try {
            String url = requestRouter.route(request);

            HttpMethod method = HttpMethod.POST;
            switch (requestRouter.type(request)) {
            case GET:
                method = HttpMethod.GET;
                break;
            case PUT:
                method = HttpMethod.PUT;
                break;
            case DELETE:
                method = HttpMethod.DELETE;
                break;
            default: // POST, keep as is
            }

            HttpClientRequest httpRequest = client.request(method, url, httpResponse -> {
                int statusCode = httpResponse.statusCode();
                if (statusCode < 400) {
                    httpResponse.bodyHandler(buffer -> {
                        try {
                            RS resp = serializer.decode(buffer.getBytes(), responseClass);
                            responseValidator.validate(resp);
                            answer.complete(resp);
                        } catch (ApiException | EncodingException | IllegalArgumentException
                                | NullPointerException ex) {
                            answer.completeExceptionally(ex);
                        }
                    });
                } else {
                    answer.completeExceptionally(new HttpException(statusCode, httpResponse.statusMessage()));
                }
            });
            for (Entry<String, String> entry : headers.entrySet()) {
                httpRequest.putHeader(entry.getKey(), entry.getValue());
            }
            httpRequest.putHeader("Content-type", CONTENT_TYPE).putHeader("Accept", CONTENT_TYPE);

            if ((method == HttpMethod.POST) || (method == HttpMethod.PUT)) {
                byte[] payload = serializer.encode(request);
                httpRequest.setChunked(true).end(Buffer.buffer(payload));
            } else {
                httpRequest.end();
            }
        } catch (IllegalArgumentException | EncodingException ex) {
            answer.completeExceptionally(ex);
        }
        return answer;
    }

    @Override
    public CompletableFuture<Void> close() {
        CompletableFuture<Void> future = new CompletableFuture<>();
        client.close();
        future.complete(null);
        return future;
    }
}