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

com.github.lontime.exthttp.container.HttpServerService Maven / Gradle / Ivy

There is a newer version: 1.4.0
Show newest version
package com.github.lontime.exthttp.container;

import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.ExecutorService;
import java.util.stream.Collectors;

import com.github.lontime.base.commonj.components.ComponentInterfaceHelper;
import com.github.lontime.base.commonj.components.Lifecycle;
import com.github.lontime.base.commonj.utils.CollectionHelper;
import com.github.lontime.base.commonj.utils.LoggerHelper;
import com.github.lontime.base.commonj.utils.StringHelper;
import com.github.lontime.exthttp.common.ConfigKey;
import com.github.lontime.exthttp.configuration.CertificateSpec;
import com.github.lontime.exthttp.configuration.OptionResolver;
import com.github.lontime.exthttp.configuration.ServerOption;
import com.github.lontime.exthttp.configuration.WiretapSpec;
import io.netty.channel.ChannelOption;
import io.netty.channel.epoll.EpollChannelOption;
import io.netty.channel.socket.nio.NioChannelOption;
import io.netty.handler.ssl.util.SelfSignedCertificate;
import io.netty.util.AttributeKey;
import reactor.netty.DisposableServer;
import reactor.netty.http.Http11SslContextSpec;
import reactor.netty.http.Http2SslContextSpec;
import reactor.netty.http.server.HttpServer;
import reactor.netty.tcp.SslProvider;

/**
 * ServerContainer.
 *
 * @author lontime
 * @since 1.0
 */
public class HttpServerService implements Lifecycle {

    private List servers = new ArrayList<>();

    private ExecutorService executorService;

    public void setExecutorService(ExecutorService executorService) {
        this.executorService = executorService;
    }

    @Override
    public void initialize() {
        servers.addAll(OptionResolver.getInstance().getServerOptions()
                .stream().map(this::loadServer).filter(Objects::nonNull)
                .collect(Collectors.toList()));
    }

    @Override
    public void start() {
        if (executorService == null) {
            return;
        }
        executorService.execute(() -> servers.stream()
                .filter(DisposableServerWrapper::getAutoStart).forEach(s -> {
                    LoggerHelper.infov("{0}@start: server start on port {1}...",
                            getClass().getName(), s.getOption().getPort());
                    s.setBlocked(true);
                    s.getDisposableServer().onDispose().block();
                }));
    }

    @Override
    public void stop() {
        servers.stream().filter(DisposableServerWrapper::getAutoStart).forEach(s -> {
            final DisposableServer server = s.getDisposableServer();
            LoggerHelper.infov("{0}@stop: server stop on port {1}...",
                    getClass().getName(), s.getOption().getPort());
            server.disposeNow(s.getOption().getDisposeTimeout());
        });
    }

    public DisposableServerWrapper getServer(String name) {
        return servers.stream().filter(s -> s.getName().equals(name))
                .findAny().orElse(null);
    }

    private DisposableServerWrapper loadServer(ServerOption option) {
        HttpServer server = HttpServer.create();
        final List listeners = ComponentInterfaceHelper.get(HttpRouteInterface.class, option.getName());
        if (CollectionHelper.isEmpty(listeners)) {
            return null;
        }
        server = server.route(r -> listeners.forEach(s -> {
            try {
                s.handle(r);
            } catch (Exception e) {
                LoggerHelper.warnv(e, "{0}@loadServer: route is error", HttpServerService.class.getName());
            }
        }));
        if (option.getPort() != null) {
            server = server.port(option.getPort());
        }
        if (StringHelper.hasText(option.getHost())) {
            server = server.host(option.getHost());
        }
        if (option.getCompressSize() != null) {
            server = server.compress(option.getCompressSize());
        } else if (option.getEnableCompress() != null) {
            server = server.compress(option.getEnableCompress());
        }
        if (option.getIdleTimeout() != null) {
            server = server.idleTimeout(option.getIdleTimeout());
        }
        if (option.getNoSSL() != null && option.getNoSSL()) {
            server = server.noSSL();
        }
        if (option.getRequestDecoder() != null) {
            server = server.httpRequestDecoder(spec -> {
                final ServerOption.RequestDecoder requestDecoder = option.getRequestDecoder();
                if (requestDecoder.getMaxChunkSize() != null) {
                    spec.maxChunkSize(requestDecoder.getMaxChunkSize());
                }
                if (requestDecoder.getMaxHeaderSize() != null) {
                    spec.maxHeaderSize(requestDecoder.getMaxHeaderSize());
                }
                if (requestDecoder.getMaxInitialLineLength() != null) {
                    spec.maxInitialLineLength(requestDecoder.getMaxInitialLineLength());
                }
                if (requestDecoder.getValidateHeaders() != null) {
                    spec.validateHeaders(requestDecoder.getValidateHeaders());
                }
                if (requestDecoder.getInitialBufferSize() != null) {
                    spec.initialBufferSize(requestDecoder.getInitialBufferSize());
                }
                if (requestDecoder.getAllowDuplicateContentLengths() != null) {
                    spec.allowDuplicateContentLengths(requestDecoder.getAllowDuplicateContentLengths());
                }
                if (requestDecoder.getH2cMaxContentLength() != null) {
                    spec.h2cMaxContentLength(requestDecoder.getH2cMaxContentLength());
                }
                return spec;
            });
        }

        if (option.getHttp11Certificate() != null) {
            final Optional contextSpecOptional =
                    buildHttp11SslContextSpec(option.getHttp2Certificate());
            if (contextSpecOptional.isPresent()) {
                server = server.secure(spec -> spec.sslContext(contextSpecOptional.get()));
            }
        }

        if (option.getHttp2Certificate() != null) {
            final Optional contextSpecOptional2 =
                    buildHttp2SslContextSpec(option.getHttp2Certificate());
            if (contextSpecOptional2.isPresent()) {
                server = server.secure(spec -> spec.sslContext(contextSpecOptional2.get()));
            }
        }

        if (option.getAccessLog() != null) {
            server = server.accessLog(option.getAccessLog());
        }

        if (option.getForwarded() != null) {
            server = server.forwarded(option.getForwarded());
        }

        if (option.getWiretapEnabled() != null) {
            server = server.wiretap(option.getWiretapEnabled());
        }
        if (option.getWiretapSpec() != null) {
            final WiretapSpec wiretapSpec = option.getWiretapSpec();
            server = server.wiretap(wiretapSpec.getCategory(), wiretapSpec.getLevel(),
                    wiretapSpec.getFormat(), wiretapSpec.getCharset());
        }

        if (CollectionHelper.isNotEmpty(option.getChannelOptions())) {
            for (Map.Entry entry : option.getChannelOptions().entrySet()) {
                final ConfigKey configKey = entry.getKey();
                server = server.option(ChannelOption.valueOf(configKey.getKey()), configKey.parseValue(entry.getValue()));
            }
        }
        if (CollectionHelper.isNotEmpty(option.getEpollChannelOptions())) {
            for (Map.Entry entry : option.getEpollChannelOptions().entrySet()) {
                final ConfigKey configKey = entry.getKey();
                server = server.option(EpollChannelOption.valueOf(configKey.getKey()), configKey.parseValue(entry.getValue()));
            }
        }
        if (CollectionHelper.isNotEmpty(option.getNioChannelOptions())) {
            for (Map.Entry entry : option.getNioChannelOptions().entrySet()) {
                final ConfigKey configKey = entry.getKey();
                server = server.option(NioChannelOption.valueOf(configKey.getKey()), configKey.parseValue(entry.getValue()));
            }
        }
        if (option.getProxyType() != null) {
            server = server.proxyProtocol(option.getProxyType());
        }

        if (CollectionHelper.isNotEmpty(option.getAttrs())) {
            for (Map.Entry entry : option.getNioChannelOptions().entrySet()) {
                final ConfigKey configKey = entry.getKey();
                server = server.attr(AttributeKey.valueOf(configKey.getKey()), configKey.parseValue(entry.getValue()));
            }
        }

        if (option.getWarmup() != null && option.getWarmup()) {
            server.warmup().block();
        }
        return new DisposableServerWrapper(server.bindNow(option.getBindTimeout()), option);
    }

    private Optional buildHttp11SslContextSpec(CertificateSpec certificate) {
        if (certificate.getTesting()) {
            try {
                final SelfSignedCertificate cert = new SelfSignedCertificate();
                return Optional.of(Http11SslContextSpec.forServer(cert.certificate(), cert.privateKey()));
            } catch (CertificateException e) {
                return Optional.empty();
            }
        }

        if (certificate.getKeyCertChainFile() == null || certificate.getKeyFile() == null) {
            return Optional.empty();
        }
        if (certificate.getKeyPassword() == null) {
            return Optional.of(Http11SslContextSpec.forServer(certificate.getKeyCertChainFile(), certificate.getKeyFile()));
        } else {
            return Optional.of(Http11SslContextSpec.forServer(certificate.getKeyCertChainFile(), certificate.getKeyFile(),
                    certificate.getKeyPassword()));
        }
    }

    private Optional buildHttp2SslContextSpec(CertificateSpec certificate) {
        if (certificate.getTesting()) {
            try {
                final SelfSignedCertificate cert = new SelfSignedCertificate();
                return Optional.of(Http2SslContextSpec.forServer(cert.certificate(), cert.privateKey()));
            } catch (CertificateException e) {
                return Optional.empty();
            }
        }
        if (certificate.getKeyCertChainFile() == null || certificate.getKeyFile() == null) {
            return Optional.empty();
        }
        if (certificate.getKeyPassword() == null) {
            return Optional.of(Http2SslContextSpec.forServer(certificate.getKeyCertChainFile(), certificate.getKeyFile()));
        } else {
            return Optional.of(Http2SslContextSpec.forServer(certificate.getKeyCertChainFile(), certificate.getKeyFile(),
                    certificate.getKeyPassword()));
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy