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

net.dongliu.cute.http.Client Maven / Gradle / Ivy

The newest version!
package net.dongliu.cute.http;

import net.dongliu.commons.Lazy;
import net.dongliu.cute.http.exception.RequestsException;
import net.dongliu.cute.http.internal.SSLContextFactories;
import net.dongliu.cute.http.json.JsonMarshaller;
import net.dongliu.cute.http.json.JsonMarshallers;
import org.checkerframework.checker.nullness.qual.Nullable;

import java.net.*;
import java.net.http.HttpClient;
import java.security.KeyStore;
import java.time.Duration;
import java.util.Optional;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicLong;

import static java.net.http.HttpClient.Redirect.ALWAYS;
import static java.net.http.HttpClient.Redirect.NEVER;
import static java.net.http.HttpClient.Version.HTTP_1_1;
import static java.net.http.HttpClient.Version.HTTP_2;
import static java.util.Objects.requireNonNull;
import static java.util.concurrent.Executors.newCachedThreadPool;
import static net.dongliu.commons.Objects2.elvis;
import static net.dongliu.commons.concurrent.ThreadFactories.newDaemonThreadFactory;

/**
 * The http client.
 */
public class Client {
    private final String name;
    @Nullable
    private final ProxySelector proxySelector;
    private final boolean useHttp2;
    private final boolean verifyCert;
    private final boolean followRedirect;
    @Nullable
    private final Authenticator authenticator;
    private final CookieHandler cookieHandler;
    private final Executor executor;
    @Nullable
    private final KeyStore keyStore;
    private final Duration connectTimeout;

    private final Duration timeout;
    private final String userAgent;
    private final boolean acceptCompressed;

    @Nullable
    private final JsonMarshaller jsonMarshaller;

    final HttpClient httpClient;

    private static final AtomicLong seq = new AtomicLong(0);

    static {
        // This may not work as user may call HttpClient module in some other place already.
        // If so, use may call this method at the begin of app, or set properties by command line.
        ClientProperties.allowRestrictedHeaders();
    }

    Client(ClientBuilder builder) {
        this.name = elvis(builder.name, () -> "HttpClient-" + seq.getAndIncrement());
        this.proxySelector = builder.proxySelector;
        this.useHttp2 = builder.useHttp2;
        this.verifyCert = builder.verifyCert;
        this.followRedirect = builder.followRedirect;
        this.timeout = builder.timeout;
        this.userAgent = elvis(builder.userAgent, () -> "HttpClient, Java " + System.getProperty("java.version"));
        this.acceptCompressed = builder.acceptCompressed;
        this.authenticator = builder.authenticator;
        this.cookieHandler = builder.cookieHandler;
        this.keyStore = builder.keyStore;
        this.connectTimeout = builder.connectTimeout;
        this.jsonMarshaller = Optional.ofNullable(builder.jsonMarshaller)
                .or(JsonMarshallers::getJsonMarshaller)
                .orElse(null);

        this.executor = elvis(builder.executor, () -> newCachedThreadPool(newDaemonThreadFactory(name)));

        var httpClientBuilder = HttpClient.newBuilder();
        if (!verifyCert) {
            httpClientBuilder.sslContext(SSLContextFactories.getTrustAllSSLContext());
        } else if (keyStore != null) {
            httpClientBuilder.sslContext(SSLContextFactories.getCustomTrustSSLContext(keyStore));
        }

        httpClientBuilder.executor(executor);
        httpClientBuilder.version(useHttp2 ? HTTP_2 : HTTP_1_1)
                .followRedirects(followRedirect ? ALWAYS : NEVER);
        if (proxySelector != null) {
            httpClientBuilder.proxy(proxySelector);
        }
        if (authenticator != null) {
            httpClientBuilder.authenticator(authenticator);
        }
        httpClientBuilder.cookieHandler(cookieHandler);
        httpClientBuilder.connectTimeout(connectTimeout);

        this.httpClient = httpClientBuilder.build();
    }

    /**
     * Get a new HttpClient Builder
     */
    public static ClientBuilder builder() {
        return new ClientBuilder();
    }


    private static final Lazy defaultClient = Lazy.of(() -> new ClientBuilder().build());

    /**
     * Return the default Http Client with default settings. The client is shared across one jvm process.
     */
    public static Client defaultClient() {
        return defaultClient.get();
    }

    /**
     * Start a GET request
     */
    public RequestContext get(URL url) {
        return newRequest(Method.GET, url);
    }

    /**
     * Start a POST request
     */
    public RequestContext post(URL url) {
        return newRequest(Method.POST, url);
    }

    /**
     * Start a PUT request
     */
    public RequestContext put(URL url) {
        return newRequest(Method.PUT, url);
    }

    /**
     * Start a DELETE request
     */
    public RequestContext delete(URL url) {
        return newRequest(Method.DELETE, url);
    }

    /**
     * Start a HEAD request
     */
    public RequestContext head(URL url) {
        return newRequest(Method.HEAD, url);
    }

    /**
     * Create new request with method and url
     */
    public RequestContext newRequest(Method method, URL url) {
        return new RequestContext(this, method, url)
                .timeout(timeout)
                .acceptCompressed(acceptCompressed)
                .userAgent(userAgent);
    }

    /**
     * Start a GET request
     */
    public RequestContext get(String url) {
        return newRequest(Method.GET, url);
    }

    /**
     * Start a POST request
     */
    public RequestContext post(String url) {
        return newRequest(Method.POST, url);
    }

    /**
     * Start a PUT request
     */
    public RequestContext put(String url) {
        return newRequest(Method.PUT, url);
    }

    /**
     * Start a DELETE request
     */
    public RequestContext delete(String url) {
        return newRequest(Method.DELETE, url);
    }

    /**
     * Start a HEAD request
     */
    public RequestContext head(String url) {
        return newRequest(Method.HEAD, url);
    }

    /**
     * Create new request with method and url
     */
    public RequestContext newRequest(Method method, String urlStr) {
        URL url;
        try {
            url = new URL(requireNonNull(urlStr));
        } catch (MalformedURLException e) {
            throw new RequestsException("Resolve url error, url: " + urlStr, e);
        }
        return newRequest(method, url);
    }

    public String name() {
        return name;
    }

    public Optional proxy() {
        return Optional.ofNullable(proxySelector);
    }

    public boolean useHttp2() {
        return useHttp2;
    }

    public boolean verifyCert() {
        return verifyCert;
    }

    public boolean followRedirect() {
        return followRedirect;
    }

    public Duration timeout() {
        return timeout;
    }

    public Duration connectTimeout() {
        return connectTimeout;
    }

    /**
     * The user-agent of this http client.
     */
    public String userAgent() {
        return userAgent;
    }

    public boolean acceptCompressed() {
        return acceptCompressed;
    }

    public Optional authenticator() {
        return Optional.ofNullable(authenticator);
    }

    public CookieHandler cookieHandler() {
        return cookieHandler;
    }

    public Optional keyStore() {
        return Optional.ofNullable(keyStore);
    }

    /**
     * The thread pool used for http executing.
     */
    public Executor executor() {
        return executor;
    }

    /**
     * The JsonMarshaller this client use.
     */
    public Optional jsonMarshaller() {
        return Optional.ofNullable(jsonMarshaller);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy