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

com.github.lontime.exthttp.configuration.OptionResolver Maven / Gradle / Ivy

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

import java.nio.charset.Charset;
import java.nio.file.Paths;
import java.time.Duration;
import java.util.List;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;

import com.github.lontime.base.commonj.utils.CollectionHelper;
import com.github.lontime.base.commonj.utils.StringHelper;
import com.github.lontime.extconfig.ConfigHelper;
import com.github.lontime.exthttp.common.ClientCookieDecoderEnum;
import com.github.lontime.exthttp.common.ClientCookieEncoderEnum;
import com.github.lontime.exthttp.common.ConfigKeys;
import com.github.lontime.shaded.com.google.common.base.Splitter;
import com.github.lontime.shaded.com.google.common.base.Suppliers;
import com.github.lontime.shaded.io.helidon.config.Config;
import io.netty.handler.codec.http.cookie.Cookie;
import io.netty.handler.codec.http.cookie.CookieHeaderNames;
import io.netty.handler.codec.http.cookie.DefaultCookie;
import io.netty.handler.logging.LogLevel;
import reactor.netty.http.HttpProtocol;
import reactor.netty.http.server.ProxyProtocolSupportType;
import reactor.netty.transport.ProxyProvider;
import reactor.netty.transport.logging.AdvancedByteBufFormat;

/**
 * OptionResolver.
 *
 * @author lontime
 * @since 1.0
 */
public class OptionResolver {

    public static final String FILE_NAME = "http";

    //------------------singleton------------------
    private static Supplier supplier = Suppliers.memoize(OptionResolver::new);

    public static OptionResolver getInstance() {
        return supplier.get();
    }
    //------------------singleton------------------

    private final Options options;

    public OptionResolver() {
        this.options = ConfigHelper.resolve(FILE_NAME)
                .as(new Mapper()).orElse(new Options());
    }

    public ClientOption getClientOption(String name) {
        return options.getClients().stream().filter(s -> s.getName().equals(name)).findFirst()
                .orElse(ClientOption.DEFAULT);
    }

    public List getServerOptions() {
        return options.getServers();
    }

    public ConnectionOption getConnectionOption(String name) {
        return options.getConnections().stream().filter(s -> s.getName().equals(name))
                .findFirst().orElse(new ConnectionOption(name));
    }

    static class Mapper implements Function {

        @Override
        public Options apply(Config config) {
            final Options opts = new Options();
            config.get("connections").asList(new ConnectionMapper()).ifPresent(opts::setConnections);
            config.get("clients").asList(new ClientMapper()).ifPresent(opts::setClients);
            config.get("servers").asList(new ServerMapper()).ifPresent(opts::setServers);
            return opts;
        }
    }

    static class ServerMapper implements Function {

        @Override
        public ServerOption apply(Config config) {
            final ServerOption opts = new ServerOption();
            opts.setName(config.name());
            config.get("protocols").asString().map(s -> Splitter.on(",").trimResults().omitEmptyStrings()
                            .splitToStream(s).map(s1 -> HttpProtocol.valueOf(s1)).collect(Collectors.toList()))
                    .filter(CollectionHelper::isNotEmpty).ifPresent(opts::setProtocols);
            config.get("host").asString().ifPresent(opts::setHost);
            config.get("port").asInt().ifPresent(opts::setPort);
            config.get("bindTimeout").asString().as(String::toUpperCase).as(Duration::parse)
                    .ifPresent(opts::setBindTimeout);
            config.get("disposeTimeout").asString().as(String::toUpperCase).as(Duration::parse)
                    .ifPresent(opts::setDisposeTimeout);
            config.get("enableCompress").asBoolean().ifPresent(opts::setEnableCompress);
            config.get("compressSize").asInt().ifPresent(opts::setCompressSize);
            config.get("idleTimeout").asString().as(String::toUpperCase).as(Duration::parse)
                    .ifPresent(opts::setIdleTimeout);
            config.get("maxKeepAliveRequests").asInt().ifPresent(opts::setMaxKeepAliveRequests);
            config.get("noSSL").asBoolean().ifPresent(opts::setNoSSL);
            config.get("warmup").asBoolean().ifPresent(opts::setWarmup);
            config.get("wiretapEnabled").asBoolean().ifPresent(opts::setWiretapEnabled);
            config.get("wiretapSpec").as(new WiretapSpecMapper()).ifPresent(opts::setWiretapSpec);
            config.get("requestDecoder").as(s -> requestDecoder(s)).ifPresent(opts::setRequestDecoder);
            config.get("http11Certificate").as(s -> certificateSpec(s)).ifPresent(opts::setHttp11Certificate);
            config.get("http2Certificate").as(s -> certificateSpec(s)).ifPresent(opts::setHttp2Certificate);
            config.get("accessLog").asBoolean().ifPresent(opts::setAccessLog);
            config.get("channelOptions").detach().asMap().ifPresent(m -> opts.setChannelOptions(ConfigKeys.resolve(m)));
            config.get("epollChannelOptions").detach().asMap().ifPresent(m -> opts.setEpollChannelOptions(ConfigKeys.resolve(m)));
            config.get("nioChannelOptions").detach().asMap().ifPresent(m -> opts.setNioChannelOptions(ConfigKeys.resolve(m)));
            config.get("proxyType").asString().as(String::toUpperCase).as(ProxyProtocolSupportType::valueOf)
                    .ifPresent(opts::setProxyType);
            config.get("attrs").detach().asMap().ifPresent(m -> opts.setAttrs(ConfigKeys.resolve(m, false)));
            config.get("autoStart").asBoolean().ifPresent(opts::setAutoStart);
            return opts;
        }

        private ServerOption.RequestDecoder requestDecoder(Config config) {
            final ServerOption.RequestDecoder opts = new ServerOption.RequestDecoder();
            config.get("initialBufferSize").asInt().ifPresent(opts::setInitialBufferSize);
            config.get("maxChunkSize").asInt().ifPresent(opts::setMaxChunkSize);
            config.get("maxHeaderSize").asInt().ifPresent(opts::setMaxHeaderSize);
            config.get("maxInitialLineLength").asInt().ifPresent(opts::setMaxInitialLineLength);
            config.get("allowDuplicateContentLengths").asBoolean().ifPresent(opts::setAllowDuplicateContentLengths);
            config.get("validateHeaders").asBoolean().ifPresent(opts::setValidateHeaders);
            config.get("h2cMaxContentLength").asInt().ifPresent(opts::setH2cMaxContentLength);
            return opts;
        }

        private CertificateSpec certificateSpec(Config config) {
            final CertificateSpec spec = new CertificateSpec();
            config.get("keyCertChainFile").asString().map(s -> Paths.get(s).toFile()).ifPresent(spec::setKeyCertChainFile);
            config.get("keyFile").asString().map(s -> Paths.get(s).toFile()).ifPresent(spec::setKeyFile);
            config.get("keyPassword").asString().ifPresent(spec::setKeyPassword);
            config.get("testing").asBoolean().ifPresent(spec::setTesting);
            return spec;
        }
    }

    static class ConnectionMapper implements Function {

        @Override
        public ConnectionOption apply(Config config) {
            final ConnectionOption opts = new ConnectionOption();
            opts.setName(config.name());
            config.get("pool").as(c -> pool(c)).ifPresent(opts::setPool);
            return opts;
        }

        private ConnectionOption.Pool pool(Config config) {
            final ConnectionOption.Pool opts = new ConnectionOption.Pool();
            config.get("name").asString().ifPresent(opts::setName);
            config.get("maxConnections").asInt().ifPresent(opts::setMaxConnections);
            config.get("pendingAcquireMaxCount").asInt().ifPresent(opts::setPendingAcquireMaxCount);
            config.get("pendingAcquireTimeout").asString().as(String::toUpperCase).as(Duration::parse)
                    .ifPresent(opts::setPendingAcquireTimeout);
            config.get("maxIdleTime").asString().as(String::toUpperCase).as(Duration::parse)
                    .ifPresent(opts::setMaxIdleTime);
            config.get("maxLifeTime").asString().as(String::toUpperCase).as(Duration::parse)
                    .ifPresent(opts::setMaxLifeTime);
            config.get("leasingStrategy").asString().ifPresent(opts::setLeasingStrategy);
            config.get("permitsSamplingRate").asDouble().ifPresent(opts::setPermitsSamplingRate);
            config.get("evictionInterval").asString().as(String::toUpperCase).as(Duration::parse)
                    .ifPresent(opts::setEvictionInterval);
            config.get("disposeTimeout").asString().as(String::toUpperCase).as(Duration::parse)
                    .ifPresent(opts::setDisposeTimeout);
            config.get("inactivePoolDisposeInterval").asString().as(String::toUpperCase).as(Duration::parse)
                    .ifPresent(opts::setInactivePoolDisposeInterval);
            config.get("poolInactivity").asString().as(String::toUpperCase).as(Duration::parse)
                    .ifPresent(opts::setPoolInactivity);
            return opts;
        }
    }

    static class ClientMapper implements Function {

        @Override
        public ClientOption apply(Config config) {
            final ClientOption opts = new ClientOption();
            config.get("name").asString().ifPresent(opts::setName);
            config.get("connectionName").asString().ifPresent(opts::setConnectionName);
            config.get("protocols").asString().map(s -> Splitter.on(",").trimResults().omitEmptyStrings()
                    .splitToStream(s).map(s1 -> HttpProtocol.valueOf(s1)).collect(Collectors.toList()))
                    .filter(CollectionHelper::isNotEmpty).ifPresent(opts::setProtocols);
            config.get("host").asString().ifPresent(opts::setHost);
            config.get("port").asInt().ifPresent(opts::setPort);
            config.get("baseUrl").asString().ifPresent(opts::setBaseUrl);
            config.get("keepAlive").asBoolean().ifPresent(opts::setKeepAlive);
            config.get("headers").detach().asMap().ifPresent(m -> opts.setHeaders(ConfigKeys.resolve(m, false)));
//            config.get("headers").detach().asMap().ifPresent(opts::setHeaders);
            config.get("cookies").asList(s -> cookie(s)).ifPresent(opts::setCookies);
            config.get("cookieEncoder").asString().as(String::toUpperCase).as(ClientCookieEncoderEnum::valueOf)
                    .ifPresent(opts::setCookieEncoder);
            config.get("cookieDecoder").asString().as(String::toUpperCase).as(ClientCookieDecoderEnum::valueOf)
                    .ifPresent(opts::setCookieDecoder);
            config.get("compress").asBoolean().ifPresent(opts::setCompress);
            config.get("disableRetry").asBoolean().ifPresent(opts::setDisableRetry);
            config.get("responseDecoder").as(s -> responseDecoder(s)).ifPresent(opts::setResponseDecoder);
            config.get("wiretapEnabled").asBoolean().ifPresent(opts::setWiretapEnabled);
            config.get("wiretapSpec").as(new WiretapSpecMapper()).ifPresent(opts::setWiretapSpec);
            config.get("secure").asBoolean().ifPresent(opts::setSecure);
            config.get("http11Secure").asBoolean().ifPresent(opts::setHttp11Secure);
            config.get("http2Secure").asBoolean().ifPresent(opts::setHttp2Secure);
            config.get("noSSL").asBoolean().ifPresent(opts::setNoSSL);
            config.get("noProxy").asBoolean().ifPresent(opts::setNoProxy);
            config.get("warmup").asBoolean().ifPresent(opts::setWarmup);
            config.get("followRedirect").asBoolean().ifPresent(opts::setFollowRedirect);
            config.get("redirect").as(s -> redirect(s)).ifPresent(opts::setRedirect);
            config.get("channelOptions").detach().asMap().ifPresent(m -> opts.setChannelOptions(ConfigKeys.resolve(m)));
            config.get("epollChannelOptions").detach().asMap().ifPresent(m -> opts.setEpollChannelOptions(ConfigKeys.resolve(m)));
            config.get("nioChannelOptions").detach().asMap().ifPresent(m -> opts.setNioChannelOptions(ConfigKeys.resolve(m)));
            config.get("proxy").as(s -> proxy(s)).ifPresent(opts::setProxy);
            config.get("attrs").detach().asMap().ifPresent(m -> opts.setAttrs(ConfigKeys.resolve(m, false)));
            return opts;
        }

        private ClientOption.Proxy proxy(Config config) {
            final ClientOption.Proxy opts = new ClientOption.Proxy();
            config.get("type").asString().as(String::toUpperCase).as(ProxyProvider.Proxy::valueOf)
                    .ifPresent(opts::setType);
            config.get("host").asString().ifPresent(opts::setHost);
            config.get("port").asInt().ifPresent(opts::setPort);
            return opts;
        }

        private ClientOption.Redirect redirect(Config config) {
            final ClientOption.Redirect opts = new ClientOption.Redirect();
            config.get("isFollowRedirect").asBoolean().ifPresent(opts::setIsFollowRedirect);
            config.get("headers").detach().asMap().ifPresent(opts::setHeaders);
            config.get("responseTimeout").asString().as(String::toUpperCase).as(Duration::parse)
                    .ifPresent(opts::setResponseTimeout);
            config.get("cookie").as(s -> cookie(s)).ifPresent(opts::setCookie);
            return opts;
        }

        private ClientOption.ResponseDecoder responseDecoder(Config config) {
            final ClientOption.ResponseDecoder opts = new ClientOption.ResponseDecoder();
            config.get("parseHttpAfterConnectRequest").asBoolean().ifPresent(opts::setParseHttpAfterConnectRequest);
            config.get("initialBufferSize").asInt().ifPresent(opts::setInitialBufferSize);
            config.get("maxChunkSize").asInt().ifPresent(opts::setMaxChunkSize);
            config.get("maxHeaderSize").asInt().ifPresent(opts::setMaxHeaderSize);
            config.get("maxInitialLineLength").asInt().ifPresent(opts::setMaxInitialLineLength);
            config.get("failOnMissingResponse").asBoolean().ifPresent(opts::setFailOnMissingResponse);
            config.get("allowDuplicateContentLengths").asBoolean().ifPresent(opts::setAllowDuplicateContentLengths);
            config.get("validateHeaders").asBoolean().ifPresent(opts::setValidateHeaders);
            config.get("h2cMaxContentLength").asInt().ifPresent(opts::setH2cMaxContentLength);
            return opts;
        }

        private Cookie cookie(Config config) {
            final String name = config.get("name").asString().orElse(null);
            final String value = config.get("value").asString().orElse(null);
            if (StringHelper.isEmpty(name) || StringHelper.isEmpty(value)) {
                return null;
            }
            final DefaultCookie cookie = new DefaultCookie(name, value);
            config.get("wrap").asBoolean().ifPresent(cookie::setWrap);
            config.get("domain").asString().ifPresent(cookie::setDomain);
            config.get("path").asString().ifPresent(cookie::setPath);
            config.get("maxAge").asLong().ifPresent(cookie::setMaxAge);
            config.get("secure").asBoolean().ifPresent(cookie::setSecure);
            config.get("httpOnly").asBoolean().ifPresent(cookie::setHttpOnly);
            config.get("sameSite").asString().as(String::toLowerCase).as(s -> StringHelper.capitalize(s))
                    .as(s -> CookieHeaderNames.SameSite.valueOf(s)).ifPresent(cookie::setSameSite);
            return cookie;
        }
    }

    static class WiretapSpecMapper implements Function {

        @Override
        public WiretapSpec apply(Config config) {
            final WiretapSpec opts = new WiretapSpec();
            config.get("category").asString().ifPresent(opts::setCategory);
            config.get("level").asString().as(String::toUpperCase).as(LogLevel::valueOf).ifPresent(opts::setLevel);
            config.get("format").asString().as(String::toUpperCase).as(s -> s.replace('-', '_'))
                    .as(AdvancedByteBufFormat::valueOf).ifPresent(opts::setFormat);
            config.get("charset").asString().map(s -> Charset.forName(s)).ifPresent(opts::setCharset);
            return opts;
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy