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

shz.core.net.api.AbstractApiRequest Maven / Gradle / Ivy

There is a newer version: 2024.0.2
Show newest version
package shz.core.net.api;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import shz.core.*;
import shz.core.PRException;
import shz.core.id.IdHelp;
import shz.core.msg.ServerFailureMsg;
import shz.core.net.HttpClient;
import shz.core.io.IOHelp;
import shz.core.FieldSetter;
import shz.core.net.HttpHelp;
import shz.core.net.HttpRequestConfig;
import shz.core.reference.LReference;
import shz.core.tag.zxx.ZLTag;
import shz.core.type.TypeHelp;

import javax.net.ssl.SSLContext;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

public abstract class AbstractApiRequest implements ApiRequest {
    @ApiIgnore
    protected static final Logger log = LoggerFactory.getLogger(AbstractApiRequest.class);
    @ApiIgnore
    protected final Type rType;
    @ApiIgnore
    protected final ApiRequestConfig config;
    @ApiIgnore
    protected final Map headers;

    static {
        Container.setLoadContainer(false);
    }

    protected AbstractApiRequest() {
        rType = TypeHelp.getParameterized(getClass(), AbstractApiRequest.class, "R");
        config = getConfig();
        headers = new HashMap<>();
    }

    private ApiRequestConfig getConfig() {
        Class cls = getClass();
        ApiConfig apiConfig = cls.getAnnotation(ApiConfig.class);
        ServerFailureMsg.requireNonNull(apiConfig, "API请求类:%s缺少ApiConfig注解", cls);
        ApiRequestConfig config = new ApiRequestConfig();
        config.url = Container.getExprProperty(apiConfig.url());
        config.method = Container.getExprProperty(apiConfig.method());

        HttpRequestConfig connConfig = new HttpRequestConfig();
        config.connConfig = connConfig;

        connConfig.setProxyHost(Container.getExprProperty(apiConfig.proxyHost()));
        connConfig.setProxyPort(apiConfig.proxyPort());
        connConfig.setSslContext(sslContext());

        connConfig.setDoInput(apiConfig.doInput());
        connConfig.setDoOutput(apiConfig.doOutput());
        connConfig.setIfModifiedSince(apiConfig.ifModifiedSince());
        connConfig.setUseCaches(apiConfig.useCaches());
        connConfig.setAllowUserInteraction(apiConfig.allowUserInteraction());
        connConfig.setConnectTimeoutMillis(apiConfig.connectTimeoutMillis());
        connConfig.setReadTimeoutMillis(apiConfig.readTimeoutMillis());
        connConfig.setRedirects(apiConfig.redirects());

        return config;
    }

    @Override
    public final R request(D data) {
        Map dataMap = dataMap();
        init(data, dataMap);
        String url = url(dataMap);
        URL u;
        try {
            u = new URL(url);
        } catch (MalformedURLException e) {
            throw PRException.of(e);
        }
        String uid = IdHelp.nanoId();
        before(uid, url, dataMap);
        LReference responseRef = new LReference<>();
        HttpClient.connect(u, config.method, headers, body(dataMap), config.connConfig, (charset, is) -> responseRef.set(read(charset, is)));
        String response = responseRef.get();
        after(uid, url, response);
        return analysis(response);
    }

    /**
     * 获取请求参数
     */
    protected Map dataMap() {
        List fields = AccessibleHelp.fields(getClass(), f -> !f.isAnnotationPresent(ApiIgnore.class));
        if (fields.isEmpty()) return new HashMap<>();
        Map dataMap = ToMap.get(fields.size()).build();
        for (Field field : fields) {
            String name = field.getName();
            Object obj = AccessibleHelp.getField(field, this);

            if (obj == null) {
                ApiValue apiValue = field.getAnnotation(ApiValue.class);
                if (apiValue != null)
                    obj = FieldSetter.parse(Container.getExprProperty((apiValue.value())), field.getType());
            }

            ZLTag key = nameFilter(name, obj);
            if (key == null || key.tag) continue;
            ZLTag value = valueFilter(name, obj);
            if (value == null || value.tag) continue;
            dataMap.put(key.data, value.data);
        }
        return dataMap;
    }

    protected ZLTag nameFilter(String name, Object value) {
        return new ZLTag<>(false, name);
    }

    protected ZLTag valueFilter(String name, Object value) {
        return new ZLTag<>(value == null, value);
    }

    protected void init(D data, Map dataMap) {
        headers.put("Content-Type", "application/x-www-form-urlencoded");
    }

    @ApiIgnore
    protected static final Pattern P_PATH = Pattern.compile("\\{([^{}]+?)}");

    protected String url(Map dataMap) {
        config.url = RegexHelp.replace(config.url, P_PATH, matcher -> {
            String g = matcher.group(1);
            String s = ToString.normal(dataMap.get(g));
            dataMap.remove(g);
            return s;
        });
        if (config.getMethod().startsWith("P")) return config.url;
        return HttpHelp.jointUrl(config.url, dataMap);
    }

    protected SSLContext sslContext() {
        return null;
    }

    protected void before(String uid, String url, Map dataMap) {
        log.info("请求,uid:{},url:{},dataMap:{}", uid, url, dataMap);
    }

    protected byte[] body(Map dataMap) {
        return null;
    }

    protected String read(Charset charset, InputStream is) {
        return IOHelp.read(IOHelp.newBufferedReader(is, charset));
    }

    protected void after(String uid, String url, String response) {
        log.info("响应,uid:{},url:{},response:{}", uid, url, response);
    }

    protected abstract R analysis(String response);
}