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

net.luminis.http3.Http3Client Maven / Gradle / Ivy

Go to download

Java implementation of HTTP3 (RFC 9114): generic client / client library and HTTP3 server plugin for Kwik.

There is a newer version: 0.5.2
Show newest version
/*
 * Copyright © 2019, 2020, 2021, 2022, 2023 Peter Doornbosch
 *
 * This file is part of Flupke, a HTTP3 client Java library
 *
 * Flupke is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the
 * Free Software Foundation, either version 3 of the License, or (at your option)
 * any later version.
 *
 * Flupke is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
 * more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program. If not, see .
 */
package net.luminis.http3;

import net.luminis.http3.core.Http3ClientConnection;
import net.luminis.http3.impl.Http3ClientConnectionImpl;
import net.luminis.http3.impl.Http3ConnectionFactory;
import net.luminis.http3.server.HttpError;
import net.luminis.quic.Statistics;
import net.luminis.quic.concurrent.DaemonThreadFactory;
import net.luminis.quic.log.Logger;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLParameters;
import java.io.IOException;
import java.net.Authenticator;
import java.net.CookieHandler;
import java.net.ProxySelector;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


public class Http3Client extends HttpClient {

    private final Duration connectTimeout;
    private final Long receiveBufferSize;
    private final boolean disableCertificateCheck;
    private final Logger logger;
    private Http3ClientConnection http3Connection;
    protected Http3ConnectionFactory http3ConnectionFactory;
    private final ExecutorService executorService;

    Http3Client(Duration connectTimeout, Long receiveBufferSize, boolean disableCertificateCheck, Logger logger) {
        this.connectTimeout = connectTimeout;
        this.receiveBufferSize = receiveBufferSize;
        this.disableCertificateCheck = disableCertificateCheck;
        this.logger = logger;
        this.http3ConnectionFactory = new Http3ConnectionFactory(this);

        executorService = Executors.newCachedThreadPool(new DaemonThreadFactory("http3"));
    }

    public static HttpClient newHttpClient() {
        return new Http3ClientBuilder().build();
    }

    public static Http3ClientBuilder newBuilder() {
        return new Http3ClientBuilder();
    }

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

    @Override
    public Optional cookieHandler() {
        return Optional.empty();
    }

    @Override
    public Optional connectTimeout() {
        return Optional.ofNullable(connectTimeout);
    }

    @Override
    public Redirect followRedirects() {
        return Redirect.NEVER;
    }

    @Override
    public Optional proxy() {
        return Optional.empty();
    }

    @Override
    public SSLContext sslContext() {
        return null;
    }

    @Override
    public SSLParameters sslParameters() {
        return null;
    }

    @Override
    public Optional authenticator() {
        return Optional.empty();
    }

    @Override
    public Version version() {
        return null;
    }

    @Override
    public Optional executor() {
        return Optional.empty();
    }

    public boolean isDisableCertificateCheck() {
        return disableCertificateCheck;
    }

    public Logger getLogger() {
        return logger;
    }

    @Override
    public  HttpResponse send(HttpRequest request, HttpResponse.BodyHandler responseBodyHandler) throws IOException {
        http3Connection = http3ConnectionFactory.getConnection(request);
        http3Connection.connect();
        return http3Connection.send(request, responseBodyHandler);
    }

    @Override
    public  CompletableFuture> sendAsync(HttpRequest request, HttpResponse.BodyHandler responseBodyHandler) {
        CompletableFuture> future = new CompletableFuture<>();
        executorService.submit(() -> {
            try {
                future.complete(send(request, responseBodyHandler));
            }
            catch (IOException ex) {
                future.completeExceptionally(ex);
            }
            catch (RuntimeException ex) {
                future.completeExceptionally(ex);
            }
        });
        return future;
    }

    @Override
    public  CompletableFuture> sendAsync(HttpRequest request, HttpResponse.BodyHandler responseBodyHandler, HttpResponse.PushPromiseHandler pushPromiseHandler) {
        throw new UnsupportedOperationException("server push is not (yet) supported");
    }

    /**
     * Sends a CONNECT request (that creates a tunnel to a remote host) and returns a HttpStream object that can be used
     * to send/receive data to/from remote host.
     *
     * https://www.rfc-editor.org/rfc/rfc9114.html#name-the-connect-method:
     * "In HTTP/2 and HTTP/3, the CONNECT method is used to establish a tunnel over a single stream."
     *
     * @param request
     * @return
     * @throws IOException
     * @throws HttpError
     */
    public Http3ClientConnectionImpl.HttpStreamImpl sendConnect(HttpRequest request) throws IOException, HttpError {
        http3Connection = http3ConnectionFactory.getConnection(request);
        http3Connection.connect();
        return http3Connection.sendConnect(request);
    }

    /**
     * Sends an Extended CONNECT request (that can be used for tunneling other protocols like websocket and webtransport).
     * See https://www.rfc-editor.org/rfc/rfc9220.html and  https://www.rfc-editor.org/rfc/rfc8441.html.
     *
     * @param request
     * @param protocol
     * @param scheme
     * @return
     * @throws IOException
     * @throws HttpError
     * @throws InterruptedException
     */
    public Http3ClientConnection.HttpStream sendExtendedConnect(HttpRequest request, String protocol, String scheme) throws IOException, HttpError, InterruptedException {
        http3Connection = http3ConnectionFactory.getConnection(request);
        http3Connection.connect();
        return http3Connection.sendExtendedConnect(request, protocol, scheme, Duration.ofSeconds(10));
    }

    public Statistics getConnectionStatistics() {
        if (http3Connection != null) {
            return http3Connection.getConnectionStats();
        }
        else {
            return null;
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy