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

org.zalando.riptide.Requester Maven / Gradle / Ivy

package org.zalando.riptide;

import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.client.AsyncClientHttpRequest;
import org.springframework.http.client.AsyncClientHttpRequestFactory;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.web.util.UriComponentsBuilder;

import javax.annotation.Nullable;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.net.URI;
import java.util.concurrent.CompletableFuture;

public final class Requester extends Dispatcher {

    private final AsyncClientHttpRequestFactory requestFactory;
    private final MessageWorker worker;
    private final HttpMethod method;
    private final UriComponentsBuilder urlBuilder;
    private final Object[] urlVariables;

    private final Multimap query = LinkedHashMultimap.create();
    private final HttpHeaders headers = new HttpHeaders();

    public Requester(final AsyncClientHttpRequestFactory requestFactory, final MessageWorker worker,
            final HttpMethod method, final UriComponentsBuilder urlBuilder, final Object... urlVariables) {
        this.requestFactory = requestFactory;
        this.worker = worker;
        this.method = method;
        this.urlBuilder = urlBuilder;
        this.urlVariables = urlVariables;
    }

    public final Requester queryParam(final String name, final String value) {
        query.put(name, value);
        return this;
    }

    public final Requester queryParams(final Multimap params) {
        query.putAll(params);
        return this;
    }

    public final Requester header(final String name, final String value) {
        headers.add(name, value);
        return this;
    }

    public final Requester headers(final HttpHeaders headers) {
        this.headers.putAll(headers);
        return this;
    }

    public final Requester accept(final MediaType acceptableMediaType, final MediaType... acceptableMediaTypes) {
        headers.setAccept(Lists.asList(acceptableMediaType, acceptableMediaTypes));
        return this;
    }

    public final Requester contentType(final MediaType contentType) {
        headers.setContentType(contentType);
        return this;
    }

    public final  Dispatcher body(final T body) {
        return execute(query, headers, body);
    }

    @Override
    public final  Completion dispatch(final RoutingTree tree) {
        return execute(query, headers, null).dispatch(tree);
    }

    protected  Dispatcher execute(final Multimap query, final HttpHeaders headers,
            final @Nullable T body) {

        final HttpEntity entity = new HttpEntity<>(body, headers);
        final ListenableFuture listenable = createAndExecute(query, entity);

        return new Dispatcher() {

            @Override
            public  Completion dispatch(final RoutingTree tree) {
                final CompletableFuture future = new CompletableFuture() {
                    @Override
                    public boolean cancel(final boolean mayInterruptIfRunning) {
                        final boolean cancelled = listenable.cancel(mayInterruptIfRunning);
                        super.cancel(mayInterruptIfRunning);
                        return cancelled;
                    }
                };

                listenable.addCallback(response -> {
                    try {
                        tree.execute(response, worker);
                        future.complete(null);
                    } catch (final Exception e) {
                        future.completeExceptionally(e);
                    }
                }, future::completeExceptionally);

                return Completion.valueOf(future);
            }

        };
    }

    private  ListenableFuture createAndExecute(final Multimap query,
            final HttpEntity entity) {
        try {
            final AsyncClientHttpRequest request = create(query, entity);
            return request.executeAsync();
        } catch (final IOException e) {
            throw new UncheckedIOException(e);
        }
    }

    private  AsyncClientHttpRequest create(final Multimap query,
            final HttpEntity entity) throws IOException {

        final URI url = createUrl(query);
        final AsyncClientHttpRequest request = requestFactory.createAsyncRequest(url, method);
        worker.write(request, entity);
        return request;
    }

    private URI createUrl(final Multimap query) {
        query.entries().forEach(entry ->
                urlBuilder.queryParam(entry.getKey(), entry.getValue()));
        return urlBuilder.buildAndExpand(urlVariables).encode().toUri().normalize();
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy